audit: task-attempt ledger feeds real first-pass/defect/rework rates (gap 3)
- cloud/attempt_ledger.py: separate task_attempts table (not tasks columns) with per-attempt rows, MAX+1 attempt_no, append-only intent; interrupted rows kept but never counted; is_defect is explicit, never inferred from failure; first defect category wins; no-ledger tasks stay unknown (None), never backfilled. SQLite DDL is CREATE TABLE IF NOT EXISTS (idempotent); PG_DDL is the verbatim manual step for production Postgres, kept out of POSTGRES_SCHEMA on purpose (migrations coverage untouched). - cloud/server.py GET /metrics-report: aggregates the ledger into compute_metrics records; missing ledger table degrades to unknown rates, not an error. Cost dual-column code untouched. - cloud/metrics.py: docstring only (ledger is now the source); compute_metrics logic and all #238 semantics unchanged. - Tests: 16 ledger tests (store/aggregate/metrics/PG adapter evidence) + 3 endpoint tests (real rates, old task beside ledger task, interrupted status non-terminal).
This commit is contained in:
1 parent
238ebbdbd2
commit
0db51f8145
6 files changed
+639
-22
No files matched your search
+19
-6
@@ -154,6 +154,9 @@ from cloud.approvals import ensure_approvals_table as _appr_ensure
|
||||
from cloud.approvals import expire_overdue as _appr_expire
|
||||
from cloud.approvals import get_approval as _appr_get
|
||||
from cloud.approvals import list_approvals as _appr_list
|
||||
from cloud.attempt_ledger import aggregate_attempts as _aggregate_attempts
|
||||
from cloud.attempt_ledger import apply_to_records as _apply_attempts
|
||||
from cloud.attempt_ledger import read_attempt_rows as _read_attempt_rows
|
||||
from cloud.auto_memory import AutoMemoryStore
|
||||
from cloud.auto_memory import process_due_tasks as _auto_process_due
|
||||
from cloud.identity import IdentityStore
|
||||
@@ -9638,12 +9641,14 @@ pid 须为整数、address 须为字符串,否则 400(注册表里的
|
||||
"""指标闭环报告:首过绿灯率 / 缺陷率 / 返工率 / 每任务成本。
|
||||
|
||||
权限与 /metrics 同款:只统计调用者是成员的项目。
|
||||
诚实边界:当前 tasks 表没有 attempts/defects 列,所以
|
||||
attempts/defects 一律传 None,首过/缺陷/返工率回 None
|
||||
(未知,不报 0);金任务集未经人工审定,报告恒为
|
||||
pending_human_approval、decision_ready False。等任务尝试
|
||||
台账落库、金任务人工审定后,这两处再接真实输入——
|
||||
在此之前绝不把样本集或未知率包装成可决策数字。
|
||||
台账(audit gap 3,见 ``cloud/attempt_ledger.py``):任务的
|
||||
attempts/defects 来自 ``task_attempts`` 台账的聚合,不再
|
||||
恒为 None;台账里只有中断行的任务、以及台账里根本没有
|
||||
行的老任务,仍传 None——未知率回 None(未知,不报 0),
|
||||
老任务绝不被算成首过或无缺陷。台账表尚不存在(老库、
|
||||
或生产 PG 未手动执行 ``PG_DDL``)时与无台账行同等处理,
|
||||
不因此让端点报错;金任务集未经人工审定,报告恒为
|
||||
pending_human_approval、decision_ready False。
|
||||
成本走 #212 双列口径:有价合计与无价 actual token 分开,
|
||||
总额在成本不完整时为 None,不把无价折成 0。
|
||||
"""
|
||||
@@ -9662,6 +9667,14 @@ pid 须为整数、address 须为字符串,否则 400(注册表里的
|
||||
"attempts": None, "defects": None}
|
||||
for row in rows
|
||||
if row["project_id"] in member_ids]
|
||||
try:
|
||||
aggregates = _aggregate_attempts(
|
||||
_read_attempt_rows(conn))
|
||||
except (sqlite3.OperationalError, _PgOperationalError):
|
||||
# No ledger table yet (old DB, or production PG
|
||||
# before the manual PG_DDL step): same as no rows.
|
||||
aggregates = {}
|
||||
records = _apply_attempts(records, aggregates)
|
||||
try:
|
||||
cost_rows = conn.execute(
|
||||
"SELECT task_id, project_id, source, total_tokens,"
|
||||
|
||||
Reference in new issue
Block a user