kin: KIN-049 Кнопка Deploy на странице задачи после approve. Для каждого проекта настраивается deploy-команда (git push, scp, ssh restart). В Settings проекта.

This commit is contained in:
Gros Frumos 2026-03-16 08:21:13 +02:00
parent 860ef3f6c9
commit d50bd703ae
11 changed files with 517 additions and 61 deletions

View file

@ -16,6 +16,11 @@ VALID_TASK_STATUSES = [
VALID_COMPLETION_MODES = {"auto_complete", "review"}
TASK_CATEGORIES = [
"SEC", "UI", "API", "INFRA", "BIZ", "DB",
"ARCH", "TEST", "PERF", "DOCS", "FIX", "OBS",
]
def validate_completion_mode(value: str) -> str:
"""Validate completion mode from LLM output. Falls back to 'review' if invalid."""
@ -132,6 +137,44 @@ def update_project(conn: sqlite3.Connection, id: str, **fields) -> dict:
# Tasks
# ---------------------------------------------------------------------------
def next_task_id(
conn: sqlite3.Connection,
project_id: str,
category: str | None = None,
) -> str:
"""Generate next task ID.
Without category: PROJ-001 (backward-compatible old format)
With category: PROJ-CAT-001 (new format, per-category counter)
"""
prefix = project_id.upper()
existing = list_tasks(conn, project_id=project_id)
if category:
cat_prefix = f"{prefix}-{category}-"
max_num = 0
for t in existing:
tid = t["id"]
if tid.startswith(cat_prefix):
try:
max_num = max(max_num, int(tid[len(cat_prefix):]))
except ValueError:
pass
return f"{prefix}-{category}-{max_num + 1:03d}"
else:
# Old format: global max across project (integers only, skip CAT-NNN)
max_num = 0
for t in existing:
tid = t["id"]
if tid.startswith(prefix + "-"):
suffix = tid[len(prefix) + 1:]
try:
max_num = max(max_num, int(suffix))
except ValueError:
pass
return f"{prefix}-{max_num + 1:03d}"
def create_task(
conn: sqlite3.Connection,
id: str,
@ -145,16 +188,17 @@ def create_task(
spec: dict | None = None,
forgejo_issue_id: int | None = None,
execution_mode: str | None = None,
category: str | None = None,
) -> dict:
"""Create a task linked to a project."""
conn.execute(
"""INSERT INTO tasks (id, project_id, title, status, priority,
assigned_role, parent_task_id, brief, spec, forgejo_issue_id,
execution_mode)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
execution_mode, category)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
(id, project_id, title, status, priority, assigned_role,
parent_task_id, _json_encode(brief), _json_encode(spec),
forgejo_issue_id, execution_mode),
forgejo_issue_id, execution_mode, category),
)
conn.commit()
return get_task(conn, id)