Skip to content

watch: writeState discards the os.WriteFile error, and get_file_context reports confident zeros for files that do not exist #140

Description

@JordanCoin

Two small silent-failure bugs, same shape: an operation that cannot succeed reports as though it did.

1. writeState throws away its write error

watch/events.go:675:

stateFile := filepath.Join(d.root, ".codemap", "state.json")
os.WriteFile(stateFile, data, 0644)      // return value discarded
}

If that write fails — read-only .codemap, disk full, permissions, a transient error — the daemon proceeds as though state was persisted. Every hook that later calls ReadState gets the stale file or nothing, and silently falls back to a scan.

writeState is called from the debounce loop and on every control event, so a persistent failure repeats indefinitely with no signal anywhere. The daemon believes it is publishing state; nothing is.

Minimal fix: check the error and surface it once (log under d.verbose, or record it so codemap watch status can report a degraded daemon). Failing loudly once is better than failing silently forever.

2. get_file_context answers confidently about files that do not exist

Driving the MCP server against a path that is not in the repo:

$ get_file_context {"file": "totally/made/up.go"}

=== File Context: totally/made/up.go ===

IMPORTS: none (leaf file)

IMPORTED BY: none (entry point or unused)

CONNECTED: 0 files in dependency graph

No error, no caveat. The parenthetical explanations make it worse than bare zeros: "leaf file" and "entry point or unused" are assertions about a file that was never scanned and does not exist. An agent that mistypes a path, or asks about a file from a stale mental model, is told the file is a harmless leaf.

Minimal fix: check membership in the scanned inventory first and return "not found in the scanned file set" — distinguishing unknown from known-and-empty. The index already has the file list, so this is a lookup, not new machinery.

Why these are worth filing despite being small

Both are the house failure mode: a confident answer where the honest one is "I don't know" or "that failed." (2) is a near-duplicate of the --importers problem in #138 on a different surface, which suggests the fix belongs at the layer where an answer about a file is assembled, not in each command.

Related: #138 (same class, --importers), #137 (the disclosure channel these should use), #111.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions