Add batch closure ladder analytics and runner (sprint 253)
This commit is contained in:
59
tools/mcp/analyze_closure_ladder_outcomes.py
Executable file
59
tools/mcp/analyze_closure_ladder_outcomes.py
Executable file
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Dict
|
||||
|
||||
|
||||
def load_json(path: Path):
|
||||
with path.open("r", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
p = argparse.ArgumentParser(description="Aggregate closure ladder outcomes.")
|
||||
p.add_argument("--runs-root", default="logs/taskitem_runs")
|
||||
p.add_argument("--include-glob", default="TEST_ONLY_*closure_ladder*")
|
||||
p.add_argument("--out", required=True)
|
||||
args = p.parse_args()
|
||||
|
||||
root = Path(args.runs_root)
|
||||
summaries = sorted(root.glob(f"{args.include_glob}/closure_ladder_summary.json"))
|
||||
|
||||
mode_counts: Dict[str, int] = {}
|
||||
status_counts: Dict[str, int] = {}
|
||||
rows = []
|
||||
for s in summaries:
|
||||
try:
|
||||
j = load_json(s)
|
||||
except Exception:
|
||||
continue
|
||||
mode = str(j.get("selected_mode", ""))
|
||||
status = str(j.get("status", "unknown"))
|
||||
mode_counts[mode] = mode_counts.get(mode, 0) + 1
|
||||
status_counts[status] = status_counts.get(status, 0) + 1
|
||||
rows.append({
|
||||
"run_id": s.parent.name,
|
||||
"status": status,
|
||||
"selected_mode": mode,
|
||||
"selected_run": str(j.get("selected_run", "")),
|
||||
})
|
||||
|
||||
out = {
|
||||
"status": "ok",
|
||||
"record_count": len(rows),
|
||||
"status_counts": status_counts,
|
||||
"selected_mode_counts": mode_counts,
|
||||
"records": rows,
|
||||
}
|
||||
|
||||
with Path(args.out).open("w", encoding="utf-8") as f:
|
||||
json.dump(out, f, indent=2, sort_keys=True)
|
||||
f.write("\n")
|
||||
|
||||
print(json.dumps({"status": "ok", "record_count": len(rows), "out": args.out}, sort_keys=True))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
35
tools/mcp/run_native_profile_closure_ladder_batch.sh
Executable file
35
tools/mcp/run_native_profile_closure_ladder_batch.sh
Executable file
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
SPEC_LIST_FILE="${1:-}"
|
||||
OUT_DIR="${2:-$ROOT_DIR/logs/taskitem_runs/TEST_ONLY_native_profile_closure_ladder_batch_$(date +%Y%m%d_%H%M%S)}"
|
||||
if [[ -z "$SPEC_LIST_FILE" ]]; then
|
||||
echo "usage: $0 <spec_list_file> [out_dir]" >&2
|
||||
exit 2
|
||||
fi
|
||||
if [[ ! -f "$SPEC_LIST_FILE" ]]; then
|
||||
echo "error: spec list not found: $SPEC_LIST_FILE" >&2
|
||||
exit 2
|
||||
fi
|
||||
mkdir -p "$OUT_DIR"
|
||||
|
||||
while IFS= read -r spec; do
|
||||
[[ -z "$spec" ]] && continue
|
||||
[[ "$spec" =~ ^# ]] && continue
|
||||
if [[ ! -f "$spec" ]]; then
|
||||
echo "skip missing spec: $spec" >&2
|
||||
continue
|
||||
fi
|
||||
safe_name="$(basename "$spec" | sed 's/[^A-Za-z0-9._-]/_/g')"
|
||||
run_out="$OUT_DIR/$safe_name"
|
||||
mkdir -p "$run_out"
|
||||
"$ROOT_DIR/tools/mcp/run_native_profile_closure_ladder.sh" "$spec" "$run_out" >/dev/null || true
|
||||
done < "$SPEC_LIST_FILE"
|
||||
|
||||
python3 "$ROOT_DIR/tools/mcp/analyze_closure_ladder_outcomes.py" \
|
||||
--runs-root "$OUT_DIR" \
|
||||
--include-glob "*" \
|
||||
--out "$OUT_DIR/closure_ladder_batch_summary.json" >/dev/null
|
||||
|
||||
jq -n --arg out_dir "$OUT_DIR" --argjson summary "$(cat "$OUT_DIR/closure_ladder_batch_summary.json")" '{status:"ok", out_dir:$out_dir, summary:$summary}'
|
||||
Reference in New Issue
Block a user