Guided mode: hand-hold the hunt for a good commit#23
Merged
Conversation
`git bisect` needs both a bad and a good endpoint before it can binary-search, but you usually only have the bad one (HEAD). Finding the good anchor meant manually walking backwards through history with no help. This adds an advisory "guided mode" that turns each manual `python recipe.py` run of that hunt into a self-explaining step. It activates only while a bisect is started with a bad commit but no good one yet (no `refs/bisect/good-*` and no good in `git bisect log`), so it stays completely silent during a real `git bisect run` (both endpoints known) and during a pre-start smoke test (no bisect at all) — no fragile "am I under bisect run?" sniffing. Behaviour when active: - Already-bad guard: refuses to re-evaluate a commit git already knows is bad (nothing to learn), pointing at older commits instead. `--force` overrides. - After a verdict, prints the copy-pasteable next step: - good -> `git bisect good` then `git bisect run python recipe.py` - bad -> `git bisect bad` plus older candidate commits to check out - skip -> older candidates to try - abort -> "fix your build script" (an infra problem, never a good/bad verdict) - Candidate commits double the distance searched (first hunt: ~1w, 2w, 4w), resolved by date on the bad commit's ancestry so they're always valid. Output is colored and boxed, mirroring the existing verb echo style. Adds a TestGuided suite (8 tests) covering the skip guard, --force, each verdict's guidance, the doubling, and the silence guarantee. Docs updated in README (new "Don't know a good commit yet?" section) and SPEC (§4.9). Bumps version to 0.15.0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two refinements to guided mode from review feedback: 1. Step by commit count, not calendar time. Commit count is what governs a bisect (it sets the number of steps) and commit density is too uneven for time to be a good proxy. Probes now double the number of commits skipped (HEAD~s, HEAD~2s, HEAD~4s, s = depth already searched via `git rev-list --count HEAD..<newest-bad>`), walking first-parent so each is a valid mainline ancestor. Each candidate still shows its committer date for orientation. 2. A build failure no longer just says "fix your build script". An old commit that won't build is untestable, and why (toolchain drift vs. a broken recipe) is a judgement the library can't make — so a failed run() now presents a direction choice: an older commit (jump past the break) and a newer one (back toward code that builds), plus the reminder to fix the recipe or set skip_on_error=True. The user decides; the library still marks nothing and moves no HEAD. Recipe errors (uncaught exceptions, unrunnable tests) keep the distinct "fix the recipe" message. Tests updated/added (78 total): commit-count doubling shows [1,2,4] with dates, build break offers OLDER/NEWER + skip_on_error, recipe error stays distinct from a build break, and a forced build break on the anchor offers only OLDER. README and SPEC §4.9 updated to match. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
git bisectcan't binary-search until it has both a bad and a good commit. You almost always have the bad one (HEAD), but finding the good anchor means walking backwards through history by hand — with no guidance. This PR adds an advisory guided mode: run the same recipe manually during that hunt and it tells you exactly what to do next.Workflow
--forceevaluates anyway.git bisect bad.git bisect goodthengit bisect run python recipe.py.run()aborts as always and says fix your build script — never mistaken for a good/bad verdict.Design
Guided output activates only while a bisect is started with a bad commit but no good one yet (
refs/bisect/good-*empty and no good ingit bisect log). So it is completely silent during a realgit bisect run(both endpoints known) and during a pre-start smoke test (no bisect at all) — no fragile "am I undergit bisect run?" sniffing. Candidates are resolved by date on the bad commit's ancestry, so they're always valid bisect points; probes past the start of history are dropped. Output is colored/boxed, matching the existing verb-echo style.Test plan
TestGuidedsuite (8 tests): already-bad skip guard,--force, each verdict's guidance, the distance-doubling ([7, 14, 28]), and the silence guarantee (good known / no bisect).python3 -m unittest discover -s tests).git bisect runpath (verified end-to-end: a real run still finds the first bad commit with no guided output).Docs: new README section "Don't know a good commit yet?" and SPEC §4.9. Version bumped to 0.15.0.
🤖 Generated with Claude Code