"""c_task_create (03-C §3.1): task queue entry creation. U-009 scope: task creation lands `status='queued'`, `assigned_org_node='planner'` (04-P `p_org_task_lifecycle` start_state, ready for the first `c_org_node_trigger` call). `c_project_create` is already built in U-002 (project_scaffold.create_project); this module only adds `c_task_create`. REQ-01's happy case ("依次触发 planner/coder/validator 三个 org_node,task.status 按状态机正确流转") is NOT achievable at this Unit's scope -- it needs c_org_node_trigger's full implementation (U-010), whose own Done criterion is almost this exact sentence. development-plan.md's U-009 line claims all three REQ-01 cases pass here; that's not accurate and is corrected in this session's notes rather than silently left as-is -- only boundary and failure are real at U-009, happy completes cumulatively once U-010 lands. """ import json import uuid class InvalidParamError(Exception): """INVALID_PARAM -- 03-C §3.1: empty goal_text, non-existent project_id, or a task_type other than 'goal' (bug_fix tasks are created by the Org Loop route, not this public-facing endpoint).""" def create_task(conn, project_id, goal_text, task_type="goal", created_via="api"): if not goal_text: raise InvalidParamError("goal_text is required") if task_type != "goal": raise InvalidParamError("task_type must be 'goal' for c_task_create") if conn.execute("SELECT 1 FROM project WHERE project_id = ?", (project_id,)).fetchone() is None: raise InvalidParamError("project_id does not exist: " + project_id) task_id = str(uuid.uuid4()) try: conn.execute( "INSERT INTO task " "(task_id, project_id, goal_text, task_type, created_via, status, loop_round, assigned_org_node) " "VALUES (?, ?, ?, ?, ?, 'queued', 0, 'planner')", (task_id, project_id, goal_text, task_type, created_via), ) conn.execute( "INSERT INTO execution_event (event_id, project_id, task_id, event_type, payload) " "VALUES (?, ?, ?, 'task_status_changed', ?)", (str(uuid.uuid4()), project_id, task_id, json.dumps({"from_status": None, "to_status": "queued"})), ) except Exception: conn.rollback() raise conn.commit() # 03-C §3.1 transaction: task insert + execution_event, same transaction return {"task_id": task_id, "status": "queued"}