Generate Deterministic Calculations from Extracted Parameters
Overview
Wraps the calculation-generator system prompt at system-prompt.txt (next to this file) and applies it to a parameter JSON produced by extract-parameters-from-full (validated by validate-parameters). Output is a single Python module of small, pure functions — one per formula_hint declared in recommended_first_calculations and derived_questions.
Stage 5 of the pipeline described in planexe_simulator/README.md.
When to Use
- User asks to "generate calculations", "emit Python", "materialise the formulas", or "build the deterministic functions" given a validated parameter JSON
- Pipeline step between
validate-parameters (passes clean) / generate-bounds and run-scenarios
- User wants importable Python functions ready for scenario tables
Not for: regenerating the parameter JSON (use extract-parameters-from-full), validating it (use validate-parameters), producing low/base/high ranges (use generate-bounds), or running scenarios (use run-scenarios).
Workflow
- Get the input JSON path. If the user did not provide one, ask. Do not guess.
- Read
system-prompt.txt (sibling of this SKILL.md). Its function-shape, division-guard, and module-structure rules are authoritative.
- Read the parameter JSON. Assume it has already passed
validate-parameters; if it visibly hasn't, tell the user and offer to validate first.
- Produce the Python module per the system prompt.
- Output destination. Default: write to a file. Suggested default path:
<input-basename>.calculations.py next to the input. Print the file path back, plus a one-line summary (function count, any # skipped lines, any TODO stubs for P(...) notation).
What gets a function
| Input list |
Action |
recommended_first_calculations |
one function each |
derived_questions |
one function each |
key_values |
not converted — these are caller-supplied inputs |
missing_values_to_estimate |
not converted — supplied via bounds at scenario time |
Skip an entry whose formula_hint is null, empty, or unparseable. Replace with a # skipped: <id> -- <reason> comment.
Function shape (re-stated for emphasis — see system prompt for full detail)
def x(a: float, b: float) -> float:
return a * b
- Function name = LHS of
formula_hint if present, else the entry's id
- Args = each
depends_on id in declared order, all typed float
- Return type
float
- Body: at most three lines (optional guard
if, optional intermediate, return)
Division guards: every variable denominator must short-circuit to float("inf") when ≤ 0. Numeric-literal denominators (e.g. value / 100) need no guard.
Function-style notation translations
| Source |
Translation |
max(...), min(...), abs(...), sum(...) |
Python builtins |
exp(...), log(...), sqrt(...), ln(...) |
math.exp, math.log, math.sqrt (add import math) |
mean(...), avg(...) |
_mean(*args) helper at top of module |
P(...), p(...) |
raise NotImplementedError(...) stub with TODO comment carrying the original formula |
Module structure
"""
Generated PlanExe deterministic calculations.
Plan: <plan_name>
Plan type: <plan_type>
One function per formula_hint entry...
"""
from __future__ import annotations
import math # only if needed
# _mean helper, only if needed
# functions, in order: recommended_first_calculations, then derived_questions
No top-level executable code, no __main__ block, no file I/O, no classes, no decorators, no per-function docstrings, no in-body comments (except the P(...) TODO).
Common Mistakes
| Mistake |
Fix |
Wrapping the Python output in ```python fences |
Raw Python only |
Adding a if __name__ == "__main__": demo block |
This stage emits a library, not a runnable script |
| Generating a class hierarchy |
One function per formula; no classes unless required by the formulas themselves (they aren't) |
| Inventing or omitting arguments to "make the formula work" |
Args must match depends_on exactly, in order |
| Forgetting the divide-by-zero guard |
Every variable denominator gets a guard; numeric literals don't |
Emitting def people_contacted(...) -> float: """People contacted""" |
No per-function docstrings — the signature is self-documenting |
Translating P(x >= y) as a literal Python comparison |
P(...) is probability notation; emit a NotImplementedError stub instead |
Including functions for key_values or missing_values_to_estimate ids |
Those are inputs, not calculations |
Reference
- System prompt (authoritative):
system-prompt.txt
- Pipeline overview and code-generation rules:
../../README.md, Stage 5
- Companion skills:
../extract-parameters-from-full/SKILL.md, ../validate-parameters/SKILL.md, ../generate-bounds/SKILL.md
- Example input for testing:
/tmp/extract-params-heatwave-v10.json (passes validate-parameters with valid: true)
1---2name: generate-calculations3description: Use when the user wants to turn a validated extract-parameters-from-full JSON into a Python module of deterministic functions implementing the formula_hint expressions for downstream scenario runs and Monte Carlo4---56# Generate Deterministic Calculations from Extracted Parameters78## Overview910Wraps the calculation-generator system prompt at `system-prompt.txt` (next to this file) and applies it to a parameter JSON produced by `extract-parameters-from-full` (validated by `validate-parameters`). Output is a single Python module of small, pure functions — one per `formula_hint` declared in `recommended_first_calculations` and `derived_questions`.1112Stage 5 of the pipeline described in `planexe_simulator/README.md`.1314## When to Use1516- User asks to "generate calculations", "emit Python", "materialise the formulas", or "build the deterministic functions" given a validated parameter JSON17- Pipeline step between `validate-parameters` (passes clean) / `generate-bounds` and `run-scenarios`18- User wants importable Python functions ready for scenario tables1920Not for: regenerating the parameter JSON (use `extract-parameters-from-full`), validating it (use `validate-parameters`), producing low/base/high ranges (use `generate-bounds`), or running scenarios (use `run-scenarios`).2122## Workflow23241. **Get the input JSON path.** If the user did not provide one, ask. Do not guess.252. **Read `system-prompt.txt`** (sibling of this SKILL.md). Its function-shape, division-guard, and module-structure rules are authoritative.263. **Read the parameter JSON.** Assume it has already passed `validate-parameters`; if it visibly hasn't, tell the user and offer to validate first.274. **Produce the Python module** per the system prompt.285. **Output destination.** Default: write to a file. Suggested default path: `<input-basename>.calculations.py` next to the input. Print the file path back, plus a one-line summary (function count, any `# skipped` lines, any TODO stubs for `P(...)` notation).2930## What gets a function3132| Input list | Action |33|---|---|34| `recommended_first_calculations` | one function each |35| `derived_questions` | one function each |36| `key_values` | not converted — these are caller-supplied inputs |37| `missing_values_to_estimate` | not converted — supplied via bounds at scenario time |3839Skip an entry whose `formula_hint` is null, empty, or unparseable. Replace with a `# skipped: <id> -- <reason>` comment.4041## Function shape (re-stated for emphasis — see system prompt for full detail)4243```python44def x(a: float, b: float) -> float:45 return a * b46```4748- Function name = LHS of `formula_hint` if present, else the entry's `id`49- Args = each `depends_on` id in declared order, all typed `float`50- Return type `float`51- Body: at most three lines (optional guard `if`, optional intermediate, return)5253Division guards: every variable denominator must short-circuit to `float("inf")` when ≤ 0. Numeric-literal denominators (e.g. `value / 100`) need no guard.5455## Function-style notation translations5657| Source | Translation |58|---|---|59| `max(...)`, `min(...)`, `abs(...)`, `sum(...)` | Python builtins |60| `exp(...)`, `log(...)`, `sqrt(...)`, `ln(...)` | `math.exp`, `math.log`, `math.sqrt` (add `import math`) |61| `mean(...)`, `avg(...)` | `_mean(*args)` helper at top of module |62| `P(...)`, `p(...)` | `raise NotImplementedError(...)` stub with TODO comment carrying the original formula |6364## Module structure6566```python67"""68Generated PlanExe deterministic calculations.6970Plan: <plan_name>71Plan type: <plan_type>7273One function per formula_hint entry...74"""7576from __future__ import annotations77import math # only if needed7879# _mean helper, only if needed8081# functions, in order: recommended_first_calculations, then derived_questions82```8384No top-level executable code, no `__main__` block, no file I/O, no classes, no decorators, no per-function docstrings, no in-body comments (except the `P(...)` TODO).8586## Common Mistakes8788| Mistake | Fix |89|---|---|90| Wrapping the Python output in ```` ```python ```` fences | Raw Python only |91| Adding a `if __name__ == "__main__":` demo block | This stage emits a library, not a runnable script |92| Generating a class hierarchy | One function per formula; no classes unless required by the formulas themselves (they aren't) |93| Inventing or omitting arguments to "make the formula work" | Args must match `depends_on` exactly, in order |94| Forgetting the divide-by-zero guard | Every variable denominator gets a guard; numeric literals don't |95| Emitting `def people_contacted(...) -> float: """People contacted"""` | No per-function docstrings — the signature is self-documenting |96| Translating `P(x >= y)` as a literal Python comparison | `P(...)` is probability notation; emit a `NotImplementedError` stub instead |97| Including functions for `key_values` or `missing_values_to_estimate` ids | Those are inputs, not calculations |9899## Reference100101- System prompt (authoritative): `system-prompt.txt`102- Pipeline overview and code-generation rules: `../../README.md`, Stage 5103- Companion skills: `../extract-parameters-from-full/SKILL.md`, `../validate-parameters/SKILL.md`, `../generate-bounds/SKILL.md`104- Example input for testing: `/tmp/extract-params-heatwave-v10.json` (passes validate-parameters with `valid: true`)