docs(adr-0078): the completeness gate — Zod-valid-but-inert metadata must fail loudly at author time#2426
Merged
Conversation
…must fail loudly at author time, uniformly across surfaces
Surfaced by cloud#687 (an AI-built `summary` shipped as a dead `{type:'summary'}`
shell; the dependent "occupancy rate" was forever 0 while the agent reported it
done) plus a 5-angle functional-completeness audit.
Positions the decision precisely in the existing 3-gate chain: ADR-0049 closes
dead *properties* (per-property liveness), ADR-0054 closes *unproven* liveness
(integration), ADR-0077 closes *surface-routing* silent traps. The seam between
them — a Zod-valid *instance* that omits a sibling config its consumer needs and
silently no-ops (bare summary, action without `locations`, lookup without
`reference`, calendar without a date field) — is uncaught, and what coverage
exists lives ONLY in cloud graph-lint (framework `@objectstack/lint` has no
field/view/action completeness; `formula_without_expression` is cloud-only), so
`os build`/`os validate`/MCP/hand authors get none of it.
Decision (extends ADR-0049's trichotomy from property to instance): a config
whose omission makes an instance silently inert must be completeness-enforced,
marked `[EXPERIMENTAL — not enforced]`, or genuinely-graceful — never parsed-
and-silently-inert. The check is ONE shared per-type predicate in
`@objectstack/spec` (sibling of `isIncoherentAggregate`), consumed by BOTH
`@objectstack/lint` and cloud graph-lint — killing the path asymmetry. Plus the
cloud root cause: materialization must spread-not-allow-list so a correct
authoring isn't stripped. Ratchet, not retrofit (ADR-0054 idiom).
Includes the audit evidence doc with the deduped, confidence-tiered catalog and
a worked correction: the audit's scariest candidate (a "sharing rule fails open"
security claim) collapsed on a three-file read — the audit yields candidates,
not bugs; each becomes a rule only after verification.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
ADR-0078 + its evidence doc. Establishes the completeness gate: a metadata instance that is Zod-valid but functionally incomplete (and therefore silently does nothing at runtime) must fail loudly at author time, enforced uniformly across every authoring surface — not just the cloud AI-build path.
docs/adr/0078-no-silently-inert-metadata.md— the decisiondocs/audits/2026-06-metadata-functional-completeness.md— the evidence (5-angle audit, deduped + confidence-tiered)Why
Surfaced by cloud#687: an AI-built
summaryfield shipped as a dead{type:'summary'}shell, the dependent "occupancy rate" formula was forever0, and the agent reported it done. A 5-angle audit showed this is a class, not a one-off.It sits in a precise seam in the existing 3-gate chain:
summaryOperationsis live (per-property, blind to a per-instance omission){type:'summary'}is valid; completeness coverage is incomplete and cloud-only@objectstack/lint(framework) does expressions/widgets/SDUI but no field/view/action completeness;formula_without_expressionexists only in cloud graph-lint. Soos build/os validate/MCP/hand authors get none of it — exactly the wrong shape when AI authors across many surfaces.Decision (in brief)
[EXPERIMENTAL — not enforced], or gracefully-optional — never parsed-and-silently-inert.@objectstack/spec(sibling ofisIncoherentAggregate), consumed by both@objectstack/lintand cloud graph-lint → kills the path asymmetry.Sibling to ADR-0077 (surface-routing traps) — same "loud-not-silent, AI-is-the-author" family, orthogonal axis.
Discipline note
The audit's scariest candidate — a "sharing rule fails open and shares every record" security claim — collapsed on a three-file read (
conditionis required;ExpressionInputSchemarejects empty; the match-all branch is gated per ADR-0049). The audit yields candidates, not bugs; each becomes a rule only after verification. That lesson is baked into the ratchet.Status
Proposed — decision record for review, no code in this PR. cloud#687 already shipped the first instance (summary/formula rules); Phase 1 re-homes them onto the shared predicate.
🤖 Generated with Claude Code