# v0.6.3-alpha — Architecture deepening (intent_classifier + tool_handlers + RAG memory exposure)

**Released**: 2026-05-16
**Status**: Pre-release (alpha), built on top of v0.6.2-alpha. `pip install aiswmm` continues to deliver v0.6.1; this version requires opt-in.
**PyPI version string**: `0.6.3a1` (PEP 440)

## How to install

```bash
pip install aiswmm==0.6.3a1   # pin
pip install --pre aiswmm      # allow any pre-release
```

## One-sentence summary

v0.6.3-alpha is an **architectural enhancement release** that consolidates and deepens what v0.6.2-alpha shipped: keyword matching is now centralized in one deep module, the 2163-LOC `tool_registry.py` is being split along skill-family lines, the previously-undocumented RAG memory skill (`swmm-rag-memory`) is now agent-callable, and the portability claim is fully delivered (the `cases/` directory now ships with reference templates).

## Architectural changes (the headline)

### `intent_classifier` deep module (#121)

Prior to this release, keyword-driven intent resolution was scattered across **six files** with 50+ checks — the user's specific architectural concern raised during the grill-me design session of 2026-05-16. Adding a new intent required touching `planner.py`, `tool_registry.py`, `single_shot.py`, `runtime_loop.py`, `continuation_classifier.py`, and `intent_map.py` in coordination. Drift between sites was a recurring source of bugs (e.g., the workflow-router compound-intent bug fixed in v0.6.2-alpha PR #117 — the `wants_plot` priority lived in one file while `wants_run` did not exist anywhere).

**New module**: `agentic_swmm/agent/intent_classifier.py` (372 LOC).

**Public interface**:
- `classify_intent(goal, *, workflow_state) -> IntentSignals` — single entry point returning a dataclass with all intent flags
- `is_negated(lowered, term)` — shared negation detector

**Migration**: The six original sites now call `classify_intent` and consume `IntentSignals` fields. Legacy entry points (`compute_intent_signals`, `is_open_shaped_prompt`, `classify`, `_is_negated`) are retained as re-export shims so external imports keep working.

**Regression coverage**: 31 new tests across `tests/test_intent_classifier.py` and `tests/test_intent_classifier_migration_parity.py`.

### `tool_handlers/` package split (#128, partial)

`tool_registry.py` was a 2163-LOC monolith with 79 functions covering 14 skill families plus the registry plumbing. v0.6.3-alpha ships the first 3 family slices:

| Slice | New file | Contents |
|---|---|---|
| `web` | `agentic_swmm/agent/tool_handlers/web.py` (99 LOC) | `_web_fetch_url_tool`, `_web_search_tool` |
| `demo` | `agentic_swmm/agent/tool_handlers/demo.py` (29 LOC) | `_demo_acceptance_tool` |
| `swmm-memory` | `agentic_swmm/agent/tool_handlers/swmm_memory.py` (239 LOC) | 4 recall/record tools + token-budget helpers |

`tool_registry.py` is now ~1900 LOC. The remaining 7 slices are queued as follow-up PRs.

**Backwards-compatibility shim**: All extracted handler functions are re-exported from `tool_registry.py` so any external caller importing them by their old names continues to work.

### Dead-code purge in `single_shot.py` (#127)

`agentic_swmm/agent/single_shot.py` shrunk from **797 LOC to 144 LOC** (−82 %). The module's own docstring already admitted the removed handlers were "not on the live path today" and were shadowed by `tool_registry.py`. Removed 6 helper functions whose only callers were inside the module itself.

## New agent capabilities

### RAG memory retrieval is now agent-callable (#124 Part A)

The `swmm-rag-memory` skill has shipped 7 retrieval scripts for several releases but had no agent-callable `ToolSpec`. README and SKILL.md claimed memory-informed planning; the planner literally could not invoke them.

**New tool**: `retrieve_memory` (read-only)
**Args**: `query` (required), `top_k`, `retriever`, `project`
**Wraps**: `skills/swmm-rag-memory/scripts/retrieve_memory.py`

**New intent**: `memory-retrieval` (matches `recall`, `前面`, `以前`, `类似`).

### Full MCP server enumeration

`agent/config/intent_map.json:mcp_enabled_skills` previously listed 8 of 11 shipped MCP servers (a stale config). Now lists all 11. `integrations/mcp/README.md` updated from "eight" to "eleven" in prose.

## Portability completeness

v0.6.2-alpha's release notes claimed "runtime contains zero hardcoded watershed names in routing/inference code" and "migration to a new watershed requires only `cases/<your-watershed>/case_meta.yaml` — no code changes". Two follow-up gaps that v0.6.3-alpha closes:

1. **`cases/` directory was empty** despite the claim. v0.6.3-alpha ships `cases/tecnopolo/case_meta.yaml` and `cases/todcreek/case_meta.yaml` as reference fixtures with an optional `aliases` field at top level so `_match_registered_case` in `runtime_loop` picks up colloquial forms.

2. **`agent/config/intent_map.json:21` still contained literal `"tecnopolo"`**. The AST regression guard from PR #118 walked Python `.py` files only — this JSON config was a blind spot. The guard now scans `intent_map.json` as well.

