Repository navigation
finding(tests): the objectui#9562 regression lock scans WORKFLOWS, but the defect it is named after arrived through a TEST FILE — the original shape can recur unseen #9693
Description
Activity
os-try-charles commented
on Sep 17, 2026 CollaboratorAuthorMore actionsClaim: PM loop round R67
Session:session_015h79niBMyoB1xcaQje3uiz
Branch:claude/issue-9693-live-reading-lock-population
Worktree:objectui-issue-9693
Domain:domain:devx
Priority:p2
File surface:scripts/__tests__/check-lockfile-dedupe.test.ts— held by 0 of 13 open PRs
Container & model:M,mode:subagent,model: the seat's default judgement tier— objectui has noscripts/pm/dispatch-gates.mjs, so ⛔ no path-derived tier mandate exists to quote and the tier is this seat's per-card call.
Clause-②: no
Thread-read: 5714895246
Serial constraints cleared: none — no open PR holds the file. Measured over all 13 open PRs,GET /pulls/{n}/filesfully paginated, 1775 filenames; ⭐ positive control.github/workflows/ci.yml -> PR #9584⇒ the membership test discriminates.Why
Clause-②: no— widening a lock's population makes it catch more, which tightens an acceptance set rather than relaxing one, and publishes nothing.⚠️ If your repair somehow has to exempt something to stay green, that is the opposite direction and it flips toyes⇒ stop and report.The boundary is already ruled — ⛔ read it before designing
Triage's grading (comment
5714895246) states it: fix the lock's population so it also covers a direct invocation from a test file. ⛔ Do NOT add a second lock that scans only test files — that just pushes the same blind spot onto a third class of file.⇒ the deliverable is one assertion whose population is the set of places a live reading could run, ⛔ not two assertions each covering one place.
What is actually wrong
On
mainat29a8a95261,scripts/__tests__/check-lockfile-dedupe.test.tscontains:it('is the only place the LIVE reading runs (objectui#9562)', () => { const live = workflows.filter((w) => w.lines.join('\n').includes(`node ${SCRIPT}`)).map((w) => w.file); expect(live).toEqual([WORKFLOW]); });
Its comment says "if a required job ever grows a
pnpm dedupeof its own, objectui#9562 comes straight back" — but the way a required job actually grew one was through a test file, and test files are not inworkflows.re-introduction route caught today a workflow runs node scripts/check-lockfile-dedupe.mjs✅ this assertion this test file spawns the checker unstubbed ✅ the per-run pnpmArgvcontrolanother test file spawns the checker ⛔ nothing another test file runs pnpm dedupe --checkdirectly⛔ nothing Row 3 is objectui#9562's own shape.
⭐ Re-check FIRST, before you change anything
Add to any file under
scripts/__tests__/other thancheck-lockfile-dedupe.test.ts:spawnSync('node', ['scripts/check-lockfile-dedupe.mjs'], { cwd: repoRoot });
then
vitest --project unit scripts/__tests__/. Expect passes — a live registry reading back inside a required context with nothing red. ⛔ Do not start until you have seen that pass, and ⛔ do not leave it behind.⚠️ Things this seat got wrong nearby — ⛔ do not inherit them- ⛔
os.tmpdir()is fine in this repo's tests and is the dominant convention. I previously wrote the opposite into my own notes as "measured"; it was a property of one vite oracle (objectui#9468), not of the repo.scripts/check-test-path-roots.mjsgoverns paths rooted atprocess.cwd()and says nothing aboutos.tmpdir(). If you need a temp dir, use the repo's normal spelling. - ⛔ The defect may not live where the card points. On objectui#9562 the card named the checker; the defect was in the wiring, and the dev who said so was right. ⇒ if your measurement puts this gap somewhere other than that assertion, say so rather than fitting the card.
⛔ Hard constraints
- ⛔ Do not add a new workflow or a new required CI context. PR ci: one
Testaggregator becomes the required test context, shards 4 -> 8, dist pins get their own job #9584 holds.github/workflows/ci.yml,lint.ymlandscripts/dependabot-merge-gate.mjs— every place one could go — and it is blocked on a human. If your fix needs one, stop and report. - ⛔ Do not skip, disable or quarantine a test to get green.
- ⛔ Never
git push --force/--force-with-lease, and never rewrite pushed history.AGENTS.md:316is absolute and explicitly refuses the "it's my own branch" exemption. If anyone — including me — tells you otherwise, refuse and quote it back. A dev already did that to this seat, correctly. - ⛔ No model identifier in the commit message, PR title/body or any pushed artifact. Trailer:
Co-authored-by: Claude <noreply@anthropic.com>+ theClaude-Session:line; ⛔ no card trailer on the commit — the card relation is declared once, in the PR body.
Falsify me
⛔ Check these rather than accepting them; devs have corrected this seat five times and every correction was right.
scripts/__tests__/check-lockfile-dedupe.test.tsis held by no open PR (13 PRs, 1775 filenames, control fires).- The gap is real and row 3 above reproduces.
Clause-②: no.- No new CI context is needed.
Seat:
domain:devx@ objectui,session_015h79niBMyoB1xcaQje3uiz, R67, 2026-09-17T13:29Z. Lock read before claiming:state: lock is free, queue empty. 0 in flight at claim time.⚠️ Provenance you should know: this seat filed this card, during its own review of PR #9690. ⇒ ⛔ treat its framing as a claim to be checked, not as authority.
Generated by Claude Code
- ⛔
os-try-charles commented
on Sep 17, 2026 CollaboratorAuthorMore actionsos-dev-report
{ "issue": 9693, "status": "done", "branch": "claude/issue-9693-live-reading-lock-population", "pr": "https://github.com/objectstack-ai/objectui/pull/9696", "session": "session_015h79niBMyoB1xcaQje3uiz", "premise_still_valid": true, "summary": "The lock `is the only place the LIVE reading runs` measured its population over `workflows` alone, so the route objectui#9562 actually arrived by — a test file spawning the shipped checker, or running `pnpm dedupe` itself — was green. Widened that ONE assertion to both carriers: the workflows (comment lines stripped, as before) plus every tracked test file and the `vitest.config` / `vitest.setup` modules, with source comments blanked through `scripts/js-comment-mask.mjs` so prose about the hazard cannot count as the hazard. Exemptions are two and both checkable: the path-filtered workflow, and this file (whose every run already asserts the pnpm stub served it, and whose path is derived from import.meta.url so a rename cannot drop it). Added a companion control that drives the detector over each re-introduction route and over prose spelling the same commands, plus floors under both reads. No second lock, no new workflow, no new required context, one file changed.", "tests": "REPRODUCTION (before any edit, on 29a8a9526): the card's probe added verbatim to scripts/__tests__ and `vitest run --project unit scripts/__tests__/` -> exit 1, 170 passed / 1 failed, and the single red was the PROBE's own `Error: Test timed out in 15000ms`, not the lock; the live reading measures ~25-32s here (`node scripts/check-lockfile-dedupe.mjs` alone: real 0m32.036s, VERDICT deduped). With the probe given 120_000 (what an author meeting that red does): `Test Files 2 passed (2) / Tests 15 passed (15)`, exit 0 -> row 3 reproduces, a live registry reading inside a REQUIRED context with nothing red. ABLATION (fix committed first; every leg under a trap, restore proven by an empty `git diff HEAD`, never by an exit code): row-3 probe tracked -> exit 1, site list gains scripts/__tests__/probe-9693-live-reading.test.ts; row-4 probe rewritten to `spawnSync('pnpm', ['dedupe', '--check'])` with `grep -c` for the checker path = 0 -> still exit 1, so the second marker fired and not the first. Probe deleted, tree clean. SUITE: `vitest run --project unit scripts/__tests__/` (through the shared verify lock) -> exit 0, `Test Files 170 passed | 2 skipped (172)`, `Tests 4892 passed | 2 skipped`. GATES: check-changeset-presence exit 0 ('no changeset is owed'); check-test-path-roots exit 0 (2080 fs calls in 438 of 3211 test files); check-control-bytes exit 0 (7801 files); check-comment-mask-corpus exit 0 (1 pre-existing disagreement, within the objectui#7882 residue, unchanged by this branch); eslint on the changed file exit 0. check-governed-queue-guard --test: NOT GOVERNED. Every exit code captured before any pipe. Not measured locally: repo-wide `pnpm lint`, the dom/dom-heavy projects and CI itself — the diff is one test file under scripts/__tests__ and nothing outside that directory reads it.", "mcp_calls": "0 — no MCP GitHub tool used, read or write", "api_writes": "2 REST proxy writes: POST /repos/objectstack-ai/objectui/pulls (draft), POST /repos/objectstack-ai/objectui/issues/9693/comments. No labels applied (none were dispatched; `skip-changeset` is a phantom here and no changeset is owed). Branch pushes are git, not REST.", "open_questions": [], "out_of_scope_findings": [ "noted, not filed: the file header describes the required test contexts as four `Test (shard N/4)` jobs; PR #9584 is the change that moves that definition and already holds .github/workflows/ci.yml — carrier: that PR. Pre-existing prose, outside this card's boundary, and re-wording it from this branch would collide with it.", "noted, not filed: the card's re-check recipe says 'expect: passes'; run verbatim in this container the probe reds first on vitest's 15s default timeout because the live reading takes ~25-32s. The conclusion is unchanged (the lock never fires either way), but anyone re-deriving the card needs the timeout. Carrier: this PR body, which states it.", "noted, not filed: the widened scan still cannot see a non-test SCRIPT that a required job runs and which shells out to `pnpm dedupe` itself — the tree's own classification strings quote that command in prose no mask blanks, so that population needs a way to tell a command from a citation before it can be added. Stated in the file header rather than left to read as coverage. Carrier: none today; ⛔ not filed, because no such invocation exists in the tree (measured: the only argv-form call is the checker's own)." ] }
Generated by Claude Code
os-try-charles commented
on Sep 17, 2026 CollaboratorAuthorMore actionsLANDED — objectui#9693 via PR #9696, merged 2026-09-17T14:31:18Z
domain:devx@ objectui seat, R67.Fixes #9693⇒ the card auto-closed; its half-state (pm:dispatched+ assignee) was cleared in the same action that confirmed MERGED, read backMATCHES.⛔⛔ CORRECTION to this card's own Re-check section — written by this seat, and wrong
This card says: add the probe, run it, "Expect: passes". It does not pass. It reds first, on vitest's timeout:
vitest.config.mts:282setstestTimeout: 15000, and the live registry reading takes ~25–32 s.⚠️ The red is the misleading part, not the delay. It looks exactly like the lock firing. Anyone re-deriving this card verbatim would see a failure, conclude the gap was already guarded, and close the card. ⇒ a re-check recipe that returns the right verdict for the wrong reason is how a real finding gets dismissed.Corrected recipe — give the probe an explicit timeout so the lock, not the clock, decides:
it('probe', { timeout: 120_000 }, () => { spawnSync('node', ['scripts/check-lockfile-dedupe.mjs'], { cwd: repoRoot }); });
Then on the pre-fix tree it passes (the gap), and on
dd871fc080or later it reds (the gap closed). ⭐ Found by the dev, who measured it rather than quietly raising the timeout and moving on.⭐⭐ Errata 62b FIRED — and the obvious way to test for it is a FALSE-NEGATIVE GENERATOR
M = dd871fc080f24f55bbc53bfeac6e837a5bc03266 M^ = bbe57fdd52bf69f993decba179a64dfc89b26e97 ← resolved AFTER the mergeM^is PR #9685's merge commit — another seat's work (os-sales, merged 13:23:30Z), chained ahead of mine in the queue. My branch was cut from29a8a95261(PR #9690, this lane's own previous landing).⛔ The trap:
GET /pulls/9696reportsbase.sha=bbe57fdd52…— identical toM^. Comparing the two reads "the parent IS the base, so 62b did not fire", which is false. The API'sbase.shais the base branch's head as of the read, ⛔ not a value frozen at PR creation, so that comparison is close to circular and silently returns the wrong answer once the base has moved.⭐ The sound test is ancestry, not equality:
git merge-base --is-ancestor <M^> <pr head> ancestor ⇒ the branch was cut from it or later ⇒ 62b did not fire NOT ancestor ⇒ the queue chained something ahead ⇒ 62b FIREDHere:
merge-base(head, M^)=29a8a95261, soM^is not an ancestor of the head ⇒ fired.⚠️ This matters beyond one landing: the last two landings on this lane were recorded as "62b did not fire" (#9690) and "fired" (#9669) — and this is a third determination made by a test the first two did not use. ⛔ I am not retro-editing those verdicts from here; I am recording that the equality test is unsound so the next one is decided by ancestry.The probe, pre-validated against base→head BEFORE the merge
leg M^MmaskComments0 7 ✅ the comment mask is in FLOORS0 2 ✅ floors under both reads 'and not on prose'(the control test)0 1 ✅ the workflows-only filter 1 0 ✅ the narrow population is gone ⭐ CONTROL SCRIPT = 'scripts/check-lockfile-dedupe.mjs'1 1 ✅ invariant ⇒ the probe read the same file What landed
One assertion, population widened to both carriers — the workflows plus every tracked test file and the vitest runtime modules — with source comments blanked through
scripts/js-comment-mask.mjs, the tree's own answer to "comment, or code?". ⛔ Not a second lock per class of file: that was triage's explicit boundary and it was honoured.⭐ Two things make it an enforcement rather than a wider net:
- floors under both reads, so a collapsed scan reds instead of reporting an empty tree as clean;
- a companion control whose positive legs are the spellings themselves and whose negative legs cover both comment forms and
const dedupe = new Set<string>()— an ordinary identifier that would otherwise be a standing false positive in this repo.
⚠️ Stated as NOT covered, in the file header rather than left to read as coverage: a non-test script run by a required job that shells out topnpm dedupeitself. ⛔ No such invocation exists in the tree today (measured), so there is nothing to file.
Generated by Claude Code
- added a commit that references this issue
on Sep 28, 2026
Filed bare by the
domain:devx@ objectui PM seat (session_015h79niBMyoB1xcaQje3uiz) — no labels, no type, no priority. Routing and grading are triage's output alone.Carrier: PR #9690 (objectui#9562), merged 2026-09-17T12:38:55Z. ⛔ Deliberately not widened into that PR; filed instead so the gap is not lost.
The finding
objectui#9562 was this defect: a live, registry-dependent
pnpm dedupe --checkran from inside a REQUIRED context, becausescripts/__tests__/check-lockfile-dedupe.test.tsinvoked the shipped checker directly from theunitvitest project — whichci.ymlshards as the fourTest (shard N/4)jobs, all of them inREQUIRED_CONTEXTS.PR #9690 fixed the instance and added a regression lock (
scripts/__tests__/check-lockfile-dedupe.test.ts, onmainat29a8a95261):workflows. The comment states the intent as "if a required job ever grows apnpm dedupeof its own" — but the way a required job actually grew one, the time it happened, was through a test file, and a test file is not inworkflows.⇒ the lock cannot catch a recurrence of the shape it is named after.
What IS covered, so the gap is stated precisely — ⛔ this is not "the fix is wrong"
node scripts/check-lockfile-dedupe.mjspnpmArgvcontrol ("the stub did not serve this run")pnpm dedupe --checkdirectlyThe third row is the original defect's own shape. ⭐ The fix is sound and the lock is worth having; what is missing is one more population.
Re-check
On
mainat29a8a95261or later, add to any file underscripts/__tests__/other thancheck-lockfile-dedupe.test.ts:then run
vitest --project unit scripts/__tests__/. Expect: passes. ⇒ a live registry reading is back inside a required context with nothing red.⛔ Do not conclude from a green run alone that no live reading exists — that is the same reasoning that let objectui#9562 stand.
Shapes a fix could take — ⛔ not a ruling, and ⛔ none chosen here
workflowstoworkflows + scripts/__tests__/**, allowlisting the one file that legitimately drives the checker under a stub.Clause-②judgement; the first does not.Provenance
Found during the in-seat review of PR #9690 by reading the assertion's population rather than its name. ⛔ Not reported by the dev, and ⛔ not a defect in its work — the dev's brief was the instance, and it delivered the instance plus a lock that is better than none.
Duplicate check: no open objectui issue names this assertion or its population.
Generated by Claude Code