Skip to content

Split the longest functions into named steps - #35

Merged
jserv merged 3 commits into
mainfrom
refactor
Sep 9, 2026
Merged

Split the longest functions into named steps#35
jserv merged 3 commits into
mainfrom
refactor

Conversation

@jserv

@jserv jserv commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

The five longest functions in the tree had each grown past the point where any one of them could be read whole. The room loop was three hundred lines of select arm bodies, so reading one meant scrolling past the other six; each arm is a named handler now, taking the event context the module already speaks rather than a second bundle of the same borrows, and the two exits that hang up use the borrowing teardown gemini.rs already had. The same split runs through the token handler, the setup submission and the browser preflight, where the level meter and the readiness sample moved into modules a test can drive. That last move is the one worth a reviewer's attention: what pinned those two before was the text of their functions, and one of those assertions forbade the cleanup this branch makes.

The pass also turned up a real defect, which is the first commit. Two overlapping start attempts could each arm a recording poll with one handle between them, leaving a request every fifteen seconds that nothing was left to stop, and the terminal verdict lived on a DOM node where the next attempt read it as its own. The poll has one owner now and the verdict belongs to the attempt that earned it.

Verified with scripts/test.sh end to end, exit 0 with no gate failing or skipped: 643 Rust tests, 456 browser tests, clippy with -D warnings, cargo audit clean over 343 crates, and the vendored-asset and git-hook lanes. Each new browser test was checked by reintroducing the defect it covers and confirming it fails.

Two limits worth stating rather than leaving to be discovered. run_room and its handlers are unreachable from cargo test, which the repository's own .cargo/mutants.toml documents, so the third commit rests on review and on comparing the loop's arm heads and exit paths against main rather than on the suite; scripts/browser-check.sh in its credentialed modes is what would exercise it, and I have not run it. Four handlers join the mutation exclusions as a result, carrying no code the gate could not judge before, only names it now has to be told about. Three long functions were left alone on purpose: build_instructions_for_plan is mostly one prompt literal, and createAvatar and loadVrm are outside what this branch set out to touch.


Summary by cubic

Splits the five longest functions into named steps so each reads as the events it dispatches rather than one long body, and fixes a recording poll leak where overlapping start attempts left a request every fifteen seconds that nothing could stop. The room loop's select arms become handlers on the event context the module already speaks, with the same split through the token handler, setup submission and browser preflight; the mic meter and recording readiness move into modules a test can drive by behavior instead of source text.

Bug Fixes

  • The poll now has one owner that clears and arms in the same statement, and the verdict is returned to the attempt that earned it: where two attempts overlap, the newer one's answer counts.

Refactors

  • run_room's handlers are unreachable from cargo test (documented in .cargo/mutants.toml); they rest on review comparing the loop's arm heads and exit paths to main, and four handlers join the mutation exclusions as a result.
  • build_instructions_for_plan, createAvatar and loadVrm were left alone: one is mostly a prompt literal, the other two are outside what this branch set out to touch.

Written for commit 8a48145. Summary will update on new commits.

Review in cubic

cubic-dev-ai[bot]

This comment was marked as resolved.

cubic-dev-ai[bot]

This comment was marked as resolved.

@sysprog21 sysprog21 deleted a comment from cubic-dev-ai Bot Sep 9, 2026
Two start attempts could each arm an interval with only one handle
between them, leaving a request every fifteen seconds that nothing was
left to stop. The terminal verdict also lived on the status node, where
the next attempt read it as its own and never asked the one route that
could establish whether that attempt had started.

One function now owns the handle and clears it in the statement that
arms it, and the verdict is returned to the attempt that earned it.
Where two attempts overlap the newer one wins, on both sides: a start
whose answer a later start has superseded writes nothing, and a poll
whose request was made for a previous attempt neither relabels the
interview nor stops the timer the current one is relying on.
A production file carrying a cfg(test) helper is a test the crate ships,
and two were left: a parse shim in gemini.rs and an OutputAudio fixture
in livekit/media.rs. The fixture sat there on the belief that a test
module cannot hand one to a sibling, which is true of siblings and not
of these two: media's tests descend from livekit, so a single copy under
tests/unit serves both.

What production keeps is a real constructor. The rate the fixture
publishes at is now the constant on both sides of the comparison that
reads it, so moving that constant fails the test rather than leaving it
to assert a number nothing sends.
The room loop had grown to three hundred lines of select arm bodies, and
reading any one of them meant scrolling past the other six. Each arm is
a handler now, taking the event context this module already speaks
rather than a second bundle of the same four borrows, and the two exits
that hang up do so through the borrowing teardown gemini.rs already had
instead of naming themselves for a caller to perform. The same split
runs through the token handler, the setup submission and the browser
preflight, where the level meter and the readiness sample move to
modules a test can drive: what pinned them before was the text of their
functions, and one of those assertions forbade a cleanup this makes.

Splitting an unjudged function multiplies the names the mutation gate
has to be told about, so five handlers join the exclusions carrying no
code it could not judge a moment ago. The gate earned one deletion in
exchange: the parse arm in minted_token answered a request that
token_handler had already refused, and neither of its mutants could
die because nothing tells a guard that is never true from one that is
never false.
@jserv
jserv merged commit cde406a into main Sep 9, 2026
7 checks passed
@jserv
jserv deleted the refactor branch September 9, 2026 20:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant