Skip to content

docs(roadmap): add #456 — doctor JSON envelope contradicts itself: discovered_files_count vs discovered_config_files use opposite definitions#3069

Open
Yeachan-Heo wants to merge 1 commit into
mainfrom
docs/roadmap-456-doctor-discovered-config-files-disagrees-with-itself
Open

docs(roadmap): add #456 — doctor JSON envelope contradicts itself: discovered_files_count vs discovered_config_files use opposite definitions#3069
Yeachan-Heo wants to merge 1 commit into
mainfrom
docs/roadmap-456-doctor-discovered-config-files-disagrees-with-itself

Conversation

@Yeachan-Heo
Copy link
Copy Markdown
Contributor

ROADMAP pinpoint #456claw doctor JSON envelope reports the same fact under two semantically-identical keys with different counts

Dogfooded for the 2026-05-24 07:30 Clawhip pinpoint nudge (message 1508009183260442777).

Repro (clean isolated workspace, no .claw.json)

mkdir -p /tmp/iso6/home /tmp/iso6/proj && (cd /tmp/iso6/proj && git init -q)
cd /tmp/iso6/proj && env -i HOME=/tmp/iso6/home PATH=/usr/bin:/bin TERM=dumb \
  claw doctor --output-format json | \
  jq '.checks[] | select(.name=="config" or .name=="workspace") | {name, summary, loaded_config_files, discovered_files_count, discovered_config_files}'

Output:

{
  "name": "config",
  "summary": "no config files present; defaults are active",
  "loaded_config_files": 0,
  "discovered_files_count": 0
}
{
  "name": "workspace",
  "summary": "project root detected on branch master",
  "loaded_config_files": 0,
  "discovered_config_files": 5
}

In the real repo where one .claw.json exists, the contradiction persists: config.discovered_files_count = 1 vs workspace.discovered_config_files = 5.

Human text envelope leaks the same contradiction:

Config
  - Config files      loaded 0/0
  - Discovered files  <none> (defaults active)

Workspace
  - Memory files     0 · config files loaded 0/5

Three different values for the same fact in one report.

Root cause (traced)

config check (rust/crates/rusty-claude-cli/src/main.rs:2180-2202):

let discovered = config_loader.discover();
let present_paths: Vec<String> = discovered
    .iter()
    .filter(|e| e.path.exists())  // <-- filters to paths that exist on disk
    .map(|e| e.path.display().to_string())
    .collect();
// …
("discovered_files_count".to_string(), json!(present_count)),

Comment at lines 2183-2186 explicitly says: "Showing non-existent paths as 'Discovered file' implies they loaded but something went wrong, which is confusing. We only surface paths that exist on disk as discovered; non-existent ones are silently omitted from the display."

workspace / status_context (rust/crates/rusty-claude-cli/src/main.rs:5759-5764):

let loader = ConfigLoader::default_for(&cwd);
let discovered_config_files = loader.discover().len();  // <-- no .exists() filter

Same discover() API, opposite definitions, both emitted under near-identical JSON keys.

Why distinct from existing items

Item Tracks
#143 Degrade-not-hard-fail on config parse failure (transport)
#322 / #447 / #450 stderr vs stdout transport
#340 type vs kind vocabulary
#449 / #451 / #452 / #453 / #454 Prompt-misdelivery & subcommand routing
#455 missing_credentials hint prose vs structured
#456 doctor JSON envelope self-consistency — two checks publish different counts for the same concept

Why it matters

doctor is the structured health surface other claws/scripts/UI panels read to decide whether a workspace is "ready". A script that branches on workspace.discovered_config_files > 0 (the most obvious key name) will believe a workspace has 5 config files when it actually has 0 — false positive on "configured workspace" detection. A script that branches on config.discovered_files_count correctly sees 0. Two equally reasonable claws produce opposite decisions reading the same envelope. The contradiction also undermines doctor as a debugging tool — humans see Discovered files <none> and config files loaded 0/5 in the same report and stop trusting the numbers.

Required fix shape (full detail in ROADMAP entry)

(a) Pick one definition of "discovered config files" — prefer "paths that exist on disk" (user-meaningful). (b) Rename the loader's raw candidate count to workspace.config_search_paths_count. (c) Consolidate both checks to read the same present_paths computation — single source of truth. (d) Regression tests across (i) empty workspace, (ii) one config file, (iii) malformed config (parse-failure path), and a parity assertion. (e) Fix the human text section so the N/M in Config and Workspace agree.

Acceptance check (one-liner)

claw doctor --output-format json | jq -e \
  '([.checks[] | select(.name=="config")][0].discovered_files_count) == ([.checks[] | select(.name=="workspace")][0].discovered_config_files)'

Should pass on any workspace.


[repo owner's gaebal-gajae (clawdbot) 🦞]

…scovered_files_count (existing-on-disk) vs discovered_config_files (raw candidate search paths)
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.

2 participants