Skip to content

fix(spec,rest,cli): validation diagnostics reach the real defect — named view-union branches + invalid_key/invalid_element descent (#7025) - #7042

Merged
os-zhuang merged 3 commits into
mainfrom
claude/issue-7025-diagnostics-descent-sweep
Aug 9, 2026
Merged

fix(spec,rest,cli): validation diagnostics reach the real defect — named view-union branches + invalid_key/invalid_element descent (#7025)#7042
os-zhuang merged 3 commits into
mainfrom
claude/issue-7025-diagnostics-descent-sweep

Conversation

@os-zhuang

@os-zhuang os-zhuang commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Fixes #6391
Fixes #5389

Sweep card: #7025 — "validation diagnostics don't reach the real defect", 2 members, one PR.

Both members are cases where a validation failure's refusal is correct but its diagnostic cannot reach the element that actually failed. Both fixes move the DIAGNOSTIC face only.


⛔ The sweep's red line, discharged

The acceptance face must not move: every input that parsed before parses after, every input refused before is refused after — pinned in both directions.

Measured, not asserted. A 42-body corpus was run through ViewMetadataSchema on origin/main @ 0f539bd and again on this branch, recording for each body its verdict, its full parse OUTPUT on accept, and its issue-code set on reject. The two reports are byte-identical:

sha256=fca9df8937bbb9f736f11895a6e1ddf23b7fb25d9b13cfa7e67c71c8dfaaf2b2   (before)
sha256=fca9df8937bbb9f736f11895a6e1ddf23b7fb25d9b13cfa7e67c71c8dfaaf2b2   (after)

That corpus is now a committed pin — packages/spec/src/ui/view-union-diagnostics.test.ts[#7025] the acceptance face of ViewMetadataSchema did not move: 19 still ACCEPTS … cases (verdict and parse output) + 23 still REFUSES … cases (verdict and issue codes). Rejection-face pins keep asserting the issue code per ADR-0112 / #6142 — a better diagnostic never weakens the envelope.

A discriminated union changes error SHAPE, not membership — so this PR does not add one. #6391 offered that as one of two routes and it was declined, because it would move membership: z.discriminatedUnion refuses an unknown discriminant outright where this union falls through all four members, and several of these shapes carry no discriminant at all (a flattened overlay may be nothing but columns). What landed instead is a diagnostic dispatch that names a branch and decides nothing. Pinned: never disagrees with ViewMetadataSchema about acceptance.

For #5389 the acceptance face is untouched by construction — no schema was edited. The three files changed for it are error formatters (formatZodIssue/formatZodError, zodIssuesToFields, formatZodErrors); objectStackErrorMap itself is unchanged.


Per-item checklist

# 落点 (landing site) before after
#6391 packages/spec/src/ui/view.zod.ts — the four ViewMetadataSchema union members, VIEW_METADATA_BRANCHES / VIEW_METADATA_MEMBERS / selectViewMetadataBranch / diagnoseViewMetadata 3 of 4 members were inline expressions with no name; the only structural route to a branch was error.issues[0].errors[<position>], and the rendered message came from a different branch the union is built from a named record; diagnoseViewMetadata(body) returns branch: 'listOverlay' + that branch's own leaf issues. No position anywhere
#5389 packages/spec/src/shared/error-map.zod.ts, packages/rest/src/rest-server.ts, packages/cli/src/utils/format.ts — the union family's three consumers all three read issue.errors only, so invalid_key / invalid_element surfaced as a bare wrapper with the real diagnosis stranded in the payload all three also descend issue.issues, additively, on all three surfaces (terminal, wire, defineStack)

Both members completed — no member dropped, so both carry Fixes.

Premise re-verification against origin/main @ 0f539bd


Real before/after error output

#5389 — a z.record with a constrained key

Fixture: z.object({ fields: z.record(SnakeKey, z.object({ type: z.string() })) }), body { fields: { 'First Name': { type: 'text' } } }.

formatZodError — spec / defineStack

  Stack validation failed (1 issue):

    ✗ fields.First Name: Invalid key in record
+     ✗ fields.First Name: Invalid identifier. Must be lowercase snake_case (e.g. 'first_name').

zodIssuesToFields — the REST wire

  [
    { "field": "fields.First Name", "code": "invalid_shape", "message": "Invalid key in record" },
+   { "field": "fields.First Name", "code": "invalid_format",
+     "message": "Invalid identifier. Must be lowercase snake_case (e.g. 'first_name')." }
  ]

formatZodErrors — the CLI terminal

    fields:
      ✗ fields.First Name
        invalid_key: Invalid key in record
+         ✗ fields.First Name: Invalid identifier. Must be lowercase snake_case (e.g. 'first_name').

    1 validation error(s) total

Additive on every surface: the container's own line / entry is unchanged and the leaves follow it. One deliberate divergence from the union descent — a union's errors[] are competing candidates, so they are ranked and capped; a container's issues[] is the one list the inner schema produced, so every entry is reported.

#6391 — a flattened list overlay whose columns is a string

Body: { type: 'grid', columns: 'not-an-array' }.

Before — the rendered message comes from the container branch (fewest issues wins) and prescribes wrapping the body in defineView, which is not the defect:

view metadata (1 issue):

  ✗ (root): Invalid input
    ✗ (root): Unrecognized key(s) on this view container: `type`, `columns`.
  • `type` belongs to a single VIEW, not to the container. Wrap it: `defineView({ list: {…} })` …
  • `columns` belongs to a single VIEW, not to the container. Wrap it: `defineView({ list: {…} })` …

The real diagnosis existed — at error.issues[0].errors[2], i.e. member position 2:

[{ "code": "invalid_union", "path": ["columns"], "message": "Invalid input", "errors": [ ] }]

After — one call, branch named, leaf issue with its real path, no position:

{
  "success": false,
  "branch": "listOverlay",
  "issues": [{ "code": "invalid_union", "path": ["columns"], "message": "Invalid input", "errors": [ ] }]
}

ViewMetadataSchema.safeParse is byte-identical to before — the old output above is still exactly what it produces. diagnoseViewMetadata is an additional entry point, not a replacement.


New public API (@objectstack/spec, ./ui) — 6 added, 0 breaking

check:api-surface reports 0 breaking (removed/narrowed), 6 added:

  • VIEW_METADATA_BRANCHES — the branch names, in the union's own order
  • VIEW_METADATA_MEMBERS — branch name → the schema the union actually holds
  • ViewMetadataBranch, ViewMetadataDiagnosis (types)
  • selectViewMetadataBranch(body), diagnoseViewMetadata(body)

The three container/overlay member schemas are published through the record rather than as individual …Schema consts, deliberately: a top-level exported schema binding mints a protocol def in json-schema.manifest/ and a full key set in the ratcheted authorable-surface/. Measured — exporting ViewContainerWireSchema directly added ui/ViewContainerWire plus 15 authorable keys that are byte-duplicates of ui/View's, i.e. 15 phantom entries on the ADR-0049 liveness worklist for a wire door nobody authors against. VIEW_METADATA_MEMBERS.container is the same contractual handle with none of that. With the record form, the only generated-tree change in this PR is the 6 api-surface lines above.


Verification record

Dependency closure built first (#6371): pnpm build green on origin/main before any edit, and again after. main moved during verification and was merged (never rebased); spec moved on the incoming side, so the four-step ran after the merge — pnpm install --frozen-lockfile, full pnpm build, rm -rf packages/runtime/.objectstack, pnpm --filter @objectstack/spec check:generated (all 10 artifacts up to date, nothing to regenerate). Branch delta vs origin/main unchanged at 10 files.

pnpm test on the merged tree: 84/94 turbo tasks green, one failing task per run and a different one each time@objectstack/types src/node.test.ts in one run, @objectstack/plugin-email src/email-service.queue-delivery.test.ts in the next. Both are Test timed out in 5000ms on the default vitest timeout, in packages this diff does not touch, on a container reporting import 166.60s for a 94-task parallel run — i.e. saturation, not a regression. Each was re-run alone on the same tree and passed (types 230/230, plugin-email 302/302), and every suite this diff does touch is green in both runs. Recording it here rather than claiming an unqualified green. CI's Test Core (1..3/3) is green on the pushed head.

Reverse verification (revert the fix, watch the diagnostics) — spec rebuilt between passes so the CLI's @objectstack/spec import saw the reverted build:

suite with the fix fix reverted
spec/src/ui/view-union-diagnostics.test.ts 66 passed 25 failed / 41 passed — every failure in the #6391 blocks; the whole [#7025] acceptance face block stayed green on both revisions, which is what makes it a no-change pin rather than a change pin
spec/src/shared/error-map.test.ts 35 passed 3 failed
rest/src/zod-union-fields.test.ts 18 passed 2 failed
cli/test/format-zod-union.test.ts 13 passed 2 failed

Consumer sweep (#6218) — direction: '…@objectstack/spec', i.e. everything downstream of spec, typechecked against the rebuilt .d.ts (#6391 adds exports, so this is the direction that matters):

  • pnpm exec turbo run build --filter='./packages/*' --filter='./examples/*^...' — 66/66
  • pnpm exec turbo run typecheck --filter='./packages/*' --filter='./packages/*/*' --filter='./apps/*' — 121/121
  • pnpm --filter './examples/*' run typecheck, pnpm --filter @objectstack/downstream-contract run typecheck — green

Gates, enumerated one by one from .github/workflows/lint.yml — all green:

pnpm lint · check:slot-lookup · check:query-options-erasure · check:verify-stand-in · check:nul-bytes · check:doc-authoring · check:docs-audit-scope · check:role-word · check:quick-reference-counts · check:adr-anchors · check:org-identifier · check:authz-resolver · check:service-providers · check:route-envelope · check:error-code-casing · check:wildcard-fallthrough · check:meta-type-normalized · check:init-service-contract · check:durability-log-level · check:startup-registry-verdict · check:objectui-changeset · check:changeset-gate-self-tests · check:release-notes · check:release-body · check:node-version · check:workflow-status-functions · check:shard-attestation · check:required-contexts · check:published-files · check:engine-double-contract · check:kernel-hook-pairs · check:resume-authority-declared · check:driver-memory-census · check:merge-driver · check:spec-parsed-alias · check:tenant-chokepoint · check:type-check-coverage · check:driver-conformance · check:stall-guard · check:skill-frame-sync · check:skill-compatibility · check:agent-model-declared · check:generated --reconcile-only · check:skill-docs · check:spec-changes · check:upgrade-guide · check:authorable-surface · check:docs · check:skill-refs · check:react-blocks · check:type-check-debt · check:api-surface · check:exported-any · check:dual-source-exports · check:skill-examples · check:doc-formula-expressions · check:i18n · check:i18n-coverage · check:app-nav-i18n

Plus node scripts/check-adr-0087-registration.mjs --base origin/main✓ this PR adds no declared-breaking changeset, and pnpm --filter @objectstack/spec check:generated → all 10 generated artifacts up to date.

Generated trees were produced by their generator only (gen:api-surface); nothing hand-edited. No content/docs/references change (check:docs green without one).


Scope self-certification

git diff --stat origin/main...HEAD maps 1:1 onto the checklist — 10 files, no file outside the two items:

 .changeset/view-union-and-container-issue-diagnostics.md |  60 ++     ← changeset (both members)
 packages/spec/src/ui/view.zod.ts                         | 354 ++     ← #6391
 packages/spec/src/ui/view-union-diagnostics.test.ts      | 336 ++     ← #6391 pins + the acceptance-face table
 packages/spec/api-surface/ui.json                        |   6 ++     ← #6391, generator output
 packages/spec/src/shared/error-map.zod.ts                | 107 ++     ← #5389 consumer 1
 packages/spec/src/shared/error-map.test.ts               | 102 ++     ← #5389 consumer 1 pins
 packages/rest/src/rest-server.ts                         |  46 ++     ← #5389 consumer 2
 packages/rest/src/zod-union-fields.test.ts               |  82 ++     ← #5389 consumer 2 pins
 packages/cli/src/utils/format.ts                         |  52 ++     ← #5389 consumer 3
 packages/cli/test/format-zod-union.test.ts               |  39 ++     ← #5389 consumer 3 pins

No out-of-scope discoveries needed filing: nothing was found outside the two items that this PR left unfixed.

Per Prime Directive #14/#15 this PR touches neither docs/adr/** nor any release surface. It was opened as a draft and was neither merged, queued, nor auto-merge-armed by this seat; it was marked ready and queued by the PM seat (os-zhuang) as part of the #7025 landing relay.


Generated by Claude Code

claude added 3 commits August 9, 2026 10:45
…, #5389)

Sweep #7025 — two cases where a refusal is correct but its DIAGNOSTIC cannot
reach the element that actually failed. Both fixes move the diagnostic face
only; the acceptance face is pinned unmoved in both directions.

#6391 — ViewMetadataSchema's union members are contractual, not positional.
Three of its four members were inline expressions with no name, so a consumer
diagnosing a failure could only reach a branch by indexing the nested
invalid_union `errors[]` BY MEMBER POSITION (objectui#3624 shipped exactly that
and had to hold the coupling down with a canary test). The union is now BUILT
from a named record — VIEW_METADATA_BRANCHES / VIEW_METADATA_MEMBERS — so
"member N is the published schema" is one declaration rather than two that can
drift, and diagnoseViewMetadata() returns the failing branch by NAME with that
branch's own leaf issues and real field paths.

The union is deliberately NOT converted to z.discriminatedUnion: that would
move membership (a discriminated union refuses an unknown discriminant outright
where this one falls through all four members, and several of these shapes
carry no discriminant at all). The dispatch is diagnostic — ViewMetadataSchema
remains the only judge of acceptance, and a pin asserts the two never disagree.

Measured: a 41-body corpus run through ViewMetadataSchema before and after
produces byte-identical verdicts, parse output and issue-code sets
(sha256 fca9df8937bbb9f736f11895a6e1ddf23b7fb25d9b13cfa7e67c71c8dfaaf2b2), and
that corpus is now a committed pin.

#5389 — invalid_key / invalid_element are descended, in all three consumers.
Zod hangs a failing record-key / map-element schema's real issues on
`issue.issues` — the same shape as invalid_union's `issue.errors`, one property
name over. The family had already been fixed three times for `errors` (#4971,
#5014, #5341) while none of the three consumers read `issues`, so both codes
surfaced as a bare wrapper line with the prescription stranded in the payload.
formatZodError/formatZodIssue (spec), zodIssuesToFields (the REST wire) and
formatZodErrors (the CLI terminal) now all descend it, additively: the
container's own line/entry is unchanged and the leaves follow it. Unlike a
union's branches — competing candidates, therefore ranked and capped — a
container's issues are the one list the inner schema produced, so every one of
them is reported.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FRQdfKG4YpSv1SkujpWmk2
`main` moved while this sweep was in verification. Merged (never rebased) per
the landing relay. No `merge=os-regen` conflicts; spec moved on the incoming
side, so the four-step ran after it: install --frozen-lockfile, full build,
`rm -rf packages/runtime/.objectstack`, `check:generated` — all 10 generated
artifacts up to date with nothing to regenerate. The branch's delta vs
`origin/main` is unchanged at 10 files.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FRQdfKG4YpSv1SkujpWmk2
Comment-only. The pin table is 19 ACCEPT + 23 REFUSED = 42; the header said 41.
No assertion changed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FRQdfKG4YpSv1SkujpWmk2
@vercel

vercel Bot commented Aug 9, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 9, 2026 11:08am

Request Review

@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 3 package(s): @objectstack/cli, @objectstack/rest, @objectstack/spec.

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

  • content/docs/ai/agents.mdx (via @objectstack/spec)
  • content/docs/ai/connect-mcp.mdx (via @objectstack/rest)
  • content/docs/ai/skills-reference.mdx (via packages/cli, @objectstack/spec)
  • content/docs/ai/skills.mdx (via @objectstack/spec)
  • content/docs/api/client-sdk.mdx (via @objectstack/cli, @objectstack/spec)
  • content/docs/api/data-flow.mdx (via @objectstack/cli)
  • content/docs/api/environment-routing.mdx (via @objectstack/cli, @objectstack/spec)
  • content/docs/api/error-catalog.mdx (via @objectstack/cli, @objectstack/spec)
  • content/docs/api/error-handling-client.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx (via @objectstack/rest, @objectstack/spec)
  • content/docs/api/index.mdx (via @objectstack/rest, @objectstack/spec)
  • content/docs/automation/approvals.mdx (via @objectstack/spec)
  • content/docs/automation/connectors.mdx (via @objectstack/spec)
  • content/docs/automation/flows.mdx (via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx (via packages/cli, packages/spec)
  • content/docs/automation/hooks.mdx (via @objectstack/spec)
  • content/docs/automation/index.mdx (via @objectstack/spec)
  • content/docs/automation/webhooks.mdx (via @objectstack/spec)
  • content/docs/automation/workflows.mdx (via @objectstack/spec)
  • content/docs/concepts/architecture.mdx (via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx (via packages/spec)
  • content/docs/concepts/index.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx (via packages/spec)
  • content/docs/concepts/north-star.mdx (via @objectstack/spec)
  • content/docs/data-modeling/analytics.mdx (via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx (via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx (via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx (via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx (via @objectstack/spec)
  • content/docs/data-modeling/index.mdx (via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx (via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx (via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx (via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx (via @objectstack/spec)
  • content/docs/deployment/backup-restore.mdx (via @objectstack/cli)
  • content/docs/deployment/cli.mdx (via @objectstack/cli, @objectstack/spec)
  • content/docs/deployment/self-hosting.mdx (via @objectstack/cli)
  • content/docs/deployment/tenancy-modes.mdx (via @objectstack/spec)
  • content/docs/deployment/troubleshooting.mdx (via @objectstack/spec)
  • content/docs/deployment/validating-metadata.mdx (via packages/cli, @objectstack/spec)
  • content/docs/getting-started/build-with-claude-code.mdx (via @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx (via @objectstack/spec)
  • content/docs/getting-started/examples.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx (via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx (via @objectstack/cli, @objectstack/spec)
  • content/docs/kernel/cluster.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx (via @objectstack/spec)
  • content/docs/kernel/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/data-service.mdx (via @objectstack/cli, @objectstack/spec)
  • content/docs/kernel/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/examples.mdx (via @objectstack/spec)
  • content/docs/kernel/runtime-services/index.mdx (via packages/cli, packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx (via @objectstack/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx (via @objectstack/spec)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/spec)
  • content/docs/kernel/services.mdx (via @objectstack/spec)
  • content/docs/permissions/authentication.mdx (via @objectstack/cli, @objectstack/rest)
  • content/docs/permissions/authorization.mdx (via @objectstack/spec)
  • content/docs/permissions/permission-sets.mdx (via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx (via @objectstack/spec)
  • content/docs/permissions/positions.mdx (via @objectstack/spec)
  • content/docs/permissions/rls.mdx (via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx (via @objectstack/spec)
  • content/docs/permissions/system-context.mdx (via packages/rest, packages/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx (via @objectstack/spec)
  • content/docs/plugins/development.mdx (via @objectstack/spec)
  • content/docs/plugins/index.mdx (via @objectstack/cli, @objectstack/rest, @objectstack/spec)
  • content/docs/plugins/packages.mdx (via @objectstack/cli, @objectstack/rest, @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx (via @objectstack/spec)
  • content/docs/protocol/diagram.mdx (via packages/spec)
  • content/docs/protocol/kernel/config-resolution.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/http-protocol.mdx (via @objectstack/rest, @objectstack/spec)
  • content/docs/protocol/kernel/i18n-standard.mdx (via packages/rest, @objectstack/spec)
  • content/docs/protocol/kernel/index.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.mdx (via @objectstack/cli, @objectstack/spec)
  • content/docs/protocol/kernel/realtime-protocol.mdx (via @objectstack/cli)
  • content/docs/protocol/knowledge.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/query-syntax.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx (via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/record-alert.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx (via @objectstack/spec)
  • content/docs/ui/actions.mdx (via @objectstack/spec)
  • content/docs/ui/apps.mdx (via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx (via @objectstack/spec)
  • content/docs/ui/dashboards.mdx (via @objectstack/spec)
  • content/docs/ui/field-grouping-and-order.mdx (via @objectstack/spec)
  • content/docs/ui/forms.mdx (via @objectstack/spec)
  • content/docs/ui/index.mdx (via @objectstack/spec)
  • content/docs/ui/public-data-collection.mdx (via @objectstack/spec)
  • content/docs/ui/setup-app.mdx (via @objectstack/spec)
  • content/docs/ui/translations.mdx (via @objectstack/spec)
  • content/docs/ui/views.mdx (via @objectstack/spec)

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

  • content/docs/releases/implementation-status.mdx (via @objectstack/cli, @objectstack/rest, @objectstack/spec)
  • content/docs/releases/index.mdx (via @objectstack/spec)
  • content/docs/releases/v12.mdx (via @objectstack/rest, @objectstack/spec)
  • content/docs/releases/v13.mdx (via @objectstack/spec)
  • content/docs/releases/v16.mdx (via @objectstack/cli, @objectstack/spec)
  • content/docs/releases/v17.mdx (via @objectstack/cli, @objectstack/rest, @objectstack/spec)
  • content/docs/releases/v9.mdx (via @objectstack/spec)

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.

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests protocol:ui tooling labels Aug 9, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review August 9, 2026 11:44
@os-zhuang
os-zhuang added this pull request to the merge queue Aug 9, 2026
Merged via the queue into main with commit 3fc2e48 Aug 9, 2026
28 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-7025-diagnostics-descent-sweep branch August 9, 2026 12:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation protocol:ui size/xl tests tooling

Projects

None yet

2 participants