Save plans as S-expressions under content hash

- Orchestrator saves plan as {plan_id}.sexp (content-addressed)
- Also saves {run_id}.sexp for easy lookup by run
- Falls back to JSON for legacy plans without to_sexp_string()

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
gilesb
2026-01-12 00:29:53 +00:00
parent 65a8170192
commit 10fe05a049

View File

@@ -296,11 +296,22 @@ def run_recipe(
logger.info(f"Generated plan with {len(plan.steps)} steps")
# Save plan for debugging
# Save plan as S-expression (content-addressed by plan_id hash)
PLAN_CACHE_DIR.mkdir(parents=True, exist_ok=True)
plan_path = PLAN_CACHE_DIR / f"{plan.plan_id}.json"
with open(plan_path, "w") as f:
f.write(plan.to_json())
plan_sexp_path = PLAN_CACHE_DIR / f"{plan.plan_id}.sexp"
if hasattr(plan, 'to_sexp_string'):
with open(plan_sexp_path, "w") as f:
f.write(plan.to_sexp_string())
else:
# Fallback to JSON for legacy plans
plan_json_path = PLAN_CACHE_DIR / f"{plan.plan_id}.json"
with open(plan_json_path, "w") as f:
f.write(plan.to_json())
# Also save a reference by run_id for easy lookup
run_plan_path = PLAN_CACHE_DIR / f"{run_id}.sexp"
if plan_sexp_path.exists():
run_plan_path.write_text(plan_sexp_path.read_text())
# Phase 3: Execute
logger.info("Phase 3: Executing plan...")