Repository navigation
Commit 84ba4a8
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:
- `toHaveLength(6)` → `toBeGreaterThanOrEqual(6)`. The **one integer
left**, demoted from an equality to a floor. Six is the population the
#12047 / #12125 rulings were made over, not a count of today; 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 takes both sides to
zero and every assertion here with them. **I write no `7` anywhere in
this diff.**
- `valid: false` × 5 → `literals.length - 1`, beside `valid: true` × 1.
Derived, and the two together now also assert the PARTITION: an exit
carrying neither literal reddens, which the two frozen integers never
checked.
## 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
- **The same rotting shape sits on two more pins, green today.**
`test/build-json-failure-warnings.e2e.test.ts` and
`test/build-json-failure-conversions.e2e.test.ts` pin `toHaveLength(11)`
/ `10` / `1` over `compile.ts`. Measured: `compile.ts` has 11 literals,
10 `success: false`, 1 `success: true` — **green right now**, and one
honest exit away from repeating this exact p1, again only at night. ⛔
Deliberately **not** touched here: `compile.ts` is a #18779 carrier and
is fenced for this card, and a p1 with a cron clock is not the place to
double the review surface. Offered to #18520 as a measurement rather
than as a new card.
- **`validate.ts:661` carries a comment that the seventh exit made
false** — it says the ordering site is read by "every one of the six
exits" and that "a seventh exit cannot be added with a different member
order". A doc nit inside a read-only file; carrier: the next PR that
touches `validate.ts`.
## 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](https://claude.ai/code/session_01DvvamiacK328idtBYJBxV3)_
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 600b1e2 commit 84ba4a8
2 files changed
Lines changed: 94 additions & 6 deletions
File tree
- packages/cli/test
Lines changed: 47 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
410 | 410 | | |
411 | 411 | | |
412 | 412 | | |
413 | | - | |
| 413 | + | |
414 | 414 | | |
415 | | - | |
416 | | - | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
417 | 460 | | |
| 461 | + | |
418 | 462 | | |
419 | 463 | | |
420 | 464 | | |
| |||
Lines changed: 47 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
495 | 495 | | |
496 | 496 | | |
497 | 497 | | |
498 | | - | |
| 498 | + | |
499 | 499 | | |
500 | | - | |
501 | | - | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
502 | 545 | | |
| 546 | + | |
503 | 547 | | |
504 | 548 | | |
505 | 549 | | |
| |||
0 commit comments