garrytan/gbrain

sources harden --dry-run performs a live git fetch + pull --rebase before any dry-run guard

Open

#3,692 opened on Jul 31, 2026

 (2 comments) (0 reactions) (0 assignees)TypeScript (3,057 forks)github user discovery
fix-neededgood first issuehelp wantedp1verified-real

Repository metrics

Stars
 (21,368 stars)
PR merge metrics
 (Avg merge 18d 10h) (162 merged PRs in 30d)

Description

What happens

gbrain sources harden <id> --dry-run is not read-only. hardenBrainRepo runs step 1 unconditionally before any dryRun check, and step 1 is a live network + working-tree operation.

src/core/brain-repo-durability.ts:673-676 calls divergenceSafePull(...) before the dryRun guards that gate steps 2-7. divergenceSafePull (src/core/git-remote.ts:489-531) runs git fetch followed by git pull --rebase against the user's brain working tree.

So a user reaching for --dry-run to see what hardening WOULD do gets a real fetch and a real rebase-pull of their brain repository. On a repo with local commits not yet pushed, that is a history-touching operation performed by a flag whose entire purpose is to avoid performing operations.

Expected

--dry-run performs no network calls and no working-tree mutations. Either move the pull inside the same dryRun guard the other six steps use, or report it as "would pull" in the plan.

Where it is

  • src/core/brain-repo-durability.ts:668-712 -- the orchestrator; step 1 at :673-676 precedes every dryRun check
  • src/core/git-remote.ts:489-531 -- divergenceSafePull, the fetch + pull --rebase

Notes

Two smaller things found in the same read, mentioned in case they are one fix:

  • gbrain sources harden --help and gbrain sources --help both print only the generic gbrain sources - run gbrain --help for the full command list. stub, so the command's flags (including --dry-run) are undiscoverable from its own help. This is the same CLI-self-help class as the report filed as #3686.
  • The credential step stores an https PAT. On a source whose remote is an SSH URL that store is inert, and the harden run still reports the step as done.

Version

gbrain 0.42.67.0. Established by reading the dispatch (src/commands/sources.ts:1365-1367 -> src/commands/sources-harden.ts:53 runHarden) and the orchestrator source. I did NOT execute harden --dry-run against a live brain -- precisely because of the behavior reported here.

Contributor guide