Summary
gitwise optimize --yes --json returns {"v":2,"dry_run":false,"steps":[...],"ok":true} listing the steps it intends to run, but does not actually execute them. The same invocation without --json runs the steps and produces the expected on-disk effect.
Environment
- gitwise: 0.22.0
- git: 2.54.0
- python: 3.12.11
- platform: Darwin (macOS, aarch64)
Reproduction
In a repository without a commit-graph file:
$ find .git -name 'commit-graph*'
# (empty — no commit-graph)
$ gitwise optimize --yes --json
{"v":2,"dry_run":false,"steps":[
{"name":"commit-graph","desc":"git commit-graph write --reachable --changed-paths"},
{"name":"repack","desc":"git repack -A -d --write-bitmap-index"},
{"name":"prune","desc":"git prune (remove unreachable objects)"}
],"ok":true}
$ find .git -name 'commit-graph*'
# (still empty — no file was created)
$ gitwise audit --json | python3 -c "import sys,json; print(json.load(sys.stdin)['summary']['commit_graph'])"
False
Then the same command without --json:
$ gitwise optimize --yes
optimizing: /path/to/repo
› git commit-graph write --reachable --changed-paths ····· pending
› git repack -A -d --write-bitmap-index ················· pending
› git prune (remove unreachable objects) ················ pending
✓ commit-graph updated
✓ repack complete
✓ prune complete
summary
✓ space freed: 520KB (844KB → 324KB)
completed in 0.2s
$ find .git -name 'commit-graph*'
.git/objects/info/commit-graph # ← file now exists
$ gitwise audit --json | python3 -c "import sys,json; print(json.load(sys.stdin)['summary']['commit_graph'])"
True
Expected behaviour
gitwise optimize --yes --json should execute the steps and report the same outcome the TTY mode does (space freed, per-step status), just rendered as JSON. With dry_run: false in both the input and output, the JSON path should not behave as a dry-run.
Impact
This silently breaks any agent / automation workflow that drives gitwise in --json mode (e.g. Claude Code, scripted CI maintenance, headless cron jobs). The caller sees ok: true and assumes the optimization ran; the next gitwise audit --json still flags missing_commit_graph and there is no error to surface the discrepancy.
I suspect the same may apply to other write-mode commands that branch on --json to choose a renderer; recommend an audit of gw setup, gw clean, gw merge, gw sync, gw commit, etc. to confirm they actually invoke their write paths in JSON mode.
Suggested fix
Run the side-effectful steps regardless of --json; let the flag only control output rendering. If a dry-run path is desired, gate it on the existing --dry-run flag (already in the schema, default false).
Reported by an automated agent (Claude Code) on behalf of the operator. Happy to provide additional traces or test in a clean clone if helpful.
Summary
gitwise optimize --yes --jsonreturns{"v":2,"dry_run":false,"steps":[...],"ok":true}listing the steps it intends to run, but does not actually execute them. The same invocation without--jsonruns the steps and produces the expected on-disk effect.Environment
Reproduction
In a repository without a commit-graph file:
Then the same command without
--json:Expected behaviour
gitwise optimize --yes --jsonshould execute the steps and report the same outcome the TTY mode does (space freed, per-step status), just rendered as JSON. Withdry_run: falsein both the input and output, the JSON path should not behave as a dry-run.Impact
This silently breaks any agent / automation workflow that drives gitwise in
--jsonmode (e.g. Claude Code, scripted CI maintenance, headless cron jobs). The caller seesok: trueand assumes the optimization ran; the nextgitwise audit --jsonstill flagsmissing_commit_graphand there is no error to surface the discrepancy.I suspect the same may apply to other write-mode commands that branch on
--jsonto choose a renderer; recommend an audit ofgw setup,gw clean,gw merge,gw sync,gw commit, etc. to confirm they actually invoke their write paths in JSON mode.Suggested fix
Run the side-effectful steps regardless of
--json; let the flag only control output rendering. If a dry-run path is desired, gate it on the existing--dry-runflag (already in the schema, defaultfalse).Reported by an automated agent (Claude Code) on behalf of the operator. Happy to provide additional traces or test in a clean clone if helpful.