bmad-module-skill-forge 0.7.3 → 0.8.0

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.
Files changed (24) hide show
  1. package/package.json +1 -1
  2. package/src/agents/forger.agent.yaml +1 -1
  3. package/src/knowledge/ccc-bridge.md +34 -2
  4. package/src/knowledge/tool-resolution.md +3 -3
  5. package/src/module.yaml +5 -3
  6. package/src/workflows/analyze-source/data/skill-brief-schema.md +11 -2
  7. package/src/workflows/analyze-source/data/unit-detection-heuristics.md +9 -0
  8. package/src/workflows/analyze-source/steps-c/step-05-recommend.md +1 -1
  9. package/src/workflows/analyze-source/steps-c/step-06-generate-briefs.md +2 -1
  10. package/src/workflows/brief-skill/data/scope-templates.md +41 -0
  11. package/src/workflows/brief-skill/data/skill-brief-schema.md +11 -3
  12. package/src/workflows/brief-skill/steps-c/step-02-analyze-target.md +1 -1
  13. package/src/workflows/brief-skill/steps-c/step-03-scope-definition.md +6 -6
  14. package/src/workflows/create-skill/data/compile-assembly-rules.md +108 -0
  15. package/src/workflows/create-skill/data/extraction-patterns.md +94 -3
  16. package/src/workflows/create-skill/data/skill-sections.md +76 -0
  17. package/src/workflows/create-skill/data/source-resolution-protocols.md +21 -9
  18. package/src/workflows/create-skill/steps-c/step-02b-ccc-discover.md +6 -4
  19. package/src/workflows/create-skill/steps-c/step-03-extract.md +48 -12
  20. package/src/workflows/create-skill/steps-c/step-03d-component-extraction.md +292 -0
  21. package/src/workflows/create-skill/steps-c/step-05-compile.md +9 -0
  22. package/src/workflows/setup-forge/steps-c/step-01b-ccc-index.md +65 -13
  23. package/src/workflows/setup-forge/steps-c/step-02-write-config.md +5 -3
  24. package/src/workflows/update-skill/steps-c/step-03-re-extract.md +2 -0
@@ -59,6 +59,82 @@ SKILL.md uses a two-tier structure to ensure actionable content survives `split-
59
59
  - **Section 4b (Migration & Deprecation Warnings)** is conditional: only emitted for Deep tier when T2-future annotations exist. Quick/Forge/Forge+ tiers and Deep tiers without T2-future annotations omit it entirely (no empty section). Parsers and validators must treat this section as optional.
60
60
  - **Section 7b (Scripts & Assets)** is conditional: only emitted when `scripts_inventory` or `assets_inventory` is non-empty. Omitted entirely when no scripts or assets are detected. Parsers and validators must treat this section as optional.
61
61
 
62
+ ### Component Library Section Overrides
63
+
64
+ When `scope.type: "component-library"`, these section formats replace their standard counterparts. All other sections (Overview, Common Workflows, Architecture, CLI, Manual Sections, etc.) use the standard format.
65
+
66
+ #### Section 4 — Component Catalog (replaces Key API Summary)
67
+
68
+ ```markdown
69
+ ## Component Catalog
70
+
71
+ | Category | Count | Key Components |
72
+ |----------|-------|---------------|
73
+ | {category} | {count} | {ComponentA}, {ComponentB}, {ComponentC}, ... |
74
+
75
+ **Design system variants:** {primary} (primary), {variant2}, {variant3}
76
+ **Total components:** {unique_count} | **With {variant1}:** {count1} | **With {variant2}:** {count2}
77
+ ```
78
+
79
+ - Source: `component_catalog[]` from step-03d extraction
80
+ - Group by `category` field from registry
81
+ - Show top 3-5 component names per category
82
+ - Cite registry file: `[SRC:{registry_file}:L1]`
83
+ - Budget: ~20 lines (same as standard Section 4)
84
+
85
+ #### Section 5 — Key Props (replaces Key Types)
86
+
87
+ ```markdown
88
+ ## Key Types
89
+
90
+ ### {ComponentName}Props
91
+
92
+ | Prop | Type | Default | Required |
93
+ |------|------|---------|----------|
94
+ | {propName} | {type} | {default or —} | {yes/no} |
95
+
96
+ {Repeat for top 5 Props interfaces}
97
+ ```
98
+
99
+ - Show only the 5 most-used Props interfaces (by component count or documentation prominence)
100
+ - Full Props details for all components go in Tier 2 reference
101
+ - Budget: ~20 lines (same as standard Section 5)
102
+
103
+ #### Tier 2 — Props Reference (replaces Full API Reference)
104
+
105
+ ```markdown
106
+ ## Full API Reference
107
+
108
+ ### {ComponentName}
109
+
110
+ **Install:** `npx {cli} add {component-id}`
111
+ **Available in:** {variant list}
112
+ **Props:** `{ComponentName}Props`
113
+
114
+ | Prop | Type | Default | Description |
115
+ |------|------|---------|-------------|
116
+ | {prop} | {type} | {default} | {description from JSDoc or —} |
117
+
118
+ **Provenance:** `[AST:{file}:L{line}]`
119
+ ```
120
+
121
+ - Organize by component, not by function
122
+ - Each component shows: install command, variant availability, full props table
123
+ - Include JSDoc descriptions for props when available
124
+ - Standard provenance citations apply
125
+
126
+ #### context-snippet.md — Component Library Format
127
+
128
+ ```markdown
129
+ [{name} v{version}]|root: skills/{name}/
130
+ |IMPORTANT: {name} v{version} — read SKILL.md before writing {name} code. Do NOT rely on training data.
131
+ |install: npx {cli} add <component-id>
132
+ |catalog:{SKILL.md#component-catalog} — {N} components: {category(count), ...}
133
+ |variants: {variant list} — {provider wrapping note if applicable}
134
+ |key-props:{SKILL.md#key-types} — {top props interfaces with key fields}
135
+ |gotchas: {detected gotchas}
136
+ ```
137
+
62
138
  ### Provenance Citation Format
63
139
 
64
140
  | Tier | Format | Example |
@@ -68,8 +68,8 @@ If `source_repo` is a remote URL (GitHub URL or owner/repo format) AND tier is F
68
68
 
69
69
  When `exclude_patterns` exist, use `--no-cone` mode to pass both include and exclude patterns directly as gitignore-style rules:
70
70
 
71
- 1. Convert `include_patterns` to gitignore-style patterns. If a pattern contains no glob characters (`*`, `?`, `[`) and does not end with `/`, append `/**` to match directory contents recursively (e.g., `cognee` → `cognee/**`; `cognee/**` → kept as-is).
72
- 2. Convert `exclude_patterns` to negation patterns by prepending `!`. Apply the same anchoring rule (e.g., `cognee/tests` → `!cognee/tests/**`; `cognee/tests/**` → `!cognee/tests/**`; `**/test_*` → `!**/test_*`).
71
+ 1. Convert `include_patterns` to gitignore-style patterns. For patterns without glob characters (`*`, `?`, `[`) that do not end with `/`, apply the **file-detection heuristic**: if the last path segment contains a `.` (file extension), it is an **individual file** — prepend `/` and keep as-is (e.g., `packages/registry/registry.json` → `/packages/registry/registry.json`). If the last path segment has no extension, it is a **bare directory name** append `/**` (e.g., `cognee` → `cognee/**`). Patterns that already contain glob characters are kept as-is (e.g., `cognee/**` → kept as-is).
72
+ 2. Convert `exclude_patterns` to negation patterns by prepending `!`. Apply the same file-detection heuristic: individual files (last segment has `.` extension) get `!/` prefix only (e.g., `src/internal/config.json` → `!/src/internal/config.json`); bare directory names get `/**` appended (e.g., `cognee/tests` → `!cognee/tests/**`). Patterns with globs are kept as-is with `!` prefix (e.g., `cognee/tests/**` → `!cognee/tests/**`; `**/test_*` → `!**/test_*`).
73
73
  3. **CRITICAL:** List all include patterns BEFORE negated exclude patterns — git processes patterns in order and a negation can only suppress a prior inclusion.
74
74
  4. Pass to sparse-checkout — include patterns first, then negated exclude patterns:
75
75
 
@@ -79,15 +79,17 @@ If `source_repo` is a remote URL (GitHub URL or owner/repo format) AND tier is F
79
79
 
80
80
  Example transformation:
81
81
  ```
82
- Brief include_patterns: Brief exclude_patterns:
83
- cognee/** cognee/tests/**
84
- cognee/alembic/**
85
- **/test_*
82
+ Brief include_patterns: Brief exclude_patterns:
83
+ cognee/** cognee/tests/**
84
+ packages/registry/registry.json cognee/alembic/**
85
+ **/test_*
86
86
 
87
87
  sparse-checkout args (--no-cone):
88
- 'cognee/**' '!cognee/tests/**' '!cognee/alembic/**' '!**/test_*'
88
+ 'cognee/**' '/packages/registry/registry.json' '!cognee/tests/**' '!cognee/alembic/**' '!**/test_*'
89
89
  ```
90
90
 
91
+ Note: `registry.json` is an individual file (has `.json` extension), so it gets `/` prefix instead of `/**` suffix.
92
+
91
93
  **Note:** `--no-cone` mode is slower than cone mode for very large repositories but eliminates downloading excluded blobs entirely.
92
94
 
93
95
  **Always-included root files:**
@@ -112,7 +114,13 @@ If `source_repo` is a remote URL (GitHub URL or owner/repo format) AND tier is F
112
114
 
113
115
  Proceed with Quick tier extraction strategy below. Note the degradation reason in context for the evidence report.
114
116
 
115
- **Ephemeral clone cleanup:** After extraction is complete for all files in scope (whether successful or partially failed), before presenting the Gate 2 summary (Section 6), if `ephemeral_clone_active`, delete the `{temp_path}` directory. Log: "Ephemeral source clone cleaned up." This ensures cleanup runs even if some extractions failed, as long as the step itself is still executing. **If any error halts the extraction step before Gate 2 is reached**, cleanup must still occur: attempt to delete `{temp_path}` before halting. Log the cleanup attempt regardless of success.
117
+ **Ephemeral clone cleanup:** After extraction is complete for all files in scope (whether successful or partially failed), before presenting the Gate 2 summary (Section 6), if `ephemeral_clone_active`:
118
+
119
+ 1. **Reset working directory first:** Before deleting the clone, ensure the shell working directory is not inside the temp path. Run `cd {project-root}` using the **absolute path** captured at workflow start (not a relative path). This prevents `getcwd` errors when the temp directory is deleted while it is the shell's cwd — which happens if `cd {temp_path}` was used during CCC init or extraction operations.
120
+ 2. **Delete the clone:** `rm -rf {temp_path}`
121
+ 3. **Log:** "Ephemeral source clone cleaned up."
122
+
123
+ This ensures cleanup runs even if some extractions failed, as long as the step itself is still executing. **If any error halts the extraction step before Gate 2 is reached**, cleanup must still occur: reset cwd to `{project-root}` and attempt to delete `{temp_path}` before halting. Log the cleanup attempt regardless of success.
116
124
 
117
125
  ---
118
126
 
@@ -137,7 +145,11 @@ Store the result as `source_commit` in context. If capture fails (not a git repo
137
145
  After the source path is accessible (local path from step-01, or ephemeral clone from above), check whether the source contains a version identifier and reconcile it with `brief.version`. Look for the first matching version file in the resolved source path:
138
146
 
139
147
  - Python: `pyproject.toml` (`[project] version`), `setup.py` (`version=`), `__version__` in `__init__.py`
140
- - JavaScript/TypeScript: `package.json` (`"version"`)
148
+ - JavaScript/TypeScript: `package.json` (`"version"`). **Monorepo resolution:** When multiple `package.json` files exist (workspace root + packages), resolve version using this priority:
149
+ 1. Package whose `name` field matches `brief.name` (e.g., the skill's target library name)
150
+ 2. Package with a `bin` field (CLI entry point — represents the published version)
151
+ 3. Root workspace `package.json` version (if present)
152
+ 4. Fall back to `brief.version` if no version found. For monorepos using workspace protocols (pnpm, yarn, npm workspaces), the root `package.json` often has no `version` field — this is expected, not an error.
141
153
  - Rust: `Cargo.toml` (`[package] version`)
142
154
  - Go: `go.mod` (module version if tagged)
143
155
 
@@ -65,9 +65,11 @@ Set `{ccc_discovery: []}` in context. Auto-proceed silently. Display no message.
65
65
 
66
66
  Check `tools.ccc` from forge-tier.yaml. If `tools.ccc` is false, set `{ccc_discovery: []}` in context and auto-proceed to section 5.
67
67
 
68
- If `tools.ccc` is true, continue to section 2.
68
+ If `tools.ccc` is true, check the remote source guard **before** proceeding to section 2:
69
69
 
70
- **Remote source guard:** If `source_root` is a remote URL (GitHub repository not yet cloned locally — ephemeral clone happens in step-03), CCC cannot operate. Set `{ccc_discovery: []}` and display: "CCC discovery skipped — remote source not yet available locally. CCC requires a local source index." Auto-proceed to the step completion / next step section.
70
+ **Remote source guard:** If `source_root` is a remote URL (GitHub repository not yet cloned locally — ephemeral clone happens in step-03), CCC cannot operate yet. Set `{ccc_discovery: []}` and display: "CCC discovery deferred — remote source will be indexed after ephemeral clone in step-03." Auto-proceed to section 5 (step completion). Step-03 will detect the deferred scenario and run CCC discovery on the ephemeral clone before AST extraction begins.
71
+
72
+ If `source_root` is a local path, continue to section 2.
71
73
 
72
74
  ### 2. Check CCC Index State
73
75
 
@@ -77,7 +79,7 @@ Read `ccc_index` from forge-tier.yaml:
77
79
  - If `ccc_index.status` is `"stale"`: display brief note — "CCC index is stale — discovery results may miss recent changes." Continue to section 3.
78
80
  - If `ccc_index.status` is `"none"` or `"failed"`: attempt lazy indexing via `ccc_bridge.ensure_index(source_root)`. If indexing succeeds, continue to section 3. If indexing fails, set `{ccc_discovery: []}` and auto-proceed to section 5.
79
81
 
80
- **Tool resolution for ccc_bridge.ensure_index:** Use `/ccc` skill indexing (Claude Code), ccc MCP server (Cursor), or `ccc init` + `ccc index {source_root}` (CLI). See [knowledge/tool-resolution.md](../../../knowledge/tool-resolution.md).
82
+ **Tool resolution for ccc_bridge.ensure_index:** Use `/ccc` skill indexing (Claude Code), ccc MCP server (Cursor), or `cd {source_root} && ccc init` + `ccc index` (CLI). Note: `ccc init` takes no positional arguments — it initializes the index for the current working directory. See [knowledge/tool-resolution.md](../../../knowledge/tool-resolution.md).
81
83
 
82
84
  ### 3. Construct Semantic Query
83
85
 
@@ -95,7 +97,7 @@ Where:
95
97
 
96
98
  Run `ccc_bridge.search(query, source_root, top_k=20)`:
97
99
 
98
- **Tool resolution for ccc_bridge.search:** Use `/ccc` skill search (Claude Code), ccc MCP server (Cursor), or `ccc search "{query}" --path {source_root} --top 20` (CLI). See [knowledge/tool-resolution.md](../../../knowledge/tool-resolution.md).
100
+ **Tool resolution for ccc_bridge.search:** Use `/ccc` skill search (Claude Code), ccc MCP server (Cursor), or `cd {source_root} && ccc search --limit 20 "{query}"` (CLI). Note: `ccc search` operates on the index in the current working directory — there is no flag to specify a project directory. See [knowledge/tool-resolution.md](../../../knowledge/tool-resolution.md).
99
101
 
100
102
  **If search succeeds:**
101
103
 
@@ -2,6 +2,7 @@
2
2
  name: 'step-03-extract'
3
3
  description: 'Tier-dependent source code extraction — AST or source reading for exports, signatures, and types'
4
4
  nextStepFile: './step-03b-fetch-temporal.md'
5
+ componentExtractionStepFile: './step-03d-component-extraction.md'
5
6
  extractionPatternsData: '../data/extraction-patterns.md'
6
7
  extractionPatternsTracingData: '../data/extraction-patterns-tracing.md'
7
8
  tierDegradationRulesData: '../data/tier-degradation-rules.md'
@@ -49,7 +50,7 @@ To extract all public exports, function signatures, type definitions, and co-imp
49
50
  - Available: brief_data, tier, source_root, file_tree from step-01; ecosystem check outcome from step-02 (proceed/halt decision — no named variable stored)
50
51
  - Focus: Source code extraction and inventory building
51
52
  - Limits: Do NOT compile, assemble, or write any output
52
- - Dependencies: Source code must be accessible (resolved in step-01)
53
+ - Dependencies: Source code must be accessible (local repos resolved in step-01; remote repos cloned in section 2a)
53
54
 
54
55
  ## MANDATORY SEQUENCE
55
56
 
@@ -69,6 +70,50 @@ From the brief, apply scope and pattern filters:
69
70
 
70
71
  Build the filtered file list from the source tree resolved in step-01. Record the result: "**Filtered file count: {N} files in scope**" — this count is the input to the AST Extraction Protocol decision tree in the extraction patterns data file.
71
72
 
73
+ ### 2a. Resolve Source Access
74
+
75
+ Load `{sourceResolutionData}` completely. Follow the **Remote Source Resolution** protocol for Forge/Deep tiers (ephemeral clone, sparse-checkout, cleanup), the **Source Commit Capture** protocol for all tiers, and the **Version Reconciliation** protocol for all tiers. This ensures source code is accessible regardless of which extraction path is taken below (standard, component-library, or docs-only).
76
+
77
+ **Deferred CCC Discovery (Forge+ and Deep — remote sources only):**
78
+
79
+ If ALL of these conditions are true:
80
+ - `tools.ccc` is true in forge-tier.yaml
81
+ - `{ccc_discovery}` is empty (step-02b deferred because source was remote)
82
+ - `ephemeral_clone_active` is true (clone succeeded in source resolution above)
83
+ - Tier is Forge+ or Deep
84
+
85
+ Then run CCC indexing and discovery on the ephemeral clone:
86
+
87
+ 1. **Index the clone:** Run `cd {temp_path} && ccc init` then `ccc index` with an extended timeout or in background mode — `ccc init` takes no positional arguments and initializes the index for the current working directory. Indexing can take several minutes on large codebases (1000+ files). Use `ccc status` to verify completion — check that `Chunks` and `Files` counts are non-zero. If init fails or indexing fails, set `{ccc_discovery: []}` and continue — this is not an error.
88
+
89
+ 2. **Construct semantic query:** Build from brief data: `"{brief.name} {brief.scope}"`. Truncate to 80 characters — keep the full skill name and trim `brief.scope` from the end. If `brief.scope` is very short (< 10 chars), append terms from `brief.description` to fill the remaining space.
90
+
91
+ 3. **Execute search:** Run `ccc_bridge.search(query, temp_path, top_k=20)`:
92
+ - **Tool resolution:** Use `/ccc` skill search (Claude Code), ccc MCP server (Cursor), or `cd {temp_path} && ccc search --limit 20 "{query}"` (CLI). Note: `ccc search` operates on the index in the current working directory. See [knowledge/tool-resolution.md](../../../knowledge/tool-resolution.md).
93
+
94
+ 4. **Store results:** If search succeeds, store as `{ccc_discovery: [{file, score, snippet}]}`. Display: "**CCC semantic discovery (post-clone): {N} relevant regions identified across {M} unique files.**"
95
+
96
+ 5. **On failure:** Set `{ccc_discovery: []}`. Display: "CCC post-clone discovery unavailable — proceeding with standard extraction." Do NOT halt.
97
+
98
+ **CCC Discovery Integration (Forge+ and Deep with ccc only):**
99
+
100
+ If `{ccc_discovery}` is in context and non-empty (populated by step-02b or deferred discovery above):
101
+ - Sort the filtered file list by CCC relevance score: files appearing in `{ccc_discovery}` results move to the front of the extraction queue, sorted by their relevance score descending
102
+ - Files NOT in CCC results remain in the queue after ranked files — they are not excluded, only deprioritized
103
+ - Display: "**CCC discovery: {N} files pre-ranked by semantic relevance** — extraction will prioritize these first."
104
+
105
+ If `{ccc_discovery}` is empty or not in context: proceed with existing file ordering (no change to current behavior).
106
+
107
+ ### 2b. Component Library Delegation
108
+
109
+ **If `scope.type: "component-library"` in the brief:**
110
+
111
+ "**Component library detected.** Delegating to specialized extraction strategy for registry-first, props-focused extraction."
112
+
113
+ Load and execute `{componentExtractionStepFile}` completely. When that step completes, it returns control here. Resume at section 5 (Build Extraction Inventory) with the enriched extraction data and `component_catalog[]` from the component extraction step.
114
+
115
+ **Otherwise:** Continue with standard extraction below.
116
+
72
117
  ### 3. Check for Docs-Only Mode
73
118
 
74
119
  **If `source_type: "docs-only"` in the brief data:**
@@ -81,7 +126,7 @@ Build an empty extraction inventory with zero exports. Set `extraction_mode: "do
81
126
 
82
127
  ### 4. Execute Tier-Dependent Extraction
83
128
 
84
- Load `{sourceResolutionData}` completely. Follow the **Remote Source Resolution** protocol for Forge/Deep tiers (ephemeral clone, sparse-checkout, cleanup) and the **Version Reconciliation** protocol for all tiers. Apply the protocols before proceeding with the tier-specific extraction strategy below.
129
+ Source resolution, version reconciliation, and CCC discovery were completed in section 2a. Proceed with the tier-specific extraction strategy below.
85
130
 
86
131
  **Quick Tier (No AST tools):**
87
132
 
@@ -96,16 +141,7 @@ Load `{sourceResolutionData}` completely. Follow the **Remote Source Resolution*
96
141
 
97
142
  **Forge/Forge+/Deep Tier (AST available):**
98
143
 
99
- **CCC Discovery Integration (Forge+ and Deep with ccc only):**
100
-
101
- If `{ccc_discovery}` is in context and non-empty (populated by step-02b):
102
- - Sort the filtered file list by CCC relevance score: files appearing in `{ccc_discovery}` results move to the front of the extraction queue, sorted by their relevance score descending
103
- - Files NOT in CCC results remain in the queue after ranked files — they are not excluded, only deprioritized
104
- - Display: "**CCC discovery: {N} files pre-ranked by semantic relevance** — extraction will prioritize these first."
105
-
106
- If `{ccc_discovery}` is empty or not in context: proceed with existing file ordering (no change to current behavior).
107
-
108
- ⚠️ **CRITICAL:** Before executing AST extraction, load the **AST Extraction Protocol** section from `{extractionPatternsData}`. Follow the decision tree based on the file count from step-01's file tree. This determines whether to use the MCP tool, scoped YAML rules, or CLI streaming. Never use `ast-grep --json` (without `=stream`) — it loads the entire result set into memory and will fail on large codebases.
144
+ ⚠️ **CRITICAL:** Before executing AST extraction, load the **AST Extraction Protocol** section from `{extractionPatternsData}`. Follow the decision tree based on the file count from step-01's file tree. This determines whether to use the MCP tool, scoped YAML rules, or CLI streaming. Never use `ast-grep --json` (without `=stream`) — it loads the entire result set into memory and will fail on large codebases. Always use the explicit `run` subcommand with streaming: `ast-grep run -p '{pattern}' --json=stream`.
109
145
 
110
146
  1. Detect language from brief or file extensions
111
147
  2. Follow the AST Extraction Protocol decision tree from `{extractionPatternsData}`:
@@ -0,0 +1,292 @@
1
+ ---
2
+ name: 'step-03d-component-extraction'
3
+ description: 'Component-library extraction strategy — registry detection, props-first extraction, variant consolidation, demo exclusion'
4
+ returnToStep: './step-03-extract.md'
5
+ extractionPatternsData: '../data/extraction-patterns.md'
6
+ ---
7
+
8
+ # Step 3d: Component Library Extraction
9
+
10
+ ## STEP GOAL:
11
+
12
+ When `scope.type: "component-library"`, perform specialized extraction that treats the component registry as the primary API surface and props interfaces as API contracts. This step replaces the standard AST extraction flow (step-03 sections 4-4c) and returns control to step-03 section 5 (Build Extraction Inventory).
13
+
14
+ ## MANDATORY EXECUTION RULES (READ FIRST):
15
+
16
+ ### Universal Rules:
17
+
18
+ - 📖 CRITICAL: Read the complete step file before taking any action
19
+ - 🎯 ALWAYS follow the exact instructions in the step file
20
+ - ⚙️ TOOL/SUBPROCESS FALLBACK: If any instruction references a tool you do not have access to, you MUST still achieve the outcome in your main context thread
21
+ - ✅ YOU MUST ALWAYS SPEAK OUTPUT in your Agent communication style with the config `{communication_language}`
22
+
23
+ ### Role Reinforcement:
24
+
25
+ - ✅ You are a skill compilation engine performing component-library-specialized extraction
26
+ - ✅ Zero hallucination tolerance — every extracted item must trace to source code
27
+ - ✅ Component registry is the source of truth for the API surface
28
+ - ✅ Props interfaces are the API contracts, not function signatures
29
+
30
+ ### Step-Specific Rules:
31
+
32
+ - 🎯 Focus ONLY on extracting component catalog, props interfaces, and shared types
33
+ - 🚫 FORBIDDEN to compile SKILL.md content — that is step-05
34
+ - 🚫 FORBIDDEN to write any output files — extraction stays in context
35
+ - 🚫 FORBIDDEN to include content that cannot be cited to a source location
36
+ - ⚒️ Every extracted item MUST have a provenance citation: `[AST:{file}:L{line}]` or `[SRC:{file}:L{line}]`
37
+
38
+ ## CONTEXT BOUNDARIES:
39
+
40
+ - Available: brief_data (including `scope.registry_path`, `scope.ui_variants`, `scope.demo_patterns` if present), tier, source_root (may be `temp_path` from ephemeral clone for remote repos — use the working source path resolved in step-03 section 2a), filtered file list from step-03 section 2, CCC discovery results (if available from step-03 section 2a)
41
+ - Focus: Component-specific extraction and inventory building
42
+ - Limits: Do NOT compile, assemble, or write output
43
+ - Dependencies: Source code accessible (resolved in step-03 section 2a — ephemeral clone for remote repos), scope filters already applied
44
+
45
+ ## MANDATORY SEQUENCE
46
+
47
+ **CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise.
48
+
49
+ ### Phase 1: Demo/Example Exclusion
50
+
51
+ Before extraction, identify and exclude demo/example files to avoid inflating export counts.
52
+
53
+ **If `scope.demo_patterns` is specified in the brief:** Use those patterns directly.
54
+
55
+ **Otherwise, auto-detect:**
56
+
57
+ 1. Scan the filtered file list for directories matching: `demo/`, `demos/`, `stories/`, `examples/`, `__stories__/`, `storybook/`
58
+ 2. Scan for file patterns matching: `*.stories.*`, `*.story.*`, `*.example.*`, `*.demo.*`
59
+ 3. Count matches per pattern category
60
+
61
+ **User confirmation required:**
62
+
63
+ "**Auto-detected {N} demo/example files** in {M} directories matching these patterns:
64
+ {list detected patterns with counts}
65
+
66
+ Confirm exclusion? [Y/n] Or adjust patterns:"
67
+
68
+ Wait for user response. Apply confirmed patterns to the exclude list. Record `demo_files_excluded: {count}` in context.
69
+
70
+ Update the filtered file list by removing excluded demo files before proceeding.
71
+
72
+ ### Phase 2: Registry Detection
73
+
74
+ The component registry is the primary API surface for component libraries.
75
+
76
+ **If `scope.registry_path` is specified in the brief:**
77
+
78
+ Read the specified file directly. Parse it as described below.
79
+
80
+ **Otherwise, auto-detect:**
81
+
82
+ 1. Search the filtered file list for files matching these patterns (in priority order):
83
+ - Files named `registry.ts`, `registry.tsx`, `registry.js` in any directory
84
+ - Files named `components.ts`, `components.tsx` in `registry/`, `catalog/`, or `components/` directories
85
+ - Files named `index.ts`, `index.tsx` in `registry/` or `catalog/` directories
86
+
87
+ 2. For each candidate, read the file and look for:
88
+ - Arrays of objects with fields like `id`, `name`, `component`, `category`
89
+ - Type annotations containing `Component[]` or similar array types
90
+ - 10+ entries to qualify as a registry (reject small arrays)
91
+
92
+ 3. **Confidence scoring** for each candidate:
93
+ - +3 points: Contains `id` field per entry
94
+ - +2 points: Contains `name` or `component` field per entry
95
+ - +2 points: Contains `category` or `tags` field per entry
96
+ - +1 point: Located in a `registry/` or `catalog/` directory
97
+ - +1 point: Has 20+ entries
98
+ - Minimum threshold: 5 points to qualify
99
+
100
+ 4. **User confirmation required:**
101
+
102
+ "**Registry candidate detected** at `{path}` (confidence: {score}/9, {count} entries).
103
+
104
+ Sample entries:
105
+ {show 3-5 sample entries with id, name, category}
106
+
107
+ Is this the component registry? [Y/n] Or provide the correct path:"
108
+
109
+ Wait for user response.
110
+
111
+ **If no registry found and no `registry_path` in brief:**
112
+
113
+ "**No component registry detected.** Component-library extraction works best with a registry file. Options:
114
+ - **[P]** Provide the registry file path
115
+ - **[S]** Skip registry — proceed with standard props-first extraction only"
116
+
117
+ Wait for user response.
118
+
119
+ ### Phase 3: Parse Registry
120
+
121
+ If a registry was confirmed, parse it into `component_catalog[]`:
122
+
123
+ **Per-component entry:**
124
+
125
+ - `id` — registry key (used for CLI `add` command)
126
+ - `name` — display name (PascalCase)
127
+ - `description` — from registry or empty
128
+ - `category` — from registry field or directory structure
129
+ - `available_in[]` — which design system variants include this component
130
+ - `code_paths[]` — source file path for each variant
131
+ - `tags[]` — from registry or empty
132
+ - Provenance citation: `[SRC:{registry_file}:L{line}]`
133
+
134
+ Display: "**Parsed component catalog: {N} components across {M} categories.**"
135
+
136
+ **If no registry:** Set `component_catalog: []` and proceed to Phase 4.
137
+
138
+ ### Phase 4: Props-First Extraction
139
+
140
+ Extract props interfaces as the primary API contracts, then link to components.
141
+
142
+ **Step 1 — Extract Props interfaces:**
143
+
144
+ Load `{extractionPatternsData}` and use the component-library-specific patterns.
145
+
146
+ Using AST tools (Forge/Deep) or source reading (Quick):
147
+
148
+ ```yaml
149
+ # React/TypeScript props interfaces
150
+ id: react-props-interfaces
151
+ language: typescript
152
+ rule:
153
+ pattern: 'export interface $NAME { $$$ }'
154
+ constraints:
155
+ NAME:
156
+ regex: '.*Props$'
157
+ ```
158
+
159
+ For each `*Props` interface found:
160
+ - Extract all fields with types, optionality, and default values
161
+ - Extract JSDoc descriptions per field (if present)
162
+ - Record: interface name, fields[], source file, line number
163
+ - Provenance: `[AST:{file}:L{line}]` or `[SRC:{file}:L{line}]`
164
+
165
+ **Step 2 — Extract component exports:**
166
+
167
+ ```yaml
168
+ # React component exports (PascalCase)
169
+ id: react-component-exports
170
+ language: tsx # Use 'tsx' for .tsx files, 'typescript' for .ts files
171
+ rule:
172
+ pattern: 'export function $NAME($$$PARAMS)'
173
+ constraints:
174
+ NAME:
175
+ regex: '^[A-Z]'
176
+ ```
177
+
178
+ Also run `export const $NAME` patterns for arrow function components.
179
+
180
+ For each component export: record name, source file, line number. Do NOT document the function signature in detail (it's always `(props: XProps) => JSX.Element`).
181
+
182
+ **Step 3 — Link Props to Components:**
183
+
184
+ Use a 3-level fallback chain:
185
+
186
+ 1. **Naming convention (primary):** Match `FooProps` → `Foo` component by stripping the `Props` suffix
187
+ 2. **File co-location (fallback):** If naming doesn't match, check if a Props interface and a component are defined in the same file
188
+ 3. **Generic parameter (deep fallback):** Look for `ComponentProps<typeof Foo>` or similar generic patterns that reference the component
189
+
190
+ For each linked pair, record the association. For unlinked Props interfaces, include them as standalone type exports.
191
+
192
+ **Step 4 — Extract shared types:**
193
+
194
+ Extract non-Props type exports using standard AST patterns (same as Forge tier):
195
+ - `export type $NAME = $VALUE`
196
+ - `export enum $NAME { $$$ }`
197
+ - `export interface $NAME { $$$ }` (excluding `*Props` already captured)
198
+
199
+ ### Phase 5: Variant Consolidation
200
+
201
+ **Skip this phase if `scope.ui_variants` is not specified and no variant directories detected.**
202
+
203
+ When multiple design system variants exist:
204
+
205
+ 1. **Group components by registry `id`** (NOT by filename — registry is source of truth):
206
+ - For each `id` in `component_catalog[]`, collect all variant paths from `available_in[]` and `code_paths[]`
207
+
208
+ 2. **Select canonical props definition:**
209
+ - Use the primary variant (first in `scope.ui_variants` list) as canonical
210
+ - If primary variant's props are unavailable, use the first available variant
211
+
212
+ 3. **Detect props differences between variants:**
213
+ - For components available in 2+ variants, compare Props interfaces
214
+ - Record any variant-specific props as notes (e.g., "Base UI variant adds `slots` prop")
215
+
216
+ 4. **Deduplicate export counts:**
217
+ - Count unique components (by registry `id`), not total files across variants
218
+ - Record: `components_unique: {N}`, `components_total_with_variants: {M}`
219
+
220
+ Display: "**Variant consolidation: {unique} unique components across {variant_count} variants** ({total} total including variants). Primary variant: {primary_name}."
221
+
222
+ ### Phase 6: Build Component Extraction Results
223
+
224
+ Compile all extracted data into the format expected by step-03 section 5:
225
+
226
+ **Per-export entry (for Props interfaces — primary API):**
227
+
228
+ - Interface name (e.g., `NativeLiquidButtonProps`)
229
+ - Full interface with all fields and types
230
+ - Parameters: each field as name, type, required/optional, default
231
+ - Linked component name (e.g., `NativeLiquidButton`)
232
+ - Source file and line number
233
+ - Provenance citation
234
+ - Confidence tier (T1 or T1-low)
235
+
236
+ **Per-export entry (for component functions):**
237
+
238
+ - Component name
239
+ - Linked Props interface (if found)
240
+ - Source file and line number
241
+ - Provenance citation
242
+ - Confidence tier
243
+
244
+ **Per-export entry (for shared types):**
245
+
246
+ - Same as standard extraction format
247
+
248
+ **Component library aggregate counts:**
249
+
250
+ - `components_registered`: count from registry (or 0)
251
+ - `components_documented`: count of components with linked Props
252
+ - `props_interfaces_extracted`: count of `*Props` interfaces
253
+ - `components_unique`: deduplicated count (after variant consolidation)
254
+ - `demo_files_excluded`: count from Phase 1
255
+ - `design_variants`: map of variant name → component count (if variants exist)
256
+
257
+ **Store `component_catalog[]` in context** — this is consumed by step-05 for the Component Catalog section.
258
+
259
+ Display: "**Component extraction complete.** Returning to main extraction flow."
260
+
261
+ ## RETURN PROTOCOL
262
+
263
+ After Phase 6 completes, return control to step-03 section 5 (Build Extraction Inventory). The extraction results from this step are merged into the standard extraction inventory format. Step-03 continues with its normal Gate 2 summary and menu.
264
+
265
+ Do NOT load `{returnToStep}` — the calling step (step-03) will continue from where it delegated.
266
+
267
+ ---
268
+
269
+ ## SYSTEM SUCCESS/FAILURE METRICS
270
+
271
+ ### SUCCESS:
272
+
273
+ - Demo/example files detected and excluded with user confirmation
274
+ - Registry detected (or user provided path) and parsed into component_catalog
275
+ - Props interfaces extracted as primary API contracts
276
+ - Components linked to Props via 3-level fallback chain
277
+ - Variant consolidation produced deduplicated counts (if applicable)
278
+ - All extracted items have provenance citations
279
+ - Results compatible with step-03 section 5 inventory format
280
+ - component_catalog stored in context for step-05
281
+
282
+ ### FAILURE:
283
+
284
+ - Excluding demo files without user confirmation
285
+ - Accepting a registry candidate without user confirmation
286
+ - Not extracting Props interfaces as primary API surface
287
+ - Documenting component function signatures instead of Props
288
+ - Including hallucinated component data not in source
289
+ - Variant deduplication based on filenames instead of registry IDs
290
+ - Not returning control to step-03 after completion
291
+
292
+ **Master Rule:** Zero hallucination — every extraction must trace to source code. The component registry is the source of truth for the API surface.
@@ -117,6 +117,15 @@ Following the structure from the skill-sections data file:
117
117
  3. `{project-root}/_bmad/skf/VERSION` → read plain text file (single line containing version string, written by the SKF installer)
118
118
  4. `"unknown"` (final fallback — add a warning to the evidence report)
119
119
  Never hardcode the version.
120
+ - Resolve `{ast_grep_version}` using this resolution chain (try each in order, use the first that succeeds):
121
+ 1. `ast-grep --version` → parse version string from output (e.g., `ast-grep 0.41.1` → `"0.41.1"`)
122
+ 2. `mcp__ast-grep__find_code` tool metadata (if version is exposed by the MCP server)
123
+ 3. `"unknown"` (final fallback — add a warning to the evidence report)
124
+ - Resolve `{qmd_version}` using this resolution chain (try each in order, use the first that succeeds):
125
+ 1. `mcp__plugin_qmd-plugin_qmd__status` → parse version from status output
126
+ 2. `pip show qmd-plugin` → read `Version:` field from pip metadata
127
+ 3. `"unknown"` (final fallback — add a warning to the evidence report)
128
+ Note: `qmd --version` and `qmd -V` return usage text instead of a version string — do not use them for version detection.
120
129
  - Store `commit_short` = first 8 characters of `source_commit` (or `"unknown"` if unavailable) for use in step-08 report.
121
130
  - If `scripts_inventory` is non-empty, populate `scripts[]` array and set `stats.scripts_count`. If `assets_inventory` is non-empty, populate `assets[]` array and set `stats.assets_count`. Omit these fields entirely when inventories are empty.
122
131