svc_update / forge merge auto-commits dirty repos and pushes via Claude — must not #181
Labels
No labels
prio_critical
prio_low
type_bug
type_contact
type_issue
type_lead
type_question
type_story
type_task
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lhumina_code/hero_skills#181
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
forge_merge_path(intools/modules/forge.nu:783-839) silently rewrites local git history as a side effect ofservice_* install --update. On any dirty repo it:git add -Afollowed by a Claude-generated commit message via theacommand (forge.nu:807-818). As root it falls back to a plainchore: auto-commit local changes before pullcommit.a 1 -i ...spawns Claude to read conflicted files and writegit add/git commit --no-edititself (forge.nu:826-832).git push -u origin <branch>always fires after the pull (forge.nu:834-836).The behaviour is documented in
services/lib.nu:161-174as intentional ("Thin wrapper aroundforge merge— which fetches, commits any local changes, pulls, resolves conflicts (via AI if needed) and pushes when ahead"). It is the wrong design for a tool people run during active development.Trigger chain
Fires whenever
--updatereachessvc_update:--updateis the onlyservice_*flag that hits this. Without--updatethe install path goes directly tosvc_cargo_installand never touches git state.forge mergestandalone,forge merge_all, andskills.nu(which callsforge merge hero_skills) hit the same code.Real damage
While working on
hero_codescalersissue (lhumina_code/hero_codescalers#19), a singleservice_codescalers start --root --updatedid the following without consent:crates/hero_codescalers_server/src/jobs.rs(~67 lines).git add -A, wrote commitbb38fe0titledfeat(jobs): add stats tracking and fix list paginationwith aCo-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>trailer.origin/development.Ctrl+C on the running command did not help — the commit was already written before the pull began.
Required behaviour
On
--updatefor each service repo:origin.origin/<current-branch>: fast-forward pull, no merge commit.--update. End-of-run summary:synced N, skipped (dirty) M, skipped (diverged) K.git add,git commit,git push,git rebase,claude/a 0/a 1, or any other command that mutates history or commits on the user's behalf.Proposed contract is detailed in the next comment for review.
Proposed approach
Replace
forge_merge_path(tools/modules/forge.nu:783-839) with a read-only sync function. Nogit add, nogit commit, nogit push, noclaudeinvocation, nogit rebase. The function only ever runsgit fetchand (when safe)git merge --ff-only.Contract
For each service repo on
--update:A failure on one repo never aborts the whole
--update. End-of-run summary line:Design decisions confirmed
apikeys.db/request_logs.dbsituation that produced commit103cc44is exactly the failure mode this prevents — runtime data ends up in working tree, gets auto-staged, gets committed. The right escape hatch is.gitignore, not "silently ignore untracked".development, a feature branch, a release branch. No branch is special-cased; no branch switching happens.--update, the build path already skipssvc_updateentirely (services/lib.nu:343if $update { svc_update }), so users who don't want any git activity already have an opt-out: just don't pass--update.Scope of the patch
Single file:
tools/modules/forge.nu.forge_merge_path(lines 783-839) with the read-only sync logic above.a 0 -ianda 1 -icalls. Remove thegit pushline.forge mergecommand (forge.nu:941) keeps the same name; only its semantics change.forge merge_allbenefits transparently because it loops overforge_merge_path.svc_update(services/lib.nu:168-174) stays as is — its doc comment needs updating to remove the "commits any local changes / resolves conflicts via AI / pushes" wording.Approx diff size: -50 / +35 lines, no new files, no new dependencies.
Out of scope for this issue
forge mergecommand's behaviour as called fromskills.nuand elsewhere is changed by this same patch (intentionally — same fix everywhere).forge merge.@despiegk wants to keep it as it