bmad-module-skill-forge 0.8.0 → 0.8.2
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.
- package/package.json +1 -1
- package/src/knowledge/ccc-bridge.md +2 -1
- package/src/knowledge/tool-resolution.md +1 -0
- package/src/workflows/create-skill/steps-c/step-03-extract.md +13 -5
- package/src/workflows/create-skill/steps-c/step-05-compile.md +3 -3
- package/src/workflows/test-skill/data/scoring-rules.md +12 -0
- package/src/workflows/test-skill/steps-c/step-04b-external-validators.md +11 -4
- package/src/workflows/update-skill/steps-c/step-03-re-extract.md +18 -2
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "bmad-module-skill-forge",
|
|
4
|
-
"version": "0.8.
|
|
4
|
+
"version": "0.8.2",
|
|
5
5
|
"description": "BMAD module — Turn code and docs into instructions AI agents can actually follow. Progressive capability tiers (Quick/Forge/Forge+/Deep).",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"bmad",
|
|
@@ -102,7 +102,7 @@ For remote repository sources (GitHub URLs), CCC cannot operate during step-02b
|
|
|
102
102
|
|
|
103
103
|
1. **step-02b:** Detects remote source, sets `{ccc_discovery: []}`, displays deferred message
|
|
104
104
|
2. **step-03:** After ephemeral clone succeeds, detects the deferred scenario (`tools.ccc == true AND {ccc_discovery} is empty AND ephemeral_clone_active == true AND tier is Forge+/Deep`)
|
|
105
|
-
3. **step-03:** Runs `cd {temp_path} && ccc init`
|
|
105
|
+
3. **step-03:** Runs `cd {temp_path} && ccc init` on the ephemeral clone, then applies brief `exclude_patterns` (if present) to `{temp_path}/.cocoindex_code/settings.yml` before running `ccc index` (extended timeout or background mode, verified via `ccc status`). This prevents CCC from indexing files the brief explicitly excludes, keeping search results focused on in-scope source code and reducing indexing time for large repositories.
|
|
106
106
|
4. **step-03:** Executes CCC search and populates `{ccc_discovery}` before AST extraction begins
|
|
107
107
|
|
|
108
108
|
The ephemeral clone index is not registered in `ccc_index_registry` — the clone is deleted after extraction and the CCC daemon's own GC handles orphaned indexes.
|
|
@@ -131,6 +131,7 @@ To prevent excessive daemon calls, workflow steps cap ccc queries:
|
|
|
131
131
|
- Passing ccc results directly to the extraction inventory — they are candidates, not extractions
|
|
132
132
|
- Listing ccc as "unavailable" in reports for Quick/Forge tiers — ccc is a Forge+ capability, not something Quick/Forge tiers are missing
|
|
133
133
|
- Indexing without configuring SKF exclusions — framework and output directories pollute search results
|
|
134
|
+
- Indexing an ephemeral clone without applying brief `exclude_patterns` — excluded files pollute CCC search results and waste indexing time on large repositories
|
|
134
135
|
- Skipping CCC discovery for remote sources without deferring to step-03 — remote repos deserve the same pre-ranking as local sources
|
|
135
136
|
|
|
136
137
|
## Related Fragments
|
|
@@ -13,6 +13,7 @@ Bridge names (`ast_bridge`, `ccc_bridge`, `qmd_bridge`, `gh_bridge`) and subproc
|
|
|
13
13
|
| `ccc_bridge` | `status()` | `/ccc` skill status | ccc MCP server | `ccc --help` + `ccc doctor` | Unavailable = `tools.ccc: false` |
|
|
14
14
|
| `qmd_bridge` | `search(query)` | `mcp__plugin_qmd-plugin_qmd__search` | qmd MCP server | `qmd search "{query}"` | Skip enrichment |
|
|
15
15
|
| `qmd_bridge` | `vector_search(query)` | `mcp__plugin_qmd-plugin_qmd__vector_search` | qmd MCP server | `qmd vector_search "{query}"` | Use BM25 search only |
|
|
16
|
+
| `qmd_bridge` | `version()` | `qmd --version` → parse `"qmd X.Y.Z"` → `"X.Y.Z"` | qmd MCP server | `qmd --version` | `"unknown"` |
|
|
16
17
|
| `gh_bridge` | `list_tree(owner, repo, branch)` | `gh api repos/{owner}/{repo}/git/trees/{branch}?recursive=1` | gh CLI | `gh api ...` | Direct file listing if local |
|
|
17
18
|
| `gh_bridge` | `read_file(owner, repo, path)` | `gh api repos/{owner}/{repo}/contents/{path}` | gh CLI | `gh api ...` | Direct file read if local |
|
|
18
19
|
|
|
@@ -84,16 +84,24 @@ If ALL of these conditions are true:
|
|
|
84
84
|
|
|
85
85
|
Then run CCC indexing and discovery on the ephemeral clone:
|
|
86
86
|
|
|
87
|
-
1. **
|
|
87
|
+
1. **Initialize index:** Run `cd {temp_path} && ccc init` — `ccc init` takes no positional arguments and initializes the index for the current working directory. If init fails, set `{ccc_discovery: []}` and continue — this is not an error.
|
|
88
88
|
|
|
89
|
-
2. **
|
|
89
|
+
2. **Apply brief exclusions:** If `brief.exclude_patterns` is present and non-empty, apply them to `{temp_path}/.cocoindex_code/settings.yml` before indexing:
|
|
90
|
+
1. Read `{temp_path}/.cocoindex_code/settings.yml` (created by `ccc init`)
|
|
91
|
+
2. For each pattern in `brief.exclude_patterns`: if the pattern is NOT already present in the `exclude_patterns` array, append it
|
|
92
|
+
3. Write the updated `settings.yml` back
|
|
93
|
+
This prevents CCC from indexing excluded files, keeping search results focused on in-scope source code. If `brief.exclude_patterns` is absent or empty, skip this step.
|
|
90
94
|
|
|
91
|
-
3. **
|
|
95
|
+
3. **Index the clone:** Run `cd {temp_path} && ccc index` with an extended timeout or in background mode. 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 indexing fails, set `{ccc_discovery: []}` and continue — this is not an error.
|
|
96
|
+
|
|
97
|
+
4. **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.
|
|
98
|
+
|
|
99
|
+
5. **Execute search:** Run `ccc_bridge.search(query, temp_path, top_k=20)`:
|
|
92
100
|
- **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
101
|
|
|
94
|
-
|
|
102
|
+
6. **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
103
|
|
|
96
|
-
|
|
104
|
+
7. **On failure:** Set `{ccc_discovery: []}`. Display: "CCC post-clone discovery unavailable — proceeding with standard extraction." Do NOT halt.
|
|
97
105
|
|
|
98
106
|
**CCC Discovery Integration (Forge+ and Deep with ccc only):**
|
|
99
107
|
|
|
@@ -122,10 +122,10 @@ Following the structure from the skill-sections data file:
|
|
|
122
122
|
2. `mcp__ast-grep__find_code` tool metadata (if version is exposed by the MCP server)
|
|
123
123
|
3. `"unknown"` (final fallback — add a warning to the evidence report)
|
|
124
124
|
- Resolve `{qmd_version}` using this resolution chain (try each in order, use the first that succeeds):
|
|
125
|
-
1. `
|
|
126
|
-
2. `
|
|
125
|
+
1. `qmd --version` → parse version string from output (e.g., `qmd 2.0.1` → `"2.0.1"`)
|
|
126
|
+
2. `mcp__plugin_qmd-plugin_qmd__status` → parse version if exposed in status output
|
|
127
127
|
3. `"unknown"` (final fallback — add a warning to the evidence report)
|
|
128
|
-
Note:
|
|
128
|
+
Note: QMD is a Bun/Node package (`@tobilu/qmd`). Install via `bun install -g @tobilu/qmd`.
|
|
129
129
|
- Store `commit_short` = first 8 characters of `source_commit` (or `"unknown"` if unavailable) for use in step-08 report.
|
|
130
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.
|
|
131
131
|
|
|
@@ -54,6 +54,18 @@ When `docs_only_mode: true` is set by step-03 (indicating a Quick tier skill whe
|
|
|
54
54
|
|
|
55
55
|
This is functionally identical to Quick tier weight redistribution but with a different coverage denominator (self-consistency instead of source comparison).
|
|
56
56
|
|
|
57
|
+
### State 2 Source Access (Any Tier, Provenance-Map Only)
|
|
58
|
+
|
|
59
|
+
When source is not locally available and analysis resolves to State 2 (provenance-map baseline per source-access-protocol.md):
|
|
60
|
+
|
|
61
|
+
- **Signature Accuracy:** N/A — provenance-map stores parameters as flat string arrays; verification is string comparison only, not semantic AST verification. Type aliases (`str` vs `String`, `list` vs `List[Any]`) cannot be resolved without live source.
|
|
62
|
+
- **Type Coverage:** N/A — cannot verify type completeness without local source access for AST re-parsing.
|
|
63
|
+
- **Weight redistribution:** Same as Quick tier — Signature Accuracy (22%) and Type Coverage (14%) weights redistributed proportionally to remaining active categories (Export Coverage, Coherence, External Validation).
|
|
64
|
+
- **Applies regardless of detected tier** (including Forge, Forge+, Deep) whenever `analysis_confidence` is `provenance-map` and local source is unavailable.
|
|
65
|
+
- **Export Coverage denominator:** Uses the union of provenance-map entry names and metadata.json `exports[]` names (per source-access-protocol.md State 2 rules).
|
|
66
|
+
|
|
67
|
+
Note: When provenance-map entries are predominantly T1 (AST-verified at compilation time), the coverage and name-matching data is already at highest confidence. The N/A categories reflect the inability to re-verify at test time, not low-quality extraction data.
|
|
68
|
+
|
|
57
69
|
### Forge Tier (ast-grep)
|
|
58
70
|
- Export Coverage: AST-backed export comparison
|
|
59
71
|
- Signature Accuracy: AST-verified signature matching
|
|
@@ -60,13 +60,20 @@ Read {outputFile} frontmatter to get the skill directory path (`skillDir`).
|
|
|
60
60
|
|
|
61
61
|
Before running external validators, check if `{forge_data_folder}/{skill_name}/evidence-report.md` contains validation results (a `## Validation Results` section with quality scores).
|
|
62
62
|
|
|
63
|
-
**Staleness check:** Determine whether SKILL.md has changed since the evidence report was generated.
|
|
63
|
+
**Staleness check:** Determine whether SKILL.md has changed since the evidence report was generated. Walk through these checks in order:
|
|
64
64
|
|
|
65
|
-
**
|
|
65
|
+
**Pre-check (untracked or staged-only file):** Run `git ls-files --error-unmatch {skillDir}/SKILL.md 2>/dev/null`.
|
|
66
|
+
- If the command fails (exit code non-zero) or git is not available, the file is either **untracked** (new, never committed) or we're in a **non-git environment**:
|
|
67
|
+
- Check if `{skillDir}/metadata.json` exists and has a `generation_date` field
|
|
68
|
+
- Compare `metadata.json` `generation_date` against the evidence report's generation date (from its frontmatter or `## Validation Results` timestamp)
|
|
69
|
+
- If timestamps match within the same minute (same workflow session): auto-reuse is safe — the evidence report was generated from the same SKILL.md content
|
|
70
|
+
- If timestamps differ or metadata.json is missing: treat as stale, proceed to section 2 for a fresh run
|
|
71
|
+
- Note: "Staleness check: SKILL.md is untracked/non-git — using metadata.json timestamp comparison."
|
|
72
|
+
- If the command succeeds (file is tracked by git), continue to Primary check below.
|
|
66
73
|
|
|
67
|
-
**
|
|
74
|
+
**Primary (git-tracked):** Run `git log -1 --format=%cI -- {skillDir}/SKILL.md` to get the last commit date of SKILL.md. Compare against the evidence report's generation date (from its frontmatter or the `## Validation Results` timestamp). If SKILL.md's last commit is newer, results are stale.
|
|
68
75
|
|
|
69
|
-
**
|
|
76
|
+
**Secondary (uncommitted changes):** Run `git diff --name-only -- {skillDir}/SKILL.md`. If output is non-empty, SKILL.md has uncommitted changes — treat results as stale regardless of commit dates. Also check `git diff --cached --name-only -- {skillDir}/SKILL.md` for staged-but-uncommitted changes — if non-empty, SKILL.md has been staged since last commit, treat results as stale.
|
|
70
77
|
|
|
71
78
|
If SKILL.md was modified after the evidence report was generated (e.g., after update-skill), the cached results are stale — skip auto-reuse and proceed to section 2 for a fresh run.
|
|
72
79
|
|
|
@@ -76,9 +76,25 @@ Perform tier-aware extraction on only the changed files identified in step 02, p
|
|
|
76
76
|
|
|
77
77
|
**Remote Source Resolution (Forge/Deep only):**
|
|
78
78
|
|
|
79
|
-
**MCP source access
|
|
79
|
+
**MCP source access (ordered fallback):** When `source_repo` is set in metadata.json, try each MCP tool in order to fetch only the changed files from the change manifest. This avoids ephemeral clone overhead entirely. Tools are ordered by data freshness — gh API returns live GitHub content and is preferred for update-skill where current file versions are required. zread and deepwiki depend on manual indexing and may return stale data if indexes haven't been refreshed since the changes being extracted.
|
|
80
80
|
|
|
81
|
-
**
|
|
81
|
+
1. **gh API** — `gh api repos/{owner}/{repo}/contents/{path}` for raw file content
|
|
82
|
+
- If accessible: fetch file content (base64-decoded), always current
|
|
83
|
+
- If rate-limited, 404, or inaccessible: log tool and reason, continue to next tool
|
|
84
|
+
2. **zread** — `get_repo_structure` + `read_file` for targeted file access
|
|
85
|
+
- If repo found: fetch changed files, proceed with extraction
|
|
86
|
+
- If "repo not found" or error: log tool and reason, continue to next tool
|
|
87
|
+
- Caveat: indexed data — may be stale if index wasn't refreshed after the target changes
|
|
88
|
+
3. **deepwiki** — `ask_question` for targeted export/signature queries
|
|
89
|
+
- If repo indexed and returns usable source data: extract from response
|
|
90
|
+
- If no results or repo not indexed: log tool and reason, continue to next tool
|
|
91
|
+
- Caveat: returns synthesized content, not raw source — extraction quality varies; index may be stale
|
|
92
|
+
|
|
93
|
+
**Confidence labeling:** MCP-fetched content written to a temp file and analyzed with ast-grep → T1. MCP-fetched content analyzed with pattern matching (AST unavailable) → T1-low.
|
|
94
|
+
|
|
95
|
+
**If all MCP tools fail for this repo:** Fall back to ephemeral clone — load and follow `{remoteSourceResolutionData}` for clone setup, version reconciliation, and AST tool unavailability handling.
|
|
96
|
+
|
|
97
|
+
**If all approaches fail (MCP + ephemeral clone):** Degrade to provenance-map-only analysis (State 2, T1 confidence from compilation-time data). Warn user: "Source access failed for {source_repo}. Analysis limited to provenance-map baseline."
|
|
82
98
|
|
|
83
99
|
**Quick tier (text pattern matching):**
|
|
84
100
|
- Extract function/class/type names via regex patterns
|