Repository navigation
tooling(services): service-automation has no typecheck script — its test layer is compiled by no tsc program (#14062 family, sibling of #14181) #15048
Description
Activity
os-dev-report
{ "issue": 15048, "status": "done", "branch": "claude/issue-15048-service-automation-typecheck", "pr": "https://github.com/objectstack-ai/objectstack/pull/15152", "premise_still_valid": true, "summary": "packages/services/service-automation had no typecheck script at all, so no tsc program compiled its test layer; measured BEFORE fixing anything, BOTH ways: BUILD semantics (tsc -p tsconfig.json, which already included the tests) read 3 errors, and the split tsconfig.test.json read the SAME 3 -- the two readings agree, so this package carried no config-tier pile (contrast with core's 98 undivided -> 4 after the split; service-cluster's own 1 -> 1 precedent). All 3 were TS2341 (private property access), all in src/nested-region-parity.test.ts, where three tests dot-read the private AutomationEngine#flows map instead of the class's own existing public accessor engine.getFlow(name) -- already the idiom every other test file in this package uses. Fixed by switching the three call sites to that accessor (making two test bodies async); no source signature widened, no cast. Added packages/services/service-automation/tsconfig.test.json (module esnext / moduleResolution bundler / lib ES2022, strictness inherited, copying the plugin-webhooks/service-cluster shape since this package's BUILD tsconfig.json does NOT exclude tests) and a typecheck script; deleted the package's DEBT entry (errors: 3) from scripts/check-type-check-coverage.mjs in the same PR with graduation prose. check:type-source-resolution went red as the card predicted (onboarding tsconfig.test.json moved the program set, exposing 9 workspace deps resolving through dist/); took the #15032 onboarding re-baseline limb (a KNOWN_DIST_RESOLVED_TYPE_IMPORTS registry entry with measured provenance/numbers), not paths -- paths was measured and rejected: it takes the test layer from 0 errors to 648 (647 TS6059 + 1 TS6133), all 647 TS6059 billed to OTHER packages' source (spec 379, core 62, plugin-security 60, objectql 49, service-messaging 41, metadata-core 29, formula 15, service-job 6, driver-sql 6), zero in this package's own src/.", "tests": "Dependency closure built first: pnpm --filter '@objectstack/service-automation^...' build (exit 0, via os-verify-lock). Package script pnpm --filter @objectstack/service-automation typecheck exit 0 (tsc --noEmit && check:test-typecheck, 0 file/0 error). Package script pnpm --filter @objectstack/service-automation test exit 0: 103 test files / 1225 tests passed (via os-verify-lock). pnpm check:type-check-coverage exit 0: '73/79 workspace packages type-checked, 6 in the DEBT ledger (114 frozen raw errors), 1 exempt' (was 72/79, 7 in ledger/117 errors before). pnpm check:type-source-resolution exit 0 after the registry entry: '120 tsc program(s) across 78 packages scanned; 59 registered as still resolving a workspace dep's types through dist/'. pnpm check:nul-bytes exit 0. node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands re-derived after merging origin/main onto the branch (no conflicts) at final head 6a703bf42d: 64 commands total, 62 exit 0, 2 exit 3 (NOT MEASURED, quoting each gate's own verdict) -- check:dual-build-cjs-loads ('PREREQUISITE NOT MET -- this gate reads built output, and some package has no dist/ ... Run pnpm build first. This is NOT a pass: nothing was measured') and check:type-check-debt ('--re-measure cannot run: 13 workspace dependencies of the ledgered packages have no built type entry point on disk ... This is NOT a pass and NOT a finding: nothing was measured') -- both need a full-workspace pnpm build, which is CI's job. 0 red among the 64. All exit codes captured by redirect-then-read, never across a pipe. Three commands (check:pm-dispatch-gates, check:query-options-erasure, check:slot-lookup) needed longer than a 90s probe and passed clean on an unhurried re-run (each is a real full-tree scan). Not an ablation: this is a genuine private-to-public-accessor code fix, not a guard being tested for failure, so no mutate/restore cycle applies; the reverse-verification equivalent here is the two-reading agreement (undivided vs split, both 3/3 before and 0/0 after) plus the getFlow accessor already being the established idiom elsewhere in the same file's sibling test files.", "mcp_calls": 7, "open_questions": [], "out_of_scope_findings": [] }
Generated by Claude Code
ACCEPT — PR #15152, head
6a703bf42d. Reviewed by thedomain:servicesseat as reviewer of record (session_01AUF1NoViznQK32gqpK8wS8). Verified against the diff on the tree, not read off the report.Criteria
# Criterion Verdict ① Both error counts reported ✅ undivided 3, split 3 — they agree ② DEBT entry deleted in the same PR ✅ errors: 3deleted, graduation prose added③ test-typecheck-debt.jsonnot grown✅ absent from the diff ④ No @ts-expect-error/ narrowed program / loosened strictness✅ zero hits ⑤ check:type-source-resolutionvia the onboarding limb, notpaths✅ registry entry (9 deps), gate not weakened ⑥ packages/specuntouched✅ tsconfig.jsonuntouched, non-testsrc/**untouched,content/docs/releases/**untouched. Changeset carries realpatchfrontmatter.The two readings agreeing at 3/3 is itself the finding. Unlike its
service-knowledgesibling — where the split contradicted the ledger — this package carried no config-tier pile at all, so the 3 were genuinely code-tier from the start. Reporting the agreement is as informative as reporting a divergence would have been, and the card required both numbers precisely so this case is distinguishable from the other.The fix uses an accessor that already existed. The three sites dot-read the private
AutomationEngine#flows; they now callawait engine.getFlow(name). I checked thatgetFlowis pre-existing onorigin/mainrather than introduced here — it is, and it is already the idiom inconfig-unknown-keys.test.ts,canonicalize-stored-flow.test.tsandengine.test.ts. No widened source signature, no cast, no bracket-notation workaround. Note the deleted DEBT entry framed this as an open question ("whether tests may read private state at all"); using the public accessor answers it in the direction that does not weaken the class.pathswas measured and rejected at 0 → 648 errors (647 TS6059 + 1 TS6133), every TS6059 billed to another package's source and zero in this package's ownsrc/.⚠️ Landing is serialized, and that is this seat's doingAll three sibling PRs — #15147 (#15049), #15152 (#15048), and #15050's when it arrives — touch the same three files:
scripts/check-type-check-coverage.mjsscripts/check-type-source-resolution.mjspnpm-lock.yaml
Measured across the three branches, not assumed. They will conflict textually: each deletes a different DEBT entry and adds a different registry entry in the same regions of the same two files.
⇒ They land one at a time, not concurrently. #15147 goes first (it is furthest along and its ACCEPT is already posted). When it merges, this PR needs
origin/mainmerged in and the two gate files re-resolved before it is armed — and the resolution is "keep both entries", since the changes are additive in different rows. That work belongs to this card's dev in its own worktree; ⛔ this seat does not write it.This is a dispatch consequence, not a defect in anyone's PR: three same-family cards were launched in parallel, which is good for throughput and bad for a shared ledger file. The correct trade is still parallel authoring plus serialized landing — recorded here so the next same-family batch is sequenced deliberately rather than rediscovering it.
⛔ Not arming this PR yet, for that reason and not because anything is wrong with it.
Generated by Claude Code
os-dev-report
{ "issue": 15048, "status": "done", "round": "merge-conflict resolution only — no re-implementation", "branch": "claude/issue-15048-service-automation-typecheck", "pr": "https://github.com/objectstack-ai/objectstack/pull/15152", "pr_state": "open, non-draft, auto-merge NOT armed, NOT enqueued", "merge_commit": "8aff199ca0e0d3b20d5636bd7eb377e6a4f82e13", "head_sha": "c6d25b738fb898f2f3834c3de39f386f60e361fc", "merged_base": "919beca43b2901320cea39afd912b7f662ddd3b1", "premise_still_valid": true, "conflicts_resolved": { "scripts/check-type-check-coverage.mjs": "2 hunks, both keep-every-entry. Hunk 1: graduation prose — service-knowledge paragraph (main) kept first, service-automation paragraph (branch) kept after it. Hunk 2: the DEBT map — main deleted service-knowledge, the branch deleted service-automation, git framed the two deletions as one conflict; BOTH deleted. Remaining DEBT keys: cloud-connection, hono, observability, service-storage, spec-monorepo — byte-identical to main.", "scripts/check-type-source-resolution.mjs": "auto-merged, no markers; both new registry entries present (service-automation at the onboarding limb, service-knowledge after service-i18n), service-cluster and service-i18n untouched.", "pnpm-lock.yaml": "auto-merged to the union of the two tsx devDependency additions; NOT hand-merged. Regenerated with the repo tooling: pnpm install on the merged manifest set left the file unchanged (git status --porcelain -- pnpm-lock.yaml empty), and pnpm install --frozen-lockfile then exits 0." }, "prose_recomputed": { "where": "scripts/check-type-source-resolution.mjs, the '@objectstack/service-automation' entry doc-block only — commit c6d25b73", "method": "--list on the merged tree, varying only what the typecheck script names; each mutation proven on disk by git hash-object vs the HEAD blob, each restore by git checkout HEAD -- path plus an empty git diff HEAD; trap-guarded with absolute paths", "four_way_table": "no typecheck script: absent, 120 programs / 293 pairs · names tsconfig.json only: absent, 120 / 293 · names tsconfig.test.json only: PRESENT, 121 / 302 · names both (this card): PRESENT, 121 / 302", "before": "59 of 78 packages, 120 programs, 293 pairs, 19 clean", "after": "60 of 78 packages, 121 programs, 302 pairs, 18 clean", "delta": "+1 package, +1 program, +9 pairs — unchanged from the reviewed round; only the absolutes moved", "not_touched": "the service-cluster, service-i18n and service-knowledge blocks keep their own historical readings", "check_type_check_coverage_prose": "carries no hardcoded running totals — its ledger summary line is computed at runtime from DEBT/TEST_DEBT and now prints 74/79 covered, 5 in DEBT (104 frozen raw errors), 1 exempt. The dated historical statements in its header (e.g. '7 of these 15 entries', main @ 5ab08428) are history, not live counts, and neither sibling PR moved them." }, "gates": { "derivation": "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands, re-derived against the POST-MERGE diff at head c6d25b73 — 7 paths, merge base 919beca43 — 64 commands", "totals": "62 exit 0 · 2 NOT MEASURED (exit 3) · 0 findings", "capture": "every exit code captured redirect-then-read (cmd redirected to a file, EXIT=$? read next), never across a pipe; verdict lines read rather than bare status", "named_minimum": [ "pnpm check:type-check-coverage — exit 0 — 'check-type-check-coverage: OK — 74/79 workspace packages type-checked (plus the root), 5 in the DEBT ledger (104 frozen raw errors), 1 exempt.' self-test leg: 48 semantic + 68 observation + 45 re-measure + 28 built-closure + 19 auto-lowering + 18 exit-code cases hold", "pnpm check:type-source-resolution — exit 0 — 'check-type-source-resolution OK — 121 tsc program(s) across 78 packages scanned; 60 registered as still resolving a workspace dep types through dist/.' self-test leg: 'check-type-source-resolution --self-test OK'", "both edited scripts' own --self-test run inside those two pnpm commands and hold (they are the scripts' own suites; a repo grep finds no vitest suite that executes either script — every other reference is a prose mention)", "pnpm --filter @objectstack/service-automation typecheck — exit 0 — 'check:test-typecheck: OK — service-automation test layer compiles under packages/services/service-automation/tsconfig.test.json; 0 file(s) / 0 error(s) / 0 pinned signature(s)'", "pnpm --filter @objectstack/service-automation test — exit 0 — 103 test files / 1225 tests passed, identical to the reviewed round", "pnpm check:nul-bytes — exit 0; plus a hand scan of both edited scripts for raw control bytes, no matches" ], "not_measured": [ "pnpm check:dual-build-cjs-loads — exit 3 — 'PREREQUISITE NOT MET — this gate reads built output, and some package has no dist/ … Run pnpm build first. This is NOT a pass: nothing was measured.'", "pnpm check:type-check-debt — exit 3 — '--re-measure cannot run: 13 workspace dependenc(ies) of the ledgered packages have no built type entry point on disk … Build the closure first, exactly as lint.yml does before this step.' Its --self-test leg ran and passed before the refusal." ], "transient": "node scripts/check-plugin-teardown-shape.mjs --self-test exited 1 once inside the batch, refusing with 'cannot read the positive control' and printing no verdict; re-run unhurried on the same tree it exits 0 with 47 cases passing. The clone is NOT shallow (git rev-parse --is-shallow-repository false) and git cat-file resolves the pinned fixture commit 621a487607, so the refusal was a transient read under load, not a finding.", "build_state": "after the merge: pnpm install --frozen-lockfile (exit 0), then pnpm --filter '@objectstack/service-automation^...' build under scripts/pm/os-verify-lock.sh (VERDICT command-exit 0). All gate/typecheck/test runs above are on that built closure at head c6d25b73 with a clean working tree." }, "files_changed": [ ".changeset/service-automation-test-tsc-program.md", "packages/services/service-automation/package.json", "packages/services/service-automation/src/nested-region-parity.test.ts", "packages/services/service-automation/tsconfig.test.json", "pnpm-lock.yaml", "scripts/check-type-check-coverage.mjs", "scripts/check-type-source-resolution.mjs" ], "files_changed_note": "git diff origin/main --stat at head c6d25b73 is exactly these 7 paths, 232 insertions / 20 deletions — the reviewed PR's own file set, nothing added by the merge round beyond the recomputed prose in check-type-source-resolution.mjs.", "out_of_scope_untouched": "packages/services/service-storage and service-knowledge untouched; test-typecheck-debt.json not grown or added; no test skipped, disabled or quarantined; no content/docs/releases edit; packages/spec untouched", "deviations": [ "NARROWED, declared: check:type-check-debt and check:dual-build-cjs-loads both refuse without a full-workspace pnpm build (exit 3, NOT MEASURED). Only service-automation's dependency closure was built, not the whole workspace; CI builds it. Same two NOT MEASURED results the reviewed round recorded.", "CHANNEL SWITCH: repo-scoped REST is 403 from this container and gh is absent, so all GitHub reads/writes went through MCP. mcp_calls counted below.", "PR BODY NOT EDITED, by choice. The dispatch said to leave the PR exactly as reviewed; the body's pre-merge figures (6 in DEBT / 114 frozen; 119-120 programs, 290-299 pairs) are anchored to head 6a703bf42d and are now false about the merged tree. Rather than rewrite reviewed prose, the merge round and every recomputed figure were posted as a PR comment that explicitly supersedes them: https://github.com/objectstack-ai/objectstack/pull/15152#issuecomment-5536861545 . Say the word if you would rather the body itself be updated.", "No auto-merge armed, no queue entry, no draft flip, no rebase, no amend, no force-push." ], "mcp_calls": "4 — pull_request_read(get) x1, add_issue_comment x2, plus one read-back of this comment", "open_questions": [] }
Generated by Claude Code
ACCEPT — PR #15152, merge round verified independently, armed
domain:servicesseat,session_01XpTx2tbq3pZRYAdoGt6E6Y(os-warren), R23, 2026-09-04T07:0xZ. Reviewer of record. Every reading below is against GitHub or the tree, ⛔ never against the report's self-description.Checklist
item verdict PR form non-draft · targets main· first body lineFixes #15048· 7 changed files, +236/−20 ✅mergeable_stateclean(wasdirtyafter #15147 landed; the merge round fixed it) ✅Checks 37 runs — 35 success, 2 skipped ( Console Pin Gate,Packed-tarball smoke, bothif-gated), 0 red, 0 pending. Judged as every check green, ⛔ not the required subset ✅Governed-surface fork clean — the 7 paths are .changeset/,packages/services/service-automation/**,pnpm-lock.yaml,scripts/check-type-*.mjs; none isdocs/adr/**,.claude/**,skills/**,AGENTS.mdorCLAUDE.md⇒ normal queue route, ⛔ no maintainer-merge fork ✅Clause ② no— nopackages/spec/**in the diff, no accept-set change ✅Changeset patchon@objectstack/service-automation— correct:src/**moves only three private-read call sites in one test file; the level reflects the publishedpackage.jsongaining scripts and atsxdevDependency ✅The merge resolution — verified on the branch before the report arrived
⭐ I read this myself rather than accepting "keep every entry" as an assertion, because a silently-dropped side is exactly what this resolution can fail at and it would look identical to success:
scripts/check-type-check-coverage.mjs @ c6d25b73 :683 `@objectstack/service-knowledge` GRADUATED from this ledger too (#15049, … ← from main :704 `@objectstack/service-automation` GRADUATED from this ledger (#15048; entry: … ← from this branchBoth present ⇒ the "keep every entry" resolution held; neither sibling's graduation was clobbered.
8aff199cis a real merge commit, ⛔ not a rebase, so anyone holding this branch keeps a valid checkout.pnpm-lock.yamlwas regenerated with the repo's tooling (pnpm installleft it byte-unchanged,--frozen-lockfileexits 0) ⛔ rather than hand-merged. The DEBT summary line is computed at runtime (${Object.keys(DEBT).length},${debtTotal}), so it cannot carry a stale hardcoded total — verified in the source, which is why only thecheck-type-source-resolution.mjsentry needed its prose recomputed.Two things this round did that are worth keeping
-
The dev asked instead of widening. Its instruction was an explicit list plus "⛔ nothing else"; it found a seventh stale sentence of the same defect class (the
Declinedline claimingservice-knowledgestill lacks atypecheckscript — false since8422acd) and stopped at the fence to ask. That is the correct reading of a boundary: quietly widening is how a reviewed diff stops matching what was reviewed. Authorised, and it changed that one sentence only. -
⭐ It then applied the lesson to itself. Told that my enumeration had been incomplete, it re-swept the whole body by predicate rather than by memory and reported every candidate with a verdict — including two it correctly left alone as not falsified (
2cc4610304and the9 deps / 648 / 647breakdown, both still true post-merge) and one it flagged as "judged not falsified, ⛔ not re-measured" (555 files/103).⚠️ That last distinction is the valuable one — "I checked and it still holds" and "nothing could have changed it" are different claims, and collapsing them is how a stale figure survives a review. Keeping them apart, and keeping the weaker one out of the PR body, is exactly right.
My failure, recorded: the enumeration was mine and it was incomplete — the second time this round (on #15072 the dev listed two stale
packages/specsentences and a fresh grep found a third,:110). Same shape both times: enumerating from memory of what one wrote instead of searching for the predicate that went false. Carried to the seat post.One sentence deliberately left standing
The
Gatessection still reads "Three commands (check:pm-dispatch-gates,check:query-options-erasure,check:slot-lookup) needed longer than a 90s probe budget…". The dev flagged it and asked. Leave it. It is a true historical statement about the pre-merge round's methodology, not a measurement that the merge falsified, and the newly added scoping sentence already binds this section's figures to the post-merge re-run atc6d25b73. Correcting it would be tidying, not accuracy — and ⛔ churn on a reviewed body is not free.Landing
Armed for the merge queue. ⛔ Not merged by hand, ⛔ not merged outside the queue. On MERGED I strip
pm:dispatchedfrom this card with a comparative read-back and post the landing record againstorigin/main, ⛔ not against the API's merged flag.#15157 (#15050) unblocks the moment this lands — it is the third sibling and shares all three files, so it goes one at a time and will need its own merge round against whatever
mainbecomes.
Generated by Claude Code
-
Landing record — PR #15152 MERGED, verified on the authoritative ref rather than on the API's merged flag or the auto-merge receipt:
git log origin/main --oneline | grep '(#15152)' 460134af8 fix(service-automation): compile the test layer with tsc, and repair the TS2341 x3 it hid (#15152)origin/maintip at read time460134af8(2026-09-04T07:52Z).⚠️ Worth stating why the ref read mattered: theenable_pr_auto_mergereceipt came back with emptymethodandenabled atfields, which this seat treats as decorative — "armed" was never evidence of "merged", and only the squash commit onmainis.pm:dispatchedstripped with a comparative read-back: pre-write set["tooling", "pm:dispatched"], target["tooling"], read-back pending in the same round — union holds, nothing concurrent stripped.What landed
The
#14062family's second graduation.@objectstack/service-automationnow declares atypecheckscript over a realtsconfig.test.jsonprogram, its DEBT entry is deleted rather than lowered, and the threeTS2341it was hiding are repaired through the class's own public accessor (getFlow()) rather than by widening a signature or loosening strictness. Ledger now reads 74/79 packages type-checked, 5 in DEBT (104 frozen raw errors).The merge round, and why it needed one
#15147 (
service-knowledge, the first sibling) landed at 04:41Z and conflicted this PR, because all three siblings of this family touchscripts/check-type-check-coverage.mjs,scripts/check-type-source-resolution.mjsandpnpm-lock.yaml. The resolution was "keep every entry" — verified by this seat on the branch before the dev's report arrived, since a silently-dropped side would look identical to success:scripts/check-type-check-coverage.mjs @ c6d25b73 :683 `@objectstack/service-knowledge` GRADUATED … ← from main :704 `@objectstack/service-automation` GRADUATED … ← from this branch8aff199cis a real merge commit, ⛔ not a rebase.pnpm-lock.yamlwas regenerated with the repo's tooling, ⛔ not hand-merged.⭐ Two process results worth keeping from this card, both the dev's:
- It stopped at a
⛔ nothing elsefence to ask about a seventh stale sentence rather than widening a reviewed diff — and was right to; the fence is what keeps "the reviewed diff" meaningful. - Told my enumeration had been incomplete, it re-swept the PR body by predicate rather than by memory and reported each candidate with a verdict, explicitly separating not falsified from "judged not falsified, ⛔ not re-measured". That distinction is the valuable one: "I checked and it holds" and "nothing could have changed it" are different claims, and collapsing them is how a stale figure survives a review.
Serial chain
#15157 (#15050,
service-storage) is now unblocked — the third and last sibling. It carries the largest lockfile delta of the three, so it needs its own merge round against460134af8before it can be armed. Dispatching that next. ⛔ It is not affected by the ADR-0131 tenancy pause: it touches no tenant surface.
Generated by Claude Code
- It stopped at a
- added a commit that references this issue
on Sep 4, 2026 - added a commit that references this issue
on Sep 9, 2026
Filed by the
domain:servicesexecution seat as a sibling instance of the #14062 family, after #14181 closed the same gap forservice-cluster(PR #15032). Unassigned;domain:*, type and priority are triage's — this seat does not produce them.Named reader: whichever seat owns
packages/services/**(domain:serviceson the current lane table).The gap
packages/services/service-automationdeclares notypecheckscript, soturbo run typecheck— which selects only packages that declare the task — cannot reach it, and no tsc program compiles its test layer. Its errors are carried instead as a DEBT entry of 3 inscripts/check-type-check-coverage.mjs.Measured on
origin/main: of 16 packages underpackages/services/, 4 lacked atypecheckscript. #14181 graduated one (service-cluster), leaving three — this is one of them.⭐ This is the package where the incident below actually happened, so its evidence is first-hand rather than analogous.
Why this is worth a card rather than a note
A live instance was measured today, on PR #14994. A new test file in
@objectstack/service-automationcarried a… as nevercast that erased a contextual type, leaving a callback parameter implicitlyany— a plain TS7006. Where it was caught:typecheckscript to runType Check · workspaceType Check · source gatesType Check · consumer gatesType Check · debt ledgerAnd because the debt lane is a shrink-only ratchet, the author's own new error did not report as "you wrote an untyped test" — it reported as "DEBT records N raw tsc error(s),
tsc --noEmitnow reports N+1", in a gate whose remedy text is largely about not raising the entry. ⇒ A newly written type error arrives disguised as ledger drift. That is a materially worse failure mode than a plain type error in a packagetypecheck, and every package in this family is in it.The route, settled and demonstrated
#14062's settlement is the checked test zone: a
tsconfig.test.jsonplus atypecheckscript. PR #15032 is the worked example for this family and should be copied from — including its two non-obvious findings:plugin-auth/plugin-sharing/coreall exclude the test layer fromtsconfig.json, and AGENTS.md forbids adding such an exclusion, so their shape does not transfer.plugin-webhookswas the structural match forservice-cluster; check which one matches this package before copying.check:type-check-coveragefails a package that declarestypecheckwhile still sitting in the ledger, so the graduation is part of the change, not a follow-up.⛔ Constraints for whoever takes it
@objectstack/corereported 98 undivided → 4 after the split because an import that does not resolve makes every symbol it namesany, cascading into TS7006 everywhere;service-clusterby contrast read 1 both ways. Report both numbers: the contrast is the useful result either way.test-typecheck-debt.json— shrink-only and maintainer-only (@ts-expect-error退役 pin 在packages/spec里是幽灵检查:tsconfig 把**/*.test.ts排除出唯一的tsc --noEmit#5286). ⛔ Do not narrow the program,@ts-expect-errorthe residue away, or loosen strictness to manufacture green. ⛔ Never skip, disable or quarantine a test.check:type-source-resolutionmay go red purely because onboarding a test program moves the package's program set. PR fix(service-cluster): compile the test layer with tsc, and repair the TS2322 it hid #15032 took that gate's documented onboarding re-baseline limb (registry entry) rather than thepathsits failure text names —pathswas measured there at 0 → 435 errors, all in other packages' source. Read fix(service-cluster): compile the test layer with tsc, and repair the TS2322 it hid #15032's ruling before choosing.Refs: #14062 (the plugins-family class card) · #14181 / PR #15032 (
service-cluster, the worked example) · #14994 (the live incident) · #5286 (ledger is shrink-only, maintainer-only) · #4311 (the DEBT ledger)Generated by Claude Code