**Bonus**: `agentic_swmm/agent/welcome.py` now reads the first registered case's `display_name` for the "Things to try" demo line, falling back to "Run a SWMM demo" when `cases/` is empty.

**Bonus**: `skills/swmm-uncertainty/scripts/monte_carlo_propagate.py` had a chart title containing a watershed name; made generic so the AST guard's pre-existing failure on that file clears.

## Documentation

- **README "preload path" mismatch fixed** (#123). The drift was in `skills/swmm-end-to-end/SKILL.md` (lines 10 and 38), fixed there.
- **README validation-snapshot anchors resolve** (#129). Two new sections in `docs/validation-evidence.md`.
- **Private-machine breadcrumbs removed** (#126). 14 absolute-home-directory references cleaned from 5 files; regression test prevents future leaks.

## Hygiene

- **Plot script defaults are self-documenting** (#125). `skills/swmm-plot/scripts/plot_rain_runoff_si.py` and `mcp/swmm-plot/server.js` now read `--rain-ts <rainfall-series-name>` / `--node <outfall-or-junction>` instead of literal `TS_RAIN` / `O1` defaults. Manual CLI invocations hitting a placeholder fail fast.

## PR + commit map

| Fix | Issue | PR | Squash SHA |
|---|---|---|---|
| Dead handlers in `single_shot.py` | [#127](https://github.com/Zhonghao1995/agentic-swmm-workflow/issues/127) | [#130](https://github.com/Zhonghao1995/agentic-swmm-workflow/pull/130) | `74a331e` |
| Plot defaults self-documenting | [#125](https://github.com/Zhonghao1995/agentic-swmm-workflow/issues/125) | [#131](https://github.com/Zhonghao1995/agentic-swmm-workflow/pull/131) | `ec5ce85` |
| Docs hygiene bundle | [#123](https://github.com/Zhonghao1995/agentic-swmm-workflow/issues/123), [#126](https://github.com/Zhonghao1995/agentic-swmm-workflow/issues/126), [#129](https://github.com/Zhonghao1995/agentic-swmm-workflow/issues/129) | [#132](https://github.com/Zhonghao1995/agentic-swmm-workflow/pull/132) | `367fcec` |
| Portability bootstrap + JSON AST guard | [#122](https://github.com/Zhonghao1995/agentic-swmm-workflow/issues/122) | [#133](https://github.com/Zhonghao1995/agentic-swmm-workflow/pull/133) | `9b4ee1f` |
| `intent_classifier` deep module | [#121](https://github.com/Zhonghao1995/agentic-swmm-workflow/issues/121) | [#134](https://github.com/Zhonghao1995/agentic-swmm-workflow/pull/134) | `90fb0a9` |
| Expose RAG memory (Part A only) | [#124](https://github.com/Zhonghao1995/agentic-swmm-workflow/issues/124) | [#135](https://github.com/Zhonghao1995/agentic-swmm-workflow/pull/135) | `64956c6` |
| Split `tool_registry.py` (partial) | [#128](https://github.com/Zhonghao1995/agentic-swmm-workflow/issues/128) | [#136](https://github.com/Zhonghao1995/agentic-swmm-workflow/pull/136) | `467e5e8` |
| Security: revert LID surface from #135 | — | [#137](https://github.com/Zhonghao1995/agentic-swmm-workflow/pull/137) | `94b199a` |

## Migration guide (from v0.6.2-alpha)

No breaking changes. CLI flags, tool schemas, and config formats are all backwards compatible.

```bash
pip install --upgrade aiswmm==0.6.3a1
aiswmm setup --refresh-mcp     # optional but recommended if you have multiple checkouts
aiswmm doctor                   # confirm no remaining WARNs
aiswmm skill list --registry    # verify retrieve_memory appears
```

If you have a custom case directory, you can now drop a `case_meta.yaml` with optional `aliases` to control how the runtime infers case ID from user prompts. See `cases/tecnopolo/case_meta.yaml` for the shipped reference.

## Known limitations carried forward

- **`tool_registry.py` split is 3 of 10 families done**. The remaining 7 slices are queued.
- **`docs/framework-validation/saanich-b7-*/network.json` retains absolute-home-directory paths** by design — frozen-evidence preservation. Same-directory README documents this.

## Reproducibility footprint

For paper-grade reproducibility of any v0.6.3-alpha experiment:

- PyPI: `aiswmm==0.6.3a1`
- Git tag: `v0.6.3a1`
- Pinned model snapshot: `gpt-5.5-2026-04-23` (unchanged since v0.6.1)
- Docker base ref: `AGENTIC_SWMM_REF=v0.6.3a1`

All paper-citable invariants from v0.6.2-alpha continue to hold; v0.6.3-alpha strengthens them:

- The `run_allowed_command` four-binary allowlist that prevents agent script-execution bypass is unchanged.
- The AST regression guard now scans Python AND JSON config — strictly stronger.
- LLM intervention auditability (`model_role="disambiguate_intent"` lines in `09_audit/llm_calls.jsonl`) is unchanged.
