le-app-design v1.0.0:统一 App 设计工坊——真实集成并调用三上游的编排器。ui-ux-pro-max(MIT,search.py 设计系统/规范检索)+ frontend-design(Apache-2.0,Skill 工具装载的视觉 design lead)+ impeccable(Apache-2.0,CLI 检测器+playbook 审查);三机制保证真集成可验证:check_deps 硬依赖门(缺即终止)、log_call 证据账本(调用落 calls.jsonl 含装载 sha256)、evidence_report 验收门(三方各 ≥1 成功调用才 PASS);S0–S7 流水线含两个回合终止停点与轻量任务路由;E2E 已真跑(习惯打卡 App 双屏原型):7 条真实调用留账、双独立 sub-agent 评审 26/36 + detect 2 findings、修复 3×P1 后字阶清零、交互复测 4/4、验收门 PASS;上游三件补装 ~/.codex/skills,仓库 README 同步
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
#!/usr/bin/env python3
|
||||
"""le-app-design 验收门:从 calls.jsonl 生成本次运行的集成证据报告。
|
||||
|
||||
用法:
|
||||
python3 evidence_report.py --run-dir <RUN> [--out <RUN>/INTEGRATION-REPORT.md] \
|
||||
[--artifact <路径>]... [--title "任务名"]
|
||||
|
||||
验收规则(硬门):
|
||||
三个上游 ui-ux-pro-max / frontend-design / impeccable 各需 ≥1 条成功调用
|
||||
(exec 且 exit_code==0,或 load 且 exit_code==0)。
|
||||
--artifact 指定的每个文件必须存在。
|
||||
任一不满足 → 报告标 FAIL,exit 1;全满足 → PASS,exit 0。
|
||||
|
||||
报告内容: 判定横幅、三方调用统计表、逐条调用清单(时间/依赖/命令/退出码)、
|
||||
产物核验清单、失败与缺口说明。这份报告就是「真实集成」的可检查证据。
|
||||
仅 python3 标准库。
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import sys
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
GATE_DEPS = ["ui-ux-pro-max", "frontend-design", "impeccable"]
|
||||
|
||||
|
||||
def load_records(ledger: Path) -> list[dict]:
|
||||
if not ledger.is_file():
|
||||
return []
|
||||
records = []
|
||||
for line in ledger.read_text(encoding="utf-8", errors="replace").splitlines():
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
try:
|
||||
rec = json.loads(line)
|
||||
except json.JSONDecodeError:
|
||||
records.append({"dep": "(unparsable)", "kind": "raw", "exit_code": None, "command": line[:120], "ts": ""})
|
||||
continue
|
||||
records.append(rec)
|
||||
return records
|
||||
|
||||
|
||||
def is_success(rec: dict) -> bool:
|
||||
return rec.get("exit_code") == 0 and rec.get("kind") in ("exec", "load")
|
||||
|
||||
|
||||
def one_line(rec: dict) -> str:
|
||||
cmd = rec.get("command", "")
|
||||
try: # exec 记录的 command 是 JSON 数组字符串
|
||||
parts = json.loads(cmd)
|
||||
if isinstance(parts, list):
|
||||
cmd = " ".join(str(p) for p in parts)
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
pass
|
||||
return cmd if len(cmd) <= 160 else cmd[:157] + "..."
|
||||
|
||||
|
||||
def main() -> int:
|
||||
ap = argparse.ArgumentParser(description="le-app-design 验收门")
|
||||
ap.add_argument("--run-dir", required=True)
|
||||
ap.add_argument("--out", default=None, help="报告写入路径,缺省 <run-dir>/INTEGRATION-REPORT.md")
|
||||
ap.add_argument("--artifact", action="append", default=[], help="须存在的交付物路径(可多次)")
|
||||
ap.add_argument("--title", default="le-app-design 集成证据报告")
|
||||
args = ap.parse_args()
|
||||
|
||||
run_dir = Path(args.run_dir).expanduser()
|
||||
records = load_records(run_dir / "calls.jsonl")
|
||||
out_path = Path(args.out).expanduser() if args.out else run_dir / "INTEGRATION-REPORT.md"
|
||||
|
||||
stats = {dep: {"ok": 0, "fail": 0} for dep in GATE_DEPS}
|
||||
for rec in records:
|
||||
dep = rec.get("dep")
|
||||
if dep in stats:
|
||||
stats[dep]["ok" if is_success(rec) else "fail"] += 1
|
||||
|
||||
gate_pass = all(stats[d]["ok"] >= 1 for d in GATE_DEPS)
|
||||
artifacts_missing = [a for a in args.artifact if not Path(a).expanduser().exists()]
|
||||
overall = gate_pass and not artifacts_missing
|
||||
|
||||
lines: list[str] = []
|
||||
lines.append(f"# {args.title}")
|
||||
lines.append("")
|
||||
lines.append(f"- 运行目录: `{run_dir}`")
|
||||
lines.append(f"- 生成时间: {datetime.now(timezone.utc).isoformat(timespec='seconds')}")
|
||||
lines.append(f"- 调用记录: {len(records)} 条(`calls.jsonl`)")
|
||||
lines.append("")
|
||||
lines.append(f"## 判定: {'✅ PASS' if overall else '❌ FAIL'}")
|
||||
lines.append("")
|
||||
lines.append("| 上游 | 成功调用 | 失败调用 | 门(≥1 成功) |")
|
||||
lines.append("|---|---|---|---|")
|
||||
for dep in GATE_DEPS:
|
||||
s = stats[dep]
|
||||
lines.append(f"| {dep} | {s['ok']} | {s['fail']} | {'✅' if s['ok'] >= 1 else '❌ 未被真实调用'} |")
|
||||
lines.append("")
|
||||
|
||||
if artifacts_missing:
|
||||
lines.append("**缺失产物:**")
|
||||
for a in artifacts_missing:
|
||||
lines.append(f"- ❌ `{a}`")
|
||||
lines.append("")
|
||||
elif args.artifact:
|
||||
lines.append("**产物核验:**")
|
||||
for a in args.artifact:
|
||||
lines.append(f"- ✅ `{a}`")
|
||||
lines.append("")
|
||||
|
||||
lines.append("## 调用清单")
|
||||
lines.append("")
|
||||
lines.append("| # | 时间(UTC) | 依赖 | 类型 | 退出码 | 命令/装载 |")
|
||||
lines.append("|---|---|---|---|---|---|")
|
||||
for i, rec in enumerate(records, 1):
|
||||
lines.append(
|
||||
f"| {i} | {rec.get('ts', '')} | {rec.get('dep', '?')} | {rec.get('kind', '?')} "
|
||||
f"| {rec.get('exit_code', '?')} | `{one_line(rec)}` |"
|
||||
)
|
||||
lines.append("")
|
||||
|
||||
if not overall:
|
||||
lines.append("## 缺口说明")
|
||||
lines.append("")
|
||||
for dep in GATE_DEPS:
|
||||
if stats[dep]["ok"] < 1:
|
||||
lines.append(f"- `{dep}` 无成功调用记录——该上游未被真实使用,本次流程**不得标记为成功**。")
|
||||
for a in artifacts_missing:
|
||||
lines.append(f"- 产物缺失: `{a}`")
|
||||
lines.append("")
|
||||
|
||||
report = "\n".join(lines)
|
||||
out_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
out_path.write_text(report + "\n", encoding="utf-8")
|
||||
print(report)
|
||||
print(f"\n[report] {'PASS' if overall else 'FAIL'} → {out_path}", file=sys.stderr)
|
||||
return 0 if overall else 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user