Skip to content

Retire the plugin manifest's three dead top-level containers: capabilities, configuration, extensions (ADR-0049) - #13287

Merged
hotlong merged 1 commit into
mainfrom
claude/issue-11332-manifest-container-retirement
Aug 30, 2026
Merged

Retire the plugin manifest's three dead top-level containers: capabilities, configuration, extensions (ADR-0049)#13287
hotlong merged 1 commit into
mainfrom
claude/issue-11332-manifest-container-retirement

Conversation

@claude

@claudeclaudeBot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Fixes#11332

ADR-0049 enforce-or-remove retirement of the plugin manifest's three dead top-level containers — capabilities, configuration, extensions — executed through the pre-registered triage disposition (2026-08-23, on the card) after the cloud leg came back clean (#12400 remains the evidence record: cloud main at commit 15f55df, all three containers CLEAN, controls positive). Family precedents mirrored, not reinvented: PR #12001 (nine contributes members) and the manifest.loading retirement.

Premise re-verification (dispatch-time, all three trees)

  • objectstack at base commit 7404925: containers still declared (configuration at manifest.zod.ts line 305, capabilities at 489, extensions at 496). Container-level probe over non-test, non-dist code: .configuration and .extensions return ZERO hits; all 40 .capabilities hits classify to other surfaces (hook/action body.capabilities, client discovery capabilities, driver loader contracts, the ADR-0066 stack-level capabilities collection, datasource-retirement machinery). Zero manifest-container reads.
  • objectui at 26896c6: zero container reads; positive control — manifest.(id|name|namespace|version) reads findable (19 in PackagesPage.tsx alone).
  • cloud at 15f55df (read-only checkout, same sha as the PM's [seam→cloud] Measure the cloud leg of the remaining plugin-manifest keys (runtime, integrity, capabilities/configuration/extensions, structured permissions) — unblocks #11330 #11331 #11332 #11333 #12400 measurement): zero container reads (body.capabilities there is the sandbox capability-token surface; app.configuration is Cloudflare rollout config); positive controls — 26 manifest field reads, sys_package_version writers present.
  • Not premise-breaking, by design: the two in-repo AUTHORS (driver-memory, plugin-hono-server — both writing configuration + capabilities blocks) are writers, not readers; both are cleaned in this PR, mirroring the hono-server precedent comment left by the contributes retirement.

Route: tombstone, not deletion — condition re-verified

ManifestSchema is a plain z.object (line 132); the only .strict() in the file belongs to PluginPermissionsSchema (line 44). A plain deletion would silently strip the keys, so each gets retiredKey() with a prescription following the five house conventions (fully-qualified key, removal record with the ADR id, why-inert clause, imperative fix; NO migrate-meta sentence because no conversion covers this surface — the contributes/loading precedent; no tracker ids in customer-facing prose per the standing check-doc-authoring rules).

configuration's prescription records the false promise honestly: properties.*.secret promised "value is encrypted/masked (e.g. API Keys)" while nothing encrypted, masked or even parsed the flag — the false-compliance shape ADR-0049 exists for.

Registration (ADR-0087)

  • RETIRED_KEYS_BY_MAJOR[18]: kernel/Manifest:capabilities, kernel/Manifest:configuration, kernel/Manifest:extensions — one entry file each under entries/retired-keys/, folded by gen:migration-registry.
  • One D3 semantic entry plugin-manifest-dead-containers-retired, mirroring the record shape of plugin-manifest-contributes-dead-members-retired.
  • Deliberately NO D2 conversion: re-verified that PLURAL_TO_SINGULAR still has no packages / plugins entry (its capabilities entry is the unrelated ADR-0066 stack collection), so a package manifest is not a stack collection member and a conversion would be a transform with no seam that ever runs — the kernel/Manifest:loading reasoning holds verbatim.
  • PluginCapabilityManifestSchema stays exported: plugin-registry.zod.ts line 205 still declares it, so this is a carrier-key tombstone with NO def removal (nothing lands in RETIRED_DEFS_BY_MAJOR; the orphan-schema clause does not apply).

Launch-window reconciliation (the #13186 precedent)

The changeset is minor with the adr-0087 registration marker: v17.0.0 was cut before this landed, so the accept-set narrowing ships on the 17.x line under the lockstep launch-window convention, while the prescriptions register under protocol major 18 where os migrate meta users will look. check-changeset-no-major (which refuses a major and is authoritative for the convention) passes on this diff.

Liveness ledger

The three rows move to the tombstone disposition (dead + RETIRED note, row STAYS because retiredKey() keeps the key in the walked shape — the loading precedent, per the ledger README's asymmetry note). The per-child rows (capabilities.{implements,provides,requires,extensionPoints,extensions}, configuration.{title,properties}) leave the ledger with the drilled shape; their provenance is folded into the container notes. Counts regenerated via gen:liveness-counts (manifest: dead 21 to 16, total 914 to 909 — arithmetic checks: 7 child rows out, 2 container rows in).

Author-facing surfaces

  • Generated: content/docs/references/** (three rows now render the REMOVED prescriptions), authorable-surface/kernel.json (three rows gain the RETIRED mark — key-level tombstone signature: no def rows move, matching the ratchet-visibility table), strictness-ledger counts, spec-changes/upgrade-guide gates green (major-18 content projects at the 18 cut, same as the family precedents).
  • Hand-written: content/docs/protocol/kernel/plugin-spec.mdx taught all three containers in its "what ManifestSchema actually declares" callout and pointed config defaults AT the secret flag; both corrected (the callout now lists the four retired tombstones, including loading, whose listing as an ordinary optional field was stale from the same sentence). No skills/** page teaches any of the three (measured: zero hits for the container spellings and extensionPoints); no ADR edits — so no landing-posture fork.
  • Examples: examples/app-showcasecapabilities: at config line 266 is the ADR-0066 stack-level collection inside defineStack — a different, live surface, untouched.

Verification

  • Full spec suite green post-change: 443 files, 11780 tests.
  • New pins (5) verified by name in a verbose run: three per-container rejections asserting the specific zod issue and its prescription content, absence-parses-clean, live-neighbours (dependencies, navigationContributions) still parse.
  • Reverse verification, from the committed state, direction pre-declared: reverting the capabilities tombstone to a plain declaration turned EXACTLY the capabilities rejection pin red (1 failed / 40 passed); mutation proven on disk by anchor grep (marker count 1, tombstone count 0), restoration proven by empty git diff HEAD afterward. In-package leg (spec tests import src directly), so no dist rebuild was part of this leg.
  • Cross-package type channel, against rebuilt dist declarations: a probe in packages/objectql authoring extensions on an ObjectStackManifest produced TS2322 (input typed never) via @objectstack/spec/kernel; probe removed. First probe attempt failed with TS2305 for an unrelated reason — that reading was discarded as not-measured and led to finding The two in-repo manifest authoring sites (driver-memory / plugin-hono-server objectstack.config.ts) sit outside every tsc program and import ObjectStackManifest from an entry that does not export it #13284 below.
  • Consumer sweep (downstream direction, importer-derived list): builds of the 62-package closure green; test suites green for objectql, metadata, metadata-protocol, client (36 turbo tasks), and for cli, runtime, service-package, service-settings, dogfood, driver-memory, plugin-hono-server, create-objectstack (70 turbo tasks, all successful).
  • Gate families derived by node scripts/pm/dispatch-gates.mjs (no hand-fed paths; derivation stderr names this repo at commit 9eda0f5) — all locally-owed members run green at 9eda0f5: nul-bytes, changeset-no-major, adr-0087-registration, empty-changeset, doc-authoring, docs-single-h1, doc-frontmatter, doc-anchors, doc-route-spelling, docs-section-name, affected-docs, drift-comment, quick-reference-counts, driver-memory-census, test-source-alias, spec-parsed-alias, and in packages/spec: liveness, empty-state, authorable-surface, docs, strictness-ledger, variant-docs, spec-changes, upgrade-guide, skill-examples (after building client-react — its dist is that gate's read prerequisite), plus check:generated fully reconciled. CI owns the full farm.

Landing posture

Clause-② YES (the accept set narrows: three previously-accepted containers become loud rejections). This PR parks at DRAFT with needs:contract-review attached at creation; the review chain owns enqueue. Not ready, not queued, not armed.

Out of scope, filed separately with evidence: #13284 (the two in-repo manifest authoring sites sit outside every tsc program and import ObjectStackManifest from an entry that does not export it — the tombstone's tsc channel is blind exactly there; found by this PR's reverse verification) and #13285 (plugin-registry.zod.ts has zero consumers outside packages/spec and is now the sole surface publishing PluginCapabilityManifestSchema — census requested; finding label). #13284 and #13285 remain open; nothing in this PR addresses them.

Generated by Claude Code


Generated by Claude Code

…ners (capabilities, configuration, extensions)
ADR-0049 enforce-or-remove. Zero reads of each container itself measured
across objectstack, objectui and cloud with positive controls; the census
settles all eight keys beneath them at once. configuration.properties.secret
promised encryption/masking that nothing implemented — the false-compliance
shape. retiredKey() tombstones (ManifestSchema is not .strict(), so a plain
deletion would silently strip), RETIRED_KEYS_BY_MAJOR[18] entries, one D3
semantic entry, ledger rows to the tombstone disposition, minor changeset per
the launch-window convention, docs corrections, and the two in-repo authors
cleaned.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KX8wnyjStaZcuMyAMNsy3N
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 3 package(s): @objectstack/driver-memory, @objectstack/plugin-hono-server, @objectstack/spec, touching 20 documentable anchor(s). ⚠️6 changed file(s) yielded no anchor (packages/spec/authorable-surface/kernel.json, packages/spec/liveness/manifest.json, packages/spec/liveness/state-counts.md, …), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

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

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

What this run could not see
  • 6 changed file(s) yielded no anchor (packages/spec/authorable-surface/kernel.json, packages/spec/liveness/manifest.json, packages/spec/liveness/state-counts.md, …) — pages documenting those are invisible to this run
  • 7 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 74049254d47bd0edd2a2fcd732dcc01c91504f10packageMentionDocs.

Which tree this was computed on

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

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

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

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests tooling labels Aug 29, 2026
@hotlong
hotlong marked this pull request as ready for review August 30, 2026 04:58
@hotlong
hotlong added this pull request to the merge queueAug 30, 2026
Merged via the queue into main with commit dce5cd4Aug 30, 2026
41 checks passed
@hotlong
hotlong deleted the claude/issue-11332-manifest-container-retirement branch August 30, 2026 05:28
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/xlteststooling

Projects

None yet

2 participants

@hotlong@claude