Uh oh!
There was an error while loading. Please reload this page.
docs(api): retire the compound-name spelling from the live docs (#12176 stage 4) - #12381
Merged
Merged
Conversation
… stage 4) Stage 4 of the #12176 maintainer-ruled retirement of slash-bearing metadata item names. Stage 1 (#12194) declared the item-name grammar and refuses every slash-bearing name at the publish door; stage 3 (#12195) un-mounted the three compound `:section` arities. These two pages were still teaching both. content/docs/api/client-sdk.mdx: - The `meta.getItem` example addressed `'views/all_leads'` and promised compound names "pass through unencoded". Both halves are dead: the name is refused at the publish door, and #12195 put encodeURIComponent on every /meta item address, so there is no unencoded pass-through left. Respelled to the grammar's own published exemplar, `crm_lead.pipeline` under type `view` — which is exactly ViewItemNameSchema's `<object>.<viewKey>` identity, so the example teaches the enforced shape rather than a new one. content/docs/api/error-catalog.mdx: - The unmintable-type entry documented TWO exemptions reaching the door. The compound-arity exemption is gone from the source (it was removed by #12194, not #12195 — `refuseUngrammaticalMetaItemName` runs before the probe and refuses every slash-bearing name), so the page has been describing a served behaviour that no longer exists. Reduced to the one surviving exemption, with a short retirement note so a caller who knew the old behaviour is not left guessing. - The residue that exemption documented — `PUT /meta/fieldz/a/b` being accepted — is closed with it, and the page now says so. - Two plural references to "the exemptions" corrected to the singular. No changeset: docs-only, releases nothing (the `skip-changeset` case the workflow prescribes). No ablation is owed — the change is prose and one example, and the example is covered by check:skill-examples' semantic pass. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H9StxQgG2DPA26XzZZqnJB
os-trump
marked this pull request as ready for review
August 25, 2026 23:50
os-trump
enabled auto-merge
August 25, 2026 23:50
Uh oh!
There was an error while loading. Please reload this page.
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 freeto 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#12196
Part of #12176 — stage 4 (docs sweep).
D1 (#12194) declared the item-name grammar and refuses every slash-bearing name at the
publish door; D3 (#12195) un-mounted the three compound
:sectionarities. D3's difftouched zero docs files, so the whole live-docs surface was still teaching names that
can no longer be created and routes that are no longer mounted. This corrects it.
FROM → TO
content/docs/api/client-sdk.mdx(lines 216-217)// Compound names (sub-resources) pass through unencodedconst view = await client.meta.getItem('object', 'views/all_leads');// Sub-resource identity is DOT-qualified — `<object>.<viewKey>`, never a `/`const view = await client.meta.getItem('view', 'crm_lead.pipeline');Both halves of the old line were dead, for two different reasons. The name is refused
at the publish door by D1. The "unencoded" promise was retired by D3, which put
encodeURIComponenton every/metaitem address to close the 10-unencoded / 4-encodedsplit — there is no unencoded pass-through left to teach.
The replacement is not invented:
crm_lead.pipelineis the grammar's own publishedexemplar (
METADATA_ITEM_NAME_PATTERN's TSDoc,ViewItemNameSchema's refusal message,and the generated
content/docs/references/api/protocol.mdxrow D1 already landed), andit is exactly
ViewItemNameSchema's<object>.<viewKey>identity — so under typeviewthe example teaches the enforced shape rather than minting a second one.
content/docs/api/error-catalog.mdx—INVALID_REQUEST— unmintable metadata typethe type segment, and the exemptions below decide whether it fires at all.the type segment, and the exemption below decides whether it fires at all.**Two shapes reach this door and are served, not refused** — neither of them visible inthe message, so a caller who does not read this entry finds them by collision:**One shape reaches this door and is served, not refused** — it is not visible in themessage, so a caller who does not read this entry finds it by collision:namecontaining/exempts the request…PUT /meta/lead/views/all_leadsistype='lead',name='views/all_leads'…PUT /meta/fieldz/a/bis therefore accepted…PUT /meta/lead/all_leadsis still refused."/, the compound arities are un-mounted, andPUT /meta/fieldz/a/bis no longer accepted and no longer reaches this verdict at all.2. **Pre-existing namespace.** …(numbered list item)- **Pre-existing namespace.** …(bullet — the list has one member now; wording otherwise unchanged)door is what stops the first row from being written; the exemptions above are what keepdoor is what stops the first row from being written; the exemption above is what keepsWhy the compound exemption is deleted rather than respelled. It has no dot-spelling —
it was an exemption from a verdict, not a name. And it was already false before this PR:
refuseUnmintableMetaType's own header inpackages/metadata-protocol/src/protocol.tsrecords that the slash exemption was removed by #12194 (D1), not by D3 —
refuseUngrammaticalMetaItemNameruns first and refuses every slash-bearing name beforethe probe is reached. The source names the corrected facts, including the residue that is
now shut, so the replacement text is pinned by landed code rather than by this PR's
judgement.
I kept a brief "retired" note rather than deleting silently: a caller who knew the old
behaviour would otherwise read the page as merely incomplete. It marks the spelling dead —
it does not teach it as usable.
Census — the population I measured
403
.md/.mdxfiles undercontent/docs/**on the post-D3 ref (7986d973),independently corroborated by
check-doc-frontmatter's own count: "content/docs(pageSchema, floor 1): 403 page(s) parse".
Instrument proven before trusting any zero — positive control
views/all_leadsfireson exactly 2 lines, both censused pages. Patterns then swept:
crm/task,:section,compound/Compound,sub-resource,unencoded,%2F,all_leads,getItem(,saveItem(,slash, quoted'<snake>/<snake>'shapes, and 3-segment/meta/<x>/<y>/<z>paths.Result: the two censused pages were the entire live surface. Everything else the
patterns caught is a true negative and was left alone —
/meta/hits are surviving literal routes (/publish,/rollback,/history,/audit,/diff,/layers,/references,/tree,/schema,/state/:field), all still mounted.<a>/<b>hits are MIME types (application/json,image/jpeg), not item names.compoundhits are state-machine node types, compound DB indexes and compound viewcells — unrelated vocabulary.
page:section/_sectionsare layout and i18n concepts, not the retired route segment.content/docs/references/api/protocol.mdx:2336already teaches the new grammar (landedby D1) — left untouched.
Fences honoured:
content/docs/releases/**(v14/v16/v17 carry compound-era text) nottouched; no CHANGELOG touched; no code, no
packages/**.Verification
All gates run on the final commit
e68376d4and quoted by their own verdict lines; exitcodes captured before any pipe. Family list self-derived by
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack(change set: 2paths, committed 2 / working tree 0) — 24 matched families, all green, plus
check:nul-bytes:check:error-status-conformance— "✓ every derivable runtime status is documented, and every documented status is reachable." (the gate that owns this exact page)check:docs-audit-scope— "✓ docs-accuracy-audit scope is in sync with content/docs/: 189 hand-written doc(s)." · "✓ release-owned pages are in scope and read-only: 9 page(s)"check:doc-authoring— "✓ doc authoring guard: 390 files clean — no bare metadata literals."check:doc-anchors— "✅ 278 internal #fragment link(s) across 408 source file(s) all resolve to a real heading"check:doc-route-spelling— "✓ route-spelling guard: population clean — every shape-matched literal spells its ledger row."@objectstack/spec check:skill-examples— "✅ 260 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them" (this is what type-checks the editedclient-sdk.mdxexample against the real built@objectstack/clientdeclarations)check:doc-frontmatter,check:docs-single-h1,check:docs-redirects,check:docs-section-name,check:section-landing-index,check:published-readme-links,check:role-word,check:react-page-adapter-contract,check:cross-package-test-inputs,check:ci-filter-parity,spec check:docs/liveness/empty-state/variant-docs/strictness-ledger,lint check:doc-formula-expressions/doc-security-posture— all exit 0check:nul-bytes— "OK (scanned 6852 text file(s) … no raw ASCII control bytes)"Four gates first exited 1 with "PREREQUISITE NOT MET — nothing was measured" (missing
packages/spec/json-schema, unbuiltspec/lint/formula/client-reactdist). Thosewere build-artifact prerequisites, not findings; after
turbo run buildfor those packagesall four are green above.
No ablation is owed. The change is prose plus one example — there is no guard here
whose failure mode a mutation would demonstrate. The one executable artifact, the SDK
example, is covered by
check:skill-examples' semantic tsc pass rather than by a fixture Icould ablate. Stating that rather than inventing one.
No changeset: docs-only, releases no package.
check-empty-changesetexits 0 ("✓ Noempty-frontmatter changeset introduced by this diff"), and
pr-automation.yml'schangeset-checkexempts only theskip-changesetlabel — whichlint.ymlcalls theprescription for a PR that "releases nothing". Label applied.
Generated by Claude Code