Skip to content

fix(core): watch new config files and directories - #46925

Open
opencode-agent[bot] wants to merge 3 commits into
v2from
config-create-watch
Open

fix(core): watch new config files and directories#46925
opencode-agent[bot] wants to merge 3 commits into
v2from
config-create-watch

Conversation

@opencode-agent

@opencode-agent opencode-agent Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Issue for this PR

Reported by nexxel; no separate issue.

Type of change

  • Bug fix

What does this PR do?

Creating a project's first opencode.json(c) or .opencode/ directory could require /restart. Files written after discovery but before a new native watch attached could also be missed.

  • Discover eligible filesystem sources separately from loading documents. ConfigDiscovery.discover returns source paths; ConfigWatch.plan is a pure grouped-watch planner. No mutable watch targets are hidden inside discovery.
  • Watch missing direct files and .opencode roots non-recursively through their parents. Keep recursive watches limited to existing config roots.
  • Use FiberMap for running watch consumers and teardown, including deleting/recreating config directories.
  • Add an optional watcher readiness callback, invoked only after native acquisition and listener registration. It queues a rescan to recover writes made during acquisition; it does not publish fake filesystem events.
  • Subscribe to the private rescan feed eagerly, before starting any watches, so synchronous initial readiness signals cannot be dropped by the debounce worker.

There are no added runtime sleeps or startup-delay workarounds. The old 10/50 ms startup sleeps were removed from the config-creation tests. Existing precedence, global/project exclusions and {file:...} refresh behavior remain intact.

How did you verify your code works?

  • bun test test/config test/filesystem/watcher.test.ts test/instruction-discovery.test.ts test/session-activation.test.ts from packages/core: 178 passed.
  • 50 repeated passes across the two deterministic readiness regressions and eight native file/directory lifecycle cases.
  • Both race regressions went red before their fixes: one pauses directory acquisition, writes the first config without emitting a file event, then resumes; the other writes synchronously inside initial native acquisition. Neither uses setup sleeps.
  • Tests also cover updates buffered during readiness, unavailable/cancelled acquisition, pure watch plans, and grouped subscription ownership. The Mercurial native test now waits on real watcher readiness rather than probe writes.
  • bun typecheck, Prettier and git diff --check: passed. Scoped lint: no errors; existing warnings only.
  • The separate plugin periodic-refresh test still has a failure reproduced on the unchanged earlier baseline; it is not included in the passing count above.

Benchmark

script/benchmark-config-watch.ts snapshots Config, discovery, watch planning and watcher sources. Compare --ref 02f8009b47 (before readiness/refactor) with --ref working, from packages/core.

Linux, Bun 1.3.14; warm Config-only construction, not full app startup. Fixtures contain one root config and an empty .opencode, with discovery clamped to the fixture root. Depth is below that root (two additional scanned directories). Retained heap includes one change observer per location. RSS is too noisy to interpret. Construction is one directional sample; reload is the median of three and includes the existing 100 ms debounce.

Before → after this readiness refactor:

Locations / depth Retained heap MiB Construction ms Reload median ms
1 / 0 0.43 → 0.57 10 → 8 108 → 109
1 / 20 0.74 → 0.82 34 → 19 117 → 119
1 / 60 1.11 → 1.07 53 → 46 136 → 140
20 / 20 9.85 → 9.65 382 → 384 229 → 215
100 / 20 44.97 → 43.22 1,743 → 1,667 645 → 572
100 / 60 100.78 → 94.82 4,177 → 4,363 1,574 → 1,497

These fixtures performed two initial scans per location: the first load plus a readiness rescan. Startup CPU/call counts and memory include settling that work. At the 100-location/60-level extreme, process CPU through settling increased from 6.31 to 7.37 seconds. Native/kernel watch counts were unchanged (163 at that extreme), and every subscription was released after closure.

Normal one/few-location overhead remains small. Many deeply nested live locations, especially with churn inside .opencode, remain the expensive case. Unrelated project-file bursts triggered zero discoveries. Config-root changes still rescan to preserve file substitutions; no dependency cache or filename-only reload filter was added.

Existing native atomic-rename behavior, directory replacement entirely within the debounce window, and replay of missed Markdown/domain-file events are outside this JSON-config fix.

Screenshots / recordings

Not a UI change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Requested by: @nexxeln (nexxel via Slack)

@opencode-agent opencode-agent Bot changed the title fix(core): reload newly created config files fix(core): watch new config files and directories Sep 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant