watch_directory registers but ingests nothing: 0 episodes across 15h, 42 non-merge commits, and a controlled probe save
Version: 1.1.1 (1.1.2 available, not installed)
OS: Windows 11 Pro 10.0.26200 (host TZ GMT Standard Time, UTC+01:00 — all times below are UTC)
Backend: memdb
Daemon: headless, started 2026-08-12T18:21:52Z, uptime ~17h at time of testing
Summary
A watch is registered for the correct repo and the correct branch, two seconds after the daemon
started, the daemon is alive and responsive, every other MCP call is healthy — and the watcher has
produced zero episodes in the ~17 hours since. This is not the enumeration hang of #70; all
aggregate calls are currently instant (see "Secondary observation" below). It is specifically the
live-ingest path.
daemon start: 2026-08-12T18:21:52Z
watch registered: 2026-08-12T18:21:54Z (+2s — created at startup, not a stale persisted entry)
latest episode: 2026-08-12T11:11:44Z (7h BEFORE the daemon started)
Because the watch is created fresh at daemon startup, there is no restart-persistence confound:
this is not a stale registry entry whose OS-level subscription was lost. It is a freshly created
watch that never ingests.
Expected vs actual
Per the watch_directory tool description, two event classes should produce episodes:
- Source file saves → a
working_tree episode, "within ~1 second of saving"
- Git ref changes (commits, pulls, rebases) → a
git_commit episode
Observed: neither occurs. No episode of either type has been created since the watch started.
Registered watch (from list_watched_paths)
{
"repo_id": "my-repo",
"branch": "feature/my-branch",
"path": "\\\\?\\C:\\Users\\USER\\Coding\\my-repo",
"origin": "manual",
"started_at": "2026-08-12T18:21:54.661928500Z"
}
12 watches total, 12 distinct repo_ids, all \\?\-prefixed, no plain-path twins — i.e. the
path-duplication issue discussed in #70 is not present here.
Evidence
get_repository_stats — the two branch scopes disagree exactly as you'd expect if ingest were dead
branch: "master" (the indexed branch):
{"episode_count":1257, "last_episode_time":"2026-08-12T11:11:44.811304+00:00",
"last_episode_type":"working_tree", "last_indexed":"2026-08-12T11:13:03.886170900Z",
"indexing_incomplete":false, "total_nodes":41834, "total_edges":44852,
"community_count":438, "symbol_node_count":9079}
branch: "feature/my-branch" (the watched branch):
{"episode_count":0, "last_episode_time":null, "last_episode_id":null, "last_episode_type":null,
"last_indexed":"2026-08-12T21:21:43.717955700+00:00",
"indexing_incomplete":true, "total_nodes":1, "total_edges":0,
"symbol_node_count":0, "nodes_by_kind":{"Repository":1}}
Note the branch scope exists and was created at 21:21:43Z (roughly when the branch was checked
out) — so branch detection works — but it contains only the Repository node. indexing_incomplete: true correctly flags it, which is good behaviour and made the diagnosis possible.
Git activity the watcher should have seen
Since started_at (2026-08-12T18:21:54Z), on the watched path:
- 49 commits across all refs
- 42 of those are non-merge commits on the checked-out branch
The 42 matters: watch_directory's docs say "Git operation guards prevent noisy intermediate
episodes during rebases and merges", so suppressed merge commits would be by design. These 42 are
ordinary commits and are not covered by that guard.
Controlled probe — a plain save, not a merge, not a worktree
To rule out git-operation guards entirely, I wrote a new source file directly in the watched tree:
// web/js/_memtrace_watch_probe.js
export function memtraceWatchProbeFunction239() {
return 'probe';
}
- Path is inside the watched root, is not
.gitignored, is a supported language (JavaScript)
- Written at
10:56:59Z; waited 25 seconds (25× the documented ~1s latency)
Result:
find_symbol("memtraceWatchProbeFunction239", repo_id="my-repo") → 0 matches
branch scope: episode_count still 0, last_episode_time still null,
last_indexed still 2026-08-12T21:21:43Z (did not advance by even 1s)
The probe file was removed afterwards.
Caveat, stated honestly: I waited 25 s, not 25 min, so an extremely slow indexer is not formally
excluded. Against that: last_indexed did not advance at all, which I'd expect to move first.
What I ruled out
| Hypothesis |
Status |
| Enumeration hang (#70) wedged the daemon |
Ruled out — all calls instant, see below |
\\?\ path duplication |
Ruled out — 12 watches, 12 distinct repo_ids, 0 plain-path twins |
| Merge-commit guards suppressing episodes |
Insufficient — 42 non-merge commits also produced nothing |
| Work happening in ignored worktrees |
Insufficient — true (.claude/ is gitignored, so agent worktrees are invisible), but the probe save was in the main checkout |
| Wrong branch scope |
Ruled out — the watch is registered on exactly the checked-out branch |
| Daemon dead / unresponsive |
Ruled out — memcore-server at 58% of one core, all MCP calls responsive |
| Stale watch entry persisted from a previous daemon run |
Ruled out — watch registered 2 s after daemon start; created fresh, not inherited |
Secondary observation — #70's enumeration hang does NOT reproduce on this daemon
Worth recording because it contradicts earlier reports on this same version:
list_indexed_repositories returned instantly, with the full list — on 1.1.1, the version
previously observed hanging >120 s (and aborting at 300 s on 1.1.0 with zero log output)
get_repository_stats(my-repo, master) then returned instantly — and critically, this was
after the enumerate call, on the same daemon. So the "one enumerate call permanently poisons the
aggregate path until restart" model does not reproduce
- No version change was involved (still 1.1.1). Daemon uptime ~15 h, started fresh
Suggestion: any future "still broken on version X" report for #70 should record daemon uptime and
whether a restart preceded the test, since the failure appears state-dependent rather than
version-determined.
Additional note: no daemon log
There is no memcore-server.log at <repo>/.memdb/ (the directory contains only
.memtrace-store-scope.json) nor under ~/.memtrace/. ~/.memtrace/rail-telemetry.jsonl is being
written actively (records of shape
{action, mode, surface, reason, message, intent, mapped_tool}) but records tool-routing decisions,
not watcher or ingest activity. So there is no server-side log to attach for the watcher path.
Questions
- Is there a way to inspect watcher health at runtime — a counter of received FS events vs episodes
created — to tell "no events received" apart from "events received, ingest failing"? That is the
single fact needed to localise this, and it is currently unobservable from outside.
- Should
list_watched_paths expose last_event_at / episodes_created per watch? A watch that is
registered but ingesting nothing is currently indistinguishable from a healthy idle one — which
is why this went unnoticed for 17 hours.
- On Windows, are
\\?\-prefixed extended-length paths fully supported by the FS-notification
layer? All 12 watches here are stored \\?\-prefixed. The registration clearly accepts them; it is
less obvious that the underlying watcher subscribes successfully with that prefix. This is a guess,
flagged as such — I have no direct evidence for it, only that it is the most conspicuous difference
between this setup and a POSIX one.
- Is there a server-side log for the watcher path? None was found (see above), so there is nothing
to attach showing whether FS events arrive at all.
A hypothesis I raised and then disproved, recorded so nobody re-derives it: that the watch registry
is persisted across restarts while the OS-level watcher is not re-established. It is false here — the
watch is created 2 s after daemon start, not inherited from a previous run. (The apparent 1-hour gap
that suggested otherwise was a timezone artifact: PowerShell's Get-Process ... StartTime returns
local time, while list_watched_paths.started_at is UTC, and this host is UTC+01:00.
Converting both to UTC collapses the gap to 2 seconds. Worth watching for in any Windows report.)
watch_directoryregisters but ingests nothing: 0 episodes across 15h, 42 non-merge commits, and a controlled probe saveVersion: 1.1.1 (1.1.2 available, not installed)
OS: Windows 11 Pro 10.0.26200 (host TZ
GMT Standard Time, UTC+01:00 — all times below are UTC)Backend:
memdbDaemon: headless, started
2026-08-12T18:21:52Z, uptime ~17h at time of testingSummary
A watch is registered for the correct repo and the correct branch, two seconds after the daemon
started, the daemon is alive and responsive, every other MCP call is healthy — and the watcher has
produced zero episodes in the ~17 hours since. This is not the enumeration hang of #70; all
aggregate calls are currently instant (see "Secondary observation" below). It is specifically the
live-ingest path.
Because the watch is created fresh at daemon startup, there is no restart-persistence confound:
this is not a stale registry entry whose OS-level subscription was lost. It is a freshly created
watch that never ingests.
Expected vs actual
Per the
watch_directorytool description, two event classes should produce episodes:working_treeepisode, "within ~1 second of saving"git_commitepisodeObserved: neither occurs. No episode of either type has been created since the watch started.
Registered watch (from
list_watched_paths){ "repo_id": "my-repo", "branch": "feature/my-branch", "path": "\\\\?\\C:\\Users\\USER\\Coding\\my-repo", "origin": "manual", "started_at": "2026-08-12T18:21:54.661928500Z" }12 watches total, 12 distinct
repo_ids, all\\?\-prefixed, no plain-path twins — i.e. thepath-duplication issue discussed in #70 is not present here.
Evidence
get_repository_stats— the two branch scopes disagree exactly as you'd expect if ingest were deadbranch: "master"(the indexed branch):{"episode_count":1257, "last_episode_time":"2026-08-12T11:11:44.811304+00:00", "last_episode_type":"working_tree", "last_indexed":"2026-08-12T11:13:03.886170900Z", "indexing_incomplete":false, "total_nodes":41834, "total_edges":44852, "community_count":438, "symbol_node_count":9079}branch: "feature/my-branch"(the watched branch):{"episode_count":0, "last_episode_time":null, "last_episode_id":null, "last_episode_type":null, "last_indexed":"2026-08-12T21:21:43.717955700+00:00", "indexing_incomplete":true, "total_nodes":1, "total_edges":0, "symbol_node_count":0, "nodes_by_kind":{"Repository":1}}Note the branch scope exists and was created at
21:21:43Z(roughly when the branch was checkedout) — so branch detection works — but it contains only the
Repositorynode.indexing_incomplete: truecorrectly flags it, which is good behaviour and made the diagnosis possible.Git activity the watcher should have seen
Since
started_at(2026-08-12T18:21:54Z), on the watched path:The 42 matters:
watch_directory's docs say "Git operation guards prevent noisy intermediateepisodes during rebases and merges", so suppressed merge commits would be by design. These 42 are
ordinary commits and are not covered by that guard.
Controlled probe — a plain save, not a merge, not a worktree
To rule out git-operation guards entirely, I wrote a new source file directly in the watched tree:
.gitignored, is a supported language (JavaScript)10:56:59Z; waited 25 seconds (25× the documented ~1s latency)Result:
The probe file was removed afterwards.
Caveat, stated honestly: I waited 25 s, not 25 min, so an extremely slow indexer is not formally
excluded. Against that:
last_indexeddid not advance at all, which I'd expect to move first.What I ruled out
\\?\path duplication.claude/is gitignored, so agent worktrees are invisible), but the probe save was in the main checkoutmemcore-serverat 58% of one core, all MCP calls responsiveSecondary observation — #70's enumeration hang does NOT reproduce on this daemon
Worth recording because it contradicts earlier reports on this same version:
list_indexed_repositoriesreturned instantly, with the full list — on 1.1.1, the versionpreviously observed hanging >120 s (and aborting at 300 s on 1.1.0 with zero log output)
get_repository_stats(my-repo, master)then returned instantly — and critically, this wasafter the enumerate call, on the same daemon. So the "one enumerate call permanently poisons the
aggregate path until restart" model does not reproduce
Suggestion: any future "still broken on version X" report for #70 should record daemon uptime and
whether a restart preceded the test, since the failure appears state-dependent rather than
version-determined.
Additional note: no daemon log
There is no
memcore-server.logat<repo>/.memdb/(the directory contains only.memtrace-store-scope.json) nor under~/.memtrace/.~/.memtrace/rail-telemetry.jsonlis beingwritten actively (records of shape
{action, mode, surface, reason, message, intent, mapped_tool}) but records tool-routing decisions,not watcher or ingest activity. So there is no server-side log to attach for the watcher path.
Questions
created — to tell "no events received" apart from "events received, ingest failing"? That is the
single fact needed to localise this, and it is currently unobservable from outside.
list_watched_pathsexposelast_event_at/episodes_createdper watch? A watch that isregistered but ingesting nothing is currently indistinguishable from a healthy idle one — which
is why this went unnoticed for 17 hours.
\\?\-prefixed extended-length paths fully supported by the FS-notificationlayer? All 12 watches here are stored
\\?\-prefixed. The registration clearly accepts them; it isless obvious that the underlying watcher subscribes successfully with that prefix. This is a guess,
flagged as such — I have no direct evidence for it, only that it is the most conspicuous difference
between this setup and a POSIX one.
to attach showing whether FS events arrive at all.
A hypothesis I raised and then disproved, recorded so nobody re-derives it: that the watch registry
is persisted across restarts while the OS-level watcher is not re-established. It is false here — the
watch is created 2 s after daemon start, not inherited from a previous run. (The apparent 1-hour gap
that suggested otherwise was a timezone artifact: PowerShell's
Get-Process ... StartTimereturnslocal time, while
list_watched_paths.started_atis UTC, and this host is UTC+01:00.Converting both to UTC collapses the gap to 2 seconds. Worth watching for in any Windows report.)