bmad-module-skill-forge 0.7.2 → 0.7.3

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 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.7.2",
4
+ "version": "0.7.3",
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",
@@ -127,7 +127,7 @@ These registries are orthogonal — they never reference each other, and their j
127
127
 
128
128
  ```
129
129
  qmd collection remove {name}-extraction (if exists)
130
- qmd collection add skills/{name} --name {name}-extraction --mask "**/*"
130
+ qmd collection add {project-root}/skills/{name} --name {name}-extraction --mask "**/*"
131
131
  qmd embed
132
132
  ```
133
133
 
@@ -9,7 +9,7 @@ Defines the output contract for skill-brief.yaml files generated by analyze-sour
9
9
  | Field | Type | Constraint | Description |
10
10
  |-------|------|------------|-------------|
11
11
  | name | string | kebab-case `[a-z0-9-]+` | Unique skill identifier |
12
- | version | string | Semantic `X.Y.Z` | Auto-detect from source (see Version Detection below), fall back to `1.0.0` |
12
+ | version | string | Semantic version (`X.Y.Z` or `X.Y.Z-prerelease`) | Auto-detect from source (see Version Detection below), fall back to `1.0.0` |
13
13
  | source_repo | string | GitHub URL or local path | Repository or project root (optional when `source_type: "docs-only"`) |
14
14
  | language | string | Recognized language | Primary programming language |
15
15
  | scope | object | See Scope Object below | Boundary definition |
@@ -49,6 +49,8 @@ If detection succeeds, use the detected version. If it fails or returns a non-se
49
49
 
50
50
  The create-skill workflow (step-03-extract) also performs version reconciliation at extraction time — if the source version has changed since the brief was created, the extraction step warns and uses the source version.
51
51
 
52
+ **Pre-release handling:** If the detected version contains a pre-release tag (e.g., `1.0.0-beta.0`, `2.0.0-rc.1`), preserve it as-is. Pre-release tags are valid semver and must not be stripped. When comparing versions during reconciliation, use semver-aware comparison that respects pre-release ordering.
53
+
52
54
  ## Scope Object
53
55
 
54
56
  ```yaml
@@ -5,8 +5,8 @@ description: 'Present unit recommendations with rationale for user confirmation
5
5
  nextStepFile: './step-06-generate-briefs.md'
6
6
  outputFile: '{forge_data_folder}/analyze-source-report-{project_name}.md'
7
7
  schemaFile: '../data/skill-brief-schema.md'
8
- advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml'
9
- partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md'
8
+ advancedElicitationSkill: '/bmad-advanced-elicitation'
9
+ partyModeSkill: '/bmad-party-mode'
10
10
  ---
11
11
 
12
12
  # Step 5: Recommend
@@ -193,8 +193,8 @@ Display: "**Select an Option:** [A] Advanced Elicitation [P] Party Mode [D] Disc
193
193
 
194
194
  #### Menu Handling Logic:
195
195
 
196
- - IF A: Execute {advancedElicitationTask}, and when finished redisplay the menu
197
- - IF P: Execute {partyModeWorkflow}, and when finished redisplay the menu
196
+ - IF A: Invoke {advancedElicitationSkill}, and when finished redisplay the menu
197
+ - IF P: Invoke {partyModeSkill}, and when finished redisplay the menu
198
198
  - IF D: Accept a new repo path/URL from the user. Run a lightweight scan + classify (subset of steps 02-03) for the new source only. Merge new units into the existing report and update `project_paths[]` in frontmatter. Run export mapping for the new units (same logic as step 04 section 2). Generate recommendation cards for the new units and present them for confirmation. Then redisplay this menu.
199
199
  - IF C: Save recommendations to {outputFile}, update frontmatter, then load, read entire file, then execute {nextStepFile}
200
200
  - IF Any other comments or queries: help user respond then [Redisplay Menu Options](#8-present-menu-options)
@@ -5,7 +5,7 @@
5
5
  | Field | Type | Constraint | Description |
6
6
  |-------|------|------------|-------------|
7
7
  | name | string | kebab-case `[a-z0-9-]+` | Unique skill identifier |
8
- | version | string | Semantic `X.Y.Z` | Auto-detect from source (see Version Detection below), fall back to `1.0.0` |
8
+ | version | string | Semantic version (`X.Y.Z` or `X.Y.Z-prerelease`) | Auto-detect from source (see Version Detection below), fall back to `1.0.0` |
9
9
  | source_repo | string | GitHub URL or local path | Repository or project root (optional when `source_type: "docs-only"`) |
10
10
  | language | string | Recognized language | Primary programming language |
11
11
  | scope | object | See Scope Object below | Boundary definition |
@@ -45,6 +45,8 @@ If detection succeeds, use the detected version. If it fails or returns a non-se
45
45
 
46
46
  The create-skill workflow (step-03-extract) also performs version reconciliation at extraction time — if the source version has changed since the brief was created, the extraction step warns and uses the source version.
47
47
 
48
+ **Pre-release handling:** If the detected version contains a pre-release tag (e.g., `1.0.0-beta.0`, `2.0.0-rc.1`), preserve it as-is. Pre-release tags are valid semver and must not be stripped. When comparing versions during reconciliation, use semver-aware comparison that respects pre-release ordering.
49
+
48
50
  ## Scope Object Structure
49
51
 
50
52
  ```yaml
