Skip to content

fix(watcher): show watch state in index_status, correct auto-sync docs (#2167) - #2348

Open
DeusData wants to merge 3 commits into
mainfrom
fix/issue-2167
Open

DeusData wants to merge 3 commits into
mainfrom
fix/issue-2167

Conversation

@DeusData

Copy link
Copy Markdown
Owner

The background watcher only watches the project an open MCP session is
rooted in, and drops the watch when the last session for that project
closes. A repository indexed with cli index_repository (or from a
session rooted elsewhere) is never watched, but README promised
"Auto-sync keeps it fresh after that" for every index_repository target
and the MCP instructions said "Indexes auto-refresh". Nothing in the
status output said which projects were actually watched, so a stale
CLI-indexed repo looked like a watcher bug.

What gets watched is unchanged. Instead:

  • index_status gains a watch object: watched, plus strategy,
    poll_interval_ms and last_scan_at when watched, or a reason
    (not_session_project, cli_session, auto_watch_off, watcher_disabled,
    not_registered, no_watcher) and a re-index hint when not. It does not
    touch the feat(mcp): report truthful index freshness from checkout evidence #1561 freshness key.
  • The watcher publishes per-project strategy, cadence and last completed
    scan time through atomics and exposes them via
    cbm_watcher_project_info(); the daemon answers index_status through a
    session-scoped provider.
  • README, docs/CONFIGURATION.md, docs/index.html, the index_status tool
    description and the MCP instructions now state the real scope.

watcher_enabled already shows in config list since v0.11.0 (680bc72).


Adds a watch object to index_status next to #2346's cross_repo object (separate hunks). Follow-up noted, not in this PR: README.md:132 still says cli never connects to the daemon, which is stale on main.

Fixes #2167

DeusData added a commit that referenced this pull request Sep 30, 2026
…aemon (#2183, #2167)

README.md:132, README.md:633, README.md:761, and docs/CONFIGURATION.md:203
said one-shot `cli` commands "never start or connect to the coordination
daemon" / read "their own environment without starting the daemon". That
was already contradicted a few lines above it (README.md:126 lists
one-shot CLI commands among the processes that "share a crash-safe OS
admission barrier" with the daemon) and by the code:
main_local_cli_daemon_execute() (src/main.c) bootstraps a client
connection to the shared per-user coordination daemon via
main_client_bootstrap_with_upgrade(), spawning one (bootstrap.daemon_spawned)
when none is running, before dispatching the tool call.

Verified live: `cli --verbose list_projects` against an isolated
HOME/CBM_CACHE_DIR/CBM_RUNTIME_DIR printed "hint: this command started a
temporary CBM daemon", and its cbm-daemon.log showed
daemon.start -> daemon.runtime_stopping (reason=last_committed_client_disconnected)
-> daemon.lifetime_end, i.e. the daemon it spawned exited again once the
CLI command's own connection closed. bootstrap_production_spawn() passes
the calling process's `environ` straight to posix_spawn(), so a CLI
invocation that starts the daemon also seeds that daemon's captured
daemon-owned environment (CBM_DIAGNOSTICS, CBM_LOG_LEVEL, etc.) - it does
not read "its own environment" independently as the docs claimed.

Corrected all four passages to state the real behavior: CLI commands
connect to the shared daemon (starting one if none is running) for the
same admission barrier and per-project locks, hold a `cli_session` that
is never registered with the background watcher, and - if their own
connection is what started the daemon - that daemon exits again once the
command's connection closes and no other session is attached. No opt-out
env var or flag for an in-process/no-daemon CLI mode exists (grepped the
whole tree), so none is documented.

This is a pure documentation fix; no production behavior changed. Kept
clear of PR #2348 (fix/issue-2167), which separately rewrites the
watcher-scope paragraph at README.md:152/237/672 and
docs/CONFIGURATION.md:88 for issue #2167's auto-sync-scope correction -
none of the lines here overlap with that diff.

Refs #2183, #2167

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
#2167)

The background watcher only watches the project an open MCP session is
rooted in, and drops the watch when the last session for that project
closes. A repository indexed with `cli index_repository` (or from a
session rooted elsewhere) is never watched, but README promised
"Auto-sync keeps it fresh after that" for every index_repository target
and the MCP instructions said "Indexes auto-refresh". Nothing in the
status output said which projects were actually watched, so a stale
CLI-indexed repo looked like a watcher bug.

What gets watched is unchanged. Instead:

- index_status gains a `watch` object: `watched`, plus `strategy`,
  `poll_interval_ms` and `last_scan_at` when watched, or a `reason`
  (not_session_project, cli_session, auto_watch_off, watcher_disabled,
  not_registered, no_watcher) and a re-index hint when not. It does not
  touch the #1561 `freshness` key.
- The watcher publishes per-project strategy, cadence and last completed
  scan time through atomics and exposes them via
  cbm_watcher_project_info(); the daemon answers index_status through a
  session-scoped provider.
- README, docs/CONFIGURATION.md, docs/index.html, the index_status tool
  description and the MCP instructions now state the real scope.

`watcher_enabled` already shows in `config list` since v0.11.0 (680bc72).

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Since #1948 a non-git root can be polled by a file-tree scan when
watch_non_git is on. index_status still reported such a root as
strategy "none", which the enum documents as "not a git project: never
polled", so a root that is actively polled looked unwatched.

publish_status now maps a tree-polled root to the new
CBM_WATCHER_STRATEGY_TREE, rendered as "tree" (the value the
watcher.baseline log already uses). "none" keeps its meaning: a
registered non-git root that is never polled. CONFIGURATION.md lists
the four values.

Test: daemon_application_index_status_reports_tree_strategy_issue2167
fails without the production change and passes with it; suites
daemon_application, watcher and mcp: 507 passed, 4 platform skips.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
@DeusData

DeusData commented Oct 4, 2026

Copy link
Copy Markdown
Owner Author

Rebased onto main and extended (head 6bda6e2):

  • Rebase: feat(watcher): opt-in polling of non-git project roots (#1948) #2333 (merged) added opt-in polling of non-git roots (watch_non_git). The conflict in poll_project keeps main's commit_baselines(), and this PR's publish_status(s, false) now sits inside its git branch. That is the one place this PR published: a git project after a successful reindex and file-count refresh.
  • New commit, "report a tree-polled non-git root as strategy tree": with watch_non_git on, such a root is actively polled, but index_status reported strategy: "none", which the enum documents as "never polled". It now reports "tree" (the value the watcher.baseline log already uses). "none" keeps its meaning, and docs/CONFIGURATION.md lists git / tree / none / pending.
  • Test: daemon_application_index_status_reports_tree_strategy_issue2167 fails without the production change and passes with it.
  • Suites: daemon_application, watcher and mcp: 507 passed, 4 platform skips.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[0.10.8/Windows] Background watcher never picks up committed new files (120s+)

1 participant