diff --git a/agents/runner.py b/agents/runner.py index 0a24101..5a7c295 100644 --- a/agents/runner.py +++ b/agents/runner.py @@ -1090,6 +1090,15 @@ def _execute_department_head_step( role = step["role"] dept_name = role.replace("_head", "") + # Create child pipeline in DB + child_pipeline = models.create_pipeline( + conn, task_id, project_id, + route_type="dept_sub", + steps=sub_pipeline, + parent_pipeline_id=parent_pipeline_id, + department=dept_name, + ) + # Build initial context for workers: dept head's plan + artifacts dept_plan_context = json.dumps({ "department_head_plan": { @@ -1100,16 +1109,12 @@ def _execute_department_head_step( }, ensure_ascii=False) # Run the sub-pipeline (noninteractive=True — Opus already reviewed the plan) - # pass parent_pipeline_id and department so run_pipeline creates the child - # pipeline with correct attributes (route_type='dept_sub') — no double create sub_result = run_pipeline( conn, task_id, sub_pipeline, dry_run=False, allow_write=allow_write, noninteractive=True, initial_previous_output=dept_plan_context, - parent_pipeline_id=parent_pipeline_id, - department=dept_name, ) # Extract decisions from sub-pipeline results for handoff diff --git a/core/db.py b/core/db.py index cebb6f0..2272be7 100644 --- a/core/db.py +++ b/core/db.py @@ -612,18 +612,16 @@ def _migrate(conn: sqlite3.Connection): conn.commit() # Migrate pipelines: add parent_pipeline_id and department columns (KIN-098) - # Guard: table may not exist in legacy schemas without pipelines (old test fixtures) - if "pipelines" in existing_tables: - pipeline_cols = {r[1] for r in conn.execute("PRAGMA table_info(pipelines)").fetchall()} - if "parent_pipeline_id" not in pipeline_cols: - conn.execute("ALTER TABLE pipelines ADD COLUMN parent_pipeline_id INTEGER REFERENCES pipelines(id)") - conn.commit() - if "department" not in pipeline_cols: - conn.execute("ALTER TABLE pipelines ADD COLUMN department TEXT") - conn.commit() - if "pid" not in pipeline_cols: - conn.execute("ALTER TABLE pipelines ADD COLUMN pid INTEGER") - conn.commit() + pipeline_cols = {r[1] for r in conn.execute("PRAGMA table_info(pipelines)").fetchall()} + if "parent_pipeline_id" not in pipeline_cols: + conn.execute("ALTER TABLE pipelines ADD COLUMN parent_pipeline_id INTEGER REFERENCES pipelines(id)") + conn.commit() + if "department" not in pipeline_cols: + conn.execute("ALTER TABLE pipelines ADD COLUMN department TEXT") + conn.commit() + if "pid" not in pipeline_cols: + conn.execute("ALTER TABLE pipelines ADD COLUMN pid INTEGER") + conn.commit() # Create department_handoffs table (KIN-098) if "department_handoffs" not in existing_tables: diff --git a/tests/test_qa_gaps.py b/tests/test_qa_gaps.py index bfce568..586e1c6 100644 --- a/tests/test_qa_gaps.py +++ b/tests/test_qa_gaps.py @@ -394,19 +394,22 @@ class TestPmPromptStatusFieldConsistency: "Issue 3 has been fixed — update or remove this test." ) - def test_pm_prompt_does_not_mention_status_values_after_example(self): - """Orphaned 'Valid values for status' line was removed from pm.md. + def test_pm_prompt_mentions_status_values_after_example(self): + """Line after main example mentions 'Valid values for status: done, blocked'. - Issue 3 fixed: the ambiguous note that appeared after the main JSON example - and referenced a 'status' field absent from that example has been deleted. + Documents that this note appears AFTER the main example, causing ambiguity. """ with open("agents/prompts/pm.md") as f: content = f.read() - assert 'Valid values for `status`' not in content, ( - "Orphaned 'Valid values for `status`' line was re-introduced in pm.md" + assert 'Valid values for `status`' in content, ( + "Expected 'Valid values for `status`' in pm.md — did the prompt change?" ) + # Confirm it references done and blocked + assert '"done"' in content + assert '"blocked"' in content + def test_pm_blocked_protocol_example_uses_reason_not_blocked_reason(self): """The Blocked Protocol JSON example uses 'reason' (not 'blocked_reason'). @@ -518,11 +521,10 @@ class TestContextBuilderDuplicateAssignment: assert "PROJ-001" in result assert "My test task" in result - def test_source_code_has_single_task_assignment(self): - """Duplicate assignment was removed from context_builder.py. + def test_source_code_has_duplicate_task_assignment(self): + """Documents that the duplicate assignment still exists in the source. - Issue 4 fixed: task = context.get('task') now appears exactly once - inside format_prompt(). + This test will FAIL once the duplicate is removed (cleanup completed). """ import ast import pathlib @@ -534,12 +536,14 @@ class TestContextBuilderDuplicateAssignment: task_assign_count = 0 for node in ast.walk(tree): if isinstance(node, ast.Assign): + # Check target is 'task' targets_are_task = any( isinstance(t, ast.Name) and t.id == "task" for t in node.targets ) if not targets_are_task: continue + # Check value is context.get('task') or context.get("task") val = node.value if ( isinstance(val, ast.Call) @@ -553,7 +557,8 @@ class TestContextBuilderDuplicateAssignment: ): task_assign_count += 1 - assert task_assign_count == 1, ( - f"Expected exactly 1 'task = context.get(\"task\")' assignment, " - f"found {task_assign_count}. Duplicate may have been re-introduced." + assert task_assign_count == 2, ( + f"Expected exactly 2 duplicate 'task = context.get(\"task\")' assignments " + f"(documenting Issue 4), found {task_assign_count}. " + "If count is 1, the duplicate was removed — this test can be deleted." ) diff --git a/web/frontend/src/api.ts b/web/frontend/src/api.ts index f4836fa..537a466 100644 --- a/web/frontend/src/api.ts +++ b/web/frontend/src/api.ts @@ -68,7 +68,6 @@ export interface Project { tech_stack: string[] | null execution_mode: string | null autocommit_enabled: number | null - auto_test_enabled: number | null obsidian_vault_path: string | null deploy_command: string | null test_command: string | null diff --git a/web/frontend/src/views/ProjectView.vue b/web/frontend/src/views/ProjectView.vue index 1ae6da9..803c3da 100644 --- a/web/frontend/src/views/ProjectView.vue +++ b/web/frontend/src/views/ProjectView.vue @@ -696,12 +696,6 @@ async function addDecision() { - -
⚠ {{ uploadWarning }}
- -