Files
whetstone_DSL/tools/mcp/spec_planning_hardener.py

66 lines
2.1 KiB
Python
Executable File

#!/usr/bin/env python3
from __future__ import annotations
import argparse
import json
from pathlib import Path
def load_readiness(path: Path) -> dict:
return json.loads(path.read_text(encoding="utf-8"))
def harden_markdown(original: str, readiness: dict) -> str:
template = (readiness.get("recommended_template") or "").strip()
if not template:
return original
missing = readiness.get("missing_actions") or []
missing_lines = "\n".join([f"- [{m.get('type','?')}] `{m.get('key','?')}`: {m.get('action','')}" for m in missing])
addendum = (
"\n\n---\n\n"
"## Planning Hardening Addendum\n\n"
"This section is auto-generated to make the spec execution-ready for Whetstone.\n\n"
"### Detected Gaps\n"
f"{missing_lines if missing_lines else '- none'}\n\n"
"### Recommended Scaffold\n\n"
f"{template}\n"
)
if "## Planning Hardening Addendum" in original:
return original
return original.rstrip() + addendum
def main() -> None:
ap = argparse.ArgumentParser(description="Generate hardened markdown spec scaffold from planning readiness output.")
ap.add_argument("--spec", required=True, help="Input markdown spec path")
ap.add_argument("--readiness", required=True, help="Readiness JSON path from spec_planning_readiness.py")
ap.add_argument("--out", required=True, help="Output hardened markdown path")
args = ap.parse_args()
spec_path = Path(args.spec)
readiness_path = Path(args.readiness)
out_path = Path(args.out)
original = spec_path.read_text(encoding="utf-8")
readiness = load_readiness(readiness_path)
hardened = harden_markdown(original, readiness)
out_path.parent.mkdir(parents=True, exist_ok=True)
out_path.write_text(hardened, encoding="utf-8")
report = {
"input_spec": str(spec_path),
"readiness_json": str(readiness_path),
"output_spec": str(out_path),
"missing_count": len(readiness.get("missing_actions") or []),
"added_addendum": hardened != original,
}
print(json.dumps(report, indent=2))
if __name__ == "__main__":
main()