docs(spec): name every accepted key in the two action convention docblocks - #16246
Conversation
…locks
`_actions` and `globalActions` are built from one factory,
`actionTranslationSchema(...)`, so their hand-written convention lists carried
the identical four addresses and the identical two omissions: `description` and
`params.<param_name>.{label, helpText, placeholder, options}` were declared and
accepted by the schema but named by neither list.
Both lists now enumerate them, in the factory's declaration order and in the
spelling already landed in `i18n-resolver.ts`'s own header. Prose only — no
schema, factory or resolver is touched, and nothing about what a bundle
validates to moves.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T6HeZvT9wdSJD1ZxJb5Eno
📓 Docs Drift Check2 anchor(s) derived from 1 changed package(s); no hand-written page names any of them, so this run has nothing to list — not a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run. What this run could not see
Coarse fallback — 130 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 c307cd52557e8f404458b89706b4675217284d3f && git checkout c307cd52557e8f404458b89706b4675217284d3f
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin e270ebb791d6a1eb17f4c494b83077bb1f157f57 a6879f8b6447b460626570357c34639df163ac8e && git checkout -B drift-repro e270ebb791d6a1eb17f4c494b83077bb1f157f57 && git merge --no-ff a6879f8b6447b460626570357c34639df163ac8e
node scripts/docs-audit/affected-docs.mjs --json e270ebb791d6a1eb17f4c494b83077bb1f157f57 |
Fixes #14708
_actionsandglobalActionsare built from one factory,actionTranslationSchema(...)— the file says so outright, "Shared by object_actionsandglobalActions" — so their hand-written convention lists carried the identical four addresses and the identical two omissions. An author reading either list to learn which keys exist saw a strict subset of what the schema has accepted all along.Placeholders below are written as bare words (OBJECT / ACTION / PARAM / VALUE) because the body sanitizer eats angle-bracket fragments. The file itself keeps its own angle-bracket spelling, unchanged.
What changed
Ten added comment lines in one file,
packages/spec/src/system/translation.zod.ts, plus a changeset. Both lists now name, in the factory's declaration order and in the spelling already landed ini18n-resolver.ts's own file header (PR #14707):description, afterlabelparams.PARAM.label,.helpText,.placeholder,.options.VALUE, beforeresultDialog.*Nothing else. No schema, no factory, no resolver.
resultDialog.*keeps its position and its wildcard — its leaves are enumerated atActionResultDialogTranslationSchema's own docblock, which is the file's existing convention for a nested sub-schema that documents itself.Both sites were re-located by pattern, not by the line numbers in the card or the claim comment; both of those had already rotted.
Does this move the contract? No — measured, not assumed
The keys were already declared and already accepted, so nothing about what a bundle validates to moves. The one measurable precondition on that verdict is whether the text projects into a generated artifact. It does not, and the control was reproduced on this file's own generated page,
content/docs/references/system/translation.mdx:.describe()string "Action translations keyed by action name".describe()string "Global action translations keyed by action name"The third and fourth rows are the sharp pair: the
.describe()string is a prefix of the docblock's opening sentence, so the same words score 3 as a describe string and 0 the moment the docblock-only suffix is included..describe()reaches the page; the docblock does not.Mechanically confirmed:
pnpm --filter @objectstack/spec check:generatedreports all 15 checked-in generated artifacts up to date after the edit —check:docs,check:api-surface,check:authorable-surfaceand the rest — so zero regeneration is owed.Where the text does land, which is why a changeset is owed.
packages/specpublishessrc/**/*.zod.tsthrough itspackage.jsonfilesarray, and the build output preserves JSDoc: 9 of 22 emitted.jschunks and 1 of 64 emitted declaration files carry the new lines. All three are comment positions, andcheck:api-surfaceis green, so no export signature moved. Documentation-only,patch.Verification
Run at
a6879f8b6, the branch tip.pnpm --filter @objectstack/spec buildpnpm --filter @objectstack/spec check:generatedpnpm --filter @objectstack/spec typechecktsc --noEmit,check:scripts-typecheck,check:test-typecheck)scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack--ranpnpm check:nul-byteseslint . --no-inline-config --format jsoncheck:i18n-walk-parityis the family most directly about this file: green, "11 declared group(s), 8 walked, 3 exempted — every declared group has an extractor face."Two gates first returned
PREREQUISITE NOT METand were read as NOT MEASURED rather than as findings —check:doc-formula-expressions(exit 3, unbuilt@objectstack/formulaand@objectstack/lint) andcheck:i18n-walk-parity(exit 1, unbuilt@objectstack/cli). Both prerequisites were built and both gates re-run green; the numbers above are the re-runs. Every exit code was captured before any pipe.Declared narrowings, both handed to CI:
pnpm check:dual-build-cjs-loads— the one derived family not run. Its prerequisite is a whole-repopnpm build; it named 86 unbuilt packages and measured nothing. This diff changes noexportsmap, no package manifest and no emitted module format.turbo ls --affectedagainst the merge base lists roughly 45 packages, all downstream of@objectstack/specand all reached only through its build output. Ran the five translation and action test files rather than all 482 spec test files or any downstream package.The lint reading needed no narrowing at all: the full population, 6196 files as counted by eslint itself, was linted.
Not in scope
Triage names the mechanism behind this card: both lists are hand-maintained prose copies of what one factory declares, and nothing binds them, which makes the docblocks a fourth consumer of one declaration alongside the resolver and the i18n extractor. That class belongs to #14653, which is untouched by this PR and stays open. Out-of-scope findings from this run: none.
Generated by Claude Code