wicked-garden 12.32.0 → 12.32.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,7 @@
2
2
  "_comment": "Issue #328: Component declarations for wicked-garden plugin. Claude Code plugin.json does not yet support inline component declarations beyond path overrides. This manifest documents all components for tooling, validation, and future schema support. When plugin.json gains a 'components' field, merge this data into plugin.json. The plugin is skills-only: former commands/ became actions of consolidated per-domain skills, and former agents/ became standalone context:fork worker skills (enumerated under fork_skills). Regenerate derived blocks with scripts/ci/sync_components.py.",
3
3
  "domains": ["agentic", "crew", "data", "engineering", "jam", "mem", "persona", "platform", "product", "qe", "search", "smaht"],
4
4
  "summary": {
5
- "skills": 141,
5
+ "skills": 142,
6
6
  "fork_skills": 78,
7
7
  "hooks": 13,
8
8
  "specialists": 7
@@ -92,6 +92,7 @@
92
92
  "qe-testability-reviewer": ["qe-testability-reviewer"],
93
93
  "qe-ui-component-test-engineer": ["qe-ui-component-test-engineer"],
94
94
  "qe-visual-regression-engineer": ["qe-visual-regression-engineer"],
95
+ "repo-learn": ["repo-learn"],
95
96
  "runtime-exec": ["runtime-exec"],
96
97
  "search": ["codebase-narrator", "search"],
97
98
  "smaht": ["discovery", "intent", "propose-skills", "smaht"],
@@ -1 +1 @@
1
- {"name": "wicked-garden", "owner": {"name": "Mike Parcewski"}, "plugins": [{"name": "wicked-garden", "source": "./", "description": "Your coding agent already plans and swarms \u2014 Wicked Garden is the curated toolkit for what it can't: proof-not-claims gates, code links grep can't see, deterministic refactor, cross-session memory, real multi-model second opinions. Don't fight the harness; fill its gaps. The gate needs wicked-vault (a self-contained infra peer, installed directly) and re-derives through garden's built-in engine; estate/bus are opt-in layers (wicked-testing and wicked-brain are retired \u2014 QE ships in-catalog as the qe domain, memory lives in wicked-estate).", "version": "12.32.0"}], "version": "12.32.0"}
1
+ {"name": "wicked-garden", "owner": {"name": "Mike Parcewski"}, "plugins": [{"name": "wicked-garden", "source": "./", "description": "Your coding agent already plans and swarms \u2014 Wicked Garden is the curated toolkit for what it can't: proof-not-claims gates, code links grep can't see, deterministic refactor, cross-session memory, real multi-model second opinions. Don't fight the harness; fill its gaps. The gate needs wicked-vault (a self-contained infra peer, installed directly) and re-derives through garden's built-in engine; estate/bus are opt-in layers (wicked-testing and wicked-brain are retired \u2014 QE ships in-catalog as the qe domain, memory lives in wicked-estate).", "version": "12.32.1"}], "version": "12.32.1"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wicked-garden",
3
- "version": "12.32.0",
3
+ "version": "12.32.1",
4
4
  "description": "Your coding agent's harness already plans and swarms; Wicked Garden is the curated toolkit for what it can't do alone. Proof, not claims \u2014 gates re-derive 'done' through the internal loom engine (fail-closed, independently attested via wicked-vault), so a self-asserted pass can't lie its way green. Relationships grep can't see \u2014 the wicked-estate code graph + injected bus/dispatch/capability/archetype edges power blast-radius & lineage. Plus deterministic multi-file refactor (wicked-patch), cross-session memory + knowledge (the mem domain over wicked-estate), real multi-model second opinions (jam:council), portable expertise as on-demand skill-refs, and evidence-gated testing (the in-catalog qe domain). It reads the shape of your work to apply the right rigor \u2014 steering, not a pipeline \u2014 then gets out of the way. The compiler stamps a self-contained evidence gate into any repo that runs with no wicked-garden installed. Don't fight the harness; fill its gaps. The evidence gate requires wicked-vault, a self-contained infra peer wicked-garden installs directly; wicked-bus is an opt-in layer \u2014 install what you'll use, the toolkit works without the rest.",
5
5
  "wicked_vault_version": "^0.5.0",
6
6
  "wicked_ledger_version": "^0.4.0",
package/CHANGELOG.md CHANGED
@@ -22,6 +22,18 @@
22
22
  - **Site: the wicked-interactive card tells the document-engine story** (recon DT-12) — wicked-interactive moved planes rather than retiring: it is the foundation's document engine (storage, version lineage, HTML/PDF/PPTX/video rendering) that wicked-crew spawns and proxies, not a standalone visual builder. Install command unchanged (two-step marketplace add + install).
23
23
  - **Backfilled the 12.30.0 and 12.31.0 changelog entries below** (recon DT-17) — the previous release entry was 12.29.1 while npm shipped 12.31.0; the vault-direct-peer entry that sat under [Unreleased] shipped in 12.31.0 and now lives there.
24
24
 
25
+ ## [12.32.1] — 2026-09-09
26
+
27
+ ### Fixed
28
+ - **Skills: the five dangling `${CLAUDE_PLUGIN_ROOT}` paths and the broken qe evidence-schema link (#1111, fixed in #1113).** wicked-crew's skills publish analyzer (crew#480) resolves every plugin-root and relative reference in the shipped plugin against the would-be snapshot; the five targets parked in `tests/test_skill_dispatch_refs_resolve.py::KNOWN_DANGLING_PATHS` are now fixed at the source and the allowlist is empty (the test fails if any of them dangles again). Imagery `alter`/`create` (+ `alter/refs/editing-reference.md` and the `scripts/{edit,generate}.sh` wrappers) invoke `skills/product/imagery/scripts/provider.py` — the sub-skills kept the pre-move `skills/imagery/` path after imagery moved under `skills/product/` (the wrappers' `PLUGIN_ROOT` fallback also climbed one directory too few); the requirements output-format ref's **Templates** section points at the two skeletons already inline instead of a `templates/` directory cut in v12.21; the user-story guide's "generate template" line (a script that never shipped) points at the inline **Template for New Stories** block; the runtime-exec example is written as the quoted `"path/to/your_script.py"` placeholder it always was (copy-safe, and no longer shaped like a plugin-root path); and `skills/qe/refs/evidence.md` cites `schemas/evidence.json` as shipped in the `wicked-vault` npm package (garden never vendored it, so the relative link had nothing to resolve to). `scripts/ci/validate.py` §6 now reports 0 broken script paths (was 11). Deliberately untouched: the architecture deployment-template links (`skills/engineering/architecture/refs/architecture-template-deployment.md`, they target the user's repo) and the domain vendor README's sibling-checkout prose.
29
+ - **repo-learn: the tier/severity enum tokens are spelled out unmissably** in the skill, so capture workers stop drifting onto values wicked-estate's `proposal.submit` rejects (#1108).
30
+
31
+ ### Added
32
+ - **`wicked-garden-repo-learn`** — churn-led repo-learning skill: churn → hotspots → captured memories + policy proposals (#1107).
33
+
34
+ ### Changed
35
+ - Docs: the architecture-wiki skill pointers route to Steering (`STEERING.md` — #1103); site additive messaging refresh — steering, governed knowledge, requirements graph (#1109); stale doc counts, version stamp and markers corrected (#1110).
36
+
25
37
  ## [12.32.0] — 2026-08-30
26
38
 
27
39
  ### Added
package/docs/README.md CHANGED
@@ -2,16 +2,16 @@
2
2
 
3
3
  Detailed guides for getting the most out of wicked-garden.
4
4
 
5
- Work in wicked-garden is organized around **9 work-shape archetypes** — not a fixed pipeline. Each prompt classifies into one or more archetypes (triage, explore, specify, decide, ship, review, incident, build, migrate); each owns its own phase shape, produces contract, and HITL discipline.
5
+ Work in wicked-garden is organized around **10 work-shape archetypes** — not a fixed pipeline. Each prompt classifies into one or more archetypes (triage, explore, specify, decide, ship, review, incident, build, migrate, modernize); each owns its own phase shape, produces contract, and HITL discipline.
6
6
 
7
7
  ## Guides
8
8
 
9
9
  | Guide | Description |
10
10
  |-------|-------------|
11
11
  | [Getting Started](getting-started.md) | Installation, required peers, first session, common workflows |
12
- | [Archetypes](v11/archetypes.md) | The 9 work-shape archetypes — why the universal pipeline went away |
13
- | [Domains](domains.md) | The 10 domain skills archetypes invoke for expertise |
14
- | [Required Peers](required-peers.md) | The five required peer plugins and the install/runtime stance |
12
+ | [Archetypes](v11/archetypes.md) | The 10 work-shape archetypes — why the universal pipeline went away |
13
+ | [Domains](domains.md) | The 9 domain skills archetypes invoke for expertise |
14
+ | [Required Peers](required-peers.md) | The one required peer (plus the opt-in layers) and the install/runtime stance |
15
15
  | [The Compiler](compiler.md) | `/wicked-garden-prove compile` — emit a self-contained vault-backed gate into any repo |
16
16
  | [Extending the Catalog](extending.md) | Ship a third-party pack — `{vendor}-{domain}-{role}` skills, the `wicked-pack.json` manifest, the shipped conformance gate, install + crew routing |
17
17
  | [Output Governance (Per-Turn)](outgov-per-turn.md) | The advisory hook lane — `WG_OUTGOV` modes (default `warn`), `rules.recall` as the single per-turn rule source, content-hash provenance for the graph-derived rules dir |
@@ -9,7 +9,7 @@
9
9
  > today, use wicked-garden's `mem` domain (`wicked-garden-mem` `store`/`ingest`)
10
10
  > over wicked-estate. Everything below is historical reference only.
11
11
 
12
- This document defines the wicked-brain chunk format so any CLI (Claude Code, Codex, Gemini, Copilot) can write chunks that integrate into the shared knowledge graph.
12
+ This document defines the wicked-brain chunk format so any CLI (Claude Code, Antigravity, Codex, OpenCode, Pi) can write chunks that integrate into the shared knowledge graph.
13
13
 
14
14
  ## Chunk File Structure
15
15
 
@@ -50,7 +50,7 @@ fail-soft (degrades to `🌱 wg │ idle`), and never blocks a render.
50
50
 
51
51
  ## Your First Session
52
52
 
53
- There is no fixed pipeline. Work is organized around **9 work-shape archetypes** — `triage`, `explore`, `specify`, `decide`, `ship`, `review`, `incident`, `build`, and `migrate`. Each archetype owns its own phase shape, what it produces, and how much human-in-the-loop discipline it demands. After installing, you can invoke any skill immediately. Here are five ways to start:
53
+ There is no fixed pipeline. Work is organized around **10 work-shape archetypes** — `triage`, `explore`, `specify`, `decide`, `ship`, `review`, `incident`, `build`, `migrate`, and `modernize`. Each archetype owns its own phase shape, what it produces, and how much human-in-the-loop discipline it demands. After installing, you can invoke any skill immediately. Here are five ways to start:
54
54
 
55
55
  ### 1. Just Describe What You Want
56
56
 
@@ -73,7 +73,7 @@ When you already know the shape of the work, skip auto-routing and call the arch
73
73
  /wicked-garden-archetype decide "Redis vs Postgres for session storage"
74
74
  ```
75
75
 
76
- All nine are available: `triage`, `explore`, `specify`, `decide`, `ship`, `review`, `incident`, `build`, `migrate`. Gates re-derive "done" through wicked-loom — which re-runs the verifier via wicked-vault — and fail closed if loom is unavailable; sign-off is evidence-backed, never self-asserted.
76
+ All ten are available: `triage`, `explore`, `specify`, `decide`, `ship`, `review`, `incident`, `build`, `migrate`, `modernize`. Gates re-derive "done" through wicked-loom — which re-runs the verifier via wicked-vault — and fail closed if loom is unavailable; sign-off is evidence-backed, never self-asserted.
77
77
 
78
78
  ### 3. Use a Domain Skill Directly
79
79
 
@@ -201,7 +201,7 @@ Your data is stored locally in `~/.something-wicked/wicked-garden/` as JSON file
201
201
 
202
202
  ## Next Steps
203
203
 
204
- - [Archetypes](v11/archetypes.md) — the 9 work-shapes: phases, produces, human-in-the-loop (HITL) discipline, cost bands
204
+ - [Archetypes](v11/archetypes.md) — the 10 work-shapes: phases, produces, human-in-the-loop (HITL) discipline, cost bands
205
205
  - [Required Peers](required-peers.md) — wicked-vault, wicked-estate, wicked-bus
206
206
  - [Compiler](compiler.md) — emit a standalone, vault-backed build gate into any repo
207
207
  - [Domains](domains.md) — browse the domain skills and their actions
@@ -64,7 +64,7 @@ The dogfood findings were patches on a foundation that was wrong-shaped.
64
64
 
65
65
  ## The reframe
66
66
 
67
- Instead of one pipeline + a rigor dial, v11 has **9 archetypes**, each
67
+ Instead of one pipeline + a rigor dial, v11 has **10 archetypes**, each
68
68
  with its own:
69
69
 
70
70
  - **Phase shape** — the actual phase order for that kind of work.
@@ -86,6 +86,7 @@ The archetypes:
86
86
  | incident | triage → investigate → mitigate → resolve → followup | mitigation / RCA / followup | hard:mitigate |
87
87
  | build | plan → implement → test → review | shipped code / test report | discrete:review |
88
88
  | migrate | plan → expand → backfill → cutover → contract | shape change / rollback proof | hard:cutover |
89
+ | modernize | discover → extract → blueprint → transform → parity → cutover | modernization blueprint / parity proof | hard:cutover-gate |
89
90
 
90
91
  Each archetype is self-contained. Phase names are NOT shared across
91
92
  archetypes — `plan` in `build` is not `plan` in `migrate`. We
@@ -188,12 +189,12 @@ See `CHANGELOG.md` v11.0.0 for the comprehensive list. Headlines:
188
189
 
189
190
  ## How to extend
190
191
 
191
- Adding a 10th archetype:
192
+ Adding an 11th archetype:
192
193
 
193
194
  1. Add an entry to `.claude-plugin/archetypes.json`. Declare phases,
194
195
  produces, HITL, signals, etc.
195
196
  2. Write `skills/archetype/refs/{name}.md` — the playbook for the
196
- archetype, ~70-100 lines, following the template of the existing 9.
197
+ archetype, ~70-100 lines, following the template of the existing 10.
197
198
  3. Register the new work-shape in `skills/archetype/SKILL.md` — add it to the
198
199
  dispatch table so `/wicked-garden-archetype {name}` loads its playbook. (The
199
200
  plugin is skills-only: there is no per-archetype command file; the archetype
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wicked-garden",
3
- "version": "12.32.0",
3
+ "version": "12.32.1",
4
4
  "type": "module",
5
5
  "description": "Curated toolkit for what AI coding agents can't do alone: evidence-gated work, codegraph relationships, deterministic multi-file refactor, multi-model second opinions, and cross-session memory. Installs as a Claude Code plugin.",
6
6
  "keywords": [
@@ -89,6 +89,7 @@ Each domain is one consolidated skill that routes to its actions.
89
89
  | `wicked-garden-platform` | Security, infrastructure, compliance, CI/CD, incidents, traces, and plugin diagnostics | security · compliance · incident · health |
90
90
  | `wicked-garden-product` | Requirements, customer feedback, strategy, UX, accessibility, and design review | elicit · acceptance · analyze · strategy · ux-review |
91
91
  | `wicked-garden-qe` | Evidence-gated quality engineering: strategy, scenario authoring, execution, independent verdicts, ledger insight, and the 3-agent acceptance pipeline | setup · plan · author · execute · review · insight · accept |
92
+ | `wicked-garden-repo-learn` | Learn an unfamiliar repo (churn → hotspots → read the load-bearing intersection) and capture BOTH memories and policies as inert estate proposals a human reviews | churn · hotspots · read · capture |
92
93
  | `wicked-garden-search` | Structural code search, lineage, blast-radius, and codebase intelligence | blast-radius · lineage · hotspots · service-map · index |
93
94
  | `wicked-garden-smaht` | On-demand context assembly + session briefing from the knowledge layer, search, and the event log | briefing · state · events-import · intent |
94
95
 
@@ -45,10 +45,11 @@ whether the artifact or diff actually violates each applicable rule.
45
45
  language/layer/framework facets to narrow). Each rule has:
46
46
  `id` (PAT-NNN), `statement` (the pattern text), `severity`, `targets`
47
47
  (language/layer/framework facets — absent = wildcard), and a provenance
48
- ref (`<doc>@<blob sha>#<RULE-ID>`) — the architecture-wiki doc that minted
49
- the rule; cite it in findings so a reviewer can read the doctrine behind
50
- the verdict. (Rules are authored as wiki docs, never written by agents —
51
- the lifecycle is wicked-core's `crates/wicked-governance/WIKI.md`.)
48
+ ref (`<doc>@<blob sha>#<RULE-ID>`) — the Steering doc that minted the
49
+ rule; cite it in findings so a reviewer can read the doctrine behind the
50
+ verdict. (Steering rules are authored by doc PR or through crew's
51
+ governed UI/chat surface — never via this MCP, which stays read-only;
52
+ the lifecycle is wicked-core's `crates/wicked-governance/STEERING.md`.)
52
53
 
53
54
  2. **Filter by target**: only evaluate rules whose facets match the artifact
54
55
  (language, layer, framework). Absent facets match everything.
@@ -88,13 +88,15 @@ and score; present the top hits and cite `memory_id`/scope when the user
88
88
  needs provenance. For a synthesized, citation-bearing answer use the
89
89
  `answer` action instead.
90
90
 
91
- **Architecture-wiki doctrine** lives in the knowledge store under `wiki:`
92
- scopes (e.g. `wiki:architecture` — planes, storage doctrine, event grammar,
93
- ADR rationale): recall it with `knowledge.recall` /
91
+ **Steering doctrine** (the governance rules, 7 steering types) lives in the
92
+ knowledge store under `wiki:` scopes (a historical prefix — e.g.
93
+ `wiki:architecture`: planes, storage doctrine, event grammar, ADR
94
+ rationale): recall it with `knowledge.recall` /
94
95
  `{"scope_prefix": "wiki:"}` via `answer`, and recall the *enforceable* rules
95
96
  behind it with the estate MCP `rules.recall` tool (faceted, severity-ordered,
96
- each hit citing its source doc). Authoring/seeding/retiring the wiki is
97
- operator work — see wicked-core's `crates/wicked-governance/WIKI.md`.
97
+ each hit citing its source doc). Managing steering (import / chat / edit /
98
+ retire) is operator work — see `crates/wicked-governance/STEERING.md`
99
+ in wicked-core.
98
100
 
99
101
  ## Review / Maintain
100
102
 
@@ -27,7 +27,7 @@ AI-powered modification of existing images through two primary modes: image-to-i
27
27
  Changes the overall style or adds global elements while preserving core composition.
28
28
 
29
29
  ```bash
30
- sh "${CLAUDE_PLUGIN_ROOT}/scripts/_python.sh" "${CLAUDE_PLUGIN_ROOT}/skills/imagery/scripts/provider.py" edit \
30
+ sh "${CLAUDE_PLUGIN_ROOT}/scripts/_python.sh" "${CLAUDE_PLUGIN_ROOT}/skills/product/imagery/scripts/provider.py" edit \
31
31
  --image ./source.png \
32
32
  --prompt "Same scene but with a dramatic sunset sky" \
33
33
  --output ./v2.png
@@ -43,7 +43,7 @@ sh "${CLAUDE_PLUGIN_ROOT}/scripts/_python.sh" "${CLAUDE_PLUGIN_ROOT}/skills/imag
43
43
  Precise edits to specific regions using a binary mask (white = edit area, black = preserve).
44
44
 
45
45
  ```bash
46
- sh "${CLAUDE_PLUGIN_ROOT}/scripts/_python.sh" "${CLAUDE_PLUGIN_ROOT}/skills/imagery/scripts/provider.py" inpaint \
46
+ sh "${CLAUDE_PLUGIN_ROOT}/scripts/_python.sh" "${CLAUDE_PLUGIN_ROOT}/skills/product/imagery/scripts/provider.py" inpaint \
47
47
  --image ./source.png \
48
48
  --mask ./mask.png \
49
49
  --prompt "Replace with floating lanterns" \
@@ -87,7 +87,7 @@ Use upscaling as the last step to bring a draft to production quality:
87
87
 
88
88
  ```bash
89
89
  # Upscaling (cstudio only — other providers may not support this)
90
- sh "${CLAUDE_PLUGIN_ROOT}/scripts/_python.sh" "${CLAUDE_PLUGIN_ROOT}/skills/imagery/scripts/provider.py" generate \
90
+ sh "${CLAUDE_PLUGIN_ROOT}/scripts/_python.sh" "${CLAUDE_PLUGIN_ROOT}/skills/product/imagery/scripts/provider.py" generate \
91
91
  --provider cstudio \
92
92
  --prompt "upscale" \
93
93
  --output ./final_hires.png
@@ -69,20 +69,20 @@ When the output is "almost there" but not quite:
69
69
 
70
70
  ```bash
71
71
  # Image-to-image edit
72
- sh "${CLAUDE_PLUGIN_ROOT}/scripts/_python.sh" "${CLAUDE_PLUGIN_ROOT}/skills/imagery/scripts/provider.py" edit \
72
+ sh "${CLAUDE_PLUGIN_ROOT}/scripts/_python.sh" "${CLAUDE_PLUGIN_ROOT}/skills/product/imagery/scripts/provider.py" edit \
73
73
  --image ./source.png \
74
74
  --prompt "Same scene but with dramatic sunset sky" \
75
75
  --output ./v2.png
76
76
 
77
77
  # Inpainting with mask
78
- sh "${CLAUDE_PLUGIN_ROOT}/scripts/_python.sh" "${CLAUDE_PLUGIN_ROOT}/skills/imagery/scripts/provider.py" inpaint \
78
+ sh "${CLAUDE_PLUGIN_ROOT}/scripts/_python.sh" "${CLAUDE_PLUGIN_ROOT}/skills/product/imagery/scripts/provider.py" inpaint \
79
79
  --image ./source.png \
80
80
  --mask ./mask.png \
81
81
  --prompt "Replace with floating lanterns" \
82
82
  --output ./v2_inpaint.png
83
83
 
84
84
  # Use a specific provider
85
- sh "${CLAUDE_PLUGIN_ROOT}/scripts/_python.sh" "${CLAUDE_PLUGIN_ROOT}/skills/imagery/scripts/provider.py" edit \
85
+ sh "${CLAUDE_PLUGIN_ROOT}/scripts/_python.sh" "${CLAUDE_PLUGIN_ROOT}/skills/product/imagery/scripts/provider.py" edit \
86
86
  --provider stability \
87
87
  --image ./source.png \
88
88
  --prompt "Oil painting style" \
@@ -34,7 +34,7 @@ AI-powered image generation from text prompts. Supports multiple providers throu
34
34
 
35
35
  ```bash
36
36
  # Check which providers are available
37
- sh "${CLAUDE_PLUGIN_ROOT}/scripts/_python.sh" "${CLAUDE_PLUGIN_ROOT}/skills/imagery/scripts/provider.py" detect
37
+ sh "${CLAUDE_PLUGIN_ROOT}/scripts/_python.sh" "${CLAUDE_PLUGIN_ROOT}/skills/product/imagery/scripts/provider.py" detect
38
38
  ```
39
39
 
40
40
  The provider abstraction selects the best available provider automatically. A specific provider can be forced when needed.
@@ -74,12 +74,12 @@ For detailed prompt engineering techniques, see [refs/prompt-engineering.md](ref
74
74
 
75
75
  ```bash
76
76
  # Basic generation (auto-detects best available provider)
77
- sh "${CLAUDE_PLUGIN_ROOT}/scripts/_python.sh" "${CLAUDE_PLUGIN_ROOT}/skills/imagery/scripts/provider.py" generate \
77
+ sh "${CLAUDE_PLUGIN_ROOT}/scripts/_python.sh" "${CLAUDE_PLUGIN_ROOT}/skills/product/imagery/scripts/provider.py" generate \
78
78
  --prompt "Your crafted prompt" \
79
79
  --output ./output/v1.png
80
80
 
81
81
  # Use a specific provider
82
- sh "${CLAUDE_PLUGIN_ROOT}/scripts/_python.sh" "${CLAUDE_PLUGIN_ROOT}/skills/imagery/scripts/provider.py" generate \
82
+ sh "${CLAUDE_PLUGIN_ROOT}/scripts/_python.sh" "${CLAUDE_PLUGIN_ROOT}/skills/product/imagery/scripts/provider.py" generate \
83
83
  --prompt "Your crafted prompt" \
84
84
  --provider openai \
85
85
  --output ./output/v1.png
@@ -19,5 +19,5 @@ if [ -z "$IMAGE" ]; then
19
19
  fi
20
20
 
21
21
  echo "Image analysis for '$IMAGE' should be performed by reading the file directly."
22
- echo "See: skills/imagery/review/SKILL.md"
22
+ echo "See: skills/product/imagery/review/SKILL.md"
23
23
  exit 0
@@ -1,6 +1,7 @@
1
1
  #!/bin/bash
2
2
  # edit.sh - Delegates to provider.py for multi-provider image editing
3
- PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "$0")/../../.." && pwd)}"
3
+ # skills/product/imagery/scripts/ -> plugin root is four levels up.
4
+ PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "$0")/../../../.." && pwd)}"
4
5
 
5
6
  IMAGE="$1"
6
7
  PROMPT="$2"
@@ -11,4 +12,4 @@ if [ -z "$IMAGE" ] || [ -z "$PROMPT" ]; then
11
12
  exit 1
12
13
  fi
13
14
 
14
- python3 "${PLUGIN_ROOT}/skills/imagery/scripts/provider.py" edit --image "$IMAGE" --prompt "$PROMPT" --output "$OUT_FILE"
15
+ python3 "${PLUGIN_ROOT}/skills/product/imagery/scripts/provider.py" edit --image "$IMAGE" --prompt "$PROMPT" --output "$OUT_FILE"
@@ -1,6 +1,7 @@
1
1
  #!/bin/bash
2
2
  # generate.sh - Delegates to provider.py for multi-provider image generation
3
- PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "$0")/../../.." && pwd)}"
3
+ # skills/product/imagery/scripts/ -> plugin root is four levels up.
4
+ PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "$0")/../../../.." && pwd)}"
4
5
 
5
6
  PROMPT="$1"
6
7
  OUT_FILE="${2:-./output.png}"
@@ -10,4 +11,4 @@ if [ -z "$PROMPT" ]; then
10
11
  exit 1
11
12
  fi
12
13
 
13
- python3 "${PLUGIN_ROOT}/skills/imagery/scripts/provider.py" generate --prompt "$PROMPT" --output "$OUT_FILE"
14
+ python3 "${PLUGIN_ROOT}/skills/product/imagery/scripts/provider.py" generate --prompt "$PROMPT" --output "$OUT_FILE"
@@ -226,19 +226,19 @@ Requirements should be saved to:
226
226
 
227
227
  ## Templates
228
228
 
229
- ### Quick Start Template
230
- ```bash
231
- # Copy minimal template for new requirements
232
- cp "${CLAUDE_PLUGIN_ROOT}/templates/requirements-minimal.md" \
233
- requirements.md
234
- ```
235
-
236
- ### Full Template
237
- ```bash
238
- # Copy full template for comprehensive analysis
239
- cp "${CLAUDE_PLUGIN_ROOT}/templates/requirements-full.md" \
240
- requirements.md
241
- ```
229
+ Both skeletons live in this document — there is no separate `templates/`
230
+ directory to copy from (it was cut in v12.21). Start a new document by copying
231
+ the fenced markdown block from the matching section above and filling in the
232
+ `{placeholders}`:
233
+
234
+ - **Quick start** — the **Minimal Output Format** section, for smaller
235
+ features or rapid analysis (3-5 core stories, out of scope, open questions).
236
+ - **Full** — the **Standard Output Structure** section, for a comprehensive
237
+ analysis (personas, functional + non-functional requirements, scope,
238
+ dependencies, risks, traceability).
239
+
240
+ Save the result where **Output Delivery** says (`requirements.md`, or
241
+ `phases/requirements/analysis.md` inside a project workflow).
242
242
 
243
243
  ## Resources
244
244
 
@@ -291,6 +291,8 @@ Use this template when creating new user stories:
291
291
 
292
292
  ## Resources
293
293
 
294
- - Domain-specific examples: `skills/requirements-analysis/refs/story-examples/`
295
- - Generate template: `sh "${CLAUDE_PLUGIN_ROOT}/scripts/_python.sh" "${CLAUDE_PLUGIN_ROOT}/scripts/user-story-template.sh"`
294
+ - Domain-specific examples: `requirements-example-auth.md` and
295
+ `requirements-example-export-integration.md` in this skill's `refs/`
296
+ - New-story skeleton: copy the fenced block in the **Template for New Stories**
297
+ section above (there is no generator script)
296
298
  - Validate against INVEST criteria checklist above
@@ -32,7 +32,9 @@ is portable by directory copy.
32
32
 
33
33
  ## 2. `manifest.json` Schema (public)
34
34
 
35
- Formal JSON Schema: [`schemas/evidence.json`](../schemas/evidence.json)
35
+ Formal JSON Schema: `schemas/evidence.json`, shipped in the `wicked-vault` npm
36
+ package (not vendored in this plugin — resolve it locally with
37
+ `ls "$(npm root -g)/wicked-vault/schemas/evidence.json"`).
36
38
 
37
39
  ```jsonc
38
40
  {
@@ -0,0 +1,163 @@
1
+ ---
2
+ name: wicked-garden-repo-learn
3
+ user-invocable: true
4
+ description: |
5
+ Learn an unfamiliar repo the way a senior engineer does: follow where the code
6
+ actually churns, find what that churn touches that the rest of the system leans
7
+ on, read the load-bearing code for real, then write down BOTH what you learned
8
+ (memories) and what should hold (policies) — as inert estate proposals a human
9
+ reviews, never as asserted fact.
10
+
11
+ Four BOUNDED phases: (1) SAMPLED git-churn → ranked active areas (explicit
12
+ top-N cap + a sampling rule for large histories — never streams every commit);
13
+ (2) hotspots + blast-radius via wicked-garden-search, cross-referenced with
14
+ churn to isolate load-bearing volatile code; (3) READ the intersection through
15
+ the estate graph (FetchContent / RetrieveEntity / TraverseGraph) for genuine
16
+ technical understanding; (4) DERIVE memories AND policies and submit them via
17
+ the estate `proposal.submit` tool (inert queue, safe under --readonly).
18
+
19
+ Use when: "learn this repo", "onboard me to this codebase", "study the active
20
+ areas", "what should I know before working here", "derive memories / policies
21
+ from this repo", "capture what matters about this codebase". Durable
22
+ orientation + capture — for a read-only narrative with no capture, use
23
+ wicked-garden-search `narrate` instead.
24
+ phase_relevance: ["*"]
25
+ archetype_relevance: ["*"]
26
+ ---
27
+
28
+ # wicked-garden-repo-learn — churn-led repo learning that captures back
29
+
30
+ A repo teaches you where to look if you follow two independent signals at once:
31
+ **temporal** (where the code churns) and **structural** (what the rest of the
32
+ system depends on). This skill walks the intersection, reads it for real, and
33
+ **captures the learning back** as estate proposals — memories (what is true) and
34
+ policies (what should hold). Garden ORCHESTRATES; estate GROUNDS (graph + read)
35
+ and RECEIVES (the proposal queue); a human APPROVES. Nothing here asserts a fact
36
+ into the record — every capture is an inert proposal the studio Memories /
37
+ Policies surfaces review.
38
+
39
+ **Why churn is a separate step:** estate's `RankHotspots` is *structural*
40
+ PageRank, not temporal — it never sees git history. Churn is the gap this skill
41
+ fills, with a **bounded, sampled** git-log method (never one that streams every
42
+ commit). The two signals are complementary, not redundant; § Cross-reference is
43
+ where the value is.
44
+
45
+ ## The four phases
46
+
47
+ | # | Phase | Produces | Where |
48
+ |---|-------|----------|-------|
49
+ | 1 | **churn** | ranked active paths/areas over a window, top-N capped | [refs/churn-sampling.md](refs/churn-sampling.md) |
50
+ | 2 | **hotspots** | most-central symbols + blast-radius of the churn set | `wicked-garden-search` (reused — do NOT reimplement) |
51
+ | 3 | **read** | real understanding of the load-bearing, volatile code | § Read the intersection |
52
+ | 4 | **capture** | memories AND policies as inert `proposal.submit` entries | [refs/capture-proposals.md](refs/capture-proposals.md) |
53
+
54
+ Run them in order — each phase narrows the next. A partial run is still useful
55
+ (churn alone orients; churn+hotspots+read without capture is a briefing), but the
56
+ skill's contract is that **understanding ends in captured proposals**, not prose.
57
+
58
+ ## Phase 1 — churn (the bounded, sampled step)
59
+
60
+ Rank the paths that changed most over a window. The method is fully specified in
61
+ [refs/churn-sampling.md](refs/churn-sampling.md); the non-negotiables:
62
+
63
+ - **Size the window first** (`git rev-list --count`) — choose full-scan vs sample
64
+ by commit count, never by hoping.
65
+ - **Explicit top-N cap** (default **40** paths) — the final list is always
66
+ `head -N`; the raw `--name-only` stream stays inside the shell pipe (sort /
67
+ uniq), never in your context.
68
+ - **Sampling rule for large histories** — above the commit cap (default
69
+ **2000**), switch to a recency-capped or even-stride sample; never `git log`
70
+ the full history unbounded. Worker output is capped ~25K chars — a full-history
71
+ churn dump both blows that and starves the phases that matter.
72
+ - **Roll up to directories** for wide monorepos; **filter generated/vendored
73
+ noise** (lockfiles, `dist/`, `target/`, `node_modules/`).
74
+
75
+ Output of phase 1: a ranked list of ≤N `count path` (or `count dir/`) rows.
76
+
77
+ ## Phase 2 — hotspots + blast-radius (reuse wicked-garden-search)
78
+
79
+ Do NOT reimplement centrality. Use the **wicked-garden-search** skill:
80
+
81
+ - `hotspots` — most-central symbols by PageRank (`RankHotspots`). Read its
82
+ [refs/hotspots.md](../search/refs/hotspots.md); pass `--limit` near your top-N.
83
+ - `blast-radius <path>` — for each top churn path, the dependents estate sees
84
+ (including injected bus/dispatch/capability/archetype edges grep can't). This
85
+ is what tells you a churny file is load-bearing vs peripheral.
86
+
87
+ Freshness is a precondition: run the search skill's `index` action first
88
+ (`wicked-estate index <path>`) and heed any `STALENESS` marker.
89
+
90
+ ## Cross-reference — the 2×2 that picks read targets
91
+
92
+ Churn and centrality answer different questions; the intersection ranks targets.
93
+
94
+ | | **High churn** | **Low churn** |
95
+ |-----------------------|----------------|---------------|
96
+ | **High centrality** | load-bearing + volatile → **read deeply**; likely yields BOTH a memory (how it works / why it moves) AND a policy (what must hold as it changes) | stable core → **read for invariants**; yields policies (severity `error`/`critical`) more than memories |
97
+ | **Low centrality** | churny periphery (config, fixtures, generated) → **mostly noise**; skip unless it's a hot integration seam | quiet leaf → **skip** |
98
+
99
+ The prime targets are the top-left cell: paths that appear in BOTH the phase-1
100
+ churn list and the phase-2 hotspot/blast-radius set. Read those first.
101
+
102
+ ## Phase 3 — read the intersection
103
+
104
+ For each cross-referenced target, build **genuine** understanding — not a file
105
+ listing — via the estate MCP (all read-only):
106
+
107
+ 1. `SearchEntity` `{"name": "<symbol-or-path>"}` → resolve to node ids/kinds.
108
+ 2. `RetrieveEntity` → the symbol's structured record; `FetchContent` → the actual
109
+ source slice (read the code, don't infer from names).
110
+ 3. `TraverseGraph` (bounded — it carries `max_depth`/`max_nodes`) or `Lineage` →
111
+ how the target connects: what it calls, what calls it, which events/commands
112
+ inject edges into it.
113
+ 4. Recall what's already known before writing anything new: `wicked-garden-mem`
114
+ `recall` (`scope_prefix: ""`) so you extend the record rather than duplicate it.
115
+
116
+ Stop when you can state, per target, **what it does, why it changes, what it
117
+ depends on, and what would break** — that is the input to phase 4.
118
+
119
+ ## Phase 4 — capture: memories AND policies as proposals
120
+
121
+ Turn understanding into two kinds of reviewable record via the estate
122
+ MCP **`proposal.submit`** tool (inert queue; a PERMITTED safe write even under
123
+ `--readonly`). Full contract, payloads, facets, and derivation heuristics:
124
+ [refs/capture-proposals.md](refs/capture-proposals.md). The essentials — use the
125
+ enum values EXACTLY as written (an out-of-enum `tier` or `severity` is rejected
126
+ when the proposal is approved, so the learning is lost):
127
+
128
+ - **Memory** — what is *true* about this repo. `kind_type: "memory"`; payload
129
+ `{"content": "<1–3 sentences>", "tier": "<value>"}` where `tier` is EXACTLY one
130
+ of `working` / `episodic` / `semantic` / `procedural` / `archival` — for a repo
131
+ learning use `semantic` (a fact/decision) or `procedural` (a how-to/convention);
132
+ NEVER invent a tier like `durable`. Facets `{"repo": "<name>", "project": "<name>"}`.
133
+ - **Policy** — what *should hold*. `kind_type: "policy:<type>"` where `<type>` ∈
134
+ architecture · development · security · testing · operations · compliance ·
135
+ design-ux; payload `{"rule": "<imperative>", "severity": "<value>"}` where
136
+ `severity` is EXACTLY one of `info` / `warn` / `error` / `critical` — the middle
137
+ band is `warn`, NOT `warning`. Facets `{"repo": "<name>", "project": "<name>", "language": "<lang>"}`.
138
+ - **Never pass `provenance`** — the server stamps it from `WICKED_RUN_*`. Passing
139
+ it is at best ignored; treat provenance as not yours to set.
140
+ - Derive **both** per target where the 2×2 warrants it: the memory records the
141
+ *is*, the policy records the *ought*. A stable high-centrality invariant is a
142
+ policy; a "this is how X actually wires up" discovery is a memory.
143
+
144
+ ## Degrade + honesty
145
+
146
+ - **Estate unreachable** (index/MCP down): phase 1 still runs (pure git); for
147
+ phases 2–3 fall back per the search skill's ladder (CLI → Grep, flagging that
148
+ injected edges are MISSING). Say so — don't present a grep approximation as the
149
+ graph answer.
150
+ - **`proposal.submit` fails (a JSON-RPC error, e.g. -32602 / -32603)**: do NOT silently drop the learning.
151
+ Emit the derived memories and policies as a structured block in your report so
152
+ a human (or a later run) can submit them, and name the degrade.
153
+ - Capture is a **proposal**, not an assertion — report it as "proposed N
154
+ memories, M policies (pending review)", never "recorded".
155
+
156
+ ## Depth
157
+
158
+ - [refs/churn-sampling.md](refs/churn-sampling.md) — the bounded/sampled git-log
159
+ method: window sizing, the sample rule, the top-N cap, directory rollup, noise
160
+ filters, and the cross-platform counting fallback.
161
+ - [refs/capture-proposals.md](refs/capture-proposals.md) — the `proposal.submit`
162
+ contract for memories and policies, the derivation heuristics (2×2 → what to
163
+ propose), worked examples, and the idempotency/dedup discipline.
@@ -0,0 +1,162 @@
1
+ # Capture — memories AND policies as estate proposals
2
+
3
+ The learning phase ends by writing back **two kinds** of record through the estate
4
+ MCP **`proposal.submit`** tool: **memories** (what is *true* about this repo) and
5
+ **policies** (what *should hold* in it). Both land in estate's **inert proposal
6
+ queue** — a type-generic write surface that is a PERMITTED safe write **even under
7
+ `--readonly`**, because a proposal is never recalled or applied until an operator
8
+ approves it. A governed worker's estate MCP already opens the operator GLOBAL
9
+ store and permits `proposal.submit`, so proposals surface in the studio Memories /
10
+ Policies review UI. This is *propose, not assert* — you never inject a fact into
11
+ the record; a human promotes it.
12
+
13
+ ## The `proposal.submit` contract (wire shape)
14
+
15
+ `proposal.submit` takes exactly three caller-supplied fields:
16
+
17
+ | Field | Type | Rule |
18
+ |-------|------|------|
19
+ | `kind_type` | string | `"memory"` OR `"policy:<type>"`; must match `^[a-z][a-z0-9_-]*(:[a-z][a-z0-9_-]*)?$` |
20
+ | `payload` | JSON **object** | required; a present non-object is rejected `-32602` (never silently defaulted) |
21
+ | `facets` | JSON object of `axis:value` strings | optional; each axis is a lowercase token `^[a-z][a-z0-9_-]*$`, each value non-empty |
22
+
23
+ **`provenance` is NOT a caller field.** The server stamps it from its own launch
24
+ env (`WICKED_RUN_ID` / `WICKED_RUN_UNIT` / `WICKED_RUN_AGENT`) — a worker cannot
25
+ forge its own attribution, and passing `provenance` in args is not honored. Do not
26
+ construct it.
27
+
28
+ On success the tool returns `{"id": "<proposal-id>"}`. A malformed `kind_type`,
29
+ `facets`, or a non-object `payload` fails loud with `-32602` — fix and resubmit,
30
+ never swallow.
31
+
32
+ ### `<type>` for policies (the seven steering types)
33
+
34
+ `policy:` must be suffixed with exactly one: `architecture` · `development` ·
35
+ `security` · `testing` · `operations` · `compliance` · `design-ux`. These are the
36
+ estate/steering types — pick the one the rule governs, not a freeform tag.
37
+
38
+ ## Memory payload + facets
39
+
40
+ ```json
41
+ {
42
+ "kind_type": "memory",
43
+ "payload": { "content": "<1–3 self-contained sentences>", "tier": "semantic" },
44
+ "facets": { "repo": "<repo-name>", "project": "<project-name>" }
45
+ }
46
+ ```
47
+
48
+ - `content` — distilled, self-contained: the *why* and *what* a future session
49
+ needs, not a paragraph of *how*. One to three sentences. If it needs the current
50
+ file open to make sense, it isn't distilled yet.
51
+ - `tier` — `"semantic"` for stable facts/decisions/gotchas ("X is wired via the
52
+ bus, not a direct call"); `"procedural"` for a repeatable how-to/convention
53
+ ("to add a language, drop a row in languages.toml + a .scm file — no core
54
+ change").
55
+ - `facets` — `repo:` and `project:` locate the memory so faceted recall admits it
56
+ for the right work. Use the repo's directory/remote name and the umbrella
57
+ project (here, `wicked`).
58
+
59
+ ## Policy payload + facets
60
+
61
+ ```json
62
+ {
63
+ "kind_type": "policy:architecture",
64
+ "payload": { "rule": "<imperative statement of what must hold>", "severity": "error" },
65
+ "facets": { "repo": "<repo-name>", "project": "<project-name>", "language": "<lang>" }
66
+ }
67
+ ```
68
+
69
+ - `rule` — an imperative the code should satisfy, phrased so a reviewer can judge
70
+ a diff against it ("Every emitted Edge carries {confidence, provenance,
71
+ resolved_by}"; "No content-hash or line-number node ids"). Not a description —
72
+ a *ought*.
73
+ - `severity` — `info` (advisory) · `warn` (should) · `error` (must; a violation
74
+ blocks) · `critical` (must; a violation is a security/data-loss class). Map from
75
+ the 2×2 below and from what the code's own guardrails signal.
76
+ - `facets` — policies add `language:` on top of `repo:`/`project:`, so a rule that
77
+ is language-scoped ("Rust: no bare `panic!` in library crates") admits only for
78
+ that language. Omit `language:` for a language-agnostic architectural rule.
79
+
80
+ ## Deriving BOTH — the 2×2 → proposal map
81
+
82
+ The cross-reference cell (SKILL.md § Cross-reference) tells you *what kind* of
83
+ proposal a read target warrants:
84
+
85
+ | Cell | Signal | Propose |
86
+ |------|--------|---------|
87
+ | **high churn + high centrality** | load-bearing and moving | **BOTH**: a memory (how it works / why it churns / what it wires) + a policy (the invariant that must survive the churn — often `error`) |
88
+ | **low churn + high centrality** | stable core / invariant | mostly **policy** (`error`/`critical`) capturing the invariant; add a memory only if the *why* is non-obvious |
89
+ | **high churn + low centrality** | churny periphery | usually **neither**; a memory only if it's a hot integration seam worth flagging (e.g. "config X is edited every release — treat as an interface") |
90
+ | **low churn + low centrality** | quiet leaf | **skip** |
91
+
92
+ The discipline: a memory records the **is** (this is how the system is), a policy
93
+ records the **ought** (this is what a change must preserve). A single load-bearing
94
+ target frequently yields one of each — the memory so the next reader understands
95
+ it, the policy so the next editor doesn't break it. Do not force a proposal from a
96
+ cell that says skip; a thin capture pollutes the queue the operator must triage.
97
+
98
+ ## Worked examples
99
+
100
+ Memory (procedural, from reading a high-churn/high-centrality extractor):
101
+
102
+ ```json
103
+ {
104
+ "kind_type": "memory",
105
+ "payload": {
106
+ "content": "Language extractors are data, not code: a new language is a row in wicked-estate-extract/languages.toml plus a <name>.scm query file — zero core change. Per-language match arms in Rust are a rejected pattern.",
107
+ "tier": "procedural"
108
+ },
109
+ "facets": { "repo": "wicked-estate", "project": "wicked" }
110
+ }
111
+ ```
112
+
113
+ Policy (architecture, from the same subsystem's invariant):
114
+
115
+ ```json
116
+ {
117
+ "kind_type": "policy:architecture",
118
+ "payload": {
119
+ "rule": "Every emitted Edge must carry {confidence, provenance, resolved_by}; never present a heuristic edge as a fact.",
120
+ "severity": "error"
121
+ },
122
+ "facets": { "repo": "wicked-estate", "project": "wicked", "language": "rust" }
123
+ }
124
+ ```
125
+
126
+ Policy (development, language-scoped, from a stable core with a clear guardrail):
127
+
128
+ ```json
129
+ {
130
+ "kind_type": "policy:development",
131
+ "payload": {
132
+ "rule": "Rust: no bare panic!/unwrap in library crates; surface a typed error.",
133
+ "severity": "warn"
134
+ },
135
+ "facets": { "repo": "wicked-estate", "project": "wicked", "language": "rust" }
136
+ }
137
+ ```
138
+
139
+ ## Before you submit — recall first, then dedup
140
+
141
+ 1. **Recall the existing record** (`wicked-garden-mem` `recall`, `scope_prefix:
142
+ ""`, and estate `rules.recall` for policies). If the learning already exists,
143
+ do not re-propose it — the queue is a human's triage list, and duplicates cost
144
+ review time. Propose only the *delta*.
145
+ 2. **One claim per proposal.** A memory that bundles three facts, or a policy that
146
+ bundles three rules, can't be approved/rejected cleanly. Split them.
147
+ 3. **Ground the claim in what you read.** Every proposal must trace to a target
148
+ you actually opened in phase 3 (`FetchContent`/`RetrieveEntity`), not to a name
149
+ you inferred. An ungrounded proposal is exactly the asserted-not-evidenced
150
+ failure this method exists to avoid.
151
+
152
+ ## Failure handling
153
+
154
+ - `-32602` (invalid kind_type/facets/payload): a *your-args* bug — fix the shape
155
+ (lowercase kind_type suffix, object payload, valid axis tokens) and resubmit.
156
+ - `-32603` / transport / MCP unreachable: the store or server failed. Do **not**
157
+ drop the learning — collect the derived memories and policies into a structured
158
+ block in your final report (the exact `{kind_type, payload, facets}` objects) so
159
+ a human or a later run can submit them, and name the degrade explicitly.
160
+ - Report captures honestly: "**proposed** N memories, M policies (pending
161
+ review)", never "recorded" or "stored" — nothing is in the record until an
162
+ operator approves it.
@@ -0,0 +1,197 @@
1
+ # Churn sampling — the bounded, top-N git-log method
2
+
3
+ Estate does **not** rank git churn: `RankHotspots` is structural PageRank over
4
+ Calls+Imports edges, blind to history. Temporal ranking is this phase's job, and
5
+ it is a git-log method — but a *disciplined* one. The failure mode to design out:
6
+ a naive `git log --name-only` over a long history streams megabytes, blows the
7
+ worker's ~25K-char output cap (estate agent-behavior R4), and starves the phases
8
+ that actually matter. Every recipe below is **bounded** — an explicit top-N cap
9
+ plus a sampling rule keyed to history size.
10
+
11
+ ## The three invariants
12
+
13
+ 1. **Cap the output.** The list you keep is always `head -N` (default **40**).
14
+ The raw `--name-only` stream is consumed *inside the shell pipe* (`sort | uniq
15
+ | sort | head`); only the final ≤N rows reach your context. Never `cat` or echo
16
+ the full stream.
17
+ 2. **Cap the input.** Above a commit threshold (default **2000**) you MUST sample
18
+ or window — never `git log` the full history unbounded. Bound it even when you
19
+ think it's small; size it first and find out.
20
+ 3. **Two signals, not one.** Churn alone over-weights churny-but-shallow files
21
+ (config, generated). The output of this phase is an *input* to the cross-
22
+ reference against structural hotspots (SKILL.md § Cross-reference), never a
23
+ standalone verdict.
24
+
25
+ ## Step 0 — size the window (bounded probe, no materialization)
26
+
27
+ Count commits in the window without listing them, and count tracked files for the
28
+ rollup decision:
29
+
30
+ ```bash
31
+ WINDOW="12.months" # default; override per ask
32
+ C=$(git rev-list --count --since="$WINDOW" HEAD) # commits in window
33
+ F=$(git ls-files | wc -l) # tracked files
34
+ echo "commits_in_window=$C tracked_files=$F"
35
+ ```
36
+
37
+ `git rev-list --count` is O(commits) but materializes nothing — safe on any
38
+ history. Choose the mode from `C`:
39
+
40
+ | `C` (commits in window) | Mode | Recipe |
41
+ |-------------------------|------|--------|
42
+ | `C ≤ 2000` | **full-scan** | § Full-scan churn |
43
+ | `C > 2000` | **sampled** | § Sampled churn (pick a strategy) |
44
+
45
+ And choose granularity from `F`:
46
+
47
+ | `F` (tracked files) | Granularity |
48
+ |---------------------|-------------|
49
+ | `F ≤ 5000` | file-level (default) |
50
+ | `F > 5000`, or file-level top-N is dominated by single-change files | **directory rollup** (§ Directory rollup) |
51
+
52
+ Thresholds are defaults, not laws — a repo with enormous commits (vendored blobs)
53
+ may warrant a lower cap; a tiny repo with a 5-year window may stay full-scan above
54
+ 2000. State the mode you picked and why.
55
+
56
+ ## Full-scan churn (small histories, `C ≤ 2000`)
57
+
58
+ ```bash
59
+ git log --since="$WINDOW" --no-renames --name-only --pretty=format: -- . \
60
+ | grep -v '^$' \
61
+ | grep -Ev '(^|/)(node_modules|dist|build|target|vendor|\.min\.|package-lock\.json|Cargo\.lock|pnpm-lock\.yaml|yarn\.lock)(/|$)' \
62
+ | sort | uniq -c | sort -rn \
63
+ | head -40
64
+ ```
65
+
66
+ - `--no-renames` (git's default; stated for intent) — do **not** `--follow`
67
+ (per-path only, incompatible with a whole-tree scan).
68
+ - `--pretty=format:` empties the commit-header lines so only file paths remain;
69
+ `grep -v '^$'` drops the blank separators.
70
+ - The two `grep -Ev` filters strip generated/vendored/lockfile noise — churn there
71
+ is not active *development*. Extend the pattern per repo (e.g. `__generated__`,
72
+ `.pb.go`, `migrations/` if autogenerated).
73
+ - `sort | uniq -c | sort -rn | head -40` = count per path, most-changed first,
74
+ top-N capped. This is the whole method for small histories.
75
+
76
+ Output rows are `<count> <path>`. That ranked list is phase 1's product.
77
+
78
+ ## Sampled churn (large histories, `C > 2000`)
79
+
80
+ Pick ONE strategy. Both keep the *input* bounded; the output cap (`head -40`) is
81
+ unchanged.
82
+
83
+ ### Strategy A — recency cap (default)
84
+
85
+ Most-recent-N commits. Recent churn is the better signal for "active areas", and
86
+ it's a single git call:
87
+
88
+ ```bash
89
+ git log --since="$WINDOW" --no-renames --name-only --pretty=format: --max-count=2000 -- . \
90
+ | grep -v '^$' \
91
+ | grep -Ev '(^|/)(node_modules|dist|build|target|vendor|\.min\.|package-lock\.json|Cargo\.lock|pnpm-lock\.yaml|yarn\.lock)(/|$)' \
92
+ | sort | uniq -c | sort -rn \
93
+ | head -40
94
+ ```
95
+
96
+ `--max-count=2000` bounds the walk to the 2000 newest commits in the window.
97
+ Deterministic, recency-biased, one process. Use this unless the window's *tail*
98
+ matters.
99
+
100
+ ### Strategy B — even stride (representative across the window)
101
+
102
+ When you need the whole window represented (e.g. auditing a long-lived module's
103
+ history, not just its recent activity), sample every k-th commit:
104
+
105
+ ```bash
106
+ K=$(( (C + 1999) / 2000 )) # ceil(C / 2000) → ~2000 samples
107
+ git rev-list --since="$WINDOW" HEAD \
108
+ | awk -v k="$K" 'NR % k == 1' \
109
+ | while IFS= read -r sha; do
110
+ git show --no-renames --name-only --pretty=format: "$sha"
111
+ done \
112
+ | grep -v '^$' \
113
+ | grep -Ev '(^|/)(node_modules|dist|build|target|vendor|\.min\.|package-lock\.json|Cargo\.lock|pnpm-lock\.yaml|yarn\.lock)(/|$)' \
114
+ | sort | uniq -c | sort -rn \
115
+ | head -40
116
+ ```
117
+
118
+ `awk 'NR % k == 1'` takes a deterministic evenly-spaced sample (~2000 SHAs). More
119
+ processes than Strategy A (one `git show` per sampled commit) — heavier, so reserve
120
+ it for when tail coverage is worth the cost. Note the sample is of *commits*, so
121
+ counts are proportional, not absolute; rank is what you use, not the raw count.
122
+
123
+ ## Directory rollup (wide repos)
124
+
125
+ When file-level churn fragments (a monorepo where every top file changed once),
126
+ roll up to a directory prefix to find active *areas*:
127
+
128
+ ```bash
129
+ git log --since="$WINDOW" --no-renames --name-only --pretty=format: --max-count=2000 -- . \
130
+ | grep -v '^$' \
131
+ | grep -Ev '(^|/)(node_modules|dist|build|target|vendor)(/|$)' \
132
+ | awk -F/ 'NF>=2 {print $1"/"$2} NF==1 {print $1}' \
133
+ | sort | uniq -c | sort -rn \
134
+ | head -40
135
+ ```
136
+
137
+ `awk -F/ '{print $1"/"$2}'` collapses each path to its first two segments (tune to
138
+ 1 or 3 per repo shape). The ranked areas then seed phase-2 hotspots/blast-radius
139
+ at the subsystem level. You can run file-level and rollup both and present each.
140
+
141
+ ## Cross-platform counting fallback (Windows / no coreutils)
142
+
143
+ `sort | uniq -c | sort -rn` is fine on macOS/Linux/WSL/Git-Bash but not native
144
+ PowerShell. `git log` itself is cross-platform; only the counting pipe isn't.
145
+ Feed git's output to a stdlib Python counter (per the repo's cross-platform rule):
146
+
147
+ Save the counter below as `churn_count.py`, then pipe git's output through it —
148
+ NOT `python3 -` (in a pipe, stdin is git's output, so `-` would try to run that
149
+ output as the program):
150
+
151
+ ```bash
152
+ git log --since="12.months" --no-renames --name-only --pretty=format: --max-count=2000 -- . \
153
+ | python3 churn_count.py 40 2>/dev/null \
154
+ || git log --since="12.months" --no-renames --name-only --pretty=format: --max-count=2000 -- . | python churn_count.py 40
155
+ ```
156
+
157
+ with this counter saved as `churn_count.py`:
158
+
159
+ ```python
160
+ import sys, collections, re
161
+ n = int(sys.argv[1]) if len(sys.argv) > 1 else 40
162
+ noise = re.compile(r'(^|/)(node_modules|dist|build|target|vendor|\.min\.|'
163
+ r'package-lock\.json|Cargo\.lock|pnpm-lock\.yaml|yarn\.lock)(/|$)')
164
+ counts = collections.Counter()
165
+ for line in sys.stdin:
166
+ p = line.strip()
167
+ if p and not noise.search(p):
168
+ counts[p] += 1
169
+ for path, c in counts.most_common(n):
170
+ sys.stdout.write("%6d %s\n" % (c, path))
171
+ ```
172
+
173
+ Same top-N cap, same noise filter, no coreutils dependency. The `--max-count` bound
174
+ still applies — Python counting an unbounded history would still be unbounded work.
175
+
176
+ ## What phase 1 hands off
177
+
178
+ A ranked list of ≤N rows: `<count> <path>` (or `<count> <dir>/`). Carry it into
179
+ phase 2 — for each of the top paths, ask `wicked-garden-search` `blast-radius
180
+ <path>` and consult `hotspots` — and into the § Cross-reference 2×2. Do not treat
181
+ a high churn count as importance on its own: a generated file that changes every
182
+ commit tops this list and means nothing until the structural signal confirms (or
183
+ denies) that anything depends on it.
184
+
185
+ ## Pitfalls
186
+
187
+ - **Streaming the full log.** The one thing this method exists to prevent. Always
188
+ `--max-count`/sample above the threshold and always `head -N`.
189
+ - **`--follow` on a whole-tree scan.** It's per-path; it silently does the wrong
190
+ thing here. Leave renames alone (`--no-renames`).
191
+ - **Counting merge commits' squashed diffs twice.** Add `--no-merges` if the repo
192
+ merges heavily and you want first-parent-ish churn; state it if you do.
193
+ - **Trusting counts across strategies.** Strategy B counts are sample-proportional.
194
+ Compare *ranks*, never raw counts, between a full-scan and a sampled run.
195
+ - **Forgetting the window is a knob.** 12 months is the default signal for "active
196
+ now"; widen it to learn a mature system's long-lived churn, narrow it to learn
197
+ what a team touched this quarter. Always report the window you used.
@@ -21,7 +21,8 @@ or `py -3` based on what's available and handles macOS, Linux, and Windows
21
21
  in one call. Bare `python3` is not available on Windows.
22
22
 
23
23
  ```bash
24
- sh "${CLAUDE_PLUGIN_ROOT}/scripts/_python.sh" "${CLAUDE_PLUGIN_ROOT}/scripts/some/script.py"
24
+ # "path/to/your_script.py" is a placeholder for the script to run
25
+ sh "${CLAUDE_PLUGIN_ROOT}/scripts/_python.sh" "path/to/your_script.py"
25
26
  ```
26
27
 
27
28
  The detection logic below is reference material for skills that need a
@@ -47,7 +47,7 @@ graph via the drop-in TOML rules in
47
47
  | `narrate` | codebase orientation / architecture walkthrough | [codebase-narrator/SKILL.md](codebase-narrator/SKILL.md) |
48
48
  | `answer` | cited answer from the estate knowledge/memory stores | [refs/answer.md](refs/answer.md) |
49
49
 
50
- Doctrine / which-rules-apply: the **architecture wiki** is in the same stores — `knowledge.recall {"scope_prefix": "wiki:"}` + estate MCP `rules.recall` (cited); lifecycle: wicked-core `crates/wicked-governance/WIKI.md`.
50
+ Doctrine / which-rules-apply: **Steering** (the governance rules, 7 steering types) is in the same stores — `knowledge.recall {"scope_prefix": "wiki:"}` (historical prefix) + estate MCP `rules.recall` (cited, read-only); management: wicked-core `crates/wicked-governance/STEERING.md`.
51
51
 
52
52
  ## Index / freshness (shared by every action)
53
53