kin: KIN-071 Добавить тип проекта: development / operations / research. Для operations: вместо path к локальной папке — ssh-доступ (host, user, key, proxy or jump). При создании operations-проекта запускается sysadmin-агент который подключается по SSH, обходит сервер, составляет карту: какие сервисы запущены (docker ps, systemctl), какие конфиги где лежат, какие порты открыты, какие версии. Результат сохраняется в decisions и modules как база знаний по серверу. Код не хранится локально — агенты работают через SSH. PM для operations вызывает sysadmin/debugger, не architect/frontend_dev.

This commit is contained in:
Gros Frumos 2026-03-16 09:17:42 +02:00
parent d9172fc17c
commit 75fee86110
4 changed files with 371 additions and 0 deletions

View file

@ -345,3 +345,64 @@ class TestOperationsProject:
ctx = build_context(ops_conn, "SRV-001", "sysadmin", "srv")
prompt = format_prompt(ctx, "sysadmin", "You are sysadmin.")
assert "Project type: operations" in prompt
# ---------------------------------------------------------------------------
# KIN-071: PM routing — operations project routes PM to infra_* pipelines
# ---------------------------------------------------------------------------
class TestPMRoutingOperations:
"""PM-контекст для operations-проекта должен содержать infra-маршруты,
не включающие architect/frontend_dev."""
@pytest.fixture
def ops_conn(self):
c = init_db(":memory:")
models.create_project(
c, "srv", "My Server", "",
project_type="operations",
ssh_host="10.0.0.1",
ssh_user="root",
)
models.create_task(c, "SRV-001", "srv", "Scan server")
yield c
c.close()
def test_pm_context_has_operations_project_type(self, ops_conn):
"""PM получает project_type=operations в контексте проекта."""
ctx = build_context(ops_conn, "SRV-001", "pm", "srv")
assert ctx["project"]["project_type"] == "operations"
def test_pm_context_has_infra_scan_route(self, ops_conn):
"""PM-контекст содержит маршрут infra_scan из specialists.yaml."""
ctx = build_context(ops_conn, "SRV-001", "pm", "srv")
assert "infra_scan" in ctx["routes"]
def test_pm_context_has_infra_debug_route(self, ops_conn):
"""PM-контекст содержит маршрут infra_debug из specialists.yaml."""
ctx = build_context(ops_conn, "SRV-001", "pm", "srv")
assert "infra_debug" in ctx["routes"]
def test_infra_scan_route_uses_sysadmin(self, ops_conn):
"""infra_scan маршрут включает sysadmin в шагах."""
ctx = build_context(ops_conn, "SRV-001", "pm", "srv")
steps = ctx["routes"]["infra_scan"]["steps"]
assert "sysadmin" in steps
def test_infra_scan_route_excludes_architect(self, ops_conn):
"""infra_scan маршрут не назначает architect."""
ctx = build_context(ops_conn, "SRV-001", "pm", "srv")
steps = ctx["routes"]["infra_scan"]["steps"]
assert "architect" not in steps
def test_infra_scan_route_excludes_frontend_dev(self, ops_conn):
"""infra_scan маршрут не назначает frontend_dev."""
ctx = build_context(ops_conn, "SRV-001", "pm", "srv")
steps = ctx["routes"]["infra_scan"]["steps"]
assert "frontend_dev" not in steps
def test_format_prompt_pm_operations_project_type_label(self, ops_conn):
"""format_prompt для PM с operations-проектом содержит 'Project type: operations'."""
ctx = build_context(ops_conn, "SRV-001", "pm", "srv")
prompt = format_prompt(ctx, "pm", "You are PM.")
assert "Project type: operations" in prompt