paqad-ai
Version:
Spec-driven development framework — AI agents that think before they type
100 lines (77 loc) • 7.25 kB
Markdown
---
name: module-map-reconciler
description: 'Scans the source tree against module-map.yml and docs/modules, writes MM-* findings to .paqad/module-map/drift.json, and routes accepted deltas through src/module-decisions/apply.ts. Use when the user asks to reconcile or refresh the module map, when documentation sync is closing, or when paqad-ai refresh runs.'
metadata:
model_tier: medium
cacheable: 'false'
output_format: markdown
paqad-meta: skill.meta.yaml
---
## What It Does
Walks the source tree under `module_health.source_roots` (declared on the active stack pack), compares the files it finds against `module-map.yml`'s declared modules / features and the `docs/modules/<slug>/` tree, and emits findings:
| Code | Meaning |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `MM-ADD` | Source files exist under a directory that no module's `sources:` glob matches. |
| `MM-FEAT-ADD` | Files under a known module match no declared feature glob. |
| `MM-REMOVE` | Declared module has no matching source files. |
| `MM-RENAME` | Module's symbol moved (only emitted when the stack pack ships a `public_api_extractor`; otherwise falls back to `MM-REMOVE` + `MM-ADD`). |
| `MM-FEAT-STALE` | Declared feature has no matching source files. |
| `MM-DOC-ORPHAN` | `docs/modules/<slug>/` exists with no matching module declaration. |
| `MM-DOC-MISSING` | Declared module has no `docs/modules/<slug>/` directory. |
| `MM-MISMATCH` | A prospective `MD-XXXX` declaration and the actual code paths diverge. |
Findings are written to `.paqad/module-map/drift.json` and consumed by:
- `paqad-ai status` (drift badge per module: Phase 4).
- `paqad-ai refresh` (non-zero exit on drift).
- `feature-development.documentation_sync` (stop with `stale_docs: stop` if undeclared modules were touched by the diff).
- `finding-normalizer` (via the `MM-*` code-prefix recognised in `assets/vocabulary.txt`).
## Use This When
- A user prompt matches the priority-225 router rules (`reconcile module map`, `refresh module map`, `update module map`, `check module map`, `module map drift`).
- `feature-development.documentation_sync` is about to close and you need to confirm no undeclared modules were touched.
- `paqad-ai refresh` invokes it to fail fast on drift.
## Inputs
- The active stack pack's `module_health.source_roots`. **Required**: refuses to run with `blocked: source_roots_unknown` when missing. Bundled details in `references/source-roots-contract.md`.
- `module-map.yml` (read-only here; mutations go through `src/module-decisions/apply.ts`).
- `docs/modules/<slug>/` tree for orphan / missing checks.
- Existing `.paqad/decisions/module-decisions/*.yml` for `MM-MISMATCH` cross-referencing.
## Procedure
1. Resolve `source_roots` from the active stack pack. If absent, surface a single Decision Pause packet asking the user to add `module_health.source_roots` to their pack, do **not** guess.
2. Invoke the TS engine via the bundled wrapper:
```
bash scripts/reconcile.sh [project-root]
```
The wrapper shells out to `paqad-ai module-map reconcile --project-root <root>`, producing `.paqad/module-map/drift.json` and a JSON summary on stdout.
3. Parse findings. Group by code and module for presentation.
4. For each finding, surface a Decision Pause packet:
- `MM-ADD` → "New module under `<dir>`. Declare? (extract → inferencer → apply)": pipes through the Attribution Gate.
- `MM-FEAT-ADD` → "Add feature glob to `<module>`?": collects feature name + glob, then routes to apply.
- `MM-REMOVE` / `MM-FEAT-STALE` → "Remove declaration?" or "Update glob?".
- `MM-DOC-ORPHAN` → "Delete `docs/modules/<slug>/` or declare module?"
- `MM-DOC-MISSING` → "Run `create module documentation` for `<slug>`?".
- `MM-MISMATCH` → "Apply pending `MD-XXXX` or revise?".
5. Apply accepted deltas through `src/module-decisions/apply.ts`. Never write `module-map.yml` directly.
## Output Contract
- `.paqad/module-map/drift.json` written with the full report (findings + counts + `blocked`).
- A `## Reconciliation Findings` markdown block listing each code, count, and one-line detail.
- A `## Pending User Decisions` block listing each surfaced packet's question and selected option.
- When invoked from `documentation_sync` and any `MM-ADD` / `MM-MISMATCH` finding touches the diff, exit with `stale_docs: stop`.
## Escalate / Stop Conditions
- Hard-fail with the literal status `blocked: source_roots_unknown` when the active stack pack has no `module_health.source_roots`. Print the path to the pack manifest that needs updating; do **not** prompt to "use a default."
- Stop if `module-map.yml` is missing: the reconciler needs declarations to reconcile against. Surface `Reconciler requires module-map.yml; run "create documentation" first.`
- Stop if any `MM-RENAME` is ambiguous (multiple candidates within Levenshtein bound): collect the user's choice.
- Do **not** write `module-map.yml` from this skill. All map mutations go through `src/module-decisions/apply.ts`.
## Scripts
Deterministic plumbing: do **not** re-derive these in the LLM layer.
- `scripts/reconcile.sh [project-root]`: invoke the reconciler; writes `.paqad/module-map/drift.json` and prints a JSON summary.
- `scripts/has-findings.sh [project-root]`: exit 0 if findings exist, 1 if clean, 2 if blocked (`source_roots_unknown`), 3 if drift.json is missing. Prints the count.
- `scripts/is-blocked.sh [project-root]`: exit 1 with the blocked reason on stdout when the reconciler is blocked.
- `scripts/count-by-code.sh [project-root]`: sorted `MM-CODE: N` lines for use in the `## Reconciliation Findings` block.
- `scripts/filter-by-code.sh <MM-CODE> [project-root]`: JSON array of findings for a specific code.
## Assets
- `assets/templates/findings-summary.md`: markdown template for the `## Reconciliation Findings` + `## Pending User Decisions` output blocks.
## Resources
- `references/source-roots-contract.md`: the source_roots requirement.
- `runtime/base/skills/module-map-reconciler/agents/openai.yaml`: agent interface metadata.
- `src/module-map/reconciler.ts`: detection engine.
- `src/module-decisions/apply.ts`: atomic apply path (only writer of `module-map.yml`).
- `runtime/base/skills/documentation-workflow/scripts/list-orphan-module-dirs.sh`: back-compat orphan detector promoted into `MM-DOC-ORPHAN`.
- the Decision Pause Contract (in the framework bootstrap): packet semantics.