Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ All notable changes to SuperBased Observer are documented here.

## [Unreleased]

### Changed

- **perf(watcher): reuse the live root map during file dispatch** — avoids
re-scanning every detected adapter on each poll/write re-dispatch, reducing
steady-state watcher CPU during high-churn session files.

## [1.32.0] — 2026-08-26

### Fixed
Expand Down
3 changes: 3 additions & 0 deletions internal/watcher/watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,9 @@ func (w *Watcher) pollCursors(ctx context.Context) error {
// The registry is still queried per call so dynamically-added
// adapters appear without restarting Watch.
func (w *Watcher) adapterFor(path string) adapter.Adapter {
if byRoot := w.snapshotByRoot(); len(byRoot) > 0 {
return adapterForPath(byRoot, path)
}
byRoot := map[string]adapter.Adapter{}
for _, a := range w.registry.Detected(w.allow) {
for _, root := range a.WatchPaths() {
Expand Down
12 changes: 12 additions & 0 deletions internal/watcher/watcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,18 @@ func TestNewClampsNegativePollInterval(t *testing.T) {
}
}

func TestAdapterForUsesLiveRootIndex(t *testing.T) {
t.Parallel()
w, _, root := setup(t)
stub := &stubRetryAdapter{name: "stub", root: root}
w.byRoot = map[string]adapter.Adapter{root: stub}

got := w.adapterFor(filepath.Join(root, "nested", "value.stub"))
if got != stub {
t.Fatalf("adapterFor used registry scan instead of live root index: got %T want %T", got, stub)
}
}

// TestCodexShortSessionMultiPassIngest reproduces the live failure mode
// reported 2026-05-06: a short ChatGPT-auth Codex rollout grows in three
// chunks (leading prompts, then function_call + token_count, then final
Expand Down