| name | swmm-report |
| description | Generate a client-deliverable Word (.docx) report from an audited SWMM run directory. Reads manifest.json, experiment_provenance.json, model_diagnostics.json, comparison.json, and any PNG figures — SWMM is never re-run. Supports custom YAML/JSON section templates.
|
SWMM Report Export Skill
Purpose
Assemble a reproducible, client-deliverable Word (.docx) report from the
artifacts produced by swmm-experiment-audit and swmm-plot. The script
reads only existing files; it never re-runs SWMM or modifies the run
directory.
Prerequisite: the run directory must contain a 09_audit/ subdirectory
with at least experiment_provenance.json. Run aiswmm audit --run-dir <path> first if that directory is absent.
CLI usage
python3 skills/swmm-report/scripts/generate_report.py \
--run-dir <path>
[--out <path.docx>]
[--template <path>]
aiswmm report --run-dir <path> [--out <path.docx>] [--template <template.yaml>]
Exit codes: 0 = success; 1 = missing dependency, missing audit dir, or
template error; 2 = argument error.
python-docx dependency: install with pip install 'aiswmm[report]'.
The script exits immediately with a clear message if python-docx is absent.
Agent tool: generate_report
Registered in AgentToolRegistry. Direct handler (not MCP-routed) —
shells out to generate_report.py, writes <run-dir>/report.docx (or
the path supplied via out).
generate_report(run_dir="runs/my_run/")
generate_report(run_dir="runs/my_run/", out="deliverables/run_report.docx")
generate_report(run_dir="runs/my_run/", template="templates/client_a.yaml")
is_read_only=False — QUICK profile prompts the user (tool writes files).
If python-docx is not installed the tool returns a failure dict whose
summary carries the install hint pip install 'aiswmm[report]'.
Executed example
mkdir -p /tmp/swmm_report_fixture/09_audit
cat > /tmp/swmm_report_fixture/09_audit/experiment_provenance.json << 'EOF'
{
"schema_version": "1.0",
"run_id": "smoke-test-run",
"generated_at_utc": "2025-01-01T00:00:00Z",
"metrics": {"peak_flow": {"value": 1.23, "time_hhmm": "06:30"},
"continuity_error": -0.5, "swmm_return_code": 0},
"qa": {"checks": [{"id": "continuity", "ok": true, "detail": "within tolerance"}]},
"repo": {"git_head": "abc1234", "git_branch": "main"},
"tools": {"swmm5_version": "5.1.015", "python_version": "3.11"},
"artifacts": {
"model.inp": {"role": "input", "sha256": "4840dbe4abcdef", "exists": true,
"produced_by": "builder"}
},
"generated_by": "aiswmm"
}
EOF
python3 skills/swmm-report/scripts/generate_report.py \
--run-dir /tmp/swmm_report_fixture \
--out /tmp/swmm_report_smoke.docx
The generated .docx follows engineering-report conventions:
- Pure black text:
Normal, Heading 1, Heading 2, and Title styles all use
RGB(0,0,0) — no Word default blue or grey.
- Numbered body sections:
1 Run Summary, 2 Model Description, … assigned
automatically from template order. The cover title is unnumbered.
- Table captions above each table:
Table N — <text> with bold Table N prefix,
numbering sequential across the whole document.
- Narrative paragraph below each table: a short explanatory paragraph stating what
the table shows and where the numbers come from (text sourced from template).
- Figure captions below each figure:
Figure N — <stem>, with a separate counter
from the table counter.
- Page number in footer: right-aligned Word
PAGE field inserted via OOXML
(fldChar begin + instrText " PAGE " + fldChar end) so Word/LibreOffice renders
a live page number.
Template override
Pass --template <path> (YAML or JSON) to control which sections appear
and in what order. The built-in template at
skills/swmm-report/templates/default.yaml uses all nine sections:
| Section ID | Content |
|---|
cover | Title, run ID, generated-at timestamp |
run_summary | Peak flow, time of peak, continuity error, return code |
model_description | Basin area, simulation window, impervious %, Green-Ampt params |
qa_gates | QA check table from experiment_provenance.json |
figures | Embedded PNG figures from 07_plot/, 08_plot/, network_layout.png |
diagnostics | Model diagnostics from model_diagnostics.json |
comparison | Baseline comparison (skipped silently when unavailable) |
provenance | Artifact SHA-256 hashes from experiment_provenance.json |
appendix | Git head/branch, SWMM version, Python version |
A custom template only needs the sections it uses. Unknown section IDs
are warned and skipped — they do not abort the build.
Determinism contract
- No random state, no timestamps injected by the script itself.
- All metadata (run ID, generated-at, SHA-256) comes from existing JSON
artifacts, not re-computed at report time.
- Identical inputs produce bit-identical
.docx output (python-docx's
internal XML is deterministic for a given template + data combination).
Scripts
scripts/generate_report.py — single entrypoint; stdlib + python-docx + PyYAML only.
Templates
templates/default.yaml — built-in nine-section template.
Dependencies
| Package | Purpose | Install |
|---|
python-docx | Write .docx output | pip install 'aiswmm[report]' |
PyYAML | Parse YAML template files | pip install PyYAML |
Part of
PRD_report_export.md — Report Export skill.
PR1: generate_report.py + default template.
PR2 (this): ToolSpec wiring + CLI verb + SKILL.md.