@@ -60,6 +60,12 @@ To analyze the target repository by resolving its location, reading its structur
60
60
  **For GitHub URLs:**
61
61
  - Use `gh api repos/{owner}/{repo}` to verify the repository exists
62
62
  - Use `gh api repos/{owner}/{repo}/git/trees/HEAD?recursive=1` to get the file tree
63
+
64
+ **Truncation detection:** After receiving the tree response, check the `truncated` field in the JSON output. If `truncated: true`:
65
+ - Display: "Note: GitHub API returned a truncated tree response ({count} items). Full analysis may require a local clone."
66
+ - Record in analysis summary: "Tree listing is partial — some files may not appear in the analysis."
67
+ - For very large repos (>1000 files in tree response): suggest local clone for complete analysis.
68
+
63
69
  - If inaccessible: **HALT** — "**Error:** Cannot access repository at {url}. Please verify the URL is correct and you have access. If private, ensure `gh auth` is configured."
64
70
 
65
71
  **For local paths:**
@@ -133,6 +139,8 @@ Based on detected language, identify public API surface:
133
139
 
134
140
  **Semantic Signals (Forge+ and Deep with ccc only):**
135
141
 
142
+ **Remote source guard:** If the target source was resolved via GitHub API (remote URL, not a local file path), skip this CCC subsection — CCC requires a local source index and cannot operate on remote-only sources. Note: "CCC semantic discovery skipped — target is remote. CCC will be available during create-skill if the source is cloned locally."
143
+
136
144
  If `tools.ccc` is true in forge-tier.yaml, supplement the module listing with a semantic discovery pass:
137
145
 
138
146
  **CCC Semantic Discovery:**
@@ -4,8 +4,8 @@ description: 'Collaboratively define skill scope boundaries using analysis findi
4
4
 
5
5
  nextStepFile: './step-04-confirm-brief.md'
6
6
  scopeTemplatesFile: '../data/scope-templates.md'
7
- advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml'
8
- partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md'
7
+ advancedElicitationSkill: '/bmad-advanced-elicitation'
8
+ partyModeSkill: '/bmad-party-mode'
9
9
  ---
10
10
 
11
11
  # Step 3: Scope Definition
@@ -90,7 +90,7 @@ Wait for confirmation. Then skip to section 5 (Summarize Scope Decisions) with:
90
90
 
91
91
  **If `source_type: "source"` (default):** Continue to scope templates below.
92
92
 
93
- ### 2c. Confirm Supplemental Documentation (if doc_urls collected)
93
+ ### 2b. Confirm Supplemental Documentation (if doc_urls collected)
94
94
 
95
95
  **If `source_type: "source"` AND supplemental `doc_urls` were collected in step 01:**
96
96
 
@@ -104,7 +104,7 @@ Wait for confirmation. Record any changes to `doc_urls`.
104
104
 
105
105
  **If no supplemental doc_urls were collected:** Skip this subsection.
106
106
 
107
- ### 2b. Offer Scope Templates
107
+ ### 2c. Offer Scope Templates
108
108
 
