Files
bench/tests/test_fresh_branch_point.py
T
istosandClaude Fable 5 0111a9ffc8 PR #7 review: count 'ahead' against HEAD, not local main
The ticker note says the branch point is N ahead of this checkout, but
the count compared origin/main to the local main branch — misleading
whenever the board runs from another branch or detached HEAD. HEAD is
the fallback base, so HEAD..origin/main is exactly what launching from
it would have missed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 07:36:51 +02:00

134 lines
5.6 KiB
Python

"""Where a fresh work launch branches from: origin/main when a fetch can
reach it, local HEAD when there is no origin or the network fails — and
never a blocked launch either way. Run with:
python3 -m unittest discover -s tests
"""
import subprocess
import sys
import tempfile
import time
import unittest
from pathlib import Path
REPO = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(REPO / "manager" / "core"))
import agents # noqa: E402
import config # noqa: E402
def _git(cwd: Path, *args: str) -> str:
return subprocess.check_output(
["git", "-C", str(cwd), *args], text=True,
stderr=subprocess.DEVNULL).strip()
def _commit(cwd: Path, msg: str) -> None:
subprocess.check_call(
["git", "-C", str(cwd), "-c", "user.email=t@t", "-c", "user.name=t",
"commit", "-q", "--allow-empty", "-m", msg])
class FreshBranchPoint(unittest.TestCase):
"""_fresh_branch_point decides the base of a brand-new task branch."""
def setUp(self):
self._tmp = tempfile.TemporaryDirectory()
root = Path(self._tmp.name)
self.upstream = root / "upstream"
self.upstream.mkdir()
_git(self.upstream, "init", "-q", "-b", "main")
_commit(self.upstream, "root")
self.local = root / "local"
subprocess.check_call(
["git", "clone", "-q", str(self.upstream), str(self.local)],
stderr=subprocess.DEVNULL)
self._saved = config.REPO, config.FETCH_TIMEOUT
config.REPO = self.local
config.FETCH_TIMEOUT = 5.0
def tearDown(self):
config.REPO, config.FETCH_TIMEOUT = self._saved
self._tmp.cleanup()
def _hang_remote(self, name: str) -> None:
"""Point a remote at a transport that never answers."""
_git(self.local, "config", "protocol.ext.allow", "always")
# ext:: runs the command as the remote helper; sleep never answers
# git's handshake, so the fetch blocks until the timeout fires.
_git(self.local, "remote", "set-url", name, "ext::sleep 30")
def test_no_remote_branches_from_head_silently(self):
_git(self.local, "remote", "remove", "origin")
self.assertEqual(agents._fresh_branch_point(), (None, None))
def test_only_origin_counts_and_is_never_fetched_when_absent(self):
# A hanging remote under another name: if anything fetched it, this
# test would stall; instead the launch path answers HEAD instantly.
_git(self.local, "remote", "rename", "origin", "upstream")
self._hang_remote("upstream")
started = time.monotonic()
self.assertEqual(agents._fresh_branch_point(), (None, None))
self.assertLess(time.monotonic() - started, 2)
def test_origin_ahead_branches_from_its_tip_and_says_so(self):
_commit(self.upstream, "landed elsewhere 1")
_commit(self.upstream, "landed elsewhere 2")
point, note = agents._fresh_branch_point()
self.assertEqual(point, "origin/main")
self.assertEqual(note, "branched from origin/main, "
"2 ahead of this checkout")
# The fetch refreshed the ref the branch will start from.
self.assertEqual(_git(self.local, "rev-parse", "origin/main"),
_git(self.upstream, "rev-parse", "main"))
def test_worktree_from_origin_main_has_its_tip_as_merge_base(self):
# The same commands start_agent runs for a fresh branch.
_commit(self.upstream, "landed elsewhere")
point, _ = agents._fresh_branch_point()
worktree = Path(self._tmp.name) / "wt"
_git(self.local, "worktree", "add", "--no-track", "-b", "task/x",
str(worktree), point)
self.assertEqual(_git(self.local, "merge-base", "task/x", "origin/main"),
_git(self.upstream, "rev-parse", "main"))
# --no-track: the task branch must not adopt origin/main as upstream.
upstream_cfg = subprocess.run(
["git", "-C", str(self.local), "config", "branch.task/x.merge"],
capture_output=True)
self.assertNotEqual(upstream_cfg.returncode, 0)
def test_ahead_count_is_relative_to_the_checkout_not_local_main(self):
# The checkout already holds origin/main's tip on another branch;
# only local main is behind. Nothing was missed, so no narration —
# counting main..origin/main would have claimed "1 ahead" here.
_commit(self.upstream, "landed elsewhere")
_git(self.local, "fetch", "-q", "origin")
_git(self.local, "checkout", "-q", "-b", "other", "origin/main")
self.assertEqual(agents._fresh_branch_point(), ("origin/main", None))
def test_origin_in_sync_is_used_without_narration(self):
self.assertEqual(agents._fresh_branch_point(), ("origin/main", None))
def test_unreachable_origin_falls_back_to_head_and_says_so(self):
_git(self.local, "remote", "set-url", "origin",
str(Path(self._tmp.name) / "gone"))
point, note = agents._fresh_branch_point()
self.assertIsNone(point)
self.assertEqual(note, "fetch of origin/main failed; "
"branched from local HEAD")
def test_hanging_fetch_times_out_within_bound_and_says_so(self):
self._hang_remote("origin")
config.FETCH_TIMEOUT = 0.5
started = time.monotonic()
point, note = agents._fresh_branch_point()
self.assertLess(time.monotonic() - started, 5)
self.assertIsNone(point)
self.assertEqual(note, "fetch of origin/main timed out; "
"branched from local HEAD")
if __name__ == "__main__":
unittest.main()