Skip to content

test(scripts): cover @object-ui/plugin-view and @object-ui/core in the vi.mock inherit gate - #8414

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-6892-vi-mock-inherit-slice15-16-final
Sep 7, 2026
Merged

baozhoutao merged 1 commit into
mainfrom
claude/issue-6892-vi-mock-inherit-slice15-16-final

Conversation

@baozhoutao

Copy link
Copy Markdown
Contributor

Fixes #6892

objectui#6892 slices 15 + 16, folded into one PR: @object-ui/plugin-view and
@object-ui/core join COVERED_SPECIFIERS in scripts/check-vi-mock-inherit.mjs,
and the file's header records the slice in the shape slices 5-14 used.

No test file is edited. Both specifiers were re-derived as already
all-inheriting, so these are membership flips rather than sweeps.

Re-derivation (the gate's own scan(), local covered override)

Taken on d9788c141 -- the base of this branch -- never from the worklist's
table and never from slice 14's paragraph in the header:

scan(ROOT, { covered: ['@object-ui/plugin-view'], floors: {} })
  -> 10 judged, 10 inheriting, 0 frozen, 0 unreadable
scan(ROOT, { covered: ['@object-ui/core'], floors: {} })
  ->  2 judged,  2 inheriting, 0 frozen, 0 unreadable

Nothing frozen turned up, so no sweep was folded in.

Census, before and after

judged inherit frozen other workspace
before (19 members) 648 648 0 12
after (21 members) 660 660 0 0

Judged rose by exactly 12 = 10 + 2, and other workspace fell by the same
number. Diffed PER SITE -- verdict and reason string -- over all 1785 call
sites the walk reports: exactly 12 rows changed, every one of them
workspace/unjudged becoming covered/inherits, and the other 1773
byte-identical. No site moved the other way, so this lands as a ratchet.

Why the closing keyword is correct here, and was not on the fourteen earlier slices

22 distinct @object-ui/* specifiers are named by some vi.mock / vi.doMock
call site in this tree. 19 were members; these 2 make 21 package roots, all
members; the 22nd is @object-ui/components/ui/sonner, a SUBPATH of the member
slice 6 swept, judged by reach since objectui#8141. So every specifier any call
site in this tree names is now judged and other workspace reaches 0 -- the
worklist has no remaining slice. Confirmed on this branch's own tree rather than
inherited from the dispatch.

The one specifier deliberately NOT added

@object-ui/components/ui/sonner. It is already covered by reach, and the
constant names package ROOTS only -- the gate's test pins that mechanically
(every member's spec.split('/') has length 2), so adding it would turn a green
pin red while changing no verdict. Refused on purpose; the header now says so.

No STEP 0 barrel walk is owed, and that is a property of the flip

Every earlier slice measured its barrel's module-scope effects because
converting a frozen factory makes the real barrel LOAD in each converted file.
Nothing converts here: all twelve factories already spread the real module, so
both barrels already load in exactly the files that load them today. This diff
cannot change what a single test executes -- only what the gate judges.

Verification (real output)

$ node scripts/check-vi-mock-inherit.mjs        # EXIT=0
OK (4458 tracked source file(s), 2724 test-named; 616 carry a mock; 660 call
site(s) on ... @object-ui/app-shell, @object-ui/plugin-view, @object-ui/core and
their subpaths judged (660 inherit, 0 auto-mocked); 0 other workspace, 243
external, 879 local, 0 non-static, 3 embedded in a string literal)

$ pnpm exec vitest run scripts/__tests__/check-vi-mock-inherit.test.ts
Test Files  1 passed (1)
     Tests  84 passed (84)
(through scripts/pm/os-verify-lock.sh: VERDICT command-exit 0, held the lock 19s)

$ pnpm check:vi-mock-specifiers   # EXIT=0, sibling gate over the same population
$ pnpm check:control-bytes        # EXIT=0
$ pnpm check:entry-guard          # EXIT=0
$ pnpm check:comment-mask-corpus  # EXIT=0
$ pnpm check:doc-fences           # EXIT=0
$ pnpm exec eslint scripts/check-vi-mock-inherit.mjs   # EXIT=0, no output

The pin suite's 84 cases include the two this diff is exposed to: every member
names a real workspace package (packages/plugin-view and packages/core both
match), and every member is a package root.

Changeset

Not owed, and measured rather than guessed:

$ node scripts/check-changeset-presence.mjs   # EXIT=0
Compared the working tree with d9788c141 (merge-base with origin/main): 1 file(s)
changed, 0 of them published source of a package the release covers ...
No source or published contract of a released package changed in this range, so
no changeset is owed.

The fourteen earlier slices each carried one because they edited test files under
a published package's src/; this one touches a single file under scripts/.

Not measured locally

pnpm check:readme-exports exits 1 in this worktree with 532 lines of
"its type entry ./dist/index.d.ts is not on disk -- run pnpm build first".
That is an unbuilt-workspace prerequisite, independent of this diff (which
touches no README and no package); CI builds first. Recorded as NOT MEASURED
rather than as a red gate.

Draft on purpose: CI convergence and the ready flip are the PM's read.


Generated by Claude Code

…n the vi.mock inherit gate

objectui#6892 slices 15 + 16, folded. Both specifiers already read
all-inheriting when judged, so this is a membership flip and no test file
is edited.

Re-derived on d9788c1 with the gate's own `scan()` under a local
`covered` override:

    @object-ui/plugin-view   10 judged, 10 inheriting, 0 frozen
    @object-ui/core           2 judged,  2 inheriting, 0 frozen

Tree-wide census moves 648 judged / 648 inherit / 12 other workspace to
660 / 660 / 0. Diffed per site (verdict and reason string) over all 1785
call sites: exactly 12 rows changed, all `workspace/unjudged` to
`covered/inherits`, the other 1773 byte-identical. A ratchet, so no sweep
was owed.

`@object-ui/components/ui/sonner` is deliberately NOT added: it is a
subpath of a member and covered by reach since objectui#8141, and the
constant names package roots only.

With these two members the worklist closes -- every `@object-ui/*`
specifier any `vi.mock` call site in this tree names is judged, and
`other workspace` reads 0. The header records what that does and does
not guarantee.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FhBNJcLRZLe8M87VcUgpKr
@claude

claude Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

ACCEPT — domain:devx @ objectui execution seat, PM session session_01FhBNJcLRZLe8M87VcUgpKr, R46, reviewed 2026-09-07T19:40Z against GitHub and the tree, ⛔ never against the report's narrative.

The diff is exactly two lines of substance, and the exclusion was refused

One file, +85/-14, draft, head 001bb74a1. Scanning the patch for member additions returns exactly two: '@object-ui/plugin-view' and '@object-ui/core'. ⛔ @object-ui/components/ui/sonner was not added, as the brief required — the trap with the mechanical tripwire was refused on purpose.

⚠️ And the dev sharpened the dispatch's framing of it, correctly: this seat wrote that three specifiers "are not members", which is true, but the dev measured that @object-ui/components/ui/sonner already classifies as scope covered by prefix reach, so it was never part of the 12 other-workspace sites in the first place. The brief's conclusion was right; its arithmetic framing invited the reading that there were three uncovered specifiers when there were two.

The re-derivation was retaken, not inherited — including from a paragraph that argued the opposite

Both figures re-derived on d9788c141 through the gate's own scan() under a local covered override: @object-ui/plugin-view 10 / 10 / 0, @object-ui/core 2 / 2 / 0. No frozen factory turned up, so no sweep was folded in and no test file is touched.

⭐ Worth recording because it is where this fold could have gone wrong: slice 14's own header paragraph — written yesterday, by another dev, and still on main until this PR — said of these two specifiers "which is why they are still owed a slice each: the precondition below is a MEASUREMENT, and a specifier that reads zero frozen today can carry a frozen factory tomorrow." That prose argued against folding. It is not a maintainer ruling and not a triage decision, so this seat's gate-by-gate fold decision overrides it — but only because the brief demanded the measurement be retaken on today's tree rather than inherited from that very paragraph, and it was. Had either specifier moved overnight, the fold would have been wrong and the dev was instructed to sweep and say so. ⭐ The PR replaces that paragraph in the same diff, so code and prose do not disagree on main.

The arithmetic that licenses Fixes, confirmed before it was written

Census 648 judged / 648 inherit / 0 frozen / 12 other workspace → 660 / 660 / 0 / 0. Judged rose by exactly 12 = 10 + 2, and other workspace reached 0. Diffed per site across all 1,785 call sites on verdict AND reason string: exactly 12 rows changed, every one workspace/unjudged → covered/inherits, the other 1,773 byte-identical — a ratchet, nothing moved the other way.

22 named specifiers = 21 package roots (now all members) + the one subpath covered by reach. ⇒ No slice remains, Fixes #6892 is correct, and GitHub registered it: the card's closed_by_pull_requests names this PR. The dev states plainly that had other workspace not reached 0, the body would have said Refs.

⭐ The header's closing statement is the part worth reading twice

Two things the dev wrote that this seat did not ask for and would have wanted:

  1. The membership rule is protected against the precedent this slice sets. The header now reads that the list holds twenty-one, "nineteen joined by sweep, and the last two … by a MEASUREMENT that found nothing to sweep, which is the degenerate case of the same precondition and not a second door". Without that sentence the next reader could conclude a member may join by judgement — which is exactly what the grow-only rule forbids and what fourteen slices of sweeping paid for.
  2. Three explicit non-guarantees are recorded against the green: other workspace will not stay 0 by itself; a member reading zero frozen today can carry a frozen factory tomorrow; and a third-party frozen neighbour can still kill a file during collection, which this gate by construction does not judge. ⇒ A worklist closing at zero is the moment a reader is most likely to mistake a measurement for a permanent guarantee, and the file now refuses that reading in its own words.

Verification

node scripts/check-vi-mock-inherit.mjs exits 0 with both new members named and 0 other workspace. The gate's own pin suite is green at 84/84 through the shared lock — and the two load-bearing pins here are the ones the brief flagged: every member must name a real packages/DIR/package.json whose name matches (packages/plugin-view and packages/core both do), and every member must be a package root. That second pin is precisely what adding the sonner subpath would have reddened.

Changeset measured, not guessed: check-changeset-presence exits 0 with "0 of them published source" — the fourteen earlier slices each owed one because they edited test files under a published package's src/; this one touches only scripts/. One NOT-MEASURED datum is recorded rather than reported as a pass: check:readme-exports exits 1 in an unbuilt worktree for all 532 lines ("run pnpm build first"), a prerequisite failure structurally independent of a diff touching no README and no package.

Not governed surface. PR stays draft; the flip is this seat's read.

Next: CI convergence → flip ready → post-flip guard → auto-merge SQUASH → queue confirmation → landing probe (both members present in COVERED_SPECIFIERS on re-fetched origin/main, and ⛔ @object-ui/components/ui/sonner still absent from it; control: the gate's own post-merge push run must print 660 … judged (660 inherit, 0 auto-mocked); 0 other workspace) → LANDED here and on #6892, which closes via Fixes — the first and only slice for which that verb is right.


Generated by Claude Code

@baozhoutao
baozhoutao marked this pull request as ready for review September 7, 2026 19:48
@baozhoutao
baozhoutao added this pull request to the merge queue Sep 7, 2026
@claude

claude Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Armed: PR #8414 flipped ready at 2026-09-07T19:48:38Z on head 001bb74a1 after CI converged all green (28 checks, Live E2E excluded, read 19:48:30Z); post-flip Governed Surface Queue Guard completed/success at 19:48:55Z; auto-merge SQUASH enabled; queued (added_to_merge_queue at 19:49:01Z, read 19:49:05Z).

Landing probe on merge, on re-fetched origin/main: '@object-ui/plugin-view' and '@object-ui/core' present in COVERED_SPECIFIERS (21 members), and ⛔ @object-ui/components/ui/sonner still ABSENT from it — a member list that grew to 22 would mean the subpath was tidied in after all, which reddens #8391's roots-only pin and quietly reopens the "join by judgement" door this worklist spent fourteen slices closing.

Control, read from the gate RUNNING on merged main, ⛔ not from a source grep: the post-merge Inert vi.mock Specifiers push run must print 660 call site(s) … judged (660 inherit, 0 auto-mocked); 0 other workspace. 660 + 0 = 660, the same total as 648 + 12 before ⇒ the twelve moved from unjudged into judged and nothing moved the other way. ⚠️ A census that stayed at 648 with two extra names in the list would be the failure this control exists to catch: members added without their measurement, reading green either way.

Then LANDED here and on #6892, which CLOSES via Fixes — the first and only slice of fourteen for which that verb is right. — domain:devx @ objectui seat, PM session session_01FhBNJcLRZLe8M87VcUgpKr.


Generated by Claude Code

Merged via the queue into main with commit 4b5e07a Sep 7, 2026
31 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-6892-vi-mock-inherit-slice15-16-final branch September 7, 2026 20:05
@claude

claude Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

LANDED — merged into main at 2026-09-07T20:05:38Z as 4b5e07a53 (squash), read 20:05:44Z. #6892 closed completed via Fixes — the worklist is finished after fourteen landings.

Content probe on re-fetched origin/main (tip 4b5e07a53, read 20:07Z) — both claims from the Armed note, and the exclusion:

  1. 21 members, with '@object-ui/plugin-view' and '@object-ui/core' both present.
  2. ⛔ @object-ui/components/ui/sonner is ABSENT from the constant, as required. Checked structurally as well as by name: every one of the 21 members splits into exactly two path segments, so no member is a subpath — the invariant PR fix(test-infra): judge a subpath of a swept package in check-vi-mock-inherit #8391 pinned mechanically still holds on main.

Control, read from the gate RUNNING on merged main (34158071665, head 4b5e07a53, step completed 20:05:52Z):

✅  check-vi-mock-inherit: OK (4458 tracked source file(s), 2724 test-named; 616 carry a mock;
    660 call site(s) on …, @object-ui/app-shell, @object-ui/plugin-view, @object-ui/core
    and their subpaths judged (660 inherit, 0 auto-mocked);
    0 other workspace, 243 external, 879 local, …)

⇒ 660 judged / 660 inherit / 0 frozen / 0 other workspace. 660 + 0 = 660, the same total as the pre-change 648 + 12, so the twelve moved from unjudged into judged and nothing moved the other way.

⭐ Why the census reading was the load-bearing half of this control rather than a formality: adding two names to the list is trivially green on its own — the gate would print the longer list and the same 648 either way. A member added without its measurement is indistinguishable from one added with it, except by the count. The count moved by exactly 12, which is what makes "joined by measurement" a fact rather than a claim.

The end state, and what it is not

Every @object-ui/* specifier any vi.mock or vi.doMock call site in this tree names is now judged, and other workspace reads 0 for the first time since the gate was built. ⛔ That is not a permanent guarantee, and the PR says so in the file rather than leaving the green to be misread: other workspace will not stay 0 by itself; a member reading zero frozen today can carry a frozen factory tomorrow; and a third-party frozen neighbour can still kill a file during collection, which this gate by construction does not judge.


Generated by Claude Code

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants