kin: KIN-080 Разобраться с KIN-FIX-003 и KIN-FIX-004, одна из задач уже выполнена, вторая берется в работу (руками завершаю) но в задаче не меняется текущий статус

This commit is contained in:
Gros Frumos 2026-03-16 17:30:31 +02:00
parent bfc8f1c0bb
commit c67fa379b3
2 changed files with 125 additions and 5 deletions

View file

@ -394,6 +394,120 @@ class TestAutoMode:
mock_resolve.assert_called_once_with(conn, "VDOL-001", pending)
# ---------------------------------------------------------------------------
# KIN-080: Guard — не перезаписывать статус, если пользователь изменил вручную
# ---------------------------------------------------------------------------
class TestPipelineStatusGuard:
"""Тесты guard-check: pipeline не должен перезаписывать статус задачи,
если пользователь вручную изменил его на 'done' или 'cancelled' пока
pipeline выполнялся."""
@patch("agents.runner._run_autocommit")
@patch("agents.runner._run_learning_extraction")
@patch("agents.runner._get_changed_files")
@patch("agents.runner.run_hooks")
@patch("agents.runner.subprocess.run")
def test_pipeline_preserves_done_status_set_during_execution(
self, mock_run, mock_hooks, mock_get_files, mock_learn, mock_autocommit, conn
):
"""Guard: если пользователь вручную поставил 'done' пока pipeline работал —
итоговый статус должен остаться 'done', а не перезаписаться в 'review'."""
def side_effect(*args, **kwargs):
# Имитируем ручную смену статуса во время выполнения агента
models.update_task(conn, "VDOL-001", status="done")
return _mock_claude_success({"result": "done"})
mock_run.side_effect = side_effect
mock_hooks.return_value = []
mock_get_files.return_value = []
mock_learn.return_value = {"added": 0, "skipped": 0}
steps = [{"role": "debugger", "brief": "find"}]
result = run_pipeline(conn, "VDOL-001", steps)
assert result["success"] is True
task = models.get_task(conn, "VDOL-001")
assert task["status"] == "done" # guard НЕ перезаписал в "review"
@patch("agents.runner._run_autocommit")
@patch("agents.runner._run_learning_extraction")
@patch("agents.runner._get_changed_files")
@patch("agents.runner.run_hooks")
@patch("agents.runner.subprocess.run")
def test_pipeline_preserves_cancelled_status_set_during_execution(
self, mock_run, mock_hooks, mock_get_files, mock_learn, mock_autocommit, conn
):
"""Guard: если пользователь вручную поставил 'cancelled' пока pipeline работал —
итоговый статус должен остаться 'cancelled'."""
def side_effect(*args, **kwargs):
models.update_task(conn, "VDOL-001", status="cancelled")
return _mock_claude_success({"result": "done"})
mock_run.side_effect = side_effect
mock_hooks.return_value = []
mock_get_files.return_value = []
mock_learn.return_value = {"added": 0, "skipped": 0}
steps = [{"role": "debugger", "brief": "find"}]
result = run_pipeline(conn, "VDOL-001", steps)
assert result["success"] is True
task = models.get_task(conn, "VDOL-001")
assert task["status"] == "cancelled" # guard НЕ перезаписал в "review"
@patch("agents.runner._run_autocommit")
@patch("agents.runner._run_learning_extraction")
@patch("agents.runner._get_changed_files")
@patch("agents.runner.run_hooks")
@patch("agents.runner.subprocess.run")
def test_pipeline_sets_review_when_no_manual_override(
self, mock_run, mock_hooks, mock_get_files, mock_learn, mock_autocommit, conn
):
"""Нормальный случай: задача в in_progress, пользователь не трогал статус —
после pipeline устанавливается 'review'."""
mock_run.return_value = _mock_claude_success({"result": "done"})
mock_hooks.return_value = []
mock_get_files.return_value = []
mock_learn.return_value = {"added": 0, "skipped": 0}
steps = [{"role": "debugger", "brief": "find"}]
result = run_pipeline(conn, "VDOL-001", steps)
assert result["success"] is True
task = models.get_task(conn, "VDOL-001")
assert task["status"] == "review"
@patch("agents.runner._run_autocommit")
@patch("agents.runner._run_learning_extraction")
@patch("agents.runner._get_changed_files")
@patch("core.followup.generate_followups")
@patch("agents.runner.run_hooks")
@patch("agents.runner.subprocess.run")
def test_auto_mode_preserves_done_status_set_during_execution(
self, mock_run, mock_hooks, mock_followup, mock_get_files, mock_learn, mock_autocommit, conn
):
"""Guard в auto_complete mode: если пользователь вручную поставил 'done'
пока pipeline работал guard пропускает обновление (уже done)."""
def side_effect(*args, **kwargs):
models.update_task(conn, "VDOL-001", status="done")
return _mock_claude_success({"result": "done"})
mock_run.side_effect = side_effect
mock_hooks.return_value = []
mock_followup.return_value = {"created": [], "pending_actions": []}
mock_get_files.return_value = []
mock_learn.return_value = {"added": 0, "skipped": 0}
models.update_project(conn, "vdol", execution_mode="auto_complete")
steps = [{"role": "tester", "brief": "verify"}]
result = run_pipeline(conn, "VDOL-001", steps)
assert result["success"] is True
task = models.get_task(conn, "VDOL-001")
assert task["status"] == "done"
# ---------------------------------------------------------------------------
# Retry on permission error
# ---------------------------------------------------------------------------