docs(spec): make the SystemIdentifierSchema docblock name the surfaces it actually validates - #14194
Conversation
…und surfaces The docblock claimed eleven consuming surfaces. The per-surface census (its os-dev-report comment, measured on origin/main @ e2debee) measured exactly ONE of the eleven as validated by this schema: select option values (SelectOptionSchema.value). Eight go to SnakeCaseIdentifierSchema or an inline flat regex that forbids dots outright; event keys went to the sibling EventNameSchema, since retired unbound. Rewrite the prose to name the whole bound list as it stands today (SelectOptionSchema.value plus the three object-storage keys the old prose never claimed, recorded as bound-but-unauthored), to point each unbound surface at the schema that really validates it, and to state that these are different accept sets rather than looser spellings of one grammar. Drop the Event keys row of the naming table and the 'for events' example, both of which asserted a binding that no longer exists. Comment lines only: no regex change, no accept-set change, no .describe() change. The storage-owned length-ceiling note is carried through unchanged.
The first draft of this changeset said the docblock ships into @objectstack/spec's .d.ts and so reached consumers' editor tooltips. Measured after the build: it does not -- no emitted .d.ts or .d.cts carries any docblock from identifiers.zod.ts. The corrected note states the real audience (readers of this source, human and agent), which is the audience the card was filed for.
…entifier-docblock-truth
📓 Docs Drift CheckThis PR changes 1 package(s): 24 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 3 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 128 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin a0dfc6479b80e08b18a2b622375011a3e17b2622 && git checkout a0dfc6479b80e08b18a2b622375011a3e17b2622
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 9dd022aea05251a8bc8ee2161bd93931abd031b9 00d8f0891db21b04ee5c94887efba93f179fdd52 && git checkout -B drift-repro 9dd022aea05251a8bc8ee2161bd93931abd031b9 && git merge --no-ff 00d8f0891db21b04ee5c94887efba93f179fdd52
node scripts/docs-audit/affected-docs.mjs --json 9dd022aea05251a8bc8ee2161bd93931abd031b9
|
Fixes #13621
Clause-②: no — a docblock rewrite changes no accept or reject verdict. Declared per the triage instruction (comment 5479051953), which reads the same way, and proven mechanically below rather than asserted: the TypeScript scanner emits a byte-identical 243-token stream for
identifiers.zod.tsbefore and after this change.What this is
Prose truth restoration on
SystemIdentifierSchema's docblock inpackages/spec/src/shared/identifiers.zod.ts. The docblock claimed eleven consuming surfaces under the heading "Applies to all metadata that acts as a machine identifier". The per-surface census on #12245 — itsos-dev-reportcomment is the measurement of record, taken onorigin/mainate2debee6— measured exactly one of those eleven as validated by this schema: select option values,SelectOptionSchema.value. Eight go toSnakeCaseIdentifierSchemaor to an inline flat regex that forbids dots outright; event keys went to the siblingEventNameSchema.The census is linked, not re-derived. Two things did have to be re-read on today's tree, because the tree moved after the census was taken: PR #14158 retired
EventNameSchema(#13613) and the four branded aliases wrapping this schema (#13612). The rewritten prose states post-retirement truth.What the docblock now says
SelectOptionSchema.value(data/field.zod.ts) plus three keys the old prose never claimed at all:LifecyclePolicyRuleSchema.id,BucketConfigSchema.name,ObjectStorageConfigSchema.name(system/object-storage.zod.ts). Select option values are the only one with a real authored population; the object-storage three are recorded as bound in declaration with nothing authoring them — the census's own "nothing to census", never "censused clean"./^[a-z_][a-z0-9_]*$/sites,SnakeCaseIdentifierSchema,MetadataItemNameSchema, and — for event keys — the closedDataEventType/BulkDataEventTypeenums, which are not a grammar at all.MetadataItemNameSchemanamed:a.,a..b,a.1b,a._bare accepted here and refused there.The
Event keys | dot.notationrow of the naming-convention table and the'order.created' (for events)example both asserted a binding that no longer exists; both now state what is true. The storage-owned length-ceiling note (#12144) is carried through unchanged.Derived judgments — zero accept-set change, item by item
.regex(/^[a-z][a-z0-9_.]*$/)— untouched. Same pattern, same flags..min(2, ...)— untouched. Same floor, same message..describe(...)— untouched. This is the string the generated reference page and the JSON Schema read, so leaving it alone is what keeps the generated artifacts byte-stable..regex()message string — untouched, deliberately: it is runtime-visible output and appears in generated baselines, and it is not false (it illustrates the grammar, and it does not claim an event binding).SnakeCaseIdentifierSchema,MetadataItemNameSchema,ITEM_NAME_SEGMENTand both derived patterns are not in the diff.identifiers.zod.tsbegins with the JSDoc continuation marker, and the TypeScript scanner run with trivia skipped yields 243 tokens before and 243 after, identical position by position. Nothing a compiler or a Zod parse can observe differs. That also settles the two gates below that read built output: this diff cannot reach them.Three of the census's own out-of-scope items are honoured and not re-litigated: narrowing either regex, the dot-free question on option values, and the 46-site inline flat-grammar unification.
Verification
Gate union re-run after the final commit, at
00d8f0891(which includes a merge oforigin/maintaken minutes before push). 40 families, derived mechanically withnode scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstackrather than from the dispatch list — the derivation found 6 families the dispatch list did not name (check:objectui-changeset,check:pm-half-states,check-changeset-no-major,check-empty-changeset,pm/check-half-states,pm/release-rehearsal-clone --self-test), and all 6 are green. Exit codes captured by redirecting first and reading the status before any pipe.38 of 40 green. The two that did not produce a reading both stopped on the same precondition and printed it themselves:
node scripts/check-dev-prereqs.mjs— "The workspace is not built ... 66 of 67 workspace packages declare an entry point underdist/that is not on disk". Reads built output for the whole workspace.pnpm check:dual-build-cjs-loads— exit 3, "PREREQUISITE NOT MET ... Runpnpm buildfirst. This is NOT a pass: nothing was measured". Its self-test passed 93 cases; only the tree-wide leg was unreachable. Note this gate distinguishes 3 from a finding's 1 precisely so the two are not confused.Both are recorded as NOT MEASURED locally, not as red, and left to CI, which builds the workspace first. Item 6 above is the reason the omission is safe rather than merely convenient: the emitted bytes cannot differ from a comment-only edit. Measured directly as well — no emitted
.d.tsor.d.ctsinpackages/spec/distcarries any docblock from this file, so the published type surface is untouched (and the changeset says so; an earlier draft of it claimed the opposite and was corrected once measured).A third gate,
node scripts/check-test-completeness.mjs, exits 3 by design when run without a test log and prints "the local reading for this gate is NOT MEASURED ... It is not a red, and there is nothing here to fix". Recorded as such.Tests:
pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2— 448 test files / 12033 tests passed, run at685d54bd, the commit carrying the entire change set of this PR.origin/main(which movedpackages/spec/src/ui/component.zod.tsunderneath the branch), the run was narrowed at00d8f0891toidentifiers.test.ts,field.test.ts,object-storage.test.ts,type-alias-convention.pin.test.tsanddoor-reachability.testkit.test.ts— 5 files / 297 tests passed. Narrowing declared: a full second 12033-test pass exceeded the container's foreground window in one attempt, and the merged-in commit arrived with its own CI. CI runs the full farm on this branch regardless.pnpm --filter @objectstack/spec run typecheck— green at00d8f0891, includingcheck:test-typecheckovertsconfig.test.json, so the test layer was actually compiled and not excluded.pnpm --filter @objectstack/spec run check:docsgreen and the working tree clean after the build'sgen:schemaran: the generatedcontent/docs/references/shared/identifiers.mdxreads.describe(), not the docblock, so this change owes it no regeneration. Measured, not assumed.node scripts/check-nul-bytes.mjsgreen (7751 files), plus a direct control-character scan of both edited files.No test asserts docblock text, so nothing needed updating to match.
Changeset:
patchon@objectstack/spec.Generated by Claude Code