docs(cli): state the precondition the filePatterns glob-discovery rationale carries - #12168
Merged
Merged
Conversation
…ionale carries
`metadata-file-name.ts`'s docblock derived the generated filename from the
registry's `filePatterns` and justified it with `MetadataPlugin._loadFromFileSystem`
globbing every registered type. Every clause was true, but the precondition was
missing, so the rationale read as a universal property of the platform.
Re-measured on origin/main: `_loadFromFileSystem` is reached on exactly one
branch — `bootstrap: 'eager'` (the default) AND no `artifactSource` — and both
non-test `new MetadataPlugin(...)` sites in this repo configure an
`artifactSource: { mode: 'local-file' }`, so nothing this repo boots takes it.
All nine tracked `objectstack.config.ts` files declare their metadata in code or
declare none; `os compile` builds the artifact from `loadConfig` alone and globs
nothing. The derivation still stands, as a consistency property rather than the
discoverability property the old wording framed.
Also records the disposition on the second question the finding raised: no
end-to-end dogfood is minted for the eager path. Stated on the CLI's own read of
`filePatterns` rather than beside the registry declaration, which lives in
`packages/spec` and is not this package's to annotate.
Comment-only: no behaviour, no public surface, no schema.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HbG3rGVLjZStHQxHDtzJdJ
Contributor
📓 Docs Drift Check
What this run could not see
Coarse fallback — 23 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
This was referenced Aug 25, 2026
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 #12075
Prose only.
metadata-file-name.ts's docblock stated the glob-discovery mechanism without its precondition, so the rationale several landed cards lean on read as a universal property of the platform. It now states the precondition, and the finding's second question gets its recorded disposition.What the docblock claimed, and what it claims now
The old paragraph derived the generated filename from the registry's
filePatternsand justified it withMetadataPlugin._loadFromFileSystemglobbing every registered type "whenever no compiled artifact is configured". Every clause was true; the missing half was how many projects this repo scaffolds, ships or dogfoods actually boot that way.Re-measured on
origin/mainata11c1a57d— not inherited from the cardThe card was measured at
c804f0ca5. Everything below was re-derived from scratch; three figures came back sharper than the card's, and one correction is noted under the ownership fence.1. The branch condition.
MetadataPlugin.start(packages/metadata/src/plugin.ts:340-396) reaches_loadFromFileSystemon exactly one arm:bootstrapiseager(the default,this.options.config?.bootstrap ?? 'eager') andoptions.artifactSourceis unset. An artifact source routes eager to_loadFromLocalFile;lazyandartifact-onlynever glob at all._loadFromFileSystem(line 836) then callsmanager.loadMany(entry.type, { patterns: entry.filePatterns })per registry row, so the mechanism itself is exactly as described.2. Nothing in this repo takes that arm — stronger than the card, which measured only
standalone-stack.ts. There are exactly two non-testnew MetadataPlugin(...)sites in the tree, and both pass an artifact source:packages/runtime/src/standalone-stack.ts:712artifactSource: { mode: 'local-file', path: artifactPath }packages/cli/src/commands/serve.ts:2332(dev HMR)artifactSource: { mode: 'local-file', path: hmrArtifactPath }os devcompiles and spawnsserve;os serveandos startboot from the compiled artifact;os initwritesdev: 'objectstack dev',start: 'objectstack compile && objectstack serve',build: 'objectstack compile',validate: 'objectstack validate'.3. The population. All nine tracked
objectstack.config.tsfiles declare their metadata in code — a barrel (import * as objects from './src/objects') or a named import (objects: authIdentityObjects) — or declare no objects at all. Zero rely onfilePatterns. No config setsbootstraporartifactSourceeither.4. The discriminator, re-derived statically rather than by re-running the card's three compiles:
packages/cli/src/commands/compile.tsbuildsdist/objectstack.jsonfromloadConfigand nothing else — the file contains no glob, noreaddir, nofilePatternsreference. So a*.object.tsin the scaffold's own object directory does not reach the artifact when the barrel omits it, while a file matching no pattern does as soon as the barrel names it. Independent corroboration in the tree:packages/cli/test/init-scaffold-file-name-registry-parity.test.ts(#11598) already records the same end-to-end measurement.The bounce clause did not trigger. Nothing measured the eager path as broken — only as unreachable from anything this repo boots.
_loadFromFileSystemis intact and internally consistent; it has no caller here. The loader was not touched.The ownership fence — where the third sentence went, and why
Triage asked for the no-dogfood disposition "beside the registry's
filePatternsdeclaration". Measured, that declaration is inpackages/spec, not inpackages/metadata*:packages/spec/src/kernel/metadata-plugin.zod.ts:220declares the field; lines 666-1122 declare the values inDEFAULT_METADATA_TYPE_REGISTRY.packages/metadata/src/metadata-manager.ts:2486andpackages/metadata-protocol/src/protocol.ts:11343readentry.filePatterns; neither declares it.packages/specis read-only for this card, so the sentence was written on the CLI's own read offilePatternsinstead — a new "WhyfilePatternsgets no end-to-end dogfood" section inmetadata-file-name.ts, naming the spec-side location it is not being written at. The half deliberately not written is filed unlabelled as #12165. Triage's instruction was neither dropped nor executed on another lane's file.Verification
Verified at
8ddfb855, the final commit on this branch.pnpm --filter @objectstack/spec build— exit 0. Measured as the parity test's only workspace dependency:metadata-file-name.tsimports@objectstack/spec/kernel;generate.tsimports@oclif/core,chalkand two relative modules whose only workspace import is@objectstack/spec.pnpm --filter @objectstack/cli exec vitest run --maxWorkers=2 test/generate-file-name-registry-parity.test.ts— exit 0, 37 passed (37), 1 file.pnpm lint— full repo, not narrowed (eslint . --no-inline-config): exit 0, no findings.node scripts/pm/dispatch-gates.mjs, each exit code captured before any pipe, all exit 0:check:nul-bytes(OK (scanned 6734 text file(s) ... no raw ASCII control bytes)),check:cli-test-child-env,check:published-files,check:slot-lookup(baseline key set verified against a11c1a5: no files added),check:test-source-alias,check:type-check-coverage,check:type-source-resolution,check:query-options-erasure,check:engine-double-contract,check:cross-package-test-inputs(OK: 16 package(s) read outside themselves, all declared),check:where-matcher.No red-before state was manufactured: the change is prose, and the parity test asserts a property this PR does not move.
Declared narrowing:
pnpm --filter @objectstack/cli typecheckwas not runIt needs the 56-package dependency closure built. The shared verify lock returned
queue-timeout(exit 99 — nothing ran) on five attempts totalling 21 minutes of queue wait, so that build was not spent. The narrowing is measured rather than asserted — a scan of both files' non-trivia token streams ata11c1a57dvs8ddfb855(comments are trivia and never become nodes tsc checks), aligned-diffed:packages/cli/src/utils/metadata-file-name.ts— 149 → 149 tokens, 0 differing tokens. Entirely comment trivia;tsc --noEmitcannot observe it.packages/cli/test/generate-file-name-registry-parity.test.ts— 261 → 263 tokens; the whole difference is three string-literal texts, two of them split into'a' + 'b'(hence the addedPlusTokenand the +2 count). No identifier, type, signature, import or control-flow token moved.Both changed messages sit in
expect(value, message)argument position and are evaluated eagerly on every assertion, so all three ran in the green 37/37. Every changed byte was additionally parsed by the ESLint TypeScript parser in the full-repo run above. CI runs the real typecheck on the real closure.check:type-check-debt --re-measureis likewise CI's — it refuses outright on an unbuilt worktree, and that refusal means not measured, never not applicable.Changeset
skip-changeset. The diff is comment text plus three assertion-message strings; it publishes nothing and changes no behaviour, no public surface and no schema. The token measurement above is the evidence that there is nothing to release.Out-of-scope findings (unlabelled, unassigned, deduped, back-linked)
packages/clisites still restate thefilePatternsglob-discovery rationale without its precondition, while three siblings now carry it #12163 — twopackages/clisites still restate the rationale without its precondition (generate.ts~line 203,generate-skill.e2e.test.ts~lines 13-19 and ~48-50), while three siblings now carry it. Deliberately left alone here: triage enumerated the actionable scope as two files, and those two sites are historical narrative about theos g skill— no scaffolder exists for the extension primitive ADR-0063 names #11025 override retirement.filePatternsdeclaration lives inpackages/spec, notpackages/metadata*— the eager-path no-dogfood disposition has no note beside it #12165 — the registry'sfilePatternsdeclaration is inpackages/spec, so the disposition note triage asked for beside it has no home on this lane; also records the correction to the dispatched ownership map.Within the two files this card owns, two assertion messages that restated the same over-claim were corrected alongside the docblock (
nothing globs it, so whatever it writes is invisible to the loader, andit would validate, publish and never load). They are the only code-adjacent text in these files that asserted the unqualified form.Environment note
The container's REST channel for GitHub was unavailable from this seat (
GITHUB_TOKENis the literal stringproxy-injected;ghis not installed; aGET /repos/.../issuesreturns "GitHub access is not enabled for this session"). Dedupe searching and the label write therefore went through the MCP GitHub tools rather than the prescribed additivePOST .../labelscurl.Generated by Claude Code