Commit f830fa2
fix(pm): H9's issue-ref class requires the reference at the declaration position (#17816)
`classifyRestartWhen`'s `issue-ref` step tested for an issue reference
the value CARRIES anywhere (`/#\d+\b/`), so a `Restart-when:` value that
merely mentions a card mid-sentence read as a machine-fireable exit and
cleared H9. On the 2026-09-11 census of the 104 open `pm:on-hold` cards
that let four holds whose value actually names a tracked repo path — a
misfiled `Restart-touch:` line, exactly the class the parent card built
a row for — read clean, each on an unrelated issue number written in
passing. The step now tests the DECLARATION POSITION: the trimmed value
must START with `#N` or `owner/repo#N`, after the same leading
decoration this file's existing `partOfDeclarationRe` idiom tolerates.
That is H9's own advertised spelling (`Restart-when: #N rules on X`)
read literally, so it costs no ruling, and the class ORDER and
`FIREABLE_RESTART_WHEN_CLASSES` are untouched. A mid-sentence mention
now falls through to `command` / `tracked-path` / `prose` and fires the
row its real shape earns; the `prose` row's remedy gains a "declare it"
clause when the value carries a reference, because an author who wrote a
number down was not missing an event — they wrote it where nothing
reads.
Fixes #17605
## Acceptance notes
### Premises — all five re-verified on `origin/main` @ `2070a1d8`, all
TRUE
1. ✅ `classifyRestartWhen` reads `if (/#\d+\b/.test(v)) return
'issue-ref';` — the reference is accepted anywhere in the value.
2. ✅ The H9 header note carries the "measured price" paragraph naming
#8753, #8607, #8589, #6009.
3. ✅ The prose row's remedy sentence ends with the words *Mark it
`manual` or name the event*, and the self-test pin asserts it. That pin
is untouched and still green (`H9: …and the row names the missing
event`).
4. ✅ `partOfDeclarationRe()` sits beside `partOfRe()` — the file's own
declaration-position idiom, mirrored here rather than reinvented.
5. ✅ Live board, read-only: #8753 / #8607 / #8589 / #6009 open
`pm:on-hold`, each naming a tracked path with the reference
mid-sentence; #13718 and #3267 start with theirs; #7401 open. ⛔ No card
was touched.
`premise_still_valid: true`.
### What landed (A–E)
- **A** — `issue-ref` narrowed to the declaration position. The
predicate is a named pair mirroring the file's own:
`restartWhenIssueDeclarationRe()` (the class test) beside
`restartWhenIssueRefRe()` (the anywhere form, kept as a LABEL for the
prose row). The decoration prefix is copied from `partOfDeclarationRe`;
the qualifier is this file's one reference grammar (`referenceRe` — a
full `owner/repo`, never a bare single segment, because `/` is what
separates a cross-repo reference from a path segment); the NUMBER test
is left byte-for-byte as the wide form spelled it. ⛔ The six-step order
is unchanged and `FIREABLE_RESTART_WHEN_CLASSES` is still
`['closed-ref', 'issue-ref', 'command']` (pinned twice).
- **B** — the prose row's remedy now branches on whether a `prose` value
carries a reference. With one, the row says the value MENTIONS an issue
reference mid-sentence but DECLARES none, and prescribes:
```
If the mentioned card IS the exit, declare it: `Restart-when: #N rules
on X`
(the reference first). Otherwise mark it `manual` or name the event
```
Without one, the existing #10102 sentence stands byte-identical — which
is what keeps the old pin green.
- **C** — the H9 header's "measured price" paragraph rewritten: the
price is no longer paid, the position test is what retired it, and the
sentence saying why ranking `tracked-path` above `issue-ref` was NOT the
instrument (the order is ruled) is kept. The reserved
unreachable-`closed …#N` paragraph above it is untouched.
- **D** — 23 new self-test cases, both directions, named by specimen
card number as the file's idiom does.
- **E** — step 3 of `classifyRestartWhen`'s docblock now says DECLARES,
not CARRIES.
### The specimens are verbatim
Each of the six values below was copied from the live card's
`Restart-when:` line on 2026-09-12 and pinned as a literal string, the
same discipline the parent card's three specimens use: #8753, #8607,
#8589, #6009 (→ `tracked-path` under an oracle naming the one path each
carries; → `prose` under the default oracle, both directions pinned),
#13718 and #3267 (→ still `issue-ref`). The existing `#13651 rules on
the count an app cannot reach` pin is still `issue-ref`, and
`objectstack-ai/cloud#861 …` still is too.
### Reverse verification (ablation)
Fix committed first (`7599059`), then the one classifier line mutated
back to the wide `/#\d+\b/` form in place, proven on disk (`grep -c` on
both the injected and the deleted text: narrow 1→0, wide 0→1; `git
hash-object` moved from `6fe3ffe` to `d30ac02`), the self-test re-run,
then restored under a `trap … EXIT INT TERM` pinned to an absolute repo
root and verified byte-identical (`git hash-object` back to `6fe3ffe`,
`git status --porcelain` empty).
- Direction predicted and observed: **turns red**. 16 of 3707 cases fail
under the wide form, and they are exactly the position-sensitive ones —
the four census values (both oracle states), the row assertions for
#8753, the whole new prose-clause group, and the
single-segment-qualifier pin.
- The two over-reach pins (#13718, #3267 stay `issue-ref`) stay GREEN
under the mutation, which is what they are for: they assert the
narrowing does not reach a declaration.
### Gates
`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` derived 41 families from the merge-base
changeset. All 41 ran, all exit 0. Reconciled with `--ran`: `41 derived,
41 run, 0 NOT-MEASURED, 0 UNRUN` (a DERIVED zero — every line carried
its exit code). Plus `node scripts/pm/check-half-states.mjs --self-test`
→ exit 0, **3707 cases pass**.
`pnpm lint` (`eslint . --no-inline-config`) run in full rather than
narrowed: exit 0 at `759905928`, 6644 files.
### Readings corrected, and things the PM should know
1. **The self-test flag is `--self-test`, not `--test`.** The dispatch
word named `--test`. That spelling is not a flag this script recognises,
so it falls through to a **live patrol sweep** — which is what it did
here, at real API cost, before the mistake was caught. The file's own
usage line (its header) is the authority. Worth fixing in whatever
produced the dispatch word.
2. **That accidental live run is, however, the best evidence this change
works.** On the live board it produced: #8753 →
`packages/objectql/src/registry.ts`, #8607 →
`scripts/check-adr-0087-registration.mjs`, #8589 →
`packages/runtime/src/domains/mcp.ts`, #6009 →
`packages/drivers/driver-sql/src/sql-driver.ts` — each a correct
`tracked-path` row naming the exact path it misfiled. #13718 and #3267
produced no H9 row at all. 73 H9 rows total.
3. **1 parent 2b08a72 commit f830fa2
1 file changed
Lines changed: 164 additions & 15 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2412 | 2412 | | |
2413 | 2413 | | |
2414 | 2414 | | |
2415 | | - | |
2416 | | - | |
2417 | | - | |
2418 | | - | |
2419 | | - | |
2420 | | - | |
2421 | | - | |
2422 | | - | |
| 2415 | + | |
| 2416 | + | |
| 2417 | + | |
| 2418 | + | |
| 2419 | + | |
| 2420 | + | |
| 2421 | + | |
| 2422 | + | |
| 2423 | + | |
| 2424 | + | |
| 2425 | + | |
| 2426 | + | |
| 2427 | + | |
| 2428 | + | |
| 2429 | + | |
| 2430 | + | |
| 2431 | + | |
| 2432 | + | |
| 2433 | + | |
| 2434 | + | |
| 2435 | + | |
| 2436 | + | |
| 2437 | + | |
| 2438 | + | |
2423 | 2439 | | |
2424 | 2440 | | |
2425 | 2441 | | |
| |||
2500 | 2516 | | |
2501 | 2517 | | |
2502 | 2518 | | |
| 2519 | + | |
| 2520 | + | |
| 2521 | + | |
| 2522 | + | |
| 2523 | + | |
| 2524 | + | |
| 2525 | + | |
| 2526 | + | |
| 2527 | + | |
| 2528 | + | |
| 2529 | + | |
| 2530 | + | |
| 2531 | + | |
| 2532 | + | |
| 2533 | + | |
| 2534 | + | |
| 2535 | + | |
| 2536 | + | |
| 2537 | + | |
| 2538 | + | |
| 2539 | + | |
| 2540 | + | |
| 2541 | + | |
| 2542 | + | |
| 2543 | + | |
| 2544 | + | |
| 2545 | + | |
| 2546 | + | |
| 2547 | + | |
| 2548 | + | |
| 2549 | + | |
| 2550 | + | |
| 2551 | + | |
| 2552 | + | |
| 2553 | + | |
| 2554 | + | |
| 2555 | + | |
| 2556 | + | |
| 2557 | + | |
| 2558 | + | |
| 2559 | + | |
| 2560 | + | |
| 2561 | + | |
| 2562 | + | |
| 2563 | + | |
| 2564 | + | |
| 2565 | + | |
| 2566 | + | |
| 2567 | + | |
| 2568 | + | |
| 2569 | + | |
| 2570 | + | |
| 2571 | + | |
2503 | 2572 | | |
2504 | 2573 | | |
2505 | 2574 | | |
| |||
2510 | 2579 | | |
2511 | 2580 | | |
2512 | 2581 | | |
2513 | | - | |
2514 | | - | |
2515 | | - | |
| 2582 | + | |
| 2583 | + | |
| 2584 | + | |
| 2585 | + | |
| 2586 | + | |
| 2587 | + | |
2516 | 2588 | | |
2517 | 2589 | | |
2518 | 2590 | | |
| |||
2531 | 2603 | | |
2532 | 2604 | | |
2533 | 2605 | | |
2534 | | - | |
| 2606 | + | |
2535 | 2607 | | |
2536 | 2608 | | |
2537 | 2609 | | |
| |||
2640 | 2712 | | |
2641 | 2713 | | |
2642 | 2714 | | |
2643 | | - | |
2644 | | - | |
2645 | | - | |
| 2715 | + | |
| 2716 | + | |
| 2717 | + | |
| 2718 | + | |
| 2719 | + | |
| 2720 | + | |
| 2721 | + | |
| 2722 | + | |
| 2723 | + | |
2646 | 2724 | | |
2647 | 2725 | | |
2648 | 2726 | | |
| |||
20598 | 20676 | | |
20599 | 20677 | | |
20600 | 20678 | | |
| 20679 | + | |
| 20680 | + | |
| 20681 | + | |
| 20682 | + | |
| 20683 | + | |
| 20684 | + | |
| 20685 | + | |
| 20686 | + | |
| 20687 | + | |
| 20688 | + | |
| 20689 | + | |
| 20690 | + | |
| 20691 | + | |
| 20692 | + | |
| 20693 | + | |
| 20694 | + | |
| 20695 | + | |
| 20696 | + | |
| 20697 | + | |
| 20698 | + | |
| 20699 | + | |
| 20700 | + | |
| 20701 | + | |
| 20702 | + | |
| 20703 | + | |
| 20704 | + | |
| 20705 | + | |
| 20706 | + | |
| 20707 | + | |
| 20708 | + | |
| 20709 | + | |
| 20710 | + | |
| 20711 | + | |
| 20712 | + | |
| 20713 | + | |
| 20714 | + | |
| 20715 | + | |
| 20716 | + | |
| 20717 | + | |
| 20718 | + | |
| 20719 | + | |
| 20720 | + | |
| 20721 | + | |
| 20722 | + | |
| 20723 | + | |
| 20724 | + | |
| 20725 | + | |
| 20726 | + | |
| 20727 | + | |
| 20728 | + | |
| 20729 | + | |
| 20730 | + | |
| 20731 | + | |
| 20732 | + | |
| 20733 | + | |
| 20734 | + | |
| 20735 | + | |
| 20736 | + | |
| 20737 | + | |
| 20738 | + | |
| 20739 | + | |
| 20740 | + | |
| 20741 | + | |
| 20742 | + | |
| 20743 | + | |
| 20744 | + | |
| 20745 | + | |
| 20746 | + | |
| 20747 | + | |
| 20748 | + | |
| 20749 | + | |
20601 | 20750 | | |
20602 | 20751 | | |
20603 | 20752 | | |
| |||
0 commit comments