feat(spec): opt-in os:check-yaml gate validates tagged docs YAML against live spec schemas - #13267
Merged
Merged
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KX8wnyjStaZcuMyAMNsy3N
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KX8wnyjStaZcuMyAMNsy3N
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KX8wnyjStaZcuMyAMNsy3N
Contributor
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
os-project-manager
marked this pull request as ready for review
August 29, 2026 20:25
os-project-manager
enabled auto-merge
August 29, 2026 20:25
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.
Fixes #13086
Implements the 2026-08-29 ruling on that card: option (ii) — an opt-in tagged-YAML checker mirroring the existing
os:checkmechanism. Corpus-wide tagging stays a follow-up (option (i), per the ruling); moving examples to ts fences (option (iii)) was explicitly not adopted.What this adds
check:yaml-examples(packages/spec/scripts/check-yaml-examples.ts): every fenced YAML block inskills/(md) andcontent/docs/(mdx, minus generatedreferences/) that carries anos:check-yaml SCHEMAmarker on the line directly above its bare yaml fence is parsed andsafeParsed against the live spec schema it declares.object,view,page, ...) resolves throughgetMetadataTypeSchema()— the same registry the runtime metadata write door validates with — so the docs' example parsing and the runtime accepting it are one fact. A PascalCase declaration (FormSectionSchema, ...) resolves against the same 15 category namespacesbuild-schemas.tswalks, because most doc examples are fragments that instantiate a named sub-schema. Ambiguous names are refused with qualified spellings listed.SCHEMAname may take a[]suffix (array of instances, validated element-wise) and akey=WRAPPERtoken (the single-key pedagogical wrapper many pages use, e.g.sections:). Any other key beside the wrapper is a loud failure.file:lineplus every Zod issue path and message untouched — the strict-object rename hints (e.g.visibleon a form section namingvisibleWhen, ADR-0089) reach the author exactly as a runtime save would print them (ruling point 1).--coveragefor the full table), so opt-in adoption is visible and proddable rather than a permanent excuse. Current reading: 6 tagged / 147 untagged across 17 files.os:checkconvention exactly: HTML-comment form in.md, MDX curly-brace expression-comment form in.mdx(the page being tagged here already carries twoos:checkmarkers of that form, so the MDX-safety precedent is on the same page).Gate obligations in full (ruling point 4):
--self-testwith 32 fixture-driven cases wired ahead of the production run in the package script (socheck:self-test-wiredcovers it by construction, verified green); classified incheck:generated's NO_GENERATOR ledger (--reconcile-onlygreen: 28 check + 17 gen scripts all classified); typechecked bycheck:scripts-typecheck(file presence in the program verified via listFiles); wired as a step in lint.yml'stypecheck-consumersjob beside the sibling example gates (adds no required context — a step in an existing job).Tagged page conversion (ruling point 2):
content/docs/protocol/objectui/layout-dsl.mdx— the page that shipped the same phantom-key class through three rounds (8251 / 8306 / 12935) — now carries the first sixos:check-yamlmarkers: twosection:wrappers, twosections:lists, the tabbedFormViewSchemaexample, and theresponsiveStylesfragment. All six validate against today's schemas with zero content edits. The 17 fences that remain untagged mostly teach shapes the live schemas refuse (whole undeclared surfaces, not typos — a removed-or-implemented decision per section); the per-fence readings are recorded as #13266, which remains open for docs-content triage rather than being cleaned up inside this mechanism card.yaml@2.9.0was added topackages/specdevDependencies — the exact version the workspace root already carries (no new third-party dependency; it makes the script's resolution explicit instead of leaning on the root hoist).Verification (all at head
4cf14eed, clean tree)check:yaml-examples --self-test: all 32 cases hold (extraction, fence-awareness of nested illustrations, all four orphan channels, resolution refusals including ambiguity, wrapper/array refusals, YAML parse errors with mapped lines, empty-claim refusals, and a pin that the live schema's rejection message reaches the output verbatim — the expectation is read from the live schema at test time, not fossilised).visible:breakpoint map into a tagged section block (mutation confirmed by anchored grep count 1) turned the gate red naminglayout-dsl.mdx:228and printing the ADR-0089 rename hint verbatim; restore viagit checkout HEADverified by grep count 0, emptygit diff HEAD, and disk blob hash equal to the HEAD blob (58f7edec). No dist is in this gate's read path (tsx over src + docs), so no rebuild leg applies.vitest run— 443 files, 11776 tests, all passing (covers thecheck-generated.tsledger edit's own pin suites).dispatch-gates.mjsfrom the merge base, re-derived at4cf14eed— list unchanged): all matched families green locally, includingcheck:docs,check:skill-examples(260 blocks across 3 surfaces — this PR's page edit is in its population),check:generatedfull aggregate, both@objectstack/lintdoc gates, the workflow-consistency family over the lint.yml edit,check:pm-dispatch-gates(879 cases) andbare-root-worklist --self-test, andcheck:nul-bytes.eslint.config.mjsaround line 328, with its own measured positive control), so per-file verdicts are independent of untouched files;eslint --no-inline-config --format jsonover both touched scripts: 2 files, 0 errors, 0 warnings. The.mdx/YAML/JSON paths in this diff are outside eslint's population and are covered by the docs gates above.check:type-check-debtre-measure leg (refuses on 55 unbuilt closure packages;@objectstack/specappears in neither DEBT nor TEST_DEBT ledger, and no ledgered package's sources are touched, so the measured numbers cannot move — the self-test and coverage half ran green),check-dev-prereqs(unbuilt-workspace precondition; this diff adds no package entry points),check:dual-build-cjs-loadsfull leg (explicit PREREQUISITE NOT MET exit 3; its 53-case self-test ran green; this diff changes no bundle or exports condition).check-test-completenessis a CI-attestation consumer and has no local run.Changeset
None, and
skip-changesetis applied deliberately: nothing published changes —packages/spec'sfileslist ships neitherscripts/nor devDependencies, and the docs tree is not a versioned package. Same shape as the merged precedents 13202 (spec gate script) and 13199 (docs + spec), bothskip-changeset.Session: https://claude.ai/code/session_01KX8wnyjStaZcuMyAMNsy3N
Generated by Claude Code
Generated by Claude Code