Multi-milestone work and documents on the new loop (M2.4)
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 3m45s
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 3m45s
- Every milestone branch is cut from the latest default branch: the next milestone builds on the merged previous one, and a redo after a closed PR drops the rejected work. Uncommitted work comes along. - While the item's PR is open, start_milestone is refused, with the PR's state read from Gitea at that moment, not the last watch round. - finish_milestone(final): earlier PRs say "Part of #N", the last "Closes #N"; unsaid, it's final, as before. - close_item with the item's PR still open waits for the merge (L2: a closed item leaves nothing open). - The driver's instructions cover ARCHITECTURE.md and build plans under docs/plans/ (D2); the harness never parses a plan. - Parking stashes uncommitted work and pushes it to <item>-parked, put back on resume, instead of committing it onto the item's branch. The walk found a half-done review fix parked onto a PR that had merged meanwhile, where it was lost. Architecture D4's parking line says so. Tests: unit tests for fresh milestone branches, the merge wait (including a merge not yet watched), redo after a closed PR, Part of/Closes, close waiting on an open PR, and the parked-fix regression; the walk's new milestones_start_fresh property (fork-from-current fails 9 seeds); an e2e two-milestone feature. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
This commit is contained in:
1 parent
da32cac5cf
commit
cd9ab2559e
10 files changed
+539
-53
No files matched your search
@@ -79,7 +79,11 @@ class PolicyModel:
|
||||
return [
|
||||
call("start_milestone", name=f"m{self.n}"),
|
||||
call("write_file", path=f"f{self.n}.py", content=f"x = {self.n}\n"),
|
||||
call("finish_milestone", summary=f"work {self.n}"),
|
||||
call(
|
||||
"finish_milestone",
|
||||
summary=f"work {self.n}",
|
||||
final=self.rng.choice(["yes", "no"]),
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@@ -308,6 +312,7 @@ class Walk:
|
||||
f"one_active (nothing left running): {where}"
|
||||
)
|
||||
self._parked_work_safe(where)
|
||||
self._milestones_start_fresh(where)
|
||||
heads = [p["head"] for p in forge.prs.values()]
|
||||
assert len(heads) == len(set(heads)), f"one_pr_per_milestone: {where}"
|
||||
bare = self.world["bare"]
|
||||
@@ -325,6 +330,29 @@ class Walk:
|
||||
)
|
||||
assert landed, f"review_fixes_land (PR {n}): {where}"
|
||||
|
||||
def _milestones_start_fresh(self, where: str) -> None:
|
||||
"""D4: a milestone starts from the latest default branch, so one
|
||||
redone after a closed PR never carries the rejected work."""
|
||||
forge: Forge = self.world["forge"]
|
||||
bare = self.world["bare"]
|
||||
for item in self.items():
|
||||
mine = sorted(
|
||||
(n, p)
|
||||
for n, p in forge.prs.items()
|
||||
if p["head"].startswith(f"{item.id}-milestone-")
|
||||
and "-fix-" not in p["head"]
|
||||
)
|
||||
for i, (n, earlier) in enumerate(mine):
|
||||
if earlier["merged"]:
|
||||
continue
|
||||
rejected = _rev(bare, f"refs/heads/{earlier['head']}")
|
||||
if _is_ancestor(bare, rejected, "refs/heads/main"):
|
||||
continue
|
||||
for m, later in mine[i + 1 :]:
|
||||
assert not _is_ancestor(
|
||||
bare, rejected, f"refs/heads/{later['head']}"
|
||||
), f"milestones_start_fresh: PR {m} carries PR {n}: {where}"
|
||||
|
||||
def _parked_work_safe(self, where: str) -> None:
|
||||
"""L1, D4: nothing of a parked item lives only on the build VM: what
|
||||
every branch of an open item that isn't on the workspace points at is
|
||||
@@ -367,7 +395,17 @@ class Walk:
|
||||
for path in written:
|
||||
if here and (root / path).exists():
|
||||
continue
|
||||
history = _git(bare, "log", "--all", "--format=%H", "--", path)
|
||||
history = _git(
|
||||
# Full history: a parked stash keeps new files in its
|
||||
# third parent, which plain log simplifies away.
|
||||
bare,
|
||||
"log",
|
||||
"--all",
|
||||
"--full-history",
|
||||
"--format=%H",
|
||||
"--",
|
||||
path,
|
||||
)
|
||||
assert history, f"parked_work_safe: {path} of #{item.id} lost: {where}"
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user