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
8a4e80c20d
commit
d303dedf32
6 files changed
+639
-22
No files matched your search
@@ -4,8 +4,11 @@ Only the standard library http.client; a temporary SQLite DB and a
|
||||
temporary port; no real model, no network, no secrets.
|
||||
|
||||
Covers: unauthenticated -> 401, empty project -> report shape with
|
||||
unknown rates (None, not 0) and pending golden set, and a completed
|
||||
task with a priced cost row -> terminal count and dual-column cost.
|
||||
unknown rates (None, not 0) and pending golden set, a completed
|
||||
task with a priced cost row -> terminal count and dual-column cost,
|
||||
and (audit gap 3) ledger-backed real rates, old tasks staying
|
||||
unknown beside ledger tasks, and interrupted status staying
|
||||
non-terminal even with ledger rows.
|
||||
"""
|
||||
|
||||
import http.client
|
||||
@@ -109,12 +112,90 @@ class MetricsReportEndpointTestCase(unittest.TestCase):
|
||||
"GET", "/metrics-report", key=self.owner_key)
|
||||
self.assertEqual(status, 200)
|
||||
self.assertEqual(report["metrics"]["terminal_tasks"], 1)
|
||||
# Attempts are not in the schema: first-pass stays unknown,
|
||||
# it must not be fabricated as 0 or 1 from status alone.
|
||||
# No ledger rows for this task (and no ledger table yet):
|
||||
# first-pass stays unknown, it must not be fabricated as
|
||||
# 0 or 1 from status alone.
|
||||
self.assertIsNone(report["metrics"]["first_pass_rate"])
|
||||
self.assertEqual(report["metrics"]["total_usd_micros"], 5000)
|
||||
self.assertTrue(report["metrics"]["cost_complete"])
|
||||
|
||||
def test_ledger_task_gives_real_rates(self):
|
||||
from cloud.attempt_ledger import record_attempt
|
||||
from cloud.db import connect as db_connect
|
||||
conn = db_connect(self.db_path)
|
||||
try:
|
||||
conn.execute(
|
||||
"INSERT INTO tasks(id, project_id, status) VALUES(?, ?, ?)",
|
||||
("t-led", self.project["id"], "completed"))
|
||||
conn.commit()
|
||||
record_attempt(conn, "t-led", "success")
|
||||
finally:
|
||||
conn.close()
|
||||
status, report = self._req(
|
||||
"GET", "/metrics-report", key=self.owner_key)
|
||||
self.assertEqual(status, 200)
|
||||
metrics = report["metrics"]
|
||||
self.assertEqual(metrics["terminal_tasks"], 1)
|
||||
# A ledger row exists, so 0 defects here is a real 0, not
|
||||
# a fabricated one: defect_known is True alongside 0.0.
|
||||
self.assertAlmostEqual(metrics["first_pass_rate"], 1.0)
|
||||
self.assertTrue(metrics["first_pass_known"])
|
||||
self.assertAlmostEqual(metrics["defect_rate"], 0.0)
|
||||
self.assertTrue(metrics["defect_known"])
|
||||
self.assertAlmostEqual(metrics["rework_rate"], 0.0)
|
||||
|
||||
def test_old_task_without_ledger_does_not_dilute_real_rate(self):
|
||||
from cloud.attempt_ledger import record_attempt
|
||||
from cloud.db import connect as db_connect
|
||||
conn = db_connect(self.db_path)
|
||||
try:
|
||||
conn.execute(
|
||||
"INSERT INTO tasks(id, project_id, status) VALUES(?, ?, ?)",
|
||||
("t-old", self.project["id"], "completed"))
|
||||
conn.execute(
|
||||
"INSERT INTO tasks(id, project_id, status) VALUES(?, ?, ?)",
|
||||
("t-new", self.project["id"], "merged"))
|
||||
conn.commit()
|
||||
record_attempt(conn, "t-new", "failure", is_defect=True,
|
||||
defect_category="contract")
|
||||
record_attempt(conn, "t-new", "success")
|
||||
finally:
|
||||
conn.close()
|
||||
status, report = self._req(
|
||||
"GET", "/metrics-report", key=self.owner_key)
|
||||
self.assertEqual(status, 200)
|
||||
metrics = report["metrics"]
|
||||
self.assertEqual(metrics["terminal_tasks"], 2)
|
||||
# The old task is excluded from the denominator (known-only
|
||||
# denominator, as in compute_metrics); it is neither counted
|
||||
# as first-pass nor as defect-free.
|
||||
self.assertAlmostEqual(metrics["first_pass_rate"], 0.0)
|
||||
self.assertAlmostEqual(metrics["rework_rate"], 1.0)
|
||||
self.assertAlmostEqual(metrics["defect_rate"], 1.0)
|
||||
self.assertEqual(metrics["defect_by_category"],
|
||||
{"contract": 1})
|
||||
|
||||
def test_interrupted_status_excluded_even_with_ledger_rows(self):
|
||||
from cloud.attempt_ledger import record_attempt
|
||||
from cloud.db import connect as db_connect
|
||||
conn = db_connect(self.db_path)
|
||||
try:
|
||||
conn.execute(
|
||||
"INSERT INTO tasks(id, project_id, status) VALUES(?, ?, ?)",
|
||||
("t-int", self.project["id"], "interrupted"))
|
||||
conn.commit()
|
||||
record_attempt(conn, "t-int", "failure", is_defect=True,
|
||||
defect_category="contract")
|
||||
finally:
|
||||
conn.close()
|
||||
status, report = self._req(
|
||||
"GET", "/metrics-report", key=self.owner_key)
|
||||
self.assertEqual(status, 200)
|
||||
metrics = report["metrics"]
|
||||
self.assertEqual(metrics["terminal_tasks"], 0)
|
||||
self.assertIsNone(metrics["first_pass_rate"])
|
||||
self.assertFalse(metrics["first_pass_known"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user