kin: KIN-016 Агенты должны уметь говорить 'не могу'. Если агент не может выполнить задачу (нет доступа, не понимает, выходит за компетенцию) — он должен вернуть status: blocked с причиной, а не пытаться угадывать. PM при получении blocked от агента — эскалирует к человеку через GUI (уведомление) и Telegram (когда будет).
This commit is contained in:
parent
a605e9d110
commit
d9172fc17c
35 changed files with 2375 additions and 23 deletions
|
|
@ -72,14 +72,22 @@ def create_project(
|
|||
forgejo_repo: str | None = None,
|
||||
language: str = "ru",
|
||||
execution_mode: str = "review",
|
||||
project_type: str = "development",
|
||||
ssh_host: str | None = None,
|
||||
ssh_user: str | None = None,
|
||||
ssh_key_path: str | None = None,
|
||||
ssh_proxy_jump: str | None = None,
|
||||
description: str | None = None,
|
||||
) -> dict:
|
||||
"""Create a new project and return it as dict."""
|
||||
conn.execute(
|
||||
"""INSERT INTO projects (id, name, path, tech_stack, status, priority,
|
||||
pm_prompt, claude_md_path, forgejo_repo, language, execution_mode)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||
pm_prompt, claude_md_path, forgejo_repo, language, execution_mode,
|
||||
project_type, ssh_host, ssh_user, ssh_key_path, ssh_proxy_jump, description)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||
(id, name, path, _json_encode(tech_stack), status, priority,
|
||||
pm_prompt, claude_md_path, forgejo_repo, language, execution_mode),
|
||||
pm_prompt, claude_md_path, forgejo_repo, language, execution_mode,
|
||||
project_type, ssh_host, ssh_user, ssh_key_path, ssh_proxy_jump, description),
|
||||
)
|
||||
conn.commit()
|
||||
return get_project(conn, id)
|
||||
|
|
@ -612,3 +620,55 @@ def get_cost_summary(conn: sqlite3.Connection, days: int = 7) -> list[dict]:
|
|||
ORDER BY total_cost_usd DESC
|
||||
""", (f"-{days} days",)).fetchall()
|
||||
return _rows_to_list(rows)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Project Phases (KIN-059)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def create_phase(
|
||||
conn: sqlite3.Connection,
|
||||
project_id: str,
|
||||
role: str,
|
||||
phase_order: int,
|
||||
) -> dict:
|
||||
"""Create a research phase for a project."""
|
||||
cur = conn.execute(
|
||||
"""INSERT INTO project_phases (project_id, role, phase_order, status)
|
||||
VALUES (?, ?, ?, 'pending')""",
|
||||
(project_id, role, phase_order),
|
||||
)
|
||||
conn.commit()
|
||||
row = conn.execute(
|
||||
"SELECT * FROM project_phases WHERE id = ?", (cur.lastrowid,)
|
||||
).fetchone()
|
||||
return _row_to_dict(row)
|
||||
|
||||
|
||||
def get_phase(conn: sqlite3.Connection, phase_id: int) -> dict | None:
|
||||
"""Get a project phase by id."""
|
||||
row = conn.execute(
|
||||
"SELECT * FROM project_phases WHERE id = ?", (phase_id,)
|
||||
).fetchone()
|
||||
return _row_to_dict(row)
|
||||
|
||||
|
||||
def list_phases(conn: sqlite3.Connection, project_id: str) -> list[dict]:
|
||||
"""List all phases for a project ordered by phase_order."""
|
||||
rows = conn.execute(
|
||||
"SELECT * FROM project_phases WHERE project_id = ? ORDER BY phase_order",
|
||||
(project_id,),
|
||||
).fetchall()
|
||||
return _rows_to_list(rows)
|
||||
|
||||
|
||||
def update_phase(conn: sqlite3.Connection, phase_id: int, **fields) -> dict:
|
||||
"""Update phase fields. Auto-sets updated_at."""
|
||||
if not fields:
|
||||
return get_phase(conn, phase_id)
|
||||
fields["updated_at"] = datetime.now().isoformat()
|
||||
sets = ", ".join(f"{k} = ?" for k in fields)
|
||||
vals = list(fields.values()) + [phase_id]
|
||||
conn.execute(f"UPDATE project_phases SET {sets} WHERE id = ?", vals)
|
||||
conn.commit()
|
||||
return get_phase(conn, phase_id)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue