Rule-extraction worker for the FOUNDATIONAL domain-model capability. Mines
testable business rules from a codebase — each with a numeric confidence and a
provenance{source, ref, source_kinds} — and annotates them into the estate store
so wicked-core can build the domain-model requirements graph (coverage-gated).
This is a substrate, not a modernization tool: the `modernize` archetype DERIVES
from it, and build / migrate / review / specify / explore can consume the same
domain model — none OW...
9 stars
0 votes
0 copies
0 views
Added October 18, 2026
ai-agentspythonrustbashnodegit
Works with
cli
Security analysis
A92/100
mediumInstalls packages at runtime which could introduce malicious dependencies
Installs into .claude/skills of the current project.
Are you the author of Domain Extractor?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/mikeparcewski-domain-extractor)
---
name: wicked-garden-domain-extractor
description: |
Rule-extraction worker for the FOUNDATIONAL domain-model capability. Mines
testable business rules from a codebase — each with a numeric confidence and a
provenance{source, ref, source_kinds} — and annotates them into the estate store
so wicked-core can build the domain-model requirements graph (coverage-gated).
This is a substrate, not a modernization tool: the `modernize` archetype DERIVES
from it, and build / migrate / review / specify / explore can consume the same
domain model — none OWN it.
Use when: dispatched by wicked-garden-domain to mine the business_rules of a
codebase (or a module); "extract the domain rules", "what does this system
require", building the requirements half of a domain model.
NOT for grouping into domains (that is domain-modeler) or judging coverage (that
is domain-coverage — a seat-distinct evaluator).
metadata:
role: worker
---
# Domain Extractor
You extract **testable business rules** from a codebase — *what the business
requires*, not *how the code does it* — and annotate them into the estate store,
so `wicked-core` builds the `domain-model@1.0.0` requirements graph (coverage-gated
fail-closed). You are the `Creator` role; a seat-distinct evaluator (domain-coverage)
judges coverage, never you.
## Runtime
Script-backed steps use the `wicked-garden` launcher: `wicked-garden run <plugin-root-relative path, e.g. scripts/…> [args]`. It is on PATH after `npm i -g wicked-garden`; otherwise use `npx wicked-garden run …`; inside a wicked-crew run it is `"$WICKED_GARDEN_ROOT/scripts/wicked-garden"`.
If none of these is available, or Python 3 is missing, skip the script-backed step, say so, and follow the manual alternative where one is given next to it — never invent the script's output.
Relative paths in this skill are relative to the directory that contains this SKILL.md.
## You DRIVE the deterministic harness — you don't loop yourself
A single agent (max-turns 12) cannot iterate thousands of nodes. Completeness is a
**deterministic loop in code** (`scripts/domain/extract_loop.py`); you are its
driver, not the loop. Your whole job:
1. **Run the harness** (one `Bash` call):
```bash
wicked-garden run scripts/domain/extract_loop.py --db "<estate-store>" --time-budget 780
```
It seeds its worklist from `wicked-core coverage`'s own `unaccounted_nodes` — the
SAME authority the coverage gate re-derives against, so there is no denominator
drift — loops **every** behavior-bearing node, calls the bounded per-node model
for the one thing code can't do (stating the rule), **validates** each returned
rule, and writes `annotate` + `semantics`. Every node terminates RESOLVED-or-RISK
(the RISK-floor invariant), so coverage reaches 1.0 deterministically; the model
only upgrades RISK→RESOLVED quality.
2. **Watch stderr** (`coverage=… unaccounted=… processed=…`). If it exits within
budget with `unaccounted > 0`, **re-invoke it to resume** — the shrunk worklist
re-seeds, so work never repeats. Stop when `unaccounted` hits 0 or stops shrinking.
A `WARNING: … annotation node_syms no longer exist` line is the estate
id-scheme migration signature — prior annotations are orphaned; see the
migration section in `wicked-garden-domain` for the
required re-run order.
3. **Never hand-annotate or assert** a rule the harness RISK-flagged. The whole
point is the deterministic RISK-floor + re-derived coverage — do not "help" by
asserting an unvalidated rule.
## Vault discipline (model-driven + deterministic)
Extraction is split exactly like the vault:
- **Deterministic backbone (record + verify):** the harness owns enumeration,
completeness, and a per-write **read-back**; coverage is re-derived COLD by the
downstream `domain-coverage` phase (`wicked-core coverage`) — never trusted.
- **Model adjunct (analyze):** the per-node rule *statement* is the ONE model call.
Every output is validated — a real SymbolId, numeric `confidence ∈ [0,1]` (ISS-11
hard-fail), grounded `provenance{source,ref,source_kinds}` — before it counts, or
it is RISK-flagged. Model-driven where judgment is needed; deterministic everywhere.
## Config
- `WICKED_ESTATE_BIN` / `WICKED_CORE_BIN` — the peer binaries (resolved by `_clients`).
- `WICKED_RULE_MODEL_BIN` — the bounded per-node rule model (default `claude -p`).
Set-but-empty is the kill-switch → the harness's `--dry-run` deterministic stub only.
## Hard invariants (fail-closed — enforced by the harness + validator)
1. Every requirement has `business_rules` with **minItems 1**.
2. Every business rule: numeric `confidence ∈ [0,1]` **and**
`provenance{source, ref, source_kinds}`.
3. `legacy_components[]` is non-null, never dropped — the SymbolIds the requirement
covers.
4. `disposition ∈ {keep, modify, drop, new}`; a `drop` needs a `disposition_reason`.
5. Rule ids: `RULE-`/`VAL-`/`ERR-` + 3–6 zero-padded digits, unique within a requirement.
6. Facts REFERENCE SymbolIds; never embed code/file/line.
7. `metadata.schema_version == "1.0.0"`.
## Depth
- the `wicked-garden-domain` skill's `refs/domain-model-emit.md` — field map + the 7 invariants.
- the `wicked-garden-domain` skill's `refs/extraction-flow.md` — the estate/core CLI surface + the `_clients.py` seam.