fix: second-audit gate findings (B1, I1-I8, M1-M10)
B1: gateway capability check now triggers on walking the sub2api gateway, not on the gateway having filled a model; task-level explicit models are audited (worker_capability_gateway_explicit) but never blocked, preserving explicit priority; gateway-default models still fail-fast under active. I1: dry-run adds a gateway-model section, sourced only from CLOUD_SUB2API_DEFAULT_MODEL (never queries the relay); an active tier whose requires the gateway model fails or cannot verify blocks, shadow only warns. I2: shadow review gate now counts completed samples (completed >= 20), same basis for sample_shortfall; the endpoint attaches per-tier capability status (read-only policy load) and flags capability-failing tiers in the recommendation. I3: configured-but-broken routing policy logs a warning in load_routing_policy (unconfigured stays silent); the worker sets routing_policy_load_failed and audits worker_routing_policy_load_failed per task. I4: resume preamble wraps prior output/error as data with an explicit do-not-execute constraint; position verified in run_one (tree -> preamble -> project -> original) and the docs corrected from the false 'closest to the original prompt' claim. I5: decided model is written back with a CAS UPDATE (model IS NULL OR model=''), so later attempts reuse it; explicit models are never overwritten. I6: agent_* columns added to worker._ensure_result_columns and db.init_postgres_schema backfill; migrations backfills them for tasks before insert (sender_task_id pattern); column-level tests for agent_tool_approvals and task_attempts. I7: coordinator requeue adds AND status=<snapshot> (rowcount 0 skips requeue/audit) and filters paused_by_user / user_cancel / user_pause children, which are never revived or cleared. I8: explicit-model tasks (including coordinator children that inherited a parent model) audit a source=explicit worker_routing row; evaluate_shadow counts it as per-tier explicit_n only, never routed_n, never a dedup slot. M1/M2/M3/M5/M6/M8/M10: dedup slot moved after tier validation, shadow sort doc fixed, truncated recommendation notes truncation, seed cleanup on gateway/quota/goal-cap early returns, tools-only coordinator definitions rejected, preamble goal branch marked effectively unreachable, DESIGN.md drift corrected (outside repo). M4/M7/M9: documentation/new-field only (pass_rate_fully_measured, whitespace-model shadow-drop note, bound-note race note); old field semantics unchanged.
This commit is contained in:
1 parent
f9a77577c5
commit
621c08d10f
13 files changed
+907
-44
No files matched your search
@@ -113,6 +113,24 @@ def _make_sqlite(path):
|
||||
conn.execute("INSERT INTO environments VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
("e1", "p1", "dev", "main", "docker", "ready", "",
|
||||
"https://example.invalid/r", "u1", 1.0, 1.0))
|
||||
# Audit fix 3(I6)列级覆盖用:tasks 的 agent 列与
|
||||
# task_attempts 整表,表级在清单里已有不算覆盖。
|
||||
conn.execute("CREATE TABLE tasks(id TEXT PRIMARY KEY,"
|
||||
" project_id TEXT, agent_name TEXT,"
|
||||
" agent_version TEXT, agent_instructions TEXT,"
|
||||
" agent_tools TEXT, agent_tool_approvals TEXT)")
|
||||
conn.execute("INSERT INTO tasks VALUES(?, ?, ?, ?, ?, ?, ?)",
|
||||
("t1", "p1", "research-brief", "v1", "do x", "[]",
|
||||
'{"websearch": "ask"}'))
|
||||
conn.execute("CREATE TABLE task_attempts(task_id TEXT,"
|
||||
" attempt_no INTEGER, kind TEXT,"
|
||||
" interrupted_reason TEXT, checkpoint_round INTEGER,"
|
||||
" result_text TEXT, error_text TEXT,"
|
||||
" created_at REAL,"
|
||||
" PRIMARY KEY(task_id, attempt_no))")
|
||||
conn.execute("INSERT INTO task_attempts VALUES(?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
("t1", 1, "platform_fresh", "worker_shutdown", -1,
|
||||
"", "", 1.0))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
@@ -186,6 +204,42 @@ class TestMigrateNewTables(unittest.TestCase):
|
||||
self.assertEqual(len(fu_inserts), 1)
|
||||
self.assertIn("sender_task_id", fu_inserts[0])
|
||||
|
||||
def test_agent_columns_added_and_attempts_migrated(self):
|
||||
# Audit fix 3(I6):PG 侧 tasks 尚无 agent 列时,
|
||||
# 迁移必须先 ALTER 补齐 5 列再直插;task_attempts
|
||||
# 行必须按列原样迁过去(表级在清单里不算列级覆盖)。
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
src = os.path.join(tmp, "src.db")
|
||||
_make_sqlite(src)
|
||||
fake = FakePgConn(pragma_columns={
|
||||
"projects": {"repo_url"},
|
||||
"tasks": {"id", "project_id"},
|
||||
"task_followups": {"id", "task_id", "project_id",
|
||||
"body", "mode", "status",
|
||||
"created_by", "sender_task_id",
|
||||
"created_at", "updated_at"},
|
||||
})
|
||||
result = migrate_sqlite_to_postgres(src, pg_conn=fake)
|
||||
self.assertEqual(result.get("tasks"), 1, "tasks")
|
||||
self.assertEqual(result.get("task_attempts"), 1, "task_attempts")
|
||||
for col in ("agent_name", "agent_version",
|
||||
"agent_instructions", "agent_tools",
|
||||
"agent_tool_approvals"):
|
||||
self.assertTrue(
|
||||
any("tasks" in a and col in a for a in fake.alters),
|
||||
"未发出 tasks.%s 补列 ALTER:%s" % (col, fake.alters))
|
||||
tasks_inserts = [cols for t, cols in fake.inserts
|
||||
if t == "tasks"]
|
||||
self.assertEqual(len(tasks_inserts), 1)
|
||||
self.assertIn("agent_tool_approvals", tasks_inserts[0])
|
||||
attempts_inserts = [cols for t, cols in fake.inserts
|
||||
if t == "task_attempts"]
|
||||
self.assertEqual(len(attempts_inserts), 1)
|
||||
for col in ("task_id", "attempt_no", "kind",
|
||||
"interrupted_reason", "checkpoint_round",
|
||||
"result_text", "error_text", "created_at"):
|
||||
self.assertIn(col, attempts_inserts[0])
|
||||
|
||||
def test_sender_column_present_skips_alter(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
src = os.path.join(tmp, "src.db")
|
||||
|
||||
Reference in new issue
Block a user