| name | verify-claude-run-commit-vs-working-tree-before-closing |
| description | After a Claude implementation run, verify the claimed file set against the actual commit and working tree before treating the issue as fully complete. |
| version | 1.0.0 |
| author | Hermes Agent |
| category | workspace-hub |
| tags | ["claude-code","verification","git","issue-closeout","workspace-hub","learned"] |
Verify Claude run commit vs working tree before closing
When to use
Use this after a Claude Code implementation run that claims:
- files were changed and committed
- a GitHub issue was commented/closed
- verification passed
Especially important when:
- the repo has many unrelated dirty files
- pre-commit or repo-specific hooks may reject some paths
- Claude reports that some changes were applied but not committed
- the issue was closed automatically by the worker
Why this skill exists
A Claude implementation run can successfully commit and close an issue while still leaving intended edits in the working tree.
Observed failure mode:
- Claude edited the target files
- some files were blocked from commit by repo rules / hooks / file policies
- Claude still posted a success comment and closed the issue
- the uncommitted delta remained in the working tree
This means "issue closed" is not sufficient evidence that all intended changes landed.
Required checks
After the run finishes, do all of these before declaring success:
- Inspect the commit Claude claims landed
git show --stat --name-only <commit>
- Verify the commit landed in the intended checkout / branch, not just somewhere in the repo ecosystem
git rev-parse --show-toplevel
git branch --show-current
git branch --contains <commit>
- if you launched Claude from an isolated worktree, confirm the commit is actually on that worktree branch
- do not assume
workdir= or prompt text was sufficient protection
- if the commit landed on another local branch / checkout (for example dirty
main) treat the worker result as only partially integrated
- Compare that file list against the files Claude claimed to have changed in its final summary
- look for any claimed files missing from the commit stat
- Inspect current working tree for owned-path leftovers
git status --short
- look specifically for files owned by the executed issue
- ignore unrelated dirty files outside the issue's owned paths
- If a claimed file is still modified after the run:
- read it and confirm whether the intended change is present only in the working tree
- decide whether to:
- make a tiny fixup commit, or
- reopen the issue and finish properly
- Verify GitHub closeout state
- read the latest issue comments
- check whether the issue is open/closed
- if closed with residual owned-path changes still uncommitted, treat the closeout as incomplete
- if the issue comment says work landed in the isolated branch but the commit actually landed on another checkout, post a correction/update before closeout
Recovery pattern when commit lands in the wrong checkout
Observed failure mode:
- Claude was launched from an isolated worktree
- Claude reported success and produced a valid commit
- the commit actually landed on local
main instead of the intended issue worktree branch
- the intended worktree remained unchanged
Safe recovery:
- identify the real landed commit hash
- verify the diff and tests in the checkout where it actually landed
- cherry-pick that exact commit into the intended clean worktree/branch
- re-run the targeted validation in the intended worktree
- treat the clean worktree commit as the authoritative execution result for push/closeout
This is distinct from the older “residual dirty files” failure mode: the code may be correct, but it is landed in the wrong branch context and must be re-homed before integration/closeout.
Decision rules
Case A — clean success
Criteria:
- all claimed files appear in the commit
- no owned-path files remain dirty
- issue comment matches actual commit
Action:
- accept the run as complete
Case B — partial landing with residual owned-path edits
Criteria:
- some claimed files are not in the commit
- those files remain modified in the working tree
- issue may already be closed
Action:
- do NOT assume full completion
- create a tiny follow-up commit for the missing owned-path files, OR reopen the issue if the gap is material
- document the discrepancy in the next GitHub comment
Case C — false success comment
Criteria:
- worker claimed success but commit does not contain the core deliverable
Action:
- reopen or continue the issue immediately
- do not treat the run as landed
Recommended workflow
- Capture Claude’s reported outputs:
- commit hash
- changed file list
- GitHub comment URL
- issue closed/open status
- Run:
git show --stat --name-only <commit>
git status --short
gh issue view <issue> --json state,comments
- Compare three surfaces:
- Claude summary
- actual commit contents
- residual working tree state
- Only then decide whether the implementation is truly done.
Workspace-hub-specific lessons
In workspace-hub, this matters when:
- docs or generated files violate local repo conventions
- some wiki/domain files are already oversized or shaped in ways that trip repo expectations
- the run stages only a subset of the owned-path edits
- a Claude run launched from an isolated worktree may still create the commit on an unexpected local branch / checkout, even when the orchestrator passed the intended worktree as cwd
Concrete example pattern A:
- worker committed 10 files
- claimed 12 intended updates
- 2 wiki
CLAUDE.md files were still modified in working tree
- issue was already closed
- correct response was to treat the issue as substantially complete but with a small residual follow-up
Concrete example pattern B:
- orchestrator launched
claude -p from a clean issue worktree
- Claude reported success and a commit hash
- the intended issue worktree branch did not move
- the reported commit actually landed on the dirty local
main checkout instead
- correct response was:
- verify the reported commit hash really contains the claimed file set
- confirm which branch/worktree actually contains that commit
- cherry-pick the validated commit into the clean execution worktree
- re-run the targeted tests in the clean worktree
- treat the clean worktree commit as the authoritative execution artifact for push/closeout
Add these checks when the worker was supposed to run in an isolated worktree:
git branch --contains <commit> from the parent repo
git log --oneline -3 in both the intended worktree and the default/main checkout
- verify the expected issue branch tip actually advanced
If the commit landed on the wrong local branch but the diff/tests are valid, prefer cherry-picking into the clean worktree over trying to salvage closeout directly from the dirty checkout.
Validation-output hygiene before closeout
When validating generated artifacts before issue closeout, do not let high-volume generator output flood the agent context. A successful validation can still waste the remaining tool budget if the generation command prints huge JSON/CSV summaries.
Preferred pattern:
- Run generators with quiet flags when available, or redirect verbose stdout to a temporary log.
- Run the fail-closed validator separately and surface only the PASS/FAIL line plus compact counts/digests needed for evidence.
- If the generator has no quiet mode, capture a bounded summary instead of raw stdout:
uv run python scripts/generate_public_graph_manifests.py --write > /tmp/artifact-generation.log
uv run python scripts/validate_public_graph_manifests.py --artifact-dir <artifact-dir> --report-path <report-path> --repo-root .
- Preserve the full log only when it is needed to debug a failure; otherwise cite the artifact paths and validator result.
Decision rule:
- a huge successful stdout dump is not closeout evidence by itself; closeout evidence is the committed artifact set, validator PASS, tests, legal scan, adversarial review, pushed commit, and verified issue state.
Separate remote landing from parent-checkout state
Another live-use failure mode:
- Claude runs in a clean issue worktree
- the commit is pushed successfully to
origin/main
- GitHub issues auto-close correctly
- but the user's current parent checkout (
/mnt/local-analysis/workspace-hub) is still dirty and remains one commit behind remote main
This is easy to misreport as "everything is updated locally" when only the remote and worker branch are updated.
Required post-push checks when working from a side worktree:
- verify the push target really contains the commit
git fetch origin
git rev-parse <commit>
git rev-parse origin/main
git branch --contains <commit>
- separately inspect the parent/default checkout state
cd <parent-checkout>
git status --short
git rev-list --left-right --count HEAD...origin/main
- report these as two different truths:
remote landed state (did the change reach origin/main?)
current local checkout state (is the user's working checkout updated/clean?)
Decision rule:
- if remote landed but parent checkout is dirty/behind, do not say the repo is fully synced locally
- say the implementation landed remotely and the parent checkout still needs an explicit sync/reconciliation step
- avoid auto-pulling into a dirty parent checkout unless the user asked for that reconciliation work
Output template for post-run review
Use this structure when reporting your verification:
- Commit landed:
<hash>
- Issue state: open/closed
- Claimed changed files: N
- Actually committed files: N
- Residual owned-path files still dirty: list or none
- Verdict: complete / substantially complete with follow-up / incomplete
- Next action: none / tiny fixup commit / reopen and continue
Pitfalls
- Trusting the worker’s final summary without checking
git show
- Looking only at
git status and not the actual commit
- Missing residual issue-owned files because the repo has lots of unrelated dirt
- Treating an auto-closed issue as authoritative proof of completeness
Minimal command set
git show --stat --name-only <commit>
git status --short
gh issue view <issue> --json state,comments
Use this every time a Claude run claims success on a dirty repo.