fix(#733): diff JSON adds changed_file_count; run git diff --name-only for staged+unstaged and deduplicate into BTreeSet

This commit is contained in:
YeonGyu-Kim 2026-05-26 13:05:44 +09:00
parent 4c16a42f39
commit db80c9b96e
2 changed files with 15 additions and 0 deletions

View File

@ -7631,3 +7631,5 @@ Original filing (2026-04-18): the session emitted `SessionStart hook (completed)
731. **`claw sandbox --output-format json` returned `status:"error"` when namespace isolation is unsupported on macOS but filesystem sandbox is active — automation treating `status != "ok"` as a hard error would block on a fully-functional degraded sandbox** — dogfooded 2026-05-26 on `425d94ee`. `sandbox_json_value` derived `status:"error"` when `!status.supported` regardless of whether `filesystem_active:true` (workspace-write containment working). On macOS the typical state is `{supported:false, filesystem_active:true, active_namespace:false}` — namespace isolation is unsupported but the filesystem sandbox IS active. This is degradation, not failure. Fix: added `else if status.filesystem_active { "warn" }` branch before the hard `"error"` arm — `status:"error"` is now reserved for the case where sandbox is enabled, unsupported, AND no filesystem containment is active either. macOS default now correctly returns `status:"warn"`. Source: Jobdori dogfood on `425d94ee`, 2026-05-26. 731. **`claw sandbox --output-format json` returned `status:"error"` when namespace isolation is unsupported on macOS but filesystem sandbox is active — automation treating `status != "ok"` as a hard error would block on a fully-functional degraded sandbox** — dogfooded 2026-05-26 on `425d94ee`. `sandbox_json_value` derived `status:"error"` when `!status.supported` regardless of whether `filesystem_active:true` (workspace-write containment working). On macOS the typical state is `{supported:false, filesystem_active:true, active_namespace:false}` — namespace isolation is unsupported but the filesystem sandbox IS active. This is degradation, not failure. Fix: added `else if status.filesystem_active { "warn" }` branch before the hard `"error"` arm — `status:"error"` is now reserved for the case where sandbox is enabled, unsupported, AND no filesystem containment is active either. macOS default now correctly returns `status:"warn"`. Source: Jobdori dogfood on `425d94ee`, 2026-05-26.
732. **`claw status --output-format json` `allowed_tools.entries` was `null` when no `--allowed-tools` flag was passed — callers doing `.allowed_tools.entries | length > 0` or trying to iterate got a null-dereference instead of an empty array** — dogfooded 2026-05-26 on `29dcd478`. `allowed_tool_entries` was computed as `allowed_tools.map(|tools| tools.iter().cloned().collect())``None` when unrestricted, serialized to JSON `null`. Fix: `.unwrap_or_default()` so unrestricted invocations emit `entries: []` instead of `entries: null`. Callers can now use `.entries | length > 0` uniformly without a null guard. Source: Jobdori dogfood on `29dcd478`, 2026-05-26. 732. **`claw status --output-format json` `allowed_tools.entries` was `null` when no `--allowed-tools` flag was passed — callers doing `.allowed_tools.entries | length > 0` or trying to iterate got a null-dereference instead of an empty array** — dogfooded 2026-05-26 on `29dcd478`. `allowed_tool_entries` was computed as `allowed_tools.map(|tools| tools.iter().cloned().collect())``None` when unrestricted, serialized to JSON `null`. Fix: `.unwrap_or_default()` so unrestricted invocations emit `entries: []` instead of `entries: null`. Callers can now use `.entries | length > 0` uniformly without a null guard. Source: Jobdori dogfood on `29dcd478`, 2026-05-26.
733. **`claw diff --output-format json` returned no `changed_file_count` field — callers seeing `result:"changes"` had to parse the raw `staged`/`unstaged` diff text to count affected files** — dogfooded 2026-05-26 on `4c16a42f`. `render_diff_json_for` ran `git diff --cached` and `git diff` and exposed them as raw strings but didn't compute a file count. Fix: run two additional `git diff --name-only` passes (staged + unstaged), deduplicate across both sets using a `BTreeSet`, and expose `changed_file_count: usize` in the envelope. Clean repos emit `changed_file_count: 0`, dirty repos emit the true unique-file count. Source: Jobdori dogfood on `4c16a42f`, 2026-05-26.

View File

@ -7973,12 +7973,25 @@ fn render_diff_json_for(cwd: &Path) -> Result<serde_json::Value, Box<dyn std::er
} }
let staged = run_git_diff_command_in(cwd, &["diff", "--cached"])?; let staged = run_git_diff_command_in(cwd, &["diff", "--cached"])?;
let unstaged = run_git_diff_command_in(cwd, &["diff"])?; let unstaged = run_git_diff_command_in(cwd, &["diff"])?;
// #733: add changed_file_count so callers don't have to count diff hunks
let staged_files =
run_git_diff_command_in(cwd, &["diff", "--cached", "--name-only"]).unwrap_or_default();
let unstaged_files = run_git_diff_command_in(cwd, &["diff", "--name-only"]).unwrap_or_default();
let mut changed: std::collections::BTreeSet<&str> = std::collections::BTreeSet::new();
for line in staged_files.lines().chain(unstaged_files.lines()) {
let t = line.trim();
if !t.is_empty() {
changed.insert(t);
}
}
let changed_file_count = changed.len();
Ok(serde_json::json!({ Ok(serde_json::json!({
"kind": "diff", "kind": "diff",
"action": "diff", "action": "diff",
"status": "ok", "status": "ok",
"working_directory": cwd.display().to_string(), "working_directory": cwd.display().to_string(),
"result": if staged.trim().is_empty() && unstaged.trim().is_empty() { "clean" } else { "changes" }, "result": if staged.trim().is_empty() && unstaged.trim().is_empty() { "clean" } else { "changes" },
"changed_file_count": changed_file_count,
"staged": staged.trim(), "staged": staged.trim(),
"unstaged": unstaged.trim(), "unstaged": unstaged.trim(),
})) }))