Skip to content

feat(spec): retire contributes.routes (ruled Option B) and redirect its last two teaching sites to the http.server mount - #12417

Merged
huangyiirene merged 2 commits into
mainfrom
claude/issue-10726-routes-tombstone
Aug 26, 2026
Merged

feat(spec): retire contributes.routes (ruled Option B) and redirect its last two teaching sites to the http.server mount#12417
huangyiirene merged 2 commits into
mainfrom
claude/issue-10726-routes-tombstone

Conversation

@huangyiirene

@huangyiirenehuangyiirene commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

Fixes#10726
Fixes#11328

Family PR (chain head #10726 + folded member #11328), one commit per member. Executes the 2026-08-22 maintainer ruling on #10726 (Option B, accepted verbatim 「接受所有」): remove contributes.routes; author-facing materials point at the imperative http.server mount. The ruling's cloud precondition is verified (#10812: cloud @ 5b5925a, zero manifest.contributes reads, controls green). The four originally-enumerated doc sites landed earlier via PR #11327 and are not redone here.

Member 1 — #10726, the tombstone half (commit 1)

  • packages/spec/src/kernel/manifest.zod.ts: contributes.routes becomes a retiredKey() tombstone — neither ManifestSchema nor the contributes object is .strict(), so a plain deletion would silently strip the key (the loading / Retire the nine dead members of the plugin-manifest contributes block (events/menus/themes/translations/actions/drivers/fieldTypes/functions/commands) — tombstone route, kinds survives #10724 route). The block's fence comment now records TEN removed members and names kinds as the sole survivor. contributes.kinds (live reader: packages/objectql/src/engine.tsregistry.registerKind) is untouched.
  • ADR-0087 registration, both obligations: retired-key entry kernel/Manifest:contributes.routes + D3 semantic entry plugin-manifest-contributes-routes-retired, one file each under packages/spec/src/migrations/entries/ (major 18, the launch-window convention Retire the nine dead members of the plugin-manifest contributes block (events/menus/themes/translations/actions/drivers/fieldTypes/functions/commands) — tombstone route, kinds survives #10724 established), registry.ts regions regenerated with gen:migration-registry. Deliberately no D2 conversion: a package manifest is not a stack collection member (PLURAL_TO_SINGULAR has no packages/plugins entry), so a conversion would be a transform with no seam that ever runs — the kernel/Manifest:loading precedent, recorded verbatim in the entry.
  • Liveness ledger: packages/spec/liveness/manifest.jsonroutes row re-graded RETIRED with the row STAYING (a tombstone keeps the key in the drilled shape — the rls.priority precedent), _note DISPOSITIONS and the README manifest row updated; counts unchanged (routes was already counted among the dead members).
  • Pin tests (manifest.test.ts): a rejection pin asserting the SPECIFIC zod issue (located at contributes.routes, matching #10726 + Delete the key + http.server), a kinds-only survivor pin with not.toHaveProperty('routes'); the previous survivor pin asserting routes parses — the exact opposite state — is replaced. The two assertions are mutually exclusive across this change, which is the red/green reverse evidence for the pin (old pin green on base, new pin green here; no dist resolution involved — the test imports ./manifest.zod from src, so no ablation build applies).
  • Changeset .changeset/manifest-contributes-routes-retired.md: minor per the launch-window convention (check-changeset-no-major green), FROM → TO mapping, and the disposition marker adr-0087: registered plugin-manifest-contributes-routes-retired.

Member 2 — #11328, the two remaining teaching sites (commit 2)

  • packages/spec/src/api/plugin-rest-api.zod.ts:31-63: the full worked @example Plugin Manifest block — a complete, copy-pasteable contributes.routes manifest whose every route served nothing — replaced with an imperative http.server mount example modeled on the verified-live consumer (packages/plugins/plugin-hono-server/src/hono-plugin.ts:271 registers the service; examples/app-showcase/src/system/server/recalc-endpoint.ts mounts POST /api/v1/showcase/recalc on kernel:ready).
  • packages/spec/src/kernel/metadata-plugin.zod.ts: the router delivered-form comments stop crediting contributes.routes as a delivered form. The text had drifted since Two more author-facing sites still teach contributes.routes — a full worked manifest example in plugin-rest-api.zod.ts and the router delivered-form comments in metadata-plugin.zod.ts #11328 was filed — re-measured at :118-122 and :124-128 on the branch base; both corrected to the imperative mount + declarative apis:.

Declared file-surface increment (bounded inline fix, same defect class)

packages/spec/src/api/dispatcher.zod.ts (protocol docblock) and packages/spec/src/ui/app.zod.ts (App.apis retiredKey guidance) — both PR-#11327-corrected sites still said an authored contributes.routes entry "parses cleanly and serves nothing", a statement THIS PR falsifies (the entry is now loudly rejected). Both updated to state the removal. Evidence of boundedness: mechanical one-sentence corrections, non-governed spec sources, no schema shape or export change, covered by the same check:docs regeneration already in this diff, no other in-flight claim holds either file (checked at claim).

Generated projections (never hand-edited)

Nine content/docs/references/** pages via gen:docs, docs/audits/2026-07-unknown-key-strictness-ledger.counts.md via gen:strictness-ledger, src/migrations/registry.ts marked regions via gen:migration-registry — all via check:generated --fix after a fresh pnpm --filter @objectstack/spec build.

Expected-reading notes for review

Verification (all at final commit be433ec; verdict lines from the gates' own output)

  • pnpm --filter @objectstack/spec testTest Files 431 passed (431) / Tests 11428 passed (11428); targeted vitest run src/kernel/manifest.test.ts1 passed / 37 passed.
  • pnpm --filter @objectstack/spec typecheck → exit 0, including check:test-typecheck (OK — @objectstack/spec's test layer compiles; the edited test file is inside tsconfig.test.json's src/**/*.test.ts program).
  • pnpm --filter @objectstack/spec check:generated (after --fix) → all 14 artifact gates in sync, including check:migration-registry, check:spec-changes, check:upgrade-guide, check:authorable-surface, check:api-surface, check:docs, check:liveness, check:strictness-ledger.
  • Audit union derived with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (no paths passed — changeset derived from merge-base): 41 gates PASS at be433ec, among them check:liveness, check:empty-state, check:skill-refs, check:variant-docs, check-adr-0087-registration, check-changeset-no-major, check-empty-changeset, check:changeset-gate-self-tests, check:objectui-changeset, check:nul-bytes, check:cross-package-test-inputs, check:engine-double-contract, check:merge-driver, doc-family gates, check-ci-filter-parity.
  • check:skill-examples → real PASS after building the client closure (260 prose examples type-check across 3 surface(s)).
  • NOT MEASURED (prerequisite-not-met, not red): check:i18n (needs built CLI dist; this diff contains no i18n extraction inputs — no *.form.ts, no translations, no extract config) and check-dev-prereqs (reports the workspace-not-built precondition for packages this diff does not touch). CI measures both on a fresh build.
  • Declared narrowing — repo-wide pnpm lint not run locally (CI-owned). Targeted measurement with all three pieces: (1) population = eslint's own config resolution over the 9 changed .ts files; (2) --format jsonfiles linted: 9 | errors: 0 | warnings: 0; (3) invariance — eslint.config.mjs states this repo never enables type-aware linting for ANY file, so this diff cannot move the verdict on any file it does not contain.

Generated by Claude Code

…ast dead member (ADR-0049, ruled Option B)
retiredKey() tombstone (non-strict object; plain deletion would silently
strip the key), ADR-0087 retired-key entry kernel/Manifest:contributes.routes
+ D3 semantic entry plugin-manifest-contributes-routes-retired (both under
major 18, launch-window convention), liveness ledger row updated in place
(tombstones keep the key in the drilled shape), pin tests (prescription as
the specific zod issue + kinds-only survivor), regenerated docs projections,
and the two spec docblocks that still said an authored entry 'parses cleanly'
(dispatcher.zod.ts, app.zod.ts App.apis guidance) updated to state the
removal. contributes.kinds — the block's sole live member — is untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E5LFCYBJ3q2s6yW6oMLxwy
…tes to the http.server mount
The worked '@example Plugin Manifest' block in plugin-rest-api.zod.ts — a
complete copy-pasteable manifest whose every route served nothing — becomes
an imperative http.server mount example modeled on the live consumer
(plugin-hono-server registers the service; app-showcase's recalc-endpoint
mounts on kernel:ready), and the metadata-plugin.zod.ts 'router'
delivered-form comments stop crediting contributes.routes as a delivered
form. Projection regenerated (plugin-rest-api.mdx).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E5LFCYBJ3q2s6yW6oMLxwy
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec, touching 30 documentable anchor(s). ⚠️4 changed file(s) yielded no anchor (packages/spec/liveness/README.md, packages/spec/liveness/manifest.json, packages/spec/src/api/dispatcher.zod.ts, …), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

45 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 2e24115710640fba45938baf24a31fd9cc80694f.

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

What this run could not see
  • 4 changed file(s) yielded no anchor (packages/spec/liveness/README.md, packages/spec/liveness/manifest.json, packages/spec/src/api/dispatcher.zod.ts, …) — pages documenting those are invisible to this run
  • 3 anchor(s) matched too much of the corpus to be a work list: /api/v1 (route, 81 pages), /api/v1/data (route, 35 pages), /api/v1/data/:object (route, 29 pages)
  • 6 name(s) were too generic to anchor anything (single lowercase words)
  • the SDK route bridge reached 47 of 219 client-bound route-ledger rows — the other 172 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 172: 14 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 56 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 102 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.

Coarse fallback — 126 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 2e24115710640fba45938baf24a31fd9cc80694fpackageMentionDocs.

Which tree this was computed on

This run read content/docs from 5984647b7ff736bb22f0f8ac80a0841f9d1b1e4c — the merge of head be433ecc36fbc265385d9854602053595e497039 into base 2e24115710640fba45938baf24a31fd9cc80694f, 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 5984647b7ff736bb22f0f8ac80a0841f9d1b1e4c && git checkout 5984647b7ff736bb22f0f8ac80a0841f9d1b1e4c
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 2e24115710640fba45938baf24a31fd9cc80694f be433ecc36fbc265385d9854602053595e497039 && git checkout -B drift-repro 2e24115710640fba45938baf24a31fd9cc80694f && git merge --no-ff be433ecc36fbc265385d9854602053595e497039
node scripts/docs-audit/affected-docs.mjs --json 2e24115710640fba45938baf24a31fd9cc80694f

⚠️ 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 2e24115710640fba45938baf24a31fd9cc80694f → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation protocol:ui tests tooling labels Aug 26, 2026
@huangyiirene
huangyiirene marked this pull request as ready for review August 26, 2026 02:38
@huangyiirene
huangyiirene added this pull request to the merge queueAug 26, 2026
Merged via the queue into main with commit bc56e18Aug 26, 2026
38 checks passed
@huangyiirene
huangyiirene deleted the claude/issue-10726-routes-tombstone branch August 26, 2026 03:05
os-warren pushed a commit that referenced this pull request Aug 26, 2026
…tree
The merge of `main` into this branch left the `kernel/` count as OURS (274) —
the `merge=os-regen` driver defers rather than text-merging, because a
generator run mid-merge reads a half-merged tree. Regenerated from the fully
merged sources, as that driver's pending marker requires.
277 at the merge base; this branch's DistributedStateConfig removal takes 3
(the def plus its inline `auth` and `replication` objects) and #12417's
`contributes.routes` retirement on main takes 1, so 273 is the composition of
both sides, not a choice between them. Predicted before the run; observed
exactly. `check:strictness-ledger` green.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment