bmad-module-skill-forge 0.8.3 → 0.9.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 (75) hide show
  1. package/README.md +9 -4
  2. package/docs/bmad-synergy.md +183 -0
  3. package/docs/concepts.md +60 -2
  4. package/docs/examples.md +70 -17
  5. package/docs/getting-started.md +23 -1
  6. package/docs/how-it-works.md +143 -29
  7. package/docs/index.md +1 -1
  8. package/docs/workflows.md +45 -5
  9. package/package.json +1 -1
  10. package/src/README.md +47 -0
  11. package/src/agents/forger.agent.yaml +9 -0
  12. package/src/knowledge/agentskills-spec.md +3 -0
  13. package/src/knowledge/overview.md +1 -0
  14. package/src/knowledge/provenance-tracking.md +3 -0
  15. package/src/knowledge/skf-knowledge-index.csv +1 -0
  16. package/src/knowledge/skill-lifecycle.md +19 -7
  17. package/src/knowledge/version-paths.md +243 -0
  18. package/src/module-help.csv +2 -0
  19. package/src/workflows/README.md +9 -1
  20. package/src/workflows/analyze-source/data/skill-brief-schema.md +4 -0
  21. package/src/workflows/audit-skill/steps-c/step-01-init.md +10 -6
  22. package/src/workflows/audit-skill/steps-c/step-02-re-index.md +1 -1
  23. package/src/workflows/audit-skill/steps-c/step-03-structural-diff.md +1 -1
  24. package/src/workflows/audit-skill/steps-c/step-04-semantic-diff.md +1 -1
  25. package/src/workflows/audit-skill/steps-c/step-05-severity-classify.md +1 -1
  26. package/src/workflows/audit-skill/steps-c/step-06-report.md +1 -1
  27. package/src/workflows/brief-skill/data/skill-brief-schema.md +11 -0
  28. package/src/workflows/brief-skill/steps-c/step-01-gather-intent.md +28 -4
  29. package/src/workflows/brief-skill/steps-c/step-02-analyze-target.md +10 -0
  30. package/src/workflows/brief-skill/steps-c/step-04-confirm-brief.md +9 -0
  31. package/src/workflows/brief-skill/steps-c/step-05-write-brief.md +14 -1
  32. package/src/workflows/create-skill/data/skill-sections.md +2 -0
  33. package/src/workflows/create-skill/data/source-resolution-protocols.md +40 -4
  34. package/src/workflows/create-skill/steps-c/step-03-extract.md +1 -1
  35. package/src/workflows/create-skill/steps-c/step-05-compile.md +1 -0
  36. package/src/workflows/create-skill/steps-c/step-07-generate-artifacts.md +48 -32
  37. package/src/workflows/create-skill/steps-c/step-08-report.md +8 -7
  38. package/src/workflows/create-stack-skill/data/compose-mode-rules.md +12 -6
  39. package/src/workflows/create-stack-skill/steps-c/step-01-init.md +4 -1
  40. package/src/workflows/create-stack-skill/steps-c/step-02-detect-manifests.md +11 -5
  41. package/src/workflows/create-stack-skill/steps-c/step-04-parallel-extract.md +1 -1
  42. package/src/workflows/create-stack-skill/steps-c/step-05-detect-integrations.md +1 -1
  43. package/src/workflows/create-stack-skill/steps-c/step-07-generate-output.md +40 -23
  44. package/src/workflows/create-stack-skill/steps-c/step-08-validate.md +6 -3
  45. package/src/workflows/create-stack-skill/steps-c/step-09-report.md +5 -3
  46. package/src/workflows/drop-skill/steps-c/step-01-select.md +298 -0
  47. package/src/workflows/drop-skill/steps-c/step-02-execute.md +290 -0
  48. package/src/workflows/drop-skill/steps-c/step-03-report.md +135 -0
  49. package/src/workflows/drop-skill/workflow.md +63 -0
  50. package/src/workflows/export-skill/data/managed-section-format.md +33 -8
  51. package/src/workflows/export-skill/data/snippet-format.md +16 -4
  52. package/src/workflows/export-skill/steps-c/step-01-load-skill.md +46 -7
  53. package/src/workflows/export-skill/steps-c/step-02-package.md +2 -2
  54. package/src/workflows/export-skill/steps-c/step-03-generate-snippet.md +39 -7
  55. package/src/workflows/export-skill/steps-c/step-04-update-context.md +185 -13
  56. package/src/workflows/export-skill/steps-c/step-05-token-report.md +2 -2
  57. package/src/workflows/export-skill/steps-c/step-06-summary.md +26 -7
  58. package/src/workflows/quick-skill/steps-c/step-01-resolve-target.md +10 -0
  59. package/src/workflows/quick-skill/steps-c/step-03-quick-extract.md +2 -0
  60. package/src/workflows/quick-skill/steps-c/step-05-validate.md +1 -1
  61. package/src/workflows/quick-skill/steps-c/step-06-write.md +30 -14
  62. package/src/workflows/refine-architecture/steps-c/step-01-init.md +8 -3
  63. package/src/workflows/rename-skill/steps-c/step-01-select.md +281 -0
  64. package/src/workflows/rename-skill/steps-c/step-02-execute.md +391 -0
  65. package/src/workflows/rename-skill/steps-c/step-03-report.md +132 -0
  66. package/src/workflows/rename-skill/workflow.md +64 -0
  67. package/src/workflows/test-skill/steps-c/step-01-init.md +17 -11
  68. package/src/workflows/test-skill/steps-c/step-02-detect-mode.md +1 -1
  69. package/src/workflows/update-skill/data/remote-source-resolution.md +18 -4
  70. package/src/workflows/update-skill/steps-c/step-01-init.md +15 -8
  71. package/src/workflows/update-skill/steps-c/step-06-write.md +43 -13
  72. package/src/workflows/update-skill/steps-c/step-07-report.md +7 -5
  73. package/src/workflows/verify-stack/steps-c/step-01-init.md +8 -3
  74. package/tools/cli/lib/installer.js +1 -0
  75. package/tools/cli/lib/ui.js +24 -2
