Found while measuring the contributes block for #10627 (census only; deliberately not fixed there). Measured on origin/main (299b85e9d).
Blocked-by: #10385 — that card is choosing the mechanism for the same root cause one category over, and whichever of its A/B/C lands decides how this one should be paid.
Observation
ManifestSchema (packages/spec/src/kernel/manifest.zod.ts:132) is a first-class authoring surface — authors write it as objectstack.config.ts / a package manifest, os plugin build parses it with ManifestSchema.safeParse, and it carries ~30 top-level keys plus the 11-member contributes block. Nothing in the liveness ledger governs any of it:
GOVERNED (packages/spec/scripts/liveness/check-liveness.mts:169) lists 30 metadata types; none is plugin, manifest or package.SPEC_ONLY_SCHEMAS (:246) — the escape hatch built for exactly "authorable but not a registry kind" — covers webhook, query, validation, qa. Not the manifest.PENDING_GOVERNANCE (:193) is empty, so the gate reports itself complete.ls packages/spec/liveness/ has 29 ledger files and nomanifest.json / plugin.json / package.json.
The consequence was demonstrated by #10627: ten of the eleven contributes members had zero readers, one of them (loading's sibling) had already been retired by hand at #4914, and no gate ever asked the question — because the ratchet's universe is the registered-kind set and a plugin manifest is not a kind.
Relationship to #10385
#10385 records the same root cause for non-kind authorable stack collections (analyticsCubes / connectors / sharingRules / themes) and proposes A (extend SPEC_ONLY_SCHEMAS), B (make the ratchet answerable to listUnregisteredKindSchemaTypes()), C (record the debt).
The manifest is a third category, and worth stating explicitly because #10385's option B would not reach it: the manifest is not in UNREGISTERED_KIND_SCHEMAS either. It is not a stack collection member at all — the retired-key entry 17.kernel__Manifest__loading.ts records exactly this, that PLURAL_TO_SINGULAR has no packages / plugins entry so a manifest is never walked as a stack collection. So a ratchet extended only to unregistered kinds would close #10385's four and still report itself complete over the manifest.
If the mechanism chosen at #10385 is A-shaped (SPEC_ONLY_SCHEMAS + a seeded ledger file), this becomes a small follow-on: add ManifestSchema to the override and seed packages/spec/liveness/manifest.json — #10627's verdict table supplies the contributes rows already, and #10724 / #10726 supply their dispositions.
Why it matters
The ledger README's own stated failure mode, applied to the ledger: "being off the registry is itself how such a drift hides." The manifest is the surface a plugin author writes first, it is where the platform's trust tier and permission declarations live, and it is the one large authorable schema on which the question "who reads this?" has never been asked by machinery — only by hand, twice, after the fact.
Filed unassigned for triage.
Generated by Claude Code
Found while measuring the
contributesblock for #10627 (census only; deliberately not fixed there). Measured onorigin/main(299b85e9d).Blocked-by: #10385 — that card is choosing the mechanism for the same root cause one category over, and whichever of its A/B/C lands decides how this one should be paid.
Observation
ManifestSchema(packages/spec/src/kernel/manifest.zod.ts:132) is a first-class authoring surface — authors write it asobjectstack.config.ts/ a package manifest,os plugin buildparses it withManifestSchema.safeParse, and it carries ~30 top-level keys plus the 11-membercontributesblock. Nothing in the liveness ledger governs any of it:GOVERNED(packages/spec/scripts/liveness/check-liveness.mts:169) lists 30 metadata types; none isplugin,manifestorpackage.SPEC_ONLY_SCHEMAS(:246) — the escape hatch built for exactly "authorable but not a registry kind" — coverswebhook,query,validation,qa. Not the manifest.PENDING_GOVERNANCE(:193) is empty, so the gate reports itself complete.ls packages/spec/liveness/has 29 ledger files and nomanifest.json/plugin.json/package.json.The consequence was demonstrated by #10627: ten of the eleven
contributesmembers had zero readers, one of them (loading's sibling) had already been retired by hand at #4914, and no gate ever asked the question — because the ratchet's universe is the registered-kind set and a plugin manifest is not a kind.Relationship to #10385
#10385 records the same root cause for non-kind authorable stack collections (
analyticsCubes/connectors/sharingRules/themes) and proposes A (extendSPEC_ONLY_SCHEMAS), B (make the ratchet answerable tolistUnregisteredKindSchemaTypes()), C (record the debt).The manifest is a third category, and worth stating explicitly because #10385's option B would not reach it: the manifest is not in
UNREGISTERED_KIND_SCHEMASeither. It is not a stack collection member at all — the retired-key entry17.kernel__Manifest__loading.tsrecords exactly this, thatPLURAL_TO_SINGULARhas nopackages/pluginsentry so a manifest is never walked as a stack collection. So a ratchet extended only to unregistered kinds would close #10385's four and still report itself complete over the manifest.If the mechanism chosen at #10385 is A-shaped (
SPEC_ONLY_SCHEMAS+ a seeded ledger file), this becomes a small follow-on: addManifestSchemato the override and seedpackages/spec/liveness/manifest.json— #10627's verdict table supplies thecontributesrows already, and #10724 / #10726 supply their dispositions.Why it matters
The ledger README's own stated failure mode, applied to the ledger: "being off the registry is itself how such a drift hides." The manifest is the surface a plugin author writes first, it is where the platform's trust tier and permission declarations live, and it is the one large authorable schema on which the question "who reads this?" has never been asked by machinery — only by hand, twice, after the fact.
Filed unassigned for triage.
Generated by Claude Code