From 389b266bee26d67e02efcd1646f56090831dd38c Mon Sep 17 00:00:00 2001 From: Gros Frumos Date: Mon, 16 Mar 2026 09:58:51 +0200 Subject: [PATCH] =?UTF-8?q?kin:=20KIN-072=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20kanban=20=D0=B2=D0=B8=D0=B4=20=D0=B2=20?= =?UTF-8?q?=D1=82=D0=B0=D1=81=D0=BA=D0=B8=20=D0=BF=D1=80=D0=BE=D0=B5=D0=BA?= =?UTF-8?q?=D1=82=D0=B0.=20=D0=9A=D0=B0=D0=BD=D0=B1=D0=B0=D0=BD=20=D0=B4?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=B8=20=D1=80?= =?UTF-8?q?=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=D0=B5=D1=82.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- agents/prompts/pm.md | 2 ++ agents/prompts/tester.md | 1 + web/api.py | 9 +++++++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/agents/prompts/pm.md b/agents/prompts/pm.md index 0c1caae..2cc40fd 100644 --- a/agents/prompts/pm.md +++ b/agents/prompts/pm.md @@ -7,6 +7,7 @@ Your job: decompose a task into a pipeline of specialist steps. You receive: - PROJECT: id, name, tech stack, project_type (development | operations | research) - TASK: id, title, brief +- ACCEPTANCE CRITERIA: what the task output must satisfy (if provided — use this to verify task completeness, do NOT confuse with current task status) - DECISIONS: known issues, gotchas, workarounds for this project - MODULES: project module map - ACTIVE TASKS: currently in-progress tasks (avoid conflicts) @@ -29,6 +30,7 @@ You receive: - For features: architect first (if complex), then developer, then test + review. - Don't assign specialists who aren't needed. - If a task is blocked or unclear, say so — don't guess. +- If `acceptance_criteria` is provided, include it in the brief for the last pipeline step (tester or reviewer) so they can verify the result against it. Do NOT use acceptance_criteria to describe current task state. ## Project type routing diff --git a/agents/prompts/tester.md b/agents/prompts/tester.md index 7695dcf..107177b 100644 --- a/agents/prompts/tester.md +++ b/agents/prompts/tester.md @@ -7,6 +7,7 @@ Your job: write or update tests that verify the implementation is correct and re You receive: - PROJECT: id, name, path, tech stack - TASK: id, title, brief describing what was implemented +- ACCEPTANCE CRITERIA: what the task output must satisfy (if provided — verify tests cover these criteria explicitly) - PREVIOUS STEP OUTPUT: dev agent output describing what was changed (required) ## Your responsibilities diff --git a/web/api.py b/web/api.py index f940a4c..b958af9 100644 --- a/web/api.py +++ b/web/api.py @@ -501,6 +501,7 @@ class TaskCreate(BaseModel): priority: int = 5 route_type: str | None = None category: str | None = None + acceptance_criteria: str | None = None @app.post("/api/tasks") @@ -519,7 +520,8 @@ def create_task(body: TaskCreate): task_id = models.next_task_id(conn, body.project_id, category=category) brief = {"route_type": body.route_type} if body.route_type else None t = models.create_task(conn, task_id, body.project_id, body.title, - priority=body.priority, brief=brief, category=category) + priority=body.priority, brief=brief, category=category, + acceptance_criteria=body.acceptance_criteria) conn.close() return t @@ -534,6 +536,7 @@ class TaskPatch(BaseModel): route_type: str | None = None title: str | None = None brief_text: str | None = None + acceptance_criteria: str | None = None VALID_STATUSES = set(models.VALID_TASK_STATUSES) @@ -552,7 +555,7 @@ def patch_task(task_id: str, body: TaskPatch): raise HTTPException(400, f"Invalid route_type '{body.route_type}'. Must be one of: {', '.join(sorted(VALID_ROUTE_TYPES))} or empty string to clear") if body.title is not None and not body.title.strip(): raise HTTPException(400, "title must not be empty") - all_none = all(v is None for v in [body.status, body.execution_mode, body.priority, body.route_type, body.title, body.brief_text]) + all_none = all(v is None for v in [body.status, body.execution_mode, body.priority, body.route_type, body.title, body.brief_text, body.acceptance_criteria]) if all_none: raise HTTPException(400, "Nothing to update.") conn = get_conn() @@ -581,6 +584,8 @@ def patch_task(task_id: str, body: TaskPatch): if body.brief_text is not None: current_brief = {**current_brief, "text": body.brief_text} fields["brief"] = current_brief if current_brief else None + if body.acceptance_criteria is not None: + fields["acceptance_criteria"] = body.acceptance_criteria models.update_task(conn, task_id, **fields) t = models.get_task(conn, task_id) conn.close()