立卡门 ① — a defect in a shipped artifact's only guard.
finding — filed by the domain:spec execution seat 1 (session session_013RDBh5DqXd2xnLwvHLgLFr, seat post #6017) from the out_of_scope_findings of the #19523 round (PR #19752). The platform dates this card. ⛔ Ungraded and unrouted: domain:*, type and priority are triage's. ⛔ Not claimed.
What is missing
packages/spec/src/migrations/registry.ts is the generated concatenation of packages/spec/src/migrations/entries/**. The only gate that proves the two agree is check:migration-registry.
It runs in no CI workflow step. Measured at origin/main @ c120dbdfb8:
| script |
occurrences in .github/workflows/ |
check:migration-registry |
0 |
check:upgrade-guide |
2 |
check:spec-changes |
3 |
check:api-surface |
4 |
⇒ the three sibling generated-artifact gates are wired; this one is not. Firing control: the same instrument returns 2 / 3 / 4 for those siblings, so it can see a gate when one is wired. Dark control: check:migration-registryy ⇒ 0.
⛔ It is not an unknown or dead script. It is declared — packages/spec/package.json — and it is classified in the generated-artifact ledger at packages/spec/scripts/check-generated.ts. ⇒ a known, intended gate that nothing runs.
⚠️ And the aggregate does not cover it. The only check:generated invocation in CI is .github/workflows/lint.yml — pnpm --filter @objectstack/spec check:generated --reconcile-only. That reconciles that every check:/gen: script is classified in the ledger; it does ⛔ not check that the artefacts are current. So the meta-gate is green precisely because the script is properly registered — while nothing ever asks whether the registry matches the entries.
⭐ The repro is a card that just paid for it
Card #19523 corrects the prose of a shipped ADR-0087 semantic entry. Its first round edited the entry file and pushed 51687e1440, with every derived gate green.
Measured on that tree by the round that followed, over the four dist bundles under the files[] entry dist:
| tree |
the OLD (false) sentence in dist |
the corrected sentence in dist |
dark control |
registry as committed at 51687e1440 |
4 |
0 |
8 |
| registry regenerated |
0 |
4 |
8 |
⇒ the corrected prose reached consumers zero times, the false sentence was still shipping, and CI was green. The dark control is unchanged across both legs, so the movement is attributable to the regeneration and nothing else.
That is not a near miss: the card needed a whole second round purely because nothing mechanical said the registry was stale.
Why it reaches users, not just contributors
packages/spec/src/migrations/entries/** is generator input only — it is not in the package's files[], and nothing imports it but the generator and two pin tests. registry.ts is what packages/spec/src/migrations/chain.ts and index.ts import, and it is what dist is built from. ⇒ a stale registry is a published artefact that disagrees with its own source, and the CLI's migration output reads the registry's copy.
Related, ⛔ NOT duplicates — same file, different mechanisms
⛔ Neither is this defect, and both are closed. 同族异缺陷 ⇒ ⛔ 不并.
Dedupe — query run by this filer
⛔ /search/issues not used: this container's proxy refuses it with a body carrying no total_count, so a naive parse prints a clean-looking zero. Repo-scoped semantic search was used instead; ⚠️ it ranks by relevance, so its total_count is ⛔ not a count of matching cards.
- query:
check:migration-registry runs in no CI workflow so a stale migrations registry.ts ships with CI green → the two cards above, both closed, neither this defect. ⛔ No open card names this gap.
⛔ What is NOT claimed
- ⛔ No fix prescribed. Wiring it into an existing lint/gate job, deriving it for the cards that touch
migrations/entries/**, or folding it into the check:generated artefact pass are different calls with different blast radii. ⛔ This seat picks none.
- ⛔ No census of how often a stale registry has shipped. This card measures the missing wiring and one repro, ⛔ not a history.
- ⚠️ Radius:
.github/workflows/ at origin/main. Whether some other runner, hook or script invokes the gate outside that directory is ⛔ not established here.
Dedupe words: check:migration-registry, registry.ts stale, check:generated --reconcile-only, migration entries not regenerated, generated artifact gate missing from CI
Generated by Claude Code
立卡门 ① — a defect in a shipped artifact's only guard.
finding— filed by thedomain:specexecution seat 1 (sessionsession_013RDBh5DqXd2xnLwvHLgLFr, seat post #6017) from theout_of_scope_findingsof the #19523 round (PR #19752). The platform dates this card. ⛔ Ungraded and unrouted:domain:*,typeandpriorityare triage's. ⛔ Not claimed.What is missing
packages/spec/src/migrations/registry.tsis the generated concatenation ofpackages/spec/src/migrations/entries/**. The only gate that proves the two agree ischeck:migration-registry.It runs in no CI workflow step. Measured at
origin/main@c120dbdfb8:.github/workflows/check:migration-registrycheck:upgrade-guidecheck:spec-changescheck:api-surface⇒ the three sibling generated-artifact gates are wired; this one is not. Firing control: the same instrument returns 2 / 3 / 4 for those siblings, so it can see a gate when one is wired. Dark control:
check:migration-registryy⇒ 0.⛔ It is not an unknown or dead script. It is declared —
packages/spec/package.json— and it is classified in the generated-artifact ledger atpackages/spec/scripts/check-generated.ts. ⇒ a known, intended gate that nothing runs.check:generatedinvocation in CI is.github/workflows/lint.yml—pnpm --filter @objectstack/spec check:generated --reconcile-only. That reconciles that everycheck:/gen:script is classified in the ledger; it does ⛔ not check that the artefacts are current. So the meta-gate is green precisely because the script is properly registered — while nothing ever asks whether the registry matches the entries.⭐ The repro is a card that just paid for it
Card #19523 corrects the prose of a shipped ADR-0087 semantic entry. Its first round edited the entry file and pushed
51687e1440, with every derived gate green.Measured on that tree by the round that followed, over the four
distbundles under thefiles[]entrydist:distdist51687e1440⇒ the corrected prose reached consumers zero times, the false sentence was still shipping, and CI was green. The dark control is unchanged across both legs, so the movement is attributable to the regeneration and nothing else.
That is not a near miss: the card needed a whole second round purely because nothing mechanical said the registry was stale.
Why it reaches users, not just contributors
packages/spec/src/migrations/entries/**is generator input only — it is not in the package'sfiles[], and nothing imports it but the generator and two pin tests.registry.tsis whatpackages/spec/src/migrations/chain.tsandindex.tsimport, and it is whatdistis built from. ⇒ a stale registry is a published artefact that disagrees with its own source, and the CLI's migration output reads the registry's copy.Related, ⛔ NOT duplicates — same file, different mechanisms
migrations/registry.tsmixes generated regions with hand-authored ones, so the documented merge remedy silently dropsstep18.conversionIds— 115 gates stayed green; only a chain-replay test caught it #18062 (closednot_planned) —registry.tsmixes generated regions with hand-authored ones, so the documented merge remedy silently dropsstep18.conversionIds. ⭐ Worth reading beside this card: it recorded that 「the 115-family gate sweep was GREEN」 on a tree with a real, behavioural registry defect, and that only a chain-replay test caught it. That is the same blind spot measured from a different direction — but its subject is the merge hazard, ⛔ not the missing CI wiring.migrations/registry.tsstill text-merges: two ADR-0087 entries with adjacent ids conflict server-side, which is the residue #7297's source sharding could not reach #8360 (closednot_planned) —registry.tstext-merges; two entries with adjacent ids conflict server-side. Different mechanism again.⛔ Neither is this defect, and both are closed. 同族异缺陷 ⇒ ⛔ 不并.
Dedupe — query run by this filer
⛔⚠️ it ranks by relevance, so its
/search/issuesnot used: this container's proxy refuses it with a body carrying nototal_count, so a naive parse prints a clean-looking zero. Repo-scoped semantic search was used instead;total_countis ⛔ not a count of matching cards.check:migration-registryruns in no CI workflow so a stale migrations registry.ts ships with CI green → the two cards above, both closed, neither this defect. ⛔ No open card names this gap.⛔ What is NOT claimed
migrations/entries/**, or folding it into thecheck:generatedartefact pass are different calls with different blast radii. ⛔ This seat picks none..github/workflows/atorigin/main. Whether some other runner, hook or script invokes the gate outside that directory is ⛔ not established here.Dedupe words:
check:migration-registry,registry.ts stale,check:generated --reconcile-only,migration entries not regenerated,generated artifact gate missing from CIGenerated by Claude Code