Uh oh!
There was an error while loading. Please reload this page.
docs(spec): record the eager glob-discovery disposition beside filePatterns - #12575
Conversation
…tterns `filePatterns` declares a discovery contract whose glob pass nothing in this tree reaches: `MetadataPlugin._loadFromFileSystem` is entered only on an `eager` bootstrap with no `options.artifactSource`, and both non-test `new MetadataPlugin(...)` sites set one unconditionally. The recorded disposition — no end-to-end dogfood is minted for that path — had been written only on the CLI's own read of the field, because the dev that measured it held `packages/spec` read-only. This is the half that was deliberately left unwritten: a reader of the declaration itself had no pointer to the measurement. The note also fences the misreading the bare fact invites. The field's VALUES have live readers that never glob — the CLI derives every scaffolded file name from them, and `codeOnlySourceHint` reads `filePatterns[0]` back as the prescription in a 403 `not_creatable` refusal, which the `capability` and `api` entries of `DEFAULT_METADATA_TYPE_REGISTRY` already lean on. "Discovery is unexercised" is not "the field is inert", and stating only the first a few lines above those entries would have set up the second. Comment-only: no schema shape, no `.describe()` text, and the note sits inside the object literal, which `build-docs.ts` selection rules exclude from the module description — `check:docs` confirms all 229 generated files stay in sync. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E5LFCYBJ3q2s6yW6oMLxwy
📓 Docs Drift Check1 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 — 126 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 7077a9ee3cbd793f5d444fca191d33ad74877511 && git checkout 7077a9ee3cbd793f5d444fca191d33ad74877511
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 9bed0b0fe6fe3606fb23eba595bd897e5f320e8c 4c5d68ee378e3a7c69e3993b414ff5554cb6fb7d && git checkout -B drift-repro 9bed0b0fe6fe3606fb23eba595bd897e5f320e8c && git merge --no-ff 4c5d68ee378e3a7c69e3993b414ff5554cb6fb7d
node scripts/docs-audit/affected-docs.mjs --json 9bed0b0fe6fe3606fb23eba595bd897e5f320e8c |
huangyiirene
commented
Aug 26, 2026
PM review — ACCEPT ( Contract verdict: Clause-② re-checked against the real diff — no on both limbs, and the comment-only surface the claim promised is verified: a pure JSDoc insertion inside the Route (a) over close-as-covered — the dev's three grounds hold on my read: the existing pointer ran one way only (the CLI-side note explicitly says the declaration site carries nothing); recording dispositions with issue refs is already this file's genre (#8586, #7893 in the same registry); and the field's own "Used to discover metadata files on disk" line is precisely what invites the over-read. The correction the note carries — "no measured consumer" is true only of the GLOB path, while the values have live non-globbing readers (#11071's scaffold parity pin, Facts re-measured on Landing: waiting for every check green on Generated by Claude Code |
Uh oh!
There was an error while loading. Please reload this page.
Fixes#12165
Route (a) of the two the triage admitted (comment 5409942502). The 24-line note is a pure insertion into the JSDoc of the
filePatternsfield inpackages/spec/src/kernel/metadata-plugin.zod.ts. No schema shape, no.describe()text, no other file.Why a note rather than close-as-covered
The triage's actual question was whether a spec-level declaration should carry a consumer-side observation at all. Three measured things say yes here:
objectstack.config.tsin this repo reachesMetadataPlugin._loadFromFileSystem— the registryfilePatternsglob has no measured consumer, which qualifies the invisibility rationale #11071 rests on #12075's CLI-side note states in its own words that it was written on the CLI's read "rather than beside the registry declaration itself — that lives inpackages/spec/src/kernel/metadata-plugin.zod.ts, which this package only reads." A reader who arrives at the CLI note gets the whole story; a reader who arrives at the declaration had nothing pointing at it. Closing as covered leaves the half the triage on finding: noobjectstack.config.tsin this repo reachesMetadataPlugin._loadFromFileSystem— the registryfilePatternsglob has no measured consumer, which qualifies the invisibility rationale #11071 rests on #12075 asked for permanently unwritten.metadata-plugin.zod.tsrecords dispositions with measured evidence and issue references throughout — theDEFAULT_METADATA_TYPE_REGISTRYdocblock (additionalTypesonMetadataPluginConfigis authorable, documented as THE way a plugin declares a metadata type, and has no reader — a plugin cannot declare a kind at all #8586), thefieldentry (meta-field-write-inert: an acceptedfieldPUT never reaches the object — a runtime-created field is storedvalid=trueand is absent fromfieldsforever #7893), thecapabilityandapientries.packages/speccarries a no-business-logic rule, not a no-comments rule, and a comment changes no accept/reject behaviour.What was re-measured, on
origin/mainat09b4f4eMeasured here rather than copied from #12075:
MetadataPlugin._loadFromFileSystem(packages/metadata/src/plugin.ts:873, called at:395) is the only reader that globs these patterns, and_bootstrapreaches it on exactly one branch —eager(the default) andsrcunset.artifact-onlyandlazynever glob;eagerwith a source goes to_loadFromLocalFile.new MetadataPlugin(...)sites setartifactSource: { mode: 'local-file', … }unconditionally:packages/runtime/src/standalone-stack.ts:725andpackages/cli/src/commands/serve.ts:2388.git ls-files '*objectstack.config.ts'→ 9 tracked configs, all declaring metadata in code.So the glob pass has no end-to-end dogfood, and the recorded disposition is that none is being minted for it — startup focus.
The second paragraph is the load-bearing one
Stating only "no measured consumer" a few hundred lines above the
capabilityandapientries would have contradicted this file's own comments, which lean oncodeOnlySourceHintreadingfilePatterns[0]back as the prescription in a403 not_creatablerefusal. The field's values have live readers that never glob — that one, plus the CLI deriving every scaffolded file name from them (#11071, pinned bypackages/cli/test/generate-file-name-registry-parity.test.ts), plusmetadata-manager.ts:2486re-projecting them. Discovery is the unexercised use; name derivation and refusal prescriptions are not. The note says so explicitly, so the observation cannot be quoted later as "the field is inert".The generated docs tree did not move
The note sits inside an object literal, and
packages/spec/scripts/lib/file-description.tspublishes a block only when it is top-level (column 0), in the header zone, and documents no declaration — all three fail here, by two counts. Verified rather than reasoned:check:docsreports 229 generated files in sync. Nothing undercontent/docs/references/**changed, so the module-header renumbering that landed in #12551 (dd4fc6c) is not engaged. The prose sits before the@exampletag, since a TSDoc block tag would otherwise absorb it.Checks — all at the final commit
4c5d68e, tree cleanExit codes captured before any pipe; verdicts quoted from each gate's own output.
pnpm --filter @objectstack/spec buildcommand-exit 0, 34/34 declarations emittedpnpm --filter @objectstack/spec typecheckcheck:scripts-typecheck,check:test-typecheck)pnpm --filter @objectstack/spec check:docs✅ 229 generated files in sync with packages/specpnpm lint(full repo,eslint . --no-inline-config)command-exit 0— not narrowedcheck:authorable-surface·check:liveness·check:empty-state·check:strictness-ledger·check:variant-docscheck:doc-authoring·check:overlay-whitelist-table·check:spec-parsed-alias·check:doc-anchorscheck-comment-mask-adoption·check-nul-bytes·docs-audit/check-affected-docsThe gate list was re-derived from the actual change set with
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack(it reads the merge-base diff itself), then run at head after the commit.pnpm check:i18nexits 1 withPREREQUISITE NOT MET — the workspace CLI is not built("Nothing was checked: no bundle was compared and no config was parsed"). It needs a built@objectstack/cli, which a comment-only spec diff cannot move a bundle through; CI runs it with the CLI built. Recorded as unmeasured rather than passed.No changeset: comment-only, releases nothing —
skip-changeset.Draft, per dispatch: no auto-merge, PM reviews and lands.
Generated by Claude Code
Generated by Claude Code