Skip to content

fix(metadata-protocol): draft preview no longer reports itself invalid over its own _draft badge - #8179

Merged
huangyiirene merged 3 commits into
mainfrom
claude/issue-7656-draft-preview-diagnostics
Aug 12, 2026
Merged

fix(metadata-protocol): draft preview no longer reports itself invalid over its own _draft badge#8179
huangyiirene merged 3 commits into
mainfrom
claude/issue-7656-draft-preview-diagnostics

Conversation

@huangyiirene

Copy link
Copy Markdown
Collaborator

Fixes#7656

The defect, reproduced

GET /api/v1/meta/{type}/{name}?preview=draft answered _diagnostics.valid:false
for a valid draft, complaining about a key the read itself had just added:

Unrecognized key(s) on this object: `_draft`. Until #4001 closed this shape these
were dropped silently on the PARSE path — ...

Confirmed on origin/main before any edit, on both injection sites, with
tests that were red first (see "Reverse verification" below).

Root cause

The preview read stamps _draft:true onto the item so the console can badge it —
protocol.ts:4462 (list overlay) and protocol.ts:4672 (single-item read) — and
then hands the item to decorateMetadataItemcomputeMetadataDiagnostics,
which re-parses it against the closed item schema.

That re-parse stripped only _diagnostics, via a private one-key helper
(stripDiagnostics) that predated _draft joining the shared
METADATA_READ_DECORATIONS list. So the reader validated its own badge and
reported the document invalid for it. The verdict described the reader, not the
document — and it reached every draft of every type, on both exits.

The fix

computeMetadataDiagnostics now calls the shared stripReadDecorations instead
of its private copy. One line of behaviour; the rest of the diff is the comment
explaining why the list is the right authority here.

This is the shape the codebase already owns. The module header of
spec/kernel/metadata-read-decorations.ts names two classes of consumer that
must strip: the write path's verbatim persist (#4326) and any re-parse of a
served document
(cloud#971's cold-boot flow bind). Read-time diagnostics are a
re-parse of a served document in exactly that sense — the third consumer — so it
reads the list rather than keeping a private subset of it.

Same class as the closed#6810 (indexed, rejected by name on a served object),
different remedy, deliberately: indexed did not belong on the served body
at all and was removed at its injection site, whereas _draft is the preview
badge the UI reads and is already a declared read decoration. Removing the stamp
would break the badge; the list is where it is consumed.

The item schema is not loosened._draft stays rejected by name in a
stored body — pinned by a test — which is what keeps the #4326 write-path strip
load-bearing rather than cosmetic.

Scope note

The declared file surface was protocol.ts — "the draft-preview read decoration
and the _diagnostics computation it feeds". The fix landed in the module that
is that computation (metadata-diagnostics.ts, same package), not in
protocol.ts. Closing it there fixes both injection sites with one edit, covers
any future decoration key for free, and touches none of protocol.ts — which is
carrying two other claimed regions this round (#8136, #8003).

Tests

packages/metadata-protocol/src/protocol.read-decorations.test.ts, +6 cases in
the file that already owns this discipline:

  • the reproduction, both exits — a valid draft read back through
    getMetaItem({ previewDrafts: true }) and through the getMetaItems draft
    overlay: _diagnostics.valid is true and no error mentions _draft.
  • anti-vacuity, both exits — a genuinely broken draft (a field whose type
    is not a field type, seeded directly since the save path refuses it with 422)
    still reads back valid:false, with errors naming amount and not
    _draft. Without these, a fix that simply stopped computing diagnostics on
    the draft path would pass.
  • drift guard — every member of METADATA_READ_DECORATIONS must be
    invisible to the verdict, so a fourth decoration fails on a unit here instead
    of as valid:false on somebody's badge.
  • anti-loosening pin — the object schema still rejects _draft with
    unrecognized_keys.

Reverse verification

Reverting only metadata-diagnostics.ts to origin/main turns 5 of the 6
new cases red, each on the card's verbatim message. The sixth — the
anti-loosening pin — is green in both directions by design: it pins a
constraint the fix must not relax (the schema stays closed), not the fix itself,
so a direction change there would mean the schema had been loosened.

Evidence

@objectstack/metadata-protocol Test Files 75 passed (75) Tests 1100 passed (1100)
@objectstack/objectql Test Files 191 passed (191) Tests 3390 passed (3390)
@objectstack/rest Test Files 102 passed (102) Tests 1728 passed (1728)
@objectstack/runtime Test Files 145 passed (145) Tests 2195 passed (2195)
@objectstack/metadata Test Files 31 passed (31) Tests 603 passed (603)
@objectstack/service-automation Test Files 79 passed (79) Tests 940 passed (940)

Consumer direction: the five non-authoring packages above are downstream
consumers of @objectstack/metadata-protocol (prefix filter ... + the package
name), picked as the ones whose suites exercise /meta reads, draft preview or
_diagnostics. Type surface is unchanged, so this sweep is about behaviour pins,
not types.

Gates named by scripts/pm/dispatch-gates.mjs for these files, all green
locally: check:error-code-casing, check:cross-package-test-inputs,
check:durability-log-level, check:changeset-gate-self-tests,
check:objectui-changeset, check-changeset-no-major, plus check:nul-bytes
and eslint on the changed files.

Changeset: .changeset/draft-preview-diagnostics-draft-badge.md (patch).


Generated by Claude Code

@vercel

vercelBot commented Aug 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectstackIgnoredIgnoredAug 12, 2026 6:45pm

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/metadata-protocol.

3 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/concepts/metadata-lifecycle.mdx(via @objectstack/metadata-protocol)
  • content/docs/kernel/services-checklist.mdx(via @objectstack/metadata-protocol)
  • content/docs/protocol/kernel/http-protocol.mdx(via @objectstack/metadata-protocol)

1 release-owned page(s) also reference the affected code. These are read-only:

  • content/docs/releases/v9.mdx(via @objectstack/metadata-protocol)

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

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

Labels

documentationImprovements or additions to documentationsize/mteststooling

Projects

None yet

2 participants

@huangyiirene@claude