109
109
  Load `{scopeTemplatesFile}` for the scope type options ([F], [M], [P]) and their descriptions.
110
110
 
@@ -167,8 +167,8 @@ Display: **Select an Option:** [A] Advanced Elicitation [P] Party Mode [C] Conti
167
167
 
168
168
  #### Menu Handling Logic:
169
169
 
170
- - IF A: Execute {advancedElicitationTask}, and when finished redisplay the menu
171
- - IF P: Execute {partyModeWorkflow}, and when finished redisplay the menu
170
+ - IF A: Invoke {advancedElicitationSkill}, and when finished redisplay the menu
171
+ - IF P: Invoke {partyModeSkill}, and when finished redisplay the menu
172
172
  - IF C: Load, read entire file, then execute {nextStepFile}
173
173
  - IF Any other comments or queries: help user respond then [Redisplay Menu Options](#6-present-menu-options)
174
174
 
@@ -5,8 +5,8 @@ description: 'Present complete skill brief for user review and confirmation befo
5
5
  nextStepFile: './step-05-write-brief.md'
6
6
  reviseStepFile: './step-03-scope-definition.md'
7
7
  briefSchemaFile: '../data/skill-brief-schema.md'
8
- advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml'
9
- partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md'
8
+ advancedElicitationSkill: '/bmad-advanced-elicitation'
9
+ partyModeSkill: '/bmad-party-mode'
10
10
  ---
11
11
 
12
12
  # Step 4: Confirm Brief
@@ -165,8 +165,8 @@ Display: **Select an Option:** [R] Revise Scope [A] Advanced Elicitation [P] Par
165
165
  #### Menu Handling Logic:
166
166
 
167
167
  - IF R: Load, read entire file, then execute {reviseStepFile} to re-enter scope definition
168
- - IF A: Execute {advancedElicitationTask}, and when finished redisplay the menu
169
- - IF P: Execute {partyModeWorkflow}, and when finished redisplay the menu
168
+ - IF A: Invoke {advancedElicitationSkill}, and when finished redisplay the menu
169
+ - IF P: Invoke {partyModeSkill}, and when finished redisplay the menu
170
170
  - IF C: Load, read entire file, then execute {nextStepFile}
171
171
  - IF Any other comments or queries: help user respond, apply any field adjustments, re-present brief if changed, then [Redisplay Menu Options](#6-present-menu-options)
172
172
 
@@ -116,6 +116,7 @@ Do NOT repeat Tier 1's name/purpose/key-params table format in Tier 2. Tier 2 is
116
116
  4. If Tier 1 alone exceeds 300 lines, reduce Key API Summary and Architecture at a Glance
117
117
  5. Tier 1 sections are kept short enough that `split-body` targets the larger Tier 2 sections (`## Full ...` headings) instead
118
118
  6. After split-body, SKILL.md must still contain all Tier 1 sections with actionable content
119
+ 7. **Signature fidelity:** When populating function entries from the extraction inventory, always use the `params` and `return_type` fields from the provenance-map entry (T1/AST-backed). Do not substitute parameter names, types, or return types from documentation, README examples, or enrichment annotations. T2/T3 sources may enrich descriptions and add usage notes, but structural signature data from AST extraction is authoritative.
119
120
 
120
121
  ### Reference File Rules
121
122
 
@@ -51,7 +51,7 @@ Structural extraction via ast-grep — verified exports with line-level citation
51
51
  - Internal/private functions: excluded (not part of public API)
52
52
 
53
53
  ### ast-grep Patterns
54
- - JS/TS: `export function $NAME($$$PARAMS): $RET` / `export const $NAME`
54
+ - JS/TS: `export function $NAME($$$PARAMS): $RET` / `export const $NAME = ($$$PARAMS) => $BODY` / `export const $NAME` / `export class $NAME`
55
55
  - Rust: `pub fn $NAME($$$PARAMS) -> $RET`
56
56
  - Python: function definitions within `__all__` list
57
57
  - Go: capitalized function definitions
@@ -260,6 +260,32 @@ rule:
260
260
  pattern: 'export const $NAME = $VALUE'
261
261
  ```
262
262
 
263
+ **JavaScript/TypeScript — exported arrow functions:**
264
+
265
+ ```yaml
266
+ id: js-exported-arrow-functions
267
+ language: typescript
268
+ rule:
269
+ pattern: 'export const $NAME = ($$$PARAMS) => $BODY'
270
+ ```
271
+
272
+ > **JS/TS Pattern Merging:** Modern TypeScript codebases often use `export const` exclusively for all exports (arrow functions, objects, constants). Run ALL four JS/TS patterns (functions, arrow functions, constants, classes) and merge results by `$NAME`. Priority when deduplicating: arrow function match > function declaration match > constant match. Arrow function matches capture parameters directly; constant matches require inspecting `$VALUE` to extract signatures.
273
+
274
+ **JavaScript/TypeScript — exported classes (use `find_code`, not `find_code_by_rule`):**
275
+
276
+ ```yaml
277
+ id: js-exported-classes
278
+ language: typescript
279
+ rule:
280
+ pattern: 'export class $NAME'
281
+ ```
282
+
283
+ > **Important:** For class patterns, use `find_code()` rather than `find_code_by_rule()`. The `find_code_by_rule` API requires explicit AST `kind` rules for class exports, which adds complexity. The simpler `find_code()` pattern approach works reliably for class detection.
284
+
285
+ **JavaScript/TypeScript — re-export detection (use `find_code`):**
286
+
287
+ Use `find_code()` with pattern `export { $$$NAMES } from $SOURCE` for re-export detection. Note: this pattern may produce multiple AST node matches. Post-process results to split comma-separated names from `$$$NAMES`. For complex re-export chains (aliased exports, default re-exports, namespace re-exports), fall back to the Re-Export Tracing protocol in `extraction-patterns-tracing.md`.
288
+
263
289
  **Rust — public functions:**
264
290
 
265
291
  ```yaml
@@ -277,12 +303,29 @@ rule:
277
303
  id: go-exported-functions
278
304
  language: go
279
305
  rule:
280
- pattern: 'func $NAME($$$PARAMS) $RET'
306
+ any:
307
+ - pattern: 'func $NAME($$$PARAMS) $RET'
308
+ - pattern: 'func $NAME($$$PARAMS)'
281
309
  constraints:
282
310
  NAME:
283
311
  regex: '^[A-Z]'
284
312
  ```
285
313
 
314
+ ### Known ast-grep Limitations
315
+
316
+ When using ast-grep for extraction, be aware of these documented limitations:
317
+
318
+ 1. **`find_code_by_rule` requires explicit `kind` for class exports:** The `export class $NAME` pattern needs a `kind` rule specifying the tree-sitter node type when used with `find_code_by_rule`. Use the simpler `find_code()` API instead for class detection.
319
+
320
+ 2. **Re-export patterns produce multiple AST nodes:** `export { A, B, C } from './module'` decomposes into multiple metavariable bindings for `$$$NAMES`. Results require post-processing to split comma-separated names.
321
+
322
+ 3. **Default anonymous exports capture no name:** `export default function $NAME` works, but `export default $EXPR` (anonymous default export) captures no name in `$NAME`. Fall back to source reading (T1-low) for anonymous defaults.
323
+
324
+ 4. **Fallback protocol:** If an ast-grep pattern returns errors or zero results when results are expected:
325
+ - First: retry with `find_code()` using a simpler pattern (drop type annotations, use broader match)
326
+ - Second: if `find_code()` also fails, fall back to source reading for that pattern category (T1-low confidence)
327
+ - Never silently accept zero results for a pattern category that the source language commonly uses
328
+
286
329
  ### Re-Export Tracing and Script/Asset Extraction
287
330
 
288
331
  See `extraction-patterns-tracing.md` for:
@@ -199,7 +199,8 @@ Each reference file includes:
199
199
  "source_line": 42,
200
200
  "confidence": "T1",
201
201
  "extraction_method": "ast-grep",
202
- "ast_node_type": "export_function_declaration"
202
+ "ast_node_type": "export_function_declaration",
203
+ "signature_source": "T1"
203
204
  }
204
205
  ],
205
206
  "file_entries": [
@@ -47,7 +47,7 @@ For Quick and Forge tiers, or when ccc is unavailable, skip silently and proceed
47
47
 
48
48
  - Available: tier, tools.ccc, ccc_index from forge-tier.yaml (loaded in step-01)
49
49
  - Available: brief_data (name, scope, description) from step-01
50
- - Available: source_root (resolved source path) from step-01
50
+ - Available: source_root (resolved source path) from step-01 — note: for remote sources, `source_root` may not be a local path until step-03 performs the ephemeral clone
51
51
  - Focus: Semantic discovery only — no extraction, no compilation
52
52
  - Dependencies: step-02 must have completed
53
53
 
@@ -67,6 +67,8 @@ Check `tools.ccc` from forge-tier.yaml. If `tools.ccc` is false, set `{ccc_disco
67
67
 
68
68
  If `tools.ccc` is true, continue 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.
71
+
70
72
  ### 2. Check CCC Index State
71
73
 
72
74
  Read `ccc_index` from forge-tier.yaml:
@@ -172,7 +172,7 @@ If a `{skill-name}-temporal` collection already exists, remove and recreate for
172
172
 
173
173
  ```bash
174
174
  qmd collection remove {skill-name}-temporal
175
- qmd collection add _bmad-output/{skill-name}-temporal/ --name {skill-name}-temporal --mask "*.md"
175
+ qmd collection add {project-root}/_bmad-output/{skill-name}-temporal/ --name {skill-name}-temporal --mask "*.md"
176
176
  qmd embed
177
177
  ```
178
178
 
@@ -193,7 +193,7 @@ If an entry with `name: "{skill-name}-temporal"` already exists in `qmd_collecti
193
193
  **Clean up** the staging directory after successful indexing:
194
194
 
195
195
  ```bash
196
- rm -rf _bmad-output/{skill-name}-temporal/
196
+ rm -rf {project-root}/_bmad-output/{skill-name}-temporal/
197
197
  ```
198
198
 
199
199
  **Error handling:**
@@ -153,7 +153,7 @@ Parse the successfully fetched markdown for:
153
153
  **If tier is Deep and at least one URL was fetched successfully:**
154
154
 
155
155
  1. Write fetched markdown files to a staging directory: `_bmad-output/{skill-name}-docs/`
156
- 2. Index into QMD: `qmd collection add _bmad-output/{skill-name}-docs/ --name {skill-name}-docs --mask "*.md"`
156
+ 2. Index into QMD: `qmd collection add {project-root}/_bmad-output/{skill-name}-docs/ --name {skill-name}-docs --mask "*.md"`
157
157
  3. Generate embeddings: `qmd embed` (required for `vector_search` and `deep_search`)
158
158
  4. Register in forge-tier.yaml `qmd_collections` array:
159
159
 
@@ -165,7 +165,7 @@ Parse the successfully fetched markdown for:
165
165
  created_at: "{current ISO date}"
166
166
  ```
167
167
 
168
- 5. Clean up staging directory after indexing: `rm -rf _bmad-output/{skill-name}-docs/`
168
+ 5. Clean up staging directory after indexing: `rm -rf {project-root}/_bmad-output/{skill-name}-docs/`
169
169
 
170
170
  **If QMD indexing fails:** Warn: "QMD indexing of fetched docs failed. T3 items are still in the extraction inventory — enrichment will proceed without QMD-indexed docs." Continue.
171
171
 
@@ -59,6 +59,17 @@ To assemble the complete skill content from the extraction inventory and enrichm
59
59
 
60
60
  Load `{skillSectionsData}` and `{assemblyRulesData}` completely. These define the agentskills.io-compliant format and detailed assembly rules for all output artifacts.
61
61
 
62
+ ### 1b. Signature Fidelity Rule
63
+
64
+ **When assembling function signatures, parameter lists, and return types in any SKILL.md section or reference file:**
65
+
66
+ - **T1 provenance-map entries (AST-extracted) are authoritative** for: function name, parameter names, parameter types, parameter order, return type, and optionality markers (e.g., `?`, `Optional`, `= default`).
67
+ - **T2 (QMD-enriched) and T3 (doc-derived) sources may ADD** contextual descriptions, usage notes, behavioral documentation, and examples to function entries, but **MUST NOT REPLACE** structural signature data from T1 entries.
68
+ - **On conflict:** If a T2/T3 source provides a different signature than the T1 extraction for the same export (e.g., different parameter count, different types, missing `Partial<>` wrapper), keep the T1 signature and log a warning in the evidence report: "Signature conflict for `{export_name}`: T1 shows `{t1_signature}`, T2/T3 shows `{other_signature}`. T1 used as authoritative."
69
+ - **`signature_source` field:** Record `signature_source: "T1" | "T1-low" | "T2" | "T3"` in each provenance-map entry to indicate the highest-confidence tier that contributed the structural signature data (params, return_type). This enables test-skill to verify signature provenance.
70
+
71
+ This rule applies to ALL sections including Tier 1 Key API Summary, Tier 2 Full API Reference, and Section 4b Migration & Deprecation Warnings.
72
+
62
73
  ### 2. Build SKILL.md Content
63
74
 
64
75
  Assemble each section in order using the assembly rules data file (`{assemblyRulesData}`). The data file specifies frontmatter format, Tier 1 section details (Sections 1-8, including conditional Section 7b for scripts/assets), Tier 2 section details (Sections 9-11), and assembly ordering rules. Follow it exactly. Assemble Section 7b (Scripts & Assets) only if `scripts_inventory` or `assets_inventory` is non-empty.
@@ -92,7 +103,7 @@ Following the structure from the skill-sections data file:
92
103
  - Set `source_commit` from resolved source (if available)
93
104
  - Set `stats` from extraction aggregate counts:
94
105
  - `exports_documented`: count of exports with documentation in the assembled SKILL.md
95
- - `exports_public_api`: count of exports from public entry points (`__init__.py`, `index.ts`, `lib.rs`, or equivalent)
106
+ - `exports_public_api`: count of exports from public entry points (`__init__.py`, `index.ts`, `lib.rs`, or equivalent) — derive this from step-03's entry-point validation (section 4b), NOT from the provenance-map entry count (which may be incomplete if extraction patterns missed some export types)
96
107
  - `exports_internal`: count of all other non-underscore-prefixed exports (internal modules, helpers, adapters)
97
108
  - `exports_total`: `exports_public_api` + `exports_internal`
98
109
  - `public_api_coverage`: `exports_documented / exports_public_api` (1.0 when all public API exports are documented; `null` if `exports_public_api` is 0)
@@ -121,7 +132,7 @@ Group functions logically by module, file, or functional area.
121
132
 
122
133
  ### 6. Build provenance-map.json Content
123
134
 
124
- One entry per extracted export: export_name, export_type, params[] (typed strings), return_type, source_file, source_line, confidence tier (T1/T1-low/T2), extraction_method, ast_node_type. If `scripts_inventory` or `assets_inventory` is non-empty, add `file_entries[]` with file_name, file_type, source_file, content_hash, confidence, extraction_method. See `{skillSectionsData}` for full schema.
135
+ One entry per extracted export: export_name, export_type, params[] (typed strings), return_type, source_file, source_line, confidence tier (T1/T1-low/T2), extraction_method, ast_node_type, signature_source ("T1"|"T1-low"|"T2"|"T3" — indicates which tier contributed the structural signature). If `scripts_inventory` or `assets_inventory` is non-empty, add `file_entries[]` with file_name, file_type, source_file, content_hash, confidence, extraction_method. See `{skillSectionsData}` for full schema.
125
136
 
126
137
  ### 7. Build evidence-report.md Content
127
138
 
@@ -76,6 +76,8 @@ This performs frontmatter validation, description quality checks, body limit enf
76
76
 
77
77
  **Context sync after --fix:** If `fixed[]` is non-empty (i.e., `--fix` modified files on disk), re-read the modified SKILL.md to update the in-context copy. Verify the re-read content matches expectations before proceeding. This prevents silent divergence between the in-context SKILL.md and the on-disk version that step-07 will use for artifact generation.
78
78
 
79
+ **Description preservation after --fix:** After re-reading the modified SKILL.md, compare the frontmatter `description` field against the original step-05 compiled description. If `--fix` replaced the description with a generic or truncated version, restore the original description to the on-disk file and update the in-context copy. The step-05 compiled description is authoritative — auto-fix tools must not replace trigger-optimized descriptions.
80
+
79
81
  **Note:** `skill-check` may return non-zero exit code even when `errorCount` is 0. Always rely on parsed JSON, not the shell exit code.
80
82
 
81
83
  - **Score ≥ 70:** Record "Schema: PASS (score: {score}/100)" in evidence-report
@@ -101,15 +103,17 @@ If fails: auto-fix (deterministic), re-validate once, record result. If passes:
101
103
 
102
104
  **If step 2 reported `body.max_lines` failure:**
103
105
 
104
- **Preferred approach — selective split:** Rather than a full `split-body`, identify which Tier 2 section(s) are largest (usually `## Full API Reference`) and manually extract only those to `references/`. Keep all Tier 1 content and smaller Tier 2 sections inline. This preserves agent accuracy inline passive context achieves 100% task accuracy vs 79% for on-demand retrieval (per Vercel research). The rationale: inline passive context achieves 100% task accuracy vs 79% for on-demand retrieval (per Vercel research).
106
+ **Description preservation:** Before any split operation, capture the current SKILL.md frontmatter `description` field. After the split completes, verify the `description` was not modified. If it was replaced with a generic placeholder, restore the original immediately.
105
107
 
106
- **If manual selective split is not feasible**, fall back to the automated full split:
108
+ **Mandatory approach selective split:** Identify Tier 2 sections by their `## Full` heading prefix (e.g., `## Full API Reference`, `## Full Type Definitions`, `## Full Integration Patterns`). Extract ONLY those sections to `references/`, starting with the largest. Keep ALL Tier 1 content and any smaller sections inline. Inline passive context achieves 100% task accuracy vs 79% for on-demand retrieval (per Vercel research).
107
109
 
108
- ```bash
109
- npx skill-check split-body <staging-skill-dir> --write
110
- ```
110
+ **FORBIDDEN:** Running `npx skill-check split-body --write` without prior selective extraction. The `split-body --write` command extracts ALL `##` sections top-to-bottom, destroying Tier 1 inline content that the two-tier design depends on. This command is a LAST RESORT only after selective split has been attempted and proven insufficient.
111
+
112
+ **If selective split alone does not bring body under the limit** (rare — typically only occurs when Tier 1 itself exceeds 300 lines): reduce Tier 1 Key API Summary and Architecture at a Glance sections to fit within limits. Do NOT fall back to automated `split-body --write` to solve a Tier 1 sizing problem.
113
+
114
+ **Tier 1 preservation check:** After ANY split operation, verify that ALL of the following sections remain inline in SKILL.md (not moved to references/): Overview, Quick Start, Common Workflows, Key API Summary, Migration & Deprecation Warnings (if present), Key Types, Architecture at a Glance, CLI (if present), Scripts & Assets (if present), Manual Sections. If any Tier 1 section was moved to references/, restore it immediately and re-split targeting only Tier 2 sections.
111
115
 
112
- After any split (selective or full), verify that context snippet section anchors (`#quick-start`, `#key-types`) still resolve to headings in SKILL.md.
116
+ **Anchor validation and remediation:** After any split, verify that context-snippet section anchors (`#quick-start`, `#key-types`) still resolve to headings in SKILL.md. If an anchor no longer resolves (section was split out), restore that section to SKILL.md inline content — the context-snippet must always reference sections that exist in the main file.
113
117
 
114
118
  Then re-validate: `npx skill-check check <staging-skill-dir> --format json --no-security-scan`
115
119
 
@@ -21,9 +21,15 @@ Before analysis, determine source access level. Walk through these states in ord
21
21
  Check if `{source_path}` (from metadata.json `source_root`) exists on disk. If yes → full analysis at detected tier (AST + signatures). Set `analysis_confidence: full`.
22
22
 
23
23
  **State 2 — Local absent, provenance-map exists:**
24
- Check `{forge_data_folder}/{skill_name}/provenance-map.json`. If present, use it as the baseline export inventory — each entry contains structured fields: `export_name`, `export_type`, `params[]`, `return_type`, `source_file`, `source_line`, `confidence`, and `ast_node_type`. Cross-reference against SKILL.md documented exports for name-matching and param-by-param coverage. Signature verification compares SKILL.md's documented params/return types against provenance-map entries directly. If remote reading tools are available (zread, deepwiki, gh API, or similar), supplement by reading the entry point file for live signature verification. Set `analysis_confidence: provenance-map`.
24
+ Check `{forge_data_folder}/{skill_name}/provenance-map.json`. If present AND contains at least 1 entry, use it as the baseline export inventory — each entry contains structured fields: `export_name`, `export_type`, `params[]`, `return_type`, `source_file`, `source_line`, `confidence`, and `ast_node_type`. Cross-reference against SKILL.md documented exports for name-matching and param-by-param coverage. Signature verification compares SKILL.md's documented params/return types against provenance-map entries directly.
25
25
 
26
- **State 2 limitations:** Signature verification at State 2 is **string comparison only**, not semantic. Provenance-map stores parameters as flat string arrays (e.g., `["data: Union[BinaryIO, list, str]"]`), so `str` vs `String` or `list` vs `List[Any]` would be treated as mismatches even when semantically equivalent. For full type-aware verification (handling type aliases, generic equivalence), State 1 (local source) with AST re-parsing is required. When the SKILL.md was compiled from the same provenance-map (typical for create-then-test flows), strings match exactly and this limitation has no practical effect.
26
+ **Cross-reference with metadata.json:** After loading provenance-map entries, compare the entry count against `metadata.json`'s `exports[]` array length and `stats.exports_public_api` count. If metadata reports more exports than provenance-map entries:
27
+ - Compute `gap = metadata.exports.length - provenance_map.entries.length`
28
+ - Report: "Provenance-map contains {pmap_count} entries but metadata.json lists {meta_count} exports ({gap} gap). Coverage denominator uses the union."
29
+ - Build the coverage denominator from the **union** of provenance-map entry names and metadata.json `exports[]` names. Exports present in metadata but absent from provenance-map are counted as "missing documentation" in the coverage calculation.
30
+ - If metadata.json is unavailable or has no `exports[]` array, use provenance-map count alone with a note: "Coverage denominator is provenance-map only — may undercount if extraction was incomplete." If remote reading tools are available (zread, deepwiki, gh API, or similar), supplement by reading the entry point file for live signature verification. Set `analysis_confidence: provenance-map`.
31
+
32
+ **State 2 limitations:** Signature verification at State 2 is **string comparison only**, not semantic. Provenance-map stores parameters as flat string arrays (e.g., `["data: Union[BinaryIO, list, str]"]`), so `str` vs `String` or `list` vs `List[Any]` would be treated as mismatches even when semantically equivalent. For full type-aware verification (handling type aliases, generic equivalence), State 1 (local source) with AST re-parsing is required. When the SKILL.md was compiled from the same provenance-map (typical for create-then-test flows), most strings will match. However, enrichment (step-04) and doc-fetching (step-03c) during compilation may alter parameter descriptions, add type annotations, or normalize signatures, causing mismatches even in create-then-test flows. Expect some string-level mismatches and treat them as compilation artifacts, not source drift signals, until signature fidelity is enforced by step-05's Signature Fidelity Rule (see `signature_source` field in provenance-map entries).
27
33
 
28
34
  **State 3 — No provenance-map, metadata exports exist (quick-skill path):**
29
35
  If no provenance-map.json exists (typical for quick-skill output), fall back to `metadata.json`'s `exports[]` array for the export name list. Coverage check becomes a self-consistency comparison: are all names in `exports[]` documented in SKILL.md with description, parameters, and return type? Signatures cannot be verified. If remote reading tools are available, supplement by reading the entry point for live export comparison. Set `analysis_confidence: metadata-only`.
@@ -185,6 +185,8 @@ Load `{scoringRulesFile}` to determine category scores:
185
185
  - **Signature Accuracy:** (matching_signatures / total_documented) * 100 (Forge/Deep only, "N/A" for Quick)
186
186
  - **Type Coverage:** (documented_types / total_types) * 100 (Forge/Deep only, "N/A" for Quick)
187
187
 
188
+ **State 2 denominator validation:** When using provenance-map as the baseline (State 2), cross-reference the provenance-map entry count against `metadata.json`'s `exports[]` array before computing Export Coverage. If they diverge, use the union as the denominator per the source-access-protocol rules. Log the gap size if any.
189
+
188
190
  ### 5. Append Coverage Analysis to Output
189
191
 
190
192
  Append the **Coverage Analysis** section to `{outputFile}`: