day 1: Kin from zero to production - agents, GUI, autopilot, 352 tests

This commit is contained in:
Gros Frumos 2026-03-15 23:22:49 +02:00
parent 8d9facda4f
commit 8a6f280cbd
22 changed files with 1907 additions and 103 deletions

View file

@ -333,7 +333,8 @@ def test_hook_setup_registers_rebuild_frontend(runner, tmp_path):
r = invoke(runner, ["hook", "list", "--project", "p1"])
assert r.exit_code == 0
assert "rebuild-frontend" in r.output
assert "web/frontend/*" in r.output
# KIN-050: trigger_module_path должен быть NULL — хук срабатывает безусловно
assert "web/frontend/*" not in r.output
def test_hook_setup_idempotent(runner, tmp_path):
@ -352,3 +353,123 @@ def test_hook_setup_project_not_found(runner):
r = invoke(runner, ["hook", "setup", "--project", "nope"])
assert r.exit_code == 1
assert "not found" in r.output
# ===========================================================================
# KIN-018 — project set-mode / task update --mode / show with mode labels
# ===========================================================================
def test_project_set_mode_auto(runner):
"""project set-mode auto — обновляет режим, выводит подтверждение."""
invoke(runner, ["project", "add", "p1", "P1", "/p1"])
r = invoke(runner, ["project", "set-mode", "--project", "p1", "auto"])
assert r.exit_code == 0
assert "auto" in r.output
def test_project_set_mode_review(runner):
"""project set-mode review — обновляет режим обратно в review."""
invoke(runner, ["project", "add", "p1", "P1", "/p1"])
invoke(runner, ["project", "set-mode", "--project", "p1", "auto"])
r = invoke(runner, ["project", "set-mode", "--project", "p1", "review"])
assert r.exit_code == 0
assert "review" in r.output
def test_project_set_mode_persisted(runner):
"""После project set-mode режим сохраняется в БД и виден в project show."""
invoke(runner, ["project", "add", "p1", "P1", "/p1"])
invoke(runner, ["project", "set-mode", "--project", "p1", "auto"])
r = invoke(runner, ["project", "show", "p1"])
assert r.exit_code == 0
assert "auto" in r.output
def test_project_set_mode_not_found(runner):
"""project set-mode для несуществующего проекта → exit code 1."""
r = invoke(runner, ["project", "set-mode", "--project", "nope", "auto"])
assert r.exit_code == 1
assert "not found" in r.output
def test_project_set_mode_invalid(runner):
"""project set-mode с недопустимым значением → ошибка click."""
invoke(runner, ["project", "add", "p1", "P1", "/p1"])
r = invoke(runner, ["project", "set-mode", "--project", "p1", "turbo"])
assert r.exit_code != 0
def test_project_show_displays_mode(runner):
"""project show отображает строку Mode: ..."""
invoke(runner, ["project", "add", "p1", "P1", "/p1"])
r = invoke(runner, ["project", "show", "p1"])
assert r.exit_code == 0
assert "Mode:" in r.output
def test_task_update_mode_auto(runner):
"""task update --mode auto задаёт execution_mode на задачу."""
invoke(runner, ["project", "add", "p1", "P1", "/p1"])
invoke(runner, ["task", "add", "p1", "Fix bug"])
r = invoke(runner, ["task", "update", "P1-001", "--mode", "auto"])
assert r.exit_code == 0
assert "auto" in r.output
def test_task_update_mode_review(runner):
"""task update --mode review задаёт execution_mode=review на задачу."""
invoke(runner, ["project", "add", "p1", "P1", "/p1"])
invoke(runner, ["task", "add", "p1", "Fix bug"])
r = invoke(runner, ["task", "update", "P1-001", "--mode", "review"])
assert r.exit_code == 0
assert "review" in r.output
def test_task_update_mode_persisted(runner):
"""После task update --mode режим сохраняется и виден в task show как (overridden)."""
invoke(runner, ["project", "add", "p1", "P1", "/p1"])
invoke(runner, ["task", "add", "p1", "Fix bug"])
invoke(runner, ["task", "update", "P1-001", "--mode", "auto"])
r = invoke(runner, ["task", "show", "P1-001"])
assert r.exit_code == 0
assert "overridden" in r.output
def test_task_update_mode_invalid(runner):
"""task update --mode с недопустимым значением → ошибка click."""
invoke(runner, ["project", "add", "p1", "P1", "/p1"])
invoke(runner, ["task", "add", "p1", "Fix bug"])
r = invoke(runner, ["task", "update", "P1-001", "--mode", "turbo"])
assert r.exit_code != 0
def test_task_show_mode_inherited(runner):
"""task show без явного execution_mode показывает (inherited)."""
invoke(runner, ["project", "add", "p1", "P1", "/p1"])
invoke(runner, ["task", "add", "p1", "Fix bug"])
r = invoke(runner, ["task", "show", "P1-001"])
assert r.exit_code == 0
assert "inherited" in r.output
def test_task_show_mode_overridden(runner):
"""task show с task-level execution_mode показывает (overridden)."""
invoke(runner, ["project", "add", "p1", "P1", "/p1"])
invoke(runner, ["task", "add", "p1", "Fix bug"])
invoke(runner, ["task", "update", "P1-001", "--mode", "review"])
r = invoke(runner, ["task", "show", "P1-001"])
assert r.exit_code == 0
assert "overridden" in r.output
def test_task_show_mode_label_reflects_project_mode(runner):
"""Если у проекта auto, у задачи нет mode — task show показывает 'auto (inherited)'."""
invoke(runner, ["project", "add", "p1", "P1", "/p1"])
invoke(runner, ["project", "set-mode", "--project", "p1", "auto"])
invoke(runner, ["task", "add", "p1", "Fix bug"])
r = invoke(runner, ["task", "show", "P1-001"])
assert r.exit_code == 0
assert "auto" in r.output
assert "inherited" in r.output