Run the deterministic module-attribution extractor over a user prompt and surface any MD-XXXX drafts via the Decision Pause Contract. This is the first half of the Attribution Gate spliced into feature-development.planning (issue #80). Pattern set is finite, framework-owned, and TS-canonical (`src/module-decisions/extractor.ts`); extending it is a framework PR.
Scanned 9/2/2026
Install to Claude Code
npx -y skills add Eliyce/paqad-ai --skill module-attribution-extractor --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Module Attribution Extractor?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/eliyce-module-attribution-extractor)More formats (shields.io, HTML) on the badges page.
---
name: module-attribution-extractor
description: Run the deterministic module-attribution extractor over a user prompt and surface any MD-XXXX drafts via the Decision Pause Contract. This is the first half of the Attribution Gate spliced into feature-development.planning (issue #80). Pattern set is finite, framework-owned, and TS-canonical (`src/module-decisions/extractor.ts`); extending it is a framework PR.
model_tier: fast
triggers:
- workflow:
- feature-development
- module-attribution
cacheable: false
cache_key_inputs: []
output_format: markdown
input_schema:
prompt:
type: string
required: true
description: The user prompt to analyse (typically a pasted ticket or feature request).
project_root:
type: path
required: false
description: Project root used to resolve module-map.yml for collision detection. Defaults to cwd.
---
## What It Does
Applies the framework-owned pattern set (`Module:` / `Component:` / `Area:` / `Subsystem:` ticket headers; `module: <slug>`; `new module <Name>`; `in the <name> module`) to the prompt. Emits one candidate per distinct slug, classified as `exact-match`, `near-collision` (Levenshtein ≤ 2 against an existing slug), or `unknown`. Multiple modules in a single prompt produce one MD-XXXX draft each (spec AC #9).
## Use This When
- Running the Attribution Gate at the start of `feature-development.planning`.
- A user pastes a ticket and you need a deterministic first pass before invoking the inferencer.
- A user prompt explicitly names a module (`module: billing`, `Subsystem: Reporting`).
## Inputs
- `prompt` — required. The user-supplied text (typically a ticket body or feature request).
- `project_root` — optional. Used to resolve `module-map.yml` for collision detection. Defaults to `cwd`.
- The pattern set itself is closed and lives in `runtime/base/skills/module-attribution-extractor/references/pattern-set.md`.
## Procedure
1. Resolve the project root (default `cwd`).
2. Invoke the TS engine via the bundled wrapper:
```
bash scripts/extract.sh <prompt-file> [project-root]
```
The wrapper shells out to `paqad-ai module-decisions extract --project-root <root> --prompt-file <tmp>`. Prefer `--prompt-file` (the wrapper always uses it) so multiline ticket text survives the shell.
3. Parse the emitted JSON. Each entry in `candidates` has: `slug`, `display_name`, `kind`, `collision_with`, `pattern`, `excerpt`.
4. If `needs_decision` is empty, the extractor either found nothing or every hit was an `exact-match` — exit with the literal status `extractor: no-decision-needed` so the caller can fall through to the inferencer (the empty case) or continue planning (the exact-match case).
5. Otherwise, for each candidate in `needs_decision`, surface a Decision Pause packet via `AskUserQuestion` (or the active adapter's Decision Pause Contract entry point).
## Decision Pause Packet Shape
For each candidate that needs a decision, the packet must include:
- **Question** — the user-visible question. For `unknown`: `Confirm new module "<display_name>" (slug: <slug>)?`. For `near-collision`: `"<slug>" is suspiciously close to existing module "<collision_with>" — confirm which one this is.`
- **Header** — short tag, e.g. `New module`, `Slug collision`.
- **Options** (2–4):
- **Accept new module `<slug>`** — proceed to atomic apply via `src/module-decisions/apply.ts`.
- For near-collision: **Use existing `<collision_with>`** — resolve to the existing slug; mark the draft `superseded`.
- **Rename** — collect a new slug from the user; loop back through `extract`.
- **Reject** — mark the draft `rejected`; no module-map mutation.
The packet's selected option drives the state transition. Only an explicit `Accept` response promotes the MD-XXXX from `draft` → `proposed` → `accepted` (spec AC #11). No silent acceptance.
## Output Contract
- Zero or more MD-XXXX YAML files written under `.paqad/decisions/module-decisions/<id>.yml` (one per candidate that needs a decision).
- A `Workflow Status` block listing what was extracted and what is awaiting the user.
- On accepted decisions only: `apply.ts` performs the snapshot → temp-write → rename → record update → events append. **Do not write `module-map.yml` from this skill directly.**
- When the extractor returns no candidates, emit the literal status `extractor: no-decision-needed` so the caller can fall through to `module-attribution-inferencer`.
## Escalate / Stop Conditions
- Stop and surface the packet if `kind === 'near-collision'` — never auto-resolve to either side.
- Stop if the same slug appears in two different patterns with conflicting display names — ask which name to use.
- Refuse to write any MD-XXXX file if the project has no `.paqad/` directory (project is not onboarded).
## Scripts
Deterministic plumbing — do **not** re-derive these in the LLM layer.
- `scripts/extract.sh <prompt-file> [project-root]` — invoke the extractor; prints the JSON report.
- `scripts/needs-decision.sh [report.json|-]` — exit 0 if a Decision Pause packet is needed, exit 1 otherwise (with `extractor: no-decision-needed` on stderr).
- `scripts/filter-by-kind.sh <exact-match|near-collision|unknown> [report.json|-]` — filter `candidates` by kind; prints a JSON array.
## Assets
- `assets/templates/packet-unknown.md` — Decision Pause packet template for an `unknown` candidate.
- `assets/templates/packet-collision.md` — Decision Pause packet template for a `near-collision` candidate.
## Resources
- `runtime/base/skills/module-attribution-extractor/references/pattern-set.md` — bundled pattern reference.
- `runtime/base/skills/module-attribution-extractor/agents/openai.yaml` — agent interface metadata.
- `src/module-decisions/extractor.ts` — pattern set + classification.
- `src/module-decisions/schema.ts` — MD-XXXX state machine.
- `src/module-decisions/apply.ts` — atomic apply path (only writer of `module-map.yml`).
- the Decision Pause Contract (in the framework bootstrap) — packet semantics.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!