优化流程

This commit is contained in:
2026-09-02 13:51:35 +08:00
parent 97a03c290b
commit f3eb5dff54
71 changed files with 5290 additions and 515 deletions
@@ -19,6 +19,7 @@ class SqliteTaskRepository:
self.database_path = database_path
self.database_path.parent.mkdir(parents=True, exist_ok=True)
self._lock = RLock()
self.protocol_reset = False
self._initialize()
@contextmanager
@@ -34,11 +35,27 @@ class SqliteTaskRepository:
def _initialize(self) -> None:
with self._lock, self._connection() as connection:
# Protocol 3.1 intentionally has no migration path from the
# structured-only / review-loop task model. Deployment starts with
# an empty task database, as those tasks do not have immutable
# Markdown source artifacts to compile from.
existing = connection.execute("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'tasks'").fetchone()
if existing is not None and "'3.1'" not in str(existing[0] or ""):
self.protocol_reset = True
connection.executescript("""
DROP TABLE IF EXISTS outbox;
DROP TABLE IF EXISTS tool_audits;
DROP TABLE IF EXISTS usage_records;
DROP TABLE IF EXISTS invocations;
DROP TABLE IF EXISTS ledger;
DROP TABLE IF EXISTS model_capabilities;
DROP TABLE IF EXISTS tasks;
""")
connection.executescript(
"""
CREATE TABLE IF NOT EXISTS tasks (
task_id TEXT PRIMARY KEY,
protocol_version TEXT NOT NULL CHECK(protocol_version = '3.0'),
protocol_version TEXT NOT NULL CHECK(protocol_version = '3.1'),
request TEXT NOT NULL,
phase TEXT NOT NULL,
state_version INTEGER NOT NULL,
@@ -50,6 +67,9 @@ class SqliteTaskRepository:
last_error TEXT,
retry_from_phase TEXT NOT NULL DEFAULT '',
requirements_spec_path TEXT NOT NULL DEFAULT '',
requirements_document_path TEXT NOT NULL DEFAULT '',
completion_target_path TEXT NOT NULL DEFAULT '',
modeling_plan_path TEXT NOT NULL DEFAULT '',
clarification_path TEXT NOT NULL DEFAULT '',
requirements_contract_path TEXT NOT NULL DEFAULT '',
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
@@ -104,8 +124,8 @@ class SqliteTaskRepository:
def create_task(self, task_id: str, request: str) -> TaskState:
with self._lock, self._connection() as connection:
connection.execute(
"INSERT OR IGNORE INTO tasks(task_id, protocol_version, request, phase, state_version) VALUES (?, '3.0', ?, ?, 0)",
(task_id, request, TaskPhase.DRAFTING_REQUIREMENTS.value),
"INSERT OR IGNORE INTO tasks(task_id, protocol_version, request, phase, state_version) VALUES (?, '3.1', ?, ?, 0)",
(task_id, request, TaskPhase.DRAFTING_REQUIREMENTS_DOCUMENT.value),
)
state = self.get_state(task_id)
if state is None:
@@ -130,7 +150,7 @@ class SqliteTaskRepository:
for item in events
if item.get("event") == "accepted" and isinstance(item.get("revision_id"), str)
]
frozen = next((item for item in reversed(events) if item.get("event") == "requirements_contract_frozen"), {})
frozen = next((item for item in reversed(events) if item.get("event") == "requirements_compiled"), {})
verification_warnings = [
str(item) for item in frozen.get("verification_warnings") or () if str(item)
] if isinstance(frozen, dict) else []
@@ -141,12 +161,13 @@ class SqliteTaskRepository:
"no_progress_limit",
"candidate_runtime_execution_failure", "candidate_recovery_runtime_execution_failure",
"failed_author_format", "runtime_contract_invalid",
"completed_best_effort",
}
), {}) if state.phase in {TaskPhase.FAILED, TaskPhase.WAITING_RETRY, TaskPhase.WAITING_FOR_USER} else {}
), {}) if state.phase in {TaskPhase.COMPLETED, TaskPhase.FAILED, TaskPhase.WAITING_RETRY, TaskPhase.WAITING_FOR_USER} else {}
questions = [str(item) for item in status_event.get("questions") or () if str(item)] if isinstance(status_event, dict) else []
issues = [str(item) for item in status_event.get("issues") or () if str(item)] if isinstance(status_event, dict) else []
return {
"schema_version": "3.0",
"schema_version": "3.1",
"task_id": state.task_id,
"phase": state.phase.value,
"lifecycle": self._lifecycle(state.phase),
@@ -160,10 +181,13 @@ class SqliteTaskRepository:
"last_error": state.last_error.value if state.last_error else "",
"retry_from_phase": state.retry_from_phase.value if state.retry_from_phase else "",
"requirements_spec_path": state.requirements_spec_path,
"requirements_document_path": state.requirements_document_path,
"completion_target_path": state.completion_target_path,
"modeling_plan_path": state.modeling_plan_path,
"clarification_path": state.clarification_path,
"requirements_contract_path": state.requirements_contract_path,
"verification_status": (
"completed_with_risks" if state.phase == TaskPhase.COMPLETED and verification_warnings
"completed_with_risks" if state.phase == TaskPhase.COMPLETED and (verification_warnings or state.last_error == ErrorCode.BEST_EFFORT_COMPLETED)
else "verified" if state.phase == TaskPhase.COMPLETED
else "pending"
),
@@ -219,7 +243,7 @@ class SqliteTaskRepository:
cursor = connection.execute(
"""UPDATE tasks SET phase = ?, state_version = ?, active_revision = ?, pending_action_json = ?,
candidate_id = ?, candidate_stage_id = ?, repair_required = ?, last_error = ?, retry_from_phase = ?, requirements_spec_path = ?,
clarification_path = ?, requirements_contract_path = ?, updated_at = CURRENT_TIMESTAMP
requirements_document_path = ?, completion_target_path = ?, modeling_plan_path = ?, clarification_path = ?, requirements_contract_path = ?, updated_at = CURRENT_TIMESTAMP
WHERE task_id = ? AND state_version = ?""",
(
state.phase.value, state.version, state.active_revision,
@@ -227,6 +251,7 @@ class SqliteTaskRepository:
state.candidate_id, state.candidate_stage_id,
int(state.repair_required), state.last_error.value if state.last_error else None,
state.retry_from_phase.value if state.retry_from_phase else "", state.requirements_spec_path,
state.requirements_document_path, state.completion_target_path, state.modeling_plan_path,
state.clarification_path, state.requirements_contract_path,
state.task_id, previous_version,
),
@@ -377,6 +402,9 @@ class SqliteTaskRepository:
last_error=ErrorCode(str(row["last_error"])) if row["last_error"] else None,
retry_from_phase=TaskPhase(str(row["retry_from_phase"])) if row["retry_from_phase"] else None,
requirements_spec_path=str(row["requirements_spec_path"] or ""),
requirements_document_path=str(row["requirements_document_path"] or ""),
completion_target_path=str(row["completion_target_path"] or ""),
modeling_plan_path=str(row["modeling_plan_path"] or ""),
clarification_path=str(row["clarification_path"] or ""),
requirements_contract_path=str(row["requirements_contract_path"] or ""),
)