Skip to content

[Tracking] split-1066 chain: rules, port sources, chain-level rows #1989

Open

Description

@easonLiangWorldedtech

Chain note: U6 (#1932) is being re-split into U6a and U6b

Posted on the unit issue #1937 first, where it belongs; this is the chain-level row update only. Full plan, figures with heads, additivity, density and the labels are in #1937 (comment) post's id will be added by edit? no - stated below): see the plan comment on #1937 posted 2026-11-12.

Addendum 2026-11-12, U6 re-cut again

U6 was cut a second time. The row above for U6 now covers two units:

unit issue pull branch state
U6a #1937 #1932 easonLiangWorldedtech:p1066/u6-execute-error-path-cleanup at 3c5036a pushed, provider-side half only (207 counted executable lines, 68 selectors, 183 instrumented mutants against main tip 53cb5b5)
U6b #1937 #2434 easonLiangWorldedtech:p1066/u6b-tool-stream-teardown at 27465f8 open against main, depends on #1932 (243 lines, 95 selectors, 227 instrumented mutants against 3c5036a)

Figures are my measurement with the stock selector of scripts/stryker-diff.mjs plus a local Stryker 10 fast dry run on the identical selector list; instrumented mutant counts are counts, not verdicts. Additivity is exact against the previously reported parent: 207 + 243 = 450 lines, 68 + 95 = 163 selectors, 183 + 227 = 410 mutants.

Declared merge order with the re-cut: U3 #1931 -> U4 #1929 -> U5 #1930 -> U6a #1932 -> U6b #2434 -> U7 #1928. While U6a is open, GitHub reports #2434 against main as the cumulative 450 lines and 410 mutants; that is the chain view, not the unit delta. Unit 1 also carries a sanctioned repair of the eight TS2540 read-only isDirty assignments in DiffViewProvider.spec.ts (lines 1414, 1447, 1475, 1500, 1548, 1674, 1745, 1805) via a locally widened structural type, with no assertion and no any; a red compile leg is not what CI reported for #1932 today (see the plan comment for the posture read).

Addendum 2026-11-12, U5 cut into two pulls

U5 was cut, so the U5 row below now covers two pulls with a declared order between them, U5a first and U5b second. The plan is #1935 (comment) and the unit issue carries both pulls in its body.

unit issue pull branch state
U5a #1935 #1930 easonLiangWorldedtech:p1066/u5-streaming-failure-capture at acd836f pushed, diff-view half only, merges first, 226 counted executable lines, 55 selectors, 192 instrumented mutants against main tip 53cb5b5
U5b #1935 #2435 easonLiangWorldedtech:p1066/u5b-tool-level-stream-state at c3dbed4 open against main, depends on #1930 and merges second, 293 lines, 109 selectors, 268 instrumented mutants against acd836f

Figures are my measurement with the stock selector of scripts/stryker-diff.mjs, blob 7dfe0006d2d5, which caps changed executable lines at 500 and instrumented mutants at 400, plus a local Stryker 10 fast dry run on the identical selector list; instrumented mutant counts are counts, not verdicts, the mutation leg is unmeasured locally, and CI at the pushed head is the only proof of the gate. Additivity is exact against the pull whole measured before the cut on main tip 53cb5b5: 226 + 293 = 519 lines, 55 + 109 = 164 selectors, 192 + 268 = 460 mutants. The 519 lines is 19 over the 500 cap and the shipped gate exits 1 on the line cap at that tree, which is what forced this cut; it is a line-cap trigger, not the mutant-cap trigger that split 1913.

Declared merge order with the U5 cut: U3 #1931 -> U4 #1929 -> U5a #1930 -> U5b #2435 -> U6a #1932 -> U6b #2434 -> U7 #1928. While U5a is open, GitHub reports pull 2435 against main as the cumulative 13 files, 4930 insertions and 130 deletions; that is the chain view, not the unit delta, which is 10 files, 2853 insertions and 90 deletions against pull 1930. This addendum moved no unit branch, merged nothing, labelled nothing, closed nothing and resolved nothing.

Activity

  1. easonLiangWorldedtech commented on Oct 10, 2026

    @easonLiangWorldedtech
    ContributorAuthor

    Migrated from #41 comment 6093034261 - this note belongs to the split-1066 chain (chain map: #1989), not to that unrelated closed bug (fork-issue numbering trap).

    Rule: a provider-state await belongs inside the cleanup-owned boundary

    Two units of the #1066 chain grew the same defect from opposite directions, which is why this is worth a line here rather than two commit messages:

    The rule: any await that happens after per-task state has been registered must be inside the boundary that releases that state - including the awaits that look like read-only setup (providerRef.deref(), getState(), a settings lookup, an isEnabled() read). getState() is not a pure read: it is an await into the extension host and it can reject or be superseded by a task switch.

    Same-shape sites to check beyond U4/U6 (measured at the heads named above, git grep over src/core/tools):

    • U4 feat(write-to-file): per-task partial stream state + cleanup primitives (split 2/6 of #1066) #1929: 16 hit(s)
    • src/core/tools/ApplyDiffTool.ts:130: const state = await provider?.getState()
    • src/core/tools/ApplyPatchTool.ts:172: const state = await provider?.getState()
    • src/core/tools/ApplyPatchTool.ts:328: const state = await provider?.getState()
    • src/core/tools/EditFileTool.ts:392: const state = await provider?.getState()
    • src/core/tools/EditTool.ts:167: const state = await provider?.getState()
    • src/core/tools/ExecuteCommandTool.ts:167: const providerState = await provider?.getState()
    • U6 fix(editor): release abandoned diff streams and owned placeholders (split 5/6 of #1066, unit U6a) #1932: 16 hit(s)
    • src/core/tools/ApplyDiffTool.ts:130: const state = await provider?.getState()
    • src/core/tools/ApplyPatchTool.ts:172: const state = await provider?.getState()
    • src/core/tools/ApplyPatchTool.ts:328: const state = await provider?.getState()
    • src/core/tools/EditFileTool.ts:392: const state = await provider?.getState()
    • src/core/tools/EditTool.ts:167: const state = await provider?.getState()
    • src/core/tools/ExecuteCommandTool.ts:167: const providerState = await provider?.getState()
    • U7 fix(write-to-file): clean partial state on missing-param and rooignore denial + integrate the #1066 split series (6/6 + FINAL) #1928: 16 hit(s)
    • src/core/tools/ApplyDiffTool.ts:130: const state = await provider?.getState()
    • src/core/tools/ApplyPatchTool.ts:172: const state = await provider?.getState()
    • src/core/tools/ApplyPatchTool.ts:328: const state = await provider?.getState()
    • src/core/tools/EditFileTool.ts:392: const state = await provider?.getState()
    • src/core/tools/EditTool.ts:167: const state = await provider?.getState()
    • src/core/tools/ExecuteCommandTool.ts:167: const providerState = await provider?.getState()
    • U3 feat(tools): onParameterParseFailure teardown boundary (split 4/6 of #1066) #1931: 16 hit(s)
    • src/core/tools/ApplyDiffTool.ts:130: const state = await provider?.getState()
    • src/core/tools/ApplyPatchTool.ts:172: const state = await provider?.getState()
    • src/core/tools/ApplyPatchTool.ts:328: const state = await provider?.getState()
    • src/core/tools/EditFileTool.ts:392: const state = await provider?.getState()
    • src/core/tools/EditTool.ts:167: const state = await provider?.getState()
    • src/core/tools/ExecuteCommandTool.ts:167: const providerState = await provider?.getState()
    • U3-fws feat(task): observation registry with read completeness (U3, #1375) #1912: 16 hit(s)
    • src/core/tools/ApplyDiffTool.ts:130: const state = await provider?.getState()
    • src/core/tools/ApplyPatchTool.ts:172: const state = await provider?.getState()
    • src/core/tools/ApplyPatchTool.ts:328: const state = await provider?.getState()
    • src/core/tools/EditFileTool.ts:392: const state = await provider?.getState()
    • src/core/tools/EditTool.ts:167: const state = await provider?.getState()
    • src/core/tools/ExecuteCommandTool.ts:167: const providerState = await provider?.getState()

    Cross-references: U4 fix 61dd05a2c (this rule's first half), U6 follow-up commit (second half, will cite this comment), U3 #1931 1b09bab32 already carries the liveness-check shape that U6 ports for its Lifecycle row.

  2. easonLiangWorldedtech commented on Oct 10, 2026

    @easonLiangWorldedtech
    ContributorAuthor

    Migrated from #41 comment 6093818950 - this note belongs to the split-1066 chain (chain map: #1989), not to that unrelated closed bug (fork-issue numbering trap).

    Chain-level row: Persistence Integrity (a rollback path can persist unapproved streamed content)

    This row is red at the same time on #1916 / #1921 / #1929 / #1930, so it is one chain-level defect rather than four per-PR defects. Recording the ownership split here before anyone ports it.

    Ownership and semantic baseline are two different facts and must be labelled separately. The earliest definer owns the primitive; the semantic baseline may be a rule another unit already broadcast. Marking only the owner makes every unit invent its own variant while porting, which is how one row ends up red on four PRs.

    Shape shipped on #1930: the contract lives in the callee. restorePreStreamBuffer() throws when applyEdit() returns false, so the saveBufferClean() call that follows it cannot run — nothing saveable survives — and the failure reaches revertChanges() → WriteToFileTool.revertDiffChangesBeforeReset(), which already returns it as rollbackError for the caller to report. discardFileTab() is byte-for-byte unchanged, because #1932 depends on its current shape (restore + save hoisted above the tab loop). A refused restore is asserted to reach the user as a failure, not as a successful rollback.

  3. easonLiangWorldedtech commented on Oct 10, 2026

    @easonLiangWorldedtech
    ContributorAuthor

    Port source of record for the write_to_file rollback shape

    eb245494a on p1066/u5-streaming-failure-capture is the source of record for the shared rollback shape: revertChanges() requires both relPath and isEditing; reset() clears relPath (and newContent); discardFileTab() restores the buffer to its pre-stream content and saves it clean before closing, because the second argument of tabGroups.close() is preserveFocus and not a force-discard flag; a close the editor refuses now fails the rollback instead of deleting the file underneath an open tab. WriteToFileTool reverts the diff view only while an edit is in progress. 215e32d3e carries the matching eslint suppression prune.

    5c0f21219 on p1066/u3-parse-failure-boundary ports that half verbatim and adds the execute() cleanup hazard report, matching onParameterParseFailure() and cleanupFailedPartialStream().

    Chain-level requirement: port both verbatim to the remaining units in merge order, and record per unit how many tests each negative control kills. The counts differ per unit by design, because the same guard covers several call sites and each unit reaches a different subset of them.

  4. easonLiangWorldedtech commented on Oct 10, 2026

    @easonLiangWorldedtech
    ContributorAuthor

    Chain rule: a suppression reduction must ship in the same commit

    The compile job runs the repository lint, and the strict run compares the counts in
    src/eslint-suppressions.json in both directions. A change that removes a suppressed violation -
    replacing an as any cast with bracket notation, for example - makes the stored count too high, and
    the run exits 2 with "There are suppressions left that do not occur anymore" even though the file
    itself reports no violations.

    This bit PR 1930: the first push reported a clean per-file lint and still failed compile, because a
    per-file run cannot see a count drift.

    Acceptance for every unit in this chain:

    • Before pushing, run the full lint the same way CI does, from the src directory:
      eslint . --ext=ts --max-warnings=0. A per-file run is not sufficient.
    • If it exits 2, regenerate with --prune-suppressions, rewrite the JSON with tab indentation, and
      confirm the diff touches only the affected count lines.
    • Ship the pruned file in the same commit as the change that reduced the count, never in a later
      cleanup commit.
    • After merging main into a unit branch, prune again on the merged tree: both sides' counts move
      together, and CI builds the merge commit rather than the branch tip.
  5. easonLiangWorldedtech commented on Oct 10, 2026

    @easonLiangWorldedtech
    ContributorAuthor

    Two chain-level entries for this chain, registered from the local queue.

    1. Series convention, not a defect: the format check script and the root prettier ignore file arrive through the PR merge ref, not through a unit branch's own base, so every unit needs its own pure-formatting commit once it merges current org main. Register it once as a convention, not as one issue per unit. Acceptance: in a worktree checked out with core.autocrlf=false, the format check reports zero offenders at the current merge ref, and only files inside that PR's diff are touched. Shared files converge because the formatter output is deterministic, so ordering between units does not matter.

    2. Fixing one call site does not fix a defect class. The Persistence Integrity row stayed red after one call site was fixed, because the existing-file branch of the same method had its own copy of the unchecked restore-and-save. When a row names a class, enumerate the other call sites and register them - changed only if the row covers them.

    Unit-scope debt for U5 (five unchecked result sites and one await-boundary follow-up) is on issue 1935.


    Addendum to entry 1, measured on the current base (2026-10-10, unit U7): org main deleted the root prettier ignore file between 09e7326 and d1f5845 - the same batch that added the format check script - so the intent is that the whole tree is formatted, not a subset. Consequence: the compile job (pnpm format:check, i.e. prettier --check over the tree) now reaches 37 files that were previously ignored, and three of them were unit U7's own spec files, which turned that unit's compile job red. The unit-level fallout is already fixed in pull 1928 commit b2b3b0d.

    Two things the chain should settle once, so no later unit rediscovers them:

    • Do not re-add the ignore file inside a unit pull request. Whoever's merge ref lands on the new base carries a separate pure-formatting commit produced by the repository's own prettier version, with a commit message stating that the deviations are not introduced by that pull request. Acceptance for that commit: the diff ignoring whitespace is empty.
    • Re-fetch and re-measure the pull request merge ref before every push. The dirty count is a property of the merge ref GitHub rebuilds, so it can jump from 0 to 37 when the base moves; a previous round's count is not this round's count.

    No action required by any unit that has not merged onto the new base yet.

  6. easonLiangWorldedtech commented on Oct 10, 2026

    @easonLiangWorldedtech
    ContributorAuthor

    Chain-level tooling note for the 1066 split units: org main is not tsc-clean on its own. Merging it brings 12 type errors (webviewMessageHandler.readOriginalContent.spec.ts accounts for 8, plus ClineProvider.spec.ts and WebviewFocusTracker), which moves the merged-tree baseline of every unit from 62 to 74.

    Consequence for how we report: an absolute tsc count is meaningless when upstream carries a dirty baseline. The check has to be an A/B on the same tree - run tsc at HEAD and at HEAD~1, or with and without the change, and require the error sets to be identical by name; this is the same trick as proving a local red with a stash A/B.

    In commit messages write "A/B equivalent, error sets identical by name", not "tsc 0 errors": when the baseline is not zero a bare 0 reads as a claim about the baseline.

    Acceptance: either org main reaches zero with the temporary tsconfig paths mapping for the types package, or every unit records its own merged-tree A/B result instead of an absolute number.

  7. easonLiangWorldedtech commented on Oct 10, 2026

    @easonLiangWorldedtech
    ContributorAuthor

    Chain-level entry from unit U6 (pull 1932): revertChanges() has no "is an edit session active" gate, so a caller that holds no session can still reach the new-file unlink branch.

    Unit U6 removed the stale-path trigger instead of adding the gate: reset() now clears relPath and newContent (commit 694bed4), so the branch is no longer reachable from the path that triggered it here. The shape question is still chain-level because unit U7 carries the gate in a different form (5c0f212), and the two units now differ deliberately.

    Acceptance if the chain wants one shape: the gate exists at the public entry point in every unit that carries the unlink branch, plus a test that revertChanges() with no session is a no-op. A guard that sits only on an internal caller is not a guard.

    Recorded so the next unit does not re-derive the difference between the two units; no action required by U6.

  8. easonLiangWorldedtech commented on Oct 10, 2026

    @easonLiangWorldedtech
    ContributorAuthor

    One fail-closed rollback path for the write-to-file stream lifecycle

    Defect: the chain currently has four separate rollback exits that each decide on their own whether to reset per-task stream state - the streaming-failure rollback, the approval-denial revert, the parse-failure release, and the task-abort teardown. Each of them can call reset while a dirty, never-approved buffer is still on disk or still open in a diff view, because closing diff views skips dirty tabs. When the restore or close itself fails, the state is dropped anyway, so a later retry can publish content the user never approved, and the per-task entry plus its abort listener can be retained.

    Acceptance, not bound to a commit:

    1. One shared rollback path is used by all four exits; no exit resets or releases state while a dirty buffer remains.
    2. Any restore, save, close, or delete failure inside that path records an unrecoverable per-task rollback failure.
    3. While that failure is recorded, later writes and saves for the task are blocked, including the approval and parse-failure routes, and the failure is reported exactly once.
    4. The state clears only after the buffer is verified clean, the tab is closed, and the placeholders are removed.
    5. The shape is defined once in the unit that owns the shared diff-view rollback behaviour and ported forward in the declared merge order, re-derived per branch rather than copied byte for byte.

    Negative-control shape: one mutant per production call site, each reddening only the tests naming that behaviour; run each mutant against the pre-fix spec to show the branch was previously uncovered; if a mutant reddens far more tests than the target, assume the mutant is wrong first; restore mutants byte for byte and verify with a hash.

    Related but separate: the parse-failure release hook is never reached on the production malformed-completion path, because the caller emits its own tool result and returns before delegating to the tool handler. That leaves the per-task entry and its abort listener retained and suppresses later previews. Its fix belongs to the unit that introduced the hook, and it must preserve the one-result-per-call behaviour and the existing report ordering.

  9. easonLiangWorldedtech commented on Oct 11, 2026

    @easonLiangWorldedtech
    ContributorAuthor

    A discarded save result can report a successful save that never persisted

    Defect: the approved-save path awaits the document save and drops the returned boolean. A save that reports failure therefore continues into the success bookkeeping, the placeholder is released, and the caller is told the approved content is on disk when it is not. The statement is inherited from upstream code that predates this chain, so it is not a regression introduced by the split, but every unit branch carries a copy and the file is inside each unit's diff.

    Acceptance, not bound to a commit:

    1. The awaited save result is captured rather than discarded.
    2. A false result raises a typed write-failure error before the placeholder path is released and before any success bookkeeping, so the existing failure handling runs.
    3. A true result behaves exactly as before.
    4. A save that rejects still propagates as before.
    5. A regression test fails against the pre-fix production file, and the test double returns an explicit boolean so a double resolving undefined cannot pass by accident.
    6. Where a branch releases the placeholder before the save, that release moves after the save or the throw, so the ordering promise holds on every branch.
    7. The shape is fixed once in the earliest unit branch that is still open and ported forward re-derived per branch, because the surrounding bookkeeping differs: one branch gates the placeholder release, another gates an on-commit callback, another has neither primitive.

    Negative-control shape: reverting to a bare await reddens exactly the save-false tests; moving the throw after the placeholder release reddens the ordering assertion; a mutant that reddens far more tests than the target is a broken mutant. Restore byte for byte and verify with a hash.

  10. easonLiangWorldedtech commented on Nov 12, 2026

    @easonLiangWorldedtech
    ContributorAuthor

    Chain note: U6 (#1932) is being re-split into U6a and U6b

    Posted on the unit issue #1937 first, where it belongs; this is the chain-level row update only. Full plan, figures with heads, additivity, density and the labels are in #1937 (comment) post's id will be added by edit? no - stated below): see the plan comment on #1937 posted 2026-11-12.

  11. easonLiangWorldedtech commented on Nov 12, 2026

    @easonLiangWorldedtech
    ContributorAuthor

    Chain-level row: two unit bodies declare different merge sequences for this chain, and no lane is resolving it

    Filed by lane u9-1917 at lead's ruling that where two bodies declare different sequences the disagreement goes to the tracking issue as a human-visible item rather than being settled by a lead picking one, because a merge sequence is a maintainer-facing promise and not a measurement. Nothing below picks a winner.

    Both texts quoted verbatim, with the line number inside each published body.

    #1931 (unit U3), body line 31:

    Merge order is fixed: U12 (1927) -> U4 -> U5 -> U3 -> U6 -> U7 -> FINAL (1928).

    #1932 (unit U6a), body line 32, in the price-table row for unit U6b:

    in the merge order named in the Stack section below: U3 #1931, U4 #1929, U5 #1930, U6a #1932, U6b, then U7 #1928

    #1932 (unit U6a), body line 52, in the row-ownership paragraph:

    the earliest branch in the declared merge order (U3 #1931, U4 #1929, U5a #1930, U5b #2435, U6a #1932, U6b #2434, U7 #1928) whose diff adds the line the mutant sits on

    Four differences, named rather than smoothed over:

    1. position of U3: after U4 and U5 in feat(tools): onParameterParseFailure teardown boundary (split 4/6 of #1066) #1931, first of all in fix(editor): release abandoned diff streams and owned placeholders (split 5/6 of #1066, unit U6a) #1932;
    2. U12 / fix(task): stage-independent saveClineMessages + finalize open partial tool ask (split 1/6 of #1066) #1927 leads the sequence in feat(tools): onParameterParseFailure teardown boundary (split 4/6 of #1066) #1931 and is absent from both lists in fix(editor): release abandoned diff streams and owned placeholders (split 5/6 of #1066, unit U6a) #1932;
    3. U5b / U5b of the split of pull 1930: per-task stream state, captured once and released once #2435 appears in fix(editor): release abandoned diff streams and owned placeholders (split 5/6 of #1066, unit U6a) #1932's ownership list and is absent from feat(tools): onParameterParseFailure teardown boundary (split 4/6 of #1066) #1931's;
    4. fix(write-to-file): clean partial state on missing-param and rooignore denial + integrate the #1066 split series (6/6 + FINAL) #1928 is a separate FINAL step after U7 in feat(tools): onParameterParseFailure teardown boundary (split 4/6 of #1066) #1931 and is named as U7 itself in fix(editor): release abandoned diff streams and owned placeholders (split 5/6 of #1066, unit U6a) #1932.

    What the transport does and does not settle. Measured 2026-11-12 with git reads only, 0 API cores, each head compared against org main tip efc22ed9f6f75975106f170cf29cc9bcc0b86682:

    • ancestry is forced in exactly one pair: 2dd4c696bf38 (U5a, U5a of the split of this pull: rollback recovery context and the report of whether a revert ran #1930) is an ancestor of 4baf005673f4 (U5b, U5b of the split of pull 1930: per-task stream state, captured once and released once #2435);
    • the other heads sit independently on main tip: git merge-base with main tip returns efc22ed9f6f7 for U4 7cf37b717791adeae8af48c8df62aa6b5f1a8f49, U5a 2dd4c696bf38, U5b 4baf005673f4, U3 4ca8b97015090c48d00e7db0d8c8f308cb86443e, U6a 5bc7709dfe515d35dd77fa2741a08bf8a6ce4250, U6b 725b8a3eb42fe3bd8c71e23b56a4ac7729ce5450 and U7 9ebacb5aa961, while b8e8a48dec1a (U12, fix(task): stage-independent saveClineMessages + finalize open partial tool ask (split 1/6 of #1066) #1927) bases on 72143527fd33306e5541116093c2cbf803cce9e0, an older main;
    • so nothing in the object database orders U4, U5a, U3, U6a and U7 against each other. The order is whatever the person merging chooses, and these two bodies promise different choices;
    • unit U6b is stacked on d52c1614f6e4780ce94b54c0357278b842cdebc1, which is the head U6a carried until 2026-11-12; U6a now carries 5bc7709dfe51, so as transported U6b trails U6a by one commit and only the promised sequence says which way to repair that;
    • the sequence is not cosmetic for the price rows either. Against main tip, src/integrations/editor/DiffViewProvider.ts is changed by U4, U5a, U5b, U3, U6a, U6b and U7, and src/core/tools/WriteToFileTool.ts by U4, U5b, U3, U6b and U7, so which branch lands first decides whose lines a mutation row sits on, and therefore which unit owes the mutant and what the cumulative line count of a later merge is.

    What is not being changed because of this item. Mutant-row attributions in #1932 and #1931 stay as published: ownership of a row follows the unit that adds the line and not the sequence the branches merge in, which is a ruling of this campaign. Lanes will keep pricing each unit against its own merge base and quoting unit and cumulative shapes apart, so a maintainer's sequence decision does not silently move a published number.

    Coordinates named: org main efc22ed9f6f7, fork main 53cb5b5e7c80, U6a 5bc7709dfe51 on p1066/u6-execute-error-path-cleanup, U6b 725b8a3eb42f on p1066/u6b-tool-stream-teardown, U3 4ca8b9701509 on p1066/u3-parse-failure-boundary, U4 7cf37b717791, U5a 2dd4c696bf38, U5b 4baf005673f4, U7 9ebacb5aa961, U12 b8e8a48dec1a. All read from the transport with git, not from any body.

  12. easonLiangWorldedtech commented on Nov 12, 2026

    @easonLiangWorldedtech
    ContributorAuthor

    Merge-order packet for the split-1066 chain: the ladder as read, the front rung, three priced merge footings, and four acts only a person can do

    Assembled at 0 metered cost from readings already on disk plus free-door and git-transport reads taken today, 2026-11-12T17:36Z to 17:37Z. One document, posted once, on this tracking issue only, because a consolidation that scatters itself across seven pulls is noise. Nothing below picks a side of the sequence disagreement filed here at 2026-11-12T09:25:16Z as comment 6819809725, which stands as written and is not amended.

    1. The ladder as read, and the shape every rung shares. The campaign's ladder read, recorded by lane s3-1395 at deferred-queue row q2267 and in handoff/README.md line 7014, states that every open rung carries a change-requested verdict, merges cleanly and reads blocked, that those three uniform fields are none of them CI fields, that every rung carries standing review requests naming four accounts of whom one is the person who merged the front rung, and that no act available to this campaign flips a review decision by itself. My own reads today corroborate the request list and the mergeability shape on two of those rungs: #1928 at head 9ebacb5 reads mergeable true, mergeable_state unstable, label awaiting-author, requested reviewers taltas, navedmerchant, edelauna, JamesRobert20; #1932 at head de36bde reads mergeable true, mergeable_state unstable, label awaiting-author, requested reviewers the same four accounts. Neither pulls object carries a review decision field, so the verdict itself is not on this door and this leg bought no review read.

    2. The front rung, and who landed it. The sequence that #1931 body line 31 declares begins with U12, which is #1927. Read on the anonymous door at 17:36:39Z: #1927 is closed, merged true, merged_at 2026-10-09T04:55:26Z, merged_by edelauna, merge commit 036245c, head b8e8a48 on p1066/u1-task-save-stages-and-partial-ask, base main at 9af61f8, 9 comments, label awaiting-maintainer still set, requested reviewers taltas, navedmerchant, JamesRobert20. So on that declaration the front rung landed on 9 October, landed by edelauna, who is also one of the four accounts holding standing review requests on the open rungs. On the other declaration, #1932 body lines 32 and 52, U12 does not appear and the first rung is U3 #1931, which is open and unmerged. Whether the front step is already under the campaign's feet is decided by the same disagreement, and which pull is the second rung is not settled anywhere in the records: the older table pairs these unit labels with different pull numbers, and one of the numbers the order line names, #1928, is the pull that same line calls the final integration step, open, 78 comments, last updated 2026-11-12T08:48:35Z.

    3. Three priced merge footings. Each is a construction that was built and measured, not a thing that landed.

    • M1, U6a then U3, the split direction. Commit b131201d886a976716e0501a94c259367f8b3895, tree dc0011b38c2a51a7b2235b302eadafa04877dcba, single parent d71db6a, the U6a head this lane priced, measured against main tip efc22ed: 478 counted executable lines, 241 of them in the provider file, 178 selectors, cap verdict not exceeded on changed lines, 0 typecheck diagnostics, vitest 240 pass 20 fail of 260 rows, split as moved file 74 of 78 passing, this unit's shared file 131 of 131, the parse-failure unit's teardown spec 10 of 26, its stream-state spec 25 of 25. Conflict hunks: the raw read of U3's file against merge base efc22ed and U6a's file gives 12 hunks in DiffViewProvider.ts and 4 in its spec, 16 in all, and this construction resolves them by taking the provider at the merged reset footing and splitting the spec file rather than choosing between its two bodies. Mutant figure: none. No killing stage has been priced at any merge footing in this campaign, so the 400-mutant cap is untested at this one.
    • M2, U5 then U6a. Commit d70707867b4e16a1eb826dcf227a1102b4083783, tree 564a1574435c0628e6008269a394df2a63eff697, parents 2dd4c69, the U5 U5a of the split of this pull: rollback recovery context and the report of whether a revert ran #1930 head, and d71db6a. Built with git merge-tree --write-tree, which exits 1 and leaves 10 conflict hunks in the written tree, 7 in DiffViewProvider.ts and 3 in its spec. Priced against main tip with the pinned instrument: 367 changed executable lines over 2 files, 363 in the provider and 4 in Task.ts, 60 selectors, 1 advisory line at src/core/task/Task.ts:4459 which is pre-existing, cap verdict overCap false. The count is a count over a conflicted tree: no conflict-free merge at that order has been built, so this is the shape of the collision, not a mergeable result. Mutant figure: none.
    • M3, the two U6 halves cumulative in the order the branches already carry. Cumulative efc22ed to 725b8a3: 474 changed executable lines, which is 208 plus 266, 172 selectors, which is 70 plus 102, and 430 mutants, which is 182 plus 248. Cap verdict: inside the 500 changed-line cap, 30 mutants over the 400-mutant cap. Conflict hunks 0, because U6b is stacked on d52c161, the head U6a carried until 2026-11-12, so it applies as a stack and not as a merge. Additivity was checked by re-measuring the chain top rather than by summing, and the sum matched. This is the only one of the three with a mutation figure, and it is the one that is over a cap.
    • Named so that three is not read as everything priced: the eight U3-against-U6a hunk constructions at 455 to 879 lines, four of them under the cap and the largest typecheck-clean one at 496, the authored both-behaviours body at 560 lines and 188 selectors, and the single-file footing at 208 lines and 70 selectors are all resolutions of the collision at one order. None of them is a merge-order footing.

    4. Freshness, because a merge-order packet is worthless at stale heads. Live branch tips read from the git transport at 17:37Z at 0 cores: U12 b8e8a48, landed; U3 41f1565; U4 7cf37b7; U5 2dd4c69; U5b 4baf005; U6a de36bde; U6b a1d9d24; U7 9ebacb5. Against those tips: d71db6a, the parent M1 and M2 were built on, is an ancestor of the live U6a tip, merge-base equals d71db6a, so both sit one commit behind a tip that adds de36bde, typed discard-test doubles; 725b8a3, M3's head, is an ancestor of the live U6b tip a1d9d24, which streams the preview before asserting the denial cleanup; U3's priced head 4ca8b97 is not an ancestor of its live tip 41f1565, merge-base equals main tip, 6 commits out and 6 in. Every figure above is therefore a price at the named construction. None of them is a price at today's tip, and re-pricing at today's tips is a metered job this packet does not claim to have done.

    5. What the free door states, and what it does not state, about the two heads the campaign's posture page missed. Both readings are at the head the pull carries now, taken at 17:36Z to 17:37Z on the anonymous door, 0 metered.

    • fix(editor): release abandoned diff streams and owned placeholders (split 5/6 of #1066, unit U6a) #1932 at de36bde, the head a merge of this unit would take today: 28 check-run rows on a single page, all of them completed with conclusion success, and the six contexts ruleset 15494382 requires, check-translations, platform-unit-test on ubuntu-latest, platform-unit-test on windows-latest, compile, knip and e2e-mock, all six named on this head and all six success, with mutation-diff completed success at 2026-11-12T16:01:32Z. The door does not state which rows are required, because it carries no required flag and the six names come from the ruleset read. It does not state whether any run is queued: a queued workflow run is invisible to this door, and a run that created no jobs is invisible to it as well. It does not state the mutant tally, because annotation titles and summaries read null here; the tally published for this head sits in digest comment 6812241362 with 21 blocking rows, quoted from the record rather than re-measured. It does not state why mergeable_state reads unstable while mergeable reads true.
    • feat(api): abort signal support for openrouter (completePrompt + createMessage) #1545 at db1bc09: 44 check-run rows on a single page, all completed with conclusion success, the same six required contexts present and success, and 26 of those rows housekeeping rather than gates, 13 reconcile PR review state runs and 13 resolve PRs to reconcile runs. Labels read awaiting-coderabbit and coderabbit-review-active, mergeable true with state unstable, and the base is main at 73931fe, an older main. The same four absences apply. One extra thing this read shows: for both heads the legacy combined-status door answers state pending with one status row and no combined object, so a person who checks that door sees pending on a commit whose six required checks are green, because that door cannot see check runs at all.
      feat(api): abort signal support for openrouter (completePrompt + createMessage) #1545 is not a rung of this chain. It is one of the eight pulls the posture page lists without a record at their live head, and its reading is filed in the lane ledger as closing two of those eight.

    6. Four things only a person can do, each with the object it applies to.

    1. Dismiss a change-request the campaign did not write. Objects: the standing change-requested verdicts on the open rungs feat(tools): onParameterParseFailure teardown boundary (split 4/6 of #1066) #1931 U3, feat(write-to-file): per-task partial stream state + cleanup primitives (split 2/6 of #1066) #1929 U4, U5a of the split of this pull: rollback recovery context and the report of whether a revert ran #1930 U5, U5b of the split of pull 1930: per-task stream state, captured once and released once #2435 U5b, fix(editor): release abandoned diff streams and owned placeholders (split 5/6 of #1066, unit U6a) #1932 U6a, fix(write-to-file): tear down per-task stream state on parse failure and dispose (split 5/6 of #1066, unit U6b) #2434 U6b and fix(write-to-file): clean partial state on missing-param and rooignore denial + integrate the #1066 split series (6/6 + FINAL) #1928 U7, which the ladder read found on every rung, held by the four accounts carrying standing review requests on them, taltas, navedmerchant, edelauna and JamesRobert20. Review identifiers per verdict are in lane u5a-2359 rows q2268 and q2271 and lane s3-1395 row q2267; this leg read no review door, so it names the objects and not the ids.
    2. Re-review a replaced head. Objects: fix(editor): release abandoned diff streams and owned placeholders (split 5/6 of #1066, unit U6a) #1932, whose adjudications were measured at 5bc7709 and whose priced parent is d71db6a while the branch now carries de36bde; feat(tools): onParameterParseFailure teardown boundary (split 4/6 of #1066) #1931, priced at 4ca8b97, its ref now carrying 41f1565 with merge-base at main tip and 6 commits each way; U5a of the split of this pull: rollback recovery context and the report of whether a revert ran #1930, whose head 2dd4c69 is a re-cut of the very commit its body names as its parent, acd836f, same author date and same subject line and provably not an ancestor of the head the branch carries, so no content at that head has been re-reviewed and the coordinate in prose folds with the next content push or does not happen at all; fix(write-to-file): clean partial state on missing-param and rooignore denial + integrate the #1066 split series (6/6 + FINAL) #1928, whose head the campaign last read as 9ebacb5 and which this leg did not re-read.
    3. Cancel queued runs. Objects: the 14 queued rows the actions door showed on 2026-11-11, seven on feat(checkpoints): per-task change journal with torn-tail repair (B2, #1375) #1406 at head a11d0de created 2026-11-11T20:34:24Z to 20:34:26Z and seven on fix(checkpoints): keep the task-start baseline from broadcasting a current checkpoint #2399 at head 915428b created 20:34:53Z to 20:34:56Z, every row status queued with conclusion null and run attempt 1. A second lane read the same door on the same two shas with the same parameters 2 h 35 m earlier and got the same run ids 7 of 7 on each pull, so this is repository queue occupancy and not an artifact of one read. Neither pull is a rung of this chain, so the act clears the queue rather than this ladder. The campaign cannot do it: reruns, cancels and workflow dispatches are refused by this credential.
    4. Merge, and choose the order. Objects: the seven open rungs named above. What the transport forces is one pair only: 2dd4c69, the U5 head, is an ancestor of 4baf005, the U5b head, and every other head sits independently on main tip, so the object database orders none of U4, U5, U3, U6a, U6b and U7 against each other and the order is whatever the person merging chooses. What the choice costs, at the priced footings: U6a-then-U3 gives a merge at 478 changed executable lines, U5-then-U6a gives 367, a difference of 111 lines, and the order the branches already carry puts the two U6 halves cumulative at 430 mutants, 30 past the cap.

    7. What this packet does not do. It picks no sequence, retracts no published number, patches no body, changes no label, and adds no comment anywhere else on the strength of anything in it. Costs: 0 metered cores and 0 GraphQL to assemble it, the new reads having gone through the anonymous door, 9 calls, remaining 52 of 60 at 17:37Z, and through the git transport, which is free; 1 metered core to post this document, whose response body is its read-back and is an echo rather than an independent read.

    Human-debt census for the eight pulls whose review lists were read, as measured

    Assembled from eight review lists and two pull bodies. Verdict rows are fresh to the second: read 2026-11-12T19:54:06Z to 19:54:12Z for 2399, 2395, 2396, 2414, 2417, 2428 and 2431 and for the first hundred rows of 1406, and 20:06:15Z for the remaining nineteen rows of 1406. Pending-reviewer sets are fresh to the minute for the two pulls carrying queued runs, read from their own pull bodies at 19:42:38Z and 19:42:39Z, and quoted from a listing read 2026-11-11T23:05:01Z for the other six, which is twenty hours and forty-nine minutes older than the lists above, so those six sets are named as disk rather than fresh. Nothing here is a verdict about a person: no reviewer is called unresponsive, because what was measured is who authored a row inside a window.

    The census. Across the eight lists, 166 review objects were read, of which 23 are verdict rows, meaning APPROVED, CHANGES_REQUESTED or DISMISSED, and 143 are plain comments. The author of every one of the 23 verdict rows is coderabbitai[bot]. The number of rows authored by a human who is not the pull author is 0 on every page read, and not one of the people named as a requested reviewer on any of these eight pulls authored a row on any of these eight doors. The weaker sentence is the true one: no requested reviewer authored a row inside these windows.

    Six of the eight already carry a bot approval at a commit named by its identifier while named people are still listed as requested: 2395 row 5835402886 APPROVED 2026-11-10T01:34:18Z at commit e8dce4f, 2396 row 5853617121 APPROVED 2026-11-11T03:52:27Z at 9225496, 2414 row 5847397818 APPROVED 2026-11-10T18:41:59Z at ca2dc28, 2417 row 5848829091 APPROVED 2026-11-10T20:27:15Z at b66149f, 2428 row 5857800454 APPROVED 2026-11-11T11:09:26Z at 4f0ca7c, 2431 row 5862622739 APPROVED 2026-11-11T17:15:25Z at f9fcfbd. Each is the newest row its own door printed. On each of the six the listing names the same three requested people, taltas, edelauna and JamesRobert20, and on each of the six the head recorded in that listing is the same commit the approval was filed at, which is a corroboration between two doors and not new evidence about the pull, and whose head each pull carries now was not read, so no verdict commit above can be called current or stale.

    On the two pulls that carry the fourteen queued runs, the verdict history is their own. On 1406 the first list read is a window over a history rather than the history: it printed exactly 100 rows and a next-page header, and the page it pointed to has now been bought, printing 19 further rows spanning 2026-11-08T00:40:50Z to 2026-11-09T22:26:05Z, all of them plain comments and none a verdict, with no further next-page header, so the list is 119 rows long and ends there and a later human verdict would have sat on the page now read and does not. The newest verdict row on 1406 is 5815496498 CHANGES_REQUESTED at 2026-11-07T23:10:05Z filed at commit e12e961. On 2399 the whole list is one row, 5837498091 CHANGES_REQUESTED at 2026-11-10T06:06:56Z filed at commit 720b2bf. The pending sets there are fresh to the minute: 1406 lists taltas, navedmerchant, hannesrudolph, edelauna and JamesRobert20, and 2399 lists taltas, edelauna and JamesRobert20.

    One door fact, reported rather than substituted around. The one call this lane named for the pending sets of the six, GET /repos/Zoo-Code-Org/Zoo-Code/pulls/reviews, answered 404 Not Found at 20:06:15Z with body message Not Found and status 404, so no such list-review-requests door is printed by this platform for an organisation repository as this lane read it, and the door that does print pending sets for many pulls in one call is the open-pulls listing, GET /pulls?state=open and per_page 100, whose rows carry requested_reviewers, which is the door the 2026-11-11T23:05:01Z listing above came from. That refresh costs 1 anonymous point and was not bought on this leg, and the 404 cost 1 anonymous point all the same, the counter moving from 30 to 31 used, which is the second time this session that a refusal was measured to charge.

    What a person is asked for here is the set this campaign has already asked for, each named once with what it covers, and nothing new. A cancel or a re-run of the fourteen queued runs on 1406 and 2399. A dismissal or another disposition of the two standing bot CHANGES_REQUESTED rows named above, 5815496498 on 1406 at commit e12e961 and 5837498091 on 2399 at 720b2bf. And reviews from the people already listed as requested, the five named above on 1406, the three named above on 2399, and taltas, edelauna and JamesRobert20 on 2395, 2396, 2414, 2417, 2428 and 2431. The credential that wrote this can read these doors and cannot file a review, dismiss one, approve, cancel a run or queue a run, so every item above remains an ask.

    Absences named rather than implied. Pull 1404 and its new head are not part of this census and are reported elsewhere. The runs listed for any head at the minute this append was written were not re-read for this census. The artifact copy priced in the queue is quoted at its printed expiry of 2026-11-19T08:12:36Z rather than refreshed. Comment 6716150010 is still unbought. No cause is advanced for the fourteen staying queued, and no cause is advanced for the authorship census above, which counts rows and names and not reasons.

  13. easonLiangWorldedtech commented on Nov 12, 2026

    @easonLiangWorldedtech
    ContributorAuthor

    The merge-order packet posted on this issue proposed nothing it could settle: it recorded what the objects force, named the acts that belong to a person, and picked no sequence. This is the measurement that closes the question it left open, and it says plainly: no ordering of the seven open rungs lands without a conflict, so the ladder is a constraint on a maintainer, not a preference among landing plans.

    The arithmetic first, so the completeness claim is checkable rather than impressive. Each rung was merged into the base-side main tip (efc22ed, re-fetched in this leg; all seven have it as merge base and none is behind main) with git merge-tree --write-tree, and each written tree was hung on the accumulated commit and the rung with commit-tree, then recursed - 69 merge-tree calls over 12 search nodes settled all 5,040 orderings, because conflicts prune hard: 38 of the 42 possible second rungs conflict, each pruning the 120 orderings that begin with that pair, and the 4 surviving prefixes conflict at the third rung in all five of their continuations each, each pruning 24. 38 x 120 + 20 x 24 = 4,560 + 480 = 5,040, the whole space, and none of it survives.

    Two facts a reader can act on. Every single rung merges into main on its own today - the first step of that search merges all seven with no conflict at all - which is exactly what the per-pull mergeability field reports and exactly what that field does not license: it says nothing about landing two of them together. And only four two-rung orders are constructible clean: the two checkpoint rungs in either order, #1930 then #2435 and #2435 then #1930, and the two write-path rungs in either order, #1932 then #2434 and #2434 then #1932. A third rung always conflicts.

    Named by file, since a person deciding whether to re-cut needs the path and not the tally: src/integrations/editor/DiffViewProvider.ts is named by every one of the 19 conflicting pairs, which makes it the single cross-cutting path of this chain rather than a majority of them, and its spec src/integrations/editor/__tests__/DiffViewProvider.spec.ts by 15. The rest is carried by src/core/tools/WriteToFileTool.ts (10 pairs) with src/core/tools/__tests__/writeToFileTool.spec.ts (10) and src/core/tools/__tests__/writeToFileTool-partial-state-cleanup.spec.ts (10), by src/core/tools/BaseTool.ts (9), by src/core/assistant-message/presentAssistantMessage.ts (4), by src/core/task/Task.ts (2, the #1930/#1928 and #2435/#1928 pairs), and by src/__tests__/removeClineFromStack-delegation.spec.ts, which appears in 7 of the 9 conflicting pairs involving #2435 or #2434 - the two exceptions being #2435 with #1932 and #1930 with #2434, whose entire conflict list is the provider pair above. One shared line is not a conflict and should not be counted as one: src/core/webview/ClineProvider.ts line 735 is carried identically as writeToFileTool.clearTaskState(task) by all five rungs that touch it, which is why that path never appears in a conflict list.

    I owe the numbers above a correction named in the sentence rather than left for a reader to reconstruct: my first report of this measurement said the provider pair appeared in 13 of 19 pairs, and my first correction said the write tool appeared in 14. The artifact says 19 and 10, and both figures are read back out of t38-pairs-today.json rather than out of memory. The map document never carried either summary sentence - it lists every conflicting pair with its own paths and its own hunk ranges - so what was wrong was a spoken count and not the measurement, and the numbers in the object store did not move.

    One rung reads over both ceilings only because of where it sits. #2435 measures 519 counted executable lines and 460 instrumented mutants against the 500 changed-line and 400 valid-mutant ceilings, 19 and 60 over, because it is stacked on the #1930 head and carries its 226 lines cumulatively; its own increment over the commit it sits on is 293 counted executable lines and 109 selector ranges, inside both ceilings. That is the difference between a unit that is too big and a stack that is too big, and only the second one is fixed by re-ordering. For contrast the other six are inside both ceilings at today's tips: #1931 at 404 lines and 384 instrumented mutants, #1929 at 368 and 349, #1930 at 226 and 192, #1932 at 210 and 185, #2434 at 474 and 430 (26 lines of headroom, 30 over on mutants, and it carries an earlier cut of the #1932 branch rather than its current head), #1928 at 334 and 277. All widths are my measurement against the merge base named above, counted with the committed instrument, and the mutant figures are preflight instrumented counts, not killing counts.

    Four disagreements about order are already on the platform and each is named here with both readings and the lane that holds one of them. (1) Whether the chain lands cleanly: lane s3-1395's row q2267, relayed in the sweep log and repeated in this issue's merge-order packet, reads every rung as merging cleanly, which is a per-pull mergeability field against main, while my measurement says 19 of 21 rung pairs conflict and no ordering of seven is clean - the two readings are about different things, and the first does not license the second. (2) What the declared order is: the committed stack protocol names #1931 then #1929 then #1930 then #1932, and that declared order conflicts at its own second step in 7 hunks across 7 paths while naming four rungs where seven are open; separately, lane u9-1917 reports from the door that #1931's body declares a sequence beginning with #1927, which the door reports closed and merged. (3) What #1930's parent is: its body names acd836f while the branch carries 2dd4c69 with single parent efc22ed, read from the transport by lane u9-1917 and verified by me in my own object store, the row closed as accepted staleness with the corrected coordinate riding the next content push. (4) Whether my prices can be sourced: lane u9-1917's row q1900 records that its controls reproduce the 207/68/183 and 243/95/227 pairs my lane could not source to 3c5036a or 27465f8; this comment carries that as that lane's reproduction and does not settle it.

    Limits, kept here rather than added afterwards. A clean written tree means no textual conflict: it does not mean the result builds, tests, or is the content a reviewer approved, and a rehearsal commit in my object store is neither CI nor a merge. Instrumented counts are not killing counts and carry this checkout's known runner-activation defect, so nothing here says a mutant is or is not equivalent. Typecheck and lint were not run on these seven heads in this leg; lint in particular is unrunnable from this worktree because the lint config's selector import is missing in the junction-resolved tree, and the node_modules junction points at another lane's tree, so cross-package resolution here carries artifacts that are not these rungs' own. Where my numbers agree with lane u9-1917's - 474 lines, 172 selectors and 430 instrumented mutants at the #2434 footing, and the both-orders conflict of an earlier #1932 head with today's #1931 head naming the provider and its spec - that is two lanes' measurements agreeing on objects, which is corroboration and not verification. This comment states no review verdict, no review request, no label and no merge authority, because no review door, checks door, merge endpoint or actions door was read in this leg.

    The map itself lives in this campaign's books, not here: .tmp-cr-audit/handoff/chain-map-1066-f0-1528.md, with every row tagged by how it was obtained - git read, my measurement, an earlier authenticated REST row, another lane's record with the lane named, or committed protocol text - so any sentence above can be traced to its kind of evidence, and a reported reading is never mistaken for a measured one. It was built at 0 metered cost on git transport and local processes, and nothing in it is pushed; the refs holding the seven tips are mine and unpushed, each with a fetched-tip contains count of 0. This comment cost 1 token core and is the only write made.

  14. easonLiangWorldedtech commented on Nov 13, 2026

    @easonLiangWorldedtech
    ContributorAuthor

    Line-cap table for the three aligned carriers of the guarded-write chain: pulls #1915, #1916, #1917

    This is the number a split decision is made with, put where a maintainer reads it rather than where this campaign reads it. Measured locally, 0 metered, on 2026-11-13 between 00:26Z and 00:31Z, from a checkout at e5f696b9e184b623bbd962fdbc10c4b436c8827f that holds all six objects, running the instrument the workflow pins at blob 7dfe0006d2d5c7e4d2282f65f68b8ed5f16866bc (scripts/stryker-diff.mjs, 869 lines). The ceiling is the script's own per-package limit, MAX_CHANGED_LINES = 500 counted executable changed lines, and every figure below is a counted executable line total for the extension package, which is the package that trips the ceiling on all three carriers.

    One row per carrier

    pull carrier head as pushed head object the figure was measured from counted executable lines, extension package, ceiling 500 over the ceiling by the merge result whose run printed the cap line extension package measured against the declared chain base a0d03a06a3aff42e2e4561e881911e48ff3bff42, counted executable lines over selector ranges
    #1915 ec3e02e56321671aedb7faa30d23ded47898d284 8d6b79a1e992731d92ebab3164945c2755317179 (door's merge result, first parent main efc22ed9f6f7 i.e. efc22ed9f6f75975106f170cf29cc9bcc0b86682) 1633 1133 8d6b79a1e992731d92ebab3164945c2755317179 2007 lines over 457 selector ranges, over the ceiling by 1507
    #1916 5f8474d16236445b0a984a3eb4ac8c4d1e38aecd f552ce47daa0e4cb4942b8c0bc26511a445cd132 (door's merge result, first parent main efc22ed9f6f7) 1577 1077 f552ce47daa0e4cb4942b8c0bc26511a445cd132 1983 lines over 449 selector ranges, over the ceiling by 1483
    #1917 e5f696b9e184b623bbd962fdbc10c4b436c8827f 704f838edc478bce7fcc1d1bb3055e91a23db3ae (door's merge result, first parent main efc22ed9f6f7) 1750 1250 704f838edc478bce7fcc1d1bb3055e91a23db3ae 1949 lines over 449 selector ranges, over the ceiling by 1449

    Each carrier now carries main's tip, so the merge result is main's tip plus that unit and nothing else, and its tree is identical to the carrier head's tree on all three, which is to say GitHub's own pre-merge join reproduces the resolution each lane wrote. The three cap lines the script printed for those three heads, verbatim and each from its own run against efc22ed9f6f75975106f170cf29cc9bcc0b86682:

    Mutation gate failed: extension has 1633 changed executable lines (limit 500). Split the PR or obtain a maintainer-reviewed narrow exclusion.
    Mutation gate failed: extension has 1577 changed executable lines (limit 500). Split the PR or obtain a maintainer-reviewed narrow exclusion.
    Mutation gate failed: extension has 1750 changed executable lines (limit 500). Split the PR or obtain a maintainer-reviewed narrow exclusion.
    

    The same script and the same ceiling, priced against the third base, the one the two footings above are not anchored on: the chain base the pull declares, a0d03a06a3aff42e2e4561e881911e48ff3bff42. The base is handed in and used as handed, because resolvePullRequestBase is deliberately not called on this footing -- every carrier head has two parents, the unit commit and main's tip efc22ed9f6f75975106f170cf29cc9bcc0b86682, and that step would throw the passed base away and price the head against its own first parent instead. Neither parent is the base here; the merge base is the chain base on all three, checked with git merge-base and not assumed. These are the lines the script prints on this footing, with the two objects it was handed written beside each one, so that this is not mistaken for a fourth rival measurement of the quantity in the table:

    base a0d03a06a3aff42e2e4561e881911e48ff3bff42  head ec3e02e56321671aedb7faa30d23ded47898d284   (pull 1915, carrier head as pushed)
      Mutation gate failed: extension has 2007 changed executable lines (limit 500). Split the PR or obtain a maintainer-reviewed narrow exclusion.
    
    base a0d03a06a3aff42e2e4561e881911e48ff3bff42  head 5f8474d16236445b0a984a3eb4ac8c4d1e38aecd   (pull 1916, carrier head as pushed)
      Mutation gate failed: extension has 1983 changed executable lines (limit 500). Split the PR or obtain a maintainer-reviewed narrow exclusion.
    
    base a0d03a06a3aff42e2e4561e881911e48ff3bff42  head e5f696b9e184b623bbd962fdbc10c4b436c8827f   (pull 1917, carrier head as pushed)
      Mutation gate failed: extension has 1949 changed executable lines (limit 500). Split the PR or obtain a maintainer-reviewed narrow exclusion.
    

    Provenance of the two columns, because it matters when they are read side by side. The chain-base figures above are read from the head being priced, the script's own arithmetic run against git show of that head. The three lines quoted earlier came from a checkout that holds pull 1917's tree, and the script reads source files off the working tree, so on pulls 1915 and 1916 those two runs filtered changed lines against 1917's files rather than their own. Read from the head being priced, the same main-tip footing prints 1808 for pull 1915 and 1784 for pull 1916, and 1750 for pull 1917 unchanged. Like-for-like the two footings are therefore 2007 against 1808, 1983 against 1784 and 1949 against 1750, and the gap is 199 lines in this package on every one of the three.

    On the chain base the other two packages price as well, identically on all three carriers: types 67 counted executable lines over 5 selector ranges and webview 50 lines over 14 selector ranges, which the main-tip footing prices at nothing, so the all-package totals on the chain base are 2124 for pull 1915, 2100 for pull 1916 and 2066 for pull 1917 against 1808, 1784 and 1750 on the main tip. The whole difference is 316 lines on each of the three, and it is main's own movement between the chain base and main's tip, not a line any of these pulls wrote. Nineteen files price only from the chain base, 296 counted executable lines: nine in the extension package, src/api/providers/fetchers/friendli.ts 58, src/api/providers/friendli.ts 55, src/api/providers/requesty.ts 46, src/api/providers/openai-codex.ts 6, src/core/task/Task.ts 5, src/core/webview/webviewMessageHandler.ts 4, src/integrations/misc/export-markdown.ts 2, src/shared/experiments.ts 2, src/shared/api.ts 1; four in types, packages/types/src/providers/openai.ts 45, packages/types/src/providers/openai-codex.ts 19, packages/types/src/experiment.ts 2, packages/types/src/provider-settings.ts 1; six in webview, webview-ui/src/components/ui/hooks/useSelectedModel.ts 15, webview-ui/src/components/settings/utils/providerModelConfig.ts 11, webview-ui/src/components/ui/hooks/useRouterModels.ts 10, webview-ui/src/components/settings/ApiOptions.tsx 7, webview-ui/src/components/chat/ModelSelector.tsx 6, webview-ui/src/components/marketplace/components/MarketplaceItemCard.tsx 1. The remaining 20 lines are in the one file both footings price by different counts, src/core/task/observationRegistry.ts, which reads 22 from the chain base and 2 from main's tip on all three carriers because main already carries 20 of those lines.

    The two footings side by side, taken from pull #1917

    Footing the job takes. A pull_request run checks out the door's merge result as github.sha,
    and the workflow sets HEAD_SHA to github.sha and BASE_SHA to git rev-parse HEAD^1:
    
    node scripts/stryker-diff.mjs ci --base efc22ed9f6f75975106f170cf29cc9bcc0b86682 --head 704f838edc478bce7fcc1d1bb3055e91a23db3ae
    
      Mutation gate failed: extension has 1750 changed executable lines (limit 500). Split the PR or
      obtain a maintainer-reviewed narrow exclusion.
      exit 1 after 0.9s, and the job writes no summary at all, because the script reaches its
      summary writer only after the selection step returns, so a cap throw leaves a red row with
      an empty title, an empty summary and no digest for anyone to read.
    
    Footing a person takes when they paste the line the report prints. The head here is the branch
    commit, and the reproduce line below is the instrument's own printed line for that run:
    
    node scripts/stryker-diff.mjs ci --base d82d63ef3e8c0595e741b8b5f58a5ba5b4d4336b --head e5f696b9e184b623bbd962fdbc10c4b436c8827f
    
      Mutation-testing 3 package(s) from merge base d82d63ef3e8c: types (67 lines), extension (186
      lines), webview (50 lines)
      exit 0, 0 blocking, 4 advisories.
    

    The base in that reproduce line is not the base that was passed to it. resolvePullRequestBase (lines 287 to 291 of the blob above, called from the selection step at line 296) replaces a passed base with the head's first parent whenever the head has two parents, so a reader who passes main's tip and gets d82d63ef3e8c... back is being handed the previous rung, and 303 lines is what arrived on top of that rung. That is a smaller and different quantity from 1750, and the two must not be read as competing measurements of the same thing.

    Both footings take their base from the head's own first parent, so both are anchored on a door's merge result or on the previous rung, and neither measures the unit against the chain's declared shared base a0d03a06a3aff42e2e4561e881911e48ff3bff42, which is the one base the chain was declared against and the only footing on which the unit's own total can be compared with its siblings; and neither footing produced a single mutant result, no killed, survived or no-coverage count for any line it priced. The absent measurement is the unit's own total against its declared base and the mutant evidence behind those lines, and a split or an exclusion is decided on exactly that.

    The chain-base footing in full, per carrier

    The extension package against the declared chain base a0d03a06a3aff42e2e4561e881911e48ff3bff42, counted executable lines and selector ranges, largest file first, down past where the weight sits, with the counted-line figure the same package shows against main's tip beside it. The two objects handed to the script are named above each block and named again in the table column.

    pull 1915  base a0d03a06a3aff42e2e4561e881911e48ff3bff42  head ec3e02e56321671aedb7faa30d23ded47898d284
     724 lines / 139 ranges from the chain base, 724 lines / 139 ranges from main's tip    src/integrations/editor/DiffViewProvider.ts
     460 lines /  48 ranges from the chain base, 460 lines /  48 ranges from main's tip    src/core/tools/guardedWrite.ts
     344 lines / 103 ranges from the chain base, 344 lines / 103 ranges from main's tip    src/services/file-safety/safeWriteText.ts
     131 lines /  46 ranges from the chain base, 131 lines /  46 ranges from main's tip    src/utils/safeWriteJson.ts
      98 lines /  16 ranges from the chain base,  98 lines /  16 ranges from main's tip    src/core/tools/ApplyPatchTool.ts
      58 lines /  10 ranges from the chain base,   0 lines /   0 ranges from main's tip    src/api/providers/fetchers/friendli.ts
      55 lines /  23 ranges from the chain base,   0 lines /   0 ranges from main's tip    src/api/providers/friendli.ts
      46 lines /  19 ranges from the chain base,   0 lines /   0 ranges from main's tip    src/api/providers/requesty.ts
      33 lines /  21 ranges from the chain base,  33 lines /  21 ranges from main's tip    src/core/tools/ReadFileTool.ts
      22 lines /  11 ranges from the chain base,   2 lines /   1 ranges  from main's tip    src/core/task/observationRegistry.ts
      extension package 2007 lines over 457 selector ranges in 18 priced files against main's tip 1808 lines over 383 ranges in 15 priced files, ceiling 500, over by 1507 and by 1308
    
    pull 1916  base a0d03a06a3aff42e2e4561e881911e48ff3bff42  head 5f8474d16236445b0a984a3eb4ac8c4d1e38aecd
     724 lines / 139 ranges from the chain base, 724 lines / 139 ranges from main's tip    src/integrations/editor/DiffViewProvider.ts
     460 lines /  48 ranges from the chain base, 460 lines /  48 ranges from main's tip    src/core/tools/guardedWrite.ts
     344 lines / 103 ranges from the chain base, 344 lines / 103 ranges from main's tip    src/services/file-safety/safeWriteText.ts
     131 lines /  46 ranges from the chain base, 131 lines /  46 ranges from main's tip    src/utils/safeWriteJson.ts
      58 lines /  10 ranges from the chain base,   0 lines /   0 ranges from main's tip    src/api/providers/fetchers/friendli.ts
      55 lines /  23 ranges from the chain base,   0 lines /   0 ranges from main's tip    src/api/providers/friendli.ts
      46 lines /  19 ranges from the chain base,   0 lines /   0 ranges from main's tip    src/api/providers/requesty.ts
      37 lines /  22 ranges from the chain base,  37 lines /  22 ranges from main's tip    src/core/tools/ReadFileTool.ts
      26 lines /   3 ranges from the chain base,  26 lines /   3 ranges  from main's tip    src/core/tools/ApplyPatchTool.ts
      22 lines /  11 ranges from the chain base,   2 lines /   1 ranges  from main's tip    src/core/task/observationRegistry.ts
      extension package 1983 lines over 449 selector ranges in 22 priced files against main's tip 1784 lines over 375 ranges in 19 priced files, ceiling 500, over by 1483 and by 1284
    
    pull 1917  base a0d03a06a3aff42e2e4561e881911e48ff3bff42  head e5f696b9e184b623bbd962fdbc10c4b436c8827f
     401 lines /  47 ranges from the chain base, 401 lines /  47 ranges from main's tip    src/core/tools/guardedWrite.ts
     338 lines /  53 ranges from the chain base, 338 lines /  53 ranges from main's tip    src/core/task-persistence/TaskHistoryStore.ts
     338 lines /  79 ranges from the chain base, 338 lines /  79 ranges from main's tip    src/integrations/editor/DiffViewProvider.ts
     266 lines /  83 ranges from the chain base, 266 lines /  83 ranges from main's tip    src/services/file-safety/safeWriteText.ts
     113 lines /  40 ranges from the chain base, 113 lines /  40 ranges from main's tip    src/utils/safeWriteJson.ts
      92 lines /  14 ranges from the chain base,  92 lines /  14 ranges from main's tip    src/core/tools/ApplyPatchTool.ts
      58 lines /  10 ranges from the chain base,   0 lines /   0 ranges from main's tip    src/api/providers/fetchers/friendli.ts
      55 lines /  23 ranges from the chain base,   0 lines /   0 ranges from main's tip    src/api/providers/friendli.ts
      46 lines /  19 ranges from the chain base,   0 lines /   0 ranges from main's tip    src/api/providers/requesty.ts
      38 lines /  10 ranges from the chain base,  38 lines /  10 ranges from main's tip    src/core/webview/ClineProvider.ts
      extension package 1949 lines over 449 selector ranges in 25 priced files against main's tip 1750 lines over 375 ranges in 22 priced files, ceiling 500, over by 1449 and by 1250
    

    File for file and range for range, every file these pulls themselves edit is counted the same way on both footings, and the only file whose count moves is observationRegistry.ts, where the 20 lines that move are main's lines that the alignment already carries. The difference between the two footings is therefore this: the chain-base footing is the unit plus everything the trunk moved between the chain base and today, 316 counted executable lines of the trunk's own work on each of the three pulls, 296 of it in files these pulls never open, while the main-tip footing is the unit alone, and the ceiling the job is complaining about is being asked of the unit alone, because the merge result already absorbed the trunk's half.

    The two options, in the instrument's own words

    The printed sentence names both: Split the PR or obtain a maintainer-reviewed narrow exclusion. Neither is a campaign decision to make. The files that carry the weight, priced file by file at the 1750-line footing, all inside the extension package and none of them over the ceiling on its own, so the ceiling is tripped by the package total rather than by any single file:

    401  src/core/tools/guardedWrite.ts
    338  src/core/task-persistence/TaskHistoryStore.ts
    338  src/integrations/editor/DiffViewProvider.ts
    266  src/services/file-safety/safeWriteText.ts
    113  src/utils/safeWriteJson.ts
     92  src/core/tools/ApplyPatchTool.ts
     38  src/core/webview/ClineProvider.ts
     35  src/core/tools/ReadFileTool.ts
     26  src/core/tools/ApplyDiffTool.ts
     26  src/core/tools/WriteToFileTool.ts
     23  src/core/tools/EditTool.ts
     23  src/core/tools/SearchReplaceTool.ts
     16  src/core/tools/EditFileTool.ts
      9  src/utils/jsonFileRecovery.ts
      4  src/integrations/misc/indentation-reader.ts
      2  src/core/task/observationRegistry.ts
    ---
    1750 total, against the ceiling of 500, over by 1250
    

    The other 26 of the pull's 42 changed paths price as nothing because they are test files or sit under the script's excluded path segments, so the weight is in production code and the six largest entries above hold 1,548 of the 1,750.

    This campaign can merge a carrier or leave one, and it can report what the ceiling says. It cannot choose a narrow exclusion for a mutant it has not run, and it has not run one on any of these three heads: on the job's footing the script throws before any mutant starts, and on the branch footing the runs this lane could start locally did not start at all because this lane's checkout borrows its node_modules across a junction. So every mutant figure in this comment is an absence, not a zero, and no suppression was added anywhere to make it look otherwise. Scanning every added line of all three carrier deltas against main's tip, 14757 lines on #1915, 13833 on #1916 and 13564 on #1917, finds no added line containing a Stryker disable directive, an eslint-disable, a ts-ignore or an as any, and src/eslint-suppressions.json is the same object f3714cd1f521... at all three carrier heads with 265 file entries and 2866 counts against 265 entries and 2868 counts on main's tip, so the suppressed counts fell by two and did not rise at any carrier.

    No door was re-read for this comment and nothing else was bought for it. It is one write on this issue, priced at two points against this lane's remaining budget, and the rate figures it reports are the response headers this own request received, printed below the comment rather than guessed.

  15. easonLiangWorldedtech commented on Nov 13, 2026

    @easonLiangWorldedtech
    ContributorAuthor

    A collision report, filed here because this is the tracking object this campaign carries the #1066 chain map on: this lane read it earlier as a free page at #1989, which prints the declared chain order U3 #1931 then U4 #1929 then U5 #1930 then U6a #1932 then U6b then U7 #1928. This lane has written twice, one threaded reply under a review thread on pull 1395 and this comment, and bought no read of any door, so the echo of this write is the only thing about this object that was paid for.

    The three spellings of one lock now in the world, and the head each one sits at the tip of.

    1. Leaf spelling. refs/heads/vps2f-filelock-identity-key at 86119de, committer 2026-11-13T07:06:42+08:00, pushed. Its kept twin at refs/heads/s3/1395/2368-lock-contention, 9d21fc3, is unpushed and has no origin copy.
    2. Ancestor realpath walk with a post-acquisition re-derivation. refs/heads/vps2f-1914-u5c1-filelock at 2c79cd4, committer 2026-11-10T12:49:18+08:00, pushed. The local copy 9c08f7b is an ancestor of it, so the pushed head carries everything the local tip holds.
    3. One canonical lock key taken inside the shared acquire protocol. refs/heads/fws/u4-read-scope-recording at cf7ab26, committer 2026-11-13T09:11:37+08:00, pushed. The same file is already paid a second time at the tip of refs/heads/fws/u4b-json-publish, e6021d6, committer 2026-11-13T09:48:23+08:00, pushed, and src/utils/fileLock.ts on those two heads is the same blob, 8d1717eb49feeaf989db1728be515aa04ba90a08, printed by rev-parse of both trees.

    The measured collision. git merge-base --is-ancestor was run for each of 9d21fc3, 9c08f7b, cf7ab26, 86119de, 2c79cd4 and e6021d6 against pull 1395 head 925f8b7 and against the trunk efc22ed. Twelve runs, twelve exits of 1, no exit of 0. None of the three answers is contained in that head or in the trunk, so whichever of them lands first, each of the others pays again at merge time on the head that already carries its content.

    What each closes and what it leaves, one clause each.

    • Leaf spelling: it closes the case where one leaf carries two names, an 8.3 alias or a case variant on a case-insensitive volume, and each name takes its own lock artefact, by naming the artefact from the spelling the volume itself holds for the final component only, and it leaves the ancestor symlink untouched, because it re-spells the leaf and never the directory and keeps realpath: false.
    • Ancestor walk: it closes the ancestor re-targeted after the key was computed for callers of withFileLock, by re-deriving the key once the lock is held and retaking the lock for the new key and refusing after 3 retargets rather than running under a lock no peer is provably holding, and it leaves the acquireFileLock route with the walk but no re-derivation, because there that function is canonicalLockPath once and then _lockCanonicalKey, and it leaves the leaf-name residual deliberately, because it canonicalizes only the nearest existing ancestor and compares the basename as written.
    • Single canonical key: it closes the two protocols watching two different lock files for one target at one instant, because withFileLock and the safeWriteJson route then take the key from the same resolveLockKey, and it leaves the time half of the ask open, because nothing in it re-derives a key after the lock is held and it tolerates a dangling link so that the key stays computable while a peer is mid-commit.

    The counted executable line price of each on pull 1395 own footing, ceiling 500 counted lines per package, measured with scripts/stryker-diff.mjs taken out of the tree being priced at 925f8b7 and each candidate committed in a scratch checkout of that head and the head reset back afterwards. Leaf spelling: 34 counted lines across 13 selector ranges, 27 lines across 11 ranges in src/utils/fileLock.ts plus 7 lines across 2 ranges in the new src/utils/lockLeafSpelling.ts, headroom 466. Ancestor walk: 86 counted lines across 31 selector ranges, all of them in src/utils/fileLock.ts, headroom 414. Single canonical key: 1 counted line across 1 selector range, headroom 499. And that cheapest figure is the size of an edit that does not typecheck there, which is the finding worth having: pull 1395 own src/services/file-safety/safeWriteText.ts exports resolvePublishTarget at line 356, assertPublishWithinAuthorizedRoot at line 424 and safeWriteText at line 461, and it does not export resolveLockKey, which is the symbol that edit imports, so the 1 line is the size of a substitution and not the size of a landing. Priced the way its own branch measures it against the trunk, that answer is 318 counted lines across 119 selector ranges with headroom 182, and it is not lock-only: safeWriteText.ts 266 lines across 87 ranges, src/core/tools/ReadFileTool.ts 40 across 25, src/integrations/misc/indentation-reader.ts 11 across 6, src/utils/fileLock.ts 1 across 1.

    Two costs a line count does not show, named rather than smoothed. The ancestor walk replaces src/utils/tests/fileLock.spec.ts, which on pull 1395 head is 125 lines and carries the rows pinning that pull own exported resolver, with its own 469 line file at the same path. And the mutant side is unspent rather than satisfied for all three: no Stryker run was bought or run for any of them, so the 400 ceiling is untested here.

    The open decision, which the maintainers own. The two routes compute the lock key by two derivations, and the review trace on pull 1395 needs them to share one, because the writer that loses an update reaches the lock through the route its peer does not share. On the canonical-key head the canonicalize sits inside acquireFileLock at line 41 while withFileLock keeps a raw path.resolve at line 86 and hands that path to the operation at line 91; on the ancestor-walk head both routes call canonicalLockPath and only withFileLock re-derives. Whether the two routes should share one derivation, and which function should own it, is not something this campaign can settle, and none of the three objects above settles it. Nothing named in this comment landed on pull 1395, no thread was resolved by it, and no read was bought for it.

  16. easonLiangWorldedtech commented on Nov 13, 2026

    @easonLiangWorldedtech
    ContributorAuthor

    The 500-line ceiling, in the instrument's own words, and what it counts

    scripts/stryker-diff.mjs, blob 7dfe0006d2d5c7e4d2282f65f68b8ed5f16866bc, 30,108 B. That is the copy in force: git rev-parse <commit>:scripts/stryker-diff.mjs returns this blob for main's tip, for the tip it replaced, and for all six heads below, so it is the copy the gate runs. Lines 11 and 12 set the two ceilings:

    export const MAX_CHANGED_LINES = 500
    export const MAX_MUTANTS = 400
    

    Lines 264 to 271 then fail a package, before a single test runs, in these words:

    `${packageEntry.id} has ${packageEntry.changedExecutableLines} changed executable lines (limit ${MAX_CHANGED_LINES}). ` +
        "Split the PR or obtain a maintainer-reviewed narrow exclusion.",
    

    What it counts, per package, from git merge-base to the head it is handed: executable changed lines, with comments and blank lines not counted, and the selector ranges those lines fall in (toRanges, line 187). Everything below was measured against main's tip f98fcf7d86534d730de936637c9cb35936461c00, tree 190a43e89bcd491a602f4dc4bdf8c814b6a9a186, and against this split's chain base a0d03a06a3aff42e2e4561e881911e48ff3bff42. Please quote these numbers against no other ground.

    Two copies of the instrument were used at every footing: the pristine one above, and a variant whose only difference is those two constants raised to 999999 (blob a421da9abdab77ddf8d1be8ed9b1af398d28f01d, 30,114 B). The variant prints what the pristine copy refuses, and its per package totals were required to equal the pristine copy's printed numbers. They did, at 62 of 63 priced constructions, with the priced branch checked out clean in a scratch worktree at all 63.

    Files that exceed 500 counted executable lines on their own

    head file counted executable lines selector ranges over the ceiling by
    PR 1915 ec3e02e56321 src/integrations/editor/DiffViewProvider.ts 724 139 224
    PR 1916 5f8474d16236 src/integrations/editor/DiffViewProvider.ts 724 139 224
    PR 1918 9b957e9b3ffc src/integrations/editor/DiffViewProvider.ts 508 101 8
    PR 2237 62454655e6b1 src/core/webview/ClineProvider.ts 557 170 57
    PR 2385 078cd7eb84c7 src/services/file-safety/safeWriteText.ts 527 150 27

    PR 1917 e5f696b9e184 has no such file. Its largest is src/core/tools/guardedWrite.ts at 401 lines over 48 ranges.

    No partition of files satisfies the ceiling

    Enumerating every subset of each head's own changed-file set - 510 subsets over 9 files for 1915, 8,190 over 13 for 1916, 65,534 over 16 for 1917, 131,072 over 17 for 1918, 30 over 5 for 2237, 6 over 3 for 2385 - no head has a file set that is itself under 500 counted lines and leaves the rest under 500, at both the current tip footing and the chain base footing.

    The smallest removal that would get the remainder under, priced

    Each row below is a construction rather than arithmetic: the file set was written onto a single parent branch on the footing named and run through the same instrument, and the half that stays was priced the same way.

    head files removed the removed half priced its headroom the half that stays at the tip the half that stays at the chain base
    1915 3 files: DiffViewProvider.ts, guardedWrite.ts, safeWriteText.ts 1,528 lines over 290 ranges minus 1,028 280 over 93, headroom 220 300 over 103, headroom 200
    1916 the same 3 files 1,528 over 290 minus 1,028 256 over 85, headroom 244 276 over 95, headroom 224
    1917 5 files: guardedWrite.ts, TaskHistoryStore.ts, DiffViewProvider.ts, safeWriteText.ts, safeWriteJson.ts 1,456 over 302 minus 956 294 over 73, headroom 206 314 over 83, headroom 186
    1918 5 files: DiffViewProvider.ts, guardedWrite.ts, safeWriteText.ts, ApplyPatchTool.ts, safeWriteJson.ts 1,621 over 326 minus 1,121 219 over 72, headroom 281 239 over 82, headroom 261
    2237 1 file: ClineProvider.ts 557 over 170 minus 57 49 over 22, headroom 451 49 over 22, headroom 451
    2385 1 file: safeWriteText.ts 527 over 150 minus 27 21 over 9, headroom 479 21 over 9, headroom 479

    So on four of these six heads the smallest set that could bring the remainder under the ceiling is itself over it by more than a thousand lines, 1,028, 1,028, 956 and 1,121, and on the other two by 57 and 27. A split cannot rescue any of the five heads that carry a file over the ceiling on its own.

    The one head where a split is arithmetically possible

    PR 1917 carries no over ceiling file and packs into four units. Exact bin packing over its 16 files, each unit built as its own branch and priced with both copies:

    unit files lines at the tip ranges headroom lines at the chain base headroom
    1 guardedWrite.ts, EditTool.ts, SearchReplaceTool.ts, EditFileTool.ts, jsonFileRecovery.ts, indentation-reader.ts, observationRegistry.ts 478 66 22 498 2
    2 TaskHistoryStore.ts, ClineProvider.ts, ReadFileTool.ts, ApplyDiffTool.ts, WriteToFileTool.ts 463 93 37 463 37
    3 DiffViewProvider.ts, ApplyPatchTool.ts 430 93 70 430 70
    4 safeWriteText.ts, safeWriteJson.ts 379 123 121 379 121

    Four is the floor and not a preference: three units hold 1,500 lines against 1,750. Unit 1 is the one that clears the chain base footing by only 2 lines, and the reason is src/core/task/observationRegistry.ts, which counts 22 lines against the chain base and 2 against the tip. Those 20 lines are main's own movement in that file and they make the unit larger, not smaller: it clears 498 despite them, and 2 lines is the whole margin on ground that is still moving.

    What an exclusion would have to cover, in mutants

    Three measured pairs. In each, the selector ranges are my own count from git diff through the pinned instrument copy and the mutant count is the platforms own tally from the CI report on this lane's disk, art-1910/, art-2383/ or leg100-u3-narrow-summary.json. The two sources are independent instruments over the same footing:

    footing selector ranges mutants what the run printed
    safeWriteText.ts file tally, base 73931fe8be25, head d5c31a1cc9d9 97 305 243 killed, 56 survived, 4 timed out, 2 uncovered; the package row that same CI run posted reads 347 lines, 318 valid, 255 killed, 4 timed out, 57 survived, 2 uncovered
    safeWriteText.ts file tally, base e487cd7b2a49, head 3edac64036eb 106 326 239 killed, 72 survived, 9 timed out, 6 uncovered; the package row reads 386 lines, 372 valid, 274 killed, 12 timed out, 78 survived, 8 uncovered
    DiffViewProvider.ts selectors narrowed, base efc22ed9f6f7, head 4ca8b9701509 46 of 141 163 valid 130 killed, 0 timed out, 28 survived, 5 uncovered, over 404 changed executable lines

    Those three pairs sit at 3.14, 3.08 and 3.54 mutants per selector range, and the third is the only one of the three measured on DiffViewProvider.ts selectors rather than on safeWriteText.ts. Read against that band, an exclusion covering DiffViewProvider.ts at 139 ranges would have to cover 427 to 493 mutants, at 101 ranges 311 to 358; ClineProvider.ts at 170 ranges would have to cover 523 to 602; safeWriteText.ts at 150 ranges 461 to 532. The mutant ceiling is 400.

    These are estimates from a measured rate at the three named footings, not measurements at these heads. No mutation run exists at any of the six heads above, because the line total throws before Stryker starts: 30 of the 63 priced constructions are exactly that throw. And an absence: no mutation report on this disk carries a per file mutant tally for DiffViewProvider.ts or ClineProvider.ts. The third pair is a package run whose selector list was narrowed to DiffViewProvider.ts, which is the closest thing to a file attribution on hand, and the 139 ranges for that file on 1915 and 1916 are priced with the whole package, not with a narrowed list.

    The asymmetry, in one sentence

    On this repository a changed line total over 500 fails the gate before anything runs, lines 264 to 271, while a completed run's valid mutant total over 400 is only an advisory row, lines 713 to 717, so an exclusion that clears the line ceiling on one of these files converts a failing gate into an advising red rather than a clean tally - and it buys even that only if the file's mutants leave the run as well, because a preflight mutant count over 400 throws too, lines 756 to 760.

    The ask

    Either these five named files receive a maintainer reviewed narrow exclusion, or the named file has to be refactored below the ceiling; this session will not write such a directive of its own, because the instrument rejects broad or unreasoned ones in these words at lines 178 to 182 - mutation exclusions must use "// Stryker disable next-line MutatorName: concrete reason"; broad or unreasoned exclusions are not allowed. - and because reading each of the five heads shows none of these files carries a directive today.

    Which figures are measurements and which are estimates. The line totals, selector ranges, per file tables, the priced removals and halves, the four 1917 unit prices and every headroom figure are measurements, taken with the pinned instrument copy named above at f98fcf7d86534d730de936637c9cb35936461c00 and at a0d03a06a3aff42e2e4561e881911e48ff3bff42. The mutant figures for the named files are estimates read off the three measured pairs above, at the footings named beside them. No figure here is a verdict about the code under test, and no mutant ran for this comment.

    Priced at 2026-11-13T02:32:24Z against f98fcf7d86534d730de936637c9cb35936461c00. Nothing was pushed, no split pull was opened, and the scratch branches these figures came from exist only on a lane machine.


    Wording correction, appended by the same hand that wrote the sentence it corrects. The table under "Files that exceed 500 counted executable lines on their own" names five rows across five heads and three distinct paths: src/integrations/editor/DiffViewProvider.ts at three of those heads (PR 1915 ec3e02e56321, PR 1916 5f8474d16236, PR 1918 9b957e9b3ffc), src/core/webview/ClineProvider.ts at PR 2237 62454655e6b1, and, as the third file, src/services/file-safety/safeWriteText.ts at PR 2385 078cd7eb84c7. The ask's first sentence should therefore have read five heads and three files where it reads these five named files, and no reader should have had to count the rows to find that out; the second half of that same sentence, which reads each of the five heads, was already correct as written. Nothing else here changes: the ask is still a maintainer reviewed narrow exclusion or a refactor below the ceiling for the write primitives inside those files, it is still addressed to the same people, and every other line of this comment is byte for byte what was posted on 2026-11-13. knip.json is not one of the three files this table names, and this correction does not ask for a change to it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions