Skip to content

feat(spec)!: retire kernel/package-upgrade.zod.ts whole — the upgrade plan, diff, snapshot and rollback model nothing implemented (ADR-0049) - #25757

Draft
objectstack-fleet[bot] wants to merge 8 commits into
mainfrom
claude/issue-25608-retire-package-upgrade
Draft

objectstack-fleet[bot] wants to merge 8 commits into
mainfrom
claude/issue-25608-retire-package-upgrade

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #25608
Clause-②: no (narrowing)
Metadata-protocol: narrowed
Ruling-ref: 6259332195 (ruling A on #24443, item 3); triage first grade 6382810541

Retires packages/spec/src/kernel/package-upgrade.zod.ts whole — the package upgrade plan, metadata diff, impact level, pre-upgrade snapshot, upgrade and rollback request/response pairs and the phase vocabulary — together with the four IPackageService members that returned them (planUpgrade, upgrade, rollback, getSnapshot) and their three input interfaces, and the plan member of PackageUpgradeResponse.data. ADR-0049 enforce-or-remove, route 3 (whole-def removal). Nothing ever implemented, served or read any of it.

The two governed sentences (ADR-0126 about :321, and the ADR-0138 D5 sentence ruling A 6386464761 orders) ride their own draft PR, #25716, which merges after this one.

Ruling executed (quoted, not re-ruled)

Ruling 6259332195 on #24443, letter A, maintainer 「其他同意」, item 3: "Retired: packages/spec/src/kernel/package-upgrade.zod.ts (plan, diff, conflict, snapshot, rollback; zero runtime consumers), with its ADR-0087 conversion." Triage 6382810541: done directly in 18.x with no retirement stage.

Premise re-measured (every zero beside a lit control)

reading tree retired names (29) + planUpgrade + the module specifier control
objectstack, outside packages/spec, CHANGELOGs excluded base 47af3dde42 0 code files: 3 generated reference pages + references/kernel/meta.json, content/docs/upgrading.mdx, one ADR-0126 sentence the same pattern hits 17 files inside packages/spec
objectui main a3c0da9 0 files @objectstack/spec: 2123 files
objectui at the pinned .objectui-sha 2958f17e9c 0 files @objectstack/spec: 2131 files
hotcrm main a4b3560 0 files @objectstack/spec: 293 files
providers base nothing implements IPackageService —

The card's inventory held, with two additions it did not list: src/system/compliance-families-retirement.test.ts used MetadataChangeType as its "live near-namesake" must-survive control (its only reader was the retired module itself; the control is now BreakingChange), and the contract lost four members and three input interfaces, not two — rollback and getSnapshot returned the retired RollbackPackageResponse / UpgradeSnapshot as well.

Why no D2 conversion and no tombstone

None of the ten shapes is a stack collection member or a metadata type, so there is no authored document a D2 conversion could rewrite and no carrier key a retiredKey() tombstone could sit on. The ruling's "ADR-0087 conversion" is therefore the ledger record, exactly as for the export-job and change-management whole-family retirements: ten RETIRED_DEFS_BY_MAJOR[18] entries (which the manifest-deletion gate reads), one D3 semantic entry kernel-package-upgrade-family-retired, and one STEP18_RATIONALE fragment. The UpgradePlan.estimatedDuration tombstone's RETIRED_KEYS_BY_MAJOR[18] entry and the D3 entry kernel-package-lifecycle-durations-unit-in-key stay as history (pinned). PackageUpgradeResponse.data is a non-strict object bound to no route, so its plan leaves without a tombstone (route 3: nothing parses it); a pin asserts a stray plan is stripped.

What changed

  • Removed: src/kernel/package-upgrade.zod.ts and its test; the re-export in src/kernel/index.ts (a comment block stays in its place naming the retirement); the upgrade section of src/contracts/package-service.ts and its test cases; plan in src/api/package-api.zod.ts.
  • Registered: src/migrations/entries/retired-defs/18.kernel__*.ts ×10, src/migrations/entries/semantic/18.kernel-package-upgrade-family-retired.ts, a STEP18_RATIONALE fragment in src/migrations/registry.ts.template.
  • Pinned: src/kernel/package-upgrade-family-retirement.test.ts (listed in vitest.repo-tests.json; its walk radius is the one already declared for @objectstack/spec in scripts/cross-package-test-inputs.mjs): zero holders on every public entry, runtime namespaces, the four contract members absent at the type level with a lit control, plan absent from the shape, module gone from disk and unimported, shards clean, ledger wired with no D2 conversion, and tree-scoped absence across packages, examples, skills, content, scripts.
  • Generated (regenerated, not hand-typed): json-schema.manifest/kernel.json (−10, deleted deliberately as the manifest-deletion gate requires), authorable-surface/kernel.json (−48, the whole-def route; check (c) re-proved it against the git base), authorable-defaults/kernel.json, api-surface/{kernel,contracts}.json, declaration-map/kernel.json, export-origins/{kernel,contracts}.json, dropped-refinements.baseline.json (two entries and their header totals), the strictness-ledger counts, and content/docs/references/** (the package-upgrade page is gone).
  • Count pins that follow the module: type-alias-convention.pin.test.ts 790 → 786 (four isomorphic pins and the M92 import), scripts/file-description.test.ts 31 → 30 level-1 openers, llms.txt 206 → 205 schemas / kernel 31 → 30, quick-reference.mdx kernel 30 → 29.
  • Hand-written docs made false by the diff: content/docs/upgrading.mdx described a package-upgrade lifecycle (pre-check, plan, snapshot, …) and linked the removed page; it now says what the platform serves — a re-install with overwrite: true and the commit rollback — and links Package Management in the Metadata API.
  • Changeset: .changeset/25608-retire-package-upgrade.md, minor (launch-window convention) with the BREAKING banner, the FROM → TO table, both declaration lines and registered kernel-package-upgrade-family-retired.

Tests and gates

All readings below are at head 3e7b204be7 (after merging origin/main c61f75d10f through scripts/pm/os-regen-merge.sh, then pnpm install --frozen-lockfile, a full turbo run build and @objectstack/spec build + check:generated), under scripts/pm/os-verify-lock.sh, exit codes captured before any pipe.

command result
pnpm --filter @objectstack/spec typecheck exit 0
pnpm --filter @objectstack/spec test exit 1: 21787 passed, 23 failed, all 23 in scripts/liveness/check-liveness.test.ts, each naming the main-red below
pnpm --filter @objectstack/spec test:repo exit 0: 80 files, 1279 tests
pnpm --filter @objectstack/cli test (unit and integration projects) exit 0: 501 files, 6297 tests
pnpm --filter @objectstack/dogfood test (the (narrowing) arm's full battery) exit 0: 295 files, 2520 tests
pnpm --filter @objectstack/metadata-protocol test (pre-merge head 80ed3baba1) exit 0: 263 files, 21485 tests
plugin-audit sys-comment-retired-fields.test.ts, service-automation decision-overlapping-edge-conditions.pin.test.ts (both read the ledger; pre-merge) exit 0 each
node scripts/check-platform-checklist.mjs --changed-from origin/main exit 0: no checklist anchor in the change set

Derived gates. node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at 3e7b204be7: 120 families. Every one run; --ran reconciles: "120 derived famil(ies) accounted for — 120 run, 0 NOT-MEASURED (a DERIVED zero — all 120 recorded an exit code and none of them is 3)". 118 exit 0, including check-adr-0087-registration, check-changeset-no-major, check-empty-changeset, check:api-surface, check:authorable-surface, check:docs, check:llms-txt, check:quick-reference-counts, check:spec-parsed-alias, check:cross-package-test-inputs and check:nul-bytes. Two are red, both the main-red below: check:liveness and check:generated (whose only stale artifact is liveness/state-counts/).

Main-red, not this PR's. check:liveness refuses translation/flows.screens → packages/services/service-automation/src/engine.ts: the citation names a file that no longer names the property. Reproduced on a clean origin/main c61f75d10f worktree (exit 1, same line). The service-automation refactors that moved bodies out of engine.ts (#25725, #25734) moved renderFlowTextSlot to packages/services/service-automation/src/node-text-rendering.ts. The proposed patch, not carried here because it is outside this diff: in packages/spec/liveness/translation.json, re-point that row's engine.ts#renderFlowTextSlot evidence to node-text-rendering.ts#renderFlowTextSlot. No fix PR existed to port when this was measured.

Ablation (reverse verification of the pin). The pin imports src, so there is no dist/ leg. Through node scripts/ablation-replace.mjs on the committed tree, I replaced the retirement comment in src/kernel/index.ts with export * from './package-upgrade.zod'; (anchor 1 → 0, blob baf1437875cf → cc18be2f5671) and restored the module from the base under an EXIT trap. Predicted red: runtime namespaces, module-on-disk / importer, and the tree-scoped walk. Predicted green: export-origin holders (they read the committed artifact), shards, registration, the contract type and the plan shape. Observed exactly that: 3 red, 7 green. The restore was blob-identical to HEAD (baf1437875cf), git diff HEAD was empty, and the restored module was deleted. A first attempt was a recorded no-op (its replacement kept the anchor, so the tool refused it) and is not counted.

Downstream. objectui main a3c0da9 / pin 2958f17e9c, and hotcrm a4b3560: zero hits (table above). No objectui fix or pin bump is needed.

Acceptance notes

  • content/docs/protocol/kernel/lifecycle.mdx § Upgrades describes objectstack upgrade strategies and pre-upgrade backups as design intent, flagged as such at the top of the page; it never cited the retired spec and this diff does not make it false. Not touched.
  • PackageUpgradeRequestSchema / PackageUpgradeResponseSchema stay published and bound to no route (recorded by the existing D3 entry package-api-contracts-unmounted-entries-retired); retiring them is outside this card.
  • The D3 entry change-management-family-retired (history) still says kernel/MetadataChangeType was "a different declaration with a live consumer" and "unaffected". That was true of that retirement; its only reader was the module retired here. Left as history.

🤖 Generated with Claude Code

https://claude.ai/code/session_01T5pRzjp4QpCwioKZ9Gt5tC


Generated by Claude Code

…for the retired defs

Claude-Session: https://claude.ai/code/session_01T5pRzjp4QpCwioKZ9Gt5tC
Co-authored-by: Claude <noreply@anthropic.com>
… demotion count follow the retirement

Claude-Session: https://claude.ai/code/session_01T5pRzjp4QpCwioKZ9Gt5tC
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec, touching 48 documentable anchor(s). ⚠️ 23 changed file(s) yielded no anchor (packages/spec/api-surface/contracts.json, packages/spec/api-surface/kernel.json, packages/spec/authorable-defaults/kernel.json, …), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

22 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: node scripts/docs-audit/affected-docs.mjs --json 5874d25302cbb80db675eddf1b69198073fbe2a9.

⛔ 10 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails.

What this run could not see
  • 23 changed file(s) yielded no anchor (packages/spec/api-surface/contracts.json, packages/spec/api-surface/kernel.json, packages/spec/authorable-defaults/kernel.json, …) — pages documenting those are invisible to this run
  • 1 cross-cutting symbol(s) contributed no route anchor: packageId (4 routes)
  • 6 name(s) were too generic to anchor anything (single lowercase words)
  • the SDK route bridge reached 54 of 206 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 144 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 5874d25302cbb80db675eddf1b69198073fbe2a9 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 9fa3f3f5a4b0ef05276d132f7501847a71b274c2 — the merge of head 3e7b204be77b8f04ff227a829a70af1d064f6c0c into base 5874d25302cbb80db675eddf1b69198073fbe2a9, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 9fa3f3f5a4b0ef05276d132f7501847a71b274c2 && git checkout 9fa3f3f5a4b0ef05276d132f7501847a71b274c2
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 5874d25302cbb80db675eddf1b69198073fbe2a9 3e7b204be77b8f04ff227a829a70af1d064f6c0c && git checkout -B drift-repro 5874d25302cbb80db675eddf1b69198073fbe2a9 && git merge --no-ff 3e7b204be77b8f04ff227a829a70af1d064f6c0c

node scripts/docs-audit/affected-docs.mjs --json 5874d25302cbb80db675eddf1b69198073fbe2a9

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 5874d25302cbb80db675eddf1b69198073fbe2a9 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对

ACCEPT · #25608 · domain:spec seat 2 (seat post #18549) · sunhaolin · session session_01PC4NPXPgPmpDRG9DdDnyXT · 2026-10-25T06:52Z · head 3e7b204be7 · report 6394223748 (on #25608; cloud session session_01T5pRzjp4QpCwioKZ9Gt5tC) · seat review at TIER_DEFAULT. A removal from packages/spec/src/**, so a same-shape ## Contract review PASS at CONTRACT_REVIEW_TIER on the landing head is owed. needs:contract-review is added in this stroke.

  1. Shape. Draft, base main, first line Fixes #25608, title feat(spec)!:. Clause-②: no (narrowing), Metadata-protocol: narrowed and Ruling-ref: 6259332195 are line-initial in the body and in the changeset (@objectstack/spec minor under the launch-window convention, with the BREAKING banner, FROM → TO, and registered kernel-package-upgrade-family-retired). 44 files, +642/−1374. check-governed-merges --pr 25757: NOT governed, 2016 lines (under 3000). The governed half (the ADR-0126 and ADR-0138 D5 sentences) is docs(adr): ADR-0126 stops deferring the package-upgrade.zod.ts retirement; ADR-0138 D5 says who opens a future site binding #25716, which os-zhuang merged at 2026-10-25T03:18:59Z. The body's "merges after this one" is stale on that point. Acceptance note, no carrier: the ADR text describes the retirement this PR makes.

  2. The ruling, measured on the diff. Ruling A on [Decision] A vendor package upgrade checks nothing: a rename silently re-enables what the customer switched off, and orphans, collisions and broken references go unreported, for every metadata type #24443, item 3 (「Retired: packages/spec/src/kernel/package-upgrade.zod.ts … with its ADR-0087 conversion」), done directly in 18.x per triage 6382810541:

    • Removed: the module and its test, and the kernel/index.ts re-export (a comment names the retirement in its place).
    • Removed from IPackageService: four members (planUpgrade, upgrade, and also rollback / getSnapshot, which returned retired types too), plus three input interfaces.
    • Removed: plan from the non-strict, unbound PackageUpgradeResponse.data.
    • The card's lead was corrected by measurement: four members and three interfaces, not two.
    • The ADR-0087 record: 10 RETIRED_DEFS_BY_MAJOR[18] entries, which the manifest-deletion gate reads, plus one D3 semantic entry and one STEP18_RATIONALE fragment. There is no D2 conversion and no tombstone, because no stack collection or metadata type carries these shapes. That is the export-job / change-management precedent, open question 1 A.
  3. Producers: 0, each beside a lit control.

    • objectstack outside packages/spec (control: 17 hits inside it).
    • objectui main a3c0da9 and its pin 2958f17e9c (2123 / 2131 spec importers).
    • hotcrm a4b3560 (293).
    • Nothing implements IPackageService.
  4. Gates.

    • At 3e7b204be7 (with origin/main c61f75d10f merged; frozen install, full build):
    • At the pre-merge head: metadata-protocol 263 / 21485.
    • Ablation: the re-export put back. Predicted 3 red / 7 green, observed exactly that. Restored blob-identical.
    • Generated shards were regenerated, not hand-typed. The count pins follow the module: type-alias 790→786, file-description 31→30, llms.txt 206→205, quick-reference kernel 30→29.
  5. Open questions.

    • (1) The ledger record in place of a D2 conversion. A: there is no authored document to rewrite.
    • (2) PackageUpgradeRequestSchema / PackageUpgradeResponseSchema. A: left as they are. The ruling names only package-upgrade.zod.ts. Recorded, no carrier.
  6. Deviations accepted.

    • The claim's "conversion with its tombstone" wording assumed a carrier key that does not exist. The dev followed the measurement.
    • The scope widened only where the removal forced it.
    • No PR subscription, per the role file.
    • mcp_calls 4, all reads. Relay writes 3.
    • content/docs/upgrading.mdx was rewritten to say what is served (a re-install with overwrite: true, plus commit rollback).
  7. Landing. Not governed. Two things block it:

    Once both are in main: the seat sends pr_update_branch through the relay, then the CONTRACT_REVIEW_TIER review runs on that landing head. On PASS with every check green, the seat sends pr_ready + automerge_enable.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 3e7b204be77b8f04ff227a829a70af1d064f6c0c
Local-runs: none
Scope: packages/spec/src/api/package-api.zod.ts, packages/spec/src/contracts/package-service.ts, packages/spec/src/kernel/index.ts, packages/spec/src/kernel/package-upgrade.zod.ts, packages/spec/src/migrations/entries/retired-defs/18.kernel__MetadataChangeType.ts, packages/spec/src/migrations/entries/retired-defs/18.kernel__MetadataDiffItem.ts, packages/spec/src/migrations/entries/retired-defs/18.kernel__RollbackPackageRequest.ts, packages/spec/src/migrations/entries/retired-defs/18.kernel__RollbackPackageResponse.ts, packages/spec/src/migrations/entries/retired-defs/18.kernel__UpgradeImpactLevel.ts, packages/spec/src/migrations/entries/retired-defs/18.kernel__UpgradePackageRequest.ts, packages/spec/src/migrations/entries/retired-defs/18.kernel__UpgradePackageResponse.ts, packages/spec/src/migrations/entries/retired-defs/18.kernel__UpgradePhase.ts, packages/spec/src/migrations/entries/retired-defs/18.kernel__UpgradePlan.ts, packages/spec/src/migrations/entries/retired-defs/18.kernel__UpgradeSnapshot.ts, packages/spec/src/migrations/entries/semantic/18.kernel-package-upgrade-family-retired.ts, packages/spec/src/migrations/registry.ts.template + .changeset/25608-retire-package-upgrade.md, packages/spec/src/kernel/package-upgrade-family-retirement.test.ts, packages/spec/src/kernel/package-upgrade.test.ts, packages/spec/src/api/package-api.test.ts, packages/spec/src/contracts/package-service.test.ts, packages/spec/src/system/compliance-families-retirement.test.ts, packages/spec/src/type-alias-convention.pin.test.ts, packages/spec/scripts/build-docs.ts, packages/spec/scripts/file-description.test.ts, packages/spec/vitest.repo-tests.json, packages/spec/json-schema.manifest/kernel.json, packages/spec/authorable-surface/kernel.json, packages/spec/authorable-defaults/kernel.json, packages/spec/api-surface/kernel.json, packages/spec/api-surface/contracts.json, packages/spec/declaration-map/kernel.json, packages/spec/export-origins/kernel.json, packages/spec/export-origins/contracts.json, packages/spec/dropped-refinements.baseline.json, packages/spec/llms.txt, docs/audits/2026-07-unknown-key-strictness-ledger.counts/kernel.md, content/docs/upgrading.mdx, content/docs/getting-started/quick-reference.mdx, content/docs/references/api/package-api.mdx, content/docs/references/index.mdx, content/docs/references/kernel/index.mdx, content/docs/references/kernel/meta.json, content/docs/references/kernel/package-upgrade.mdx (cited, read at the head or on origin/main: packages/spec/scripts/build-schemas.ts, scripts/check-adr-0087-registration.mjs, .claude/skills/spec-property-retirement/SKILL.md, packages/spec/src/migrations/entries/README.md, packages/spec/src/migrations/entries/semantic/18.package-api-contracts-unmounted-entries-retired.ts, packages/spec/src/migrations/entries/retired-keys/18.kernel__UpgradePlan__estimatedDuration.ts, packages/spec/src/migrations/entries/semantic/18.kernel-package-lifecycle-durations-unit-in-key.ts, packages/spec/authorable-surface.base.json, packages/spec/authorable-surface/api.json, packages/spec/liveness/translation.json, scripts/pm/clause2-line.mjs, scripts/pm/dispatch-gates.mjs, scripts/pm/check-governed-merges.mjs, scripts/cross-package-test-inputs.mjs, turbo.json, packages/runtime/src/domains/packages.ts, packages/runtime/src/route-ledger.ts, packages/spec/src/kernel/plugin-versioning.zod.ts, content/docs/api/metadata-api.mdx, .objectui-sha, docs/adr/0126-packaged-metadata-customization-model.md as #25716 left it)

Rendered 2026-10-25T09:25Z on PR #25757 at head 3e7b204be7 (base c61f75d10f, 44 files, +642/−1374), against card #25608 (body and all four comments: triage 6382810541, claim 6390284569, dispatch 6390382970, dev report 6394223748), ruling A on #24443 item 3 (6259332195), the merged ADR half #25716 (4cc17db3c0), and the 48 check-runs on the head. Read-only: the diff with git diff against the pinned base sha, the head's files with git show, anonymous REST for the board, scripts/pm/ci-failure.mjs --pr 25757 for the gates. The dispatching seat's ACCEPT (6394585108) was read as one input and re-measured, not adopted.

① Derived judgments

R1 — the removal takes what the ruling names, plus what it forced, and nothing else. Right. kernel/package-upgrade.zod.ts had 26 exports at the base (10 *Schema consts, 16 type aliases) and leaves whole; the kernel/index.ts re-export is replaced by a comment naming the retirement (the plugin-runtime precedent the retirement skill cites). Forced, each traced in the cited code: the four IPackageService members — planUpgrade and upgrade as the card said, and rollback / getSnapshot because they returned RollbackPackageResponse / UpgradeSnapshot — with their three input interfaces (PlanUpgradeInput, ExecuteUpgradeInput, RollbackInput, read by no other declaration); PackageUpgradeResponse.data.plan, which carried UpgradePlanSchema; the M92 import and its four isomorphic pins in type-alias-convention.pin.test.ts (790 → 786, the other six defs carried XParsed aliases and were never pinned there); the file-description level-1 opener count (31 → 30, one # Package Upgrade Protocol); build-docs.ts SECTION_GROUPS; and the compliance-families-retirement.test.ts must-survive control, whose MetadataChangeType lost its only reader with this module (BreakingChangeSchema from kernel/plugin-versioning.zod.ts, exported through kernel/index.ts at the head, is a sound replacement). The 29 names the PR counts = 26 + 3. Nothing outside the ruling's item 3 is touched: PackageUpgradeRequestSchema / PackageUpgradeResponseSchema stay published (right — see ③, open question 2).

R2 — plan leaves a non-strict, unparsed object without a tombstone. Right, by the skill's own fork. The retirement skill's route table has a row for exactly this: a shape nobody parses takes neither retiredKey() nor a guidance-map entry, because a prescription no one can receive is noise. Measured at the head: nothing outside packages/spec names PackageUpgradeRequest/PackageUpgradeResponse (only the changeset); the D3 entry package-api-contracts-unmounted-entries-retired already records both schemas as bound to no route; authorable-surface/api.json carries only the top-level rows api/PackageUpgradeResponse:{data,error,meta,success}, so data.plan was never a surface row and no api/ shard moves. The new pin in package-api.test.ts asserts a stray plan is stripped beside a lit sibling control — the right pin for a route-3 removal.

R3 — the ADR-0087 carrier is the ledger record, not a D2 conversion or a tombstone. Right. None of the ten defs is a stack collection or a metadata type; the skill's §3 says a surface with no authored source to rewrite takes the D3 semantic entry alone, and the manifest-deletion gate in build-schemas.ts (#4725) requires one RETIRED_DEFS_BY_MAJOR entry per deleted manifest key. The PR supplies exactly that: ten entry files named per entries/README.md (18.kernel__X.ts, export const entry = 'kernel/X'), the ten manifest keys deleted (json-schema.manifest/kernel.json −10, the exact set), one SemanticMigration with all five required fields (surface backtick-free as the upgrade guide needs, reason stating why D3 and not D2, acceptanceCriteria naming the TS2305/TS2339 compiler evidence), and one STEP18_RATIONALE fragment inserted at its id's sort position (between hook-body-… and list-view-…) with order: 109 = highest existing + 1, as the list's header prescribes. Same carrier as the export-job and change-management precedents in entries/retired-defs/18.api__* / 18.kernel__MetadataChangeOperation.ts. The ruling's phrase "with its ADR-0087 conversion" is thereby executed as the record the ADR offers for this class; the merged ADR-0126 sentence (#25716) describes the same retirement and is consistent. The retained history — RETIRED_KEYS_BY_MAJOR[18] kernel/UpgradePlan:estimatedDuration and D3 kernel-package-lifecycle-durations-unit-in-key — is untouched and pinned; right, a registration is never deleted.

R4 — the generated artifacts move the way a whole-def retirement must. Right. The skill's visibility table says a whole-def removal MUST move all four ratchets; it did, and nothing was added: api-surface −29/+0 (26 kernel + 3 contracts interfaces), declaration-map −20, export-origins −29, authorable-surface/kernel.json −48/+0 across the seven non-enum defs, authorable-defaults −8, dropped-refinements.baseline.json −2 entries with its header totals (245→243, 835→831), the reference page deleted and the kernel counts 30→29 / 161→151 followed through references/index.mdx, kernel/index.mdx, meta.json, llms.txt (206→205) and quick-reference.mdx. authorable-surface.base.json is rightly NOT touched: build-schemas.ts makes it the deletion gate's anchor, a mirror of an already-merged upstream commit that a PR must never rewrite — the card's listing it among the regenerate targets was wrong, and the dev did not follow it. The liveness ledger (packages/spec/liveness/*.json) carried no row for any retired def at the head, so there is no orphan row for the main-red below to hide. Lint & Repo Gates and TypeScript Type Check (which carries check:api-surface, check:authorable-surface, check:docs, check:spec-changes, check-adr-0087-registration, check:cross-package-test-inputs) are success on the head.

R5 — producers are zero, re-measured here beside a lit control. Right, with one stale citation corrected. In this repository at the head, outside packages/spec and CHANGELOGs: the changeset and the one ADR-0126 sentence (now history, rewritten by #25716); control: 27 files inside packages/spec. objectui origin/main 0063f22ce: 0 (the three .getSnapshot( hits are assistantBus.getSnapshot() in app-shell, an unrelated store; control @objectstack/spec: 2133 files). objectui at the .objectui-sha pinned AT THIS HEAD, b41ed7f68956: 0 (control 2126). HotCRM origin/main a7faf819: 0 (control 294). No class implements IPackageService. The dev's and the seat's census name pin 2958f17e9c, which was the pin at the dev's base 47af3dde42; #25735 moved it to b41ed7f6 before the dev merged c61f75d10f, and the merge was not followed by a re-measure. 2958f17e9c is an ancestor of b41ed7f6, and the zero holds at the current pin, so no objectui fix or pin bump is owed; the stale sha survives only in the PR body, the dev report and the pin test's header comment (prose, not an assertion).

R6 — the new pin is inside its declared radius. Right. package-upgrade-family-retirement.test.ts is listed in vitest.repo-tests.json; its walk over packages, examples, skills, content, scripts with the stated extension sets is covered by the @objectstack/spec globs in scripts/cross-package-test-inputs.mjs and the @objectstack/spec#test:repo inputs in turbo.json (packages/**/*.{ts,…,yml}, examples/**/*.{json,md,mdx,yaml,yml}, skills/**, content/**, scripts/**). Its anti-vacuity probes (matcher positives and negatives, visited floor, surviving neighbours) are present.

R7 — the hand-written prose made false by the diff was corrected truthfully. Right. upgrading.mdx now says what the platform serves; both replacements it and the changeset prescribe exist at the head: a re-install with overwrite: true (package-api.zod.ts, body or ?overwrite=true) and the ADR-0067 commit rollback POST /packages/:id/rollback with commitId (served in packages/runtime/src/domains/packages.ts, declared in packages/runtime/src/route-ledger.ts with RollbackToPackageCommitResponseSchema, SDK packages.rollback); the new link target /docs/api/metadata-api#package-management is a heading on that page. Check Documentation Links is success.

② Semver level

.changeset/25608-retire-package-upgrade.md: '@objectstack/spec': minor with the **BREAKING** banner — right under the launch-window convention check-changeset-no-major.mjs enforces (breaking records as minor outside pre-mode; the body says so in words). Metadata-protocol: narrowed is the right kind (ten defs and 48 authorable rows leave the surface, plan is removed) and demands at least minor. Clause-②: no (narrowing) is the right declaration: dispatch-gates.mjs states that a card that only narrows a published surface is Clause-②: no with the (narrowing) arm — the card's draft yes (narrowing) was the wrong reading and the claim corrected it. Both declaration lines and Ruling-ref: 6259332195 are line-initial in the PR body and in the changeset. FROM → TO table present with one row per removed group and the one-line fix (delete the imports; TS2305 / TS2339 find them); the out-of-repo population beyond objectui and HotCRM is declared NOT MEASURED, which is honest. Disposition marker: exactly one, adr-0087: registered kernel-package-upgrade-family-retired — registered requires the id to resolve at the head and to be new in this diff; both hold. Breaking signals read by the gate: banner, title !, the (narrowing) arm and narrowed — four of five, major correctly absent. PR title feat(spec)!: carries the !. Check Changeset: success.

③ Boundary flags

Dev report 6394223748, every flag and open question:

  • Deviation: worktree created from a primary checkout that already had the branch checked out (detached it first). Process only; the committed diff is unaffected. Answered.
  • Deviation: no PR-activity subscription (role file). Not a contract matter. Answered.
  • Deviation: git worktree remove --force on the dev's own throwaway probe tree. Own tree, clean. Answered.
  • Deviation: "ADR-0087 conversion" executed as the ledger record, not a D2 conversion or tombstone. Right — R3. Answered.
  • Deviation: scope widened where the removal forced it (rollback/getSnapshot, three inputs, compliance control, count pins). Each widening traced to a forced dependency — R1. Answered.
  • Open question 1 (carrier for shapes no collection or metadata type carries): A, ledger record + D3, no D2. A is right — R3; B would be a transform with no seam. Answered.
  • Open question 2 (retire PackageUpgradeRequestSchema / PackageUpgradeResponseSchema too?): A, leave for a separate card. Right: ruling item 3 names only package-upgrade.zod.ts; the pair is already recorded as unmounted by the D3 package-api-contracts-unmounted-entries-retired, so no new false claim is left standing. Whether a card is filed is the dispatching seat's call; nothing in this diff turns on it. Answered, not escalated.
  • Out-of-scope (a): check:liveness main-red. Confirmed by reading, not by the dev's word: packages/spec/liveness/translation.json at this head AND on origin/main cites engine.ts#renderFlowTextSlot, while renderFlowTextSlot is defined in packages/services/service-automation/src/node-text-rendering.ts (engine.ts only imports it); the advisory Spec property liveness check is failure on the head and equally on main at c61f75d10f and 5874d25302. fix(spec/liveness): drop the comment-only engine.ts pointer from the translation/flows.screens row #25751 (the one-line pointer fix) is still OPEN. Escalated to the landing seat below.
  • Out-of-scope (b): content/docs/protocol/kernel/lifecycle.mdx Upgrades section left as flagged design intent. It names none of the retired symbols (0 hits under content/docs at the head outside the changeset). Answered.
  • Out-of-scope (c): the change-management-family-retired D3 history text still calls MetadataChangeType a live declaration. History entries are not rewritten; the new D3 entry and the retired-defs entry carry the current fact. Answered.
  • Flag raised here: the objectui pin sha in the census is stale (2958f17e9c is the base's pin; this head's pin is b41ed7f68956). Re-measured at the current pin: zero — R5. No code change owed; the body and the pin test's header comment are prose. Answered.
  • Flag raised here: the PR body says docs(adr): ADR-0126 stops deferring the package-upgrade.zod.ts retirement; ADR-0138 D5 says who opens a future site binding #25716 "merges after this one". It merged already (2026-10-25T03:02Z, 4cc17db3c0); the ADR text describes the retirement this PR performs, so the order is harmless. Answered.
  • Escalation — the head's gate verdicts, read off the check-runs. 32 success, 12 skipped, 4 failure: Spec property liveness (advisory, main-red above), and the required Test Core through shards 1/8 (packages/spec) and 8/8 (packages/plugins/plugin-pinyin-search, a package this diff does not touch — the boot-reconcile timeout test(plugin-pinyin-search): boot-reconcile.integration.test.ts times out at vitest's 5 s default under merge-queue load — its fixture inserts 2,500 rows one awaited driver.create at a time #25749, OPEN). The failing step's own stdout was not readable from here (the job-log download is refused in transit), so the attribution of shard 1/8 to scripts/liveness/check-liveness.test.ts rests on the dev's local reading (21787 passed / 23 failed, all in that file, reproduced on clean main) together with the pointer evidence above; no reading contradicts it, and the liveness ledger carries no row this diff could have orphaned. This record does not relax the green requirement: the seat lands only once every required check is success on the landing head, and a branch update that moves the head needs a record naming THAT head — this one names 3e7b204be7 alone.

Implemented-by: session_01T5pRzjp4QpCwioKZ9Gt5tC
Reviewed-by: session_01PC4NPXPgPmpDRG9DdDnyXT

VERDICT: PASS


Generated by Claude Code

This branch has not been deployed

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

Labels

documentation Improvements or additions to documentation protocol:system size/xl tests tooling

Projects

None yet

2 participants