|
@@ -28,10 +28,11 @@ call, questions ride `saddle block` through run_command):
|
|
|
5. the terminal transition (the goals row's last_terminal_watermark)
|
|
5. the terminal transition (the goals row's last_terminal_watermark)
|
|
|
coalesces (~SADDLE_GOAL_RESUME_S) into the goal agent's batched
|
|
coalesces (~SADDLE_GOAL_RESUME_S) into the goal agent's batched
|
|
|
resume; it merges, deletes the task branch, pushes the goal branch
|
|
resume; it merges, deletes the task branch, pushes the goal branch
|
|
|
- (push-before-review) and submit_report enters completion review
|
|
|
|
|
-6. completion review accept — the live per-repo push flags gate it:
|
|
|
|
|
- the accept REFUSES while origin is behind, passes once the branch
|
|
|
|
|
- is re-pushed and the probe re-cached -> goal complete, run task done
|
|
|
|
|
|
|
+ (push-before-review, enforced daemon-side at the completion
|
|
|
|
|
+ attempt) and submit_report enters completion review
|
|
|
|
|
+6. completion review accept -> goal complete, run task done (no
|
|
|
|
|
+ web-side push gate: the daemon already refused the completion
|
|
|
|
|
+ attempt until every goal branch was on origin)
|
|
|
7. the audit trail: the DERIVED goal narrative, the unified events
|
|
7. the audit trail: the DERIVED goal narrative, the unified events
|
|
|
ledger (turn cards with tool_call/tool_result, usage rows, the §7.2
|
|
ledger (turn cards with tool_call/tool_result, usage rows, the §7.2
|
|
|
kind set, web-originated-only comment kinds), the event log page +
|
|
kind set, web-originated-only comment kinds), the event log page +
|
|
@@ -698,50 +699,17 @@ def main():
|
|
|
capture_output=True).returncode == 0
|
|
capture_output=True).returncode == 0
|
|
|
check(pushed, "the goal branch was pushed to origin (push-before-review)")
|
|
check(pushed, "the goal branch was pushed to origin (push-before-review)")
|
|
|
|
|
|
|
|
- print("== accept refuses while origin is behind (the live push gate) ==")
|
|
|
|
|
- # Rewind origin's goal branch to the pre-merge base and refresh
|
|
|
|
|
- # the daemon probe: the live per-repo flags flip to unpushed and
|
|
|
|
|
- # the completion accept must REFUSE (plan 15 C4 / F9) until the
|
|
|
|
|
- # branch is pushed again — enforcing push-after-each-merge at
|
|
|
|
|
- # the human gate, read from probe state (never a snapshot).
|
|
|
|
|
- completion = state["completion_pending_block"]
|
|
|
|
|
- subprocess.run(["git", "-C", goal_clone, "push", "-f", "origin",
|
|
|
|
|
- "main:refs/heads/goal/demo-run"], check=True, capture_output=True)
|
|
|
|
|
- subprocess.run(["git", "-C", goal_clone, "fetch", "origin"],
|
|
|
|
|
- check=True, capture_output=True)
|
|
|
|
|
- act(auth, card["refresh"], {})
|
|
|
|
|
- check(wait_for(lambda: any(
|
|
|
|
|
- "demo" in (b.get("branch") or "") and b.get("pushed") is False
|
|
|
|
|
- for b in goal_state(auth, goal1).get("push_branches", [])) or False,
|
|
|
|
|
- timeout=60, what="unpushed chip") is not None,
|
|
|
|
|
- "the rewound origin flips the live push chip to unpushed")
|
|
|
|
|
- refusal = act(auth, completion["answer_action"], {"verdict": "accept"})
|
|
|
|
|
- check(any(d.get("type") == "notify" and d.get("kind") == "error"
|
|
|
|
|
- and "Origin is behind" in (d.get("message") or "")
|
|
|
|
|
- for d in refusal),
|
|
|
|
|
- "the accept refuses with a clear message while origin is behind")
|
|
|
|
|
- check(goal_state(auth, goal1)["status"] == "completion_review",
|
|
|
|
|
- "the refused accept leaves the goal in completion review")
|
|
|
|
|
- check(goal_state(auth, goal1)["completion_pending_block"]
|
|
|
|
|
- not in (None, False),
|
|
|
|
|
- "the refused accept leaves the completion block unanswered")
|
|
|
|
|
- subprocess.run(["git", "-C", goal_clone, "push", "origin", "goal/demo-run"],
|
|
|
|
|
- check=True, capture_output=True)
|
|
|
|
|
- act(auth, card["refresh"], {})
|
|
|
|
|
- check(wait_for(lambda: any(
|
|
|
|
|
- "demo" in (b.get("branch") or "") and b.get("pushed") is True
|
|
|
|
|
- for b in goal_state(auth, goal1).get("push_branches", [])) or False,
|
|
|
|
|
- timeout=60, what="pushed chip restored") is not None,
|
|
|
|
|
- "re-pushing the branch restores the live push chip (after push)")
|
|
|
|
|
- completion = goal_state(auth, goal1)["completion_pending_block"]
|
|
|
|
|
-
|
|
|
|
|
print("== completion accept ==")
|
|
print("== completion accept ==")
|
|
|
|
|
+ # Goal 21: the accept-time push gate is gone — the daemon already
|
|
|
|
|
+ # refused the agent's completion attempt until every goal branch
|
|
|
|
|
+ # was pushed (push-before-review, asserted above), so the branch
|
|
|
|
|
+ # is on origin here and the verdict path needs no second check.
|
|
|
check("greeting.txt added via one worker task" in (completion or {}).get("body", ""),
|
|
check("greeting.txt added via one worker task" in (completion or {}).get("body", ""),
|
|
|
"the run task's completion block carries the report")
|
|
"the run task's completion block carries the report")
|
|
|
winning_body = (completion or {}).get("body", "")
|
|
winning_body = (completion or {}).get("body", "")
|
|
|
accept = act(auth, completion["answer_action"], {"verdict": "accept"})
|
|
accept = act(auth, completion["answer_action"], {"verdict": "accept"})
|
|
|
check(not any(d.get("type") == "notify" and d.get("kind") == "error" for d in accept),
|
|
check(not any(d.get("type") == "notify" and d.get("kind") == "error" for d in accept),
|
|
|
- "the accept passes once the push flags read pushed")
|
|
|
|
|
|
|
+ "the accept passes (no web-side push gate on the verdict)")
|
|
|
check(wait_goal_status(auth, goal1, "complete", timeout=30) is not None,
|
|
check(wait_goal_status(auth, goal1, "complete", timeout=30) is not None,
|
|
|
"accepting the verdict marker completes the goal (server-owned wording)")
|
|
"accepting the verdict marker completes the goal (server-owned wording)")
|
|
|
check(wait_task_status(auth, run_task, "done", timeout=30) is not None,
|
|
check(wait_task_status(auth, run_task, "done", timeout=30) is not None,
|