Skip to content

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

Draft
claude[bot] wants to merge 1 commit into
mainfrom
claude/issue-11332-manifest-container-retirement
Draft

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

Conversation

@claude

@claude claude Bot 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-showcase capabilities: 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.

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

Labels

Projects

None yet

1 participant