Repository navigation
fix(vacuity): pair moved code git doesn't pair, only ever taking measure away (#1014) - #1068
jayden1711 wants to merge 13 commits into
Conversation
…ure away (#1014) Code moved in a way git doesn't pair as a rename or move read as added code, so a test that ran the moved code passed the gate for the whole PR (R1, R3, R4, M3, M4b, M5b, M5c, R3s, and a tested function moved into an existing file: all auto: true before this commit). The reader now measures each file a second way (movedCode): every top-level statement whose code lines are all added is paired with one whose code lines are all removed, from any app file at the base (a deleted one too, sent as `elsewhere`), by its code first, then by its declared name, and measured against it (codeRanges' `moved` mode: parentheses, commas and semicolons are no change there). A file counts only where it counts both ways, so the pairing can only take measure away: the M1/D1/C1 must-holds keep holding, and nothing that held before can merge. Lines swapped inside a function that stays are in no moved unit, so a reorder is still measured: the two round-9 "moved line inside a branch" tests that round 13's unfinished attempt broke still hold and merge. The todo limits become must-holds; M4b1, M5c and A6 are added, each with a merging control. Headers, quickstart and changelog name what is left: a statement renamed as it moved, or moved inside one that stays. Test (fails without): test/merge-vacuity-r12.test.ts, test/merge-vacuity-r13.test.ts Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
|
PASS 18b48ab Verdict: PASS. I found nothing that has to change. The fix does what #1014 asks, it can only hold more PRs than before, nothing loosens, and CI is green at this head. The engine's own weakening check holds the PR for the owner. That is expected here and is not a reason to fail it. I reviewed in a fresh detached worktree at the head. The diff is against the merge base Fail-before (measured)
Full vacuity set (measured)
The gate can't pass a PR it held before
Other mutants (measured)
The seven todo-to-must-hold conversions only tighten (measured, from the diff)
Nothing loosens (inferred, from reading the diff)
CI (measured): Weakening scan (measured): this is the engine's merge-policy check, not a CI job, so I called
It flags any changed test or guard line. I checked those lines (above): the test changes only tighten and the guard changes only add measuring. This PR is in the critical set and is owner-merged anyway, so the hold just sends it to the owner, as intended. Optional, not required
|
|
Second review (adversarial): FAIL 18b48ab The pairing never lets through a PR that main holds. But in two common shapes it silently falls back to the old vacuous measure, so a PR with an untested real change still merges. Those shapes aren't among the limits the docs name. Separately, the What I checked and ran (scratch detached worktree at the head, everything heavy through
Required changes
Optional
The scratch worktree is removed: the |
…hrough (#1014) From the adversarial review of 18b48ab, each measured there and here: - A division inside brackets (`Math.round(u / 2)`) turned the pairing off for the rest of its file: codeLines' `top` needed both readings, and the every-`/`-is-a-regex one swallows the `)`, so no later line started outside the brackets. `top` now comes from the first reading when it ends cleanly (P1a, P1b: auto true at 18b48ab). - A moved unit codeRanges couldn't place left its whole file measured as added code. It now throws UNPLACEABLE, as a hunk does (P2: a 300-line g rewritten untested into 280 lines beside a tested h). Must-holds P3m, P3d and P5 pin the both-ways rule in app code and through dist/ source maps: each fails under the mutant that drops one half of it. Test (fails without): test/merge-vacuity-r13.test.ts (P1a, P1b, P2) Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
|
Owner decision on the weakening scan, scoped to head 01163c9: "ok", not a weakening. The engine's
A new head needs a new scan and decision. |
|
FAIL 01163c9 Summary. Every claim in the PR body's "Adversarial review fixes" section checks out. But the new UNPLACEABLE throw makes ordinary, fully tested PRs hold that merge on main and at 18b48ab. Neither the PR body, the changelog nor the quickstart mentions this. A smaller change I tried in a scratch build fixes it and keeps P2 held. What I checked and ran
Mutants, applied to
Findings
The scratch worktree is removed. |
|
Second review (adversarial): FAIL 01163c9 The fixes for the previous review hold, but 7 of my 12 probes still merge with The probes are in Required changes
What I checked
The scratch worktree is removed. |
#1014) Round 3 of the moved-code pairing, after both reviews of 01163c9: - A unit paired by name that can't be aligned with its source is measured as added code, as git paired it; the file's other pairings stay. A unit with its source's code is never aligned: nothing in it changed. The UNPLACEABLE throw from movedCode is gone (FH1, FH2 must merge; P2 holds as ran none; P2x). - A top-level statement runs until its code has ended, across a line a formatter wrapped after an operator (E1, E1b, E1f, E1s). - A closing line git keeps between a moved unit and the code written in its place doesn't stop the pairing, at either end (E2, E2d). - Declared names also read from exports/module.exports assignments and TypeScript abstract classes, enums and namespaces (E3, E3m, E3a, E3n). - Statement starts come from their own lexer reading (a regular expression after a condition's `)`, a division after a postfix increment), else the every-slash-a-regex reading, whichever balances its brackets; codeLines' mask is unchanged (E4, E4b, E5, E7). A file no reading balances pairs nothing, as before #1014: a todo names it. Docs, changelog and comments name what still reads as added code. Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
|
Owner decision on the weakening scan, scoped to head e19bdc3: "ok", not a weakening. The engine's
A new head needs a new scan and decision. |
|
FAIL e19bdc3 Summary. Every round-3 claim I re-checked holds. But round 3 opens a new way for an untested change to merge, and the docs don't name it. The shape is a TypeScript file written without semicolons, where a line ending in What I checked and ran All of this ran in fresh detached worktrees (r18e at the head, r18e-b as a scratch copy), built with
Mutants (measured, applied to All 10 of the builder's mutants I re-ran are killed:
R6 needed its text corrected for the compiled file ( All 4 of my own mutants survive (63/63 pass with each):
O1, O2 and O4 only change where measure is taken away, so the both-ways rule keeps them from merging anything main holds (inferred). O3 matters only in a file that has both an identical-code unit and an unplaceable name-paired unit, and no test has that combination. Findings
My probe file is at |
|
Second review (adversarial): FAIL e19bdc3 This head makes an ordinary tested PR worse than main (measured). Take a one-line top-level function edited in place, with no move at all, where the fix only adds parentheses ( The probes are in Required changes
Optional (outside the stated scope, or rare; main merges these too; measured)
Held correctly at the head (main merges them all; measured)
Also measured: Z-F2 (a tested What I checked
|
…ound 4) - A unit is never paired with the old text git already paired it with, so a statement edited in place is measured as git measured it. - Only formatting is no change in moved code: semicolons, a comma before a closing bracket, and parentheses that can't change meaning. Parentheses that change precedence count as code. - A column-0 export or import line always starts a statement; so does a line starting with a keyword no expression continues with. - Same-named pairs are taken best-aligned first, so a same-named unit never takes another's source by path order. A source may keep its header where git keeps it for the code rewritten in its place, provided one of its lines was removed. - Docs and limits updated: X1, and unbalanced files start statements only on export or import lines. Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
|
Owner decision on the weakening scan, scoped to head d76d96f: "ok", not a weakening. The engine's
A new head needs a new scan and decision. |
|
FAIL d76d96f Summary. Every claim in round 4 that I re-checked holds, and CI at this head is complete and green. But I found a new false hold: a shape main merges and this head holds. The docs claim it can't happen. Two smaller test gaps also need fixing. What I checked and ran I worked in fresh detached worktrees at the head, at e19bdc3 and at main (e91629f), built each with
Findings
My probe file is |
|
Second review (adversarial): FAIL d76d96f I'm failing this head for two reasons. First, one shape is worse than main: a tested one-line edit in place now holds, where main merges it. Second, the docs say redundant parentheses in moved code are no change, but they still count, so an untested change merges. Fail-before reproduces, the suites pass and CI is green at this head. My 28 probes of ordinary in-place edits all give the same result at the head and at main. The full verdict is in Required changes
Optional
What I checked
|
- A statement git paired in place with a removed statement of its own name pairs with nothing, so a tested one-line edit is measured as git measured it even when the PR removes a copy of its new text elsewhere (G1, G1b, D1, D1d: must merge). - Pin the parenthesis positions quiet treats as formatting (G2, G2e, G5, B16b must merge; Q-Pq, Q-Pc must hold) and the template guard on the column-0 anchor (Z-T3). - The unbalanced-file limit's todo imports its CommonJS module whole, so it reaches the measurement it names; a balanced control holds. - Docs name exactly which parentheses are formatting and list the rest as a limit. Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
|
Second review (adversarial): FAIL 7f79694 I'm failing this head for two reasons. First, round 5 makes one documented-held shape merge: a function moved into a file in place of a stale function of the same name (bar b, and the docs claim c). It held at d76d96f. Second, the changelog's "so parentheses that change precedence count" is false for parentheses after Bar applied: the owner's sibling-PR bar. FAIL only on (a) an overclaim in the docs, changelog or PR body, (b) a documented-held shape that merges, or (c) a clear false hold on an ordinary shape main merges. New surviving mutants and gaps outside the docs' claims are follow-ups. Required
What I ranAll of this ran in detached worktrees at head, d76d96f and main, with TMPDIR set to
Follow-ups (not blocking)
Probes, the mutant script and logs are in |
|
FAIL 7f79694 Final check R18i: PR #1068 at head
|
…kept, keep precedence parentheses after ?? (#1014) A moved function that git pairs in place with a stale same-named one it replaces (N5, N6) no longer skips the move pairing: the in-place skip now needs a code-character similarity of at least 0.8, and the removals git measured inside a placed unit go with it. Parentheses after ?? whose content holds a lower-precedence operator count as code (PQ2, PQ3). W1, W2 and a large in-place rewrite to a removed copy's text are pinned as limit todos and documented. Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
|
FAIL 51538c8 Final check R18k: PR #1068 at head
|
| Todo | Asserts | Head | Main | What it is |
|---|---|---|---|---|
unbalanced-file exports.g |
hold | merges | merges | limit main shares |
| X1 | hold | merges | merges | limit main shares |
| W1 | hold | merges | merges | limit main shares |
| W2 | hold | merges | merges | limit main shares |
rewritten in place past EDITED_IN_PLACE |
merge | holds ("ran none", src/a.js, src/b.js) |
merges | new hold, fails closed |
None of the five relaxes a check.
The new hold is a rare shape, not an ordinary one (measured probes, inferred judgement). It fires only when two things are both true:
- A statement whose code lines are all new is rewritten in place below 0.8 similarity.
- The same PR removes another copy elsewhere that matches its new text exactly, ignoring formatting.
The probes at head:
- Merge, as at main:
- O1: a one-line rewrite in place, tested.
- O2: O1, with a deleted file holding an unrelated
f. - O3: a multi-line rewrite whose header also changed.
- O4: O3, with an unrelated same-named
fdeleted. - L1: the limit shape with a multi-line
fwhose header git keeps. - L2: the limit shape where the copy differs in tested code.
- L3: the limit shape with the copy kept, not removed.
- Holds: only L0, the one-line exact-copy de-duplication.
That shape can't be told apart from N5, a move over a stale same-named function, and it matches the PR's stated change that a PR which only moves code holds.
What I ran
Labels: measured unless marked inferred.
- PR head:
51538c8bat the start and the end. - Merge base:
32cd15e5. The API'sbase.shareads04f83b51. - Build and
npm run typecheck: clean. - Vacuity suites (
merge-vacuity-*,vacuity,merge-policy-vacuity): 369 tests, 355 pass, 0 fail, 14 todo. This matches the PR body. - Other
merge-policy*suites: 91/91 pass. - Fail-before: I ran the head's r11-align, r12 and r13 tests over each commit's source.
- Mutants of compiled
vacuity.js: all killed, as claimed.
| Mutant | Killed by |
|---|---|
| threshold 2/3 | N5 |
| threshold 0.96 | G1, G1b, D1, D1d, U1 |
loose never set |
PQ2, PQ3 |
| removals not dropped | N6 |
- Rule statements: read against
quietandmovedCode.- The
??rule and the opener and closer lists match the code exactly (inferred). p === '?'can only qualify after??, because a ternary's?needs a:before the close (inferred).- Probe P1 (a lone
?? (u.b)dropped) holds as formatting. - Probe P2 (
?? (u.b == null)dropped) counts as code, as documented. - The in-place rule matches the code except for R1.
- The
- PR body similarity figures (0.95, ≥ 0.96, 0.67, 0.43): consistent with the mutant thresholds. I didn't compute them myself (inferred).
- Merge onto main:
git merge-tree --write-tree cc34fd79 51538c8bis clean (tree575d0b33). On that tree,adversarial.testandmerge-door.testgive 242 tests, 218 pass, 0 fail, 24 todo. - CI at head: every check is complete, 20 success and 7 skipped (bootstrap and the real-systemd jobs). Nothing is failing or pending.
- Sign-off: all 6 commits are signed off.
- Not re-run locally:
check:denylistandpush-gate. CI's denylist and push-gate jobs passed.
Optional follow-ups
- Changelog scope: its new
Limit:sentence says "a statement rewritten in place". It applies only when every code line is new (L1 merges). That overstates when the hold happens, not when code merges, so it's harmless. - Already-disclosed holds: PQ1, PQ1r and RA1 still hold at head where main merges. Track them as the issues the body promises.
My probes are in /var/tmp/r18k-9sYd/zz-r18k-probes.test.ts, with probes-*.txt, fb-*.tap, mut-*/out.tap, vac-head.tap and adv.tap beside them. The detached worktree /var/tmp/wl-coord/rev/r18k is left in place, with an untracked node_modules symlink and probe file. Nothing is running, and I made no commits, pushes or GitHub posts.
|
Second review (adversarial): FAIL 51538c8 The Bar applied: the owner's bar for this PR. FAIL only on (a) a docs, changelog or PR-body sentence that claims more than a case proves, (b) a shape the docs say is held that merges, (c) a clear false hold on an ordinary shape main merges, or (d) a shape that held at d76d96f or 7f79694, is documented as held, and now merges. Required
The weakening flagsNone of them relaxes a check.
What I ranHead, main cc34fd7, d76d96f and 7f79694 each had their own detached worktree, built with
Follow-ups (not blocking)
Probes and logs are in
I made no commits, pushes or posts, and nothing is left running. |
…1014) The in-place check aligned against a PR-wide cell budget and read both a spent budget and an alignment too large to make as kept, so one big in-place change anywhere earlier in the PR (BUDf, BUD120, B3), or a big moved function over a stale one (BL1wb), skipped the move pairing and merged. Each pair now aligns on its own, bounded as codeRanges bounds each hunk, and one it can't align pairs like any moved unit. D1p pins the per-pair choice; N5u is pinned as a limit todo, and the docs state the fallback and when the rewrite limit applies. Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
|
Independent final check (R18m), posted by the coordinator. FAIL ce7be5f Final check R18m: PR #1068 at head
|
| Probe | Head | 51538c8 | 7f79694 | d76d96f | Main d5650da |
|---|---|---|---|---|---|
| n = 0, 1, 2, 3 | holds | holds | holds | holds | merges |
| n = 5, 8 | merges | merges | merges | merges | merges |
| ZN4spent, n = 5 | merges | merges | merges | merges | merges |
- Causal mutant: with
MOVE_PAIR_CELLS = Infinity, every variant holds. r11-align, r12 and r13 still pass under it (143 pass, 0 fail), so no test pins this. - Not a regression: it is the same at every head since d76d96f, and main merges all of these. The budget is also spent cheaply: it counts the full key product, while the near-identical pairs actually align in only a few cells.
- Either fix is enough (inferred):
- name the fallback as a limit in the quickstart, the changelog and both headers, and narrow "never takes another's source";
- or make it fail closed (throw so the PR waits, or score each pair on its own as
edited()now does, with the reader's 120 s limit as the backstop), and pin ZN1spent n=5 as a must-hold.
Weakening flags (owner-delegated question for this head)
weakeningOf(base 32cd15e5, head ce7be5fa, tip d5650da8), run with main's scanner, reports the same three flags (measured). None of them relaxes a check.
- Changed test lines in
test/merge-vacuity-r12.test.ts: a strengthening.- R1, R3 and R4 go from
limit:todos to must-holds with identical assertions (measured, diff). - All three pass at head and fail with main's source (measured).
- R1, R3 and R4 go from
- Changed guard lines in
src/coordinator/merge-flow.ts: a strengthening.- The file only adds
elsewhere: the removed line spans of app files the PR doesn't measure (measured, diff). - Only
movedCodereads it.measureTouchedcounts a file only where bothcodeOfandmovedOfcount it, so pairing can only take measure away (inferred, from reading the code).
- The file only adds
- Added
limit:todos intest/merge-vacuity-r13.test.ts. Head's r13 todos, run against head's source and against main's (measured):
| Todo | Asserts | Head | Main | What it is |
|---|---|---|---|---|
unbalanced-file exports.g |
hold | merges | merges | limit main shares |
| X1 | hold | merges | merges | limit main shares |
| W1 | hold | merges | merges | limit main shares |
| W2 | hold | merges | merges | limit main shares |
| N5u (new this round) | hold | merges | merges | limit main shares |
rewritten in place past EDITED_IN_PLACE |
merge | holds ("ran none", src/a.js, src/b.js) |
merges | a stricter hold, which fails closed |
What I ran
Labels: measured unless marked inferred.
- PR head:
ce7be5faat the start and at the end. Main isd5650da8, and the merge base is32cd15e5. - Build and
npm run typecheck: clean. - Vacuity suites (
merge-vacuity-*,vacuity,merge-policy-vacuity): 378 tests, 363 pass, 0 fail, 15 todo. This matches the PR body. merge-policy*suites: 104/104 pass.- Fail-before: head's r11-align, r12 and r13 tests over 51538c8's compiled reader give 149 tests, 139 pass, 4 fail: exactly BUDf, BUD120, B3 and BL1wb. D1p and BIGIN pass both there and at head.
- The PR's mutants:
- "too large to align counts as kept" is killed by BL1wb only.
- "PR-wide budget that fails closed" is killed by D1p only.
- The
inOneequivalence argument (inferred, from readingcodeRanges,ranOn,innerAtandranSegments): sound.- A removal's need counts only when both of its sides are in ran ranges outside the module's top level, and share an innermost V8 range in every process.
- A need that straddles a unit boundary has its sides in two different top-level statements, so it can never count. Dropping it (
some) or keeping it (every) gives the same verdict. - One caveat: this relies on
topUnitscutting at real top-level statements, which is true for balanced readings.
- Per-pair cost: I called
measureToucheddirectly on N same-named functions, each rewritten in place, with about 3.97M cells per pair (just underALIGN_CELLS):
| Pairs | File size | Head | 51538c8 |
|---|---|---|---|
| 200 | 0.58 MB | 1.5 s | 0.97 s |
| 1,000 | 2.9 MB | 8.4 s | 7.6 s |
| 2,000 | 5.9 MB | 26.6 s | 28.6 s |
- Per pair, the cost is about 10 ms at the limit. Pairs just over the limit return null at once, which is cheaper.
- So it stays well under the reader's 120 s limit, and past that limit the read errors and the PR waits (inferred, from
readTouchedInChild). The PR body's "costs about what the module already spends per hunk" is consistent with this. - Other budgets in the module:
MOVE_PAIR_CELLSin the scoring loop fails open (R1).- The source-map limits stop at the map files; past the source count it throws, so it holds.
- Each
alignCharsnull incodeRangeseither holds (UNPLACEABLE) or, for moved units, is measured as git paired it, which the both-ways rule keeps from merging anything (inferred).
- Docs:
- The rule's wording matches the code: the 0.8 similarity, a pair too large to align never counted as edited in place, and "about 2,000 code characters a side" (√4M, of the middle).
- N5u is named as a limit in the quickstart, the changelog and both headers.
- The narrowed rewrite-limit sentence matches L1 from R18k.
- The exception is R1.
- I did not re-run the PR body's "Head vs 51538c8: no other difference" probe set.
- Merge onto main:
git merge-tree --write-tree d5650da8 ce7be5fais clean (tree78c9b9de). I exported that tree, built it, and ran:adversarial/adversarial,adversarial/merge-doorandmerge-policy-tip-merged-in: 255 tests, 231 pass, 0 fail, 24 todo;- r12, r13 and tip-merged-in: 0 fail.
- CI at head: every check is complete, 20 success and 7 skipped. Nothing is failing or pending.
- Sign-off: all 7 commits are signed off.
- Not re-run locally:
check:denylistandpush-gate.
Optional follow-ups
- A test that pins the scoring budget's behaviour, whichever fix is taken.
- The scoring budget counts full key products, not the cells actually aligned. If the budget stays, counting the middle (after the common start and end) would make it far harder to spend.
- Already-disclosed holds at head where main merges (PQ1, PQ1r, RA1, F4) and the known limits (W1, W2, N5u, the B7 and B8 parenthesis shapes) are unchanged.
Every worktree I added is removed, and nothing is running. I made no commits, pushes or GitHub posts.
|
Independent adversarial review (R18n), posted by the coordinator. Second review (adversarial): FAIL ce7be5f Bar (owner decision, applied to this PR): FAIL only if one of these holds:
Round 7's own fix is sound. One fail-open path is left in the same pairing code: the last budget shared across the whole PR. Required1. The by-name scoring budget lets a decoy take the source, so Z-N1 and Z-N4 merge (bars a and b; measured).
Weakening flags (owner-delegated question)None of them relaxes a check.
What I ran (measured unless marked)
Follow-ups (not blocking)
|
The by-name scoring budget was shared across the PR: once big contested pairs elsewhere spent it, every score tied and candidates paired in path order, so a same-named unit could take another's source (Z-N1, Z-N4). Each contested pair is now compared on its own: by character within the alignment bound, else by its lines' text; when even the lines are too many, the coverage read fails and the PR waits. Counting contested pairs with a map also removes the quadratic filter over candidates. Tests: ZN1spent, ZN1B, ZN4B and ZN1L must hold; ZN1Bs, ZN1Bz and M3B stay holds; D1L (a large in-place edit) must merge. Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
|
Independent adversarial review (R68p), posted by the coordinator. VERDICT: FAIL @35d11f5610d7771779e9acf4a6a2b85233f2ad8a (adversarial) RequiredR1. The line fallback scores raw lines, so formatting the docs call "no change" lets a small decoy take the source. ZN1L plus Q-S or a comment merges (bars a and b; measured).
Checked, no finding
Follow-ups (not blocking)
What I ran
|
|
Independent final check (R68o), posted by the coordinator. VERDICT: FAIL @35d11f5610d7771779e9acf4a6a2b85233f2ad8a (final check) Final check R68o: PR #1068, round 8Round 8 fixes what R18m and R18n found: ZN1spent, ZN1B and ZN4B hold, CI is green, and fail-before is exact. One gap is left. The new line fallback counts comment text, so a decoy can still take another statement's source. That makes the changelog's unconditional claim false again. RequiredR1. When the by-line score is used, a decoy that keeps the source's comments takes the source (bars a and b; measured).
Checked and true (measured)
Follow-ups
Cleanup: my worktree and its temporary files are removed. I made no GitHub writes. |
…nes (#1014) The by-line score for a contested same-named pair read raw lines, so dropped semicolons or comments kept by a decoy let a two-line decoy take the moved statement's source (SEMI, SEMI-z, SEMI-half, CMT, ZN1L-cmt). Score each line by its code characters, as `key` reads them. Every hunk is now also aligned code against code and comment against comment, not only line pairs whose code matches: before, comments a statement dropped could stand in for code its untaken branch changed (CM1 to CM4, which also fail on main; ZN1L-cmt needs this too). Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
…nk (#1014) CM5 is CM3 with a comment on every line of g, the edited line's naming its new arm: too large to align whole, its lines are paired by code and the edited pair aligned on its own. Aligned without the code/comment tags, as 35d11f5 aligned a pair whose code differs, the comment stands in for the edited code and a test that runs g merges the PR. No test caught that half of the previous commit before. Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
|
Independent final check (R68q), posted by the coordinator. VERDICT: PASS @08b5e159cfab7b112a18088e80f35a8c63e210d0 (final check) Final check R68q: PR #1068, round 9Round 9 fixes both round-8 failures (R68o ZN1L-cmt, R68p SEMI/CMT). Each must-hold case is pinned, fails on 35d11f5 and passes at head. Required CI is green on the exact head. Findings (all measured unless labelled)
Not re-runThe full 23-file vacuity set (404 tests), Follow-ups (not blocking, carried over)
Worktrees and TMPDIR removed. No GitHub writes. |
…aks never decide (#1014) Too large to align by character, a contested same-named pair was scored by its line rows, so a moved g re-wrapped on half or more of its lines counted every wrapped line as changed and a two-line decoy g took its source (R68r: WRAP-1of2, WRAP-2of3, WRAP-3of4, before and after the decoy in path order). Score the tokens of `key` instead (word runs and punctuation runs, each weighing its characters): `key` holds no whitespace, so a line break never changes them. ZN4L-S, ZN4L-U and ZN4L-N pin each side's unkept tokens and their weight. The quickstart and changelog name a statement re-wrapped on every line, or with pairs of lines joined, under the too-far-to-align limit. Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
|
Independent adversarial review (R68r), posted by the coordinator. VERDICT: FAIL @08b5e159cfab7b112a18088e80f35a8c63e210d0 (adversarial) RequiredR1. Line breaks still decide the by-line score: a re-wrapped moved
Follow-ups
Checked, no finding (measured)
What I ran
|
|
Independent final check (R68s), posted by the coordinator. VERDICT: PASS @4869afd27f8b72a1ce65ddee4e65b7c335af8321 (final check) Head confirmed at start and end ( Findings
Weakening scan flagsRan
What I ranA detached worktree at Follow-ups (not blocking)
|
|
Independent adversarial review (R68t), posted by the coordinator. VERDICT: FAIL @4869afd27f8b72a1ce65ddee4e65b7c335af8321 (adversarial) RequiredR1. A two-line decoy still takes a large moved
Follow-ups (measured)
Checked, no finding (measured)
Weakening scan flags
No real weakening. What I ran |
… a moved pair (#1014) Scored by token, every edited name cost its full length on both sides, so a 105-line g moved with every word of 100 lines edited inside a block its test never enters scored worse than a two-line decoy g, which took its source, and the PR merged (R68t: UB100, UB100z). Each run of tokens between kept ones is now aligned by character and costs the characters it doesn't keep (its full length when too large to align). ZN1T pins the fail-closed path: two same-named statements too large to tell apart by token make the PR wait, even with the change tested. ZN4L-P pins punctuation tokens, and ZN4L-S now drops lines only, so a source-side-only score loses it. Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
|
Independent final check (R68u), posted by the coordinator. VERDICT: PASS @29bb7f6c865b8bdef4a15753f2b56673ee1193c2 (final check) Head confirmed at start and end ( Findings
Ruling on ORD200 / TC120t / BND166-180: accepted fail-closed limit, not (c)
Weakening scan flags
The ZN4L-S rebuild changes inputs, not assertions, and the source-side mutant shows it got stronger. No real weakening. Follow-ups
What I ranDetached worktree |
|
Independent adversarial review (R68v), posted by the coordinator. VERDICT: FAIL @29bb7f6c865b8bdef4a15753f2b56673ee1193c2 (adversarial) RequiredR1. A two-line decoy still takes a fully edited large moved
Ruling on the disclosed behaviour change (ORD200, TC120t, BND166–180)These are an accepted fail-closed limit, not (c).
Mutants (r11-align, r12, r13 compiled tests; 187 pass at head;
|
… the PR wait (#1014) A contested same-named pair scored by token weighed a run of edited tokens past ALIGN_CELLS by its full length, so a two-line decoy took a fully edited large moved statement's source and the PR merged (BR220). Such a run now throws CoverageUnreadable, as a too-large token alignment does: the PR waits with 'too large to tell'. BR220, BR220z, BR300 and BR220t must hold with that reason; BR220c is the no-decoy control. LNG100 and LNG100t pin that each short run is aligned on its own. Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
What and why
Closes #1014. Code a PR moved in a way git doesn't pair as a rename or move read as added code, so a test that ran the moved code passed the vacuity gate for the whole PR, even when the real change beside it was untested (R1, R3, R4, M3, M4b, M5b, M5c, R3s, and a tested function moved into an existing app file).
The reader now measures each changed app file a second way (
movedCodeinsrc/vacuity.ts):elsewhere.&&inmeasureTouched).The two older tests that broke round 13's unfinished attempt ("a moved line, inside a branch the test never takes" and its control) were understood first. That attempt read two lines swapped inside a function as a move and left nothing to measure. A reorder is a real change, so here a statement moved inside one that stays is in no moved unit and is measured as before. Both tests pass (measured).
Behaviour change: a PR that only moves code (unpaired) now holds with "ran none" instead of merging when a test runs the moved code, as a rename git pairs already holds (inferred).
How it was verified
git checkoutof the three source files, fix kept as a patch), rebuilt,node --import ./dist/test/isolate.js --test dist/test/merge-vacuity-r12.test.js dist/test/merge-vacuity-r13.test.js: 39 tests, 29 pass, 10 fail. Each fails withactual [true, []]: R1, R3, R4, M3, M4b, M4b1, M5b, M5c, A6, R3s.merge-vacuity-*,vacuityandmerge-policy-vacuitytest: 280 tests, 271 pass, 0 fail, 9 todo (the existing V8-limit todos, unchanged).npm run typecheckclean.npm run check:denylist1645 files clean.node scripts/push-gate.mjs --range origin/main..HEADclean. CI-parity lints (change-files-renames, merge-policy, changelog, owner-terminal-removed, changelog-fragments, brand, boundaries, engine-guard-locks, docs-guardrails, merge-policy-weakening and others) 193/193 pass.todolimits inmerge-vacuity-r12/-r13become must-holds. M4b1 (a move past one 6-line function), M5c and A6 are added, each with a merging control.This is the merge policy, so it is in the critical set: it needs independent and adversarial head-pinned reviews.
What remains
dist/) applies the same both-ways rule but has no moved-code test (inferred).Checklist
Adversarial review fixes (head 01163c9)
R18b's findings, as one new commit on top of 18b48ab:
codeLines'topcame from both lexer readings; the every-/-is-a-regex reading swallows the)ofMath.round(u / 2), so no later line started at the top level.topnow comes from the first reading when it ends cleanly. P1a (division in the file g left) and P1b (in the file g moved to) are must-holds: both wereauto: trueat 18b48ab (measured); theu * 2control holds.movedCodenow throwsUNPLACEABLE, as an unplaceable hunk does, instead of measuring the file as added code. P2 (a 300-line g moved and rewritten untested into 280 lines, beside a tested unchanged h) is a must-hold:auto: trueat 18b48ab (measured); its small-rewrite control holds as "ran none".dist/check's unpaired half fails P3d;Correction: the earlier "What remains" bullet "No test fails if the both-ways rule is removed" was wrong. The existing L1 control in
merge-vacuity-r11-alignalready caught the non-dist/mutant (measured), and P3m now targets it directly.Verified at 01163c9 (measured): all vacuity tests 288, 279 pass, 0 fail, 9 todo (existing V8 limits); the CI-parity set with merge-policy-weakening 193/193; typecheck clean;
check:denylist1645 files clean;push-gate --range origin/main..HEADclean (2 commits).Still open, not blocking (from R18b):
Round 3 fixes (head e19bdc3)
Both reviews of 01163c9 failed it. Each claim is labelled: measured (from a command or CI output, named) or inferred (reasoned, not run).
What changed
movedCodeis gone.=>,+or=. A new statement starts only after;or}, or on a declaration line.exports.x =,module.exports.x =, and TypeScript'sabstract class,enumandnamespace. Each form is pinned end to end exceptenum, which the gate can't measure differently: an enum's code runs only as the module loads, so a probe holds both at main and at this head (measured)./after anif/for/while/withcondition for a regular expression, and one after a postfix++/--for a division./-a-regex reading is used.codeLines' mask, which U measures, is unchanged.Limits, all reading as added code as on main
{ todo }test, and that shape merges both at this head and at main's versions of the four files this PR changes (measured).These are named in docs/quickstart.md, the changelog fragment, and the headers of
src/merge-policy-vacuity.tsandsrc/vacuity.ts.Evidence
auto: true). P2x holds with UNPLACEABLE. E1s passes there and guards the declaration rule (mutant R7).dist/src/vacuity.js(measured): all 16 are killed, one per new rule plus the earlier A, B and C.merge-vacuity-*plusvacuityandmerge-policy-vacuitygive 309 tests, 299 pass, 0 fail, 10 todo. The CI-parity set, includingmerge-policy-weakening, passes 193/193.npm run typecheckandcheck:denylistare clean.push-gate --range origin/main..HEADis clean.Round 4 fixes (head d76d96f)
False holds (measured: Z-F1, Z-F1b, Z-F6, Z-F7, Z-F9, Z-F10, Z-F11 and FH3 merge, as on main; the Z-F8 control merges).
=,=>,(,[,,,?,:,return,throw). Parentheses that change precedence count as code.Statement starts (measured: X2, X2b, X3, Z-A1 to Z-A4, Z-A3c, Z-A4c, Z-B1, Z-B2 and E4c hold; E1f still holds; the Z-A1c and Z-B1c controls hold).
exportor staticimportline always starts a statement, at any bracket depth the lexer reports.export,const,let,var,enum,interface,declare,abstract,namespaceor a staticimportalso starts one, whatever the line before ends with.Name steal (measured: Z-N1 to Z-N4 hold; the Z-N1z control holds).
Probes (measured, both reviewers' files at head / e19bdc3 / main).
Tests and mutants (measured).
exportanchor a statement. It is harmless (inferred): such a line occurs only inside a TypeScript namespace, where anchoring only splits the block into its members, and the both-ways rule keeps it from merging anything main holds. All of r11-align, r12 and r13 pass under it (measured).Limits (listed in quickstart, the changelog and the merge-policy-vacuity header).
exportorimportline (a todo; measured).Checks (measured).
node scripts/push-gate.mjs --range origin/main..HEAD: clean.merge-policy-weakeningtest file that doesn't exist.Round 5 fixes (head 7f79694)
In-place false hold (measured: G1, G1b, D1 and D1d merge, as on main; the G1c and D1m controls merge).
Parentheses: the docs now say exactly what the code does (measured).
,or;of its own that doesn't start with{, opened right after an assignment's=,=>,return,throw,(,[,,,?or:, and closed right before;,,,),],}or the end.exportanchor.Unbalanced-file limit (measured).
Docs.
merge-policy-vacuity.tsheader and thevacuity.tsheader name the formatting positions and the parenthesis limit.Probes (measured, both reviewers' files at head and at main).
;. Both also count as no change in place on main, and the reviewer didn't require them.Tests, fail-before and mutants (measured).
{guard, the??position, the:position, and the template guard.Checks (measured).
merge-vacuity-*,vacuityandmerge-policy-vacuity: 349 pass, 0 fail, 11 todo.merge-policy-weakening: 428 pass, 0 fail, 10 todo.node scripts/push-gate.mjs --range origin/main..HEAD: clean.Round 6 fixes (head 51538c8)
1. In-place skip narrowed (N5). A unit git pairs in a hunk with a removed statement of its own name (or, unnamed, an unnamed one) counts as edited in place only when the code characters both keep reach a similarity (2 × kept / both) of at least 0.8 (
EDITED_IN_PLACE). Otherwise it took that statement's place and pairs like any moved unit. Removals git measured inside a placed unit are dropped with it (N6). Measured similarities: G1/D1/U1 0.95, Z-F6/F7/F10 ≥ 0.96, N5 0.67, N6 0.43.merge-vacuity-r13,-r12)limit:todo that fails on the verdict (measured), documented in the quickstart, the changelog fragment and both headers:;added in place must merge (inferred).2.
??precedence (PQ2, PQ3). Parentheses after??are formatting only when their content holds no?,:,|,&or=outside brackets. The other position, the arrow function's one parameter, and the list of openers (=,=>,return,throw,(,[,,,:) and closers (;,,,),],}, end) are unchanged and stated exactly in the docs. PQ2 and PQ3 must merge; Q-Pq and Q-Pc still hold. (measured)Fail-before (measured, src reverted through a patch): at 7f79694, N5, N6, PQ2 and PQ3 fail. At main e91629f, N5, N5x and N6 fail; PQ2 and PQ3 pass there because main pairs no moves. Everything passes at head.
Mutants (measured, r11-align + r13 + r12), all killed:
loosenever set → PQ2, PQ3;??ignoresloose→ PQ2, PQ3;edited()always true → N5, N6;edited()always false → G1, G1b, D1, D1d, U1; threshold 2/3 → N5; threshold 0.96 → G1, G1b, D1, D1d, U1; removals not dropped → N6.Probes at head vs main (measured; R18g/R18h head verdicts identical to round-5 head):
Checks (measured): vacuity set 355 pass / 0 fail / 14 todo; CI-parity lints plus every test importing the weakening module (excluding
desktop-removed) 449 / 0 / 10 todo;npm run typecheckclean;check:denylist1645 files clean;push-gate --range origin/main..HEAD6 commits, 1 tip clean.Round 7 fixes (head ce7be5f)
1.
edited()fails closed (R18k B3; R18l BUDf, BUD120, BUD160, BL1wb, BL2wb). Each same-named pair git puts in one hunk is now aligned on its own (alignChars, bounded byALIGN_CELLS). The PR-widenearCellsbudget is gone. A pair too large to align is not edited in place: it pairs like any moved unit, which can only take measure away.codeRangesaligns every git hunk under the same per-call bound and no PR-wide budget, so this costs about what the module already spends per hunk. A PR-wide budget that failed closed would turn D1 into a false hold after any big in-place edit earlier in the PR. D1p pins that.2. Docs. The quickstart, the changelog fragment and both headers state the rule: a same-named (or both-unnamed) git partner, a code-character similarity of at least 0.8, and a pair too large to align (about 2,000 code characters a side, each pair on its own) never counted as edited in place.
limit:todo that fails on the verdict (measured): git keeps the staleg's identical first line, so the movedgis never wholly added. It merges at head, 51538c8 and main. The changelog example now says "every code line of it replaced".3. R18l's
inOnesome-vs-every mutant is equivalent (inferred).ranSegmentsleaves out the module's top level, andranOncounts a removal only where both sides ran. A removal straddling a moved unit's boundary has one side at a top-level statement start, so it can never count. Probes ST7 (a removal right before a movedg) and ST7c (the same in place) hold under botheveryandsome(measured). No test added.Probes (measured; R18g, R18h, R18j, R18k, R18l at head, 51538c8 and main cc34fd7):
g(u)with the same first line. These are follow-ups, not chased.Checks (measured): vacuity set 363 pass / 0 fail / 15 todo; CI-parity lints plus every test importing the weakening module (excluding
desktop-removed) 449 / 0 / 10 todo;npm run typecheckclean;check:denylist1645 files clean;push-gate --range origin/main..HEAD7 commits, 1 tip clean.Round 8 fixes (head 35d11f5)
1. By-name scoring fails closed (R18m ZN1spent; R18n ZN1B, ZN4B). The PR-wide
MOVE_PAIR_CELLSbudget is gone. Each same-named pair a unit or a source shares with another candidate is now scored on its own: by character (alignChars, bounded byALIGN_CELLS), or, too large for that, by its lines' whitespace-free text. When even the lines are too many, the reader throwsCoverageUnreadableand the PR waits. It never falls back to path order.ALIGN_CELLS, asedited()andcodeRangesalready are. Total work is backstopped by the 120 s reader timeout, which fails closed.gwhose decoy is too large to align by character). Controls (hold, as at ce7be5f): ZN1Bs, ZN1Bz, M3B. Must merge: D1L (a ~1,300-character line edited in place, about 1.7M cells).edited()→ D1L. All killed. Not killed: the line score also counting kept lines (S4), which is informational. The by-name-budget-removed mutant from R18m/R18n is moot because the budget is gone.2. PERF2 (measured, PERF2 probe on this machine). Contested pairs are now counted with a map, not
named.filterper candidate. Q=150: 318 ms at head, 2,306 ms at ce7be5f, 273 ms at main. Q=399: 513 ms at head, 71,290 ms at ce7be5f, 273 ms at main. All merge, as wanted.3. Docs. The quickstart's in-place sentence now says "a removed statement of the same name (or, unnamed, an unnamed one)". The quickstart, the changelog fragment and both headers say that each same-named pair is compared on its own, by character or by line, and that two too large to compare make the PR wait.
Probes (measured; R18m, R18n ZN set, R18g, R18h, R18j, R18k, R18l at head, ce7be5f and main cc34fd7):
Checks (measured): vacuity set 371 pass / 0 fail / 15 todo; CI-parity lints plus every test importing the weakening module (excluding
desktop-removed) 253 / 0 outside the adversarial file, which hit the script's 300 s per-file limit under load; run alone, it passes 196 / 0 / 10 todo in 298 s at head (350 s at ce7be5f);npm run typecheckclean;check:denylist1645 files clean;push-gate --range origin/main..HEAD8 commits, 1 tip clean.Round 9 fixes (head 08b5e15)
Both round-8 verdicts (R68o, R68p) failed 35d11f5 on the same cause: when a contested same-named pair was too large to align by character,
closenessscored it on raw lines with only whitespace removed, so semicolons and comments decided which source a moved statement took.What changed
rows, its lines' code characters taken from the same mask askey. The line fallback aligns those, skipping empty rows, instead oflines.replace(/\s/g, ''). Every hunk, at every size, is also aligned code against code and comment against comment: the whole hunk, a run of unequal line counts, and each line pair. Before, only line pairs whose code matched were aligned this way.g, the edited line's comment naming its new arm. CM5t (must merge) is CM5 with the arm the test takes edited too.Fail-before and pass-after (measured). I exported the tree twice under a private TMPDIR: head's tests with 35d11f5's
src, and with head'ssrc. I rebuilt each withtsc -p tsconfig.jsonand rannode --import ./dist/test/isolate.js --test --test-name-pattern=<cases> dist/test/merge-vacuity-r13.test.js.src, these fail, each withactual [true, []]: SEMI, SEMI-z, SEMI-half, CMT, ZN1L-cmt, CM1, CM2, CM3, CM4 and CM5.src, these pass: ZN1L, ZN4L, the SEMIc, SEMI-halfc and CMTc controls, and CM1t, CM3t, CM4t and CM5t.Mutants of compiled
vacuity.js(measured: one line each, run against r11-align, r12 and r13, then restored and checked withcmp). All four are killed:Checks at 08b5e15 (measured)
dist/test/*vacuity*.test.js, 23 files): 404 tests, 389 pass, 0 fail, 15 todo.npm run typecheck: exit 0.npm run check:denylist: 1647 files clean in the builder worktree. The script listsgit ls-files -co, so this count includes the worktree's two untracked files; R68s measured 1645 in a clean checkout.node scripts/push-gate.mjs --range origin/main..HEAD: 10 commits and 1 tip, clean.npm test(run once under the shared lock, at eca4071, before CM5 existed): 5868 tests, 5756 pass, 18 fail, 69 skipped, 25 todo. The 18 failures are in add-project-api-key, coordinator (worktree dependency cache), desktop-removed (yamlresolving through the symlinkednode_modules) and machine-sudoers-closed, -narrow and -removal. None is a vacuity test.src: the same tests fail in both (19 each; the extra one is a git-checkout test that the export can't satisfy). So this change doesn't cause them (measured). They are environmental on this host (inferred). CI is the authoritative run.Not re-run: R68o's surviving mutant (a line score that counts only the source side), the throw path, the PERF2 timings, the COST probe, and R68p's probes beyond the five pinned as tests.
Still open (inferred, unchanged from R68p): there is no PR-wide cost cap, and the 120 s reader timeout backstops it, failing closed (#1016's subject). An exact untested copy of
gstill takes the source by code before naming is tried.This is the merge policy, in the critical set: it needs independent and adversarial head-pinned reviews of 08b5e15.
Round 10 fixes (head 4869afd)
R68q (final check) passed 08b5e15. R68r (adversarial) failed it on an overclaim. A contested same-named pair too large to align by character was scored by its line rows. So a moved
gwith half or more of its lines re-wrapped after=counted every wrapped line as changed, and a two-line decoygtook its source.What changed
closenessnow aligns the tokens ofkey(word runs and punctuation runs,/[\w$]+|[^\w$]+/g), and each unkept token weighs its characters.keyholds no whitespace, so a line break never changes these tokens. The unusedrowsare gone.ALIGN_CELLS, so the reader threw and they failed (measured). Punctuation runs keep them aligned.b.jsand inz.js. The controls WRAP-1of2c, WRAP-2of3c and WRAP-3of4c have no decoy and hold.gwhose parameter is renamed at both ends, so it is scored by token. They pass at 08b5e15 too: they exist to catch the mutants below.ALIGN_CELLS= 4M, not probed.Fail-before and pass-after (measured). I exported 08b5e15 under a private TMPDIR, copied in the new r13 test file, built it with
tsc -p tsconfig.json, and rannode --import ./dist/test/isolate.js --test --test-name-pattern='WRAP|ZN4L' dist/test/merge-vacuity-r13.test.js.actual [true, []]. The three controls and the four ZN4L tests pass.Mutants of compiled
vacuity.js(measured: one line each, run against r11-align, r12 and r13, then restored and checked withcmp)src/0.js)R68r's two other survivors, keeping empty rows and weighting by line count, no longer apply: rows are gone (inferred, from the code).
R68r's probe file at head, 08b5e15 and main 028013d (measured, 43 probes).
? 2) is never taken withf(1), so the hold looks correct (inferred).Cost (measured)
node /var/tmp/wl-coord/r68r-perf2.mjs <tree> 100(100 near-limit hunks, 3 runs each):codeRanges, which this round doesn't change.Checks at 4869afd (measured)
dist/test/*vacuity*.test.js): 416 tests, 401 pass, 0 fail, 15 todo.npm run typecheck: exit 0.npm run check:denylist: 1647 files clean in the builder worktree, which includes two untracked files (the script listsgit ls-files -co); R68s measured 1645 in a clean checkout.node scripts/push-gate.mjs --range origin/main..HEAD: 11 commits and 1 tip, clean.git merge-tree --write-tree origin/main HEAD: clean.npm testwas not re-run this round. CI is the authoritative run.Behaviour change (inferred, not probed): before, a pair fell back from line rows to the throw only past about 2,000 lines a side. Now that happens past about 2,000 unshared tokens a side, which is some 165 lines of dense code. Two contested same-named statements that size now make the PR wait, where 08b5e15 scored them. This fails closed.
This is the merge policy, in the critical set: it needs independent and adversarial head-pinned reviews of 4869afd.
Round 11 fixes (head 29bb7f6)
R68s (final check) passed 4869afd. R68t (adversarial) failed it on an overclaim. In probe UB100, a 105-line
gis moved with every word of 100 lines edited inside anif (u.never)block the test never enters. Scored by token, each edited name cost its full length on both sides. The movedgscored −3402 against a two-line decoy's −2818, so the decoy took the source and the PR merged.What changed
closeness's token fallback, each run of tokens between kept ones is now aligned by character, and costs the characters it doesn't keep. A run too large to align by character costs its full length. Soalphaedited toalphzcosts 2, not 10.b.js) and UB100z (decoy inz.js).gis moved with its taken arm edited and tested, beside a two-line decoy. The pair is too large to tell apart by token, so the PR must wait with "two statements named g are too large to tell which one … was moved from".grenamed at both ends, with every+turned into-.Fail-before and pass-after (measured). I exported 4869afd under a private TMPDIR, copied in the new r13 test file, built with
tsc -p tsconfig.json, and rannode --import ./dist/test/isolate.js --test --test-name-pattern='UB100|ZN1T|ZN4L' dist/test/merge-vacuity-r13.test.js.actual [true, []]. UB100c, UB100t, ZN1T and every ZN4L test pass.Mutants of compiled
vacuity.js(measured: one line each, run against r11-align, r12 and r13, then restored and checked withcmp)return -InfinityTwo mutants survive:
\wwithout$in the token pattern: with character-level runs, a$that splits a token is still aligned by character (inferred).\sfilter inkey: R68t inferred this is equivalent, because the code mask never marks whitespace (inferred).R68r's and R68t's probe files at head, 4869afd and main 246e3f6 (measured, 95 probes, with
R68T_R1=1).renders, each moved into another file with a tested edit), TC120t, and BND166 to BND180, both tested and untested. This is the fail-closed threshold that round 10 named: more than about 2,000 unshared code tokens a side. It turns ordinary large same-named moves with tested changes into PRs that wait for the owner. A row-score fallback before the throw would avoid it, but it isn't in this PR.Cost (measured)
node /var/tmp/wl-coord/r68r-perf2.mjs <tree> 100, 3 runs each:Checks at 29bb7f6 (measured)
dist/test/*vacuity*.test.js): 422 tests, 407 pass, 0 fail, 15 todo.npm run typecheck: exit 0.npm run check:denylist: 1647 files clean in the builder worktree, which includes two untracked files.node scripts/push-gate.mjs --range origin/main..HEAD: 12 commits and 1 tip, clean.git merge-tree --write-tree origin/main HEADonto 246e3f6: clean.npm testwas not re-run this round. CI is the authoritative run.Body corrections: the round 9 and round 10 denylist lines and round 10's "one token per character" row above are corrected in place, as R68s noted.
This is the merge policy, in the critical set: it needs independent and adversarial head-pinned reviews of 29bb7f6.
Round 12 fixes (head 1c87263)
R68u (final check) passed 29bb7f6. R68v (adversarial) failed it on an overclaim (R1). Once one run of edited tokens was past
ALIGN_CELLS(about 2,000 code characters a side), it cost its full length. So a two-line decoygtook the source of a large movedgwhose long expression was edited at every token, and the PR merged (BR220 to BR300, BRSIM300).What changed
closeness's token fallback, a run of edited tokens thatalignCharscan't align now throws the sameCoverageUnreadableas a too-large token alignment. The PR waits with "two statements named g are too large to tell which one … was moved from". A run is never weighed by its length any more. This was R68v's preferred fix; I didn't take the run-splitting alternative.b.js), BR220z (decoy inz.js), BR300, and BR220t (the taken arm edited and tested). Each must wait with the "too large to tell" reason.ALIGN_CELLS, but each run is aligned on its own.Fail-before and pass-after (measured). In the builder worktree, with the new r13 tests and the unfixed
src/vacuity.tsof 29bb7f6, I rannpx tsc -p .and thennode --import ./dist/test/isolate.js --test --test-name-pattern='BR2|BR3|LNG100' dist/test/merge-vacuity-r13.test.js.expected: false, actual: true(they merge). BR220c, LNG100 and LNG100t pass.Mutants of compiled
vacuity.js(measured: one change each, run against r11-align, r12 and r13 (194 tests), then restored and checked withcmp)run()at a kept token (R68v survivor)The first run of the last mutant overlapped with a rebuild of
dist, which overwrote the mutant, and reported a false "survives". I reran it on its own with nothing else touchingdist; the row above is that rerun.R68t's and R68v's probe files at head, 29bb7f6 and main 246e3f6 (measured).
r68v-probe.test.tsholdsr68t-probe.test.tsverbatim, plus the R68V probes, so I ran it once per tree, with pattern^R68[RTV],R68T_R1=1,R68V_BR=150,200,210,220,230,260,300,R68V_ORD=60,195,200andR68V_DD=220,250. That is 136 decisions, 134 distinct IDs, per tree.b.jsorz.js, hold at head as before, and their tested variants BR150t to BR210t merge as before. Every BRnc control holds, and BRSIM150 holds.npm test.Checks at 1c87263 (measured)
npm run typecheck: exit 0.npm run check:denylist: 1647 files clean in the builder worktree, which includes two untracked files.node scripts/push-gate.mjs --range origin/main..HEAD: 13 commits and 1 tip, clean.git merge-tree --write-tree origin/main HEADonto 246e3f6: clean.npm test, once, under the shared lock: 5895 tests, 5783 pass, 18 fail, 69 skipped, 25 todo. None of the failures is in vacuity or merge policy.Not done (follow-ups)
$survivor from round 11 is unchanged.This is the merge policy, in the critical set: it needs independent and adversarial head-pinned reviews of 1c87263.