Repository navigation
Remove the auto-push modes; full is the only behaviour - #8
Conversation
The memory loop is reliable now, so the review report and the parked
deletions only add friction. Every change under memories/, deletions
included, is committed and pushed at the end of the turn.
- Delete MEMORIES_AUTOPUSH_MODE: its prompt and settings component, the
mode resolver, the review report and dedupe state, and the review-only
PostToolUse announce hook.
- Rename /approve-memories to /resolve-memories and refocus it on what
retrying never fixes: merge rebase conflicts, rename files the guardrail
rejects, restore a missing upstream, finish a rebase left in progress.
- Pause both hooks while a rebase or merge is in progress, instead of
staging conflict markers into the half-finished rebase.
- Warn at SessionStart when the checkout has no upstream, which used to
keep memories local without a word.
- Commit as the git user with a subject that says what changed
("Ana: add learning_x", or counts plus a per-file body) instead of
"auto: memories from <hostname> <date>". The CI hostname check goes.
- Goldens re-recorded from the TypeScript (UPDATE_GOLDENS=1), each diff
reviewed; the locked-index golden keeps the macOS git wording.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Jcf1cp8tAMmCJBLywkDC1
- RESOLVE_COMMAND next to RENAME_HINT; the hooks, push loop and configure script interpolate it instead of spelling the command out eight times. - commit-message.mts: one KINDS table instead of three parallel ones, the rename arrow written once; configure builds its migration body with the shared changeLine instead of its own copy of the name stripping. - Fewer git spawns: operationInProgress asks rev-parse for all three paths at once, pull stops checking the upstream twice, and the Stop hook reads the staged set once instead of probing with diff --quiet first. - authorName drops the hostname fallback: without an identity the commit fails anyway, so the fallback only ever named a commit that never landed. - hook-io: drop the unused parseJson, keep streamValues and emitJson private, and share detail() with the push loop. No behaviour change: every golden still matches. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018Jcf1cp8tAMmCJBLywkDC1
bguidolim
left a comment
There was a problem hiding this comment.
Two inline comments: a silent skip in the auto-push commit check, and a relative-path problem in the /resolve-memories rebase check.
Generated by Claude Code
| if (commit.ok) { | ||
| committed = true; | ||
| } else { | ||
| const changes = stagedChanges(repo); |
There was a problem hiding this comment.
Staged changes can be skipped with no message. The old gate was git diff --cached --quiet. If that check failed, the code still tried the commit and git's error got printed. The new gate is stagedChanges(repo).length > 0, and stagedChanges builds its list from gitLines(... diff --cached --name-status ...) passed through parseNameStatus, dropping anything that comes back null. The list ends up empty in two cases:
- the
git diffcall itself fails, sincegitLinesreturns[] - every line has a status
parseNameStatusdoesn't handle (e.g.Ufor an unmerged path after a conflicting stash apply, orT)
When that happens, uncommitted > 0 is true but nothing is committed and nothing is reported. If unpushed is 0 the function returns quietly, and every later Stop repeats the same silent skip.
Suggested fix: gate the commit on whether anything is staged (e.g. keep diff --cached --quiet, or check !ok separately), and use changes only for the message. commitMessage already falls back to "<who>: update memories" for an empty list. Otherwise, at least say(...) something when uncommitted > 0 but no changes were parsed.
Generated by Claude Code
| - `git -C .claude/.memories-repo status --porcelain -- memories/`: dirty files | ||
| - `git -C .claude/.memories-repo rev-parse --abbrev-ref --symbolic-full-name '@{u}'`: the upstream (fails if none) | ||
| - `git -C .claude/.memories-repo rev-list '@{u}..HEAD' --count`: unpushed commits | ||
| - whether `git -C .claude/.memories-repo rev-parse --git-path rebase-merge` or `rebase-apply` exists: a rebase in progress |
There was a problem hiding this comment.
This rebase check can look in the wrong .git. git -C .claude/.memories-repo rev-parse --git-path rebase-merge returns a path relative to .claude/.memories-repo, e.g. .git/rebase-merge. Claude runs the existence check from the project root, so it ends up testing the project's own .git/rebase-merge. It can then report "Nothing to resolve." while a rebase is still in progress in the memories repo, and step 2 is never reached.
The hook code avoids this by asking for absolute paths. Suggest doing the same here:
git -C .claude/.memories-repo rev-parse --path-format=absolute --git-path rebase-merge
(same for rebase-apply). Another option is to tell Claude to resolve the result relative to .claude/.memories-repo.
Generated by Claude Code
- autopush: decide whether to commit with `diff --cached --quiet` again, and use the parsed name-status list only to word the message. An empty parse (a failed diff, or an unmerged path after a failed autostash) used to skip the commit silently on every Stop. - resolve-memories: ask rev-parse for absolute --git-path results, as the hooks do. A relative path resolves against the project root, so the check looked in the project's own .git and could report "Nothing to resolve." mid-rebase. MERGE_HEAD is checked too, and step 2 says how to finish a merge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018Jcf1cp8tAMmCJBLywkDC1
Commands now load like skills, so Claude could run this one on its own when a hook message names it. Merging conflicts and pushing to the team's repo should be the user's call: disable-model-invocation keeps it manual, and argument-hint shows the optional commit reason while typing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018Jcf1cp8tAMmCJBLywkDC1
The memory loop is reliable now, so the review report and the parked
deletions only add friction. Every change under memories/, deletions
included, is committed and pushed at the end of the turn.
mode resolver, the review report and dedupe state, and the review-only
PostToolUse announce hook.
retrying never fixes: merge rebase conflicts, rename files the guardrail
rejects, restore a missing upstream, finish a rebase left in progress.
staging conflict markers into the half-finished rebase.
keep memories local without a word.
("Ana: add learning_x", or counts plus a per-file body) instead of
"auto: memories from ". The CI hostname check goes.
reviewed; the locked-index golden keeps the macOS git wording.
Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_018Jcf1cp8tAMmCJBLywkDC1