Repository navigation
fix: stop an arriving code answer from freezing the pane for its length - #631
Merged
Merged
Conversation
A note's rows were built whole on every frame, twice, before the clamp kept the screenful that fits, and a fenced block in an answer was parsed whole on the frame it arrived. A note is now counted without building a row, and built from the first row the clamp keeps to the last the pane holds; a quoted block keeps its parser position and is parsed as far as the last line the frame draws. Frame::diff_with's counterpart here is Pass::quoted_to, which fills a block forward to a line. The answer no longer carries spans at placement: the rows the clamp keeps ask for them. View::built counts the note rows a screen built, and three gates hold the shape: the frame a 2,000-line fenced answer arrives on parses no more lines than the pane has rows and holds I9's budget, a second screen parses nothing more, and a 10,000-line answer builds at most a screenful of rows. Release-note: An answer the agent quotes as code no longer freezes the pane for the length of the block when it arrives. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
SPEC.md's I4 paragraph says a note's rows and a quoted block's parse follow the window, with the arrival numbers before and after on both panes and the gates that hold them. ROADMAP.md flips the Shelf row and records the pull-forward. Release-note: none Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The arrival gate asked for ten coloured rows, which a thirteen-row body cannot show; it now asks that every parsed line drew a class, since every line of the block is a fn. The spec carries the numbers from the run that passed. Release-note: none Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A note's rows are one list of sections that the count sums and the build walks, so the two cannot disagree, and a unit test holds every shape, width and window to that. The answer's window functions report the rows they walked, so no part is counted before it is built. A quoted block's window is walked once for its pieces and its end, then given runs. The clamp finds a row's pins by index rather than by scanning them, and the box rows are windowed by a drain. The core's Quote doc says what it now does. The tall pane is read, not timed, and both budget gates share the coloured-rows count. The notes gates build their note with the file's own helper. Release-note: none Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The read arm runs no warmup, so its first view was the app's plain first frame and parsed nothing. Release-note: none Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The two structural gates take names of four words, the row gate holds the built count to the note rows drawn, the section window and the sum have one name each, and three docblocks say what the code does rather than argue for it. Release-note: none Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The I4 paragraph keeps the rule in the present tense with its author and its user-facing line, and names the bottom clamp's cost. RULINGS.md gains the entry with the measurements on both panes, the three rejected shapes and what is left as it is. Release-note: none Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The pass sweeps a block it is not asked for after two frames, and a pinned note whose block rows are off the window was no longer asking, so a return re-parsed it. Every pinned answer now asks for its blocks each frame without parsing, which also raises the demand for an uncompiled grammar before the block is drawn, as it did before. A note whose own line leaves the pane is not pinned and is swept as before; its return now costs a screenful rather than the block, and a gate holds that. The arrival rig uses one highlighter, since every sample is a fresh digest, and the row gate's name is a label. Release-note: none Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The highlighter marks an existing block live without hashing it, renews the demand for an uncompiled grammar, and starts an entry only where none exists, so a pinned answer behind the window costs the frame a lookup per block. Two gates hold the keep from both sides: a pinned note whose answer sits behind the window for two frames is not parsed again when its rows return, and a note whose line leaves the pane is swept and parses a screenful on return, no less and no more. The counter doc says what the pin keeps. The keep runs under the same condition as the rows it keeps for. Release-note: none Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A held entry that was waiting on a grammar now compiled is rebuilt, as a draw would rebuild it, so it stops demanding a grammar it has; the demand itself is one function both the hold and the draw call. A gate in the warm suite holds a block behind the window for two frames and asserts its demand stands, then warms the grammar and asserts the demand ends and a draw finds colour. The hold says that a rewrite behind the window is seen when the block is next drawn. Release-note: none Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
One function says when a block waits on a grammar the warmer has compiled since or on one its fence no longer names, and both the hold and the draw rebuild on it, so a held block rewritten to another language behind the window is not held against the old grammar's demand. The warm gate holds the rebuild count as well as the demand, and takes a label for a name. The hold's doc says what a held block costs per case. Release-note: none Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
breferrari
marked this pull request as ready for review
September 30, 2026 21:19
This was referenced Oct 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
An answer the agent quotes as code no longer freezes the pane for the length of the block when it arrives, and a note taller than the pane costs its count and its drawn rows rather than every row it has. Closes #530. Plan: #530 (comment). Deviations: #530 (comment) and #530 (comment).
Before,
answer_ofparsed every line of a fenced block on the frame the answer arrived, andPin::rowsbuilt every row of every note twice a frame before the clamp kept a screenful. Now a note is one list of sections (Pin::sections) that the clamp's count sums and the build walks, built only from the first row the clamp keeps to the last the pane holds; a quoted block keeps its parser position in the highlighter and is parsed as far as the last line the frame draws (Pass::quoted_to), and every pinned answer holds its blocks each frame (Pass::hold, no digest) so the sweep keeps them.HighlightStats::quoted_linescounts the lines of blocks parsed andView::builtthe note rows a screen built.Scope:
full. Labelreleaseby path.SPEC.md's I4 paragraph carries the rule, attributed to the reader's plan approval;RULINGS.mdcarries the numbers and the three rejected shapes.Test plan
budgets.rs::arrival_holds_the_budget, release: a 2,000-line fenced answer arrives on every sample, timed on the 80x24 pane against I9's 16ms and read on the 80x160 pane, asserting on both that the lines parsed are no more than the rows drawn and that every parsed line drew a class. Onmainthe tall pane read 119.98ms p50 fenced against 15.25ms as prose and parsed the whole block, which is the red run; the ordinary pane was not timed onmain. On this branch: 80x24 fenced 7.98ms against 7.52ms prose, 8 lines parsed for 13 rows; 80x160, when it was timed, 18.69ms against 13.14ms prose, 110 lines parsed for 115 rows. The tall pane's remainder is its window, a hundred-odd lines of grammar, the first-touch shape §7 leaves outside I9.notes.rs::parse_follows_the_window: the arrival parses no more lines than the pane has rows, a second screen parses none, and a screenful down parses at most another screenful.notes.rs::rows_follow_the_window: a 10,000-line prose answer fills the screen and builds exactly the note rows drawn.notes.rs::kept_while_pinned: a note whose line stays on the pane with its whole answer behind the window for two frames is not parsed again when its rows return.notes.rs::return_costs_a_screenful: a note whose line leaves the pane for two frames is swept, and coming back parses at least one line and at most a screenful, wheremainparsed the whole block again.view::tests::count_matches_build: every note shape at seven widths counts what its build produces, and every window of it is the same rows.warm.rs::held_demand: a cold block held behind the window for two frames keeps demanding its grammar and is not rebuilt; once warmed, the next hold rebuilds it exactly once, the demand ends and a draw finds colour.-D warnings. The full workspace runs in CI.Review
/simplify: one description of a note's rows (Section) shared by count and build; the window functions report the rows they walked so no part is counted before it is built; the code window is walked once for its pieces and its end; pins are found by row index; the box rows are windowed by a drain; the tall pane is read rather than timed; the two budget gates share the coloured-rows count; the notes gates use the file's own note builder. Skipped: memoising the count on the pin (two walks per frame now, count and build, over the reader's short body); the quadratic remainder scan inprose_pieces, which predates this change and is named in the ledger; thechunksallocation per frame at placement, which also predates it./two-axis-review: test names as labels, the row gate holding the counter to the rows drawn, the rule attributed and its history moved to the ledger, the bottom clamp's cost recorded, the section window and the sum with one name each, three docblocks trimmed. Skipped: a struct fornote_widthsand forwrap_rows's eight arguments, the shape the file's other painters already allow; thequoted_toargument list, which mirrorsquoted; keepingHighlighter::quoted, which the coverage tests call./code-review high: a pinned answer's blocks are held each frame so the sweep does not drop them and an uncompiled grammar is demanded before the block is drawn; one highlighter in the arrival rig; the five-word gate renamed; thequotedcounter's doc corrected. The scroll-away case it named is not a regression: a note whose line leaves the pane is not pinned onmaineither, and its block was re-parsed whole there; here the return costs a screenful, andreturn_costs_a_screenfulholds that. Skipped: caching theAnswerper note write (chunksand the digest per frame predate this change; the prose arm's 13.14ms arrival on the tall pane bounds what a held 2,000-line answer costs a frame); foldingAnswer::rows_inontosection_window(a part is not counted before it is walked); the double body walk inPin::sections(the body is the reader's short text)./code-reviewof the fix commit: the hold takes no digest; the keep has its own gate,kept_while_pinned, and a mutation that drops it goes red; the return gate has a lower bound; the counter doc says the line, not the file; the keep's condition is anif. Skipped: none./code-reviewof the second fix commit: the hold skipped the thaw a draw applies, so a held block whose grammar was warmed meanwhile kept demanding it; the demand is now one function both paths call, the hold rebuilds a thawed entry, and the warm suite gates both halves. Accepted and said in the code: a rewrite behind the window is seen when the block is next drawn, which is the cost of holding without a digest./code-reviewof the third fix commit: the stale test is one function the hold and the draw share, and it also fires when a held block's fence now names another grammar, so a rewrite behind the window cannot pin the old grammar's demand; the warm gate holds the rebuild count; the hold's doc states its cost per case; the gate's name is a label. The fourth commit carries only those asks and their gates and had no further agent pass.Release note
Release-note: An answer the agent quotes as code no longer freezes the pane for the length of the block when it arrives.
🤖 Generated with Claude Code