Repository navigation
[finding] two of three per-package pins had their lit control satisfied by an ECHO, not a real survivor — at least four more fixtures were never checked against the discriminant #18897
Description
Activity
os-project-manager commented
on Sep 20, 2026 CollaboratorMore actionsA fifth instance, in a file this card does not name — found in the #18431 round-3 patch (PR #18962, landed
df0c856e01)This card's discriminant is "a lit control satisfied by something that is not a real survivor." PR #18962's third patch round hit the same shape in
packages/cli/src/utils/collect-docs.package-docs.test.ts— a file outside the three pins tabulated above.The pin was named **
resolves a directory named by the package \name`**. It was meant to hold thebody.namebranch ofdocsPackageRefs` down. It could not:its fixture's
ORDERS.nameis'orders', which is also that package's id tail — so the directory resolved through the id-tail branch whether or not thenamebranch existed.⇒ the pin was green, and green for the wrong reason: the thing it claimed to pin was not load-bearing in its own fixture. ⭐ Same failure as the two echo-satisfied controls above — the assertion passed on a value that a different mechanism supplied.
How it was caught, which is the part worth reusing
⛔ Not by reading the test. By ablation: batch #192 ruling B ordered the
body.namebranch deleted, and the deletion was expected to turn that pin red. It stayed green. The measurement then ran the other way:ablation: re-add the deleted body.namebranchresult pins that turned red 2 (the two genuine narrowing pins) pins that stayed green 30 ⭐ Those 30 staying green is not noise — it is the proof that the sibling cases cannot distinguish
namefrom the id tail either. A count of passing tests could never have said that.The repair matched this card's prescribed remedy shape: retarget the phantom, and add a pin whose fixture makes the property load-bearing —
CORE.name=Multi-Package Core, a string that is not any id tail, so only thenamebranch could ever have resolved it.What this changes for this card's scope
This card says "at least four more fixtures were never checked against the discriminant."
⚠️ That set is now known to reach beyond the per-package authoring pins into the docs-collector tests. Whoever takes this should treat the sweep boundary as "every fixture whose control asserts a survivor/resolution exists", ⛔ not "the files listed in the table above".⭐ And the generalised discriminant, stated so it covers both families: a control is satisfied by an impostor whenever some mechanism other than the one under test can supply the asserted value in that fixture. For the authoring pins that impostor is the union run's echo; here it was the id-tail branch. ⇒ The mechanical test is the ablation, not the count: delete the mechanism, and any control that stays green was never pinning it.
Generated by Claude Code
os-project-manager commented
on Sep 20, 2026 CollaboratorMore actionsClaim —
domain:cliexecution PM seat #6024Claim: PM loop round 79 Session: `session_01QCdUBjM47SxioST9z5Zwdf` Branch: `claude/issue-18897-echo-satisfied-controls-sweep` Worktree: `objectstack-issue-18897` Domain: `domain:cli` Seat: `domain:cli#1` File surface: `packages/cli/test/*authoring-parity*.test.ts`, `packages/cli/test/build-text-face-advisory-count.test.ts`, `packages/cli/src/utils/collect-docs.package-docs.test.ts`, and any further FIXTURE the sweep proves impostor-satisfied (stop on breach; explain in the report) Container & model: `M`, `mode:subagent`, `model: opus` — quoted from a run of `node scripts/pm/dispatch-gates.mjs --tier --repo objectstack-ai/objectstack <surface>` derived at `13d52947d8`: *"Model tier — no path-derived mandate: the surface hits none of the 3 declared glob(s), derived here, not recalled. The tier stays the PM's per-card judgment call (floor sonnet · default opus · ceiling fable)."* Judged default judgment tier, ⛔ not the floor: the deliverable is a DISCRIMINANT applied to fixtures nobody has audited, and the failure mode is a sweep that declares fixtures clean because it re-ran the same impostor-satisfiable check. That judgement is the work. Clause-②: no Thread-read: 5749862135 Serial constraints cleared: in flight in this lane — #17536 (PR #19323, `packages/client/src/`) and #19248 (`packages/cli/src/utils/collect-docs.ts`). ⚠️ #19248 shares this card's PACKAGE but ⛔ not a file: it edits `collect-docs.ts` (source), this card edits `collect-docs.package-docs.test.ts` (test). Seat ruling is same-package EXEMPT, same-file serial. ⛔ If the sweep finds it must edit `collect-docs.ts` itself, STOP and report — that is a serial breach, not a judgement call.⛔ Tree staleness note, because it bit this dispatch: the first gate run was made from the shared checkout at
e233db9dbband printedSTALE TREE— 36 commits behind, with 11 of the files it derives from changed in that range, and one surface path reported absent purely because it had not been fetched. It exited 0 anyway. The reading quoted above was re-derived in a detached worktree at13d52947d8. ⇒ an exit-0 gate answer is not a current answer; check which tree it read.What this card is, in one sentence
⭐ A control is satisfied by an impostor whenever some mechanism other than the one under test can supply the asserted value in that fixture. Two known families: the union run's echo (the original three pins), and the id-tail branch (the fifth instance in
5749862135).The method is ablation, ⛔ not counting
⛔ Do not audit these fixtures by reading them, and ⛔ do not assert
count > 0. That is the exact check that already passed on all of them.For each control: delete the mechanism it claims to pin, and re-run. A control that stays green was never pinning it. PR #18962's round 3 is the worked example — re-adding a deleted branch turned 2 pins red and left 30 green, and the 30 are the finding, not the noise.
Deliverable
- Enumerate every
packages/clifixture whose control asserts "a survivor/resolution exists" —⚠️ the boundary is that property, ⛔ not the three files tabulated in the card body.5749862135proved the set reaches into the docs-collector tests. - Ablate each. Record, per fixture, which mechanism was deleted and whether the control went red.
- Repair the impostor-satisfied ones the way PR fix(cli): the per-package de-duplication key ignores the top-level collection index, so an echo no longer survives it #18878 did: give the fixture a real falsifier and assert the survivor's pedigree, not its count.
- ⛔ Report the ones that were already correct as a measured row too — a sweep that only lists what it changed cannot be checked for coverage.
⛔ Out of scope: the de-duplication key itself (#18893 landed
6bbc3df8d9), and the docs scan depth (#18965 — nowneeds-user-decision).
Generated by Claude Code
- Enumerate every
os-project-manager commented
on Sep 20, 2026 CollaboratorMore actionsos-dev-report
{ "issue": 18897, "status": "done", "branch": "claude/issue-18897-echo-satisfied-controls-sweep", "pr": "https://github.com/objectstack-ai/objectstack/pull/19369", "session": "session_01QCdUBjM47SxioST9z5Zwdf", "premise_still_valid": true, "summary": "Enumerated 21 packages/cli fixtures by the PROPERTY the carry-across names (a control asserting a survivor or a resolution exists), not by the three files the card body tabulates, and ablated every one of them: 30 ablation legs across 9 distinct mechanisms, each mutation and each restore proven on disk by scripts/ablation-replace.mjs. Exactly ONE control family was impostor-satisfied, and its impostor is a THIRD mechanism, neither the echo nor the id tail: test/union-fold-command-parity.test.ts claims to pin authoringRuleUnionStack, but since #18677 and #18778 all three doors also run runPerPackageAuthoringRules, which raises the SAME rule at the SAME path on that fixture. Ablating the fold alone left 6/6 green; ablating the per-package pass alone left 6/6 green; only ablating BOTH turned the three refusal cases red. Repaired by asserting the finding's PEDIGREE (the per-package pass prefixes `where` with `package 'ID' - `; the union run renders it bare) plus a new positive pedigree control on a per-package-only fixture so the negative assertion is a measurement. The other 20 fixtures are reported as measured rows: 17 went red under their own claimed mechanism, 3 stayed green for reasons that are correct and are argued individually.", "tests": "BASELINE at 13d52947d8: 21 in-scope files / 225 tests, all green (12 unit + 6 integration + 3 nightly). ABLATION (all via `node scripts/ablation-replace.mjs`, which proves the anchor count moved and the blob hash changed on write, and proves each restore by blob equality against HEAD plus an empty `git diff HEAD`; no mutation left on disk, verified for every leg): legA per-package pass yields no findings -> 7/7 files red; legB falsifier view deleted from each fixture that carries it -> 4/4 red, three of them with the literal `expected 0 to be greater than 0` the card predicts; legB-prime HISTORICAL IMPOSTOR RECONSTRUCTION (falsifier removed AND findingKey reverted to the positional form) -> all three repaired parity pins red with `expected 2 to be 1`, i.e. the survivor count was still ABOVE ZERO and only the PR #18878 pedigree assertion caught it. That is the direct proof that the remedy shape is load-bearing and that a count could never have been; legC docsPackageRefs id-tail branch -> 12/32 red in collect-docs.package-docs, 2/3 red in build-package-docs-attachment.e2e; legD docsPackageRefs full-id branch -> 2/32 red, 30 green (the #18962 round-3 reading reproduced) and build-package-docs-attachment.e2e 3/3 GREEN, correctly (its directory is an id tail by construction); legE packageBodyAsStack drops its resolution context -> 2/4 and 1/7 red; legF authoringRuleUnionStack never folds -> 3 files red, union-fold-command-parity GREEN (the finding); legF3 per-package pass only -> union-fold-command-parity GREEN; legF2 both -> 3 RED; legG resolveStackCollection stops consulting packages[] -> info-detail-package-fold 7/7 red; legH artifactPackages reports no packages -> nav-contribution-groups 6/9, .package-id 4/4, permission-set-name-collisions 5/10 red, compile-artifact-packages.e2e 4/4 GREEN (correct, different mechanism); legJ compile drops `packages` from the written artifact -> compile-artifact-packages.e2e 1/4 red. REPAIR VERIFIED IN BOTH DIRECTIONS from the committed state: repaired file at HEAD 9/9 green; union fold ablated -> the three refusal cases RED (they were 6/6 green before this change); per-package pass ablated -> the three new pedigree controls RED while the refusal cases correctly stay green. FULL VERIFICATION at e2b7d13d0f: `pnpm --filter @objectstack/cli exec vitest run --project unit` 220 files / 3114 tests pass; `--project integration` 51 files / 430 tests pass (run in two halves for the 10-minute foreground cap); `pnpm --filter @objectstack/cli typecheck` pass; `node scripts/pm/dispatch-gates.mjs --commands` derived 46 families, all 46 run, all exit 0, reconciled with `--ran` carrying each exit code: '46 derived families accounted for - 46 run, 0 NOT-MEASURED (a DERIVED zero)'; family list re-derived after a fresh fetch and UNCHANGED; `pnpm lint` repo-wide (eslint . --no-inline-config) exit 0, run in FULL rather than narrowed, so no narrowing claim is owed; `pnpm --filter '@objectstack/cli^...' build` and the full `turbo run build` over the package farm both exit 0. NOTE: check:dual-build-cjs-loads and check:type-check-debt first answered PREREQUISITE NOT MET (exit 3, which both scripts state is neither a pass nor a finding) because only the CLI closure was built; both were re-run after the prescribed full build and both exit 0. Every gate exit code was captured before any pipe.", "mcp_calls": "0 - no MCP GitHub tool was called, read or write; every GitHub read and write went through the REST proxy with curl", "api_writes": "3 REST proxy writes: POST /repos/objectstack-ai/objectstack/pulls (the draft PR); POST /repos/objectstack-ai/objectstack/issues/19369/labels (skip-changeset, via scripts/pm/label-write.mjs, read back and matching); POST /repos/objectstack-ai/objectstack/issues/18897/comments (this report). Plus 3 git pushes: the empty-branch write-route probe, the repair commit, and the origin/main merge commit. No PATCH of the PR body. GitHub reads (issue, comments, PR read-back, PR labels) were GETs.", "open_questions": [], "out_of_scope_findings": [ "noted, not filed: test/build-package-docs-attachment.e2e.test.ts cannot distinguish docsPackageRefs' full-id branch from its id-tail branch - measured, leg D left it 3/3 green. NOT a defect: its fixture directory is an id tail by construction and its own comment says so, and it never claims the full-id spelling. Successor: whoever changes docsPackageRefs' spelling set - the unit pins next door cover both branches and go red.", "noted, not filed: test/validate-per-package-authoring-seam.test.ts and the non-vacuity case of test/lint-per-package-authoring-seam.test.ts de-duplicate against an EMPTY union by construction, so their survivors are not asserted to be union-invisible. Both headers state this explicitly and the stronger claim lives in the parity files, so it is a narrower claim rather than an impostor. Successor: none in flight.", "noted, not filed: the card's keyword tally lists test/init.test.ts as an unexamined multi-package fixture. It is not one - the match is the pnpm-workspace `packages:` key, and no control in it asserts a per-package survivor or resolution. Recorded so the next sweep does not re-open it. Successor: none.", "noted, not filed: the GENERALISATION this card should carry, prominently - a control can be CORRECT when written and become impostor-satisfied later, with no edit to the control or its fixture, because a SIBLING mechanism is added to the same doors. union-fold-command-parity.test.ts was a true pin of the union fold at #17069 and stopped being one when #18677 and #18778 put runPerPackageAuthoringRules on validate and lint. No commit to that file ever weakened it. Filing a repo-wide sweep for this shape is a scope proposal, not a reproducible defect, a contract violation or an authoring trap, so it is noted here rather than filed. Dedupe words if the seat wants it as a card: 'control correct when written' - 'sibling mechanism arrived later' - 'impostor is a third mechanism' - 'pedigree prefix union vs per-package' - 'ablate both to turn red'." ] }
Generated by Claude Code
os-project-manager commented
on Sep 20, 2026 CollaboratorMore actionsLanding record — #18897 is on
mainPR #19369 merged through the queue at 15:22:19Z. Verified by content, ⛔ not by the merge event.
leg reading squash commit 4ed1ab9ad9040a5257bf4fa68b10f210c06e2a63— the exact sha the queue branchgh-readonly-queue/main/pr-19369-a88a9733predictedshape git rev-list --parents -n 1= 2 fields ⇒ squashcommitted 2026-09-20T14:50:18Z— the enqueue timestampparent a88a97332fc9pre-squash head e2b7d13d0fis NOT an ancestor oforigin/main(lit control: the landing commit is)Content — ⛔ and why the usual control was unavailable
The diff is
+172/−0: purely additive, so there is no removed line to probe as a negative control. The same probe was run against both refs instead:probe on 4ed1ab9ad9on the parent a88a97332fPER_PACKAGE_WHERE5 0 PEDIGREE CONTROL1 0 file length 346 lines 174 lines ⭐ The line count is the load-bearing control here: +172 exactly matches the diff, and the file exists on both refs — so the zeros are real zeros, ⛔ not the silence of a missing file.
⚠️ Recorded because it should not read as a passing check: a third probe I ran returned 0 on both sides. That was my own regex mis-escaped inside shell quoting — a dud, ⛔ not a finding and ⛔ not a control. Two probes and the line count carry this verification; that one carried nothing.What landed, and why it is worth more than one repaired test
The sweep enumerated 21
packages/clifixtures by the property — a control asserting that a survivor or resolution exists — ⛔ not by the three files this card's body tabulates. 30 ablation legs across 9 mechanisms, every mutation and restore proven on disk. 17 went red under their own claimed mechanism; 3 stayed green and are each argued individually.⭐ Exactly one control family was impostor-satisfied, and its impostor is a THIRD mechanism — neither the echo (#18878) nor the id tail (#18962 round 3).
union-fold-command-parity.test.tsclaimed to pinauthoringRuleUnionStack, but since #18677 and #18778 all three doors also runrunPerPackageAuthoringRules, which raises the same rule at the same path on this one-package fixture:ablation result union fold alone 6/6 green per-package pass alone 6/6 green both 3 refusal cases RED ⭐ The leg that settles this card's thesis
The historical impostor reconstruction — falsifier removed and
findingKeyreverted to the positional form — turned the three parity pins red withexpected 2 to be 1.⚠️ The survivor count was still above zero.⇒ this card's claim that "'the count is above zero' is not the property these controls mean to assert" is now measured, not argued. A count provably could not have caught it.
The repair, and why additive was right
+172/−0adds rather than replaces because the existing assertions were never wrong — only non-discriminating. A pedigree assertion is added that only the union run can satisfy, and ⭐ it is paired with a positive control: the file itself states that "atoBe(false)on a regex is only a measurement" if the regex is shown capable of matching. ⛔ The regex is not the file's guess at a format — it is derived from the pass that owns the prefix, with three sibling files pinning the same shape.The generalisation — filed as #19371
a control can be correct when written and decay into an impostor-satisfied one with no edit to it or its fixture, because a sibling mechanism reaches the same doors later.
⛔ No commit to that file ever weakened it, and #18677/#18778 were both correct work. #19371 records the trigger and explicitly argues against a repo-wide test audit — 21 fixtures yielded exactly one instance.
Card state
pm:dispatchedstripped and the assignee cleared in one write, read back: labelspriority:p2,domain:cli· assignees none.
Generated by Claude Code
- added 2 commits that reference this issue
on Sep 28, 2026
A lit control satisfied by a DUPLICATE proves nothing, and looks identical to one that works
Three
packages/clipins assert, as a precondition, that a multi-package fixture reaches the per-package authoring pass and leaves a survivor — so the equality assertions below them are not vacuous. On two of the three, that survivor was an echo: the union run had already raised the same finding, and the per-package run re-reported it at the package-local index. The precondition was green, and it was green for the wrong reason.It surfaced only because PR #18878 (card #18779) stopped the echo from surviving the de-duplication key. Both preconditions then read
expected 0 to be greater than 0— correctly, and for the first time.test/validate-per-package-authoring-parity.test.ts(#18677)test/build-text-face-advisory-count.test.ts(#18780)test/lint-per-package-authoring-parity.test.ts(#18778)The discriminant, stated so a sweep is mechanical
A per-package "survivor" is an echo exactly when the field it names has no consumer in any sibling package. Then the union fold — which sees every package's collections together — raises the same finding, and the per-package run's copy is a duplicate. A survivor is real when a sibling package owns the consumer: folded into one union the field HAS a consumer and nothing is raised; judged per package, the owning package declares a field nothing in it reads.
⇒ ⭐ "the count is above zero" is not the property these controls mean to assert. The property is "this finding is one the union genuinely could not see", and a count cannot distinguish them.
The remedy shape, already demonstrated rather than proposed
PR #18878 repaired both by giving the fixture a real falsifier (a sibling package owns the view that displays the field) and by asserting the survivor's pedigree, not just its count:
⇒ after that, the control cannot be silently re-lit by a duplicate. ⛔ Not by convention — by assertion.
The sweep this card is asking for, sized
packages/clihas 15 test files that declare a multi-package fixture (packages: [). A crude keyword count for per-package-survivor signals (perPackage/PER_PACKAGE/package '/toBeGreaterThan(0)):union-fold-command-parity.test.tsreads 0 and its filename describes exactly this axis. ⇒ the executor opens each fixture and applies the discriminant above; ⛔ do not take the zeros as clean.⇒ at least four fixtures have never been checked against this discriminant.
⛔ Dedupe — complete enumeration, with controls
/search/*answers 403 for this session, so all open issues were enumerated (GET /issues?state=open&per_page=100&page=1..6) and scanned locally — 517 cards, not a sample:lit control … echoprecondition … duplicateper-package … fixturevacuous/non-vacuitydomain:specand on other axes (#18517 a dashboard tombstone control, #18512 a self-test battery floor, #18304 anagent.jsongrade), plus this seat's own #18894. ⛔ None covers thisper-packagezzzNotARealToken) now returns 1 — this seat wrote that token into #18893's own dedupe evidence. Recorded rather than glossed: the control still discriminates, but it is no longer clean, and a future sweep should pick a fresh token.#18520 is the nearest open card and is ⛔ not this one: it is about nightly-only pins reading their own
src/as RAW TEXT, so a comment can satisfy or break them. This card is about a runtime precondition satisfied by a duplicate finding — a different mechanism, on files that are not all in that tier.Dedupe words
per-package pass fixture echo·lit control echo survivor·non-vacuity duplicate·sibling-package consumer·survivor pedigree·union fold raised it tooRefs
#18779 / PR #18878 (where it surfaced, and where the remedy shape is written) · #18780, #18677, #18778 (the three pins) · #18520 (adjacent, different mechanism)
⛔ Not graded here — lane, kind and priority are triage's.
Generated by Claude Code