Skip to content

[finding] HotReloadManager.startWatching watches nothing and logs "File watching started" at info; watchPatterns has no reader and watchHandles is never populated #12428

Description

@os-warren

Origin: measured while implementing #12340 (base cdbd920) by the os-dev run for PR #12425. Filed unassigned, recording only — the sibling declared-not-enforced defect in the same file, deliberately left out of that PR's scope.

Measurement

In packages/core/src/hot-reload.ts (located by symbol, not line):

  • HotReloadManager.startWatching(pluginName) contains no watcher. Its whole body is a guard plus this.logger.info('File watching started', { plugin, patterns: config.watchPatterns }), above the in-source note "Actual file watching would require chokidar or similar / This is a placeholder for the integration point".
  • private watchHandles = new Map() is only ever read, deleted, iterated and cleared — never set. stopWatching does this.watchHandles.get(pluginName) against a map nothing writes to, so its cleanup branch is unreachable, and the teardown loop over watchHandles.keys() always runs zero times.
  • HotReloadConfig.watchPatterns therefore has no reader that acts on it. Its only uses are the two log lines (registerPlugin and startWatching).

Why it is worth a card rather than a shrug

This is the same declared-not-enforced family as #12340, but the silence is louder in one specific way: #12340's fallback at least announced itself at debug. Here the log line says "File watching started" at info, which reads as positive confirmation that watching is live. An operator who sets enabled: true with watchPatterns and sees that line in the log has been told the opposite of what is true — nothing is watched, and no reload will ever be triggered by a file change.

Note this is a differentstartWatching from the real one in packages/metadata/src/node-metadata-manager.ts, which does poll. Same method name, different subsystem — worth stating so a reader does not resolve the wrong symbol.

Boundary

Inside the host-driven library the 2026-08-25 #11825 ruling deliberately KEPT, same as #12340. The library survives; what is in question is a parameter it declares and does not honour.

Options when triaged (not chosen here — ADR-0049 enforce-or-remove):

  1. Enforce — implement watching. Feature work with no recorded pull; the class is composed by no runtime today, so this would be building for a caller that does not exist.
  2. Refuse — make startWatching throw rather than claim success, and/or retire watchPatterns. Narrows an accept set, clause-② applies.
  3. Mark experimental — ADR-0049's second state, if watching is genuinely roadmapped.

At minimum the info log is a defect on its own terms: whatever the disposition of the feature, a placeholder should not report success.

Dedup (searched 2026-08-26): no in-tree prior art — a repo-wide grep for startWatching / File watching started / watchPatterns turns up only the implementation, its example, and the generated reference page, with no card referencing them. ⚠️ Channel caveats, declared rather than hidden: the REST issues endpoint returns 403 on this seat (#12123, reproduced this run), and search_issues returned 0 — which per #11835 is not evidence of absence on this seat. So the dedup rests on the in-tree scan alone; a PM with a working list channel should re-check before this is queued.

Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions