auto-sync 2026-07-04T06:38:25Z workspace (part 4)
Browse files
workspace/scripts/audit_ctt_paper_artifacts.py
CHANGED
|
@@ -108,13 +108,15 @@ ADVISOR_RUN_FILES: tuple[str, ...] = (
|
|
| 108 |
"eval.log",
|
| 109 |
"metrics_by_task.json",
|
| 110 |
"metrics_by_seed.json",
|
| 111 |
-
"report.md",
|
| 112 |
)
|
| 113 |
|
| 114 |
|
| 115 |
INPUT_RE = re.compile(r"\\input\{([^}]+)\}")
|
| 116 |
|
| 117 |
|
|
|
|
|
|
|
|
|
|
| 118 |
def main(argv: list[str] | None = None) -> int:
|
| 119 |
parser = argparse.ArgumentParser(
|
| 120 |
description=(
|
|
@@ -143,7 +145,15 @@ def main(argv: list[str] | None = None) -> int:
|
|
| 143 |
paper_inputs = _paper_input_checks(repo_root, paper_path, paper_text)
|
| 144 |
required_paths = [] if args.skip_implementation_checks else _required_path_checks(repo_root)
|
| 145 |
run_artifacts = _run_artifact_checks(repo_root, paper_inputs["run_dirs"])
|
| 146 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 147 |
|
| 148 |
payload = {
|
| 149 |
"schema_version": 1,
|
|
@@ -151,9 +161,10 @@ def main(argv: list[str] | None = None) -> int:
|
|
| 151 |
"markdown_policy": "consolidated_readme_only",
|
| 152 |
"markdown_note": (
|
| 153 |
"Advisor checklist asks for report.md files, but the current workspace "
|
| 154 |
-
"policy keeps README.md as the only Markdown document.
|
| 155 |
-
"
|
| 156 |
),
|
|
|
|
| 157 |
},
|
| 158 |
"paper": str(paper_path.relative_to(repo_root)),
|
| 159 |
"summary": summary,
|
|
@@ -162,6 +173,7 @@ def main(argv: list[str] | None = None) -> int:
|
|
| 162 |
"paper_inputs": paper_inputs,
|
| 163 |
"required_paths": required_paths,
|
| 164 |
"run_artifacts": run_artifacts,
|
|
|
|
| 165 |
}
|
| 166 |
|
| 167 |
out_dir = _resolve(repo_root, args.out_dir)
|
|
@@ -175,6 +187,8 @@ def main(argv: list[str] | None = None) -> int:
|
|
| 175 |
"paper: " + str(paper_path.relative_to(repo_root)),
|
| 176 |
"markdown_policy: consolidated_readme_only",
|
| 177 |
"strict_report_md: false",
|
|
|
|
|
|
|
| 178 |
]
|
| 179 |
)
|
| 180 |
+ "\n"
|
|
@@ -293,22 +307,52 @@ def _run_artifact_checks(repo_root: Path, run_dirs: list[str]) -> list[dict[str,
|
|
| 293 |
"status": status,
|
| 294 |
"missing_required": missing_required,
|
| 295 |
"missing_advisor_contract": missing_advisor,
|
| 296 |
-
"markdown_report_policy":
|
| 297 |
-
"warning_only_consolidated_readme"
|
| 298 |
-
if "report.md" in missing_advisor
|
| 299 |
-
else "present"
|
| 300 |
-
),
|
| 301 |
}
|
| 302 |
)
|
| 303 |
return rows
|
| 304 |
|
| 305 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 306 |
def _summary(
|
| 307 |
forbidden: list[dict[str, Any]],
|
| 308 |
phrase_checks: list[dict[str, Any]],
|
| 309 |
paper_inputs: dict[str, Any],
|
| 310 |
required_paths: list[dict[str, Any]],
|
| 311 |
run_artifacts: list[dict[str, Any]],
|
|
|
|
| 312 |
) -> dict[str, Any]:
|
| 313 |
failures = (
|
| 314 |
len(forbidden)
|
|
@@ -316,6 +360,7 @@ def _summary(
|
|
| 316 |
+ sum(1 for item in phrase_checks if item["status"] == "fail")
|
| 317 |
+ sum(1 for item in required_paths if item["status"] == "fail")
|
| 318 |
+ sum(1 for item in run_artifacts if item["status"] == "fail")
|
|
|
|
| 319 |
)
|
| 320 |
warnings = sum(len(item.get("missing_advisor_contract", [])) for item in run_artifacts)
|
| 321 |
return {
|
|
@@ -323,6 +368,7 @@ def _summary(
|
|
| 323 |
"num_failures": failures,
|
| 324 |
"num_warnings": warnings,
|
| 325 |
"num_forbidden_matches": len(forbidden),
|
|
|
|
| 326 |
"num_paper_inputs": paper_inputs["num_inputs"],
|
| 327 |
"num_run_dirs_in_paper": len(paper_inputs["run_dirs"]),
|
| 328 |
}
|
|
@@ -340,7 +386,8 @@ def _latex_table(payload: dict[str, Any]) -> str:
|
|
| 340 |
f"Paper inputs & {summary['num_paper_inputs']} & {_latex_status(payload['paper_inputs']['num_missing'] == 0)} \\\\",
|
| 341 |
f"Run dirs in paper & {summary['num_run_dirs_in_paper']} & {_latex_status(all(row['status'] == 'pass' for row in payload['run_artifacts']))} \\\\",
|
| 342 |
f"Implementation paths & {len(payload['required_paths'])} & {_latex_status(all(row['status'] == 'pass' for row in payload['required_paths']))} \\\\",
|
| 343 |
-
f"
|
|
|
|
| 344 |
"\\bottomrule",
|
| 345 |
"\\end{tabular}",
|
| 346 |
]
|
|
|
|
| 108 |
"eval.log",
|
| 109 |
"metrics_by_task.json",
|
| 110 |
"metrics_by_seed.json",
|
|
|
|
| 111 |
)
|
| 112 |
|
| 113 |
|
| 114 |
INPUT_RE = re.compile(r"\\input\{([^}]+)\}")
|
| 115 |
|
| 116 |
|
| 117 |
+
ALLOWED_MARKDOWN_FILES: tuple[str, ...] = ("README.md",)
|
| 118 |
+
|
| 119 |
+
|
| 120 |
def main(argv: list[str] | None = None) -> int:
|
| 121 |
parser = argparse.ArgumentParser(
|
| 122 |
description=(
|
|
|
|
| 145 |
paper_inputs = _paper_input_checks(repo_root, paper_path, paper_text)
|
| 146 |
required_paths = [] if args.skip_implementation_checks else _required_path_checks(repo_root)
|
| 147 |
run_artifacts = _run_artifact_checks(repo_root, paper_inputs["run_dirs"])
|
| 148 |
+
markdown_policy = _markdown_policy_checks(repo_root)
|
| 149 |
+
summary = _summary(
|
| 150 |
+
forbidden,
|
| 151 |
+
phrase_checks,
|
| 152 |
+
paper_inputs,
|
| 153 |
+
required_paths,
|
| 154 |
+
run_artifacts,
|
| 155 |
+
markdown_policy,
|
| 156 |
+
)
|
| 157 |
|
| 158 |
payload = {
|
| 159 |
"schema_version": 1,
|
|
|
|
| 161 |
"markdown_policy": "consolidated_readme_only",
|
| 162 |
"markdown_note": (
|
| 163 |
"Advisor checklist asks for report.md files, but the current workspace "
|
| 164 |
+
"policy keeps README.md as the only Markdown document. This audit now "
|
| 165 |
+
"fails on additional Markdown files instead of regenerating report.md."
|
| 166 |
),
|
| 167 |
+
"allowed_markdown_files": list(ALLOWED_MARKDOWN_FILES),
|
| 168 |
},
|
| 169 |
"paper": str(paper_path.relative_to(repo_root)),
|
| 170 |
"summary": summary,
|
|
|
|
| 173 |
"paper_inputs": paper_inputs,
|
| 174 |
"required_paths": required_paths,
|
| 175 |
"run_artifacts": run_artifacts,
|
| 176 |
+
"markdown_policy": markdown_policy,
|
| 177 |
}
|
| 178 |
|
| 179 |
out_dir = _resolve(repo_root, args.out_dir)
|
|
|
|
| 187 |
"paper: " + str(paper_path.relative_to(repo_root)),
|
| 188 |
"markdown_policy: consolidated_readme_only",
|
| 189 |
"strict_report_md: false",
|
| 190 |
+
"allowed_markdown_files:",
|
| 191 |
+
*[f" - {name}" for name in ALLOWED_MARKDOWN_FILES],
|
| 192 |
]
|
| 193 |
)
|
| 194 |
+ "\n"
|
|
|
|
| 307 |
"status": status,
|
| 308 |
"missing_required": missing_required,
|
| 309 |
"missing_advisor_contract": missing_advisor,
|
| 310 |
+
"markdown_report_policy": "consolidated_readme_only",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 311 |
}
|
| 312 |
)
|
| 313 |
return rows
|
| 314 |
|
| 315 |
|
| 316 |
+
def _markdown_policy_checks(repo_root: Path) -> dict[str, Any]:
|
| 317 |
+
ignored_parts = {".git", ".venv"}
|
| 318 |
+
rows = []
|
| 319 |
+
for path in sorted(repo_root.rglob("*.md")):
|
| 320 |
+
try:
|
| 321 |
+
rel = path.relative_to(repo_root)
|
| 322 |
+
except ValueError:
|
| 323 |
+
continue
|
| 324 |
+
if any(part in ignored_parts for part in rel.parts):
|
| 325 |
+
continue
|
| 326 |
+
rel_text = rel.as_posix()
|
| 327 |
+
rows.append(
|
| 328 |
+
{
|
| 329 |
+
"path": rel_text,
|
| 330 |
+
"status": "pass" if rel_text in ALLOWED_MARKDOWN_FILES else "fail",
|
| 331 |
+
}
|
| 332 |
+
)
|
| 333 |
+
unexpected = [row["path"] for row in rows if row["status"] != "pass"]
|
| 334 |
+
missing_allowed = [
|
| 335 |
+
name for name in ALLOWED_MARKDOWN_FILES if not (repo_root / name).exists()
|
| 336 |
+
]
|
| 337 |
+
return {
|
| 338 |
+
"policy": "consolidated_readme_only",
|
| 339 |
+
"allowed": list(ALLOWED_MARKDOWN_FILES),
|
| 340 |
+
"rows": rows,
|
| 341 |
+
"unexpected_markdown": unexpected,
|
| 342 |
+
"missing_allowed": missing_allowed,
|
| 343 |
+
"num_markdown_files": len(rows),
|
| 344 |
+
"num_unexpected_markdown": len(unexpected),
|
| 345 |
+
"status": "pass" if not unexpected and not missing_allowed else "fail",
|
| 346 |
+
}
|
| 347 |
+
|
| 348 |
+
|
| 349 |
def _summary(
|
| 350 |
forbidden: list[dict[str, Any]],
|
| 351 |
phrase_checks: list[dict[str, Any]],
|
| 352 |
paper_inputs: dict[str, Any],
|
| 353 |
required_paths: list[dict[str, Any]],
|
| 354 |
run_artifacts: list[dict[str, Any]],
|
| 355 |
+
markdown_policy: dict[str, Any],
|
| 356 |
) -> dict[str, Any]:
|
| 357 |
failures = (
|
| 358 |
len(forbidden)
|
|
|
|
| 360 |
+ sum(1 for item in phrase_checks if item["status"] == "fail")
|
| 361 |
+ sum(1 for item in required_paths if item["status"] == "fail")
|
| 362 |
+ sum(1 for item in run_artifacts if item["status"] == "fail")
|
| 363 |
+
+ (0 if markdown_policy["status"] == "pass" else 1)
|
| 364 |
)
|
| 365 |
warnings = sum(len(item.get("missing_advisor_contract", [])) for item in run_artifacts)
|
| 366 |
return {
|
|
|
|
| 368 |
"num_failures": failures,
|
| 369 |
"num_warnings": warnings,
|
| 370 |
"num_forbidden_matches": len(forbidden),
|
| 371 |
+
"num_unexpected_markdown": markdown_policy["num_unexpected_markdown"],
|
| 372 |
"num_paper_inputs": paper_inputs["num_inputs"],
|
| 373 |
"num_run_dirs_in_paper": len(paper_inputs["run_dirs"]),
|
| 374 |
}
|
|
|
|
| 386 |
f"Paper inputs & {summary['num_paper_inputs']} & {_latex_status(payload['paper_inputs']['num_missing'] == 0)} \\\\",
|
| 387 |
f"Run dirs in paper & {summary['num_run_dirs_in_paper']} & {_latex_status(all(row['status'] == 'pass' for row in payload['run_artifacts']))} \\\\",
|
| 388 |
f"Implementation paths & {len(payload['required_paths'])} & {_latex_status(all(row['status'] == 'pass' for row in payload['required_paths']))} \\\\",
|
| 389 |
+
f"Unexpected Markdown files & {summary['num_unexpected_markdown']} & {_latex_status(summary['num_unexpected_markdown'] == 0)} \\\\",
|
| 390 |
+
f"Advisor-contract warnings & {summary['num_warnings']} & {'pass' if summary['num_warnings'] == 0 else 'warn'} \\\\",
|
| 391 |
"\\bottomrule",
|
| 392 |
"\\end{tabular}",
|
| 393 |
]
|