Repository navigation
tooling(services): service-storage has no typecheck script — its test layer is compiled by no tsc program (#14062 family, sibling of #14181) #15050
Description
Activity
- added a commit that references this issue
on Sep 4, 2026 os-dev-report
{ "issue": 15050, "status": "done", "branch": "claude/issue-15050-service-storage-typecheck", "pr": "https://github.com/objectstack-ai/objectstack/pull/15157", "premise_still_valid": true, "summary": "Gave service-storage the #14062/#14181 checked-test-zone shape: a tsconfig.test.json (structural match to plugin-webhooks/service-cluster, since tsconfig.json never excluded tests) plus a tsconfig.scripts.json for the ninth i18n-extract.config.ts instance, both named by a new typecheck script. Measured BOTH ways as required: undivided/BUILD semantics read 51 errors (matching the DEBT ledger's recorded 51 exactly, a positive control), the split read 10. Unlike service-cluster, BUILD was not already clean, so both programs needed real repair, not just the split: 23 TS2835 (missing .js extensions) fixed by adding the extension (valid under both module modes), which also cleared 15 TS7006 as a downstream cascade (98->4 shape); 3 TS2550 (Array.prototype.at) rewritten to indexed access rather than widening BUILD's lib; 8 genuine code-tier defects (TS2339 a test helper's spread dropping its index signature, TS2347 a fake ctx:any's generic calls -- one call site in the same file had already hit and documented this exact fix). Both readings now agree at 0/0. DEBT entry deleted, no test-typecheck-debt.json needed. check:type-source-resolution repaired via the documented onboarding-limb registry entry (measured paths as the wrong tool: 306 errors, all in other packages' source, same as the exemplar found).", "tests": "pnpm --filter @objectstack/service-storage typecheck: exit 0 (tsc --noEmit + tsc --noEmit -p tsconfig.scripts.json + check:test-typecheck, 0/0/0 errors). pnpm --filter @objectstack/service-storage test: exit 0, 35 files / 536 tests passed (re-run 3x across edits, always 536/536). node scripts/check-type-check-coverage.mjs: OK, 73/79 packages covered, 6 in DEBT (66 raw errors, down from 7/117). node scripts/check-type-source-resolution.mjs: OK, 121 programs/78 packages, 59 registered dist-resolved. Both edited gate scripts' --self-test green. Full dispatch-gates.mjs --commands union (66 commands) run on final head 7c6ec7d0a7 (rebased onto fresh origin/main after an initial stale-tree warning): 63 green, 3 NOT MEASURED/exit 3 (check:dual-build-cjs-loads, check:i18n, check:type-check-debt -- unbuilt sibling dist/, same class PR #15032 hit), 1 exit-1-wearing-NOT-MEASURED (check:published-readme-exports, names an unrelated unbuilt packages/verify/dist/index.d.ts). Reproduced the TS2339 root cause in an isolated 5-line repro before fixing. Measured the paths alternative directly (temporary block, never committed) rather than assuming symmetry with the exemplar.", "mcp_calls": "7", "open_questions": [], "out_of_scope_findings": [] }
Generated by Claude Code
ACCEPT — PR #15157, head
7c6ec7d0a7. 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 51, split 10; both 0 after ② DEBT entry deleted in the same PR ✅ { errors: 51 }deleted, not lowered③ test-typecheck-debt.jsonnot grown✅ none needed, none created ④ No @ts-expect-error/ narrowed program / loosened strictness✅ zero hits ⑤ check:type-source-resolutionvia the onboarding limb, notpaths✅ registry entry (7 deps), gate not weakened ⑥ packages/specuntouched✅ content/docs/releases/**untouched. Changeset carries realpatchfrontmatter.The undivided 51 matching the ledger's recorded 51 exactly is a positive control, and the dev names it as one. Unlike its
service-clusterexemplar, BUILD was not already clean here, so both programs needed real repair rather than just a split.Three judgements worth naming
- 3 TS2550 (
Array.prototype.at) rewritten to indexed access rather than widening BUILD'slib. Wideninglibis the cheap path and it would have been a loosening; the dev took the other one. - The TS2339 root cause was reproduced in an isolated 5-line repro before being fixed — not pattern-matched.
pathswas measured, not assumed. 306 errors, all in other packages' source, via a temporary block that was never committed. The exemplar's asymmetry was not taken on faith.
23 TS2835 were fixed by adding
.js(valid under both module modes), which cleared 15 TS7006 as a downstream cascade — the same "the config tier was manufacturing the noise tier" shape the ledger documents elsewhere.⭐ It answered a warning written in advance for this card. The ledger text this PR deletes contained: "THE NINTH CONFIG IS NOT HERE, deliberately… service-storage declares [no
typecheckscript]… giving it atypecheckscript is not a one-line graduation, it is a 51-error burn-down, and wiring one that ran ONLYtsconfig.scripts.jsonwould be" — and the PR adds bothtsconfig.test.jsonandtsconfig.scripts.json, which is why it carries two configs where its siblings carry one.Two things I checked because they looked wrong, and cleared
The lockfile.
pnpm-lock.yamlshowed 60 changed lines with heavy deletions, re-keyingvite/vitest/@vitest/mockerfromesbuild@0.28.1to0.28.2, where both siblings changed only+3. That reads like an unrelated dependency bump riding on a scoped card. It is not:origin/main's own lockfile is already mixed at 11 × 0.28.1 / 89 × 0.28.2, and this branch is 4 / 90 —pnpm installconverged 7 stragglers toward the version main already predominantly pins. No upgrade, no downgrade, nothing this card introduced.The docs-drift flag. This PR's run did not return the siblings' clean "no opinion". It reported one file that yielded no anchor (
packages/services/service-storage/tsconfig.scripts.json) and said explicitly that this is not a clean bill of health. Hand-checked, because "NOT COVERED" is the one verdict that requires it: zero docs pages referencei18n-extract.configortsconfig.scripts.json, and of the five non-release pages mentioningservice-storage, every one has zero occurrences oftypecheckortsconfig— so none states a claim this diff could falsify. The remaining two arecontent/docs/releases/**, release-owned and never edited from a code PR, documenting shipped behaviour this diff does not move. Real exposure in principle, empty in fact.⚠️ Harmless prose drift, recorded so no later reader trusts a stale numberAll three siblings measured the ledger against the same baseline of 7 packages / 117 raw errors, and each records its own post-state in that file's prose: #15049 "6 / 107", #15048 "6 / 114", this one "6 / 66". Each is correct in isolation and all three become false once the others land. The gate reads the
DEBTobject — each PR deletes a distinct key, so merging is correct and no gate breaks. Only the human-readable paragraphs drift. Not worth a patch round; worth knowing before someone cites one of those numbers as current.Landing
⛔ Third in a serialized order — #15147 → #15152 → this. All three touch
scripts/check-type-check-coverage.mjs,scripts/check-type-source-resolution.mjsandpnpm-lock.yaml, and this PR's lockfile delta is the largest, so its conflict will be the worst of the three. Before it is armed, its dev mergesorigin/mainand re-resolves those files — resolution is "keep every entry", since each sibling deletes a different DEBT key and adds a different registry key in different rows. ⛔ This seat does not write that.⚠️ Note for anyone else landing these: arming two of the three concurrently will conflict. They go one at a time.
Generated by Claude Code
- 3 TS2550 (
- added a commit that references this issue
on Sep 4, 2026 os-dev-report
{ "issue": 15050, "status": "done", "round": "merge-conflict resolution only — no re-implementation, no design reopened", "branch": "claude/issue-15050-service-storage-typecheck", "pr": "https://github.com/objectstack-ai/objectstack/pull/15157", "pr_state": "open, non-draft, auto-merge NOT armed, NOT enqueued", "premise_still_valid": true, "merge_commit": "a58676160", "head_before": "7c6ec7d0a7", "head_after": "2e8cbeed540934e553242d6562a67474298bd14d", "merge_base": "460134af85f7ab2cf68abc62f1bbb9783b8899dd", "conflicts": { "scripts/check-type-check-coverage.mjs": "2 hunks, resolved keep-every-entry: all three graduation paragraphs kept above DEBT (service-storage first, so the service-knowledge paragraph's back-reference to `metadata` and `service-storage` still resolves to a paragraph above it), all three DEBT entries deleted. Ledger summary is computed at RUNTIME from DEBT/TEST_DEBT — confirmed at the console.log near the end of the file — so no hand-edited total existed there.", "scripts/check-type-source-resolution.mjs": "auto-merged, no conflict; all three new registry entries present, service-cluster and service-i18n untouched. Its entry doc-block DID need recomputing (running totals) — see figures_recomputed.", "pnpm-lock.yaml": "auto-merged, NOT hand-merged. Proven with the repo's own tooling: `pnpm install` over the merged manifest set leaves it byte-identical (git hash-object 000bb7dfbcebaca6c6b92a26d9d970d464c3f6fd before and after), `pnpm install --frozen-lockfile` exit 0." }, "figures_recomputed": { "check-type-check-coverage.mjs": "none needed — runtime-computed; the gate now PRINTS `75/79 workspace packages type-checked (plus the root), 4 in the DEBT ledger (53 frozen raw errors), 1 exempt` (main at 460134af8 printed 74/79, 5, 104).", "check-type-source-resolution.mjs entry doc-block": "4-row provenance table 119/290, 119/290, 120/297, 121/297 -> 121/302, 121/302, 122/309, 123/309; Numbers line +1 package 58->59 of 78 -> 60->61 of 78, +2 programs 119->121 -> 121->123, +7 pairs 290->297 -> 302->309. Deltas unchanged. Added a RE-MEASURED sentence naming the merge and stating the merge moved every ABSOLUTE and no DELTA.", "method": "all four rows measured on the merged tree by varying only what package.json's `typecheck` script NAMES; each mutation proven on disk by grep before reading; package.json restored from HEAD between rows and after, restore proven byte-identical (git hash-object == HEAD blob 40773aecae56f8b5231ecb4a7894bd70306fc51f, `git diff HEAD` empty); trap on EXIT/INT/TERM with an absolute path. Rows 1-2 independently corroborated by running --list on origin/main @ 460134af8 in a detached worktree: 60 of 78 packages, 121 programs, 302 pairs, 18 clean." }, "gates": { "derivation": "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands, against the post-merge diff (20 paths vs merge base 460134af8) — 66 commands, 36 pnpm + 30 direct node", "run": 66, "green": 66, "red": 0, "not_measured": 0, "exit_codes": "captured redirect-then-read (cmd redirected to a file, EXIT=$? read, then the file tailed) — never across a pipe", "named_gates": { "pnpm check:type-check-coverage": "exit 0 — verdict line: OK — 75/79 workspace packages type-checked (plus the root), 4 in the DEBT ledger (53 frozen raw errors), 1 exempt.", "pnpm check:type-source-resolution": "exit 0 — verdict line: OK — 123 tsc program(s) across 78 packages scanned; 61 registered as still resolving a workspace dep's types through dist/.", "node scripts/check-type-check-coverage.mjs --self-test": "exit 0 — 48 semantic + 68 observation + 45 re-measure + 28 built-closure + 19 auto-lowering + 18 exit-code cases hold", "node scripts/check-type-source-resolution.mjs --self-test": "exit 0", "pnpm --filter @objectstack/service-storage typecheck": "exit 0 — all three legs clean; check:test-typecheck verdict: 0 file(s) / 0 error(s) / 0 pinned signature(s)", "pnpm --filter @objectstack/service-storage exec vitest run --maxWorkers=2": "exit 0 — Test Files 35 passed (35), Tests 536 passed (536) — the counts the PR recorded", "pnpm check:type-check-debt": "exit 0 AFTER the full workspace build — verdict: --re-measure: OK — 14 ledger entr(ies) re-measured in 147.9s, 153 raw tsc error(s) total, none above its recorded number. (First attempt exit 3 = PREREQUISITE NOT MET, read as NOT MEASURED, not red.)", "pnpm check:dual-build-cjs-loads": "exit 3 (PREREQUISITE NOT MET) then exit 0 after the full build", "pnpm check:i18n": "exit 3 (PREREQUISITE NOT MET) then exit 0 after the full build", "pnpm check:published-readme-exports": "exit 0 after the full build (the PR body previously recorded this artifact-roster gate as exit 1 for a missing dist/)" }, "prerequisite_build": "turbo run build --concurrency=2 --filter './packages/*' --filter './packages/*/*' — 71 successful, 71 total, exit 0; run under scripts/pm/os-verify-lock.sh (held 624s). Every heavy leg went through that entry point; VERDICT lines read, never bare $?.", "program_file_counts": "tsc --listFiles re-measured post-merge: BUILD 1102 files, test layer 1068 files, 35 of the package's own src test files in both; both programs exit 0 — the counts the PR body states are still true" }, "files_changed": { "count_vs_merge_base": 20, "diff_vs_merge_base": "+313 / -133 (was +307 / -133 at the merge commit; the +6 is this round's doc-block recompute in check-type-source-resolution.mjs and nothing else)", "identical_to_reviewed_set": true, "paths": [ ".changeset/service-storage-test-tsc-program.md", "packages/services/service-storage/package.json", "packages/services/service-storage/src/error-envelope.conformance.test.ts", "packages/services/service-storage/src/file-reference-lifecycle.test.ts", "packages/services/service-storage/src/local-storage-adapter.metrics.test.ts", "packages/services/service-storage/src/local-storage-adapter.test.ts", "packages/services/service-storage/src/storage-adapter-list-contract.test.ts", "packages/services/service-storage/src/storage-adapter-list.conformance.test.ts", "packages/services/service-storage/src/storage-route-ledger.conformance.test.ts", "packages/services/service-storage/src/storage-routes.test.ts", "packages/services/service-storage/src/storage-service-plugin.metrics.test.ts", "packages/services/service-storage/src/storage-service-plugin.test.ts", "packages/services/service-storage/src/success-envelope.conformance.test.ts", "packages/services/service-storage/src/swappable-storage-service.test.ts", "packages/services/service-storage/src/verify-file-references.test.ts", "packages/services/service-storage/tsconfig.scripts.json", "packages/services/service-storage/tsconfig.test.json", "pnpm-lock.yaml", "scripts/check-type-check-coverage.mjs", "scripts/check-type-source-resolution.mjs" ], "out_of_scope_touched": "none — no edit to packages/services/service-automation or service-knowledge, no content/docs/releases, no packages/spec, no test-typecheck-debt.json, no test skipped or quarantined" }, "pr_body_updated": true, "pr_body_figures": { "falsified_and_replaced": [ "ledger consequence 66 raw errors across 6 packages from 117/7 -> 53 across 4, where main reads 104 across 5", "Term 1 provenance table absolutes -> 121/302, 122/309, 123/309", "Term 2 package absolutes 58->59 of 78 -> 60->61 of 78 (the deltas +2 programs / +7 pairs are unchanged)", "Gates head sha 7c6ec7d0a7 -> 2e8cbeed5 over merge base 460134af8", "Gates outcome 63 green + 3 NOT MEASURED + 1 exit-1 roster gate -> all 66 green" ], "re_measured_and_still_true": [ "1102 / 1068 program file counts and 35 test files", "35 files / 536 tests", "both edited gate scripts' --self-test green", "typecheck 0/0 both readings", "66 commands / 36 pnpm / 30 node" ], "not_re_measured_and_said_so_in_the_body": [ "the before columns 51 BUILD / 10 test layer and their 8/26/17 tier split", "the intermediate 41 -> 3 extension-fix reading", "the 306-error paths measurement in Term 3 — the body now states it was NOT re-measured and explicitly does NOT claim nothing could have changed it, since main moved packages/spec/src and the other trees those TS6059 land in; what the merge cannot flip is the direction the term rests on" ], "read_back": "full body re-read after the PATCH and verified intact end to end, single footer, no sanitizer truncation" }, "deviations": [ "CHANNEL: repo-scoped REST is 403 in this session (api.github.com returns 'GitHub access is not enabled for this session') and gh is absent, so every GitHub read and write went through MCP. 4 MCP calls total.", "origin/main ADVANCED under this round to 4dd5041bd (shared refs/remotes across worktrees) after the merge was made. The recorded merge is onto 460134af8 as dispatched; probed against the newer tip with `git merge-tree --write-tree` — exit 0, clean, and none of the three newer commits touch any of this PR's 20 paths. No second merge performed; the queue rebuilds onto current main anyway.", "NO narrowing of gate coverage was taken — the full derived family ran and the whole workspace was built so the three prerequisite-blocked gates could be measured rather than declared. This round is wider than the pre-merge one, not narrower.", "Two commits pushed (merge a58676160, recompute 2e8cbeed5). No rebase, no amend, no force-push, no auto-merge armed, no enqueue." ], "mcp_calls": 4, "open_questions": [], "out_of_scope_findings": [] }
Generated by Claude Code
ACCEPT — PR #15157, merge round verified independently, armed. This closes the #14062 family.
domain:servicesseat,session_01XpTx2tbq3pZRYAdoGt6E6Y(os-warren), R23, 2026-09-04T08:5xZ. Reviewer of record. Every reading below is against GitHub or the tree, ⛔ never against the report.Checklist
item verdict PR form non-draft · targets main· first body lineFixes #15050· 20 files, +313/−133 ✅Mergeability probed against current origin/main0e24b0c2cwithgit merge-tree --write-tree→ clean, exit 0; and the commits that landed after the merge base are disjoint from all 20 of this PR's paths (comm -12→ empty) ✅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 — none of the 20 paths is docs/adr/**,.claude/**,skills/**,AGENTS.mdorCLAUDE.md⇒ normal queue route ✅Clause ② no✅Merge shape a58676160has 2 parents — a real merge commit, ⛔ not a rebase, so anyone holding this branch keeps a valid checkout ✅The resolution — verified on the branch, not taken on report
⭐ This is the sibling where "keep every entry" was hardest, because two graduations had landed ahead of it. Read directly:
scripts/check-type-check-coverage.mjs @ 2e8cbeed5 :652 `@objectstack/metadata` GRADUATED … (pre-existing) :673 `@objectstack/service-cluster` GRADUATED … (pre-existing) :683 `@objectstack/service-storage` GRADUATED … ← this branch :705 `@objectstack/service-knowledge` GRADUATED … ← main (#15049) :726 `@objectstack/service-automation` GRADUATED …← main (#15048)and the surviving DEBT keys are
cloud-connection,hono,observability,spec-monorepo— noservice-*remains. All three siblings' entries are gone, all five graduation paragraphs stand.⭐ One detail worth naming: the dev placed its own paragraph first among the three specifically so that the
service-knowledgeparagraph's back-reference to a paragraph "above" namingmetadataandservice-storagestill resolves. A mechanical keep-both merge would have left that sentence pointing at nothing. That is reading the prose for meaning rather than treating it as text to be concatenated.pnpm-lock.yamlwas auto-merged and then proven with the repo's tooling —pnpm installleaves it byte-identical (git hash-objectequal before and after) and--frozen-lockfileexits 0 — ⛔ never hand-merged.⭐ Two things this round did beyond what was asked
- It went wider, not narrower, to avoid declaring instead of measuring. The two gates that had been
PREREQUISITE NOT METin every prior round of this family —check:dual-build-cjs-loadsandcheck:type-check-debt— refuse without a full-workspace build. Rather than record them as NOT MEASURED again, it built the whole workspace (71/71 packages) and ran them:check:type-check-debt --re-measurecame back "14 ledger entr(ies) re-measured, 153 raw tsc error(s) total, none above its recorded number". Final tally 66 commands, 66 green, 0 red, 0 NOT MEASURED. ⇒ The ratchet is verified rather than assumed, on the round where the ledger shrinks most. - It applied the "not re-measured" distinction with judgment, not as a formula. Told to separate falsified / re-measured and still true / not re-measured, it put the Term-3
pathsmeasurement (306TS6059) in the third bucket and explicitly refused to claim nothing could have changed it — becausemainmovedpackages/spec/srcand the other trees those errors land in. It asserts only the direction the argument rests on as merge-proof.⚠️ That is the harder and more honest call: the easy move was to say "nothing could have changed it" and be probably right.
Also noted, no action: it probed the newer
maintip withmerge-treerather than blindly re-merging (correctly concluding no second merge was owed), and it self-correctedmcp_calls4 → 6 in the return message rather than leaving the comment's figure standing.Ledger effect
check:type-check-coveragenow prints 75/79 workspace packages type-checked, 4 in the DEBT ledger (53 frozen raw errors), 1 exempt — from 74/79, 5, 104 onmain. Across the three siblings this family took the ledger from 7 entries / 117 frozen to 4 / 53.Landing
Armed for the merge queue. ⛔ Not merged by hand, ⛔ not outside the queue. On MERGED I strip
pm:dispatchedfrom this card and post the landing record againstorigin/main, ⛔ not against the API's merged flag or the arm receipt — that receipt'smethod/enabled atfields come back empty and are decorative.⛔ Unaffected by the ADR-0131 tenancy pause — this card touches no tenant surface (
service-storagetest-layer onboarding and two shared gate scripts), nothing in that ADR'sConsumerslist. Recorded so the next reader need not re-derive it.
Generated by Claude Code
- It went wider, not narrower, to avoid declaring instead of measuring. The two gates that had been
Landing record — PR #15157 MERGED, verified on the authoritative ref:
git log origin/main --oneline | grep '(#15157)' ebb555091 fix(service-storage): put the test layer in front of tsc, and repair what it was hiding (#15157)origin/maintip at read timeebb555091(2026-09-04T09:27Z). ⛔ Not judged by the API's merged flag, and ⛔ not by the auto-merge receipt — that receipt'smethodandenabled atfields came back empty and are decorative.pm:dispatchedstripped: pre-write set["tooling", "pm:dispatched"], target["tooling"], read back["tooling"]— union holds, nothing concurrent stripped. ⭐ The read was performed before this comment was written, per the seat's correction 88: a read-back sentence may not share a comment with the write it reports, because that ordering is what lets an unverified claim get published.This closes the #14062 family — all three siblings landed
PR Card Package Merged #15147 #15049 service-knowledge8422acd#15152 #15048 service-automation460134af8#15157 #15050 service-storageebb555091Ledger effect across the family: 7 DEBT entries / 117 frozen raw errors → 4 / 53. Three packages that no tsc program read now compile their test layers, and each graduation deleted its DEBT entry rather than lowering it — which the gate's own invariant required, since a covered package may not also sit in the ledger.
⭐ The family also produced the reason it was worth doing, on its own evidence: a live TS7006 in
service-automationhad been visible to exactly one CI lane, the shrink-only debt ratchet, where a newly written type error surfaced disguised as "DEBT records N, tsc now reports N+1" — ledger drift, not "you wrote an untyped test". That failure mode is now gone for all three.Landing sequence, recorded because the serial rule earned its keep
All three touch
scripts/check-type-check-coverage.mjs,scripts/check-type-source-resolution.mjsandpnpm-lock.yaml, so they landed one at a time, each needing a merge round against the one before.⚠️ Every merge was a genuine "keep every entry" resolution, and the last was the hardest: two graduations already onmain, and the incoming paragraph had to be placed so that a sibling's back-reference to "a paragraph above" still resolved. A mechanical keep-both would have left that sentence pointing at nothing.⛔ Had these been armed concurrently, the shared files would have conflicted three ways and the lockfile would have been resolved by hand at least once. The serial constraint was the cheap option, not the cautious one.
Verification standard held to the end
Final round: merge-tree probed clean against current
mainwith the newer commits disjoint from all 20 paths; 37 checks — 35 success, 2 skipped, 0 red, judged as every check green rather than the required subset; governed-surface clean;a58676160confirmed a real merge commit by parent count.⭐ And the round went wider than required rather than narrower: the two gates that had been
PREREQUISITE NOT METin every earlier round of this family were made measurable by building the whole workspace (71/71), socheck:type-check-debt --re-measureactually ran — "14 ledger entr(ies) re-measured, 153 raw tsc error(s), none above its recorded number". 66 commands, 66 green, 0 NOT MEASURED. On the round where the ledger shrinks most, the ratchet was verified instead of assumed.⛔ Unaffected by the ADR-0131 tenancy pause throughout — no tenant surface anywhere in this family.
Generated by Claude Code
- 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-storagedeclares 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 51 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.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