feat(spec): retire RestApiEndpoint.handlerStatus and the Route Coverage Report shapes (#13823) - #14531

Merged
os-zhuang merged 6 commits into
mainfrom
claude/issue-13823-retire-handler-status
Sep 2, 2026
Merged

feat(spec): retire RestApiEndpoint.handlerStatus and the Route Coverage Report shapes (#13823)#14531
os-zhuang merged 6 commits into
mainfrom
claude/issue-13823-retire-handler-status

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#13823

Ruling implemented

Director decision batch #27, maintainer 2026-09-01 verbatim 「同意」 (issue comment 5494755488), implemented exactly:

  1. remove:RestApiEndpointSchema.handlerStatusspec-property-retirement 手册退役(liveness 台账 verdict 确认 → ADR-0087 转换 → 墓碑 + 生成基线/表单/文档/pin 全套);RouteCoverageEntrySchema/RouteCoverageReportSchema 随同一 PR 按 liveness 读数处置(零构造者即同退);
  2. 前置一扫:退役前跑教材扫描 —— 除 flight ⑦ 已纠的那句外,还有哪些 published skill / 文档 / 示例在教 handlerStatus;非零则同笔清扫(教材曾教过不存在的 501 行为,是本卡的出处);
  3. enforce 排除:「声明未建的路由回 501」是零拉力的新能力,不是修复;
  4. 类方向入册(finding(spec): all six branded identifier schemas in branded-types.zod.ts are declared but unbound — no schema anywhere composes them #13612 / finding(spec): EventNameSchema's only three binding schemas have no runtime consumer — the live event vocabulary is a closed enum that never touches it #13613 引用用):ADR-0049 declared-but-unenforced 的默认处置 = retire(零拉力键);enforce/bind 只当有具名消费者或实测拉力。
  5. 条款②:YES(发布 accept 面收窄)⇒ draft + needs:contract-review 同笔,本席复审;changeset 按退役惯例。

Clause ② applies (the published accept set narrows): draft PR, needs:contract-review on both carriers, in-seat review. Item 4 is recorded here as the class direction for #13612 / #13613 — not ruled by this PR.

Premise re-measured on origin/main (a9b2be0, 2026-09-02)

Identifier search for handlerStatus, skills/** and tests excluded — three hits, all in the declaring file:

sitewhat
packages/spec/src/api/plugin-rest-api.zod.ts:177the declaration on RestApiEndpointSchema (HandlerStatusSchema.optional())
packages/spec/src/api/plugin-rest-api.zod.ts:1415the same enum re-declared on RouteCoverageEntrySchema
packages/spec/src/api/plugin-rest-api.zod.ts:1431the docblock saying adapters SHOULD warn when handlerStatus !== 'implemented'

Plus CHANGELOG.md:1502 (history) and generated artifacts. DispatcherErrorCode.enum.NOT_IMPLEMENTED emitters, none consulting the key: packages/runtime/src/endpoint-executor.ts:320,505,517, packages/runtime/src/api-mapping.ts:225, and one more than the card counted — packages/runtime/src/api-endpoint-step.ts:343 — every one the declarative-endpoint executor refusing a target or mapping it cannot serve. RouteCoverageEntrySchema / RouteCoverageReportSchema constructors: zero in objectstack (only the type-alias pin and generated artifacts reference them), zero in objectui at the pinned sha d8ec8d6d, zero in cloud. RestApiEndpointSchema itself is parsed by nothing in the tree outside its own unit tests. Premise still valid; no consumer has appeared.

Teaching sweep (before retiring)

pathhitaction
content/docs/references/api/plugin-rest-api.mdx:200,375,408,424,442generated reference rows for handlerStatus / the coverage shapesAUTO-GEN — regenerated by gen:docs (tombstone row now reads [REMOVED] …; coverage sections gone)
content/docs/references/index.mdx:90generated export list naming HandlerStatus, RouteCoverageEntry, RouteCoverageReportAUTO-GEN — regenerated
content/docs/** hand-written treesno hit for handlerStatus; the 501 prose at api/index.mdx:161,171, kernel/services-checklist.mdx:193, permissions/authentication.mdx:1243,1281 describes the service-slot / discovery status 501, not this keynot the false claim — no action
examples/**, packages/*/README.md, packages/create-objectstack/**zero hitsnone
skills/objectstack-api/SKILL.md (at this PR's base a9b2be0: :136handlerStatus: 'implemented', inside the os:check-marked RestApiEndpointSchema.parse({...}) example; :380 the 501 NOT_IMPLEMENTED — Route declared but handler is a stub table row; :383-391 the "Handler Status" section; :393-395 flight ⑦'s PR #13808 correction)four teaching sites at the base⛔ governed surface, not edited. None on main: bae4088f3 (#14448, 08:27Z today) cut every one — git grep -n -i -E 'handlerStatus|handler status|RouteCoverage|HandlerStatus' origin/main -- skills/ returns zero hits at 99b8faf8f, with RestApiEndpoint still hitting the skill as the live control — so no skills-lane follow-up is needed. (check:skill-examples was measured green against the base's marked block too: parse takes unknown, so the tombstone's never input type never reached it.)

Retirement steps (spec-property-retirement playbook)

  • Route.RestApiEndpointSchema is a non-strict lazySchema(() => z.object(...))retiredKey() tombstone for the key (packages/spec/src/api/plugin-rest-api.zod.ts:208-217), prescription hoisted as HANDLER_STATUS_RETIRED (:131-138) under the retirement record (:91-130). RouteCoverageEntrySchema / RouteCoverageReportSchema ⇒ whole-def removal, route 3 (nobody parses or constructs one), recorded at the file tail (:1439-1453). HandlerStatusSchema / HandlerStatus ⇒ orphan value def once both carriers are gone (refactor(spec)!: remove the plugin sandboxing / integrity / approval config that never existed (#3896 follow-up) #3950, the ui/ThemeMode precedent) — removed with them.
  • Liveness ledger. Verdict dead, confirmed by the re-measure above. No ledger row moves: RestApiEndpointSchema is outside the walked population — it is not a registered metadata type and not in SPEC_ONLY_SCHEMAS (packages/spec/scripts/liveness/check-liveness.mts:328) — so there is no row to write and adding one would be an ORPHAN. The verdict is recorded in the schema comment, the D3 entry and the changeset.
  • ADR-0087. Tail-appended entries, registry.ts regenerated by gen:migration-registry: entries/retired-keys/18.api__RestApiEndpoint__handlerStatus.ts; entries/retired-defs/18.api__HandlerStatus.ts, 18.api__RouteCoverageEntry.ts, 18.api__RouteCoverageReport.ts; entries/semantic/18.rest-api-endpoint-handler-status-retired.ts. No D2 conversion, deliberately — a REST API plugin route registration is not a stack collection member and never a sys_metadata row, so a MetadataConversion would be a transform with no seam that ever runs (the kernel/Manifest:loading / kernel/KernelContext:previewMode disposition); for the same reason the tombstone carries no os migrate meta sentence. Registered under 18 (launch-window convention). spec-changes.json and the upgrade guide are unchanged because both project majors up to PROTOCOL_MAJOR (17) only — the same as every 18-registered precedent.
  • Generated baselines.json-schema.manifest/api.json −3 keys (deleted deliberately; the json-schema.manifest.json 的「deliberate removal」删行仍是纪律而非门禁 —— #4650 的同类洞,上移一层(整 schema 级) #4725 manifest deletion gate adjudicated all three against RETIRED_DEFS_BY_MAJOR[18]); authorable-surface/api.json −10 rows for the two defs (route 3, check (c) proof) and api/RestApiEndpoint:handlerStatus… [RETIRED]; api-surface/api.json, export-origins/api.json, declaration-map/api.json −6 names each; content/docs/references/** and the strictness-ledger counts regenerated by check:generated --fix. authorable-surface.base.json lags (allowed; check:authorable-surface green).
  • Forms / i18n. No *.form.ts offers the key; no bundle changes.
  • Pin tests.packages/spec/src/api/plugin-rest-api.handler-status-retirement.test.ts: all three former values (including the documented default 'implemented' — prose only, never a Zod .default(), so no residue window) refused with code: 'invalid_type', path: ['handlerStatus'] and the prescription text (ADR named, no issue id); the same refusal through the route-registration embed at ['endpoints', 0, 'handlerStatus']; positive control — a well-formed endpoint without the key parses and grows no handlerStatus property; the eight shipped default route registrations still parse; a tsc-channel pin (@ts-expect-error, file proven in the tsconfig.test.json program via --listFiles); zero holders for all six retired names on every public entry with the carriers surviving; RETIRED_KEYS_BY_MAJOR[18] / RETIRED_DEFS_BY_MAJOR[18] / step-18 semantic membership. type-alias-convention.pin.test.ts: pins Iso123 / Iso125 / Iso126 left with their schemas, count rebalanced 835 → 832 with the file's history note.
  • Changeset..changeset/rest-api-endpoint-handler-status-retired.md@objectstack/spec minor, BREAKING under the launch-window convention, FROM → TO + one-line fix, ADR-0087 marker registered rest-api-endpoint-handler-status-retired (check:adr-0087-registration green).
  • Enforce excluded. No 501 stub mounting, no registrar change.

Verification

Every heavy step ran under scripts/pm/os-verify-lock.sh (OS_VERIFY_LOCK_SLOT=issue-13823); every exit captured before any pipe; the gates' own verdict lines quoted.

Final head 875e3fa5e (chain 4): pnpm --filter @objectstack/spec build exit 0 (gen:schema: "3 schema(s) left the published set since a9b2be0, each declared (#4725)" and "2 baseline deletion(s) since a9b2be0 carry their own proof (#4650)"; check-dts-emitted: 34/34); check:generated (check-only) exit 0 — "✓ All 15 generated artifacts are up to date."; targeted vitest via exec vitest run --maxWorkers=2 FILES (type-alias-convention.pin, plugin-rest-api.handler-status-retirement, plugin-rest-api, retired-key-migrate-sentence, migrations) — "Test Files 5 passed (5)" / "Tests 172 passed (172)"; check:skill-examples exit 0 — "✅ 265 prose examples type-check across 3 surface(s)" (the @objectstack/client-react closure was built for it); check:adr-0087-registration exit 0 — "1 declared-breaking changeset(s), each carrying an ADR-0087 disposition"; check:empty-changeset, check-changeset-no-major, check:nul-bytes, check:doc-authoring, check:spec-parsed-alias all exit 0; git status --porcelain empty after the build (the authorable-surface.base.json anchor was not rewritten — it lags, allowed).

7cbf0ed60 (chain 3, the pin-literal fix): targeted vitest 5 files / 172 tests passed; check:test-typecheck exit 0; check:spec-parsed-alias / check:doc-authoring / check:nul-bytes exit 0; check:api-surface refused to judge ("dist/**/*.d.ts is OLDER than packages/spec/src" — the test-file edit post-dated the build; not a measurement, settled by the rebuild above).

90d567cd3 (chain 2, the full union): pnpm --filter @objectstack/spec typecheck exit 0 (tsc, the scripts tsconfig, and "check:test-typecheck: OK — 54 file(s) / 262 error(s) / 146 pinned signature(s)", ledger unchanged, so the new test file compiles clean; its membership in the tsconfig.test.json program proven with tsc --listFiles); full spec vitest--maxWorkers=2: "Test Files 1 failed | 451 passed (452)" / "Tests 1 failed | 12190 passed (12191)" — the single failure was still declares all 832 isomorphic pins (the toHaveLength literal still 835; the same red CI reported on Test Core 2/6), fixed in 7cbf0ed60 and green in chains 3 and 4; check:skill-examples exit 0; check:exported-any, check:dual-source-exports, check:entry-nameability, check:browser-reachable-entries exit 0; check:generated exit 0 (15/15); check:doc-authoring / check:nul-bytes / check:adr-0087-registration / check:spec-parsed-alias exit 0; check-dev-prereqs exit 1 = "The workspace is not built — 32 of 67 workspace packages declare an entry point under dist/ that is not on disk" (a pnpm dev precondition on apps and services, unrelated to this diff — NOT MEASURED, not red).

Earlier on the same tree (before the docs-only, test-literal and changeset-prose commits): check:variant-docs, check:empty-state, check:llms-txt, check:yaml-examples, check:template-manifests, check:error-code-provenance, check:objectui-pin-citations, check:quick-reference-counts, check:corpus-claim-drift, check:skill-identifier-liveness, check:doc-anchors, check:docs-single-h1, check:docs-audit-scope, check:test-source-alias, check:cross-package-test-inputs, check:published-files, check:type-check-coverage, check:migration-registry and check:liveness (both inside check:generated), and the root check-doc-frontmatter / check-docs-section-name / check-doc-route-spelling / check-section-landing-index / check-keyed-text-bounds / check-ci-filter-parity / check-comment-mask-adoption / check-shard-attestation / check-system-context-census / check-undeclared-dep-imports / check-plugin-teardown-shape / docs-audit/check-affected-docs / docs-audit/check-drift-comment / pm/check-half-states scripts — all exit 0. Earlier reds that this PR fixed before landing: check:doc-authoring (the tombstone string carried #13823; now cites ADR-0049 only, with a negative pin) and the pin-count test above.

Declared narrowing: the full 452-file spec suite ran on 90d567cd3; the two later commits change one assertion literal in a test file and changeset prose, re-verified with the targeted files rather than the whole suite (≈6 min held under a contended lock) — CI's Test Core runs the full suite on the final head. Gate list derived with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths; 74 commands at b862317); what was not run is the CI-owned farm named below. CI on 875e3fa at report time: 31 check-runs — completed/skipped: 2, completed/success: 14, in_progress/None: 15.

Not measured here (CI-owned)

  • check:type-check-coverage --re-measure / check:type-check-debt (needs the whole package closure built — PREREQUISITE NOT MET, exit 3, not a finding), check:test-completeness (grades CI's turbo test log), check:react-declaration-parity (needs objectui's manifest), the repo-wide pnpm lint and the rest of the 74-command derivation not named above.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21


Generated by Claude Code

os-zhuangand others added 4 commits September 2, 2026 09:10
…ge Report shapes (#13823)
WIP: tombstone, three whole-def removals, ADR-0087 registrations (key, defs,
D3 semantic entry), pin tests and changeset. Generated artifacts follow in
the next commit.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
…age retirement (#13823)
json-schema.manifest and authorable-surface rows for the three whole-def
removals deleted deliberately (route 3 — the #4725 manifest deletion gate
and check (c) adjudicated them against RETIRED_DEFS_BY_MAJOR[18]); the
tombstone row carries [RETIRED]; api-surface / export-origins /
declaration-map lose the six retired names; the reference page and the
strictness-ledger counts regenerate.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
…ic pin count rebalanced 835 -> 832 (#13823)
check:doc-authoring refuses an issue id in customer-facing spec text — the
prescription now cites ADR-0049 only (the id stays in the adjacent comment),
with a negative pin. The type-alias pin count drops by the three pins whose
schemas left the module, recorded in the file's own history block.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

14 anchor(s) derived from 1 changed package(s); no hand-written page names any of them. ⚠️9 changed file(s) yielded no anchor (packages/spec/api-surface/api.json, packages/spec/authorable-surface/api.json, packages/spec/declaration-map/api.json, …), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

What this run could not see
  • 9 changed file(s) yielded no anchor (packages/spec/api-surface/api.json, packages/spec/authorable-surface/api.json, packages/spec/declaration-map/api.json, …) — pages documenting those are invisible to this run
  • 10 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 — 128 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 99b8faf8f937d8d2992f1bf167e418687c5f2f71packageMentionDocs.

Which tree this was computed on

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

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

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests tooling labels Sep 2, 2026
@claude

claudeBot commented Sep 2, 2026

Copy link
Copy Markdown
ContributorAuthor

CI red on head 90d567cd — this PR's own; patch round requested from the dispatched dev. (domain:spec seat, session session_01GDA48PuRFrHyRfdkBz8m21, seat post #6017.)

  • Failing check: Test Core (2/6)packages/spec/src/type-alias-convention.pin.test.ts > "still declares all 832 isomorphic pins": expected [ Array(832) ] to have a length of 835 but got 832 at line 2093.
  • Cause: the diff updated the case title, the section header and added the 835 -> 832 receipt prose, but the assertion literal expect(pins).toHaveLength(835) directly under the receipt still reads 835. One-literal fix (835 -> 832); every other file in that shard passed (450 passed / 1 failed).
  • Not a base failure: the same case is green on origin/main at 835 pins; the count moved because this PR removed Iso123 / Iso125 / Iso126 with the retired defs, which is the intended shape.
  • Action: the dev is fixing the literal on this branch as a new commit (no history rewrite), re-running the spec test locally, then pushing. Contract review resumes on the pushed head; the landing gate stays "every check on the current head green".

Generated by Claude Code

os-zhuangand others added 2 commits September 2, 2026 10:32
…eipt to 832 (#13823)
Title, header and receipt already said 832; the toHaveLength literal under
the receipt still read 835 (Test Core 2/6 on the PR head, and the local
full run: 1 failed / 12190 passed).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
…e base (#13823)
The published skill taught handlerStatus at this PR's base; main dropped that
teaching in the #14448 optimization flight (bae4088), so the changeset —
release-notes input — no longer claims an outstanding skills limb.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/lteststooling

Projects

None yet

1 participant

@os-zhuang
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat(spec): retire RestApiEndpoint.handlerStatus and the Route Coverage Report shapes (#13823) - #14531

Merged
os-zhuang merged 6 commits into
mainfrom
claude/issue-13823-retire-handler-status
Sep 2, 2026
Merged

feat(spec): retire RestApiEndpoint.handlerStatus and the Route Coverage Report shapes (#13823)#14531
os-zhuang merged 6 commits into
mainfrom
claude/issue-13823-retire-handler-status

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#13823

Ruling implemented

Director decision batch #27, maintainer 2026-09-01 verbatim 「同意」 (issue comment 5494755488), implemented exactly:

  1. remove:RestApiEndpointSchema.handlerStatusspec-property-retirement 手册退役(liveness 台账 verdict 确认 → ADR-0087 转换 → 墓碑 + 生成基线/表单/文档/pin 全套);RouteCoverageEntrySchema/RouteCoverageReportSchema 随同一 PR 按 liveness 读数处置(零构造者即同退);
  2. 前置一扫:退役前跑教材扫描 —— 除 flight ⑦ 已纠的那句外,还有哪些 published skill / 文档 / 示例在教 handlerStatus;非零则同笔清扫(教材曾教过不存在的 501 行为,是本卡的出处);
  3. enforce 排除:「声明未建的路由回 501」是零拉力的新能力,不是修复;
  4. 类方向入册(finding(spec): all six branded identifier schemas in branded-types.zod.ts are declared but unbound — no schema anywhere composes them #13612 / finding(spec): EventNameSchema's only three binding schemas have no runtime consumer — the live event vocabulary is a closed enum that never touches it #13613 引用用):ADR-0049 declared-but-unenforced 的默认处置 = retire(零拉力键);enforce/bind 只当有具名消费者或实测拉力。
  5. 条款②:YES(发布 accept 面收窄)⇒ draft + needs:contract-review 同笔,本席复审;changeset 按退役惯例。

Clause ② applies (the published accept set narrows): draft PR, needs:contract-review on both carriers, in-seat review. Item 4 is recorded here as the class direction for #13612 / #13613 — not ruled by this PR.

Premise re-measured on origin/main (a9b2be0, 2026-09-02)

Identifier search for handlerStatus, skills/** and tests excluded — three hits, all in the declaring file:

sitewhat
packages/spec/src/api/plugin-rest-api.zod.ts:177the declaration on RestApiEndpointSchema (HandlerStatusSchema.optional())
packages/spec/src/api/plugin-rest-api.zod.ts:1415the same enum re-declared on RouteCoverageEntrySchema
packages/spec/src/api/plugin-rest-api.zod.ts:1431the docblock saying adapters SHOULD warn when handlerStatus !== 'implemented'

Plus CHANGELOG.md:1502 (history) and generated artifacts. DispatcherErrorCode.enum.NOT_IMPLEMENTED emitters, none consulting the key: packages/runtime/src/endpoint-executor.ts:320,505,517, packages/runtime/src/api-mapping.ts:225, and one more than the card counted — packages/runtime/src/api-endpoint-step.ts:343 — every one the declarative-endpoint executor refusing a target or mapping it cannot serve. RouteCoverageEntrySchema / RouteCoverageReportSchema constructors: zero in objectstack (only the type-alias pin and generated artifacts reference them), zero in objectui at the pinned sha d8ec8d6d, zero in cloud. RestApiEndpointSchema itself is parsed by nothing in the tree outside its own unit tests. Premise still valid; no consumer has appeared.

Teaching sweep (before retiring)

pathhitaction
content/docs/references/api/plugin-rest-api.mdx:200,375,408,424,442generated reference rows for handlerStatus / the coverage shapesAUTO-GEN — regenerated by gen:docs (tombstone row now reads [REMOVED] …; coverage sections gone)
content/docs/references/index.mdx:90generated export list naming HandlerStatus, RouteCoverageEntry, RouteCoverageReportAUTO-GEN — regenerated
content/docs/** hand-written treesno hit for handlerStatus; the 501 prose at api/index.mdx:161,171, kernel/services-checklist.mdx:193, permissions/authentication.mdx:1243,1281 describes the service-slot / discovery status 501, not this keynot the false claim — no action
examples/**, packages/*/README.md, packages/create-objectstack/**zero hitsnone
skills/objectstack-api/SKILL.md (at this PR's base a9b2be0: :136handlerStatus: 'implemented', inside the os:check-marked RestApiEndpointSchema.parse({...}) example; :380 the 501 NOT_IMPLEMENTED — Route declared but handler is a stub table row; :383-391 the "Handler Status" section; :393-395 flight ⑦'s PR #13808 correction)four teaching sites at the base⛔ governed surface, not edited. None on main: bae4088f3 (#14448, 08:27Z today) cut every one — git grep -n -i -E 'handlerStatus|handler status|RouteCoverage|HandlerStatus' origin/main -- skills/ returns zero hits at 99b8faf8f, with RestApiEndpoint still hitting the skill as the live control — so no skills-lane follow-up is needed. (check:skill-examples was measured green against the base's marked block too: parse takes unknown, so the tombstone's never input type never reached it.)

Retirement steps (spec-property-retirement playbook)

  • Route.RestApiEndpointSchema is a non-strict lazySchema(() => z.object(...))retiredKey() tombstone for the key (packages/spec/src/api/plugin-rest-api.zod.ts:208-217), prescription hoisted as HANDLER_STATUS_RETIRED (:131-138) under the retirement record (:91-130). RouteCoverageEntrySchema / RouteCoverageReportSchema ⇒ whole-def removal, route 3 (nobody parses or constructs one), recorded at the file tail (:1439-1453). HandlerStatusSchema / HandlerStatus ⇒ orphan value def once both carriers are gone (refactor(spec)!: remove the plugin sandboxing / integrity / approval config that never existed (#3896 follow-up) #3950, the ui/ThemeMode precedent) — removed with them.
  • Liveness ledger. Verdict dead, confirmed by the re-measure above. No ledger row moves: RestApiEndpointSchema is outside the walked population — it is not a registered metadata type and not in SPEC_ONLY_SCHEMAS (packages/spec/scripts/liveness/check-liveness.mts:328) — so there is no row to write and adding one would be an ORPHAN. The verdict is recorded in the schema comment, the D3 entry and the changeset.
  • ADR-0087. Tail-appended entries, registry.ts regenerated by gen:migration-registry: entries/retired-keys/18.api__RestApiEndpoint__handlerStatus.ts; entries/retired-defs/18.api__HandlerStatus.ts, 18.api__RouteCoverageEntry.ts, 18.api__RouteCoverageReport.ts; entries/semantic/18.rest-api-endpoint-handler-status-retired.ts. No D2 conversion, deliberately — a REST API plugin route registration is not a stack collection member and never a sys_metadata row, so a MetadataConversion would be a transform with no seam that ever runs (the kernel/Manifest:loading / kernel/KernelContext:previewMode disposition); for the same reason the tombstone carries no os migrate meta sentence. Registered under 18 (launch-window convention). spec-changes.json and the upgrade guide are unchanged because both project majors up to PROTOCOL_MAJOR (17) only — the same as every 18-registered precedent.
  • Generated baselines.json-schema.manifest/api.json −3 keys (deleted deliberately; the json-schema.manifest.json 的「deliberate removal」删行仍是纪律而非门禁 —— #4650 的同类洞,上移一层(整 schema 级) #4725 manifest deletion gate adjudicated all three against RETIRED_DEFS_BY_MAJOR[18]); authorable-surface/api.json −10 rows for the two defs (route 3, check (c) proof) and api/RestApiEndpoint:handlerStatus… [RETIRED]; api-surface/api.json, export-origins/api.json, declaration-map/api.json −6 names each; content/docs/references/** and the strictness-ledger counts regenerated by check:generated --fix. authorable-surface.base.json lags (allowed; check:authorable-surface green).
  • Forms / i18n. No *.form.ts offers the key; no bundle changes.
  • Pin tests.packages/spec/src/api/plugin-rest-api.handler-status-retirement.test.ts: all three former values (including the documented default 'implemented' — prose only, never a Zod .default(), so no residue window) refused with code: 'invalid_type', path: ['handlerStatus'] and the prescription text (ADR named, no issue id); the same refusal through the route-registration embed at ['endpoints', 0, 'handlerStatus']; positive control — a well-formed endpoint without the key parses and grows no handlerStatus property; the eight shipped default route registrations still parse; a tsc-channel pin (@ts-expect-error, file proven in the tsconfig.test.json program via --listFiles); zero holders for all six retired names on every public entry with the carriers surviving; RETIRED_KEYS_BY_MAJOR[18] / RETIRED_DEFS_BY_MAJOR[18] / step-18 semantic membership. type-alias-convention.pin.test.ts: pins Iso123 / Iso125 / Iso126 left with their schemas, count rebalanced 835 → 832 with the file's history note.
  • Changeset..changeset/rest-api-endpoint-handler-status-retired.md@objectstack/spec minor, BREAKING under the launch-window convention, FROM → TO + one-line fix, ADR-0087 marker registered rest-api-endpoint-handler-status-retired (check:adr-0087-registration green).
  • Enforce excluded. No 501 stub mounting, no registrar change.

Verification

Every heavy step ran under scripts/pm/os-verify-lock.sh (OS_VERIFY_LOCK_SLOT=issue-13823); every exit captured before any pipe; the gates' own verdict lines quoted.

Final head 875e3fa5e (chain 4): pnpm --filter @objectstack/spec build exit 0 (gen:schema: "3 schema(s) left the published set since a9b2be0, each declared (#4725)" and "2 baseline deletion(s) since a9b2be0 carry their own proof (#4650)"; check-dts-emitted: 34/34); check:generated (check-only) exit 0 — "✓ All 15 generated artifacts are up to date."; targeted vitest via exec vitest run --maxWorkers=2 FILES (type-alias-convention.pin, plugin-rest-api.handler-status-retirement, plugin-rest-api, retired-key-migrate-sentence, migrations) — "Test Files 5 passed (5)" / "Tests 172 passed (172)"; check:skill-examples exit 0 — "✅ 265 prose examples type-check across 3 surface(s)" (the @objectstack/client-react closure was built for it); check:adr-0087-registration exit 0 — "1 declared-breaking changeset(s), each carrying an ADR-0087 disposition"; check:empty-changeset, check-changeset-no-major, check:nul-bytes, check:doc-authoring, check:spec-parsed-alias all exit 0; git status --porcelain empty after the build (the authorable-surface.base.json anchor was not rewritten — it lags, allowed).

7cbf0ed60 (chain 3, the pin-literal fix): targeted vitest 5 files / 172 tests passed; check:test-typecheck exit 0; check:spec-parsed-alias / check:doc-authoring / check:nul-bytes exit 0; check:api-surface refused to judge ("dist/**/*.d.ts is OLDER than packages/spec/src" — the test-file edit post-dated the build; not a measurement, settled by the rebuild above).

90d567cd3 (chain 2, the full union): pnpm --filter @objectstack/spec typecheck exit 0 (tsc, the scripts tsconfig, and "check:test-typecheck: OK — 54 file(s) / 262 error(s) / 146 pinned signature(s)", ledger unchanged, so the new test file compiles clean; its membership in the tsconfig.test.json program proven with tsc --listFiles); full spec vitest--maxWorkers=2: "Test Files 1 failed | 451 passed (452)" / "Tests 1 failed | 12190 passed (12191)" — the single failure was still declares all 832 isomorphic pins (the toHaveLength literal still 835; the same red CI reported on Test Core 2/6), fixed in 7cbf0ed60 and green in chains 3 and 4; check:skill-examples exit 0; check:exported-any, check:dual-source-exports, check:entry-nameability, check:browser-reachable-entries exit 0; check:generated exit 0 (15/15); check:doc-authoring / check:nul-bytes / check:adr-0087-registration / check:spec-parsed-alias exit 0; check-dev-prereqs exit 1 = "The workspace is not built — 32 of 67 workspace packages declare an entry point under dist/ that is not on disk" (a pnpm dev precondition on apps and services, unrelated to this diff — NOT MEASURED, not red).

Earlier on the same tree (before the docs-only, test-literal and changeset-prose commits): check:variant-docs, check:empty-state, check:llms-txt, check:yaml-examples, check:template-manifests, check:error-code-provenance, check:objectui-pin-citations, check:quick-reference-counts, check:corpus-claim-drift, check:skill-identifier-liveness, check:doc-anchors, check:docs-single-h1, check:docs-audit-scope, check:test-source-alias, check:cross-package-test-inputs, check:published-files, check:type-check-coverage, check:migration-registry and check:liveness (both inside check:generated), and the root check-doc-frontmatter / check-docs-section-name / check-doc-route-spelling / check-section-landing-index / check-keyed-text-bounds / check-ci-filter-parity / check-comment-mask-adoption / check-shard-attestation / check-system-context-census / check-undeclared-dep-imports / check-plugin-teardown-shape / docs-audit/check-affected-docs / docs-audit/check-drift-comment / pm/check-half-states scripts — all exit 0. Earlier reds that this PR fixed before landing: check:doc-authoring (the tombstone string carried #13823; now cites ADR-0049 only, with a negative pin) and the pin-count test above.

Declared narrowing: the full 452-file spec suite ran on 90d567cd3; the two later commits change one assertion literal in a test file and changeset prose, re-verified with the targeted files rather than the whole suite (≈6 min held under a contended lock) — CI's Test Core runs the full suite on the final head. Gate list derived with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths; 74 commands at b862317); what was not run is the CI-owned farm named below. CI on 875e3fa at report time: 31 check-runs — completed/skipped: 2, completed/success: 14, in_progress/None: 15.

Not measured here (CI-owned)

  • check:type-check-coverage --re-measure / check:type-check-debt (needs the whole package closure built — PREREQUISITE NOT MET, exit 3, not a finding), check:test-completeness (grades CI's turbo test log), check:react-declaration-parity (needs objectui's manifest), the repo-wide pnpm lint and the rest of the 74-command derivation not named above.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21


Generated by Claude Code

os-zhuangand others added 4 commits September 2, 2026 09:10
…ge Report shapes (#13823)
WIP: tombstone, three whole-def removals, ADR-0087 registrations (key, defs,
D3 semantic entry), pin tests and changeset. Generated artifacts follow in
the next commit.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
…age retirement (#13823)
json-schema.manifest and authorable-surface rows for the three whole-def
removals deleted deliberately (route 3 — the #4725 manifest deletion gate
and check (c) adjudicated them against RETIRED_DEFS_BY_MAJOR[18]); the
tombstone row carries [RETIRED]; api-surface / export-origins /
declaration-map lose the six retired names; the reference page and the
strictness-ledger counts regenerate.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
…ic pin count rebalanced 835 -> 832 (#13823)
check:doc-authoring refuses an issue id in customer-facing spec text — the
prescription now cites ADR-0049 only (the id stays in the adjacent comment),
with a negative pin. The type-alias pin count drops by the three pins whose
schemas left the module, recorded in the file's own history block.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

14 anchor(s) derived from 1 changed package(s); no hand-written page names any of them. ⚠️9 changed file(s) yielded no anchor (packages/spec/api-surface/api.json, packages/spec/authorable-surface/api.json, packages/spec/declaration-map/api.json, …), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

What this run could not see
  • 9 changed file(s) yielded no anchor (packages/spec/api-surface/api.json, packages/spec/authorable-surface/api.json, packages/spec/declaration-map/api.json, …) — pages documenting those are invisible to this run
  • 10 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 — 128 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 99b8faf8f937d8d2992f1bf167e418687c5f2f71packageMentionDocs.

Which tree this was computed on

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

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

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests tooling labels Sep 2, 2026
@claude

claudeBot commented Sep 2, 2026

Copy link
Copy Markdown
ContributorAuthor

CI red on head 90d567cd — this PR's own; patch round requested from the dispatched dev. (domain:spec seat, session session_01GDA48PuRFrHyRfdkBz8m21, seat post #6017.)

  • Failing check: Test Core (2/6)packages/spec/src/type-alias-convention.pin.test.ts > "still declares all 832 isomorphic pins": expected [ Array(832) ] to have a length of 835 but got 832 at line 2093.
  • Cause: the diff updated the case title, the section header and added the 835 -> 832 receipt prose, but the assertion literal expect(pins).toHaveLength(835) directly under the receipt still reads 835. One-literal fix (835 -> 832); every other file in that shard passed (450 passed / 1 failed).
  • Not a base failure: the same case is green on origin/main at 835 pins; the count moved because this PR removed Iso123 / Iso125 / Iso126 with the retired defs, which is the intended shape.
  • Action: the dev is fixing the literal on this branch as a new commit (no history rewrite), re-running the spec test locally, then pushing. Contract review resumes on the pushed head; the landing gate stays "every check on the current head green".

Generated by Claude Code

os-zhuangand others added 2 commits September 2, 2026 10:32
…eipt to 832 (#13823)
Title, header and receipt already said 832; the toHaveLength literal under
the receipt still read 835 (Test Core 2/6 on the PR head, and the local
full run: 1 failed / 12190 passed).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
…e base (#13823)
The published skill taught handlerStatus at this PR's base; main dropped that
teaching in the #14448 optimization flight (bae4088), so the changeset —
release-notes input — no longer claims an outstanding skills limb.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/lteststooling

Projects

None yet

1 participant

@os-zhuang
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(spec): retire RestApiEndpoint.handlerStatus and the Route Coverage Report shapes (#13823) - #14531

Merged
os-zhuang merged 6 commits into
mainfrom
claude/issue-13823-retire-handler-status
Sep 2, 2026
Merged

feat(spec): retire RestApiEndpoint.handlerStatus and the Route Coverage Report shapes (#13823)#14531
os-zhuang merged 6 commits into
mainfrom
claude/issue-13823-retire-handler-status

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#13823

Ruling implemented

Director decision batch #27, maintainer 2026-09-01 verbatim 「同意」 (issue comment 5494755488), implemented exactly:

  1. remove:RestApiEndpointSchema.handlerStatusspec-property-retirement 手册退役(liveness 台账 verdict 确认 → ADR-0087 转换 → 墓碑 + 生成基线/表单/文档/pin 全套);RouteCoverageEntrySchema/RouteCoverageReportSchema 随同一 PR 按 liveness 读数处置(零构造者即同退);
  2. 前置一扫:退役前跑教材扫描 —— 除 flight ⑦ 已纠的那句外,还有哪些 published skill / 文档 / 示例在教 handlerStatus;非零则同笔清扫(教材曾教过不存在的 501 行为,是本卡的出处);
  3. enforce 排除:「声明未建的路由回 501」是零拉力的新能力,不是修复;
  4. 类方向入册(finding(spec): all six branded identifier schemas in branded-types.zod.ts are declared but unbound — no schema anywhere composes them #13612 / finding(spec): EventNameSchema's only three binding schemas have no runtime consumer — the live event vocabulary is a closed enum that never touches it #13613 引用用):ADR-0049 declared-but-unenforced 的默认处置 = retire(零拉力键);enforce/bind 只当有具名消费者或实测拉力。
  5. 条款②:YES(发布 accept 面收窄)⇒ draft + needs:contract-review 同笔,本席复审;changeset 按退役惯例。

Clause ② applies (the published accept set narrows): draft PR, needs:contract-review on both carriers, in-seat review. Item 4 is recorded here as the class direction for #13612 / #13613 — not ruled by this PR.

Premise re-measured on origin/main (a9b2be0, 2026-09-02)

Identifier search for handlerStatus, skills/** and tests excluded — three hits, all in the declaring file:

sitewhat
packages/spec/src/api/plugin-rest-api.zod.ts:177the declaration on RestApiEndpointSchema (HandlerStatusSchema.optional())
packages/spec/src/api/plugin-rest-api.zod.ts:1415the same enum re-declared on RouteCoverageEntrySchema
packages/spec/src/api/plugin-rest-api.zod.ts:1431the docblock saying adapters SHOULD warn when handlerStatus !== 'implemented'

Plus CHANGELOG.md:1502 (history) and generated artifacts. DispatcherErrorCode.enum.NOT_IMPLEMENTED emitters, none consulting the key: packages/runtime/src/endpoint-executor.ts:320,505,517, packages/runtime/src/api-mapping.ts:225, and one more than the card counted — packages/runtime/src/api-endpoint-step.ts:343 — every one the declarative-endpoint executor refusing a target or mapping it cannot serve. RouteCoverageEntrySchema / RouteCoverageReportSchema constructors: zero in objectstack (only the type-alias pin and generated artifacts reference them), zero in objectui at the pinned sha d8ec8d6d, zero in cloud. RestApiEndpointSchema itself is parsed by nothing in the tree outside its own unit tests. Premise still valid; no consumer has appeared.

Teaching sweep (before retiring)

pathhitaction
content/docs/references/api/plugin-rest-api.mdx:200,375,408,424,442generated reference rows for handlerStatus / the coverage shapesAUTO-GEN — regenerated by gen:docs (tombstone row now reads [REMOVED] …; coverage sections gone)
content/docs/references/index.mdx:90generated export list naming HandlerStatus, RouteCoverageEntry, RouteCoverageReportAUTO-GEN — regenerated
content/docs/** hand-written treesno hit for handlerStatus; the 501 prose at api/index.mdx:161,171, kernel/services-checklist.mdx:193, permissions/authentication.mdx:1243,1281 describes the service-slot / discovery status 501, not this keynot the false claim — no action
examples/**, packages/*/README.md, packages/create-objectstack/**zero hitsnone
skills/objectstack-api/SKILL.md (at this PR's base a9b2be0: :136handlerStatus: 'implemented', inside the os:check-marked RestApiEndpointSchema.parse({...}) example; :380 the 501 NOT_IMPLEMENTED — Route declared but handler is a stub table row; :383-391 the "Handler Status" section; :393-395 flight ⑦'s PR #13808 correction)four teaching sites at the base⛔ governed surface, not edited. None on main: bae4088f3 (#14448, 08:27Z today) cut every one — git grep -n -i -E 'handlerStatus|handler status|RouteCoverage|HandlerStatus' origin/main -- skills/ returns zero hits at 99b8faf8f, with RestApiEndpoint still hitting the skill as the live control — so no skills-lane follow-up is needed. (check:skill-examples was measured green against the base's marked block too: parse takes unknown, so the tombstone's never input type never reached it.)

Retirement steps (spec-property-retirement playbook)

  • Route.RestApiEndpointSchema is a non-strict lazySchema(() => z.object(...))retiredKey() tombstone for the key (packages/spec/src/api/plugin-rest-api.zod.ts:208-217), prescription hoisted as HANDLER_STATUS_RETIRED (:131-138) under the retirement record (:91-130). RouteCoverageEntrySchema / RouteCoverageReportSchema ⇒ whole-def removal, route 3 (nobody parses or constructs one), recorded at the file tail (:1439-1453). HandlerStatusSchema / HandlerStatus ⇒ orphan value def once both carriers are gone (refactor(spec)!: remove the plugin sandboxing / integrity / approval config that never existed (#3896 follow-up) #3950, the ui/ThemeMode precedent) — removed with them.
  • Liveness ledger. Verdict dead, confirmed by the re-measure above. No ledger row moves: RestApiEndpointSchema is outside the walked population — it is not a registered metadata type and not in SPEC_ONLY_SCHEMAS (packages/spec/scripts/liveness/check-liveness.mts:328) — so there is no row to write and adding one would be an ORPHAN. The verdict is recorded in the schema comment, the D3 entry and the changeset.
  • ADR-0087. Tail-appended entries, registry.ts regenerated by gen:migration-registry: entries/retired-keys/18.api__RestApiEndpoint__handlerStatus.ts; entries/retired-defs/18.api__HandlerStatus.ts, 18.api__RouteCoverageEntry.ts, 18.api__RouteCoverageReport.ts; entries/semantic/18.rest-api-endpoint-handler-status-retired.ts. No D2 conversion, deliberately — a REST API plugin route registration is not a stack collection member and never a sys_metadata row, so a MetadataConversion would be a transform with no seam that ever runs (the kernel/Manifest:loading / kernel/KernelContext:previewMode disposition); for the same reason the tombstone carries no os migrate meta sentence. Registered under 18 (launch-window convention). spec-changes.json and the upgrade guide are unchanged because both project majors up to PROTOCOL_MAJOR (17) only — the same as every 18-registered precedent.
  • Generated baselines.json-schema.manifest/api.json −3 keys (deleted deliberately; the json-schema.manifest.json 的「deliberate removal」删行仍是纪律而非门禁 —— #4650 的同类洞,上移一层(整 schema 级) #4725 manifest deletion gate adjudicated all three against RETIRED_DEFS_BY_MAJOR[18]); authorable-surface/api.json −10 rows for the two defs (route 3, check (c) proof) and api/RestApiEndpoint:handlerStatus… [RETIRED]; api-surface/api.json, export-origins/api.json, declaration-map/api.json −6 names each; content/docs/references/** and the strictness-ledger counts regenerated by check:generated --fix. authorable-surface.base.json lags (allowed; check:authorable-surface green).
  • Forms / i18n. No *.form.ts offers the key; no bundle changes.
  • Pin tests.packages/spec/src/api/plugin-rest-api.handler-status-retirement.test.ts: all three former values (including the documented default 'implemented' — prose only, never a Zod .default(), so no residue window) refused with code: 'invalid_type', path: ['handlerStatus'] and the prescription text (ADR named, no issue id); the same refusal through the route-registration embed at ['endpoints', 0, 'handlerStatus']; positive control — a well-formed endpoint without the key parses and grows no handlerStatus property; the eight shipped default route registrations still parse; a tsc-channel pin (@ts-expect-error, file proven in the tsconfig.test.json program via --listFiles); zero holders for all six retired names on every public entry with the carriers surviving; RETIRED_KEYS_BY_MAJOR[18] / RETIRED_DEFS_BY_MAJOR[18] / step-18 semantic membership. type-alias-convention.pin.test.ts: pins Iso123 / Iso125 / Iso126 left with their schemas, count rebalanced 835 → 832 with the file's history note.
  • Changeset..changeset/rest-api-endpoint-handler-status-retired.md@objectstack/spec minor, BREAKING under the launch-window convention, FROM → TO + one-line fix, ADR-0087 marker registered rest-api-endpoint-handler-status-retired (check:adr-0087-registration green).
  • Enforce excluded. No 501 stub mounting, no registrar change.

Verification

Every heavy step ran under scripts/pm/os-verify-lock.sh (OS_VERIFY_LOCK_SLOT=issue-13823); every exit captured before any pipe; the gates' own verdict lines quoted.

Final head 875e3fa5e (chain 4): pnpm --filter @objectstack/spec build exit 0 (gen:schema: "3 schema(s) left the published set since a9b2be0, each declared (#4725)" and "2 baseline deletion(s) since a9b2be0 carry their own proof (#4650)"; check-dts-emitted: 34/34); check:generated (check-only) exit 0 — "✓ All 15 generated artifacts are up to date."; targeted vitest via exec vitest run --maxWorkers=2 FILES (type-alias-convention.pin, plugin-rest-api.handler-status-retirement, plugin-rest-api, retired-key-migrate-sentence, migrations) — "Test Files 5 passed (5)" / "Tests 172 passed (172)"; check:skill-examples exit 0 — "✅ 265 prose examples type-check across 3 surface(s)" (the @objectstack/client-react closure was built for it); check:adr-0087-registration exit 0 — "1 declared-breaking changeset(s), each carrying an ADR-0087 disposition"; check:empty-changeset, check-changeset-no-major, check:nul-bytes, check:doc-authoring, check:spec-parsed-alias all exit 0; git status --porcelain empty after the build (the authorable-surface.base.json anchor was not rewritten — it lags, allowed).

7cbf0ed60 (chain 3, the pin-literal fix): targeted vitest 5 files / 172 tests passed; check:test-typecheck exit 0; check:spec-parsed-alias / check:doc-authoring / check:nul-bytes exit 0; check:api-surface refused to judge ("dist/**/*.d.ts is OLDER than packages/spec/src" — the test-file edit post-dated the build; not a measurement, settled by the rebuild above).

90d567cd3 (chain 2, the full union): pnpm --filter @objectstack/spec typecheck exit 0 (tsc, the scripts tsconfig, and "check:test-typecheck: OK — 54 file(s) / 262 error(s) / 146 pinned signature(s)", ledger unchanged, so the new test file compiles clean; its membership in the tsconfig.test.json program proven with tsc --listFiles); full spec vitest--maxWorkers=2: "Test Files 1 failed | 451 passed (452)" / "Tests 1 failed | 12190 passed (12191)" — the single failure was still declares all 832 isomorphic pins (the toHaveLength literal still 835; the same red CI reported on Test Core 2/6), fixed in 7cbf0ed60 and green in chains 3 and 4; check:skill-examples exit 0; check:exported-any, check:dual-source-exports, check:entry-nameability, check:browser-reachable-entries exit 0; check:generated exit 0 (15/15); check:doc-authoring / check:nul-bytes / check:adr-0087-registration / check:spec-parsed-alias exit 0; check-dev-prereqs exit 1 = "The workspace is not built — 32 of 67 workspace packages declare an entry point under dist/ that is not on disk" (a pnpm dev precondition on apps and services, unrelated to this diff — NOT MEASURED, not red).

Earlier on the same tree (before the docs-only, test-literal and changeset-prose commits): check:variant-docs, check:empty-state, check:llms-txt, check:yaml-examples, check:template-manifests, check:error-code-provenance, check:objectui-pin-citations, check:quick-reference-counts, check:corpus-claim-drift, check:skill-identifier-liveness, check:doc-anchors, check:docs-single-h1, check:docs-audit-scope, check:test-source-alias, check:cross-package-test-inputs, check:published-files, check:type-check-coverage, check:migration-registry and check:liveness (both inside check:generated), and the root check-doc-frontmatter / check-docs-section-name / check-doc-route-spelling / check-section-landing-index / check-keyed-text-bounds / check-ci-filter-parity / check-comment-mask-adoption / check-shard-attestation / check-system-context-census / check-undeclared-dep-imports / check-plugin-teardown-shape / docs-audit/check-affected-docs / docs-audit/check-drift-comment / pm/check-half-states scripts — all exit 0. Earlier reds that this PR fixed before landing: check:doc-authoring (the tombstone string carried #13823; now cites ADR-0049 only, with a negative pin) and the pin-count test above.

Declared narrowing: the full 452-file spec suite ran on 90d567cd3; the two later commits change one assertion literal in a test file and changeset prose, re-verified with the targeted files rather than the whole suite (≈6 min held under a contended lock) — CI's Test Core runs the full suite on the final head. Gate list derived with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths; 74 commands at b862317); what was not run is the CI-owned farm named below. CI on 875e3fa at report time: 31 check-runs — completed/skipped: 2, completed/success: 14, in_progress/None: 15.

Not measured here (CI-owned)

  • check:type-check-coverage --re-measure / check:type-check-debt (needs the whole package closure built — PREREQUISITE NOT MET, exit 3, not a finding), check:test-completeness (grades CI's turbo test log), check:react-declaration-parity (needs objectui's manifest), the repo-wide pnpm lint and the rest of the 74-command derivation not named above.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21


Generated by Claude Code

os-zhuangand others added 4 commits September 2, 2026 09:10
…ge Report shapes (#13823)
WIP: tombstone, three whole-def removals, ADR-0087 registrations (key, defs,
D3 semantic entry), pin tests and changeset. Generated artifacts follow in
the next commit.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
…age retirement (#13823)
json-schema.manifest and authorable-surface rows for the three whole-def
removals deleted deliberately (route 3 — the #4725 manifest deletion gate
and check (c) adjudicated them against RETIRED_DEFS_BY_MAJOR[18]); the
tombstone row carries [RETIRED]; api-surface / export-origins /
declaration-map lose the six retired names; the reference page and the
strictness-ledger counts regenerate.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
…ic pin count rebalanced 835 -> 832 (#13823)
check:doc-authoring refuses an issue id in customer-facing spec text — the
prescription now cites ADR-0049 only (the id stays in the adjacent comment),
with a negative pin. The type-alias pin count drops by the three pins whose
schemas left the module, recorded in the file's own history block.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

14 anchor(s) derived from 1 changed package(s); no hand-written page names any of them. ⚠️9 changed file(s) yielded no anchor (packages/spec/api-surface/api.json, packages/spec/authorable-surface/api.json, packages/spec/declaration-map/api.json, …), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

What this run could not see
  • 9 changed file(s) yielded no anchor (packages/spec/api-surface/api.json, packages/spec/authorable-surface/api.json, packages/spec/declaration-map/api.json, …) — pages documenting those are invisible to this run
  • 10 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 — 128 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 99b8faf8f937d8d2992f1bf167e418687c5f2f71packageMentionDocs.

Which tree this was computed on

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

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

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests tooling labels Sep 2, 2026
@claude

claudeBot commented Sep 2, 2026

Copy link
Copy Markdown
ContributorAuthor

CI red on head 90d567cd — this PR's own; patch round requested from the dispatched dev. (domain:spec seat, session session_01GDA48PuRFrHyRfdkBz8m21, seat post #6017.)

  • Failing check: Test Core (2/6)packages/spec/src/type-alias-convention.pin.test.ts > "still declares all 832 isomorphic pins": expected [ Array(832) ] to have a length of 835 but got 832 at line 2093.
  • Cause: the diff updated the case title, the section header and added the 835 -> 832 receipt prose, but the assertion literal expect(pins).toHaveLength(835) directly under the receipt still reads 835. One-literal fix (835 -> 832); every other file in that shard passed (450 passed / 1 failed).
  • Not a base failure: the same case is green on origin/main at 835 pins; the count moved because this PR removed Iso123 / Iso125 / Iso126 with the retired defs, which is the intended shape.
  • Action: the dev is fixing the literal on this branch as a new commit (no history rewrite), re-running the spec test locally, then pushing. Contract review resumes on the pushed head; the landing gate stays "every check on the current head green".

Generated by Claude Code

os-zhuangand others added 2 commits September 2, 2026 10:32
…eipt to 832 (#13823)
Title, header and receipt already said 832; the toHaveLength literal under
the receipt still read 835 (Test Core 2/6 on the PR head, and the local
full run: 1 failed / 12190 passed).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
…e base (#13823)
The published skill taught handlerStatus at this PR's base; main dropped that
teaching in the #14448 optimization flight (bae4088), so the changeset —
release-notes input — no longer claims an outstanding skills limb.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/lteststooling

Projects

None yet

1 participant

@os-zhuang
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(spec): retire RestApiEndpoint.handlerStatus and the Route Coverage Report shapes (#13823) - #14531

Merged
os-zhuang merged 6 commits into
mainfrom
claude/issue-13823-retire-handler-status
Sep 2, 2026
Merged

feat(spec): retire RestApiEndpoint.handlerStatus and the Route Coverage Report shapes (#13823)#14531
os-zhuang merged 6 commits into
mainfrom
claude/issue-13823-retire-handler-status

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#13823

Ruling implemented

Director decision batch #27, maintainer 2026-09-01 verbatim 「同意」 (issue comment 5494755488), implemented exactly:

  1. remove:RestApiEndpointSchema.handlerStatusspec-property-retirement 手册退役(liveness 台账 verdict 确认 → ADR-0087 转换 → 墓碑 + 生成基线/表单/文档/pin 全套);RouteCoverageEntrySchema/RouteCoverageReportSchema 随同一 PR 按 liveness 读数处置(零构造者即同退);
  2. 前置一扫:退役前跑教材扫描 —— 除 flight ⑦ 已纠的那句外,还有哪些 published skill / 文档 / 示例在教 handlerStatus;非零则同笔清扫(教材曾教过不存在的 501 行为,是本卡的出处);
  3. enforce 排除:「声明未建的路由回 501」是零拉力的新能力,不是修复;
  4. 类方向入册(finding(spec): all six branded identifier schemas in branded-types.zod.ts are declared but unbound — no schema anywhere composes them #13612 / finding(spec): EventNameSchema's only three binding schemas have no runtime consumer — the live event vocabulary is a closed enum that never touches it #13613 引用用):ADR-0049 declared-but-unenforced 的默认处置 = retire(零拉力键);enforce/bind 只当有具名消费者或实测拉力。
  5. 条款②:YES(发布 accept 面收窄)⇒ draft + needs:contract-review 同笔,本席复审;changeset 按退役惯例。

Clause ② applies (the published accept set narrows): draft PR, needs:contract-review on both carriers, in-seat review. Item 4 is recorded here as the class direction for #13612 / #13613 — not ruled by this PR.

Premise re-measured on origin/main (a9b2be0, 2026-09-02)

Identifier search for handlerStatus, skills/** and tests excluded — three hits, all in the declaring file:

sitewhat
packages/spec/src/api/plugin-rest-api.zod.ts:177the declaration on RestApiEndpointSchema (HandlerStatusSchema.optional())
packages/spec/src/api/plugin-rest-api.zod.ts:1415the same enum re-declared on RouteCoverageEntrySchema
packages/spec/src/api/plugin-rest-api.zod.ts:1431the docblock saying adapters SHOULD warn when handlerStatus !== 'implemented'

Plus CHANGELOG.md:1502 (history) and generated artifacts. DispatcherErrorCode.enum.NOT_IMPLEMENTED emitters, none consulting the key: packages/runtime/src/endpoint-executor.ts:320,505,517, packages/runtime/src/api-mapping.ts:225, and one more than the card counted — packages/runtime/src/api-endpoint-step.ts:343 — every one the declarative-endpoint executor refusing a target or mapping it cannot serve. RouteCoverageEntrySchema / RouteCoverageReportSchema constructors: zero in objectstack (only the type-alias pin and generated artifacts reference them), zero in objectui at the pinned sha d8ec8d6d, zero in cloud. RestApiEndpointSchema itself is parsed by nothing in the tree outside its own unit tests. Premise still valid; no consumer has appeared.

Teaching sweep (before retiring)

pathhitaction
content/docs/references/api/plugin-rest-api.mdx:200,375,408,424,442generated reference rows for handlerStatus / the coverage shapesAUTO-GEN — regenerated by gen:docs (tombstone row now reads [REMOVED] …; coverage sections gone)
content/docs/references/index.mdx:90generated export list naming HandlerStatus, RouteCoverageEntry, RouteCoverageReportAUTO-GEN — regenerated
content/docs/** hand-written treesno hit for handlerStatus; the 501 prose at api/index.mdx:161,171, kernel/services-checklist.mdx:193, permissions/authentication.mdx:1243,1281 describes the service-slot / discovery status 501, not this keynot the false claim — no action
examples/**, packages/*/README.md, packages/create-objectstack/**zero hitsnone
skills/objectstack-api/SKILL.md (at this PR's base a9b2be0: :136handlerStatus: 'implemented', inside the os:check-marked RestApiEndpointSchema.parse({...}) example; :380 the 501 NOT_IMPLEMENTED — Route declared but handler is a stub table row; :383-391 the "Handler Status" section; :393-395 flight ⑦'s PR #13808 correction)four teaching sites at the base⛔ governed surface, not edited. None on main: bae4088f3 (#14448, 08:27Z today) cut every one — git grep -n -i -E 'handlerStatus|handler status|RouteCoverage|HandlerStatus' origin/main -- skills/ returns zero hits at 99b8faf8f, with RestApiEndpoint still hitting the skill as the live control — so no skills-lane follow-up is needed. (check:skill-examples was measured green against the base's marked block too: parse takes unknown, so the tombstone's never input type never reached it.)

Retirement steps (spec-property-retirement playbook)

  • Route.RestApiEndpointSchema is a non-strict lazySchema(() => z.object(...))retiredKey() tombstone for the key (packages/spec/src/api/plugin-rest-api.zod.ts:208-217), prescription hoisted as HANDLER_STATUS_RETIRED (:131-138) under the retirement record (:91-130). RouteCoverageEntrySchema / RouteCoverageReportSchema ⇒ whole-def removal, route 3 (nobody parses or constructs one), recorded at the file tail (:1439-1453). HandlerStatusSchema / HandlerStatus ⇒ orphan value def once both carriers are gone (refactor(spec)!: remove the plugin sandboxing / integrity / approval config that never existed (#3896 follow-up) #3950, the ui/ThemeMode precedent) — removed with them.
  • Liveness ledger. Verdict dead, confirmed by the re-measure above. No ledger row moves: RestApiEndpointSchema is outside the walked population — it is not a registered metadata type and not in SPEC_ONLY_SCHEMAS (packages/spec/scripts/liveness/check-liveness.mts:328) — so there is no row to write and adding one would be an ORPHAN. The verdict is recorded in the schema comment, the D3 entry and the changeset.
  • ADR-0087. Tail-appended entries, registry.ts regenerated by gen:migration-registry: entries/retired-keys/18.api__RestApiEndpoint__handlerStatus.ts; entries/retired-defs/18.api__HandlerStatus.ts, 18.api__RouteCoverageEntry.ts, 18.api__RouteCoverageReport.ts; entries/semantic/18.rest-api-endpoint-handler-status-retired.ts. No D2 conversion, deliberately — a REST API plugin route registration is not a stack collection member and never a sys_metadata row, so a MetadataConversion would be a transform with no seam that ever runs (the kernel/Manifest:loading / kernel/KernelContext:previewMode disposition); for the same reason the tombstone carries no os migrate meta sentence. Registered under 18 (launch-window convention). spec-changes.json and the upgrade guide are unchanged because both project majors up to PROTOCOL_MAJOR (17) only — the same as every 18-registered precedent.
  • Generated baselines.json-schema.manifest/api.json −3 keys (deleted deliberately; the json-schema.manifest.json 的「deliberate removal」删行仍是纪律而非门禁 —— #4650 的同类洞,上移一层(整 schema 级) #4725 manifest deletion gate adjudicated all three against RETIRED_DEFS_BY_MAJOR[18]); authorable-surface/api.json −10 rows for the two defs (route 3, check (c) proof) and api/RestApiEndpoint:handlerStatus… [RETIRED]; api-surface/api.json, export-origins/api.json, declaration-map/api.json −6 names each; content/docs/references/** and the strictness-ledger counts regenerated by check:generated --fix. authorable-surface.base.json lags (allowed; check:authorable-surface green).
  • Forms / i18n. No *.form.ts offers the key; no bundle changes.
  • Pin tests.packages/spec/src/api/plugin-rest-api.handler-status-retirement.test.ts: all three former values (including the documented default 'implemented' — prose only, never a Zod .default(), so no residue window) refused with code: 'invalid_type', path: ['handlerStatus'] and the prescription text (ADR named, no issue id); the same refusal through the route-registration embed at ['endpoints', 0, 'handlerStatus']; positive control — a well-formed endpoint without the key parses and grows no handlerStatus property; the eight shipped default route registrations still parse; a tsc-channel pin (@ts-expect-error, file proven in the tsconfig.test.json program via --listFiles); zero holders for all six retired names on every public entry with the carriers surviving; RETIRED_KEYS_BY_MAJOR[18] / RETIRED_DEFS_BY_MAJOR[18] / step-18 semantic membership. type-alias-convention.pin.test.ts: pins Iso123 / Iso125 / Iso126 left with their schemas, count rebalanced 835 → 832 with the file's history note.
  • Changeset..changeset/rest-api-endpoint-handler-status-retired.md@objectstack/spec minor, BREAKING under the launch-window convention, FROM → TO + one-line fix, ADR-0087 marker registered rest-api-endpoint-handler-status-retired (check:adr-0087-registration green).
  • Enforce excluded. No 501 stub mounting, no registrar change.

Verification

Every heavy step ran under scripts/pm/os-verify-lock.sh (OS_VERIFY_LOCK_SLOT=issue-13823); every exit captured before any pipe; the gates' own verdict lines quoted.

Final head 875e3fa5e (chain 4): pnpm --filter @objectstack/spec build exit 0 (gen:schema: "3 schema(s) left the published set since a9b2be0, each declared (#4725)" and "2 baseline deletion(s) since a9b2be0 carry their own proof (#4650)"; check-dts-emitted: 34/34); check:generated (check-only) exit 0 — "✓ All 15 generated artifacts are up to date."; targeted vitest via exec vitest run --maxWorkers=2 FILES (type-alias-convention.pin, plugin-rest-api.handler-status-retirement, plugin-rest-api, retired-key-migrate-sentence, migrations) — "Test Files 5 passed (5)" / "Tests 172 passed (172)"; check:skill-examples exit 0 — "✅ 265 prose examples type-check across 3 surface(s)" (the @objectstack/client-react closure was built for it); check:adr-0087-registration exit 0 — "1 declared-breaking changeset(s), each carrying an ADR-0087 disposition"; check:empty-changeset, check-changeset-no-major, check:nul-bytes, check:doc-authoring, check:spec-parsed-alias all exit 0; git status --porcelain empty after the build (the authorable-surface.base.json anchor was not rewritten — it lags, allowed).

7cbf0ed60 (chain 3, the pin-literal fix): targeted vitest 5 files / 172 tests passed; check:test-typecheck exit 0; check:spec-parsed-alias / check:doc-authoring / check:nul-bytes exit 0; check:api-surface refused to judge ("dist/**/*.d.ts is OLDER than packages/spec/src" — the test-file edit post-dated the build; not a measurement, settled by the rebuild above).

90d567cd3 (chain 2, the full union): pnpm --filter @objectstack/spec typecheck exit 0 (tsc, the scripts tsconfig, and "check:test-typecheck: OK — 54 file(s) / 262 error(s) / 146 pinned signature(s)", ledger unchanged, so the new test file compiles clean; its membership in the tsconfig.test.json program proven with tsc --listFiles); full spec vitest--maxWorkers=2: "Test Files 1 failed | 451 passed (452)" / "Tests 1 failed | 12190 passed (12191)" — the single failure was still declares all 832 isomorphic pins (the toHaveLength literal still 835; the same red CI reported on Test Core 2/6), fixed in 7cbf0ed60 and green in chains 3 and 4; check:skill-examples exit 0; check:exported-any, check:dual-source-exports, check:entry-nameability, check:browser-reachable-entries exit 0; check:generated exit 0 (15/15); check:doc-authoring / check:nul-bytes / check:adr-0087-registration / check:spec-parsed-alias exit 0; check-dev-prereqs exit 1 = "The workspace is not built — 32 of 67 workspace packages declare an entry point under dist/ that is not on disk" (a pnpm dev precondition on apps and services, unrelated to this diff — NOT MEASURED, not red).

Earlier on the same tree (before the docs-only, test-literal and changeset-prose commits): check:variant-docs, check:empty-state, check:llms-txt, check:yaml-examples, check:template-manifests, check:error-code-provenance, check:objectui-pin-citations, check:quick-reference-counts, check:corpus-claim-drift, check:skill-identifier-liveness, check:doc-anchors, check:docs-single-h1, check:docs-audit-scope, check:test-source-alias, check:cross-package-test-inputs, check:published-files, check:type-check-coverage, check:migration-registry and check:liveness (both inside check:generated), and the root check-doc-frontmatter / check-docs-section-name / check-doc-route-spelling / check-section-landing-index / check-keyed-text-bounds / check-ci-filter-parity / check-comment-mask-adoption / check-shard-attestation / check-system-context-census / check-undeclared-dep-imports / check-plugin-teardown-shape / docs-audit/check-affected-docs / docs-audit/check-drift-comment / pm/check-half-states scripts — all exit 0. Earlier reds that this PR fixed before landing: check:doc-authoring (the tombstone string carried #13823; now cites ADR-0049 only, with a negative pin) and the pin-count test above.

Declared narrowing: the full 452-file spec suite ran on 90d567cd3; the two later commits change one assertion literal in a test file and changeset prose, re-verified with the targeted files rather than the whole suite (≈6 min held under a contended lock) — CI's Test Core runs the full suite on the final head. Gate list derived with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths; 74 commands at b862317); what was not run is the CI-owned farm named below. CI on 875e3fa at report time: 31 check-runs — completed/skipped: 2, completed/success: 14, in_progress/None: 15.

Not measured here (CI-owned)

  • check:type-check-coverage --re-measure / check:type-check-debt (needs the whole package closure built — PREREQUISITE NOT MET, exit 3, not a finding), check:test-completeness (grades CI's turbo test log), check:react-declaration-parity (needs objectui's manifest), the repo-wide pnpm lint and the rest of the 74-command derivation not named above.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21


Generated by Claude Code

os-zhuangand others added 4 commits September 2, 2026 09:10
…ge Report shapes (#13823)
WIP: tombstone, three whole-def removals, ADR-0087 registrations (key, defs,
D3 semantic entry), pin tests and changeset. Generated artifacts follow in
the next commit.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
…age retirement (#13823)
json-schema.manifest and authorable-surface rows for the three whole-def
removals deleted deliberately (route 3 — the #4725 manifest deletion gate
and check (c) adjudicated them against RETIRED_DEFS_BY_MAJOR[18]); the
tombstone row carries [RETIRED]; api-surface / export-origins /
declaration-map lose the six retired names; the reference page and the
strictness-ledger counts regenerate.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
…ic pin count rebalanced 835 -> 832 (#13823)
check:doc-authoring refuses an issue id in customer-facing spec text — the
prescription now cites ADR-0049 only (the id stays in the adjacent comment),
with a negative pin. The type-alias pin count drops by the three pins whose
schemas left the module, recorded in the file's own history block.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

14 anchor(s) derived from 1 changed package(s); no hand-written page names any of them. ⚠️9 changed file(s) yielded no anchor (packages/spec/api-surface/api.json, packages/spec/authorable-surface/api.json, packages/spec/declaration-map/api.json, …), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

What this run could not see
  • 9 changed file(s) yielded no anchor (packages/spec/api-surface/api.json, packages/spec/authorable-surface/api.json, packages/spec/declaration-map/api.json, …) — pages documenting those are invisible to this run
  • 10 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 — 128 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 99b8faf8f937d8d2992f1bf167e418687c5f2f71packageMentionDocs.

Which tree this was computed on

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

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

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests tooling labels Sep 2, 2026
@claude

claudeBot commented Sep 2, 2026

Copy link
Copy Markdown
ContributorAuthor

CI red on head 90d567cd — this PR's own; patch round requested from the dispatched dev. (domain:spec seat, session session_01GDA48PuRFrHyRfdkBz8m21, seat post #6017.)

  • Failing check: Test Core (2/6)packages/spec/src/type-alias-convention.pin.test.ts > "still declares all 832 isomorphic pins": expected [ Array(832) ] to have a length of 835 but got 832 at line 2093.
  • Cause: the diff updated the case title, the section header and added the 835 -> 832 receipt prose, but the assertion literal expect(pins).toHaveLength(835) directly under the receipt still reads 835. One-literal fix (835 -> 832); every other file in that shard passed (450 passed / 1 failed).
  • Not a base failure: the same case is green on origin/main at 835 pins; the count moved because this PR removed Iso123 / Iso125 / Iso126 with the retired defs, which is the intended shape.
  • Action: the dev is fixing the literal on this branch as a new commit (no history rewrite), re-running the spec test locally, then pushing. Contract review resumes on the pushed head; the landing gate stays "every check on the current head green".

Generated by Claude Code

os-zhuangand others added 2 commits September 2, 2026 10:32
…eipt to 832 (#13823)
Title, header and receipt already said 832; the toHaveLength literal under
the receipt still read 835 (Test Core 2/6 on the PR head, and the local
full run: 1 failed / 12190 passed).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
…e base (#13823)
The published skill taught handlerStatus at this PR's base; main dropped that
teaching in the #14448 optimization flight (bae4088), so the changeset —
release-notes input — no longer claims an outstanding skills limb.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/lteststooling

Projects

None yet

1 participant

@os-zhuang
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat(spec): retire RestApiEndpoint.handlerStatus and the Route Coverage Report shapes (#13823) - #14531

Merged
os-zhuang merged 6 commits into
mainfrom
claude/issue-13823-retire-handler-status
Sep 2, 2026
Merged

feat(spec): retire RestApiEndpoint.handlerStatus and the Route Coverage Report shapes (#13823)#14531
os-zhuang merged 6 commits into
mainfrom
claude/issue-13823-retire-handler-status

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#13823

Ruling implemented

Director decision batch #27, maintainer 2026-09-01 verbatim 「同意」 (issue comment 5494755488), implemented exactly:

  1. remove:RestApiEndpointSchema.handlerStatusspec-property-retirement 手册退役(liveness 台账 verdict 确认 → ADR-0087 转换 → 墓碑 + 生成基线/表单/文档/pin 全套);RouteCoverageEntrySchema/RouteCoverageReportSchema 随同一 PR 按 liveness 读数处置(零构造者即同退);
  2. 前置一扫:退役前跑教材扫描 —— 除 flight ⑦ 已纠的那句外,还有哪些 published skill / 文档 / 示例在教 handlerStatus;非零则同笔清扫(教材曾教过不存在的 501 行为,是本卡的出处);
  3. enforce 排除:「声明未建的路由回 501」是零拉力的新能力,不是修复;
  4. 类方向入册(finding(spec): all six branded identifier schemas in branded-types.zod.ts are declared but unbound — no schema anywhere composes them #13612 / finding(spec): EventNameSchema's only three binding schemas have no runtime consumer — the live event vocabulary is a closed enum that never touches it #13613 引用用):ADR-0049 declared-but-unenforced 的默认处置 = retire(零拉力键);enforce/bind 只当有具名消费者或实测拉力。
  5. 条款②:YES(发布 accept 面收窄)⇒ draft + needs:contract-review 同笔,本席复审;changeset 按退役惯例。

Clause ② applies (the published accept set narrows): draft PR, needs:contract-review on both carriers, in-seat review. Item 4 is recorded here as the class direction for #13612 / #13613 — not ruled by this PR.

Premise re-measured on origin/main (a9b2be0, 2026-09-02)

Identifier search for handlerStatus, skills/** and tests excluded — three hits, all in the declaring file:

sitewhat
packages/spec/src/api/plugin-rest-api.zod.ts:177the declaration on RestApiEndpointSchema (HandlerStatusSchema.optional())
packages/spec/src/api/plugin-rest-api.zod.ts:1415the same enum re-declared on RouteCoverageEntrySchema
packages/spec/src/api/plugin-rest-api.zod.ts:1431the docblock saying adapters SHOULD warn when handlerStatus !== 'implemented'

Plus CHANGELOG.md:1502 (history) and generated artifacts. DispatcherErrorCode.enum.NOT_IMPLEMENTED emitters, none consulting the key: packages/runtime/src/endpoint-executor.ts:320,505,517, packages/runtime/src/api-mapping.ts:225, and one more than the card counted — packages/runtime/src/api-endpoint-step.ts:343 — every one the declarative-endpoint executor refusing a target or mapping it cannot serve. RouteCoverageEntrySchema / RouteCoverageReportSchema constructors: zero in objectstack (only the type-alias pin and generated artifacts reference them), zero in objectui at the pinned sha d8ec8d6d, zero in cloud. RestApiEndpointSchema itself is parsed by nothing in the tree outside its own unit tests. Premise still valid; no consumer has appeared.

Teaching sweep (before retiring)

pathhitaction
content/docs/references/api/plugin-rest-api.mdx:200,375,408,424,442generated reference rows for handlerStatus / the coverage shapesAUTO-GEN — regenerated by gen:docs (tombstone row now reads [REMOVED] …; coverage sections gone)
content/docs/references/index.mdx:90generated export list naming HandlerStatus, RouteCoverageEntry, RouteCoverageReportAUTO-GEN — regenerated
content/docs/** hand-written treesno hit for handlerStatus; the 501 prose at api/index.mdx:161,171, kernel/services-checklist.mdx:193, permissions/authentication.mdx:1243,1281 describes the service-slot / discovery status 501, not this keynot the false claim — no action
examples/**, packages/*/README.md, packages/create-objectstack/**zero hitsnone
skills/objectstack-api/SKILL.md (at this PR's base a9b2be0: :136handlerStatus: 'implemented', inside the os:check-marked RestApiEndpointSchema.parse({...}) example; :380 the 501 NOT_IMPLEMENTED — Route declared but handler is a stub table row; :383-391 the "Handler Status" section; :393-395 flight ⑦'s PR #13808 correction)four teaching sites at the base⛔ governed surface, not edited. None on main: bae4088f3 (#14448, 08:27Z today) cut every one — git grep -n -i -E 'handlerStatus|handler status|RouteCoverage|HandlerStatus' origin/main -- skills/ returns zero hits at 99b8faf8f, with RestApiEndpoint still hitting the skill as the live control — so no skills-lane follow-up is needed. (check:skill-examples was measured green against the base's marked block too: parse takes unknown, so the tombstone's never input type never reached it.)

Retirement steps (spec-property-retirement playbook)

  • Route.RestApiEndpointSchema is a non-strict lazySchema(() => z.object(...))retiredKey() tombstone for the key (packages/spec/src/api/plugin-rest-api.zod.ts:208-217), prescription hoisted as HANDLER_STATUS_RETIRED (:131-138) under the retirement record (:91-130). RouteCoverageEntrySchema / RouteCoverageReportSchema ⇒ whole-def removal, route 3 (nobody parses or constructs one), recorded at the file tail (:1439-1453). HandlerStatusSchema / HandlerStatus ⇒ orphan value def once both carriers are gone (refactor(spec)!: remove the plugin sandboxing / integrity / approval config that never existed (#3896 follow-up) #3950, the ui/ThemeMode precedent) — removed with them.
  • Liveness ledger. Verdict dead, confirmed by the re-measure above. No ledger row moves: RestApiEndpointSchema is outside the walked population — it is not a registered metadata type and not in SPEC_ONLY_SCHEMAS (packages/spec/scripts/liveness/check-liveness.mts:328) — so there is no row to write and adding one would be an ORPHAN. The verdict is recorded in the schema comment, the D3 entry and the changeset.
  • ADR-0087. Tail-appended entries, registry.ts regenerated by gen:migration-registry: entries/retired-keys/18.api__RestApiEndpoint__handlerStatus.ts; entries/retired-defs/18.api__HandlerStatus.ts, 18.api__RouteCoverageEntry.ts, 18.api__RouteCoverageReport.ts; entries/semantic/18.rest-api-endpoint-handler-status-retired.ts. No D2 conversion, deliberately — a REST API plugin route registration is not a stack collection member and never a sys_metadata row, so a MetadataConversion would be a transform with no seam that ever runs (the kernel/Manifest:loading / kernel/KernelContext:previewMode disposition); for the same reason the tombstone carries no os migrate meta sentence. Registered under 18 (launch-window convention). spec-changes.json and the upgrade guide are unchanged because both project majors up to PROTOCOL_MAJOR (17) only — the same as every 18-registered precedent.
  • Generated baselines.json-schema.manifest/api.json −3 keys (deleted deliberately; the json-schema.manifest.json 的「deliberate removal」删行仍是纪律而非门禁 —— #4650 的同类洞,上移一层(整 schema 级) #4725 manifest deletion gate adjudicated all three against RETIRED_DEFS_BY_MAJOR[18]); authorable-surface/api.json −10 rows for the two defs (route 3, check (c) proof) and api/RestApiEndpoint:handlerStatus… [RETIRED]; api-surface/api.json, export-origins/api.json, declaration-map/api.json −6 names each; content/docs/references/** and the strictness-ledger counts regenerated by check:generated --fix. authorable-surface.base.json lags (allowed; check:authorable-surface green).
  • Forms / i18n. No *.form.ts offers the key; no bundle changes.
  • Pin tests.packages/spec/src/api/plugin-rest-api.handler-status-retirement.test.ts: all three former values (including the documented default 'implemented' — prose only, never a Zod .default(), so no residue window) refused with code: 'invalid_type', path: ['handlerStatus'] and the prescription text (ADR named, no issue id); the same refusal through the route-registration embed at ['endpoints', 0, 'handlerStatus']; positive control — a well-formed endpoint without the key parses and grows no handlerStatus property; the eight shipped default route registrations still parse; a tsc-channel pin (@ts-expect-error, file proven in the tsconfig.test.json program via --listFiles); zero holders for all six retired names on every public entry with the carriers surviving; RETIRED_KEYS_BY_MAJOR[18] / RETIRED_DEFS_BY_MAJOR[18] / step-18 semantic membership. type-alias-convention.pin.test.ts: pins Iso123 / Iso125 / Iso126 left with their schemas, count rebalanced 835 → 832 with the file's history note.
  • Changeset..changeset/rest-api-endpoint-handler-status-retired.md@objectstack/spec minor, BREAKING under the launch-window convention, FROM → TO + one-line fix, ADR-0087 marker registered rest-api-endpoint-handler-status-retired (check:adr-0087-registration green).
  • Enforce excluded. No 501 stub mounting, no registrar change.

Verification

Every heavy step ran under scripts/pm/os-verify-lock.sh (OS_VERIFY_LOCK_SLOT=issue-13823); every exit captured before any pipe; the gates' own verdict lines quoted.

Final head 875e3fa5e (chain 4): pnpm --filter @objectstack/spec build exit 0 (gen:schema: "3 schema(s) left the published set since a9b2be0, each declared (#4725)" and "2 baseline deletion(s) since a9b2be0 carry their own proof (#4650)"; check-dts-emitted: 34/34); check:generated (check-only) exit 0 — "✓ All 15 generated artifacts are up to date."; targeted vitest via exec vitest run --maxWorkers=2 FILES (type-alias-convention.pin, plugin-rest-api.handler-status-retirement, plugin-rest-api, retired-key-migrate-sentence, migrations) — "Test Files 5 passed (5)" / "Tests 172 passed (172)"; check:skill-examples exit 0 — "✅ 265 prose examples type-check across 3 surface(s)" (the @objectstack/client-react closure was built for it); check:adr-0087-registration exit 0 — "1 declared-breaking changeset(s), each carrying an ADR-0087 disposition"; check:empty-changeset, check-changeset-no-major, check:nul-bytes, check:doc-authoring, check:spec-parsed-alias all exit 0; git status --porcelain empty after the build (the authorable-surface.base.json anchor was not rewritten — it lags, allowed).

7cbf0ed60 (chain 3, the pin-literal fix): targeted vitest 5 files / 172 tests passed; check:test-typecheck exit 0; check:spec-parsed-alias / check:doc-authoring / check:nul-bytes exit 0; check:api-surface refused to judge ("dist/**/*.d.ts is OLDER than packages/spec/src" — the test-file edit post-dated the build; not a measurement, settled by the rebuild above).

90d567cd3 (chain 2, the full union): pnpm --filter @objectstack/spec typecheck exit 0 (tsc, the scripts tsconfig, and "check:test-typecheck: OK — 54 file(s) / 262 error(s) / 146 pinned signature(s)", ledger unchanged, so the new test file compiles clean; its membership in the tsconfig.test.json program proven with tsc --listFiles); full spec vitest--maxWorkers=2: "Test Files 1 failed | 451 passed (452)" / "Tests 1 failed | 12190 passed (12191)" — the single failure was still declares all 832 isomorphic pins (the toHaveLength literal still 835; the same red CI reported on Test Core 2/6), fixed in 7cbf0ed60 and green in chains 3 and 4; check:skill-examples exit 0; check:exported-any, check:dual-source-exports, check:entry-nameability, check:browser-reachable-entries exit 0; check:generated exit 0 (15/15); check:doc-authoring / check:nul-bytes / check:adr-0087-registration / check:spec-parsed-alias exit 0; check-dev-prereqs exit 1 = "The workspace is not built — 32 of 67 workspace packages declare an entry point under dist/ that is not on disk" (a pnpm dev precondition on apps and services, unrelated to this diff — NOT MEASURED, not red).

Earlier on the same tree (before the docs-only, test-literal and changeset-prose commits): check:variant-docs, check:empty-state, check:llms-txt, check:yaml-examples, check:template-manifests, check:error-code-provenance, check:objectui-pin-citations, check:quick-reference-counts, check:corpus-claim-drift, check:skill-identifier-liveness, check:doc-anchors, check:docs-single-h1, check:docs-audit-scope, check:test-source-alias, check:cross-package-test-inputs, check:published-files, check:type-check-coverage, check:migration-registry and check:liveness (both inside check:generated), and the root check-doc-frontmatter / check-docs-section-name / check-doc-route-spelling / check-section-landing-index / check-keyed-text-bounds / check-ci-filter-parity / check-comment-mask-adoption / check-shard-attestation / check-system-context-census / check-undeclared-dep-imports / check-plugin-teardown-shape / docs-audit/check-affected-docs / docs-audit/check-drift-comment / pm/check-half-states scripts — all exit 0. Earlier reds that this PR fixed before landing: check:doc-authoring (the tombstone string carried #13823; now cites ADR-0049 only, with a negative pin) and the pin-count test above.

Declared narrowing: the full 452-file spec suite ran on 90d567cd3; the two later commits change one assertion literal in a test file and changeset prose, re-verified with the targeted files rather than the whole suite (≈6 min held under a contended lock) — CI's Test Core runs the full suite on the final head. Gate list derived with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths; 74 commands at b862317); what was not run is the CI-owned farm named below. CI on 875e3fa at report time: 31 check-runs — completed/skipped: 2, completed/success: 14, in_progress/None: 15.

Not measured here (CI-owned)

  • check:type-check-coverage --re-measure / check:type-check-debt (needs the whole package closure built — PREREQUISITE NOT MET, exit 3, not a finding), check:test-completeness (grades CI's turbo test log), check:react-declaration-parity (needs objectui's manifest), the repo-wide pnpm lint and the rest of the 74-command derivation not named above.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21


Generated by Claude Code

os-zhuangand others added 4 commits September 2, 2026 09:10
…ge Report shapes (#13823)
WIP: tombstone, three whole-def removals, ADR-0087 registrations (key, defs,
D3 semantic entry), pin tests and changeset. Generated artifacts follow in
the next commit.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
…age retirement (#13823)
json-schema.manifest and authorable-surface rows for the three whole-def
removals deleted deliberately (route 3 — the #4725 manifest deletion gate
and check (c) adjudicated them against RETIRED_DEFS_BY_MAJOR[18]); the
tombstone row carries [RETIRED]; api-surface / export-origins /
declaration-map lose the six retired names; the reference page and the
strictness-ledger counts regenerate.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
…ic pin count rebalanced 835 -> 832 (#13823)
check:doc-authoring refuses an issue id in customer-facing spec text — the
prescription now cites ADR-0049 only (the id stays in the adjacent comment),
with a negative pin. The type-alias pin count drops by the three pins whose
schemas left the module, recorded in the file's own history block.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

14 anchor(s) derived from 1 changed package(s); no hand-written page names any of them. ⚠️9 changed file(s) yielded no anchor (packages/spec/api-surface/api.json, packages/spec/authorable-surface/api.json, packages/spec/declaration-map/api.json, …), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

What this run could not see
  • 9 changed file(s) yielded no anchor (packages/spec/api-surface/api.json, packages/spec/authorable-surface/api.json, packages/spec/declaration-map/api.json, …) — pages documenting those are invisible to this run
  • 10 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 — 128 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 99b8faf8f937d8d2992f1bf167e418687c5f2f71packageMentionDocs.

Which tree this was computed on

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

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

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests tooling labels Sep 2, 2026
@claude

claudeBot commented Sep 2, 2026

Copy link
Copy Markdown
ContributorAuthor

CI red on head 90d567cd — this PR's own; patch round requested from the dispatched dev. (domain:spec seat, session session_01GDA48PuRFrHyRfdkBz8m21, seat post #6017.)

  • Failing check: Test Core (2/6)packages/spec/src/type-alias-convention.pin.test.ts > "still declares all 832 isomorphic pins": expected [ Array(832) ] to have a length of 835 but got 832 at line 2093.
  • Cause: the diff updated the case title, the section header and added the 835 -> 832 receipt prose, but the assertion literal expect(pins).toHaveLength(835) directly under the receipt still reads 835. One-literal fix (835 -> 832); every other file in that shard passed (450 passed / 1 failed).
  • Not a base failure: the same case is green on origin/main at 835 pins; the count moved because this PR removed Iso123 / Iso125 / Iso126 with the retired defs, which is the intended shape.
  • Action: the dev is fixing the literal on this branch as a new commit (no history rewrite), re-running the spec test locally, then pushing. Contract review resumes on the pushed head; the landing gate stays "every check on the current head green".

Generated by Claude Code

os-zhuangand others added 2 commits September 2, 2026 10:32
…eipt to 832 (#13823)
Title, header and receipt already said 832; the toHaveLength literal under
the receipt still read 835 (Test Core 2/6 on the PR head, and the local
full run: 1 failed / 12190 passed).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
…e base (#13823)
The published skill taught handlerStatus at this PR's base; main dropped that
teaching in the #14448 optimization flight (bae4088), so the changeset —
release-notes input — no longer claims an outstanding skills limb.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/lteststooling

Projects

None yet

1 participant

@os-zhuang
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(spec): retire RestApiEndpoint.handlerStatus and the Route Coverage Report shapes (#13823) - #14531

Merged
os-zhuang merged 6 commits into
mainfrom
claude/issue-13823-retire-handler-status
Sep 2, 2026
Merged

feat(spec): retire RestApiEndpoint.handlerStatus and the Route Coverage Report shapes (#13823)#14531
os-zhuang merged 6 commits into
mainfrom
claude/issue-13823-retire-handler-status

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#13823

Ruling implemented

Director decision batch #27, maintainer 2026-09-01 verbatim 「同意」 (issue comment 5494755488), implemented exactly:

  1. remove:RestApiEndpointSchema.handlerStatusspec-property-retirement 手册退役(liveness 台账 verdict 确认 → ADR-0087 转换 → 墓碑 + 生成基线/表单/文档/pin 全套);RouteCoverageEntrySchema/RouteCoverageReportSchema 随同一 PR 按 liveness 读数处置(零构造者即同退);
  2. 前置一扫:退役前跑教材扫描 —— 除 flight ⑦ 已纠的那句外,还有哪些 published skill / 文档 / 示例在教 handlerStatus;非零则同笔清扫(教材曾教过不存在的 501 行为,是本卡的出处);
  3. enforce 排除:「声明未建的路由回 501」是零拉力的新能力,不是修复;
  4. 类方向入册(finding(spec): all six branded identifier schemas in branded-types.zod.ts are declared but unbound — no schema anywhere composes them #13612 / finding(spec): EventNameSchema's only three binding schemas have no runtime consumer — the live event vocabulary is a closed enum that never touches it #13613 引用用):ADR-0049 declared-but-unenforced 的默认处置 = retire(零拉力键);enforce/bind 只当有具名消费者或实测拉力。
  5. 条款②:YES(发布 accept 面收窄)⇒ draft + needs:contract-review 同笔,本席复审;changeset 按退役惯例。

Clause ② applies (the published accept set narrows): draft PR, needs:contract-review on both carriers, in-seat review. Item 4 is recorded here as the class direction for #13612 / #13613 — not ruled by this PR.

Premise re-measured on origin/main (a9b2be0, 2026-09-02)

Identifier search for handlerStatus, skills/** and tests excluded — three hits, all in the declaring file:

sitewhat
packages/spec/src/api/plugin-rest-api.zod.ts:177the declaration on RestApiEndpointSchema (HandlerStatusSchema.optional())
packages/spec/src/api/plugin-rest-api.zod.ts:1415the same enum re-declared on RouteCoverageEntrySchema
packages/spec/src/api/plugin-rest-api.zod.ts:1431the docblock saying adapters SHOULD warn when handlerStatus !== 'implemented'

Plus CHANGELOG.md:1502 (history) and generated artifacts. DispatcherErrorCode.enum.NOT_IMPLEMENTED emitters, none consulting the key: packages/runtime/src/endpoint-executor.ts:320,505,517, packages/runtime/src/api-mapping.ts:225, and one more than the card counted — packages/runtime/src/api-endpoint-step.ts:343 — every one the declarative-endpoint executor refusing a target or mapping it cannot serve. RouteCoverageEntrySchema / RouteCoverageReportSchema constructors: zero in objectstack (only the type-alias pin and generated artifacts reference them), zero in objectui at the pinned sha d8ec8d6d, zero in cloud. RestApiEndpointSchema itself is parsed by nothing in the tree outside its own unit tests. Premise still valid; no consumer has appeared.

Teaching sweep (before retiring)

pathhitaction
content/docs/references/api/plugin-rest-api.mdx:200,375,408,424,442generated reference rows for handlerStatus / the coverage shapesAUTO-GEN — regenerated by gen:docs (tombstone row now reads [REMOVED] …; coverage sections gone)
content/docs/references/index.mdx:90generated export list naming HandlerStatus, RouteCoverageEntry, RouteCoverageReportAUTO-GEN — regenerated
content/docs/** hand-written treesno hit for handlerStatus; the 501 prose at api/index.mdx:161,171, kernel/services-checklist.mdx:193, permissions/authentication.mdx:1243,1281 describes the service-slot / discovery status 501, not this keynot the false claim — no action
examples/**, packages/*/README.md, packages/create-objectstack/**zero hitsnone
skills/objectstack-api/SKILL.md (at this PR's base a9b2be0: :136handlerStatus: 'implemented', inside the os:check-marked RestApiEndpointSchema.parse({...}) example; :380 the 501 NOT_IMPLEMENTED — Route declared but handler is a stub table row; :383-391 the "Handler Status" section; :393-395 flight ⑦'s PR #13808 correction)four teaching sites at the base⛔ governed surface, not edited. None on main: bae4088f3 (#14448, 08:27Z today) cut every one — git grep -n -i -E 'handlerStatus|handler status|RouteCoverage|HandlerStatus' origin/main -- skills/ returns zero hits at 99b8faf8f, with RestApiEndpoint still hitting the skill as the live control — so no skills-lane follow-up is needed. (check:skill-examples was measured green against the base's marked block too: parse takes unknown, so the tombstone's never input type never reached it.)

Retirement steps (spec-property-retirement playbook)

  • Route.RestApiEndpointSchema is a non-strict lazySchema(() => z.object(...))retiredKey() tombstone for the key (packages/spec/src/api/plugin-rest-api.zod.ts:208-217), prescription hoisted as HANDLER_STATUS_RETIRED (:131-138) under the retirement record (:91-130). RouteCoverageEntrySchema / RouteCoverageReportSchema ⇒ whole-def removal, route 3 (nobody parses or constructs one), recorded at the file tail (:1439-1453). HandlerStatusSchema / HandlerStatus ⇒ orphan value def once both carriers are gone (refactor(spec)!: remove the plugin sandboxing / integrity / approval config that never existed (#3896 follow-up) #3950, the ui/ThemeMode precedent) — removed with them.
  • Liveness ledger. Verdict dead, confirmed by the re-measure above. No ledger row moves: RestApiEndpointSchema is outside the walked population — it is not a registered metadata type and not in SPEC_ONLY_SCHEMAS (packages/spec/scripts/liveness/check-liveness.mts:328) — so there is no row to write and adding one would be an ORPHAN. The verdict is recorded in the schema comment, the D3 entry and the changeset.
  • ADR-0087. Tail-appended entries, registry.ts regenerated by gen:migration-registry: entries/retired-keys/18.api__RestApiEndpoint__handlerStatus.ts; entries/retired-defs/18.api__HandlerStatus.ts, 18.api__RouteCoverageEntry.ts, 18.api__RouteCoverageReport.ts; entries/semantic/18.rest-api-endpoint-handler-status-retired.ts. No D2 conversion, deliberately — a REST API plugin route registration is not a stack collection member and never a sys_metadata row, so a MetadataConversion would be a transform with no seam that ever runs (the kernel/Manifest:loading / kernel/KernelContext:previewMode disposition); for the same reason the tombstone carries no os migrate meta sentence. Registered under 18 (launch-window convention). spec-changes.json and the upgrade guide are unchanged because both project majors up to PROTOCOL_MAJOR (17) only — the same as every 18-registered precedent.
  • Generated baselines.json-schema.manifest/api.json −3 keys (deleted deliberately; the json-schema.manifest.json 的「deliberate removal」删行仍是纪律而非门禁 —— #4650 的同类洞,上移一层(整 schema 级) #4725 manifest deletion gate adjudicated all three against RETIRED_DEFS_BY_MAJOR[18]); authorable-surface/api.json −10 rows for the two defs (route 3, check (c) proof) and api/RestApiEndpoint:handlerStatus… [RETIRED]; api-surface/api.json, export-origins/api.json, declaration-map/api.json −6 names each; content/docs/references/** and the strictness-ledger counts regenerated by check:generated --fix. authorable-surface.base.json lags (allowed; check:authorable-surface green).
  • Forms / i18n. No *.form.ts offers the key; no bundle changes.
  • Pin tests.packages/spec/src/api/plugin-rest-api.handler-status-retirement.test.ts: all three former values (including the documented default 'implemented' — prose only, never a Zod .default(), so no residue window) refused with code: 'invalid_type', path: ['handlerStatus'] and the prescription text (ADR named, no issue id); the same refusal through the route-registration embed at ['endpoints', 0, 'handlerStatus']; positive control — a well-formed endpoint without the key parses and grows no handlerStatus property; the eight shipped default route registrations still parse; a tsc-channel pin (@ts-expect-error, file proven in the tsconfig.test.json program via --listFiles); zero holders for all six retired names on every public entry with the carriers surviving; RETIRED_KEYS_BY_MAJOR[18] / RETIRED_DEFS_BY_MAJOR[18] / step-18 semantic membership. type-alias-convention.pin.test.ts: pins Iso123 / Iso125 / Iso126 left with their schemas, count rebalanced 835 → 832 with the file's history note.
  • Changeset..changeset/rest-api-endpoint-handler-status-retired.md@objectstack/spec minor, BREAKING under the launch-window convention, FROM → TO + one-line fix, ADR-0087 marker registered rest-api-endpoint-handler-status-retired (check:adr-0087-registration green).
  • Enforce excluded. No 501 stub mounting, no registrar change.

Verification

Every heavy step ran under scripts/pm/os-verify-lock.sh (OS_VERIFY_LOCK_SLOT=issue-13823); every exit captured before any pipe; the gates' own verdict lines quoted.

Final head 875e3fa5e (chain 4): pnpm --filter @objectstack/spec build exit 0 (gen:schema: "3 schema(s) left the published set since a9b2be0, each declared (#4725)" and "2 baseline deletion(s) since a9b2be0 carry their own proof (#4650)"; check-dts-emitted: 34/34); check:generated (check-only) exit 0 — "✓ All 15 generated artifacts are up to date."; targeted vitest via exec vitest run --maxWorkers=2 FILES (type-alias-convention.pin, plugin-rest-api.handler-status-retirement, plugin-rest-api, retired-key-migrate-sentence, migrations) — "Test Files 5 passed (5)" / "Tests 172 passed (172)"; check:skill-examples exit 0 — "✅ 265 prose examples type-check across 3 surface(s)" (the @objectstack/client-react closure was built for it); check:adr-0087-registration exit 0 — "1 declared-breaking changeset(s), each carrying an ADR-0087 disposition"; check:empty-changeset, check-changeset-no-major, check:nul-bytes, check:doc-authoring, check:spec-parsed-alias all exit 0; git status --porcelain empty after the build (the authorable-surface.base.json anchor was not rewritten — it lags, allowed).

7cbf0ed60 (chain 3, the pin-literal fix): targeted vitest 5 files / 172 tests passed; check:test-typecheck exit 0; check:spec-parsed-alias / check:doc-authoring / check:nul-bytes exit 0; check:api-surface refused to judge ("dist/**/*.d.ts is OLDER than packages/spec/src" — the test-file edit post-dated the build; not a measurement, settled by the rebuild above).

90d567cd3 (chain 2, the full union): pnpm --filter @objectstack/spec typecheck exit 0 (tsc, the scripts tsconfig, and "check:test-typecheck: OK — 54 file(s) / 262 error(s) / 146 pinned signature(s)", ledger unchanged, so the new test file compiles clean; its membership in the tsconfig.test.json program proven with tsc --listFiles); full spec vitest--maxWorkers=2: "Test Files 1 failed | 451 passed (452)" / "Tests 1 failed | 12190 passed (12191)" — the single failure was still declares all 832 isomorphic pins (the toHaveLength literal still 835; the same red CI reported on Test Core 2/6), fixed in 7cbf0ed60 and green in chains 3 and 4; check:skill-examples exit 0; check:exported-any, check:dual-source-exports, check:entry-nameability, check:browser-reachable-entries exit 0; check:generated exit 0 (15/15); check:doc-authoring / check:nul-bytes / check:adr-0087-registration / check:spec-parsed-alias exit 0; check-dev-prereqs exit 1 = "The workspace is not built — 32 of 67 workspace packages declare an entry point under dist/ that is not on disk" (a pnpm dev precondition on apps and services, unrelated to this diff — NOT MEASURED, not red).

Earlier on the same tree (before the docs-only, test-literal and changeset-prose commits): check:variant-docs, check:empty-state, check:llms-txt, check:yaml-examples, check:template-manifests, check:error-code-provenance, check:objectui-pin-citations, check:quick-reference-counts, check:corpus-claim-drift, check:skill-identifier-liveness, check:doc-anchors, check:docs-single-h1, check:docs-audit-scope, check:test-source-alias, check:cross-package-test-inputs, check:published-files, check:type-check-coverage, check:migration-registry and check:liveness (both inside check:generated), and the root check-doc-frontmatter / check-docs-section-name / check-doc-route-spelling / check-section-landing-index / check-keyed-text-bounds / check-ci-filter-parity / check-comment-mask-adoption / check-shard-attestation / check-system-context-census / check-undeclared-dep-imports / check-plugin-teardown-shape / docs-audit/check-affected-docs / docs-audit/check-drift-comment / pm/check-half-states scripts — all exit 0. Earlier reds that this PR fixed before landing: check:doc-authoring (the tombstone string carried #13823; now cites ADR-0049 only, with a negative pin) and the pin-count test above.

Declared narrowing: the full 452-file spec suite ran on 90d567cd3; the two later commits change one assertion literal in a test file and changeset prose, re-verified with the targeted files rather than the whole suite (≈6 min held under a contended lock) — CI's Test Core runs the full suite on the final head. Gate list derived with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths; 74 commands at b862317); what was not run is the CI-owned farm named below. CI on 875e3fa at report time: 31 check-runs — completed/skipped: 2, completed/success: 14, in_progress/None: 15.

Not measured here (CI-owned)

  • check:type-check-coverage --re-measure / check:type-check-debt (needs the whole package closure built — PREREQUISITE NOT MET, exit 3, not a finding), check:test-completeness (grades CI's turbo test log), check:react-declaration-parity (needs objectui's manifest), the repo-wide pnpm lint and the rest of the 74-command derivation not named above.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21


Generated by Claude Code

os-zhuangand others added 4 commits September 2, 2026 09:10
…ge Report shapes (#13823)
WIP: tombstone, three whole-def removals, ADR-0087 registrations (key, defs,
D3 semantic entry), pin tests and changeset. Generated artifacts follow in
the next commit.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
…age retirement (#13823)
json-schema.manifest and authorable-surface rows for the three whole-def
removals deleted deliberately (route 3 — the #4725 manifest deletion gate
and check (c) adjudicated them against RETIRED_DEFS_BY_MAJOR[18]); the
tombstone row carries [RETIRED]; api-surface / export-origins /
declaration-map lose the six retired names; the reference page and the
strictness-ledger counts regenerate.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
…ic pin count rebalanced 835 -> 832 (#13823)
check:doc-authoring refuses an issue id in customer-facing spec text — the
prescription now cites ADR-0049 only (the id stays in the adjacent comment),
with a negative pin. The type-alias pin count drops by the three pins whose
schemas left the module, recorded in the file's own history block.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

14 anchor(s) derived from 1 changed package(s); no hand-written page names any of them. ⚠️9 changed file(s) yielded no anchor (packages/spec/api-surface/api.json, packages/spec/authorable-surface/api.json, packages/spec/declaration-map/api.json, …), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

What this run could not see
  • 9 changed file(s) yielded no anchor (packages/spec/api-surface/api.json, packages/spec/authorable-surface/api.json, packages/spec/declaration-map/api.json, …) — pages documenting those are invisible to this run
  • 10 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 — 128 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 99b8faf8f937d8d2992f1bf167e418687c5f2f71packageMentionDocs.

Which tree this was computed on

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

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

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests tooling labels Sep 2, 2026
@claude

claudeBot commented Sep 2, 2026

Copy link
Copy Markdown
ContributorAuthor

CI red on head 90d567cd — this PR's own; patch round requested from the dispatched dev. (domain:spec seat, session session_01GDA48PuRFrHyRfdkBz8m21, seat post #6017.)

  • Failing check: Test Core (2/6)packages/spec/src/type-alias-convention.pin.test.ts > "still declares all 832 isomorphic pins": expected [ Array(832) ] to have a length of 835 but got 832 at line 2093.
  • Cause: the diff updated the case title, the section header and added the 835 -> 832 receipt prose, but the assertion literal expect(pins).toHaveLength(835) directly under the receipt still reads 835. One-literal fix (835 -> 832); every other file in that shard passed (450 passed / 1 failed).
  • Not a base failure: the same case is green on origin/main at 835 pins; the count moved because this PR removed Iso123 / Iso125 / Iso126 with the retired defs, which is the intended shape.
  • Action: the dev is fixing the literal on this branch as a new commit (no history rewrite), re-running the spec test locally, then pushing. Contract review resumes on the pushed head; the landing gate stays "every check on the current head green".

Generated by Claude Code

os-zhuangand others added 2 commits September 2, 2026 10:32
…eipt to 832 (#13823)
Title, header and receipt already said 832; the toHaveLength literal under
the receipt still read 835 (Test Core 2/6 on the PR head, and the local
full run: 1 failed / 12190 passed).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
…e base (#13823)
The published skill taught handlerStatus at this PR's base; main dropped that
teaching in the #14448 optimization flight (bae4088), so the changeset —
release-notes input — no longer claims an outstanding skills limb.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/lteststooling

Projects

None yet

1 participant

@os-zhuang
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(spec): retire RestApiEndpoint.handlerStatus and the Route Coverage Report shapes (#13823) - #14531

Merged
os-zhuang merged 6 commits into
mainfrom
claude/issue-13823-retire-handler-status
Sep 2, 2026
Merged

feat(spec): retire RestApiEndpoint.handlerStatus and the Route Coverage Report shapes (#13823)#14531
os-zhuang merged 6 commits into
mainfrom
claude/issue-13823-retire-handler-status

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#13823

Ruling implemented

Director decision batch #27, maintainer 2026-09-01 verbatim 「同意」 (issue comment 5494755488), implemented exactly:

  1. remove:RestApiEndpointSchema.handlerStatusspec-property-retirement 手册退役(liveness 台账 verdict 确认 → ADR-0087 转换 → 墓碑 + 生成基线/表单/文档/pin 全套);RouteCoverageEntrySchema/RouteCoverageReportSchema 随同一 PR 按 liveness 读数处置(零构造者即同退);
  2. 前置一扫:退役前跑教材扫描 —— 除 flight ⑦ 已纠的那句外,还有哪些 published skill / 文档 / 示例在教 handlerStatus;非零则同笔清扫(教材曾教过不存在的 501 行为,是本卡的出处);
  3. enforce 排除:「声明未建的路由回 501」是零拉力的新能力,不是修复;
  4. 类方向入册(finding(spec): all six branded identifier schemas in branded-types.zod.ts are declared but unbound — no schema anywhere composes them #13612 / finding(spec): EventNameSchema's only three binding schemas have no runtime consumer — the live event vocabulary is a closed enum that never touches it #13613 引用用):ADR-0049 declared-but-unenforced 的默认处置 = retire(零拉力键);enforce/bind 只当有具名消费者或实测拉力。
  5. 条款②:YES(发布 accept 面收窄)⇒ draft + needs:contract-review 同笔,本席复审;changeset 按退役惯例。

Clause ② applies (the published accept set narrows): draft PR, needs:contract-review on both carriers, in-seat review. Item 4 is recorded here as the class direction for #13612 / #13613 — not ruled by this PR.

Premise re-measured on origin/main (a9b2be0, 2026-09-02)

Identifier search for handlerStatus, skills/** and tests excluded — three hits, all in the declaring file:

sitewhat
packages/spec/src/api/plugin-rest-api.zod.ts:177the declaration on RestApiEndpointSchema (HandlerStatusSchema.optional())
packages/spec/src/api/plugin-rest-api.zod.ts:1415the same enum re-declared on RouteCoverageEntrySchema
packages/spec/src/api/plugin-rest-api.zod.ts:1431the docblock saying adapters SHOULD warn when handlerStatus !== 'implemented'

Plus CHANGELOG.md:1502 (history) and generated artifacts. DispatcherErrorCode.enum.NOT_IMPLEMENTED emitters, none consulting the key: packages/runtime/src/endpoint-executor.ts:320,505,517, packages/runtime/src/api-mapping.ts:225, and one more than the card counted — packages/runtime/src/api-endpoint-step.ts:343 — every one the declarative-endpoint executor refusing a target or mapping it cannot serve. RouteCoverageEntrySchema / RouteCoverageReportSchema constructors: zero in objectstack (only the type-alias pin and generated artifacts reference them), zero in objectui at the pinned sha d8ec8d6d, zero in cloud. RestApiEndpointSchema itself is parsed by nothing in the tree outside its own unit tests. Premise still valid; no consumer has appeared.

Teaching sweep (before retiring)

pathhitaction
content/docs/references/api/plugin-rest-api.mdx:200,375,408,424,442generated reference rows for handlerStatus / the coverage shapesAUTO-GEN — regenerated by gen:docs (tombstone row now reads [REMOVED] …; coverage sections gone)
content/docs/references/index.mdx:90generated export list naming HandlerStatus, RouteCoverageEntry, RouteCoverageReportAUTO-GEN — regenerated
content/docs/** hand-written treesno hit for handlerStatus; the 501 prose at api/index.mdx:161,171, kernel/services-checklist.mdx:193, permissions/authentication.mdx:1243,1281 describes the service-slot / discovery status 501, not this keynot the false claim — no action
examples/**, packages/*/README.md, packages/create-objectstack/**zero hitsnone
skills/objectstack-api/SKILL.md (at this PR's base a9b2be0: :136handlerStatus: 'implemented', inside the os:check-marked RestApiEndpointSchema.parse({...}) example; :380 the 501 NOT_IMPLEMENTED — Route declared but handler is a stub table row; :383-391 the "Handler Status" section; :393-395 flight ⑦'s PR #13808 correction)four teaching sites at the base⛔ governed surface, not edited. None on main: bae4088f3 (#14448, 08:27Z today) cut every one — git grep -n -i -E 'handlerStatus|handler status|RouteCoverage|HandlerStatus' origin/main -- skills/ returns zero hits at 99b8faf8f, with RestApiEndpoint still hitting the skill as the live control — so no skills-lane follow-up is needed. (check:skill-examples was measured green against the base's marked block too: parse takes unknown, so the tombstone's never input type never reached it.)

Retirement steps (spec-property-retirement playbook)

  • Route.RestApiEndpointSchema is a non-strict lazySchema(() => z.object(...))retiredKey() tombstone for the key (packages/spec/src/api/plugin-rest-api.zod.ts:208-217), prescription hoisted as HANDLER_STATUS_RETIRED (:131-138) under the retirement record (:91-130). RouteCoverageEntrySchema / RouteCoverageReportSchema ⇒ whole-def removal, route 3 (nobody parses or constructs one), recorded at the file tail (:1439-1453). HandlerStatusSchema / HandlerStatus ⇒ orphan value def once both carriers are gone (refactor(spec)!: remove the plugin sandboxing / integrity / approval config that never existed (#3896 follow-up) #3950, the ui/ThemeMode precedent) — removed with them.
  • Liveness ledger. Verdict dead, confirmed by the re-measure above. No ledger row moves: RestApiEndpointSchema is outside the walked population — it is not a registered metadata type and not in SPEC_ONLY_SCHEMAS (packages/spec/scripts/liveness/check-liveness.mts:328) — so there is no row to write and adding one would be an ORPHAN. The verdict is recorded in the schema comment, the D3 entry and the changeset.
  • ADR-0087. Tail-appended entries, registry.ts regenerated by gen:migration-registry: entries/retired-keys/18.api__RestApiEndpoint__handlerStatus.ts; entries/retired-defs/18.api__HandlerStatus.ts, 18.api__RouteCoverageEntry.ts, 18.api__RouteCoverageReport.ts; entries/semantic/18.rest-api-endpoint-handler-status-retired.ts. No D2 conversion, deliberately — a REST API plugin route registration is not a stack collection member and never a sys_metadata row, so a MetadataConversion would be a transform with no seam that ever runs (the kernel/Manifest:loading / kernel/KernelContext:previewMode disposition); for the same reason the tombstone carries no os migrate meta sentence. Registered under 18 (launch-window convention). spec-changes.json and the upgrade guide are unchanged because both project majors up to PROTOCOL_MAJOR (17) only — the same as every 18-registered precedent.
  • Generated baselines.json-schema.manifest/api.json −3 keys (deleted deliberately; the json-schema.manifest.json 的「deliberate removal」删行仍是纪律而非门禁 —— #4650 的同类洞,上移一层(整 schema 级) #4725 manifest deletion gate adjudicated all three against RETIRED_DEFS_BY_MAJOR[18]); authorable-surface/api.json −10 rows for the two defs (route 3, check (c) proof) and api/RestApiEndpoint:handlerStatus… [RETIRED]; api-surface/api.json, export-origins/api.json, declaration-map/api.json −6 names each; content/docs/references/** and the strictness-ledger counts regenerated by check:generated --fix. authorable-surface.base.json lags (allowed; check:authorable-surface green).
  • Forms / i18n. No *.form.ts offers the key; no bundle changes.
  • Pin tests.packages/spec/src/api/plugin-rest-api.handler-status-retirement.test.ts: all three former values (including the documented default 'implemented' — prose only, never a Zod .default(), so no residue window) refused with code: 'invalid_type', path: ['handlerStatus'] and the prescription text (ADR named, no issue id); the same refusal through the route-registration embed at ['endpoints', 0, 'handlerStatus']; positive control — a well-formed endpoint without the key parses and grows no handlerStatus property; the eight shipped default route registrations still parse; a tsc-channel pin (@ts-expect-error, file proven in the tsconfig.test.json program via --listFiles); zero holders for all six retired names on every public entry with the carriers surviving; RETIRED_KEYS_BY_MAJOR[18] / RETIRED_DEFS_BY_MAJOR[18] / step-18 semantic membership. type-alias-convention.pin.test.ts: pins Iso123 / Iso125 / Iso126 left with their schemas, count rebalanced 835 → 832 with the file's history note.
  • Changeset..changeset/rest-api-endpoint-handler-status-retired.md@objectstack/spec minor, BREAKING under the launch-window convention, FROM → TO + one-line fix, ADR-0087 marker registered rest-api-endpoint-handler-status-retired (check:adr-0087-registration green).
  • Enforce excluded. No 501 stub mounting, no registrar change.

Verification

Every heavy step ran under scripts/pm/os-verify-lock.sh (OS_VERIFY_LOCK_SLOT=issue-13823); every exit captured before any pipe; the gates' own verdict lines quoted.

Final head 875e3fa5e (chain 4): pnpm --filter @objectstack/spec build exit 0 (gen:schema: "3 schema(s) left the published set since a9b2be0, each declared (#4725)" and "2 baseline deletion(s) since a9b2be0 carry their own proof (#4650)"; check-dts-emitted: 34/34); check:generated (check-only) exit 0 — "✓ All 15 generated artifacts are up to date."; targeted vitest via exec vitest run --maxWorkers=2 FILES (type-alias-convention.pin, plugin-rest-api.handler-status-retirement, plugin-rest-api, retired-key-migrate-sentence, migrations) — "Test Files 5 passed (5)" / "Tests 172 passed (172)"; check:skill-examples exit 0 — "✅ 265 prose examples type-check across 3 surface(s)" (the @objectstack/client-react closure was built for it); check:adr-0087-registration exit 0 — "1 declared-breaking changeset(s), each carrying an ADR-0087 disposition"; check:empty-changeset, check-changeset-no-major, check:nul-bytes, check:doc-authoring, check:spec-parsed-alias all exit 0; git status --porcelain empty after the build (the authorable-surface.base.json anchor was not rewritten — it lags, allowed).

7cbf0ed60 (chain 3, the pin-literal fix): targeted vitest 5 files / 172 tests passed; check:test-typecheck exit 0; check:spec-parsed-alias / check:doc-authoring / check:nul-bytes exit 0; check:api-surface refused to judge ("dist/**/*.d.ts is OLDER than packages/spec/src" — the test-file edit post-dated the build; not a measurement, settled by the rebuild above).

90d567cd3 (chain 2, the full union): pnpm --filter @objectstack/spec typecheck exit 0 (tsc, the scripts tsconfig, and "check:test-typecheck: OK — 54 file(s) / 262 error(s) / 146 pinned signature(s)", ledger unchanged, so the new test file compiles clean; its membership in the tsconfig.test.json program proven with tsc --listFiles); full spec vitest--maxWorkers=2: "Test Files 1 failed | 451 passed (452)" / "Tests 1 failed | 12190 passed (12191)" — the single failure was still declares all 832 isomorphic pins (the toHaveLength literal still 835; the same red CI reported on Test Core 2/6), fixed in 7cbf0ed60 and green in chains 3 and 4; check:skill-examples exit 0; check:exported-any, check:dual-source-exports, check:entry-nameability, check:browser-reachable-entries exit 0; check:generated exit 0 (15/15); check:doc-authoring / check:nul-bytes / check:adr-0087-registration / check:spec-parsed-alias exit 0; check-dev-prereqs exit 1 = "The workspace is not built — 32 of 67 workspace packages declare an entry point under dist/ that is not on disk" (a pnpm dev precondition on apps and services, unrelated to this diff — NOT MEASURED, not red).

Earlier on the same tree (before the docs-only, test-literal and changeset-prose commits): check:variant-docs, check:empty-state, check:llms-txt, check:yaml-examples, check:template-manifests, check:error-code-provenance, check:objectui-pin-citations, check:quick-reference-counts, check:corpus-claim-drift, check:skill-identifier-liveness, check:doc-anchors, check:docs-single-h1, check:docs-audit-scope, check:test-source-alias, check:cross-package-test-inputs, check:published-files, check:type-check-coverage, check:migration-registry and check:liveness (both inside check:generated), and the root check-doc-frontmatter / check-docs-section-name / check-doc-route-spelling / check-section-landing-index / check-keyed-text-bounds / check-ci-filter-parity / check-comment-mask-adoption / check-shard-attestation / check-system-context-census / check-undeclared-dep-imports / check-plugin-teardown-shape / docs-audit/check-affected-docs / docs-audit/check-drift-comment / pm/check-half-states scripts — all exit 0. Earlier reds that this PR fixed before landing: check:doc-authoring (the tombstone string carried #13823; now cites ADR-0049 only, with a negative pin) and the pin-count test above.

Declared narrowing: the full 452-file spec suite ran on 90d567cd3; the two later commits change one assertion literal in a test file and changeset prose, re-verified with the targeted files rather than the whole suite (≈6 min held under a contended lock) — CI's Test Core runs the full suite on the final head. Gate list derived with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths; 74 commands at b862317); what was not run is the CI-owned farm named below. CI on 875e3fa at report time: 31 check-runs — completed/skipped: 2, completed/success: 14, in_progress/None: 15.

Not measured here (CI-owned)

  • check:type-check-coverage --re-measure / check:type-check-debt (needs the whole package closure built — PREREQUISITE NOT MET, exit 3, not a finding), check:test-completeness (grades CI's turbo test log), check:react-declaration-parity (needs objectui's manifest), the repo-wide pnpm lint and the rest of the 74-command derivation not named above.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21


Generated by Claude Code

os-zhuangand others added 4 commits September 2, 2026 09:10
…ge Report shapes (#13823)
WIP: tombstone, three whole-def removals, ADR-0087 registrations (key, defs,
D3 semantic entry), pin tests and changeset. Generated artifacts follow in
the next commit.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
…age retirement (#13823)
json-schema.manifest and authorable-surface rows for the three whole-def
removals deleted deliberately (route 3 — the #4725 manifest deletion gate
and check (c) adjudicated them against RETIRED_DEFS_BY_MAJOR[18]); the
tombstone row carries [RETIRED]; api-surface / export-origins /
declaration-map lose the six retired names; the reference page and the
strictness-ledger counts regenerate.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
…ic pin count rebalanced 835 -> 832 (#13823)
check:doc-authoring refuses an issue id in customer-facing spec text — the
prescription now cites ADR-0049 only (the id stays in the adjacent comment),
with a negative pin. The type-alias pin count drops by the three pins whose
schemas left the module, recorded in the file's own history block.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

14 anchor(s) derived from 1 changed package(s); no hand-written page names any of them. ⚠️9 changed file(s) yielded no anchor (packages/spec/api-surface/api.json, packages/spec/authorable-surface/api.json, packages/spec/declaration-map/api.json, …), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

What this run could not see
  • 9 changed file(s) yielded no anchor (packages/spec/api-surface/api.json, packages/spec/authorable-surface/api.json, packages/spec/declaration-map/api.json, …) — pages documenting those are invisible to this run
  • 10 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 — 128 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 99b8faf8f937d8d2992f1bf167e418687c5f2f71packageMentionDocs.

Which tree this was computed on

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

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

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests tooling labels Sep 2, 2026
@claude

claudeBot commented Sep 2, 2026

Copy link
Copy Markdown
ContributorAuthor

CI red on head 90d567cd — this PR's own; patch round requested from the dispatched dev. (domain:spec seat, session session_01GDA48PuRFrHyRfdkBz8m21, seat post #6017.)

  • Failing check: Test Core (2/6)packages/spec/src/type-alias-convention.pin.test.ts > "still declares all 832 isomorphic pins": expected [ Array(832) ] to have a length of 835 but got 832 at line 2093.
  • Cause: the diff updated the case title, the section header and added the 835 -> 832 receipt prose, but the assertion literal expect(pins).toHaveLength(835) directly under the receipt still reads 835. One-literal fix (835 -> 832); every other file in that shard passed (450 passed / 1 failed).
  • Not a base failure: the same case is green on origin/main at 835 pins; the count moved because this PR removed Iso123 / Iso125 / Iso126 with the retired defs, which is the intended shape.
  • Action: the dev is fixing the literal on this branch as a new commit (no history rewrite), re-running the spec test locally, then pushing. Contract review resumes on the pushed head; the landing gate stays "every check on the current head green".

Generated by Claude Code

os-zhuangand others added 2 commits September 2, 2026 10:32
…eipt to 832 (#13823)
Title, header and receipt already said 832; the toHaveLength literal under
the receipt still read 835 (Test Core 2/6 on the PR head, and the local
full run: 1 failed / 12190 passed).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
…e base (#13823)
The published skill taught handlerStatus at this PR's base; main dropped that
teaching in the #14448 optimization flight (bae4088), so the changeset —
release-notes input — no longer claims an outstanding skills limb.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/lteststooling

Projects

None yet

1 participant

@os-zhuang
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat(spec): retire RestApiEndpoint.handlerStatus and the Route Coverage Report shapes (#13823) - #14531

Merged
os-zhuang merged 6 commits into
mainfrom
claude/issue-13823-retire-handler-status
Sep 2, 2026
Merged

feat(spec): retire RestApiEndpoint.handlerStatus and the Route Coverage Report shapes (#13823)#14531
os-zhuang merged 6 commits into
mainfrom
claude/issue-13823-retire-handler-status

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#13823

Ruling implemented

Director decision batch #27, maintainer 2026-09-01 verbatim 「同意」 (issue comment 5494755488), implemented exactly:

  1. remove:RestApiEndpointSchema.handlerStatusspec-property-retirement 手册退役(liveness 台账 verdict 确认 → ADR-0087 转换 → 墓碑 + 生成基线/表单/文档/pin 全套);RouteCoverageEntrySchema/RouteCoverageReportSchema 随同一 PR 按 liveness 读数处置(零构造者即同退);
  2. 前置一扫:退役前跑教材扫描 —— 除 flight ⑦ 已纠的那句外,还有哪些 published skill / 文档 / 示例在教 handlerStatus;非零则同笔清扫(教材曾教过不存在的 501 行为,是本卡的出处);
  3. enforce 排除:「声明未建的路由回 501」是零拉力的新能力,不是修复;
  4. 类方向入册(finding(spec): all six branded identifier schemas in branded-types.zod.ts are declared but unbound — no schema anywhere composes them #13612 / finding(spec): EventNameSchema's only three binding schemas have no runtime consumer — the live event vocabulary is a closed enum that never touches it #13613 引用用):ADR-0049 declared-but-unenforced 的默认处置 = retire(零拉力键);enforce/bind 只当有具名消费者或实测拉力。
  5. 条款②:YES(发布 accept 面收窄)⇒ draft + needs:contract-review 同笔,本席复审;changeset 按退役惯例。

Clause ② applies (the published accept set narrows): draft PR, needs:contract-review on both carriers, in-seat review. Item 4 is recorded here as the class direction for #13612 / #13613 — not ruled by this PR.

Premise re-measured on origin/main (a9b2be0, 2026-09-02)

Identifier search for handlerStatus, skills/** and tests excluded — three hits, all in the declaring file:

sitewhat
packages/spec/src/api/plugin-rest-api.zod.ts:177the declaration on RestApiEndpointSchema (HandlerStatusSchema.optional())
packages/spec/src/api/plugin-rest-api.zod.ts:1415the same enum re-declared on RouteCoverageEntrySchema
packages/spec/src/api/plugin-rest-api.zod.ts:1431the docblock saying adapters SHOULD warn when handlerStatus !== 'implemented'

Plus CHANGELOG.md:1502 (history) and generated artifacts. DispatcherErrorCode.enum.NOT_IMPLEMENTED emitters, none consulting the key: packages/runtime/src/endpoint-executor.ts:320,505,517, packages/runtime/src/api-mapping.ts:225, and one more than the card counted — packages/runtime/src/api-endpoint-step.ts:343 — every one the declarative-endpoint executor refusing a target or mapping it cannot serve. RouteCoverageEntrySchema / RouteCoverageReportSchema constructors: zero in objectstack (only the type-alias pin and generated artifacts reference them), zero in objectui at the pinned sha d8ec8d6d, zero in cloud. RestApiEndpointSchema itself is parsed by nothing in the tree outside its own unit tests. Premise still valid; no consumer has appeared.

Teaching sweep (before retiring)

pathhitaction
content/docs/references/api/plugin-rest-api.mdx:200,375,408,424,442generated reference rows for handlerStatus / the coverage shapesAUTO-GEN — regenerated by gen:docs (tombstone row now reads [REMOVED] …; coverage sections gone)
content/docs/references/index.mdx:90generated export list naming HandlerStatus, RouteCoverageEntry, RouteCoverageReportAUTO-GEN — regenerated
content/docs/** hand-written treesno hit for handlerStatus; the 501 prose at api/index.mdx:161,171, kernel/services-checklist.mdx:193, permissions/authentication.mdx:1243,1281 describes the service-slot / discovery status 501, not this keynot the false claim — no action
examples/**, packages/*/README.md, packages/create-objectstack/**zero hitsnone
skills/objectstack-api/SKILL.md (at this PR's base a9b2be0: :136handlerStatus: 'implemented', inside the os:check-marked RestApiEndpointSchema.parse({...}) example; :380 the 501 NOT_IMPLEMENTED — Route declared but handler is a stub table row; :383-391 the "Handler Status" section; :393-395 flight ⑦'s PR #13808 correction)four teaching sites at the base⛔ governed surface, not edited. None on main: bae4088f3 (#14448, 08:27Z today) cut every one — git grep -n -i -E 'handlerStatus|handler status|RouteCoverage|HandlerStatus' origin/main -- skills/ returns zero hits at 99b8faf8f, with RestApiEndpoint still hitting the skill as the live control — so no skills-lane follow-up is needed. (check:skill-examples was measured green against the base's marked block too: parse takes unknown, so the tombstone's never input type never reached it.)

Retirement steps (spec-property-retirement playbook)

  • Route.RestApiEndpointSchema is a non-strict lazySchema(() => z.object(...))retiredKey() tombstone for the key (packages/spec/src/api/plugin-rest-api.zod.ts:208-217), prescription hoisted as HANDLER_STATUS_RETIRED (:131-138) under the retirement record (:91-130). RouteCoverageEntrySchema / RouteCoverageReportSchema ⇒ whole-def removal, route 3 (nobody parses or constructs one), recorded at the file tail (:1439-1453). HandlerStatusSchema / HandlerStatus ⇒ orphan value def once both carriers are gone (refactor(spec)!: remove the plugin sandboxing / integrity / approval config that never existed (#3896 follow-up) #3950, the ui/ThemeMode precedent) — removed with them.
  • Liveness ledger. Verdict dead, confirmed by the re-measure above. No ledger row moves: RestApiEndpointSchema is outside the walked population — it is not a registered metadata type and not in SPEC_ONLY_SCHEMAS (packages/spec/scripts/liveness/check-liveness.mts:328) — so there is no row to write and adding one would be an ORPHAN. The verdict is recorded in the schema comment, the D3 entry and the changeset.
  • ADR-0087. Tail-appended entries, registry.ts regenerated by gen:migration-registry: entries/retired-keys/18.api__RestApiEndpoint__handlerStatus.ts; entries/retired-defs/18.api__HandlerStatus.ts, 18.api__RouteCoverageEntry.ts, 18.api__RouteCoverageReport.ts; entries/semantic/18.rest-api-endpoint-handler-status-retired.ts. No D2 conversion, deliberately — a REST API plugin route registration is not a stack collection member and never a sys_metadata row, so a MetadataConversion would be a transform with no seam that ever runs (the kernel/Manifest:loading / kernel/KernelContext:previewMode disposition); for the same reason the tombstone carries no os migrate meta sentence. Registered under 18 (launch-window convention). spec-changes.json and the upgrade guide are unchanged because both project majors up to PROTOCOL_MAJOR (17) only — the same as every 18-registered precedent.
  • Generated baselines.json-schema.manifest/api.json −3 keys (deleted deliberately; the json-schema.manifest.json 的「deliberate removal」删行仍是纪律而非门禁 —— #4650 的同类洞,上移一层(整 schema 级) #4725 manifest deletion gate adjudicated all three against RETIRED_DEFS_BY_MAJOR[18]); authorable-surface/api.json −10 rows for the two defs (route 3, check (c) proof) and api/RestApiEndpoint:handlerStatus… [RETIRED]; api-surface/api.json, export-origins/api.json, declaration-map/api.json −6 names each; content/docs/references/** and the strictness-ledger counts regenerated by check:generated --fix. authorable-surface.base.json lags (allowed; check:authorable-surface green).
  • Forms / i18n. No *.form.ts offers the key; no bundle changes.
  • Pin tests.packages/spec/src/api/plugin-rest-api.handler-status-retirement.test.ts: all three former values (including the documented default 'implemented' — prose only, never a Zod .default(), so no residue window) refused with code: 'invalid_type', path: ['handlerStatus'] and the prescription text (ADR named, no issue id); the same refusal through the route-registration embed at ['endpoints', 0, 'handlerStatus']; positive control — a well-formed endpoint without the key parses and grows no handlerStatus property; the eight shipped default route registrations still parse; a tsc-channel pin (@ts-expect-error, file proven in the tsconfig.test.json program via --listFiles); zero holders for all six retired names on every public entry with the carriers surviving; RETIRED_KEYS_BY_MAJOR[18] / RETIRED_DEFS_BY_MAJOR[18] / step-18 semantic membership. type-alias-convention.pin.test.ts: pins Iso123 / Iso125 / Iso126 left with their schemas, count rebalanced 835 → 832 with the file's history note.
  • Changeset..changeset/rest-api-endpoint-handler-status-retired.md@objectstack/spec minor, BREAKING under the launch-window convention, FROM → TO + one-line fix, ADR-0087 marker registered rest-api-endpoint-handler-status-retired (check:adr-0087-registration green).
  • Enforce excluded. No 501 stub mounting, no registrar change.

Verification

Every heavy step ran under scripts/pm/os-verify-lock.sh (OS_VERIFY_LOCK_SLOT=issue-13823); every exit captured before any pipe; the gates' own verdict lines quoted.

Final head 875e3fa5e (chain 4): pnpm --filter @objectstack/spec build exit 0 (gen:schema: "3 schema(s) left the published set since a9b2be0, each declared (#4725)" and "2 baseline deletion(s) since a9b2be0 carry their own proof (#4650)"; check-dts-emitted: 34/34); check:generated (check-only) exit 0 — "✓ All 15 generated artifacts are up to date."; targeted vitest via exec vitest run --maxWorkers=2 FILES (type-alias-convention.pin, plugin-rest-api.handler-status-retirement, plugin-rest-api, retired-key-migrate-sentence, migrations) — "Test Files 5 passed (5)" / "Tests 172 passed (172)"; check:skill-examples exit 0 — "✅ 265 prose examples type-check across 3 surface(s)" (the @objectstack/client-react closure was built for it); check:adr-0087-registration exit 0 — "1 declared-breaking changeset(s), each carrying an ADR-0087 disposition"; check:empty-changeset, check-changeset-no-major, check:nul-bytes, check:doc-authoring, check:spec-parsed-alias all exit 0; git status --porcelain empty after the build (the authorable-surface.base.json anchor was not rewritten — it lags, allowed).

7cbf0ed60 (chain 3, the pin-literal fix): targeted vitest 5 files / 172 tests passed; check:test-typecheck exit 0; check:spec-parsed-alias / check:doc-authoring / check:nul-bytes exit 0; check:api-surface refused to judge ("dist/**/*.d.ts is OLDER than packages/spec/src" — the test-file edit post-dated the build; not a measurement, settled by the rebuild above).

90d567cd3 (chain 2, the full union): pnpm --filter @objectstack/spec typecheck exit 0 (tsc, the scripts tsconfig, and "check:test-typecheck: OK — 54 file(s) / 262 error(s) / 146 pinned signature(s)", ledger unchanged, so the new test file compiles clean; its membership in the tsconfig.test.json program proven with tsc --listFiles); full spec vitest--maxWorkers=2: "Test Files 1 failed | 451 passed (452)" / "Tests 1 failed | 12190 passed (12191)" — the single failure was still declares all 832 isomorphic pins (the toHaveLength literal still 835; the same red CI reported on Test Core 2/6), fixed in 7cbf0ed60 and green in chains 3 and 4; check:skill-examples exit 0; check:exported-any, check:dual-source-exports, check:entry-nameability, check:browser-reachable-entries exit 0; check:generated exit 0 (15/15); check:doc-authoring / check:nul-bytes / check:adr-0087-registration / check:spec-parsed-alias exit 0; check-dev-prereqs exit 1 = "The workspace is not built — 32 of 67 workspace packages declare an entry point under dist/ that is not on disk" (a pnpm dev precondition on apps and services, unrelated to this diff — NOT MEASURED, not red).

Earlier on the same tree (before the docs-only, test-literal and changeset-prose commits): check:variant-docs, check:empty-state, check:llms-txt, check:yaml-examples, check:template-manifests, check:error-code-provenance, check:objectui-pin-citations, check:quick-reference-counts, check:corpus-claim-drift, check:skill-identifier-liveness, check:doc-anchors, check:docs-single-h1, check:docs-audit-scope, check:test-source-alias, check:cross-package-test-inputs, check:published-files, check:type-check-coverage, check:migration-registry and check:liveness (both inside check:generated), and the root check-doc-frontmatter / check-docs-section-name / check-doc-route-spelling / check-section-landing-index / check-keyed-text-bounds / check-ci-filter-parity / check-comment-mask-adoption / check-shard-attestation / check-system-context-census / check-undeclared-dep-imports / check-plugin-teardown-shape / docs-audit/check-affected-docs / docs-audit/check-drift-comment / pm/check-half-states scripts — all exit 0. Earlier reds that this PR fixed before landing: check:doc-authoring (the tombstone string carried #13823; now cites ADR-0049 only, with a negative pin) and the pin-count test above.

Declared narrowing: the full 452-file spec suite ran on 90d567cd3; the two later commits change one assertion literal in a test file and changeset prose, re-verified with the targeted files rather than the whole suite (≈6 min held under a contended lock) — CI's Test Core runs the full suite on the final head. Gate list derived with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths; 74 commands at b862317); what was not run is the CI-owned farm named below. CI on 875e3fa at report time: 31 check-runs — completed/skipped: 2, completed/success: 14, in_progress/None: 15.

Not measured here (CI-owned)

  • check:type-check-coverage --re-measure / check:type-check-debt (needs the whole package closure built — PREREQUISITE NOT MET, exit 3, not a finding), check:test-completeness (grades CI's turbo test log), check:react-declaration-parity (needs objectui's manifest), the repo-wide pnpm lint and the rest of the 74-command derivation not named above.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21


Generated by Claude Code

os-zhuangand others added 4 commits September 2, 2026 09:10
…ge Report shapes (#13823)
WIP: tombstone, three whole-def removals, ADR-0087 registrations (key, defs,
D3 semantic entry), pin tests and changeset. Generated artifacts follow in
the next commit.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
…age retirement (#13823)
json-schema.manifest and authorable-surface rows for the three whole-def
removals deleted deliberately (route 3 — the #4725 manifest deletion gate
and check (c) adjudicated them against RETIRED_DEFS_BY_MAJOR[18]); the
tombstone row carries [RETIRED]; api-surface / export-origins /
declaration-map lose the six retired names; the reference page and the
strictness-ledger counts regenerate.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
…ic pin count rebalanced 835 -> 832 (#13823)
check:doc-authoring refuses an issue id in customer-facing spec text — the
prescription now cites ADR-0049 only (the id stays in the adjacent comment),
with a negative pin. The type-alias pin count drops by the three pins whose
schemas left the module, recorded in the file's own history block.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

14 anchor(s) derived from 1 changed package(s); no hand-written page names any of them. ⚠️9 changed file(s) yielded no anchor (packages/spec/api-surface/api.json, packages/spec/authorable-surface/api.json, packages/spec/declaration-map/api.json, …), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

What this run could not see
  • 9 changed file(s) yielded no anchor (packages/spec/api-surface/api.json, packages/spec/authorable-surface/api.json, packages/spec/declaration-map/api.json, …) — pages documenting those are invisible to this run
  • 10 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 — 128 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 99b8faf8f937d8d2992f1bf167e418687c5f2f71packageMentionDocs.

Which tree this was computed on

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

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

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests tooling labels Sep 2, 2026
@claude

claudeBot commented Sep 2, 2026

Copy link
Copy Markdown
ContributorAuthor

CI red on head 90d567cd — this PR's own; patch round requested from the dispatched dev. (domain:spec seat, session session_01GDA48PuRFrHyRfdkBz8m21, seat post #6017.)

  • Failing check: Test Core (2/6)packages/spec/src/type-alias-convention.pin.test.ts > "still declares all 832 isomorphic pins": expected [ Array(832) ] to have a length of 835 but got 832 at line 2093.
  • Cause: the diff updated the case title, the section header and added the 835 -> 832 receipt prose, but the assertion literal expect(pins).toHaveLength(835) directly under the receipt still reads 835. One-literal fix (835 -> 832); every other file in that shard passed (450 passed / 1 failed).
  • Not a base failure: the same case is green on origin/main at 835 pins; the count moved because this PR removed Iso123 / Iso125 / Iso126 with the retired defs, which is the intended shape.
  • Action: the dev is fixing the literal on this branch as a new commit (no history rewrite), re-running the spec test locally, then pushing. Contract review resumes on the pushed head; the landing gate stays "every check on the current head green".

Generated by Claude Code

os-zhuangand others added 2 commits September 2, 2026 10:32
…eipt to 832 (#13823)
Title, header and receipt already said 832; the toHaveLength literal under
the receipt still read 835 (Test Core 2/6 on the PR head, and the local
full run: 1 failed / 12190 passed).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
…e base (#13823)
The published skill taught handlerStatus at this PR's base; main dropped that
teaching in the #14448 optimization flight (bae4088), so the changeset —
release-notes input — no longer claims an outstanding skills limb.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/lteststooling

Projects

None yet

1 participant

@os-zhuang