Problem
run() in lib/git.ts uses execFileSync('git', args) — no shell interpretation. But many tools pass strings containing shell operators that silently break:
2>/dev/null — passed as literal git args
|| fallback — not executed, literal args
| tail -1 / | grep — literal args
&& git commit — literal args
< file — literal args
git diff ... — becomes git git diff ...
Already fixed
Still broken
| Tool |
Line(s) |
Shell syntax used |
| verify-completion |
37, 58, 83, 115, 133 |
cat, pipe, 2>/dev/null, npm run build via git |
| token-audit |
42-43, 66, 83, 142 |
2>/dev/null, wc -l <, tail -c |
| session-handoff |
11, 47 |
command -v, gh pr list ... || echo |
| audit-workspace |
39, 78 |
2>/dev/null, find ... | wc -l |
| sharpen-followup |
90 |
2>/dev/null |
| scope-work |
131 |
git ls-files | head | grep |
| enrich-agent-task |
32-56 |
2>/dev/null, head -30, grep pipes |
| sequence-tasks |
93 |
2>/dev/null |
Fix approach
For each tool:
- Replace shell-piped commands with array-arg
run() calls
- Do filtering/piping in JS (split, filter, slice)
- For non-git commands (
wc, find, cat), use Node.js fs/child_process directly
- Remove
2>/dev/null — run() already catches errors gracefully
Problem
run()inlib/git.tsusesexecFileSync('git', args)— no shell interpretation. But many tools pass strings containing shell operators that silently break:2>/dev/null— passed as literal git args|| fallback— not executed, literal args| tail -1/| grep— literal args&& git commit— literal args< file— literal argsgit diff ...— becomesgit git diff ...Already fixed
Still broken
cat, pipe,2>/dev/null,npm run buildvia git2>/dev/null,wc -l <,tail -ccommand -v,gh pr list ... || echo2>/dev/null,find ... | wc -l2>/dev/nullgit ls-files | head | grep2>/dev/null,head -30,greppipes2>/dev/nullFix approach
For each tool:
run()callswc,find,cat), use Node.js fs/child_process directly2>/dev/null—run()already catches errors gracefully