Uh oh!
There was an error while loading. Please reload this page.
refactor(spec): rename ./system's ServiceStatus to KernelServiceStatus (#6604) - #7240
Conversation
…6604) `ServiceStatus` was published by two entry points for two disjoint concepts: `./api`'s discovery health enum and `./system`'s kernel service state object. Per the maintainer's 2026-08-08 Option-B ruling the kernel side takes the domain-specific name, matching its `KernelServiceMapSchema` sibling, and `./api` keeps its published name untouched. This is what finally lets `./system` declare the `KernelServiceStatus` type alias #4593's backfill had to skip: declaring `ServiceStatus` on both entry points would have minted the #4411 dual-source trap that `dual-source-exports.baseline.json` stays empty to prevent. Routed through `RENAMED_DEFS` rather than the retirement kit — all 6 authorable keys carry, so nothing left the author-facing contract. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PiRUoQkTSBBmpyXBY3cVn2
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
📓 Docs Drift CheckThis PR changes 1 package(s): 106 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
⛔ 7 release-owned page(s) also reference the affected code. These are read-only:
|
Uh oh!
There was an error while loading. Please reload this page.
Closes#6604
Executes the maintainer's 2026-08-08 ruling verbatim. Scope line, quoted:
Premise re-measured on
origin/main@3566e5520All three legs of the issue's premise still held at dispatch time:
./apideclares aServiceStatusenumapi/discovery.zod.ts:22const +:33type export — live./systemdeclares a differentServiceStatusSchemasystem/core-services.zod.ts:229, afeatures-bearing object — livedocs-import-surface.baseline.json:45— livedual-source-exports.baseline.jsonentries: []— emptyChanges
packages/spec/src/system/core-services.zod.tsServiceStatusSchema→KernelServiceStatusSchema; newexport type KernelServiceStatus = z.input< typeof KernelServiceStatusSchema >; docblock records why the prefix existspackages/spec/scripts/lib/renamed-defs.tsRENAMED_DEFSentrysystem/ServiceStatus→system/KernelServiceStatus, 6 keys carriedpackages/spec/src/type-alias-convention.pin.test.tsIso835; count 823 → 824 in the assertion and both prose statements; receipt paragraphpackages/spec/docs-import-surface.baseline.jsonsystem/ServiceStatus — no type exportrow deleted (shrink-only ratchet)packages/spec/src/system/core-services.test.tspackages/spec/scripts/schema-index.test.tsjson-schema.manifest/system.json,authorable-surface/system.json,api-surface/system.json,export-origins/system.json,content/docs/references/system/core-services.mdx,content/docs/references/index.mdxThe
./apienum is untouched, anddual-source-exports.baseline.jsonis unmodified and still empty — the collision is resolved at its source, not baselined.Why
RENAMED_DEFSand not the retirement kitThe first build failed the way the ruling did not anticipate: the manifest ratchet saw
json-schema/system/ServiceStatus.jsondisappear and demanded a deliberate manifest deletion plus aRETIRED_DEFS_BY_MAJORentry. That is the wrong claim here — nothing was retired.packages/spec/scripts/lib/renamed-defs.tsis the channel built for exactly this case (#4684, ADR-0112 D9a), and its docblock rejects the retirement route in as many words: a tombstone would have "no live def to hang on" and would "pollute the ADR-0087 registries with a migration consumers must not run".Routed through the rename table, all 6 authorable keys carry and the ratchets go green on their own terms:
api/ServiceStatusis deliberately absent from the table — it is still emitted, so the table would (correctly) reject it as a copy rather than a rename.Gates
Build ran before every dist-derived regen (stale-dist trap #7122). Dual-snapshot rule applied in full: this is one export removed and two added, so
api-surface/andexport-origins/were both regenerated after the real build.pnpm --filter @objectstack/spec buildcheck:generatedAll 11 generated artifacts are up to date.check:docsimport examples resolve against api-surface/ (62 accepted gap(s) in the baseline)— was 63check:dual-source-exports4801 names across 16 entry points — 170 re-exported, 0 accepted dual-source (baseline)check:api-surfacepublic API surface + factory signatures unchangedcheck:export-origins4971 exports across 16 entry points resolve exactly as recordedcheck:authorable-surface1587 schemas,1277 default(s) unchangedcheck:spec-parsed-alias1509 bare z.input aliases, 824 pinned isomorphic, 685 paired with an XParsed. OKpnpm --filter @objectstack/spec test360 passed (360)/9397 passed (9397)pnpm --filter @objectstack/spec typecheckcheck:empty-changeset/check:adr-0087-registration/check:changeset-no-majorcheck:nul-bytes6619 text file(s) ... no raw ASCII control bytesReverse verification — directions predicted before running
Both probes were predicted first, then run; both landed as predicted.
Prediction 1 — restore the deleted baseline row ⇒ RED as a STALE entry (not as a gap: the def key
system/ServiceStatusis now emitted by nothing). Confirmed:Prediction 2 — remove
KernelServiceStatusfrom the export surface ⇒ RED as a NEW gap, under the NEW name. Confirmed:Together these pin that the baseline-row deletion is load-bearing in both directions: the row cannot stay, and it cannot be replaced by its renamed twin. Probes were taken out with a file copy and
git checkout, nevergit stash.The alias's isomorphism is proven rather than asserted:
Iso835is anAssert< Eq< z.input, z.infer > >compiled by tsc undertsconfig.test.json, so it is a compile error the day the schema gains a.default().Consumers repointed
Grepped all three repos (
objectstack,objectui,cloud) for the old const:packages/spec/src/system/core-services.test.ts— 8 occurrences, repointed.content/docs/references/system/core-services.mdx+references/index.mdx— regenerated, not hand-edited.Special inspection
Two synthetic fixtures still spell
ServiceStatusSchemaon purpose.packages/spec/scripts/schema-index.test.ts(2) andscripts/def-key-collisions.test.ts(2) pass the name as string literals into pure functions; they import nothing. What they pin is that cross-category same-name resolution is correct whenever it occurs — a rename retires the specimen, not the property. Rewiring them to whatever names collide onmaintoday would make the coverage evaporate at the next tidy-up. Only the stale claim was fixed:schema-index.test.tssaid "The live specimen onmain", which this PR falsifies, so the comment now records thatServiceStatus在 ./api 与 ./system 各有一个不同声明,#4593 的别名补齐卡在这个名字上 #6604 retired it.def-key-collisions.test.tsclaims no liveness and is untouched.Changeset class — the one place I did not follow a written instruction, flagged for your call.
renamed-defs.ts's docblock says an entry there "rides with amajorchangeset spelling FROM → TO", and the closest precedent (spec 双源清账 C17:ActionLocationSchema(./studio ≠ ./ui)—— studio 侧 D9(a) 改名,1 条 #4737studio/ActionLocation) ismajor. I shippedminorinstead, because the dispatch specified non-major and becausecheck-changeset-no-major's own docblock states the current convention: "During the launch window we ship breaking changes asminor". No gate enforces either class — I checked; the prose is convention-only, andcheck-changeset-no-majoris stood down anyway while.changeset/pre.jsonis in"mode": "pre". The changeset still spells FROM → TO as the docblock requires. If you prefermajor, it is a one-word edit, but note it would then tripcheck-adr-0087-registration, which would need anadr-0087: not-requireddisposition — and perrenamed-defs.tsa pure rename genuinely has no metadata migration to register.RETIRED_DEFS_BY_MAJORdeliberately untouched — an entry there would falsely claim the metadata contract shrank. It did not: every key carries.Generated by Claude Code