Skip to content

fix: make plans root-consistent from any subdirectory and fail concisely outside a repo - #28

Merged
rogerchappel merged 7 commits into
mainfrom
agent/oss-56f39972edf8-root-consistent-plan-noise-free-error
Sep 11, 2026
Merged

rogerchappel merged 7 commits into
mainfrom
agent/oss-56f39972edf8-root-consistent-plan-noise-free-error

Conversation

@rogerchappel

Copy link
Copy Markdown
Owner

Summary

  • plan previously produced different, wrong results depending on the invocation directory: git diff enumerated repo-wide root-relative paths while git ls-files --others was cwd-scoped with cwd-relative paths, so root-level untracked files were dropped and subdirectory files got wrong paths/stats (untrackedStat then diffed the wrong file).
  • collectGitDiff now resolves the repository root once via git rev-parse --show-toplevel and runs every read-only git command from that root, so any subdirectory yields the identical root-relative plan (88aedc4 test, 955a337 fix).
  • Outside a git repository the CLI no longer leaks ~140 lines of git diff usage text plus an uncaught Node stack trace: collectGitDiff returns null, main prints one stderr line atomcommit: not a git repository, exit 1, stdout empty (50775bc test, 1c7b73a fix).
  • README "What it reads" command list corrected to the exact final invocations (adds rev-parse --show-toplevel, -z markers, and the staged --cached --numstat/--stat queries that were never listed), help safety note and CHANGELOG updated, and scripts/smoke.sh extended to assert root-vs-subdirectory plan equality and the concise non-repository error end-to-end.

Commits: 7 — test(red)→fix(green) pairs for each defect, then docs/help alignment, smoke extension, changelog.
Files: src/index.js, test/cli.test.js, README.md, CHANGELOG.md, scripts/smoke.sh.

Verification

  • Tests or checks run: npm test 23/23 pass (incl. 2 new regression tests), npm run check pass, npm run smoke pass ("subdirectory-stable, and non-repository error concise"), bash scripts/validate.sh exit 0, npm run release:check exit 0, git diff --check clean.
  • Manual review completed: reproduced both defects on origin/main@43b61b2 first (subdir scan filesChanged 1 vs 2 with cwd-relative path; non-repo stderr was 143 lines incl. stack trace), confirmed fixed behavior manually from a fresh mktemp dir (--version still works outside a repo, --bogus unchanged).
  • All 7 commits verified author+committer Roger Chappel <miscanalysis@gmail.com> via git log --format='%h%x09%an%x09%ae%x09%cn%x09%ce' origin/main..HEAD before push.

Risk Level

  • Low
  • Medium
  • High

Notes: read-only planning path only; no staging/mutation, no dependency/workflow/API changes. collectGitDiff (exported) now returns null outside a repository instead of throwing a wrapped git-usage error — documented in code comment; no in-repo callers besides main.

Rollback Plan

  • Revert this PR's merge commits; no data, lockfile, or workflow changes to unwind.

Human Decision Needed

  • None
  • Maintainer review
  • Product/design decision
  • Security/privacy review
  • Other:

Running the CLI from a repository subdirectory drops root-level
untracked files and reports cwd-relative paths, so the plan disagrees
with the same repository scanned from its root. This test pins the
root-relative equality that the fix must restore.
collectGitDiff ran every git command in the invocation directory, so
git diff enumerated root-relative repo-wide paths while git ls-files
--others only saw the cwd subtree with cwd-relative paths, and
untracked stats then resolved against the wrong file. Resolve the
top level once via git rev-parse --show-toplevel and run diff,
ls-files, and per-file stat commands from that single root so any
subdirectory produces the same root-relative plan as the root.
Outside a git repository the CLI currently dumps git diff usage text
plus a Node stack trace; pin the intended contract instead: exit 1,
stdout empty, and exactly one 'atomcommit: not a git repository'
stderr line.
collectGitDiff now returns null when git rev-parse --show-toplevel
fails, and main() prints a single 'atomcommit: not a git repository'
stderr line with exit code 1 instead of letting the raw git usage
dump and Node stack trace escape through an uncaught error.
--help/--version and argument validation are unchanged and still work
outside a repository.
README 'What it reads' omitted -z markers and the staged numstat/stat
queries and did not mention the new rev-parse root resolution; the
help safety note named only diff and ls-files. Update both to match
exactly what the CLI runs, including subdirectory equivalence and the
concise non-repository error.
…checks

The fixture plan generated from docs/ must be byte-identical to the
root-generated plan, and a plan run outside any repository must exit 1
with exactly the single-line stderr, mirroring the unit regressions at
the packaged-CLI level.
@rogerchappel

Copy link
Copy Markdown
Owner Author

Automated merge note

Triage class: auto-merge

Summary: Root-consistent plan output from any subdirectory (resolve repo root via git rev-parse --show-toplevel, run all read-only git commands from it so diff/ls-files/untracked stats share one root-relative path space) plus a concise atomcommit: not a git repository stderr line and exit 1 outside a repo instead of a raw git usage dump and stack trace. Includes regression tests, README/AGENTS "What it reads" updates, CHANGELOG entry, and extended smoke checks. 5 files, +144/−17 — routine code/docs/tests, no migrations/secrets/auth/workflow/dependency changes.

Checks run: GitHub check "Repository hygiene" — SUCCESS (completed). Independent local verification at head SHA in an isolated worktree: npm test (0 failures), npm run check, npm run smoke, bash scripts/validate.sh — all pass. All 7 commits verified author+committer Roger Chappel miscanalysis@gmail.com.

Rebased / CI-repaired: No — branch clean and mergeable; BLOCKED state was review-required only (no branch protection rules on main).

Verified head SHA: 998dcbe8ebb2e370e47f7c80d963767d84794500

@rogerchappel
rogerchappel merged commit 64c5c1e into main Sep 11, 2026
1 check passed
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.

1 participant