@@ -6,21 +6,35 @@ If `source_root` (from metadata.json) is a remote URL (GitHub URL or owner/repo
6
6
 
7
7
  1. **Check `git` availability:** Verify `git` is functional (`git --version`). If `git` is not available, skip to the fallback warning below.
8
8
 
9
- 2. **Ephemeral sparse clone:** Clone only the changed files from the change manifest to a system temp path. Note: at this point in the flow, `{source_root}` is known to be a remote URL (the local-path case was already handled above).
9
+ 2. **Resolve source ref:** Read `source_ref` from the existing `metadata.json`. If the user provided a new `target_version`, resolve its tag first (using the Tag Resolution algorithm in `create-skill/data/source-resolution-protocols.md`).
10
+
11
+ 3. **Ephemeral sparse clone:** Clone only the changed files from the change manifest to a system temp path. Note: at this point in the flow, `{source_root}` is known to be a remote URL (the local-path case was already handled above).
10
12
 
11
13
  ```
12
14
  temp_path = {system_temp}/skf-ephemeral-{skill-name}-{timestamp}/
15
+ ```
16
+
17
+ If `source_ref` exists and is not `HEAD`/null/`"local"`:
18
+ ```
19
+ git clone --depth 1 --branch {source_ref} --single-branch --filter=blob:none --sparse {source_root} {temp_path}
20
+ ```
21
+
22
+ If `source_ref` is `HEAD`/null/`"local"` (or absent):
23
+ ```
13
24
  git clone --depth 1 --single-branch --filter=blob:none --sparse {source_root} {temp_path}
25
+ ```
26
+
27
+ ```
14
28
  git -C {temp_path} sparse-checkout set --skip-checks {changed_files_from_manifest}
15
29
  ```
16
30
 
17
31
  **Note:** `--skip-checks` is required because `changed_files_from_manifest` contains individual file paths (e.g., `src/core/parser.py`), not directories. Without this flag, `git sparse-checkout set` rejects non-directory entries.
18
32
 
19
- No `--branch` flag is used the clone targets the remote's default branch, which must match the branch used during the original [CS] Create Skill run. This scopes the clone to only the files identified in step-02's change manifest, avoiding a full repository download.
33
+ When `source_ref` is a tag (e.g., `v0.5.0`), the clone targets that specific tag to ensure update-skill extracts from the same source version as the original create-skill run. When `source_ref` is `HEAD`, null, or `"local"`, no `--branch` flag is used the clone targets the remote's default branch. This scopes the clone to only the files identified in step-02's change manifest, avoiding a full repository download.
20
34
 
21
- 3. **If clone succeeds:** Update the working source path to `{temp_path}` for all subsequent AST operations in this step. Proceed with the **Forge tier** extraction strategy below. Mark `ephemeral_clone_active = true` for cleanup.
35
+ 4. **If clone succeeds:** Update the working source path to `{temp_path}` for all subsequent AST operations in this step. Proceed with the **Forge tier** extraction strategy below. Mark `ephemeral_clone_active = true` for cleanup.
22
36
 
23
- 4. **If clone fails (network error, auth failure, timeout):**
37
+ 5. **If clone fails (network error, auth failure, timeout):**
24
38
 
25
39
  Warning message: "Ephemeral clone of `{source_root}` failed: {error}. Degrading to source reading (T1-low) for this run. For T1 (AST-verified) confidence, clone the repository locally and re-run [CS] Create Skill with the local path, then re-run this update."
26
40
 
@@ -60,25 +60,32 @@ Load the existing skill and all its provenance data, detect whether this is an i
60
60
  "**Which skill would you like to update?**
61
61
 
62
62
  Provide either:
63
- - A skill name (resolves to `{skills_output_folder}/{name}/`)
63
+ - A skill name (resolves via version-aware path resolution — see [knowledge/version-paths.md](../../../knowledge/version-paths.md))
64
64
  - A full path to the skill folder
65
65
  - A skill name with `--from-test-report` to use the test report's gap findings instead of source drift detection
66
66
 
67
67
  **Skill:** {user provides path or name}"
68
68
 
69
+ **Version-Aware Path Resolution:**
70
+ 1. Read `{skills_output_folder}/.export-manifest.json` and look up the skill name in `exports` to get `active_version`
71
+ 2. If found: resolve to `{skill_package}` = `{skills_output_folder}/{skill-name}/{active_version}/{skill-name}/`
72
+ 3. If not in manifest: check for `active` symlink at `{skills_output_folder}/{skill-name}/active` — resolve to `{skill_group}/active/{skill-name}/`
73
+ 4. If neither: fall back to flat path `{skills_output_folder}/{skill-name}/`. If SKILL.md exists at the flat path, auto-migrate per `knowledge/version-paths.md` migration rules
74
+ 5. Store the resolved path as `{resolved_skill_package}` for all subsequent artifact loading
75
+
69
76
  Resolve the path to an absolute skill folder location.
70
77
 
71
78
  **If `--from-test-report` was provided (or user references a test report):**
72
- Search for the test report at `{forge_data_folder}/{skill_name}/test-report-{skill_name}.md`. If found, set `test_report_path` in context and `update_mode: gap-driven`. If not found, warn and continue with normal source drift mode.
79
+ Search for the test report at `{forge_data_folder}/{skill_name}/{active_version}/test-report-{skill_name}.md` (i.e., `{forge_version}/test-report-{skill_name}.md`). If not found at the versioned path, fall back to `{forge_data_folder}/{skill_name}/test-report-{skill_name}.md`. If found, set `test_report_path` in context and `update_mode: gap-driven`. If not found at either path, warn and continue with normal source drift mode.
73
80
 
74
81
  ### 2. Validate Required Artifacts
75
82
 
76
83
  **Check SKILL.md exists:**
77
- - Load `{resolved_skill_path}/SKILL.md`
78
- - If missing: **ABORT** — "No SKILL.md found at `{resolved_skill_path}`. Run create-skill first."
84
+ - Load `{resolved_skill_package}/SKILL.md`
85
+ - If missing: **ABORT** — "No SKILL.md found at `{resolved_skill_package}`. Run create-skill first."
79
86
 
80
87
  **Check metadata.json exists:**
81
- - Load `{resolved_skill_path}/metadata.json`
88
+ - Load `{resolved_skill_package}/metadata.json`
82
89
  - Extract: `name`, `skill_type` (single or stack), `version`, `generation_date`, `confidence_tier`, `source_root`
83
90
  - If missing: **ABORT** — "No metadata.json found. This skill may have been created manually. Run create-skill to generate provenance data."
84
91
 
@@ -102,13 +109,13 @@ Search for the test report at `{forge_data_folder}/{skill_name}/test-report-{ski
102
109
 
103
110
  ### 4. Load Provenance Map
104
111
 
105
- **Load `{forge_data_folder}/{skill_name}/provenance-map.json`:**
112
+ **Load `{forge_data_folder}/{skill_name}/{active_version}/provenance-map.json`** (i.e., `{forge_version}/provenance-map.json`). If not found at the versioned path, fall back to `{forge_data_folder}/{skill_name}/provenance-map.json`:
106
113
  - Extract: export list, file mappings, extraction timestamps, confidence tiers
107
114
  - Calculate provenance age (days since last extraction)
108
115
 
109
- **If provenance map missing:**
116
+ **If provenance map missing at both paths:**
110
117
 
111
- "**WARNING:** No provenance map found at `{forge_data_folder}/{skill_name}/provenance-map.json`.
118
+ "**WARNING:** No provenance map found at `{forge_version}/provenance-map.json` or flat fallback.
112
119
 
113
120
  Without a provenance map, update-skill cannot perform targeted change detection. Options:
114
121
 
@@ -49,6 +49,7 @@ Write all updated skill artifacts to disk: the merged SKILL.md, updated provenan
49
49
  - Focus: file I/O operations — write and verify
50
50
  - Limits: write only to skill output and forge data directories
51
51
  - Dependencies: steps 02-05 must all be complete
52
+ - Path resolution: See `knowledge/version-paths.md` for canonical path templates (`{skill_package}`, `{skill_group}`, `{forge_version}`, `{forge_group}`)
52
53
 
53
54
  ## MANDATORY SEQUENCE
54
55
 
@@ -56,14 +57,16 @@ Write all updated skill artifacts to disk: the merged SKILL.md, updated provenan
56
57
 
57
58
  ### 1. Write Updated SKILL.md
58
59
 
59
- Write the merged SKILL.md content to `{skills_output_folder}/{skill_name}/SKILL.md`:
60
+ Write the merged SKILL.md content to `{skill_package}/SKILL.md`:
60
61
  - Overwrite the existing file with merged content
61
62
  - Preserve file encoding (UTF-8)
62
63
  - Verify write by reading back and confirming [MANUAL] section count matches expected
63
64
 
65
+ If the version changed (source version differs from the previous metadata version), write to the new `{skill_package}` (creating the version directory if needed). The previous version's directory is preserved on disk.
66
+
64
67
  ### 2. Write Updated metadata.json
65
68
 
66
- Update `{skills_output_folder}/{skill_name}/metadata.json`:
69
+ Update `{skill_package}/metadata.json`:
67
70
  - Update `version`: if a source version was detected during re-extraction and differs from the current metadata version, use the source version; otherwise increment patch version
68
71
  - Update `generation_date` timestamp to current ISO-8601 date
69
72
  - Update `exports` array to reflect current export list
@@ -81,7 +84,7 @@ Update `{skills_output_folder}/{skill_name}/metadata.json`:
81
84
 
82
85
  ### 3. Write Updated provenance-map.json
83
86
 
84
- Write to `{forge_data_folder}/{skill_name}/provenance-map.json`:
87
+ Write to `{forge_version}/provenance-map.json`:
85
88
 
86
89
  **For each export in the updated skill:**
87
90
  - Update `export_name` if renamed
@@ -117,7 +120,7 @@ Write to `{forge_data_folder}/{skill_name}/provenance-map.json`:
117
120
 
118
121
  ### 4. Write Updated evidence-report.md
119
122
 
120
- Append update operation section to `{forge_data_folder}/{skill_name}/evidence-report.md` (create the file with a standard header if it does not yet exist):
123
+ Append update operation section to `{forge_version}/evidence-report.md` (create the file with a standard header if it does not yet exist):
121
124
 
122
125
  ```markdown
123
126
  ## Update Operation — {current_date}
@@ -146,17 +149,43 @@ Append update operation section to `{forge_data_folder}/{skill_name}/evidence-re
146
149
  - Provenance: {PASS/WARN/FAIL}
147
150
  ```
148
151
 
149
- ### 5. Write Stack Skill Reference Files (Conditional)
152
+ ### 5. Write Stack Skill Reference Files (Conditional) and Regenerate context-snippet.md
150
153
 
151
154
  **ONLY if skill_type == "stack":**
152
155
 
153
156
  For each affected reference file from the merge:
154
157
  - Write updated `references/{library}.md` files
155
158
  - Write updated `references/integrations/{pair}.md` files
156
- - Regenerate `context-snippet.md` with updated export summaries
157
159
  - Verify [MANUAL] sections preserved in each reference file
158
160
 
159
- **If skill_type != "stack":** Skip reference file updates. However, if exports changed (added, removed, or renamed), warn: "⚠️ `context-snippet.md` was NOT updated — exports have changed. Run **[EX] Export Skill** to regenerate the context snippet and update CLAUDE.md/AGENTS.md."
161
+ **For all skills (both single and stack) regenerate `context-snippet.md`:**
162
+
163
+ Per `knowledge/version-paths.md` "Writing Workflows (CS, QS, SS, US)", update-skill is a writing workflow that MUST write all deliverables to `{skill_package}`. `context-snippet.md` is one of those deliverables and goes stale whenever exports, version, or gotchas change.
164
+
165
+ Regenerate the snippet using the format from the matching template file:
166
+
167
+ - For single skills: `create-skill/data/skill-sections.md` (pipe-delimited indexed format)
168
+ - For stack skills: `create-stack-skill/data/stack-skill-template.md`
169
+
170
+ Use the **flat legacy form** for the `root:` path in the draft snippet: `root: skills/{skill-name}/`. The platform-specific prefix (`.claude/skills/`, `.cursor/skills/`, `.agents/skills/`) is applied later by `export-skill` step-03 when the skill is exported. Do not choose a platform prefix in update-skill — that is an export-time decision that depends on config.yaml.
171
+
172
+ Pull values for the regenerated snippet from the updated metadata.json (version, top exports), the merged SKILL.md (section anchors, inline summaries), and the evidence report (new gotchas). If gotchas cannot be derived from the updated evidence but the prior snippet has a `|gotchas:` line, carry forward the prior line with the `[CARRIED]` marker — see `export-skill/steps-c/step-03-generate-snippet.md` for the carry-forward protocol (one-cycle limit).
173
+
174
+ Write the regenerated snippet to `{skill_package}/context-snippet.md`, preserving file permissions.
175
+
176
+ **If skill_type == "stack"**, also verify that the reference file updates from the first half of this section have been applied before writing the snippet so the stack snippet reflects the newest integration list.
177
+
178
+ ### 5b. Update Active Symlink (If Version Changed)
179
+
180
+ If the version was incremented or changed in section 2 (metadata.json update):
181
+ - Create or update the `active` symlink at `{skill_group}/active` pointing to the new `{version}`
182
+ - If the symlink already exists, remove it first and recreate
183
+
184
+ ```
185
+ {skill_group}/active -> {version}
186
+ ```
187
+
188
+ If the version did not change, the existing symlink already points to the correct version -- no action needed.
160
189
 
161
190
  ### 6. Verify All Writes
162
191
 
@@ -183,11 +212,11 @@ For each file written:
183
212
  External tool checks deferred from step-05 now run against the written files:
184
213
 
185
214
  **If skill-check available:**
186
- - Run: `npx skill-check check {skills_output_folder}/{skill_name} --fix --format json --no-security-scan`
215
+ - Run: `npx skill-check check {skill_package} --fix --format json --no-security-scan`
187
216
  - **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. This prevents silent divergence between the in-context SKILL.md and the on-disk version that step-07-report will reference.
188
- - If `body.max_lines` reported, prefer selective split — extract only the largest Tier 2 section(s) to `references/`, keeping Tier 1 inline (inline passive context achieves 100% task accuracy vs 79% for on-demand retrieval). Fall back to `npx skill-check split-body {skills_output_folder}/{skill_name} --write` if not feasible. Verify anchors resolve after split.
217
+ - If `body.max_lines` reported, prefer selective split — extract only the largest Tier 2 section(s) to `references/`, keeping Tier 1 inline (inline passive context achieves 100% task accuracy vs 79% for on-demand retrieval). Fall back to `npx skill-check split-body {skill_package} --write` if not feasible. Verify anchors resolve after split.
189
218
  - Run: `npx skill-check diff` if original version was preserved
190
- - Run: `npx skill-check check {skills_output_folder}/{skill_name} --format json` for security scan
219
+ - Run: `npx skill-check check {skill_package} --format json` for security scan
191
220
 
192
221
  Record findings in the evidence report (section 4). These are advisory — do not block on warnings.
193
222
 
@@ -216,11 +245,12 @@ ONLY WHEN all files have been written and verified will you load {nextStepFile}
216
245
 
217
246
  ### ✅ SUCCESS:
218
247
 
219
- - SKILL.md written with all merged content and [MANUAL] sections intact
248
+ - SKILL.md written to {skill_package} with all merged content and [MANUAL] sections intact
220
249
  - metadata.json updated with new version, timestamp, export counts
221
- - provenance-map.json updated with current file:line references and timestamps
222
- - evidence-report.md appended with update operation record
250
+ - provenance-map.json updated at {forge_version} with current file:line references and timestamps
251
+ - evidence-report.md appended at {forge_version} with update operation record
223
252
  - Stack reference files updated if applicable
253
+ - Active symlink updated at {skill_group}/active -> {version} if version changed
224
254
  - All writes verified by read-back confirmation
225
255
 
226
256
  ### ❌ SYSTEM FAILURE:
@@ -142,11 +142,13 @@ Source code matches provenance map exactly. The skill `{skill_name}` is current
142
142
 
143
143
  | File | Status |
144
144
  |------|--------|
145
- | `{skills_output_folder}/{skill_name}/SKILL.md` | Updated |
146
- | `{skills_output_folder}/{skill_name}/metadata.json` | Updated |
147
- | `{forge_data_folder}/{skill_name}/provenance-map.json` | Updated |
148
- | `{forge_data_folder}/{skill_name}/evidence-report.md` | Appended |
149
- | {stack reference files if applicable} | Updated |"
145
+ | `{resolved_skill_package}/SKILL.md` | Updated |
146
+ | `{resolved_skill_package}/metadata.json` | Updated |
147
+ | `{forge_version}/provenance-map.json` | Updated |
148
+ | `{forge_version}/evidence-report.md` | Appended |
149
+ | {stack reference files if applicable} | Updated |
150
+
151
+ Where `{resolved_skill_package}` = `{skills_output_folder}/{skill_name}/{version}/{skill_name}/` and `{forge_version}` = `{forge_data_folder}/{skill_name}/{version}/` — see [knowledge/version-paths.md](../../../knowledge/version-paths.md)."
150
152
 
151
153
  ### 5. Workflow Chaining Recommendations
152
154
 
@@ -81,9 +81,14 @@ Wait for user input.
81
81
 
82
82
  ### 2. Scan Skills Folder
83
83
 
84
- Read the `{skills_output_folder}` directory.
84
+ Read the `{skills_output_folder}` directory. Skills use a version-nested directory structure (see [knowledge/version-paths.md](../../../knowledge/version-paths.md)).
85
85
 
86
- For each subdirectory, check for the presence of `SKILL.md` and `metadata.json`.
86
+ **Version-aware skill discovery:**
87
+ 1. Read `{skills_output_folder}/.export-manifest.json` if it exists. For each skill in `exports`, use `active_version` to resolve `{skill_package}` = `{skills_output_folder}/{skill-name}/{active_version}/{skill-name}/`
88
+ 2. For any subdirectory not covered by the manifest, check for an `active` symlink at `{skills_output_folder}/{dir_name}/active` — resolve to `{skill_group}/active/{dir_name}/`
89
+ 3. Fall back to flat path `{skills_output_folder}/{dir_name}/` for unmigrated skills
90
+
91
+ For each resolved skill package, check for the presence of `SKILL.md` and `metadata.json`.
87
92
 
88
93
  **For each valid skill directory, extract from metadata.json:**
89
94
  - `name` — skill name
@@ -94,7 +99,7 @@ For each subdirectory, check for the presence of `SKILL.md` and `metadata.json`.
94
99
 
95
100
  **Build a skill inventory** as an internal list of all loaded skills with the fields above.
96
101
 
97
- **If a subdirectory lacks SKILL.md or metadata.json:**
102
+ **If a resolved skill package lacks SKILL.md or metadata.json:**
98
103
  - Log: "Skipping `{dir_name}` — missing SKILL.md or metadata.json"
99
104
  - Do not include in inventory
100
105
 
@@ -238,6 +238,7 @@ class Installer {
238
238
  document_output_language: 'en',
239
239
  skills_output_folder: config.skills_output_folder || 'skills',
240
240
  forge_data_folder: config.forge_data_folder || 'forge-data',
241
+ sidecar_path: '_bmad/_memory/forger-sidecar',
241
242
  skf_folder: config.skfFolder,
242
243
  ides: config.ides || [],
243
244
  };
@@ -15,6 +15,8 @@ const figlet = require('figlet');
15
15
  const path = require('node:path');
16
16
  const fs = require('fs-extra');
17
17
  const yaml = require('js-yaml');
18
+ const { readManifest } = require('./manifest');
19
+ const { compareVersions } = require('./version-check');
18
20
 
19
21
  const SKF_FOLDER = '_bmad/skf';
20
22
 
@@ -94,12 +96,32 @@ class UI {
94
96
  let action = 'fresh';
95
97
 
96
98
  if (detection.type === 'existing') {
97
- log.warn(`Found existing installation at ${chalk.white(SKF_FOLDER + '/')}`);
99
+ const existingManifest = await readManifest(projectDir);
100
+ const installedVersion = existingManifest?.version || null;
101
+ const incomingVersion = require('../../../package.json').version;
102
+
103
+ let versionLabel;
104
+ let updateOptionLabel;
105
+ if (!installedVersion) {
106
+ versionLabel = `version unknown → v${incomingVersion}`;
107
+ updateOptionLabel = `Update — Install v${incomingVersion}, keep config.yaml`;
108
+ } else if (installedVersion === incomingVersion) {
109
+ versionLabel = `v${installedVersion} — already at this version`;
110
+ updateOptionLabel = `Update — Reinstall v${incomingVersion}, keep config.yaml`;
111
+ } else if (compareVersions(installedVersion, incomingVersion)) {
112
+ versionLabel = `v${installedVersion} → v${incomingVersion} available`;
113
+ updateOptionLabel = `Update — Upgrade from v${installedVersion} to v${incomingVersion}, keep config.yaml`;
114
+ } else {
115
+ versionLabel = `v${installedVersion} → v${incomingVersion}, DOWNGRADE`;
116
+ updateOptionLabel = `Update — Downgrade to v${incomingVersion}, keep config.yaml`;
117
+ }
118
+
119
+ log.warn(`Found existing installation at ${chalk.white(SKF_FOLDER + '/')} (${versionLabel})`);
98
120
 
99
121
  const choice = await select({
100
122
  message: 'What would you like to do?',
101
123
  options: [
102
- { label: 'Update — Replace SKF files, keep config.yaml', value: 'update' },
124
+ { label: updateOptionLabel, value: 'update' },
103
125
  { label: 'Fresh install — Remove everything and start over', value: 'fresh' },
104
126
  { label: 'Cancel', value: 'cancel' },
105
127
  ],