Skip to content

test(cli): read the emitJson exit count off the source in the two os validate --json pins - #18880

Merged
os-support-ai merged 1 commit into
mainfrom
claude/issue-18848-validate-emitjson-exit-count-pins
Sep 18, 2026
Merged

os-support-ai merged 1 commit into
mainfrom
claude/issue-18848-validate-emitjson-exit-count-pins

Conversation

@os-support-ai

Copy link
Copy Markdown
Collaborator

Fixes #18848

Clause-②: no — the diff is two files under packages/cli/test/, no governed surface (docs/adr/**, .claude/**, skills/**, AGENTS.md, CLAUDE.md). Declared from the diff, and it agrees with the claim comment's declaration from the card.

packages/cli/src/commands/validate.ts is untouched — read only, never written. The seventh exit is correct and stays.

What was actually wrong

validate.ts has 7 await emitJson( exits; two nightly-only pins asserted 6.

reading value
await emitJson( exits in validate.ts at b0b5f31cc6 7 (:286 :364 :434 :517 :554 :661 :762)
control at 095c7f60ae^ (pre-#18769) 6
what both pins asserted toHaveLength(6)
exits carrying warnings: 7 of 7
exits carrying conversions: 7 of 7

⇒ both CONTRACTS these two files exist for still hold. Only the COUNT was stale. Re-measured independently here and the dispatching seat's figures reproduce exactly.

The seventh exit came with #18769 and is legitimate. Its payload carries both keys.

The choice: DERIVED, not 7

The claim asked for the option taken and the cost of the rejected one.

Rejected — toHaveLength(7). It is one character of work and it is wrong for a measurable reason. It re-arms the identical trap for exit eight, and the trap is not theoretical: it just cost a night of red main and was about to cost a duplicate p1 card. Its cost is not only that it rots, but where it rots — see the tier reading below. And it is strictly weaker: ablation C is a validate.ts with eight call sites where a pin of 7 reads green while the file has an exit no assertion in the family covers.

Taken — read the count off the source. The extractor must produce one payload literal per emitJson call site the file actually has:

callSites = every `emitJson` call in SRC, matched with a word boundary,
            optional whitespace, then the opening paren
expect(literals).toHaveLength(callSites.length)

Both sides read raw source, which keeps them symmetric: a commented-out await emitJson( is counted by the extractor and by the pattern alike. The one asymmetric case — prose naming the call with its paren but no await — reddens, and that is the accepted price for not importing a comment masker into these two files.

Nothing is skipped, disabled, quarantined or deleted. The count assertion is still there, the success/failure partition is still there, the contract negative is still there:

The tier, measured in BOTH directions

Not inferred from the workflow YAML — collected, on this branch, in packages/cli:

OS_TEST_TIERS files vitest collects these two pins among them
unset (pull request · merge queue · local default) 266 0
nightly 68 2 — both, in the integration project

⇒ the pins are not "a red nobody looks at". In the queue population they are not collected at all. No pull request and no merge-queue run could have reddened on this, which is why #18769's own CI was green and correct. That is a measurement for #18520, not a new card — it is in the report for the seat.

Red → green, in the nightly tier itself

Not a substitute: the tier the pins actually live in, reached locally with OS_TEST_TIERS=nightly.

Before (at b0b5f31cc6, pre-fix):

FAIL |integration| test/validate-json-failure-conversions.e2e.test.ts
  AssertionError: the `emitJson` exit count moved — a new exit must carry
  `conversions` too: expected [ …(7) ] to have a length of 6 but got 7
FAIL |integration| test/validate-json-failure-warnings.e2e.test.ts
  AssertionError: … expected [ …(7) ] to have a length of 6 but got 7

Test Files  2 failed (2)      Tests  2 failed | 5 passed | 16 skipped (23)

This is also the first runner-level reproduction of this card: the filing seat stated it had no install and relayed the PR run's result instead.

After:

Test Files  4 passed (4)      Tests  14 passed | 36 skipped (50)

Four files, because the run also carries the two build-json-failure-* siblings — see acceptance notes.

Ablation — four legs, mutation proven on disk, restore proven byte-exact

Run from the committed fix. The mutation is confined to my own two test files (the SRC seed), driven by env var; validate.ts is never written. trap … EXIT INT TERM, absolute paths, and the restore is verified by git diff HEAD empty and git hash-object equal to the HEAD blob hash (non-empty, both files).

leg mutation expected observed
A an 8th exit, await, carrying both keys — an honest addition green green — 2 files, 7 passed
B an 8th exit missing warnings: warnings red, conversions green exactly that — expected [ Array(1) ] to deeply equal []
C an 8th call site spelled without await derived equality red both red — an `emitJson(` call site the payload extractor could not read: expected [ …(7) ] to have a length of 8 but got 7
D source truncated to 5 exits floor red both red — expected 5 to be greater than or equal to 6

Leg A is the fix doing its job: a hard-coded 7 is red here. Leg C is the capability the rejected option does not have at all — the extractor reports 7, so toHaveLength(7) passes while the file carries an exit no assertion covers. Leg B proves deriving the count weakened nothing: the contract still bites over the added exit, and the two files isolate from each other. Leg D proves the remaining integer is live.

A first ablation attempt exited 127 on a wrong vitest path — the mutation landed but nothing ran, so those readings were void and discarded rather than reported. The table above is the re-run.

Changeset

skip-changeset. Measured, not assumed — nothing published moves:

  • packages/cli files[] is ["dist", "README.md", "CHANGELOG.md"]; tsconfig.build.json has include: ["src"], so test/ is outside the compiled tree entirely.
  • npm pack --dry-run --json: 0 published paths under test/ or src/. Instrument lit by the positive control README.md, which is present.
  • ⚠️ The dist/ positive control was not lit in the worktree where that manifest was taken (no build yet at that point). The include: ["src"] boundary is what carries the negative, and the closure build reading is in the report.

Acceptance notes — noted, not filed

An instruction conflict, named rather than quietly resolved

Triage comment 5723031597 pinned the dispatch order: land the two-line literal repair first, and take the "does an integer pin belong here at all" question as a second, separate stroke. The claim comment 5724808732 instead hands the choice to the deliverer and says ⛔ not to reflexively hard-code 7.

I took the claim's instruction, because the thing triage was protecting against is not in play: the derived form is the same edit in the same assertion slot, measured and proven in this run, and it delays the red main by nothing. The design question triage deferred — whether these files belong in the core tier, or the tier's path filter should name validate.ts — is untouched here and remains the cli lane's call.

Verification

OS_TEST_TIERS measured in both directions · red→green in the nightly tier · four ablation legs · gate families derived with scripts/pm/dispatch-gates.mjs and reconciled with --ran. Full readings, including anything that came back NOT MEASURED, are in the os-dev-report comment on #18848.


Generated by Claude Code

…os validate --json` pins

`validate.ts` has SEVEN `await emitJson(` exits; both nightly-only pins
asserted SIX, so `main`'s nightly tier has been red since the seventh exit
landed with #18769 — with no run able to say so, because these files are
nightly-tier by NAME and a `packages/cli/**` diff never triggers that
workflow.

Both CONTRACTS the two files exist for still hold: every one of the seven
exits carries `warnings` AND `conversions`. Only the COUNT was stale.

So the integer is not re-pinned to 7 — that re-arms the identical trap for
exit eight, and only a cron would ever read it. It is derived instead: the
extractor must produce one payload literal per `emitJson` call site the file
actually has, whatever today's number is. That is strictly stronger than an
integer — it also catches a call site the extractor CANNOT see (one spelled
without `await`), which a hard-coded count reads as green.

The one integer left is demoted from an equality to a floor (six, the
population the #12047 / #12125 rulings were made over). It rots only in the
direction that has to be reviewed anyway — exits being removed — and it
floors the derived pair away from the single vacuum they share, an `emitJson`
renamed out of existence taking both sides to zero.

Nothing is skipped, disabled or deleted: the count assertion, the
success/failure partition and the contract negative are all still there.
`validate.ts` is untouched.

Measured on this branch, `packages/cli`:
  OS_TEST_TIERS unset   266 files collected, ZERO of them these two
  OS_TEST_TIERS=nightly  68 files collected, both of them present

Claude-Session: https://claude.ai/code/session_01DvvamiacK328idtBYJBxV3
Co-authored-by: Claude <noreply@anthropic.com>
@os-support-ai os-support-ai added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 18, 2026 — with Claude
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs.

What this run could not see
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 0b31d90fb37d490d7da12c7acd4b14c4feb22501 → packageMentionDocs.

@github-actions github-actions Bot added the tests label Sep 18, 2026
@os-support-ai
os-support-ai marked this pull request as ready for review September 18, 2026 04:32
@os-support-ai
os-support-ai added this pull request to the merge queue Sep 18, 2026
Merged via the queue into main with commit 84ba4a8 Sep 18, 2026
40 checks passed
@os-support-ai
os-support-ai deleted the claude/issue-18848-validate-emitjson-exit-count-pins branch September 18, 2026 04:55
os-support-ai pushed a commit that referenced this pull request Sep 18, 2026
… so an honest new exit cannot red `main` at night

`build-json-failure-{warnings,conversions}.e2e.test.ts` each froze three
integers read off `packages/cli/src/commands/compile.ts` — 11 payload
literals, 10 `success: false`, 1 `success: true`. All six were correct; the
defect is the shape. Both files are nightly-tier by name, so the pull request
that adds an honest twelfth exit cannot collect them (measured: `OS_TEST_TIERS`
unset collects 267 files in this package with zero of these two among them,
`=nightly` collects 68 with both), merges green, and leaves `main` red until a
cron says so — the #18848 incident, pre-staged.

Ported from the shape PR #18880 landed on the `validate-json-failure-*` pair:
the count is derived (`toHaveLength(callSites.length)` against a word-boundary
`emitJson` call-site match over the same masked source the extractor reads),
the old integer is demoted to a `toBeGreaterThanOrEqual(10)` floor that rots
only in the exits-are-removed direction, and one partition assertion
(`success: true` ×1, `success: false` = `literals.length - 1`) replaces the two
frozen counts.

The verdict key was re-derived rather than copied: `compile.ts` spells it
`success:`, not the `valid:` of `validate.ts` — measured over the 11 masked
payload literals, `success: false` 10 / `success: true` 1 / `valid:` 0.

Claude-Session: https://claude.ai/code/session_01DvvamiacK328idtBYJBxV3
Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Sep 28, 2026
… so an honest new exit cannot red `main` at night (objectstack-ai#18966)

Fixes objectstack-ai#18894

Clause-②: no

## What this changes

`packages/cli/test/build-json-failure-warnings.e2e.test.ts` and
`packages/cli/test/build-json-failure-conversions.e2e.test.ts` each
froze three integers read
off `packages/cli/src/commands/compile.ts` — 11 payload literals, 10
`success: false`,
1 `success: true`. **All six were correct**, and that is the defect: the
*shape*, not a stale
number. One honest new exit — the very thing these two files exist to
enforce — turns all six
red, and because both files are nightly-tier by NAME they turn red only
at night, hours after
the PR that did it has merged. That is objectstack-ai#18848's `priority:p1` pre-staged
on `compile.ts`.

Ported from the shape PR objectstack-ai#18880 landed on the sibling
`validate-json-failure-*` pair:

- the count is **derived** — `toHaveLength(callSites.length)` against a
word-boundary
`emitJson` call-site match over **the same masked source** the payload
extractor reads;
- the old integer is demoted to a **floor**,
`toBeGreaterThanOrEqual(10)`, which rots only in
  the exits-are-REMOVED direction;
- one **partition** assertion (`success: true` ×1, `success: false` =
`literals.length - 1`)
  replaces the two frozen counts.

⛔ No production file is touched. The diff is those two test files and
nothing else —
`compile.ts` is card objectstack-ai#18431's carrier (branch `ccdc9f5389`) and is left
alone.

## Premises, re-measured on `origin/main` before a line was written

Re-derived with the tests' OWN extractor against the masked `compile.ts`
at
`f112a740bd` (`origin/main` at branch point), ⛔ not inherited from the
card:

```
payload literals          11      the pins' 11 was correct
success: false            10      correct
success: true              1      correct
/\bemitJson\s*\(/g        11      symmetric with the extractor
```

**Collection, re-measured in this worktree** (`vitest list --filesOnly`,
`packages/cli`):
`OS_TEST_TIERS` unset ⇒ 267 files, **0** of these two among them, lit
control
`artifact-packages.test.ts` present; `=nightly` ⇒ 68 files, **both**
present, lit control
absent. Both files sit in the `integration` project (`--project unit`
collects 0 of them).

## ⚠️ The trap this card names — the verdict key, MEASURED not copied

**`compile.ts` spells its verdict key `success:`. `validate.ts` spells
it `valid:`.** Measured
over the 11 masked payload literals of `compile.ts`:

| needle | count |
|:--|--:|
| `success: false` | 10 |
| `success: true` | 1 |
| `valid: false` | **0** |
| `valid: true` | **0** |

A verbatim port of objectstack-ai#18880's two partition lines would have asserted over
an **empty
population**. The lines here read `success:`, and the reading is
recorded in the code comment
beside them so the next author does not have to re-derive it.

## The symmetry the derived form needs — every `emitJson` occurrence
enumerated

The looser `/\bemitJson\s*\(/g` can only be trusted equal to the
extractor's
`await emitJson(` needle if nothing else in the file matches it.
Enumerated with left context
on `compile.ts`, **13 raw occurrences**:

| where | reading |
|:--|:--|
| `:43` | `emitJson,` — an **import** from `../utils/format.js`. No
paren ⇒ matches neither side. |
| `:104`, `:694` | prose inside comments — the shared `maskComments`
blanks both (objectstack-ai#18520, applied to these two files by objectstack-ai#18924) |
| the other 10 | `await emitJson(` call sites, plus the multi-line ones
⇒ 11 payload literals |

⭐ `emitJson` is **IMPORTED here, never declared** — there is no
`function emitJson(` in
`compile.ts` (grep: zero hits for `function emitJson` / `const
emitJson`), so the looser
pattern cannot over-count and red the pin by construction. Raw and
masked agree: 11 literals,
11 call sites, both ways. That agreement is a **reading, not a law**,
and the derived equality
is exactly where a future file that broke it would report.

## The floor's anchor — 10, and why not 11

objectstack-ai#18880 chose "the population the governing ruling was made over", not
today's count. The
equivalent anchor here is the commit that landed each file's ruling,
read out of git:

| file | ruling | landed by | count pinned that day |
|:--|:--|:--|--:|
| `build-json-failure-warnings.e2e.test.ts` | maintainer, 2026-08-25,
option 1 (objectstack-ai#11772) | `d114d5e140` (objectstack-ai#12079) | `toHaveLength(10)` — 9
failure + 1 success |
| `build-json-failure-conversions.e2e.test.ts` | the same 2026-08-25
ruling applied to `conversions` (objectstack-ai#12125) | `79cf692b0e` (objectstack-ai#12285) |
`toHaveLength(10)` — "all nine of its failure exits" + 1 |

Control for the anchor rule: the sibling
`validate-json-failure-warnings.e2e.test.ts` was
created at `33e81a5fe0` (objectstack-ai#12130) pinning `toHaveLength(6)`, and objectstack-ai#18880's
floor is `6`. Same
rule, same arithmetic. ⇒ **the floor here is 10.** Today's eleventh exit
is ADR-0130 D4's
per-package author-time rule leg (objectstack-ai#14439), which arrived *after* the
ruling — exactly what a
derived count absorbs and a frozen one trips over.

## Ablation battery — every leg's mutation proven on disk, every restore
proven by hash

Harness: a bash trap on EXIT, INT and TERM whose handler is the restore
function, absolute paths, restore is
`git checkout HEAD -- PATH` (never a bare `git checkout --`), verified
by comparing
`git hash-object` against the HEAD blob hash **and** by `git diff HEAD`
being empty. Each leg
prints the extractor's counts BEFORE and AFTER the mutation and a marker
grep, so a no-op leg
is refused rather than read as green. All runs `OS_TEST_TIERS=nightly`,
exit codes captured
before any pipe. No rebuild is needed or done: both files read
`compile.ts` from disk and the
CLI is loaded from `src/` through `bin/run-dev.js`, as each file's own
header states.

| leg | mutation to `compile.ts` | measured on disk after | THIS branch
| the frozen `11/10/1` |
|:--|:--|:--|:--|:--|
| 0 control | none | literals 11 · sites 11 | **GREEN** 7/7 | — |
| A | honest 12th exit carrying **both** keys | literals 12 · sites 12 |
**GREEN** 7/7 | **RED** — `expected [ …(12) ] to have a length of 11`
(both files) |
| B | 12th exit **missing** both keys | literals 12 · sites 12 | **RED**
— `an os build --json exit publishes no warnings` / `no conversions` | —
|
| C | 12th call site spelled **without `await`** | literals 11 · sites
**12** | **RED** — `an emitJson( call site the payload extractor could
not read: expected [ …(11) ] to have a length of 12` | **GREEN** 7/7 |
| D | two exits deleted (truncation) | literals 9 · sites 9 | **RED** —
`publishes fewer exits than the ruling above was made over: expected 9
to be greater than or equal to 10` | — |

⭐ **Leg C is the one that decides it.** A twelfth call site the payload
extractor cannot read
leaves the frozen integer **green** and reddens the derived equality.
The frozen form is not a
parallel option — it is strictly weaker. Leg A is the mirror: the honest
exit this contract
exists to welcome now stays green instead of reddening `main` at 20:44Z.

The "old" arms of A and C ran the pre-change files restored
worktree-only with
`git restore --source=f112a740bd -- PATH`, hashes printed and matched
against the BASE blobs,
then reset with `git checkout HEAD -- PATH`.

## `skip-changeset`, by measurement with controls both ways

`packages/cli` `files[]` is `["dist","README.md","CHANGELOG.md"]`;
`tsconfig.build.json` has
`rootDir: "src"`, `include: ["src"]` and an `exclude` that drops every
`*.test.ts`. Measured
against the freshly built `packages/cli/dist`:

| probe | direction | hits in `dist/` |
|:--|:--|--:|
| `an emitJson( call site the payload extractor could not read` | new,
this diff | **0** |
| `publishes fewer exits than the ruling above was made over` | new,
this diff | **0** |
| `ABLATION` | new, this diff | **0** |
| `access matrix drift` | positive control, lives in
`src/commands/compile.ts` | 1 |
| `warningsSoFar` | positive control | 2 |
| `runtime bundle failed` | positive control | 1 |
| `build-json-failure` | ⚠️ 1 hit — `dist/commands/compile.js:621`, a
**comment** compiled from `src/commands/compile.ts:698` that names the
test file. Not this diff's content; `compile.ts` is untouched. | 1 |

The positive controls prove the grep was reading `dist`. Nothing this
diff adds reaches any
published path from any released package ⇒ `skip-changeset`, label
applied on this PR.

## ⚠️ The adjacent axis — a POSITION, not a silent widening

Comment 5726117707 on the card asked for a judgement on the byte-exact
multi-line spread ORDER
pin, and warned its own probe was narrow. **Re-derived here with a
different predicate**
(`expect(SRC)` / `SRC.match` / `SRC.indexOf` across all four files),
which finds MORE than the
seat's word probe did — including one in
`validate-json-failure-conversions.e2e.test.ts`, where
the seat's probe scored 0 and recorded it as **未判**:

| file | line | what it binds byte-exactly |
|:--|--:|:--|
| `build-json-failure-warnings.e2e.test.ts` | `:536` `:537` | `const
warningsSoFar = () => [` , and the 4-member spread ORDER |
| `build-json-failure-conversions.e2e.test.ts` | `:450` | sink
declaration + blank line + `try {` adjacency |
| `validate-json-failure-warnings.e2e.test.ts` | `:571` `:572` | the
same two, 5 members |
| `validate-json-failure-conversions.e2e.test.ts` | `:486` | the same
adjacency ⇐ **the seat's 0 was 未判, not absent** |

**Judgement: named, measured, and left to the seat — deliberately NOT
done in this PR.**
Against the lane's standing three-rung ruling (claim 5725386686 on
objectstack-ai#18520):

- **Rung 1** — 「⛔ nightly-only 的 pin 永不绑一个逐 PR 兄弟已经绑着的字节精确拼写。」 Its
precondition is measured **FALSE**. Repo-wide, the only other reader of
those four list
identifiers is `build-json-advisory-parity.e2e.test.ts`, which is itself
**nightly-tier**
and compares with `new Set(...)` — order-blind by construction. No
per-PR sibling binds this
order behaviourally or textually. ⇒ rung 1 does not authorise deleting
it.
- **Rung 2** — 「⭐ nightly-only 的 pin 绑那条性质本身,从源码推导 —— 读出来的计数、分区、下限
—— ⛔ 永不绑一个写死的数。」 It governs frozen **numbers**. The order pin binds a
*spelling*.
⇒ rung 2 does not reach it; this PR discharges rung 2 for the counts,
which is this card.
- **Rung 3** — 「⭐ 一个读原始源码文本的读者,要么能把代码和散文分开,要么就不该对位置/顺序下
断言。」 Already satisfied: PR objectstack-ai#18924 put the shared `maskComments` in place
on both files. ⛔
  Not re-added here.

⇒ Under the ruling **as written and as measured**, the order pin in
these two files is
currently compliant and needs no change. What is *not* settled is a
rung-1 **extension**: may a
nightly-only pin bind a byte-exact spelling when **no** per-PR sibling
binds the property at
all? That is a new question, not an application of the existing three
rungs, and it sits
identically on the `validate-json-failure-*` pair, **which has no
carrier card**. Widening this
PR to answer it would convert half a family under a rule nobody has made
yet. Handed to the
`domain:cli` seat as a finding with dedupe words.

## Verification

Measured on `git rev-parse --short HEAD` = `0eb90c0a91`, in worktree
`/home/user/objectstack-issue-18894`, branched from `origin/main` at
`f112a740bd`.

| what | how | result |
|:--|:--|:--|
| the two files, BEFORE the edit | `OS_TEST_TIERS=nightly … --project
integration` on both files | **27 passed (27)** — the pins were correct,
as the card said |
| the two files, AFTER the edit | same | **27 passed (27)** |
| `packages/cli` WHOLE, default tier | `pnpm --filter @objectstack/cli
test` (bare `vitest run`, ⛔ no `--project`) | **267 files / 3485 tests
passed** |
| `packages/cli` WHOLE, nightly tier | `OS_TEST_TIERS=nightly pnpm
--filter @objectstack/cli test` | **68 files / 695 tests passed** — the
tier that actually collects these two files |
| typecheck | `pnpm --filter @objectstack/cli typecheck` | exit 0 (incl.
`check:test-typecheck`) |
| dependency closure + package build | `pnpm --filter
'@objectstack/cli^...' build` then `pnpm --filter @objectstack/cli
build` | exit 0 both — required, several pins refuse at load without it
|
| gate families | `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack`, then `--ran` with exit codes | 47 derived,
**46 run green**, **1 NOT MEASURED** |
| whole-repo lint | `pnpm lint` (`eslint . --no-inline-config`), NOT
narrowed | exit 0 |

**NOT MEASURED (1)**: `pnpm check:dual-build-cjs-loads` exits **3** —
`PREREQUISITE NOT MET —
this gate reads built output, and some package has no dist/`. It needs a
whole-repo `pnpm
build`; this worktree built only the `@objectstack/cli` closure. ⛔
Recorded as NOT MEASURED,
not as a pass and not as a red. CI's `Build Core` job builds the tree
and measures it there.
`dispatch-gates --ran` classified it from the recorded exit code rather
than from a claim.

Two derivation caveats stated rather than hidden: `dispatch-gates`
printed a **STALE TREE**
warning (`origin/main` moved 2 commits under this branch, touching
`scripts/check-adr-0087-registration.mjs` and
`scripts/check-single-claim-paths.mjs`); the
command list was re-derived after `git fetch origin main` and came back
**byte-identical**, so
the 47 stands. And the tool's own footer is quoted rather than
paraphrased: the 47 is not a
complete account of CI — 51 artifact-roster families, 11 wide-population
families, 13
pending-changeset families and 5 path-scheduled CI jobs are outside it
by construction.

## Acceptance notes

Noted, not filed — observations from the two files, none of them a
reproducible defect, a
contract violation, or a metadata-authoring trap:

- The `describe` blocks in both files are still titled with their
originating card numbers
(`objectstack-ai#11772`, `objectstack-ai#12125`) while the assertions inside them now answer objectstack-ai#18894
too. Cosmetic;
renaming a `describe` moves every `-t` filter that names it. Carrier:
whoever next opens
  these files for a behavioural change.
- `packages/cli/test/build-json-advisory-parity.e2e.test.ts` is
nightly-tier and is the only
other reader of the four advisory-list identifiers; its `new Set(...)`
comparisons are
deliberately order-blind, so the family has **no** order coverage in the
per-PR tier at all.
Recorded as the measurement behind the adjacent-axis position above, not
as a defect.
Carrier: the `domain:cli` seat, together with the rung-1 extension
question.

---
_Generated by [Claude
Code](https://claude.ai/code/session_01DvvamiacK328idtBYJBxV3)_

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/m skip-changeset PR has no user-facing published change; bypasses the changeset gate tests

Projects

None yet

2 participants