Tighten report layout and gate contract evidence
This commit is contained in:
@@ -8,7 +8,7 @@ from typing import Any
|
||||
from review_studio_actions import build_review_actions, render_review_actions
|
||||
from review_studio_data import evidence_paths, insight_cards, load_review_data
|
||||
from review_studio_formatting import registry_package_summary, render_kv_grid
|
||||
from review_studio_gates import add_blockers_from_gate, build_gates, status_label, weighted_score
|
||||
from review_studio_gates import add_blockers_from_gate, build_gates, gate_contract, status_label, weighted_score
|
||||
from review_studio_layout import render_review_nav, review_studio_css
|
||||
from review_studio_output_review import render_output_review_section
|
||||
from review_studio_skillops import render_skillops_section
|
||||
@@ -123,6 +123,19 @@ def render_html(report: dict[str, Any]) -> str:
|
||||
description = overview.get("description") or frontmatter.get("description", "")
|
||||
nav_html = render_review_nav()
|
||||
gates_html = render_gate_list(gates)
|
||||
gate_contract_panel = render_kv_grid(
|
||||
report.get("gate_contract", {}),
|
||||
[
|
||||
"ok",
|
||||
"expected_gate_count",
|
||||
"actual_gate_count",
|
||||
"missing_gate_keys",
|
||||
"unknown_gate_keys",
|
||||
"duplicate_gate_keys",
|
||||
"unweighted_gate_keys",
|
||||
],
|
||||
"gate contract missing",
|
||||
)
|
||||
metrics_html = render_insights(insights)
|
||||
blockers_html = render_issue_list("阻断事项", blockers)
|
||||
warnings_html = render_issue_list("关注事项", warnings)
|
||||
@@ -413,6 +426,11 @@ def render_html(report: dict[str, Any]) -> str:
|
||||
<div class="gates">{gates_html}</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>闸门契约</h2>
|
||||
<div class="panel">{gate_contract_panel}</div>
|
||||
</section>
|
||||
|
||||
<div class="twocol">
|
||||
{blockers_html}
|
||||
{warnings_html}
|
||||
@@ -584,6 +602,7 @@ def render_review_studio(skill_dir: Path, output_html: Path | None = None, outpu
|
||||
output_json = output_json or reports_dir / "review-studio.json"
|
||||
data = load_review_data(skill_dir)
|
||||
gates = build_gates(skill_dir, output_html, data)
|
||||
contract = gate_contract(gates)
|
||||
blockers, warnings = add_blockers_from_gate(gates)
|
||||
review_actions = build_review_actions(gates, skill_dir, output_html, data)
|
||||
score = weighted_score(gates)
|
||||
@@ -593,12 +612,13 @@ def render_review_studio(skill_dir: Path, output_html: Path | None = None, outpu
|
||||
decision = "blocked" if blockers or open_annotation_blockers else ("review" if warnings or open_annotation_warnings else "ready")
|
||||
report = {
|
||||
"schema_version": "2.0",
|
||||
"ok": True,
|
||||
"ok": contract["ok"],
|
||||
"skill_dir": display_path(skill_dir, skill_dir),
|
||||
"summary": {
|
||||
"decision": decision,
|
||||
"world_class_score": score,
|
||||
"gate_count": len(gates),
|
||||
"gate_contract_ok": contract["ok"],
|
||||
"blocker_count": len(blockers),
|
||||
"warning_count": len(warnings),
|
||||
"action_count": len(review_actions),
|
||||
@@ -608,6 +628,7 @@ def render_review_studio(skill_dir: Path, output_html: Path | None = None, outpu
|
||||
"open_annotation_warning_count": open_annotation_warnings,
|
||||
},
|
||||
"gates": gates,
|
||||
"gate_contract": contract,
|
||||
"blockers": blockers,
|
||||
"warnings": warnings,
|
||||
"review_actions": review_actions,
|
||||
|
||||
@@ -19,6 +19,7 @@ LABELS = {
|
||||
"archive_entry_count": "Zip 条目",
|
||||
"archive_present": "归档存在",
|
||||
"archive_sha256": "归档哈希",
|
||||
"actual_gate_count": "实际 Gate",
|
||||
"answer_revealed_count": "答案揭示",
|
||||
"baseline_pass_rate": "Baseline",
|
||||
"breaking_change_count": "破坏变更",
|
||||
@@ -31,7 +32,9 @@ LABELS = {
|
||||
"declared_bump": "声明版本",
|
||||
"decision": "决策",
|
||||
"delta": "增益",
|
||||
"duplicate_gate_keys": "重复 Gate",
|
||||
"event_count": "事件数",
|
||||
"expected_gate_count": "期望 Gate",
|
||||
"failure_count": "失败数",
|
||||
"file_count": "文件数",
|
||||
"fstring_311_violation_count": "F-string 3.11",
|
||||
@@ -56,6 +59,7 @@ LABELS = {
|
||||
"metadata_fallback_count": "Metadata fallback",
|
||||
"missed_trigger_count": "漏触发",
|
||||
"missing_count": "缺失数",
|
||||
"missing_gate_keys": "缺失 Gate",
|
||||
"module_count": "模块数",
|
||||
"model_executed_count": "模型执行",
|
||||
"name": "名称",
|
||||
@@ -85,6 +89,7 @@ LABELS = {
|
||||
"recommended_pr_count": "建议 PR",
|
||||
"recommended_bump": "建议版本",
|
||||
"release_lock_ready": "发布锁",
|
||||
"rendered_gate_keys": "渲染 Gate",
|
||||
"residual_risk_count": "残余风险",
|
||||
"risk_band": "风险带",
|
||||
"route_collision_count": "路由冲突",
|
||||
@@ -103,6 +108,8 @@ LABELS = {
|
||||
"token_estimated_count": "估算 Token",
|
||||
"token_observed_count": "真实 Token",
|
||||
"trust_level": "信任级别",
|
||||
"unknown_gate_keys": "未知 Gate",
|
||||
"unweighted_gate_keys": "未加权 Gate",
|
||||
"unique_opportunity_count": "唯一机会",
|
||||
"variant_run_count": "运行数",
|
||||
"valid_submission_count": "有效提交",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
import json
|
||||
import os
|
||||
from collections import Counter
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
@@ -80,6 +81,27 @@ def add_blockers_from_gate(gates: list[dict[str, str]]) -> tuple[list[dict[str,
|
||||
return blockers, warnings
|
||||
|
||||
|
||||
def gate_contract(gates: list[dict[str, str]]) -> dict[str, Any]:
|
||||
rendered_gate_keys = [str(item.get("key", "")) for item in gates]
|
||||
rendered_gate_set = set(rendered_gate_keys)
|
||||
expected_gate_set = set(REVIEW_STUDIO_GATE_KEYS)
|
||||
duplicate_gate_keys = sorted(key for key, count in Counter(rendered_gate_keys).items() if count > 1)
|
||||
missing_gate_keys = sorted(expected_gate_set - rendered_gate_set)
|
||||
unknown_gate_keys = sorted(rendered_gate_set - expected_gate_set)
|
||||
unweighted_gate_keys = sorted(rendered_gate_set - set(GATE_WEIGHTS))
|
||||
return {
|
||||
"ok": not (missing_gate_keys or unknown_gate_keys or duplicate_gate_keys or unweighted_gate_keys),
|
||||
"expected_gate_count": len(expected_gate_set),
|
||||
"actual_gate_count": len(rendered_gate_keys),
|
||||
"expected_gate_keys": sorted(expected_gate_set),
|
||||
"rendered_gate_keys": rendered_gate_keys,
|
||||
"missing_gate_keys": missing_gate_keys,
|
||||
"unknown_gate_keys": unknown_gate_keys,
|
||||
"duplicate_gate_keys": duplicate_gate_keys,
|
||||
"unweighted_gate_keys": unweighted_gate_keys,
|
||||
}
|
||||
|
||||
|
||||
def target_maturity(skill_dir: Path, overview: dict[str, Any]) -> str:
|
||||
manifest = _load_json(skill_dir / "manifest.json")
|
||||
if manifest.get("maturity_tier"):
|
||||
|
||||
Reference in New Issue
Block a user