kin: auto-commit after pipeline
This commit is contained in:
parent
c6e53a95a1
commit
e1fe41c428
1 changed files with 125 additions and 0 deletions
|
|
@ -402,3 +402,128 @@ class TestAutoReturnIntegration:
|
||||||
assert result.get("auto_returned") is not True
|
assert result.get("auto_returned") is not True
|
||||||
task = models.get_task(conn, "P1-001")
|
task = models.get_task(conn, "P1-001")
|
||||||
assert task["status"] == "done"
|
assert task["status"] == "done"
|
||||||
|
|
||||||
|
@patch("core.followup.generate_followups")
|
||||||
|
@patch("agents.runner.run_hooks")
|
||||||
|
@patch("agents.runner.subprocess.run")
|
||||||
|
def test_exit_condition_strategic_decision_blocks_task(
|
||||||
|
self, mock_run, mock_hooks, mock_followup, conn
|
||||||
|
):
|
||||||
|
"""exit_condition='strategic_decision' → task stays blocked, no auto-return."""
|
||||||
|
mock_hooks.return_value = []
|
||||||
|
mock_followup.return_value = {"created": [], "pending_actions": []}
|
||||||
|
|
||||||
|
mock_run.return_value = _mock_reviewer(
|
||||||
|
"changes_requested",
|
||||||
|
reason="Needs architectural decision from management",
|
||||||
|
exit_condition="strategic_decision",
|
||||||
|
)
|
||||||
|
|
||||||
|
steps = [{"role": "reviewer", "brief": "review"}]
|
||||||
|
result = run_pipeline(conn, "P1-001", steps)
|
||||||
|
|
||||||
|
assert result["success"] is False
|
||||||
|
assert result.get("auto_returned") is not True, (
|
||||||
|
"strategic_decision должен блокировать auto-return"
|
||||||
|
)
|
||||||
|
task = models.get_task(conn, "P1-001")
|
||||||
|
assert task["status"] == "blocked", (
|
||||||
|
"exit_condition='strategic_decision' → задача должна остаться blocked"
|
||||||
|
)
|
||||||
|
|
||||||
|
@patch("core.followup.generate_followups")
|
||||||
|
@patch("agents.runner.run_hooks")
|
||||||
|
@patch("agents.runner.subprocess.run")
|
||||||
|
def test_review_mode_reviewer_rejection_no_auto_return(
|
||||||
|
self, mock_run, mock_hooks, mock_followup
|
||||||
|
):
|
||||||
|
"""Scenario 2: execution_mode='review' + reviewer rejection → no auto-return.
|
||||||
|
|
||||||
|
In review mode, gate check is skipped — task moves to 'review' status
|
||||||
|
waiting for human approval, never triggering auto-return.
|
||||||
|
"""
|
||||||
|
c = init_db(":memory:")
|
||||||
|
models.create_project(c, "p1", "P1", "/tmp/p1", tech_stack=["python"])
|
||||||
|
models.create_task(c, "P1-001", "p1", "Implement feature",
|
||||||
|
brief={"route_type": "feature"})
|
||||||
|
# Explicitly review mode (not auto_complete)
|
||||||
|
models.update_task(c, "P1-001", execution_mode="review")
|
||||||
|
|
||||||
|
mock_hooks.return_value = []
|
||||||
|
mock_followup.return_value = {"created": [], "pending_actions": []}
|
||||||
|
mock_run.return_value = _mock_reviewer("changes_requested",
|
||||||
|
reason="Needs work")
|
||||||
|
|
||||||
|
steps = [{"role": "reviewer", "brief": "review"}]
|
||||||
|
result = run_pipeline(c, "P1-001", steps)
|
||||||
|
c.close()
|
||||||
|
|
||||||
|
assert result.get("auto_returned") is not True, (
|
||||||
|
"В режиме review авто-возврат не должен срабатывать"
|
||||||
|
)
|
||||||
|
# In review mode the pipeline succeeds (all steps run), task waits for human
|
||||||
|
assert result["success"] is True
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Unit tests: two sequential auto-returns (decision #1082)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class TestTwoSequentialAutoReturns:
|
||||||
|
"""KIN-136: return_count increments correctly across two consecutive returns (decision #1082)."""
|
||||||
|
|
||||||
|
def test_two_sequential_auto_returns_increment_count_to_two(self, conn):
|
||||||
|
"""Two _trigger_auto_return calls → return_count = 2 (not reset, not stuck at 1)."""
|
||||||
|
with patch("agents.runner.run_pipeline") as mock_rp:
|
||||||
|
mock_rp.return_value = {"success": True, "steps_completed": 2}
|
||||||
|
|
||||||
|
# First auto-return
|
||||||
|
result1 = _trigger_auto_return(
|
||||||
|
conn, "P1-001", "p1", pipeline=None,
|
||||||
|
original_steps=[{"role": "reviewer"}],
|
||||||
|
gate_role="reviewer",
|
||||||
|
gate_reason="first rejection",
|
||||||
|
allow_write=False,
|
||||||
|
noninteractive=True,
|
||||||
|
)
|
||||||
|
assert result1["should_escalate"] is False
|
||||||
|
task_after_first = models.get_task(conn, "P1-001")
|
||||||
|
assert (task_after_first.get("return_count") or 0) == 1, (
|
||||||
|
"После первого авто-возврата return_count должен быть 1"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Second auto-return (without resetting count)
|
||||||
|
result2 = _trigger_auto_return(
|
||||||
|
conn, "P1-001", "p1", pipeline=None,
|
||||||
|
original_steps=[{"role": "reviewer"}],
|
||||||
|
gate_role="reviewer",
|
||||||
|
gate_reason="second rejection",
|
||||||
|
allow_write=False,
|
||||||
|
noninteractive=True,
|
||||||
|
)
|
||||||
|
assert result2["should_escalate"] is False
|
||||||
|
task_after_second = models.get_task(conn, "P1-001")
|
||||||
|
assert (task_after_second.get("return_count") or 0) == 2, (
|
||||||
|
"После второго авто-возврата return_count должен быть 2 (не сброшен в 1)"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_return_count_not_reset_between_sequential_auto_returns(self, conn):
|
||||||
|
"""Ensures return_count accumulates across calls — cumulative, not per-run (decision #1082)."""
|
||||||
|
with patch("agents.runner.run_pipeline") as mock_rp:
|
||||||
|
mock_rp.return_value = {"success": True, "steps_completed": 2}
|
||||||
|
|
||||||
|
for call_number in range(1, _AUTO_RETURN_MAX):
|
||||||
|
_trigger_auto_return(
|
||||||
|
conn, "P1-001", "p1", pipeline=None,
|
||||||
|
original_steps=[{"role": "reviewer"}],
|
||||||
|
gate_role="reviewer",
|
||||||
|
gate_reason=f"rejection #{call_number}",
|
||||||
|
allow_write=False,
|
||||||
|
noninteractive=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
task = models.get_task(conn, "P1-001")
|
||||||
|
assert (task.get("return_count") or 0) == _AUTO_RETURN_MAX - 1, (
|
||||||
|
f"После {_AUTO_RETURN_MAX - 1} авто-возвратов return_count должен быть "
|
||||||
|
f"{_AUTO_RETURN_MAX - 1} — не сброшен и не потерян"
|
||||||
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue