v7 mech-2: split scorecard into code/production/product tables

(cherry picked from commit 67b7f5e42d001b655aef3e04e1d3c1d98166b98f)

Reconcile-port: handler_admin.py hunks redirected into cloud/server.py _audit_scorecard (target keeps 6-mixin split; scorecard module itself applied cleanly).
This commit is contained in:
host committed 2026-11-03 02:49:27 +00:00
1 parent 19fe4fc7e1
commit f8a6a9d258
3 files changed
+526 -33

No files matched your search

+294
View File
@@ -0,0 +1,294 @@
"""v7 机制第 2 项:三张表拆分定向测试。
维分配(与 cloud/audit_scorecard.py 的注释一致):
- 代码表:delivery_quality、gate_audit、arch_contract、test_coverage
(代码证据,不含生产项)。
- 生产表:security_ledger、cost_quota、ops_scale(生产证据)。
- 产品表:全部 7 维 + 真实产品轮门禁;无真实产品轮证据时恒 not_pass,
这只是评分卡输入结构拆分,不代表任何产品功能已落地。
钉住的规则:
- 代码表 overall 独立:生产证据缺失、B/C 用户侧项 pending,
都不拉低代码表。
- 生产表缺项不拉低代码表;生产表 overall 独立,平均分不作依据。
- 三张表各自 average_is_not_pass_criterion=True。
- 阈值默认值一律 test_default_unapproved,未拍板。
- 端点 GET /audit-scorecard 返回的示例卡带 code/production/product
三个子对象(端点已接线,非冒充)。
"""
import http.client
import json
import os
import sys
import tempfile
import threading
import unittest
from pathlib import Path
try:
from cloud.audit_scorecard import (
CODE_DIMENSION_IDS, DEFAULT_THRESHOLDS, PRODUCTION_DIMENSION_IDS,
PRODUCT_DIMENSION_IDS, build_code_scorecard,
build_product_scorecard, build_production_scorecard, build_scorecard,
example_scorecard_as_of_2026_10_31)
from cloud.auth import AuthStore
from cloud.server import create_server
except ImportError:
sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
from cloud.audit_scorecard import (
CODE_DIMENSION_IDS, DEFAULT_THRESHOLDS, PRODUCTION_DIMENSION_IDS,
PRODUCT_DIMENSION_IDS, build_code_scorecard,
build_product_scorecard, build_production_scorecard, build_scorecard,
example_scorecard_as_of_2026_10_31)
from cloud.auth import AuthStore
from cloud.server import create_server
def _code_evidence():
return {
"delivery_quality": {
"first_pass_rate": 0.96, "defect_rate": 0.01,
"rework_rate": 0.04, "first_pass_known": True,
"defect_known": True, "rework_known": True,
"attempts_present": True, "evidence_kind": "real",
},
"gate_audit": {
"hard_gate_enforced": True, "gate_items_passed": 5,
"gate_items_total": 5, "merge_blocked_verified": True,
"loop_end_to_end_verified": True,
"sampling_misjudgment_rate": 0.0,
},
"arch_contract": {
"contract_frozen": True, "arch_violations": 0,
"directory_violations": 0, "import_violations": 0,
"stack_changed_without_approval": False,
},
"test_coverage": {
"prd_coverage_rate": 1.0, "cross_matrix_coverage_rate": 1.0,
"coverage_pct": 0.92, "cross_matrix_kind": "real",
"real_pg": True, "real_service": True,
"agent_six_complete": True,
"lint_items": 0, "mypy_items": 0, "bandit_high": 0,
},
}
def _production_evidence():
return {
"security_ledger": {
"ledger_verify_ok": True, "ledger_coverage_rate": 1.0,
"branch_protection": "protected",
"shell_whitelist_pass_rate": 1.0, "anchor_check_recent": True,
},
"cost_quota": {
"cost_records_complete": True, "unpriced_as_zero": False,
"per_creator_present": True, "quota_cutoff_verified": True,
},
"ops_scale": {
"ci_green_rate": 1.0, "deploy_success_rate": 1.0,
"rollback_drill_done": True, "ha_status": "second_host",
"parallel_scale_proven": 40,
},
}
def _full_evidence():
ev = {}
ev.update(_code_evidence())
ev.update(_production_evidence())
return ev
def _product_evidence():
return {
"real_product_round": True,
"real_app_installed": True,
"real_user_flow_verified": True,
"product_round_as_of": "2026-11-02",
}
class SplitTablesTestCase(unittest.TestCase):
def test_dimension_allocation_is_pinned(self):
self.assertEqual(CODE_DIMENSION_IDS, [
"delivery_quality", "gate_audit", "arch_contract",
"test_coverage"])
self.assertEqual(PRODUCTION_DIMENSION_IDS, [
"security_ledger", "cost_quota", "ops_scale"])
self.assertEqual(PRODUCT_DIMENSION_IDS, [
"delivery_quality", "gate_audit", "arch_contract",
"test_coverage", "security_ledger", "cost_quota", "ops_scale"])
self.assertFalse(set(CODE_DIMENSION_IDS)
& set(PRODUCTION_DIMENSION_IDS))
def test_code_table_passes_on_code_evidence_alone(self):
table = build_code_scorecard(_code_evidence())
self.assertEqual(table["overall"], "pass")
self.assertTrue(table["overall_pass"])
self.assertEqual([d["id"] for d in table["dimensions"]],
CODE_DIMENSION_IDS)
self.assertTrue(table["average_is_not_pass_criterion"])
self.assertEqual(table["thresholds_source"],
"test_default_unapproved")
for dim in table["dimensions"]:
self.assertGreaterEqual(dim["score"], 9.0)
def test_bc_all_pending_code_passes_production_not_pass(self):
# 核心验收:B/C 全 pending 时代码表仍可 pass、生产表 not_pass。
# user_side_items 在此只是占位证据,不依赖第 7 项的代码。
user_side = [{"id": "B", "status": "pending"},
{"id": "C", "status": "pending"}]
code = build_code_scorecard(_full_evidence())
prod = build_production_scorecard(
_full_evidence(), user_side_items=user_side)
self.assertEqual(code["overall"], "pass")
self.assertEqual(prod["overall"], "not_pass")
self.assertFalse(prod["overall_pass"])
self.assertTrue(prod["user_side_blocked"])
self.assertEqual([p["id"] for p in prod["user_side_pending"]],
["B", "C"])
self.assertTrue(any("B" in m for m in prod["missing_items"]))
self.assertTrue(any("C" in m for m in prod["missing_items"]))
# 挡住 overall 但不篡改维分数:生产维本身仍全 >=9。
for dim in prod["dimensions"]:
self.assertGreaterEqual(dim["score"], 9.0)
def test_bc_pending_in_dict_and_string_forms_also_blocks(self):
prod = build_production_scorecard(
_full_evidence(), user_side_items={"B": "pending"})
self.assertEqual(prod["overall"], "not_pass")
prod2 = build_production_scorecard(
_full_evidence(), user_side_items=["B"])
self.assertEqual(prod2["overall"], "not_pass")
def test_production_missing_evidence_does_not_lower_code_table(self):
# 生产证据直接缺失(不传 user_side_items 也一样):生产表
# not_pass,代码表仍 pass——缺项不跨表拉低。
code = build_code_scorecard(_code_evidence())
prod = build_production_scorecard(_code_evidence())
self.assertEqual(code["overall"], "pass")
self.assertEqual(prod["overall"], "not_pass")
for dim in prod["dimensions"]:
self.assertIsNone(dim["score"])
self.assertEqual(dim["status"], "unknown")
def test_production_passes_when_evidence_full_and_user_side_done(self):
prod = build_production_scorecard(
_full_evidence(),
user_side_items=[{"id": "B", "status": "done"},
{"id": "C", "status": "approved"}])
self.assertEqual(prod["overall"], "pass")
self.assertFalse(prod["user_side_blocked"])
self.assertEqual(prod["user_side_pending"], [])
def test_product_table_without_real_round_is_always_not_pass(self):
# 无真实产品轮证据:即使代码+生产证据全满,产品表也恒 not_pass,
# 全部维 None——绝不把代码/生产分数冒充成产品分数。
table = build_product_scorecard(_full_evidence())
self.assertEqual(table["overall"], "not_pass")
self.assertFalse(table["product_gate_passed"])
for dim in table["dimensions"]:
self.assertIsNone(dim["score"])
self.assertEqual(dim["status"], "unknown")
self.assertTrue(table["product_round_missing_fields"])
def test_product_table_with_real_round_scores_same_dimensions(self):
table = build_product_scorecard(_full_evidence(),
product_evidence=_product_evidence())
self.assertTrue(table["product_gate_passed"])
self.assertEqual(table["overall"], "pass")
self.assertEqual(len(table["dimensions"]), 7)
for dim in table["dimensions"]:
self.assertGreaterEqual(dim["score"], 9.0)
def test_product_average_91_with_one_four_still_fails(self):
# 产品表平均分规则:6 维 10 分、1 维 4 分,平均 9.1,仍 not_pass。
ev = _full_evidence()
ev["gate_audit"]["hard_gate_enforced"] = False
table = build_product_scorecard(ev,
product_evidence=_product_evidence())
self.assertEqual(table["average_score"], 9.1)
self.assertTrue(table["average_is_not_pass_criterion"])
self.assertEqual(table["overall"], "not_pass")
def test_build_scorecard_carries_three_subobjects(self):
report = build_scorecard(
_full_evidence(),
user_side_items=[{"id": "B", "status": "pending"},
{"id": "C", "status": "pending"}])
# 旧字段语义不变:7 维全满时旧 overall 仍 pass。
self.assertEqual(report["overall"], "pass")
self.assertEqual(len(report["dimensions"]), 7)
self.assertEqual(report["code"]["overall"], "pass")
self.assertEqual(report["production"]["overall"], "not_pass")
# 产品表无真实产品轮证据,恒 not_pass。
self.assertEqual(report["product"]["overall"], "not_pass")
self.assertEqual([d["id"] for d in report["code"]["dimensions"]],
CODE_DIMENSION_IDS)
self.assertEqual(
[d["id"] for d in report["production"]["dimensions"]],
PRODUCTION_DIMENSION_IDS)
def test_example_card_carries_three_subobjects_all_not_pass(self):
report = example_scorecard_as_of_2026_10_31()
self.assertEqual(report["overall"], "not_pass")
self.assertEqual(report["code"]["overall"], "not_pass")
self.assertEqual(report["production"]["overall"], "not_pass")
self.assertEqual(report["product"]["overall"], "not_pass")
self.assertFalse(report["product"]["product_gate_passed"])
def test_threshold_defaults_still_unapproved_in_all_tables(self):
for entry in DEFAULT_THRESHOLDS.values():
self.assertEqual(entry["source"], "test_default_unapproved")
for table in (build_code_scorecard(_full_evidence()),
build_production_scorecard(_full_evidence()),
build_product_scorecard(_full_evidence(),
product_evidence=_product_evidence())):
self.assertEqual(table["thresholds_source"],
"test_default_unapproved")
class SplitTablesEndpointTestCase(unittest.TestCase):
def setUp(self):
self.tmp = tempfile.TemporaryDirectory()
self.db_path = os.path.join(self.tmp.name, "control.db")
self.auth = AuthStore(self.db_path)
self.owner_id, self.owner_key = self.auth.create_user("owner")
self.server = create_server(self.db_path, "127.0.0.1", 0)
self.port = self.server.server_address[1]
self.thread = threading.Thread(
target=self.server.serve_forever, daemon=True)
self.thread.start()
def tearDown(self):
self.server.shutdown()
self.server.server_close()
self.thread.join(timeout=5)
try:
self.auth.conn.close()
except Exception:
pass
self.tmp.cleanup()
def test_endpoint_returns_three_subobjects(self):
conn = http.client.HTTPConnection("127.0.0.1", self.port, timeout=10)
try:
conn.request("GET", "/audit-scorecard",
headers={"X-API-Key": self.owner_key})
resp = conn.getresponse()
report = json.loads(resp.read().decode("utf-8"))
finally:
conn.close()
self.assertEqual(resp.status, 200)
self.assertEqual(report["overall"], "not_pass")
for key in ("code", "production", "product"):
self.assertIn(key, report)
self.assertEqual(report[key]["overall"], "not_pass")
self.assertEqual(len(report["code"]["dimensions"]), 4)
self.assertEqual(len(report["production"]["dimensions"]), 3)
self.assertEqual(len(report["product"]["dimensions"]), 7)
if __name__ == "__main__":
unittest.main()