kin: KIN-059 Workflow new_project с выбором команды. При создании нового проекта через GUI или CLI директор описывает проект свободным текстом и выбирает галочками какие этапы research нужны: ☐ Business analyst (бизнес-модель, аудитория, монетизация) ☐ Market researcher (конкуренты, ниша, отзывы, сильные/слабые стороны) ☐ Legal researcher (юрисдикция, лицензии, KYC/AML, GDPR) ☐ Tech researcher (API, ограничения, стоимость, альтернативы) ☐ UX designer (анализ UX конкурентов, user journey, wireframes) ☐ Marketer (стратегия продвижения, SEO, conversion-паттерны) ☐ Architect (blueprint на основе одобренных research'ей) — всегда последний Architect включается автоматически если выбран хотя бы один researcher. Каждый выбранный этап — отдельная задача на review. Директор одобряет, отклоняет, или просит доисследовать (Revise). Следующий этап только после approve предыдущего. GUI: форма 'New Project' с описанием + чекбоксы ролей + кнопка 'Start Research'. CLI: kin new-project 'описание' --roles 'business,market,tech,architect'

This commit is contained in:
Gros Frumos 2026-03-16 09:30:00 +02:00
parent 75fee86110
commit 4188384f1b
7 changed files with 820 additions and 9 deletions

View file

@ -407,6 +407,69 @@ def revise_phase(phase_id: int, body: PhaseRevise):
return result
@app.post("/api/projects/{project_id}/phases/start")
def start_project_phase(project_id: str):
"""Launch agent for the current active/revising phase in background. Returns 202.
Finds the first phase with status 'active' or 'revising', sets its task to
in_progress, spawns a background subprocess (same as /api/tasks/{id}/run),
and returns immediately so the HTTP request doesn't block on agent execution.
"""
conn = get_conn()
p = models.get_project(conn, project_id)
if not p:
conn.close()
raise HTTPException(404, f"Project '{project_id}' not found")
phases = models.list_phases(conn, project_id)
active_phase = next(
(ph for ph in phases if ph["status"] in ("active", "revising")), None
)
if not active_phase:
conn.close()
raise HTTPException(404, f"No active or revising phase for project '{project_id}'")
task_id = active_phase.get("task_id")
if not task_id:
conn.close()
raise HTTPException(400, f"Phase {active_phase['id']} has no task assigned")
t = models.get_task(conn, task_id)
if not t:
conn.close()
raise HTTPException(404, f"Task '{task_id}' not found")
models.update_task(conn, task_id, status="in_progress")
conn.close()
kin_root = Path(__file__).parent.parent
cmd = [sys.executable, "-m", "cli.main", "--db", str(DB_PATH), "run", task_id]
cmd.append("--allow-write")
import os
env = os.environ.copy()
env["KIN_NONINTERACTIVE"] = "1"
try:
proc = subprocess.Popen(
cmd,
cwd=str(kin_root),
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
stdin=subprocess.DEVNULL,
env=env,
)
_logger.info("Phase agent started for task %s (phase %d), pid=%d",
task_id, active_phase["id"], proc.pid)
except Exception as e:
raise HTTPException(500, f"Failed to start phase agent: {e}")
return JSONResponse(
{"status": "started", "phase_id": active_phase["id"], "task_id": task_id},
status_code=202,
)
# ---------------------------------------------------------------------------
# Tasks
# ---------------------------------------------------------------------------