feat(v2): 实现SQLite对公租赁经验加工与卡片预审轨迹闭环

This commit is contained in:
2026-10-01 13:38:03 +08:00
parent 9c351b08d3
commit fa4163b2d0
60 changed files with 2111 additions and 59 deletions
+6 -12
View File
@@ -66,8 +66,6 @@ def dimension_results(frozen_plan: dict, findings) -> list[dict]:
for item in items:
states.add(item.get("result"))
bases.extend(item.get("evidence_ids") or [])
# 静默不等于通过(BR-07):任一被引用的组件没有结果,维度就不能算已核查。
# issue 优先于 unknown —— 具体的阻断比"信息缺失"更该被看到。
unreported = len(refs) - reported
if states & {"issue"}:
state = "blocked"
@@ -122,7 +120,6 @@ def assemble(run_body: dict, frozen_plan: dict, decision: dict, judgment_config,
"versions": versions_block(frozen_plan, {"trajectory_id": trajectory_id}
if trajectory_id else None),
"dimension_results": dimension_results(frozen_plan, decision.get("findings")),
# 证据是界面"查看依据"的实体来源;超长只截断列表,不改内容
"evidence": [dict(item) for item in (run_body.get("evidence") or ())][:200],
"run_instruction": run_body.get("requirement") or "",
"created_at": run_body.get("created_at") or store.now(),
@@ -131,8 +128,6 @@ def assemble(run_body: dict, frozen_plan: dict, decision: dict, judgment_config,
if status in ("completed", "partial"):
body["probability_view"] = probability_view(snapshot_id)
result = ScreeningRun(**body).model_dump(mode="json")
# 最后一道闸:契约已把这两个字段的类型限死为 None,这里再显式确认一次,
# 使得"未校准就没有概率"在装配出口也是可读的断言而不是隐含约束。
if result["probability"] is not None:
raise ValueError("未校准时不得产出审批概率")
if (result.get("probability_view") or {}).get("real_estimate") is not None:
@@ -151,9 +146,7 @@ def assert_versions_frozen(screening: dict) -> None:
raise ValueError("启用专项的运行必须冻结配置 ID 与修订")
# ---------------------------------------------------------------- 执行链装配(纠偏第一批)
# 证据成熟度刻度。**只表达证据成熟度,不看结论好坏**:发现问题不会降阶段,
# 通过也不会升到人工复核(见 docs/v2/16-delivery-corrections.md BR-46)。
STAGE_SCALE_ID = "evidence-stage"
STAGE_SCALE_VERSION = "1.0.0"
STAGE_LEVELS = [
@@ -168,12 +161,11 @@ DISABLED_JUDGMENT_CONFIG = {
"disabled_reason": "本次运行未启用专项判断;主审仍按规则、工具与经验形成意见",
}
# 阶段 3/4 需要"核验记录"或"人工复核记录"这类依据,P0 的执行链还产不出,
# 因此自动映射只会落在 0–2;3/4 保留给后续判别路径,不在这里臆造。
def stage_from_check(item) -> int:
"""核查项 → 证据成熟度阶段(BR-46)。"""
if item.get("result") in (None, "not_applicable"):
if item.get("result") in (None, "not_applicable", "error"):
return 0
return 2 if item.get("evidence_ids") else 1
@@ -296,14 +288,16 @@ def screening_from_run(run: dict, data_domain: str = "demo",
"content_hash": components.get("content_hash"),
"dimensions": dimensions,
}
decision = policy.decide(checks, _missing_inputs(steps, run), _degradations(steps, run))
hard_codes = [c['code'] for rule in rules if rule.get('effect') == 'hard' and rule.get('on_match', 'block') == 'block' for c in rule.get('conditions', []) if c.get('code')]
critical = components.get('plan', {}).get('critical_check_ids', [])
decision = policy.decide(checks, _missing_inputs(steps, run), _degradations(steps, run),
critical_check_ids=critical, hard_rule_codes=hard_codes,
rule_versions=[{'id': r['id'], 'version': r['version']} for r in rules])
decision["findings"] = [dict(item) for item in run.get("findings") or ()]
view = assemble(run, frozen_plan, decision,
judgment_config or DISABLED_JUDGMENT_CONFIG,
data_domain=data_domain,
status=str(run.get("status") or "completed"),
trajectory_id=run.get("id"))
# 维度状态用**本次执行的步骤与核查项**算(含跑通但无问题的项):
# 只看待办 finding 会把通过的维度误判成未核查。
view["dimension_results"] = dimension_results(frozen_plan, dimension_inputs)
return ScreeningRun(**view).model_dump(mode="json")