Add the puga command and plan pull; document the UI plan workflow

- pyproject.toml + puga/cli.py: `pip install -e .` installs a `puga <tool>` command, so no
  venv path is needed (replaces requirements.txt)
- tools/plan_push.py: `pull <uuid>` reads a plan (incl. UI edits) back into a YAML spec;
  recipe entries may carry an amount so switched-off recipes round trip; fixes a variable
  that overwrote the plan name in build_payload, with a regression test
- README: usage with the puga command, and a section on working on the same plans in the
  PRUNplanner UI and from Claude (write, edit in UI, read back)
- CLAUDE.md updated accordingly

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-19 00:37:20 +02:00
co-authored by Claude Sonnet 5
parent 455e04a520
commit 4c186ac677
13 changed files with 158 additions and 25 deletions
+8
View File
@@ -34,3 +34,11 @@ def test_guardrail_requires_prefix_and_validates():
pp_tool.build_payload(_spec(**bad), R, {"SME"})
with pytest.raises(ValueError):
pp_tool.build_payload(_spec(buildings=[{"building": "ZZZ", "amount": 1}]), R, {"SME"})
def test_recipe_dict_keeps_amount_and_does_not_clobber_plan_name():
"""Regression: a loop variable once overwrote the plan name; also switched-off recipes (amount 0) must round trip."""
spec = _spec(buildings=[{"building": "SME", "amount": 1, "recipes": [{"recipe": "ALO,C,O=>AL", "amount": 0}]}])
out = pp_tool.build_payload(spec, R, {"SME"})
assert out["plan_name"] == "[PuGa] x"
assert out["plan_data"]["buildings"][0]["active_recipes"] == [{"recipeid": "SME#6xALO 1xO 1xC=>3xAL", "amount": 0}]