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:
host committed 2026-11-04 18:02:21 +00:00
1 parent f9a77577c5
commit 621c08d10f
13 files changed
+907 -44

No files matched your search

+61
View File
@@ -67,6 +67,8 @@ from cloud.auth import AuthStore
from cloud.coordinator import parse_parts as _coord_parse_parts
from cloud.coordinator import validate_parts as _coord_validate_parts
from cloud.cost import CostStore, unpriced_token_cap
from cloud.models import check_model_capabilities as _check_caps
from cloud.models import load_routing_policy as _load_routing_policy
from cloud.routing_shadow import evaluate_shadow as _evaluate_shadow
from cloud.db import connect as _db_connect
from cloud.db import create_database as _create_database
@@ -4227,6 +4229,54 @@ class CloudControlPlaneHandler(BaseHTTPRequestHandler):
tasks_by_id, costs_by_task, explicit_n=explicit_n)
report["project_id"] = project_id
report["truncated"] = truncated
# Audit fix 3(I2,端点侧):只读加载当前策略,
# 给每档附能力状态(档模型 vs requires)。加载
# 失败/未配置时状态为 policy_unavailable,不拦、
# 不改任何状态;能力不满足的档即使样本够,也
# 在 recommendation 里标明——样本够不等于可激活。
# Audit fix 3(M3):截断时 recommendation 必须
# 提及截断,ready 不能建立在不说明的数据上。
try:
_policy = _load_routing_policy()
except Exception:
_policy = None
_cap_flagged = []
for _tier, _bucket in report["tiers"].items():
if _policy is None:
_cap = {"status": "policy_unavailable",
"model": None, "missing": [], "unknown": False}
else:
_req = _policy.tier_requirements.get(_tier) or {}
_model = _policy.tiers.get(_tier)
if not _req:
_cap = {"status": "not_applicable",
"model": _model, "missing": [],
"unknown": False}
elif _model is None:
_cap = {"status": "no_model",
"model": None, "missing": [],
"unknown": False}
else:
_ok, _missing, _unknown = _check_caps(
_policy.model_capabilities, _model, _req)
_cap = {"status": "ok" if _ok else (
"unknown" if _unknown else "fail"),
"model": _model, "missing": _missing,
"unknown": _unknown}
_bucket["capability"] = _cap
if _cap["status"] in ("fail", "unknown"):
_cap_flagged.append(
"%s (%s)" % (_tier, _cap["status"]))
if _cap_flagged:
report["recommendation"] += (
" Capability note: tier(s) %s do not meet their"
" requirements (or cannot be verified) — sample"
" readiness is not activation readiness."
% ", ".join(_cap_flagged))
if truncated:
report["recommendation"] += (
" Note: audit rows were truncated to 10000, so"
" this report is based on a partial sample.")
self._send_json(200, report)
def _task_cost(self, user_id, task_id):
@@ -4794,6 +4844,17 @@ class CloudControlPlaneHandler(BaseHTTPRequestHandler):
"error": "agent tool_approvals cannot be used with"
" goal/coordinator tasks"})
return
# Audit fix 3(M6):只带 tools 的定义同款拒绝。
# 旧版只拒 instructions 与 tool_approvals,单带
# tools 的协调员定义可正常创建,但父任务在网关/
# 工具门之前返回、子任务又不继承 agent_tools,
# tools 声明被无声丢弃——与同一段的拒绝理由自相矛盾。
if definition is not None and definition.tools:
if goal_mode or verify_command or coord_parts:
self._send_json(400, {
"error": "agent tools cannot be used with"
" goal/coordinator tasks"})
return
agent_name_val = definition.name if definition else None
agent_version_val = definition.version if definition else None
agent_instructions_val = (