Fix #2871: don't mark an empty slice branch COMPLETE on restart - #2874
Conversation
is_slice_branch_merged_into_parent treated 'slice tip is an ancestor of parent' as merged → COMPLETE. An empty (un-started) slice branch's tip is exactly the parent SHA it was forked at, so when the parent advances it becomes a trivial ancestor — falsely marking the slice complete and skipping it, leaving dependents to run without their prerequisite. Git topology alone can't tell an empty branch from a merged one (both are ancestors of the advanced parent), so record the branch's creation base SHA and require the tip to have moved past it. - Slice.integration_base_sha: new optional contract field, the origin SHA the integration branch was forked at. - Persist it once, right after create_slice_integration_branch succeeds (branch fresh, tip == base, no agent spawned yet). - is_slice_branch_merged_into_parent gains an integration_base_sha kwarg: when the tip still equals the recorded base, return False (un-started). Purely additive — an unknown base (legacy slices) falls back to the prior ancestor-only check, so #2549 behaviour is preserved. - Both call sites (bootstrap reconciliation + mid-run race check) pass the recorded base.
|
egg is investigating the Test check failure...
|
Check Failure: Integration Tests / Integration TestsWhat's failing: The Integration Tests tier failed during cluster setup, before any integration test executed. The Cilium CNI install could not reach the k3s API server: Root cause: A transient CI infrastructure race, not a code defect. The This is unrelated to this PR. The Test workflow's other tiers all passed (Unit Tests: success, Security Scan: success), and the PR only touches Python orchestrator code ( What needs to be done:
Suggestion (workflow hardening, separate from this PR): make the integration setup wait for k3s API readiness before installing Cilium, e.g. poll — Authored by egg |
Autofix tracking{"Test/Integration Tests / Integration Tests": 1} |
|
egg check fixer completed for Test. CI will re-run to verify. View run logs — Authored by egg |
Document the new Slice.integration_base_sha field added in #2874. The slice-dag architecture doc maintains a table of notable Slice model fields; the new field should be listed there so readers understand its purpose in distinguishing empty (un-started) slice branches from genuinely merged ones on pipeline restart. Authored-by: egg Co-authored-by: jwbron <8340608+jwbron@users.noreply.github.com>
is_slice_branch_merged_into_parent treated 'slice tip is an ancestor of parent' as merged → COMPLETE. An empty (un-started) slice branch's tip is exactly the parent SHA it was forked at, so when the parent advances it becomes a trivial ancestor — falsely marking the slice complete and skipping it, leaving dependents to run without their prerequisite. Git topology alone can't tell an empty branch from a merged one (both are ancestors of the advanced parent), so record the branch's creation base SHA and require the tip to have moved past it. - Slice.integration_base_sha: new optional contract field, the origin SHA the integration branch was forked at. - Persist it once, right after create_slice_integration_branch succeeds (branch fresh, tip == base, no agent spawned yet). - is_slice_branch_merged_into_parent gains an integration_base_sha kwarg: when the tip still equals the recorded base, return False (un-started). Purely additive — an unknown base (legacy slices) falls back to the prior ancestor-only check, so #2549 behaviour is preserved. - Both call sites (bootstrap reconciliation + mid-run race check) pass the recorded base.
Document the new Slice.integration_base_sha field added in #2874. The slice-dag architecture doc maintains a table of notable Slice model fields; the new field should be listed there so readers understand its purpose in distinguishing empty (un-started) slice branches from genuinely merged ones on pipeline restart. Authored-by: egg Co-authored-by: jwbron <8340608+jwbron@users.noreply.github.com>
Closes #2871.
Problem
On
restart_phase implement, bootstrap reconciliation falsely marked a no-work sliceCOMPLETEwhen its stale, empty integration branch was an ancestor of an advanced work branch. The slice was then skipped and its dependents ran without their prerequisite (observed onissue-2777-replan: slice-1 died at spawn, committed nothing, yet was marked complete withcommit=None, review_cycles=0).is_slice_branch_merged_into_parenttreats "slice tip is an ancestor of parent" as merged → COMPLETE. An empty slice branch's tip is the parent SHA it was forked at, so once the parent advances (parent-slice progress, amainmerge, or an operator patch) the empty tip becomes a trivial ancestor — indistinguishable, by ancestry alone, from a genuinely merged branch.Fix
Git topology alone can't tell the two apart (both are ancestors of the advanced parent), so we record the branch's creation base SHA and require the tip to have moved past it before treating "ancestor of parent" as COMPLETE.
Slice.integration_base_sha— new optional contract field: the origin SHA the integration branch was forked at.create_slice_integration_branchsucceeds — the branch is fresh (tip == base) and no agent has been spawned yet, so the tip is the true base. Only written when unset, so a#2512restart-recovery over a branch that already carries slice commits keeps its original base.is_slice_branch_merged_into_parentgains anintegration_base_shakwarg: when the branch tip still equals the recorded base, returnFalse(un-started, not merged) before the merge-base call.The change is purely additive: when the base is unknown (slices provisioned before this field existed), the check falls back to its prior ancestor-only behaviour, so the
#2549already-merged-skip path is preserved. This favours a loud non-fast-forward failure over silent corruption for the narrow legacy-branch window.Tests
test_empty_branch_at_creation_base_is_not_merged: empty branch (tip == recorded base) →False, and the merge-base call is short-circuited.test_recorded_base_does_not_block_genuinely_merged_branch: a tip past its base that is an ancestor of parent still reportsTrue(guard is additive).test_create_slice_integration_branch.py(26 tests) passes; lint clean. Changeset-awaremake testwas running at PR-open time.Part of the 3-bug sequence (#2869, #2870, #2871) gating the
issue-2777-replanresume.