Found while characterizing #9701. Filed unassigned — recording, not claiming. Not fixed there: that card's declared file surface was packages/metadata/src/node-metadata-manager.ts, and this is a different defect class (a documented-vs-actual default on a public export).
Open-issue search run before filing: no hits for the MetadataPlugin watch default, and no hits for startWatching reachability.
The contradiction
MetadataPluginOptions.watch documents its own default at packages/metadata/src/plugin.ts:144:
Default: false (post PR-10e — was previously true).
The constructor implements the opposite (plugin.ts:253-263):
this.options={watch: true, ...options};// ...consteffectiveWatch=bootstrapMode==='artifact-only' ? false : (this.options.watch??true);Both spellings resolve to true: the object literal supplies watch: true when the caller omits the key, and the ?? true fallback catches an explicit undefined.
Measured on origin/main @ 2065e31, constructing the plugin with no options and reading the manager's private watcher field:
DEFAULT watcher defined? = true
DEFAULT options.watch = true
UNDEF watcher defined? = true
So the documented default and the implemented default disagree, and the implemented one attaches the watcher.
Why the drift went unnoticed
PR-10e appears to have been applied at the call sites rather than in the constructor. Both — and the only two — non-test construction sites pass watch: false explicitly:
packages/runtime/src/standalone-stack.ts:697 — "Source-file scanner OFF ... Scanning would also recursively watch the project root (incl. node_modules), which is expensive and prone to EMFILE."packages/cli/src/commands/serve.ts:1806 — "Mirror the standalone stack's dev config exactly ... no source-file scanner (redundant + EMFILE-prone)."
So no in-repo configuration exercises the default, and the drift is invisible to every test and gate.
Why it still matters
MetadataPlugin is a public export (packages/metadata/src/index.ts:14, node.ts:11). External code constructing it without naming watch — the documented-safe thing to do — gets exactly the configuration both internal call sites go out of their way to avoid: a recursive polling chokidar watch over the whole project root (usePolling: true, interval: 1000, node_modules excluded only via the default ignored).
It also switches on the exposure characterized in #9701: with watch: true the eager boot path primes every filesystem item into the TTL-free registry, and a lost watcher delivery then makes an edited or deleted metadata file serve its boot-time content for the life of the process. That characterization concluded the exposure was acceptable because no shipped configuration reaches the watcher — this default is the one thing that makes it reachable for an external consumer.
Suggested resolution
Flip the constructor default to match the documentation (watch: false), since that is the intent PR-10e recorded and the posture both call sites already assert. The two internal call sites pass watch: false explicitly and are unaffected either way.
Alternatively, if the true default is deliberate, correct the doc comment — but note it would then contradict the EMFILE rationale both call sites cite.
Related
#9701 (the characterization that surfaced this) · #9339 / PR #9656 (the sibling one-shot delivery repair in packages/metadata-fs)
Found while characterizing #9701. Filed unassigned — recording, not claiming. Not fixed there: that card's declared file surface was
packages/metadata/src/node-metadata-manager.ts, and this is a different defect class (a documented-vs-actual default on a public export).Open-issue search run before filing: no hits for the
MetadataPluginwatch default, and no hits forstartWatchingreachability.The contradiction
MetadataPluginOptions.watchdocuments its own default atpackages/metadata/src/plugin.ts:144:The constructor implements the opposite (
plugin.ts:253-263):Both spellings resolve to
true: the object literal supplieswatch: truewhen the caller omits the key, and the?? truefallback catches an explicitundefined.Measured on
origin/main@2065e31, constructing the plugin with no options and reading the manager's privatewatcherfield:So the documented default and the implemented default disagree, and the implemented one attaches the watcher.
Why the drift went unnoticed
PR-10e appears to have been applied at the call sites rather than in the constructor. Both — and the only two — non-test construction sites pass
watch: falseexplicitly:packages/runtime/src/standalone-stack.ts:697— "Source-file scanner OFF ... Scanning would also recursively watch the project root (incl. node_modules), which is expensive and prone to EMFILE."packages/cli/src/commands/serve.ts:1806— "Mirror the standalone stack's dev config exactly ... no source-file scanner (redundant + EMFILE-prone)."So no in-repo configuration exercises the default, and the drift is invisible to every test and gate.
Why it still matters
MetadataPluginis a public export (packages/metadata/src/index.ts:14,node.ts:11). External code constructing it without namingwatch— the documented-safe thing to do — gets exactly the configuration both internal call sites go out of their way to avoid: a recursive polling chokidar watch over the whole project root (usePolling: true, interval: 1000,node_modulesexcluded only via the defaultignored).It also switches on the exposure characterized in #9701: with
watch: truethe eager boot path primes every filesystem item into the TTL-free registry, and a lost watcher delivery then makes an edited or deleted metadata file serve its boot-time content for the life of the process. That characterization concluded the exposure was acceptable because no shipped configuration reaches the watcher — this default is the one thing that makes it reachable for an external consumer.Suggested resolution
Flip the constructor default to match the documentation (
watch: false), since that is the intent PR-10e recorded and the posture both call sites already assert. The two internal call sites passwatch: falseexplicitly and are unaffected either way.Alternatively, if the
truedefault is deliberate, correct the doc comment — but note it would then contradict the EMFILE rationale both call sites cite.Related
#9701 (the characterization that surfaced this) · #9339 / PR #9656 (the sibling one-shot delivery repair in
packages/metadata-fs)