bmad-module-skill-forge 1.4.1 → 1.5.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 (230) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/README.md +0 -8
  3. package/docs/_data/pinned.yaml +1 -1
  4. package/docs/_internal/STABILITY.md +1 -1
  5. package/docs/architecture.md +2 -2
  6. package/docs/examples.md +1 -1
  7. package/docs/workflows.md +5 -5
  8. package/package.json +2 -2
  9. package/src/README.md +1 -1
  10. package/src/knowledge/ccc-bridge.md +12 -12
  11. package/src/knowledge/qmd-registry.md +5 -5
  12. package/src/shared/health-check.md +5 -5
  13. package/src/shared/references/description-guard-protocol.md +100 -0
  14. package/src/shared/references/output-contract-schema.md +1 -1
  15. package/src/shared/scripts/schemas/skf-brief-result-envelope.v1.json +6 -6
  16. package/src/shared/scripts/schemas/skf-setup-result-envelope.v1.json +9 -3
  17. package/src/shared/scripts/schemas/skf-update-result-envelope.v1.json +149 -0
  18. package/src/shared/scripts/schemas/skill-brief.v1.json +22 -2
  19. package/src/shared/scripts/skf-build-change-manifest.py +420 -0
  20. package/src/shared/scripts/skf-check-workspace-drift.py +321 -0
  21. package/src/shared/scripts/skf-compare-file-hashes.py +357 -0
  22. package/src/shared/scripts/skf-description-guard.py +359 -0
  23. package/src/shared/scripts/skf-detect-language.py +2 -2
  24. package/src/shared/scripts/skf-detect-scripts-assets.py +613 -0
  25. package/src/shared/scripts/skf-detect-tools.py +97 -8
  26. package/src/shared/scripts/skf-detect-workspaces.py +1 -1
  27. package/src/shared/scripts/skf-disqualify-candidates.py +576 -0
  28. package/src/shared/scripts/skf-emit-brief-result-envelope.py +3 -3
  29. package/src/shared/scripts/skf-emit-result-envelope.py +93 -9
  30. package/src/shared/scripts/skf-enumerate-stack-skills.py +514 -0
  31. package/src/shared/scripts/skf-forge-tier-rw.py +11 -11
  32. package/src/shared/scripts/skf-hash-content.py +284 -0
  33. package/src/shared/scripts/skf-load-provenance.py +295 -0
  34. package/src/shared/scripts/skf-merge-ccc-exclusions.py +34 -4
  35. package/src/shared/scripts/skf-pair-intersect.py +250 -0
  36. package/src/shared/scripts/skf-provenance-gap-dispatch.py +433 -0
  37. package/src/shared/scripts/skf-qmd-classify-collections.py +42 -8
  38. package/src/shared/scripts/skf-recommend-scope-type.py +2 -2
  39. package/src/shared/scripts/skf-render-quick-metadata.py +2 -2
  40. package/src/shared/scripts/skf-resolve-authoritative-files.py +504 -0
  41. package/src/shared/scripts/skf-scan-manifests.py +738 -0
  42. package/src/shared/scripts/skf-scan-skill-md-structure.py +375 -0
  43. package/src/shared/scripts/skf-update-active-symlink.py +315 -0
  44. package/src/shared/scripts/skf-validate-brief-inputs.py +5 -5
  45. package/src/shared/scripts/skf-validate-brief-schema.py +348 -0
  46. package/src/shared/scripts/skf-write-skill-brief.py +61 -5
  47. package/src/skf-analyze-source/SKILL.md +69 -16
  48. package/src/skf-analyze-source/assets/skill-brief-schema.md +1 -1
  49. package/src/skf-analyze-source/customize.toml +55 -0
  50. package/src/skf-analyze-source/{steps-c/step-01b-continue.md → references/continue.md} +12 -12
  51. package/src/skf-analyze-source/{steps-c/step-06-generate-briefs.md → references/generate-briefs.md} +29 -10
  52. package/src/skf-analyze-source/{steps-c/step-07-health-check.md → references/health-check.md} +5 -3
  53. package/src/skf-analyze-source/{steps-c/step-03-identify-units.md → references/identify-units.md} +44 -14
  54. package/src/skf-analyze-source/{steps-c/step-01-init.md → references/init.md} +27 -6
  55. package/src/skf-analyze-source/{steps-c/step-04-map-and-detect.md → references/map-and-detect.md} +52 -25
  56. package/src/skf-analyze-source/{steps-c/step-05-recommend.md → references/recommend.md} +15 -8
  57. package/src/skf-analyze-source/{steps-c/step-02-scan-project.md → references/scan-project.md} +12 -10
  58. package/src/skf-analyze-source/references/unit-detection-heuristics.md +2 -0
  59. package/src/skf-analyze-source/templates/analysis-report-template.md +6 -6
  60. package/src/skf-audit-skill/SKILL.md +66 -15
  61. package/src/skf-audit-skill/assets/drift-report-template.md +6 -5
  62. package/src/skf-audit-skill/customize.toml +49 -0
  63. package/src/skf-audit-skill/{steps-c/step-07-health-check.md → references/health-check.md} +5 -3
  64. package/src/skf-audit-skill/{steps-c/step-01-init.md → references/init.md} +57 -19
  65. package/src/skf-audit-skill/{steps-c/step-02-re-index.md → references/re-index.md} +11 -11
  66. package/src/skf-audit-skill/{steps-c/step-06-report.md → references/report.md} +25 -7
  67. package/src/skf-audit-skill/{steps-c/step-04-semantic-diff.md → references/semantic-diff.md} +6 -6
  68. package/src/skf-audit-skill/{steps-c/step-05-severity-classify.md → references/severity-classify.md} +5 -5
  69. package/src/skf-audit-skill/references/severity-rules.md +2 -0
  70. package/src/skf-audit-skill/{steps-c/step-03-structural-diff.md → references/structural-diff.md} +29 -17
  71. package/src/skf-brief-skill/SKILL.md +48 -18
  72. package/src/skf-brief-skill/assets/description-voice-examples.md +1 -1
  73. package/src/skf-brief-skill/assets/skill-brief-schema.md +32 -2
  74. package/src/skf-brief-skill/customize.toml +44 -0
  75. package/src/skf-brief-skill/{steps-c/step-02-analyze-target.md → references/analyze-target.md} +5 -5
  76. package/src/skf-brief-skill/{steps-c/step-04-confirm-brief.md → references/confirm-brief.md} +13 -10
  77. package/src/skf-brief-skill/references/draft-checkpoint.md +4 -4
  78. package/src/skf-brief-skill/{steps-c/step-01-gather-intent.md → references/gather-intent.md} +24 -24
  79. package/src/skf-brief-skill/references/headless-args.md +9 -9
  80. package/src/skf-brief-skill/references/headless-source-authority-detection.md +1 -1
  81. package/src/skf-brief-skill/{steps-c/step-06-health-check.md → references/health-check.md} +4 -2
  82. package/src/skf-brief-skill/references/portfolio-similarity-check.md +2 -2
  83. package/src/skf-brief-skill/references/qmd-collection-registration.md +1 -1
  84. package/src/skf-brief-skill/{steps-c/step-03-scope-definition.md → references/scope-definition.md} +19 -16
  85. package/src/skf-brief-skill/references/version-resolution.md +2 -2
  86. package/src/skf-brief-skill/{steps-c/step-05-write-brief.md → references/write-brief.md} +11 -10
  87. package/src/skf-create-skill/SKILL.md +25 -19
  88. package/src/skf-create-skill/assets/compile-assembly-rules.md +3 -3
  89. package/src/skf-create-skill/assets/skill-sections.md +5 -5
  90. package/src/skf-create-skill/assets/tessl-dismissal-rules.md +11 -11
  91. package/src/skf-create-skill/customize.toml +35 -0
  92. package/src/skf-create-skill/references/authoritative-files-protocol.md +142 -0
  93. package/src/skf-create-skill/{steps-c/step-05-compile.md → references/compile.md} +16 -16
  94. package/src/skf-create-skill/{steps-c/step-03d-component-extraction.md → references/component-extraction.md} +16 -16
  95. package/src/skf-create-skill/{steps-c/step-02-ecosystem-check.md → references/ecosystem-check.md} +4 -4
  96. package/src/skf-create-skill/{steps-c/step-04-enrich.md → references/enrich.md} +3 -3
  97. package/src/skf-create-skill/{steps-c/step-03-extract.md → references/extract.md} +52 -120
  98. package/src/skf-create-skill/references/extraction-patterns.md +8 -8
  99. package/src/skf-create-skill/{steps-c/step-07-generate-artifacts.md → references/generate-artifacts.md} +11 -11
  100. package/src/skf-create-skill/{steps-c/step-09-health-check.md → references/health-check.md} +4 -2
  101. package/src/skf-create-skill/{steps-c/step-01-load-brief.md → references/load-brief.md} +40 -32
  102. package/src/skf-create-skill/{steps-c/step-08-report.md → references/report.md} +8 -8
  103. package/src/skf-create-skill/references/source-resolution-protocols.md +6 -6
  104. package/src/skf-create-skill/{steps-c/sub/step-02b-ccc-discover.md → references/sub/ccc-discover.md} +5 -5
  105. package/src/skf-create-skill/{steps-c/sub/step-03c-fetch-docs.md → references/sub/fetch-docs.md} +28 -12
  106. package/src/skf-create-skill/{steps-c/sub/step-03b-fetch-temporal.md → references/sub/fetch-temporal.md} +81 -50
  107. package/src/skf-create-skill/{steps-c/step-06-validate.md → references/validate.md} +46 -26
  108. package/src/skf-create-stack-skill/SKILL.md +76 -17
  109. package/src/skf-create-stack-skill/assets/provenance-map-schema.md +102 -0
  110. package/src/skf-create-stack-skill/assets/stack-skill-template.md +1 -1
  111. package/src/skf-create-stack-skill/customize.toml +46 -0
  112. package/src/skf-create-stack-skill/{steps-c/step-06-compile-stack.md → references/compile-stack.md} +6 -5
  113. package/src/skf-create-stack-skill/references/compose-mode-rules.md +3 -1
  114. package/src/skf-create-stack-skill/{steps-c/step-05-detect-integrations.md → references/detect-integrations.md} +32 -11
  115. package/src/skf-create-stack-skill/{steps-c/step-02-detect-manifests.md → references/detect-manifests.md} +28 -28
  116. package/src/skf-create-stack-skill/{steps-c/step-07-generate-output.md → references/generate-output.md} +11 -85
  117. package/src/skf-create-stack-skill/{steps-c/step-10-health-check.md → references/health-check.md} +4 -2
  118. package/src/skf-create-stack-skill/{steps-c/step-01-init.md → references/init.md} +70 -4
  119. package/src/skf-create-stack-skill/references/integration-patterns.md +2 -0
  120. package/src/skf-create-stack-skill/references/manifest-patterns.md +2 -0
  121. package/src/skf-create-stack-skill/{steps-c/step-04-parallel-extract.md → references/parallel-extract.md} +40 -17
  122. package/src/skf-create-stack-skill/{steps-c/step-03-rank-and-confirm.md → references/rank-and-confirm.md} +5 -4
  123. package/src/skf-create-stack-skill/{steps-c/step-09-report.md → references/report.md} +3 -3
  124. package/src/skf-create-stack-skill/{steps-c/step-08-validate.md → references/validate.md} +6 -6
  125. package/src/skf-drop-skill/SKILL.md +84 -12
  126. package/src/skf-drop-skill/customize.toml +57 -0
  127. package/src/skf-drop-skill/{steps-c/step-02-execute.md → references/execute.md} +49 -34
  128. package/src/skf-drop-skill/{steps-c/step-04-health-check.md → references/health-check.md} +6 -4
  129. package/src/skf-drop-skill/{steps-c/step-03-report.md → references/report.md} +13 -5
  130. package/src/skf-drop-skill/{steps-c/step-01-select.md → references/select.md} +63 -15
  131. package/src/skf-export-skill/SKILL.md +85 -16
  132. package/src/skf-export-skill/assets/managed-section-format.md +3 -3
  133. package/src/skf-export-skill/assets/snippet-format.md +2 -2
  134. package/src/skf-export-skill/customize.toml +49 -0
  135. package/src/skf-export-skill/{steps-c/step-03-generate-snippet.md → references/generate-snippet.md} +11 -11
  136. package/src/skf-export-skill/{steps-c/step-07-health-check.md → references/health-check.md} +6 -4
  137. package/src/skf-export-skill/{steps-c/step-01-load-skill.md → references/load-skill.md} +11 -49
  138. package/src/skf-export-skill/references/manifest-rebuild.md +68 -0
  139. package/src/skf-export-skill/references/multi-skill-mode.md +38 -0
  140. package/src/skf-export-skill/references/orphan-context-detection.md +75 -0
  141. package/src/skf-export-skill/references/orphan-row-detection.md +102 -0
  142. package/src/skf-export-skill/{steps-c/step-02-package.md → references/package.md} +7 -7
  143. package/src/skf-export-skill/references/preflight-snippet-root-probe.md +74 -0
  144. package/src/skf-export-skill/{steps-c/step-06-summary.md → references/summary.md} +20 -8
  145. package/src/skf-export-skill/{steps-c/step-05-token-report.md → references/token-report.md} +5 -5
  146. package/src/skf-export-skill/{steps-c/step-04-update-context.md → references/update-context.md} +109 -113
  147. package/src/skf-quick-skill/SKILL.md +63 -123
  148. package/src/skf-quick-skill/customize.toml +44 -0
  149. package/src/skf-quick-skill/references/batch-mode.md +102 -0
  150. package/src/skf-quick-skill/{steps-c/step-04-compile.md → references/compile.md} +10 -10
  151. package/src/skf-quick-skill/{steps-c/step-02-ecosystem-check.md → references/ecosystem-check.md} +5 -5
  152. package/src/skf-quick-skill/{steps-c/step-06-finalize.md → references/finalize.md} +7 -7
  153. package/src/skf-quick-skill/{steps-c/step-07-health-check.md → references/health-check.md} +3 -3
  154. package/src/skf-quick-skill/{steps-c/step-03-quick-extract.md → references/quick-extract.md} +5 -5
  155. package/src/skf-quick-skill/references/registry-resolution.md +2 -0
  156. package/src/skf-quick-skill/{steps-c/step-01-resolve-target.md → references/resolve-target.md} +14 -10
  157. package/src/skf-quick-skill/{steps-c/step-05-write-and-validate.md → references/write-and-validate.md} +4 -4
  158. package/src/skf-refine-architecture/SKILL.md +86 -16
  159. package/src/skf-refine-architecture/customize.toml +49 -0
  160. package/src/skf-refine-architecture/{steps-c/step-05-compile.md → references/compile.md} +4 -4
  161. package/src/skf-refine-architecture/{steps-c/step-02-gap-analysis.md → references/gap-analysis.md} +5 -5
  162. package/src/skf-refine-architecture/{steps-c/step-07-health-check.md → references/health-check.md} +6 -4
  163. package/src/skf-refine-architecture/{steps-c/step-04-improvements.md → references/improvements.md} +5 -5
  164. package/src/skf-refine-architecture/references/init.md +144 -0
  165. package/src/skf-refine-architecture/{steps-c/step-03-issue-detection.md → references/issue-detection.md} +5 -5
  166. package/src/skf-refine-architecture/references/refinement-rules.md +2 -0
  167. package/src/skf-refine-architecture/{steps-c/step-06-report.md → references/report.md} +14 -5
  168. package/src/skf-rename-skill/SKILL.md +82 -12
  169. package/src/skf-rename-skill/customize.toml +52 -0
  170. package/src/skf-rename-skill/{steps-c/step-02-execute.md → references/execute.md} +94 -99
  171. package/src/skf-rename-skill/references/health-check.md +30 -0
  172. package/src/skf-rename-skill/references/rebuild-context.md +110 -0
  173. package/src/skf-rename-skill/{steps-c/step-03-report.md → references/report.md} +13 -5
  174. package/src/skf-rename-skill/{steps-c/step-01-select.md → references/select.md} +59 -20
  175. package/src/skf-setup/SKILL.md +35 -35
  176. package/src/skf-setup/customize.toml +33 -0
  177. package/src/skf-setup/{steps-c/step-03-auto-index.md → references/auto-index.md} +10 -18
  178. package/src/skf-setup/{steps-c/step-01b-ccc-index.md → references/ccc-index.md} +16 -31
  179. package/src/skf-setup/{steps-c/step-01-detect-and-tier.md → references/detect-and-tier.md} +23 -10
  180. package/src/skf-setup/{steps-c/step-05-health-check.md → references/health-check.md} +1 -1
  181. package/src/skf-setup/{steps-c/step-04-report.md → references/report.md} +21 -19
  182. package/src/skf-setup/references/tier-rules.md +1 -1
  183. package/src/skf-setup/{steps-c/step-02-write-config.md → references/write-config.md} +14 -13
  184. package/src/skf-test-skill/SKILL.md +77 -15
  185. package/src/skf-test-skill/customize.toml +54 -0
  186. package/src/skf-test-skill/{steps-c/step-04-coherence-check.md → references/coherence-check.md} +28 -71
  187. package/src/skf-test-skill/{steps-c/step-03-coverage-check.md → references/coverage-check.md} +16 -39
  188. package/src/skf-test-skill/{steps-c/step-02-detect-mode.md → references/detect-mode.md} +4 -26
  189. package/src/skf-test-skill/{steps-c/step-04b-external-validators.md → references/external-validators.md} +6 -28
  190. package/src/skf-test-skill/references/health-check.md +14 -0
  191. package/src/skf-test-skill/{steps-c/step-01-init.md → references/init.md} +21 -37
  192. package/src/skf-test-skill/references/migration-section-rules.md +4 -2
  193. package/src/skf-test-skill/{steps-c/step-06-report.md → references/report.md} +41 -51
  194. package/src/skf-test-skill/{steps-c/step-05-score.md → references/score.md} +26 -43
  195. package/src/skf-test-skill/references/scoring-rules.md +8 -6
  196. package/src/skf-test-skill/references/source-access-protocol.md +7 -5
  197. package/src/skf-test-skill/scripts/compute-score.py +88 -17
  198. package/src/skf-test-skill/templates/test-report-template.md +13 -13
  199. package/src/skf-update-skill/SKILL.md +23 -14
  200. package/src/skf-update-skill/customize.toml +44 -0
  201. package/src/skf-update-skill/{steps-c/step-02-detect-changes.md → references/detect-changes.md} +176 -68
  202. package/src/skf-update-skill/references/health-check.md +32 -0
  203. package/src/skf-update-skill/{steps-c/step-01-init.md → references/init.md} +56 -8
  204. package/src/skf-update-skill/references/manual-section-rules.md +4 -0
  205. package/src/skf-update-skill/references/merge-conflict-rules.md +4 -0
  206. package/src/skf-update-skill/{steps-c/step-04-merge.md → references/merge.md} +8 -8
  207. package/src/skf-update-skill/{steps-c/step-03-re-extract.md → references/re-extract.md} +53 -44
  208. package/src/skf-update-skill/references/remote-source-resolution.md +5 -1
  209. package/src/skf-update-skill/references/report.md +214 -0
  210. package/src/skf-update-skill/{steps-c/step-05-validate.md → references/validate.md} +5 -5
  211. package/src/skf-update-skill/{steps-c/step-06-write.md → references/write.md} +73 -51
  212. package/src/skf-verify-stack/SKILL.md +89 -17
  213. package/src/skf-verify-stack/assets/feasibility-report-template.md +4 -4
  214. package/src/skf-verify-stack/customize.toml +50 -0
  215. package/src/skf-verify-stack/references/coverage-patterns.md +2 -2
  216. package/src/skf-verify-stack/{steps-c/step-02-coverage.md → references/coverage.md} +7 -7
  217. package/src/skf-verify-stack/{steps-c/step-07-health-check.md → references/health-check.md} +7 -5
  218. package/src/skf-verify-stack/references/init.md +166 -0
  219. package/src/skf-verify-stack/references/integration-verification-rules.md +1 -1
  220. package/src/skf-verify-stack/{steps-c/step-03-integrations.md → references/integrations.md} +12 -12
  221. package/src/skf-verify-stack/{steps-c/step-06-report.md → references/report.md} +22 -41
  222. package/src/skf-verify-stack/{steps-c/step-04-requirements.md → references/requirements.md} +7 -7
  223. package/src/skf-verify-stack/{steps-c/step-05-synthesize.md → references/synthesize.md} +8 -8
  224. package/tools/validate-docs-drift.js +1 -1
  225. package/src/skf-refine-architecture/steps-c/step-01-init.md +0 -136
  226. package/src/skf-rename-skill/steps-c/step-04-health-check.md +0 -22
  227. package/src/skf-test-skill/steps-c/step-07-health-check.md +0 -25
  228. package/src/skf-update-skill/steps-c/step-07-report.md +0 -148
  229. package/src/skf-update-skill/steps-c/step-08-health-check.md +0 -22
  230. package/src/skf-verify-stack/steps-c/step-01-init.md +0 -178
@@ -1,7 +1,9 @@
1
1
  ---
2
- nextStepFile: './step-06-write.md'
2
+ nextStepFile: 'write.md'
3
3
  ---
4
4
 
5
+ <!-- Config: communicate in {communication_language}. -->
6
+
5
7
  # Step 5: Validate
6
8
 
7
9
  ## STEP GOAL:
@@ -16,8 +18,6 @@ Validate the merged skill content against the agentskills.io specification, veri
16
18
 
17
19
  ## MANDATORY SEQUENCE
18
20
 
19
- **CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise unless user explicitly requests a change.
20
-
21
21
  ### 1. Check Tool Availability and Validation Timing
22
22
 
23
23
  Run: `npx skill-check -h`
@@ -27,7 +27,7 @@ Run: `npx skill-check -h`
27
27
 
28
28
  **Important:** Do not assume availability — empirical check required.
29
29
 
30
- **Validation timing note:** Step-04 section 6b has already written SKILL.md (and stack reference files) to disk. External-tool checks against written files (skill-check Checks A, E, F) still run in **step-06 section 7** to co-locate external-tool validation with post-write verification. Structural checks (B, C, D) run here against the merged content — content on disk is byte-identical to the in-context copy.
30
+ **Validation timing note:** Step-04 section 6b has already written SKILL.md (and stack reference files) to disk. External-tool checks against written files (skill-check Checks A, E, F) still run in **step 6 section 7** to co-locate external-tool validation with post-write verification. Structural checks (B, C, D) run here against the merged content — content on disk is byte-identical to the in-context copy.
31
31
 
32
32
  ### 2. Launch Parallel Validation Checks
33
33
 
@@ -35,7 +35,7 @@ Launch subprocesses in parallel for each validation category, aggregating result
35
35
 
36
36
  **Check A — Spec Compliance (deferred to post-write):**
37
37
 
38
- Skill-check requires written files on disk. This check is deferred to step-06 section 7. Perform manual structural check only: verify merged SKILL.md has required sections (exports, usage patterns, conventions), verify export entries have name/type/signature/file:line reference, flag missing sections.
38
+ Skill-check requires written files on disk. This check is deferred to step 6 section 7. Perform manual structural check only: verify merged SKILL.md has required sections (exports, usage patterns, conventions), verify export entries have name/type/signature/file:line reference, flag missing sections.
39
39
 
40
40
  **Check B — [MANUAL] Section Integrity:**
41
41
  - Compare [MANUAL] inventory from step 01 against merged content
@@ -1,64 +1,65 @@
1
1
  ---
2
- nextStepFile: './step-07-report.md'
2
+ nextStepFile: 'report.md'
3
+ descriptionGuardProtocol: '{project-root}/src/shared/references/description-guard-protocol.md'
4
+ # Resolve `{descriptionGuardHelper}` by probing `{descriptionGuardProbeOrder}`
5
+ # in order (installed SKF module path first, src/ dev-checkout fallback);
6
+ # first existing path wins. HALT if neither resolves — letting an external
7
+ # tool's rewrite of the merged description field stand would silently
8
+ # regress discovery quality and re-introduce angle-bracket tokens.
9
+ descriptionGuardProbeOrder:
10
+ - '{project-root}/_bmad/skf/shared/scripts/skf-description-guard.py'
11
+ - '{project-root}/src/shared/scripts/skf-description-guard.py'
12
+ # Resolve `{updateActiveSymlinkHelper}` to the first existing path; HALT if
13
+ # neither candidate exists. §5b uses it to atomically flip the active
14
+ # symlink; §6 uses it (verify mode) to confirm the post-state. Without
15
+ # the helper, §5b's "rm and recreate" pattern leaves a brief window where
16
+ # concurrent readers see a missing symlink.
17
+ updateActiveSymlinkProbeOrder:
18
+ - '{project-root}/_bmad/skf/shared/scripts/skf-update-active-symlink.py'
19
+ - '{project-root}/src/shared/scripts/skf-update-active-symlink.py'
3
20
  ---
4
21
 
22
+ <!-- Config: communicate in {communication_language}. -->
23
+
5
24
  # Step 6: Write Updated Files
6
25
 
7
26
  ## STEP GOAL:
8
27
 
9
- Verify the merged SKILL.md and stack reference files that step-04 section 6b wrote to disk, then write the derived artifacts (metadata.json, provenance-map.json, evidence-report.md, context-snippet.md, and the active symlink).
28
+ Verify the merged SKILL.md and stack reference files that step 4 section 6b wrote to disk, then write the derived artifacts (metadata.json, provenance-map.json, evidence-report.md, context-snippet.md, and the active symlink).
10
29
 
11
30
  ## Rules
12
31
 
13
- - Focus only on verifying merged files and writing derived artifacts — merge content was already written in step-04
32
+ - Focus only on verifying merged files and writing derived artifacts — merge content was already written in step 4
14
33
  - Do not modify merged SKILL.md content — any mismatch detected during verification triggers HALT, not repair
15
34
  - Do not skip provenance map update — critical for future audits
16
35
  - HALT immediately on verification failure before writing any derived artifact — a partial-write skill package is worse than an unchanged one
17
36
 
18
37
  ## MANDATORY SEQUENCE
19
38
 
20
- **CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise unless user explicitly requests a change.
21
-
22
39
  ### 0. Description Guard Protocol
23
40
 
24
41
  **Used by:** §7 (`skill-check check --fix` and `skill-check split-body --write`), and any future tool invocation that may modify SKILL.md's frontmatter on disk.
25
42
 
26
- External validators occasionally rewrite the frontmatter `description` field `skill-check --fix` may replace it with a generic or truncated version, and `split-body` may touch it during mechanical restructuring. The merged description written to disk in step-04 is **authoritative**: it reflects the final merge of the prior skill's description (with any author edits preserved) and fresh re-extraction results. Losing it to a tool's well-meaning rewrite breaks discovery quality and — if the prior skill was compiled from a sanitized description (step-05 §2a) — can re-introduce angle-bracket tokens that then fail tessl on the next run.
27
-
28
- To prevent this, any tool invocation in §7 that may touch SKILL.md must run inside the following four-phase guard:
29
-
30
- 1. **Capture.** Before invoking the tool, read `{skill_package}/SKILL.md` frontmatter and snapshot the exact `description` value into a local variable (e.g., `guarded_description`). Capture the in-context copy as well.
31
- 2. **Execute.** Run the tool as specified in its section.
32
- 3. **Verify.** After the tool completes, re-read the on-disk SKILL.md and compare its frontmatter `description` against `guarded_description`. Normalize whitespace for comparison (trim leading/trailing whitespace, collapse internal runs) but do not ignore content differences.
33
- 4. **Restore on divergence.** If the post-tool description differs from `guarded_description` in any way other than whitespace normalization, write `guarded_description` back to the on-disk SKILL.md frontmatter and update the in-context copy to match. Record `description_guard_restored: true` with the tool name in context for the evidence report.
43
+ Load `{descriptionGuardProtocol}` for the full prose explanation of the four-phase guard (why it exists, what counts as divergence, why token-stream comparison is the right shape). The deterministic phases are executed via `{descriptionGuardHelper}` §7 invokes the helper at the capture and verify-restore points around every `skill-check` call.
34
44
 
35
- **What counts as divergence:**
36
-
37
- - The description was replaced (different content).
38
- - The description was truncated (suffix missing).
39
- - Angle-bracket tokens were re-introduced (should never happen if the prior skill was correctly sanitized, but protect anyway).
40
- - The field was deleted entirely (extreme tool behavior).
41
-
42
- **What does NOT count as divergence:** whitespace-only differences (trailing newline, trimmed spaces) — treat as equivalent.
43
-
44
- **Why this lives in update-skill too:** the guard protocol was first introduced in `skf-create-skill/step-06-validate.md §0` to defend the freshly-compiled description. Update-skill runs the identical `skill-check check --fix` command against the merged skill package in §7, so it faces the same risk and needs the same defense. Keep the two §0 protocols functionally identical — if external tool behavior changes, update both workflows.
45
+ Update-skill does not run the optional post-restore frontmatter re-validation today — the post-write checks in §1 catch downstream issues, and a `restored: true` outcome is already surfaced through the evidence report (§4).
45
46
 
46
47
  ### 1. Verify SKILL.md Write
47
48
 
48
- SKILL.md was written in step-04 section 6b. Verify the write landed intact before proceeding to any derived-artifact writes.
49
+ SKILL.md was written in step 4 section 6b. Verify the write landed intact before proceeding to any derived-artifact writes.
49
50
 
50
51
  - Read `{skill_package}/SKILL.md` from disk
51
- - Count `<!-- [MANUAL:*] -->` opening markers and compare against the [MANUAL] inventory captured in step-01
52
- - Verify the resolved `{skill_package}` path matches the version directory step-04 wrote to (if the version changed, step-04 updated `{skill_package}` in context to point at the new path)
52
+ - Count `<!-- [MANUAL:*] -->` opening markers and compare against the [MANUAL] inventory captured in step 1
53
+ - Verify the resolved `{skill_package}` path matches the version directory step 4 wrote to (if the version changed, step 4 updated `{skill_package}` in context to point at the new path)
53
54
  - If [MANUAL] count matches and path resolves: proceed to section 2
54
55
  - **If [MANUAL] count does not match: HALT immediately.** Do not write `metadata.json`, `provenance-map.json`, or any other artifact — further writes would compound the inconsistency. Alert the user:
55
56
 
56
- "**[MANUAL] section count mismatch after write.** Expected {N} from step-01 inventory, found {M} on disk at `{skill_package}/SKILL.md`. The skill package is in an inconsistent state. Manual recovery required — restore the previous version from `{skill_group}/{previous_version}/` or fix the file in place, then re-run update-skill."
57
+ "**[MANUAL] section count mismatch after write.** Expected {N} from step 1 inventory, found {M} on disk at `{skill_package}/SKILL.md`. The skill package is in an inconsistent state. Manual recovery required — restore the previous version from `{skill_group}/{previous_version}/` or fix the file in place, then re-run update-skill."
57
58
 
58
59
  ### 2. Write Updated metadata.json
59
60
 
60
61
  Update `{skill_package}/metadata.json`:
61
- - Update `version`: **if `update_mode == "gap-driven"`, do not bump — the skill is being repaired against the same source commit, so leave `version` unchanged and update only `generation_date` / `last_update` below.** This keeps metadata `version` consistent with the on-disk `{skill_package}` path, which step-04 §6b also leaves unchanged in gap-driven mode (see step-04 §6b's "If the source version detected during step-03 differs..." carve-out — in gap-driven mode no source version is detected, so step-04 writes into the existing version directory). Otherwise, if a source version was detected during re-extraction and differs from the current metadata version, use the source version; otherwise increment patch version
62
+ - Update `version`: **if `update_mode == "gap-driven"`, do not bump — the skill is being repaired against the same source commit, so leave `version` unchanged and update only `generation_date` / `last_update` below.** This keeps metadata `version` consistent with the on-disk `{skill_package}` path, which step 4 §6b also leaves unchanged in gap-driven mode (see step 4 §6b's "If the source version detected during step 3 differs..." carve-out — in gap-driven mode no source version is detected, so step 4 writes into the existing version directory). Otherwise, if a source version was detected during re-extraction and differs from the current metadata version, use the source version; otherwise increment patch version
62
63
  - Update `generation_date` timestamp to current ISO-8601 date
63
64
  - Update `exports` array to reflect current export list
64
65
  - Update `stats` from re-extraction results:
@@ -77,13 +78,13 @@ Update `{skill_package}/metadata.json`:
77
78
 
78
79
  Write to `{forge_version}/provenance-map.json`:
79
80
 
80
- **If `no_reextraction == true` (gap-driven mode from step-03 section 0):**
81
- Dispatch per-entry on the verification outcome recorded by step-03 — gap-driven runs produce a mix of `verified`, `moved`, `re-extracted`, and `unknown` outcomes, and each requires a different provenance-map write strategy:
81
+ **If `no_reextraction == true` (gap-driven mode from step 3 section 0):**
82
+ Dispatch per-entry on the verification outcome recorded by step 3 — gap-driven runs produce a mix of `verified`, `moved`, `re-extracted`, and `unknown` outcomes, and each requires a different provenance-map write strategy:
82
83
 
83
84
  - **`verified` exports**: no fresh extraction data exists — do NOT overwrite `confidence`, `extraction_method`, `ast_node_type`, `params[]`, `return_type`, `source_file`, or `source_line`. The provenance entry stays byte-identical.
84
85
  - **`moved` exports**: update `source_line` (and `source_file` if different) to the new location recorded by the spot-check. Do not touch other fields.
85
- - **`re-extracted` exports** (resolved via step-03 §0a's Targeted Re-Extraction Branch from `remediation_paths[]`): write a full entry — `source_file`, `source_line`, `confidence`, `extraction_method`, `ast_node_type`, `params[]`, `return_type` — from §0a's fresh AST extraction record. This is the only gap-driven outcome that produces normal-mode-quality provenance; do NOT fall through to the byte-identical preservation above.
86
- - **`unknown` exports** (not in provenance map; no `source_citation`; `severity` is `Medium`, `Low`, or `Info`, OR `remediation_paths[]` was empty and §0a did not halt): add new entries with fields populated from step-04 merge output. `source_file`/`source_line` may be `null` here — leave these fields unset rather than writing stale values. **This path is only acceptable for `severity` in `Medium`, `Low`, or `Info`.** A Critical/High `unknown` reaching this branch indicates step-03 §0a was skipped or bypassed and is a workflow bug — step-03 §0a should have halted with status `halted-for-remediation-path` before step-06 ran. If you encounter one, halt with a pointer to §0a rather than writing null citations for a blocking gap.
86
+ - **`re-extracted` exports** (resolved via step 3 §0a's Targeted Re-Extraction Branch from `remediation_paths[]`): write a full entry — `source_file`, `source_line`, `confidence`, `extraction_method`, `ast_node_type`, `params[]`, `return_type` — from §0a's fresh AST extraction record. This is the only gap-driven outcome that produces normal-mode-quality provenance; do NOT fall through to the byte-identical preservation above.
87
+ - **`unknown` exports** (not in provenance map; no `source_citation`; `severity` is `Medium`, `Low`, or `Info`, OR `remediation_paths[]` was empty and §0a did not halt): add new entries with fields populated from step 4 merge output. `source_file`/`source_line` may be `null` here — leave these fields unset rather than writing stale values. **This path is only acceptable for `severity` in `Medium`, `Low`, or `Info`.** A Critical/High `unknown` reaching this branch indicates step 3 §0a was skipped or bypassed and is a workflow bug — step 3 §0a should have halted with status `halted-for-remediation-path` before step 6 ran. If you encounter one, halt with a pointer to §0a rather than writing null citations for a blocking gap.
87
88
  - Skip the "For each export in the updated skill" bullets below — they apply only to normal re-extraction mode.
88
89
 
89
90
  **For each export in the updated skill (normal mode only):**
@@ -160,7 +161,7 @@ Append update operation section to `{forge_version}/evidence-report.md` (create
160
161
  - Notes: {one-sentence detail or —}
161
162
  ```
162
163
 
163
- **Description Guard population** (used by §7 Post-Write Validation when the §0 protocol fires): fill all four fields from context when `description_guard_restored == true` (triggering tool, whether restore succeeded, what changed). When `Restored: false`, the other three fields are `—` — this is the clean-run expected state. Same field semantics and populator logic as create-skill step-06 §8.
164
+ **Description Guard population** (used by §7 Post-Write Validation when the §0 protocol fires): fill all four fields from context when `description_guard_restored == true` (triggering tool, whether restore succeeded, what changed). When `Restored: false`, the other three fields are `—` — this is the clean-run expected state. Same field semantics and populator logic as create-skill step 6 §8.
164
165
 
165
166
  **Context Snippet population** (used by §5 after the staleness check runs): §4 writes the sub-block with placeholders; §5 updates the on-disk evidence report in place after deciding whether to regenerate. Set `Regenerated: true` and populate `Triggers fired` with any combination of `headline-exports`, `version`, `gotchas` when at least one trigger fired. Set `Regenerated: false` and `Triggers fired: —` when none fired (the gap-driven / internals-only outcome). Always fill `Notes` with a one-sentence reason (e.g., `"Gap-driven repair — no snippet surface changed"`, `"Version bumped 0.1.0 → 0.2.0; headline exports re-ranked"`).
166
167
 
@@ -168,11 +169,11 @@ Append update operation section to `{forge_version}/evidence-report.md` (create
168
169
 
169
170
  **ONLY if skill_type == "stack":**
170
171
 
171
- Stack reference files were written in step-04 section 6b. Verify each affected reference file that the merge produced:
172
+ Stack reference files were written in step 4 section 6b. Verify each affected reference file that the merge produced:
172
173
 
173
174
  - Read each `references/{library}.md` back from disk
174
175
  - Read each `references/integrations/{pair}.md` back from disk
175
- - Verify per-file [MANUAL] section counts match the per-file inventory captured in step-01
176
+ - Verify per-file [MANUAL] section counts match the per-file inventory captured in step 1
176
177
  - **If any verification fails: HALT** using the same recovery protocol as section 1 — do not regenerate `context-snippet.md` or write any further derived artifact
177
178
 
178
179
  **For all skills (both single and stack) — regenerate `context-snippet.md` if stale:**
@@ -194,36 +195,43 @@ Stack reference files were written in step-04 section 6b. Verify each affected r
194
195
  - For single skills: `skf-create-skill/assets/skill-sections.md` (pipe-delimited indexed format)
195
196
  - For stack skills: `skf-create-stack-skill/assets/stack-skill-template.md`
196
197
 
197
- Use the **flat draft form** for the `root:` path in the draft snippet: `root: skills/{skill-name}/`. The per-IDE skill root (e.g., `.claude/skills/`, `.windsurf/skills/`, `.github/skills/` — see `skf-export-skill/assets/managed-section-format.md`) is applied later by `export-skill` step-03 when the skill is exported. Do not choose an IDE-specific prefix in update-skill — that is an export-time decision that depends on config.yaml.
198
+ Use the **flat draft form** for the `root:` path in the draft snippet: `root: skills/{skill-name}/`. The per-IDE skill root (e.g., `.claude/skills/`, `.windsurf/skills/`, `.github/skills/` — see `skf-export-skill/assets/managed-section-format.md`) is applied later by `export-skill` step 3 when the skill is exported. Do not choose an IDE-specific prefix in update-skill — that is an export-time decision that depends on config.yaml.
198
199
 
199
- 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 `skf-export-skill/steps-c/step-03-generate-snippet.md` for the carry-forward protocol (one-cycle limit).
200
+ 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 `skf-export-skill/references/generate-snippet.md` for the carry-forward protocol (one-cycle limit).
200
201
 
201
202
  Write the regenerated snippet to `{skill_package}/context-snippet.md`, preserving file permissions.
202
203
 
203
204
  **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.
204
205
 
205
- ### 5b. Update Active Symlink (If Version Changed)
206
+ ### 5b. Update Active Symlink
206
207
 
207
- If the version was incremented or changed in section 2 (metadata.json update):
208
- - Create or update the `active` symlink at `{skill_group}/active` pointing to the new `{version}`
209
- - If the symlink already exists, remove it first and recreate
208
+ Flip `{skill_group}/active` to point at the current `{version}` via the helper. The call is **always** run — atomic, idempotent, and verified in one shot. The helper's no-op path handles the "version did not change" case (gap-driven mode, or no source drift) without writing to disk:
210
209
 
211
- ```
212
- {skill_group}/active -> {version}
210
+ ```bash
211
+ uv run {updateActiveSymlinkHelper} update \
212
+ --skill-group {skill_group} \
213
+ --version {version}
213
214
  ```
214
215
 
215
- If the version did not change, the existing symlink already points to the correct version -- no action needed.
216
+ The helper emits a result envelope with `status` ∈ `{ok, flipped, mismatch, missing-target}` and a pre-formatted `log_message`. Log the message to the evidence report.
217
+
218
+ **Dispatch on `status`:**
219
+
220
+ - **`ok`** (exit 0): symlink already points at `{version}` — no disk write. Continue to §6.
221
+ - **`flipped`** (exit 0): symlink was atomically updated (temp-and-replace). Continue to §6.
222
+ - **`missing-target`** (exit 2): `{skill_group}/{version}/` directory does not exist on disk. HALT — display `halt_message` verbatim. This indicates §4 §6b did not write the version directory before §5b ran (a workflow bug, not a user error).
223
+ - **`mismatch`** (exit 2): re-read after flip showed the symlink still points elsewhere. HALT — display `halt_message`. Should be impossible because the helper uses `os.replace` (atomic rename); a mismatch here indicates filesystem-level interference (concurrent writer, broken FUSE mount).
216
224
 
217
225
  ### 6. Verify Derived Artifact Writes
218
226
 
219
- SKILL.md was verified in section 1 and stack reference files in section 5 (both written by step-04 section 6b). This section verifies the artifacts this step wrote: `metadata.json`, `provenance-map.json`, `evidence-report.md`, `context-snippet.md`, and the `active` symlink from §5b.
227
+ SKILL.md was verified in section 1 and stack reference files in section 5 (both written by step 4 section 6b). This section verifies the artifacts this step wrote: `metadata.json`, `provenance-map.json`, `evidence-report.md`, `context-snippet.md`, and the `active` symlink from §5b.
220
228
 
221
229
  For each derived artifact:
222
230
  - Read back the file
223
231
  - Confirm content matches expected output
224
232
  - Report verification status
225
233
 
226
- **Active symlink verification:** resolve `readlink({skill_group}/active)` and assert it equals the `version` just written to `metadata.json` in §2. This closes the §5b gap where a silent skip would otherwise leave the manifest and symlink divergent — the symlink is the fallback resolver for consumers that don't read the manifest (see `knowledge/version-paths.md` §Reading Workflows step 5), so a mismatch must fail the step, not warn. Applies in every mode — gap-driven runs do not bump `version`, but the symlink must still point to the current `version`, otherwise a prior partial run left it pointing elsewhere.
234
+ **Active symlink verification:** run `{updateActiveSymlinkHelper} verify --skill-group {skill_group} --version {version}` read-only check that the symlink resolves to the version just written to `metadata.json` in §2. This closes the §5b gap where a silent skip would otherwise leave the manifest and symlink divergent — the symlink is the fallback resolver for consumers that don't read the manifest (see `knowledge/version-paths.md` §Reading Workflows step 5), so a `mismatch` must fail the step, not warn. Applies in every mode — gap-driven runs do not bump `version`, but the symlink must still point to the current `version`, otherwise a prior partial run left it pointing elsewhere.
227
235
 
228
236
  "**Write Verification:**
229
237
 
@@ -237,27 +245,41 @@ For each derived artifact:
237
245
  | {skill_group}/active symlink | {VERIFIED/FAILED} (readlink → {resolved_version}, expected {version}) |
238
246
  | {stack reference files...} | {VERIFIED in section 5} |
239
247
 
240
- **On symlink FAILED:** HALT. Do not proceed to §7 post-write validation or §8 menu. Alert the user: "**Active symlink divergence.** `{skill_group}/active` resolves to `{resolved_version}` but `metadata.json` reports `version: {version}`. §5b did not apply. Re-point the symlink manually (`ln -sfn {version} {skill_group}/active`) or re-run update-skill, then re-verify." This matches the severity of the other four artifact checks — silent divergence here mis-routes any downstream consumer that uses the symlink fallback.
248
+ **On symlink `mismatch` (helper exit 2):** HALT. Do not proceed to §7 post-write validation or §8 menu. Display the helper's `halt_message` verbatim it already includes the diverged target, the expected version, and the recovery command. This matches the severity of the other four artifact checks — silent divergence here mis-routes any downstream consumer that uses the symlink fallback.
241
249
 
242
250
  **All files written and verified.**"
243
251
 
244
252
  ### 7. Run Post-Write Validation (Deferred from Step 05)
245
253
 
246
- External tool checks deferred from step-05 now run against the written files.
254
+ External tool checks deferred from step 5 now run against the written files.
255
+
256
+ **Description Guard Protocol:** every invocation below that may modify SKILL.md (`skill-check check --fix` and any `split-body` write) must run inside the four-phase guard defined in §0. Invoke `{descriptionGuardHelper}` at the capture and verify-restore points around each call:
257
+
258
+ ```bash
259
+ # Phase 1 — capture before any frontmatter-touching tool call
260
+ uv run {descriptionGuardHelper} capture {skill_package}/SKILL.md
261
+ # stash returned `description` as `guarded_description`
262
+
263
+ # Phase 2 — run the tool (skill-check --fix, split-body --write, etc.)
264
+
265
+ # Phases 3+4 — verify and restore after the tool call
266
+ uv run {descriptionGuardHelper} verify-restore {skill_package}/SKILL.md \
267
+ --captured-description "{guarded_description}"
268
+ ```
247
269
 
248
- **Description Guard Protocol:** every invocation below that may modify SKILL.md (`skill-check check --fix` and any `split-body` write) must run inside the four-phase guard defined in §0. Capture `guarded_description` before each call, execute, verify against the post-tool description, and restore on divergence. Do not rely on per-call ad-hoc preservation logic — use the §0 protocol.
270
+ Do not rely on per-call ad-hoc preservation logic — use the helper.
249
271
 
250
272
  **If skill-check available:**
251
273
 
252
274
  - Run: `npx skill-check check {skill_package} --fix --format json --no-security-scan` **inside the §0 guard**.
253
- - **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. The §0 guard has already restored `description` if divergent; the re-read picks up any other fix-corrected content.
275
+ - **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 report will reference. The §0 guard has already restored `description` if divergent; the re-read picks up any other fix-corrected content.
254
276
  - 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). **If falling back to `npx skill-check split-body {skill_package} --write`, run it inside the §0 guard** — split-body can also touch frontmatter. Verify anchors resolve after split.
255
277
  - Run: `npx skill-check diff` if original version was preserved.
256
278
  - Run: `npx skill-check check {skill_package} --format json` for security scan. (Read-only; guard not required.)
257
279
 
258
280
  Record findings in the evidence report (section 4), including any `description_guard_restored` events recorded by the §0 protocol. These are advisory — do not block on warnings.
259
281
 
260
- **If skill-check unavailable:** Skip with note — structural checks from step-05 are sufficient.
282
+ **If skill-check unavailable:** Skip with note — structural checks from step 5 are sufficient.
261
283
 
262
284
  ### 8. Present MENU OPTIONS
263
285
 
@@ -11,6 +11,14 @@ Cross-references generated skills against architecture and PRD documents to prod
11
11
 
12
12
  **Schema contract:** This skill is the PRODUCER of the feasibility report schema defined in `src/shared/references/feasibility-report-schema.md`. All report outputs emit `schemaVersion: "1.0"` in frontmatter, use only the defined verdict tokens (`Verified|Plausible|Risky|Blocked` per pair; `FEASIBLE|CONDITIONALLY_FEASIBLE|NOT_FEASIBLE` overall), follow the fixed section-heading order, and are written through `src/shared/scripts/skf-atomic-write.py write` to both the timestamped file and the stable `-latest.md` copy.
13
13
 
14
+ ## Conventions
15
+
16
+ - Bare paths (e.g. `references/<name>.md`) resolve from the skill root.
17
+ - `references/` holds prompt content carved out of SKILL.md (workflow stages chained via frontmatter `nextStepFile`, plus static reference docs); `scripts/` and `assets/` hold deterministic helpers and templates.
18
+ - `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives, if present).
19
+ - `{project-root}`-prefixed paths resolve from the project working directory.
20
+ - `{skill-name}` resolves to the skill directory's basename.
21
+
14
22
  ## Role
15
23
 
16
24
  You are a stack feasibility analyst and integration verifier operating in Ferris Audit mode. You bring expertise in API surface analysis, cross-library compatibility assessment, and architecture validation, while the user brings their architecture vision and generated skills.
@@ -21,40 +29,104 @@ These rules apply to every step in this workflow:
21
29
 
22
30
  - Read-only — never modify skills, architecture docs, or PRD files
23
31
  - Every verdict must cite evidence from the generated skills
24
- - Read each step file completely before taking any action
25
- - Follow the mandatory sequence in each step exactly — do not skip, reorder, or optimize
26
32
  - Only load one step file at a time — never preload future steps
27
33
  - If any instruction references a subprocess or tool you lack, achieve the outcome in your main context thread
28
34
  - Always communicate in `{communication_language}`
35
+ - At any interactive prompt, the inputs `cancel`, `exit`, `[X]`, `q`, or `:q` exit cleanly with exit code 6 (`halt_reason: "user-cancelled"`)
29
36
  - If `{headless_mode}` is true, auto-proceed through confirmation gates with their default action and log each auto-decision
30
37
 
31
38
  ## Stages
32
39
 
33
40
  | # | Step | File | Auto-proceed |
34
41
  |---|------|------|--------------|
35
- | 1 | Initialize & Load Inputs | steps-c/step-01-init.md | No (confirm) |
36
- | 2 | Coverage Analysis | steps-c/step-02-coverage.md | Yes |
37
- | 3 | Integration Verification | steps-c/step-03-integrations.md | Yes |
38
- | 4 | Requirements Mapping | steps-c/step-04-requirements.md | Yes |
39
- | 5 | Synthesize Verdict | steps-c/step-05-synthesize.md | Yes |
40
- | 6 | Report | steps-c/step-06-report.md | No (confirm) |
41
- | 7 | Workflow Health Check | steps-c/step-07-health-check.md | Yes |
42
+ | 1 | Initialize & Load Inputs | references/init.md | No (confirm) |
43
+ | 2 | Coverage Analysis | references/coverage.md | Yes |
44
+ | 3 | Integration Verification | references/integrations.md | Yes |
45
+ | 4 | Requirements Mapping | references/requirements.md | Yes |
46
+ | 5 | Synthesize Verdict | references/synthesize.md | Yes |
47
+ | 6 | Report | references/report.md | No (confirm) |
48
+ | 7 | Workflow Health Check | references/health-check.md | Yes |
42
49
 
43
50
  ## Invocation Contract
44
51
 
45
52
  | Aspect | Detail |
46
53
  |--------|--------|
47
- | **Inputs** | architecture_doc_path [required], prd_path [optional] |
48
- | **Gates** | step-01: Input Gate [use args] | step-06: Confirm Gate [C] |
49
- | **Outputs** | `feasibility-report-{projectSlug}-{timestamp}.md` and `feasibility-report-{projectSlug}-latest.md` (copy, not symlink) per `src/shared/references/feasibility-report-schema.md` with integration verdicts, coverage analysis, recommendations, and evidence sources |
50
- | **Headless** | All gates auto-resolve with default action when `{headless_mode}` is true |
54
+ | **Inputs** | architecture_doc_path [required], prd_path [optional], previous_report_path [optional] |
55
+ | **Flags** | `--headless` / `-H` (auto-resolve all gates); `--architecture-doc <path>` (skip step 1 prompt for the required input); `--prd <path>` (skip step 1 prompt for the optional PRD); `--previous-report <path>` (skip step 1 prompt for delta comparison) |
56
+ | **Gates** | step 1: Input Gate [use args] | step 6: Confirm Gate [C] |
57
+ | **Outputs** | `feasibility-report-{projectSlug}-{timestamp}.md` and `feasibility-report-{projectSlug}-latest.md` (copy, not symlink) per `src/shared/references/feasibility-report-schema.md` — with integration verdicts, coverage analysis, recommendations, and evidence sources; plus `verify-stack-result-{timestamp}.json` and `verify-stack-result-latest.json` |
58
+ | **Headless** | All gates auto-resolve with default action when `{headless_mode}` is true. Per-flag args (`--architecture-doc`, `--prd`, `--previous-report`) consumed at the gates that would otherwise prompt. |
59
+ | **Exit codes** | See "Exit Codes" below |
60
+
61
+ ## Exit Codes
62
+
63
+ Every HARD HALT in this workflow exits with a stable code so headless automators can branch on the failure class without grepping message text:
64
+
65
+ | Code | Meaning | Raised by |
66
+ | ---- | -------------------- | -------------------------------------------------------------------------------------------- |
67
+ | 0 | success | step 7 (terminal) |
68
+ | 2 | input-missing / input-invalid | step 1 §1 (headless missing `architecture-doc` arg, or invalid path) → `input-missing`; non-existent file → `input-invalid` |
69
+ | 3 | resolution-failure | step 1 §2 (`{skills_output_folder}` does not exist or is empty); step 1 §3 (forge_data_folder unconfigured) |
70
+ | 4 | write-failure | On-Activation §3 pre-flight write probe; step 1 §4 (atomic write of report skeleton failed); step 6 §4b (result-contract write failed) |
71
+ | 5 | state-conflict | step 1 §3 (fewer than 2 valid skills found — stack requires ≥2); step 1 §1 (`previousReport` resolves to same inode as `{outputFile}`); step 6 §1 (report section order or schemaVersion mismatch — schema-violation) |
72
+ | 6 | user-cancelled | step 1 §1 prompt cancelled; any prompt that accepted `cancel`/`exit`/`:q`; step 6 menu cancelled |
73
+ | 7 | inventory-unreliable | step 1 §2 (>20% subagent failures or enumerate-stack-skills warnings exceed budget) |
74
+
75
+ ## Result Contract (Headless)
76
+
77
+ When `{headless_mode}` is true, step 6 emits a single-line JSON envelope on **stdout** before chaining to step 7, and every HARD HALT emits the same envelope shape on **stderr** with `status: "error"`:
78
+
79
+ ```
80
+ SKF_VERIFY_STACK_RESULT_JSON: {"status":"success|error","report_path":"…|null","report_latest_path":"…|null","overall_verdict":"…|null","coverage_percentage":0,"recommendation_count":0,"exit_code":0,"halt_reason":null}
81
+ ```
82
+
83
+ `status` is `"success"` on the terminal happy path, `"error"` on any HALT. `halt_reason` is one of: `null` (success), `"input-missing"`, `"input-invalid"`, `"skills-folder-missing"`, `"insufficient-skills"`, `"forge-folder-unconfigured"`, `"previous-report-collision"`, `"inventory-unreliable"`, `"schema-violation"`, `"write-failed"`, `"user-cancelled"`. `exit_code` matches the table above. `overall_verdict` uses the schema tokens (`FEASIBLE`/`CONDITIONALLY_FEASIBLE`/`NOT_FEASIBLE`).
51
84
 
52
85
  ## On Activation
53
86
 
54
87
  1. Load config from `{project-root}/_bmad/skf/config.yaml` and resolve:
55
- - `project_name`, `user_name`, `communication_language`
56
- - `skills_output_folder`, `forge_data_folder`, `document_output_language`
88
+ - `project_name`, `user_name`, `communication_language`, `document_output_language`
89
+ - `skills_output_folder`, `forge_data_folder`, `sidecar_path`
90
+
91
+ 2. **Compute run-scoped variables** (same place as config so every stage can reference them without re-derivation):
92
+ - `project_slug` ← slugify `project_name` (lowercase, hyphens only, no unicode, no whitespace)
93
+ - `timestamp` ← UTC `YYYYMMDD-HHmmss` captured at activation time
94
+ - These two combine in init.md §4 into `{outputFile}` per the stage frontmatter template, but the values themselves are fixed for the entire workflow run — every later reference to `{outputFile}` resolves consistently. (Computing them here resolves an order-of-operations bug where the §1 §3 inode-collision check referenced `{outputFile}` before `{project_slug}` and `{timestamp}` were defined.)
95
+
96
+ 3. **Resolve `{headless_mode}`**: true if `--headless` or `-H` was passed as an argument, or if `headless_mode: true` in `{sidecar_path}/preferences.yaml`. Default: false.
97
+
98
+ 4. **Resolve workflow customization.** Run:
99
+
100
+ ```bash
101
+ python3 {project-root}/_bmad/scripts/resolve_customization.py \
102
+ --skill {skill-root} --key workflow
103
+ ```
104
+
105
+ The script merges the three customization layers per `bmad-customize`'s structural merge rules (scalars override, arrays append):
106
+
107
+ - `{skill-root}/customize.toml` — bundled defaults
108
+ - `_bmad/custom/<skill-name>.toml` under `{project-root}` — team overrides (committed)
109
+ - `_bmad/custom/<skill-name>.user.toml` under `{project-root}` — personal overrides (gitignored)
110
+
111
+ If the script fails or is missing, fall back to reading `{skill-root}/customize.toml` directly — the bundled defaults are an empty string for each path scalar.
112
+
113
+ Apply the path-scalar fallback now so stage files don't have to repeat the conditional logic. For each of the four scalars, if the merged value is empty or absent, use the bundled default:
114
+
115
+ - `{reportTemplatePath}` ← `workflow.report_template_path` if non-empty, else `assets/feasibility-report-template.md`
116
+ - `{integrationRulesPath}` ← `workflow.integration_rules_path` if non-empty, else `references/integration-verification-rules.md`
117
+ - `{coveragePatternsPath}` ← `workflow.coverage_patterns_path` if non-empty, else `references/coverage-patterns.md`
118
+ - `{outputFolderPath}` ← `workflow.output_folder_path` if non-empty, else `{forge_data_folder}`
119
+
120
+ Stash all four as workflow-context variables. Stage files reference them directly — no conditional at the usage site. Empty-string overrides cleanly fall through to the bundled default.
121
+
122
+ 5. **Pre-flight write probe.** Verify `{outputFolderPath}` is writable. A read-only mount, full disk, or permissions-denied path otherwise only surfaces at init.md §4 atomic write — by then the user has already gone through the input prompts:
123
+
124
+ ```bash
125
+ mkdir -p "{outputFolderPath}" && \
126
+ printf 'probe' > "{outputFolderPath}/.skf-write-probe" && \
127
+ rm "{outputFolderPath}/.skf-write-probe"
128
+ ```
57
129
 
58
- 2. **Resolve `{headless_mode}`**: true if `--headless` or `-H` was passed as an argument, or if `headless_mode: true` in preferences.yaml. Default: false.
130
+ On any non-zero exit: HALT (exit code 4, `halt_reason: "write-failed"`). In headless mode, emit the error envelope per **Result Contract (Headless)** with `report_path: null`, `report_latest_path: null`, `overall_verdict: null`.
59
131
 
60
- 3. Load, read the full file, and then execute `./steps-c/step-01-init.md` to begin the workflow.
132
+ 6. Load, read the full file, and then execute `references/init.md` to begin the workflow.
@@ -49,13 +49,13 @@ deltaUnchanged: null
49
49
 
50
50
  ## Coverage Analysis
51
51
 
52
- <!-- Appended by step-02-coverage -->
52
+ <!-- Appended by coverage -->
53
53
 
54
54
  ---
55
55
 
56
56
  ## Integration Verdicts
57
57
 
58
- <!-- Appended by step-03-integrations.
58
+ <!-- Appended by integrations.
59
59
  Consumers grep for the `## Integration Verdicts` heading to locate the pair table.
60
60
  The table header is fixed and MUST be emitted exactly as shown below: -->
61
61
 
@@ -66,11 +66,11 @@ The table header is fixed and MUST be emitted exactly as shown below: -->
66
66
 
67
67
  ## Recommendations
68
68
 
69
- <!-- Appended by step-05-synthesize -->
69
+ <!-- Appended by synthesize -->
70
70
 
71
71
  ---
72
72
 
73
73
  ## Evidence Sources
74
74
 
75
- <!-- Appended by step-05-synthesize — cite each skill's SKILL.md path, metadata_schema_version,
75
+ <!-- Appended by synthesize — cite each skill's SKILL.md path, metadata_schema_version,
76
76
  confidence_tier, stack manifest (if any), and architecture/PRD doc paths -->
@@ -0,0 +1,50 @@
1
+ # DO NOT EDIT -- overwritten on every update.
2
+ #
3
+ # Workflow customization surface for skf-verify-stack.
4
+
5
+ [workflow]
6
+
7
+ # --- Configurable below. Overrides merge per BMad structural rules: ---
8
+ # scalars: override wins • arrays (persistent_facts, activation_steps_*): append
9
+ # arrays-of-tables with `code`/`id`: replace matching items, append new ones.
10
+
11
+ # Steps to run before the standard activation (uv probe, config load).
12
+ # Overrides append. Use for org-wide pre-flight checks (auth, network,
13
+ # compliance) that must precede any verification work.
14
+
15
+ activation_steps_prepend = []
16
+
17
+ # Steps to run after activation but before the first stage executes.
18
+ # Overrides append. Use for context loads or banner customization that
19
+ # should run once activation completes successfully.
20
+
21
+ activation_steps_append = []
22
+
23
+ # Persistent facts the workflow keeps in mind for the whole run
24
+ # (verification standards, evidence-citation rules, house-style verdict
25
+ # language). Overrides append.
26
+ #
27
+ # Each entry is either:
28
+ # - a literal sentence, e.g. "Verdict citations must include file:line spans."
29
+ # - a file reference prefixed with `file:`, e.g.
30
+ # "file:{project-root}/docs/verify-policy.md" (globs supported; file
31
+ # contents are loaded and treated as facts).
32
+
33
+ persistent_facts = [
34
+ "file:{project-root}/**/project-context.md",
35
+ ]
36
+
37
+ # --- Optional asset overrides ---
38
+ #
39
+ # Lift the canonical asset paths so orgs can substitute house-style copies
40
+ # without forking the skill. Empty string = use the bundled default.
41
+
42
+ report_template_path = ""
43
+ integration_rules_path = ""
44
+ coverage_patterns_path = ""
45
+
46
+ # Override the destination directory for the feasibility report. Empty =
47
+ # use {forge_data_folder} from config.yaml. Useful for orgs that want
48
+ # verification artifacts to land outside the per-skill forge tree.
49
+
50
+ output_folder_path = ""
@@ -26,14 +26,14 @@ Parse document section headers for technology groupings:
26
26
 
27
27
  ### Coverage Verdict
28
28
 
29
- The coverage matrix renders two verdict tokens per referenced technology: **Covered** and **Missing**. Extra skills (skills present in the inventory but NOT referenced by the architecture document) are tracked in a separate informational subdivision — they are not coverage verdicts and do not appear in the primary `Technology → Skill Match → Verdict` column. See step-02 §4 for the Extra-skill subdivision output.
29
+ The coverage matrix renders two verdict tokens per referenced technology: **Covered** and **Missing**. Extra skills (skills present in the inventory but NOT referenced by the architecture document) are tracked in a separate informational subdivision — they are not coverage verdicts and do not appear in the primary `Technology → Skill Match → Verdict` column. See step 2 §4 for the Extra-skill subdivision output.
30
30
 
31
31
  | Verdict | Meaning |
32
32
  |-------------|------------------------------------------------------------------|
33
33
  | **Covered** | A generated skill exists in `skills/` for this technology |
34
34
  | **Missing** | Technology is referenced in architecture doc but no skill exists |
35
35
 
36
- **Informational — Extra skills subdivision (not a verdict; rendered in a separate section per step-02 §4):**
36
+ **Informational — Extra skills subdivision (not a verdict; rendered in a separate section per step 2 §4):**
37
37
 
38
38
  | Label | Meaning |
39
39
  |----------------------------------------|----------------------------------------------------------------------------------------------------------------------------------|
@@ -1,12 +1,14 @@
1
1
  ---
2
- nextStepFile: './step-03-integrations.md'
3
- coveragePatternsData: 'references/coverage-patterns.md'
2
+ nextStepFile: 'integrations.md'
3
+ coveragePatternsData: '{coveragePatternsPath}'
4
4
  feasibilitySchemaRef: 'src/shared/references/feasibility-report-schema.md'
5
5
  atomicWriteScript: '{project-root}/src/shared/scripts/skf-atomic-write.py'
6
- outputFile: '{forge_data_folder}/feasibility-report-{project_slug}-{timestamp}.md'
7
- outputFileLatest: '{forge_data_folder}/feasibility-report-{project_slug}-latest.md'
6
+ outputFile: '{outputFolderPath}/feasibility-report-{project_slug}-{timestamp}.md'
7
+ outputFileLatest: '{outputFolderPath}/feasibility-report-{project_slug}-latest.md'
8
8
  ---
9
9
 
10
+ <!-- Config: communicate in {communication_language}. Append the Coverage Analysis section to the report in {document_output_language}. -->
11
+
10
12
  # Step 2: Technology Coverage Analysis
11
13
 
12
14
  ## STEP GOAL:
@@ -20,8 +22,6 @@ Verify that a generated skill exists for every technology, library, or framework
20
22
 
21
23
  ## MANDATORY SEQUENCE
22
24
 
23
- **CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise.
24
-
25
25
  ### 1. Load Coverage Patterns
26
26
 
27
27
  Load `{coveragePatternsData}` for detection rules.
@@ -112,7 +112,7 @@ Write the **Coverage Analysis** section to `{outputFile}` (see `{feasibilitySche
112
112
  - Include coverage percentage
113
113
  - Include missing skill recommendations
114
114
  - Include the Extra (unreferenced) and Orphan (source_repo unresolvable) subdivisions from section 4
115
- - Update frontmatter: append `'step-02-coverage'` to `stepsCompleted`; set `coveragePercentage` (integer 0..100)
115
+ - Update frontmatter: append `'coverage'` to `stepsCompleted`; set `coveragePercentage` (integer 0..100)
116
116
  - Pipe the updated full content through `python3 {atomicWriteScript} write --target {outputFile}` and again with `--target {outputFileLatest}`
117
117
 
118
118
  ### 7. Auto-Proceed to Next Step
@@ -1,10 +1,12 @@
1
1
  ---
2
- # `shared/health-check.md` resolves relative to the SKF module root
3
- # (`_bmad/skf/` when installed, `src/` during development), NOT relative
4
- # to this step file.
2
+ # Note: `shared/health-check.md` resolves relative to the SKF module root
3
+ # ({project-root}/_bmad/skf/ when installed, {project-root}/src/ during
4
+ # development), NOT relative to this step file.
5
5
  nextStepFile: 'shared/health-check.md'
6
6
  ---
7
7
 
8
+ <!-- Config: communicate in {communication_language}. -->
9
+
8
10
  # Step 7: Workflow Health Check
9
11
 
10
12
  ## STEP GOAL:
@@ -13,7 +15,7 @@ Chain to the shared workflow self-improvement health check at `{nextStepFile}`.
13
15
 
14
16
  ## Rules
15
17
 
16
- - No user-facing reports, file writes, or result contracts in this step — those belong in step-06
18
+ - No user-facing reports, file writes, or result contracts in this step — those belong in step 6
17
19
  - Delegate directly to `{nextStepFile}` with no additional commentary
18
20
  - Do not attempt any other action between loading this step and executing `{nextStepFile}`
19
21
 
@@ -22,4 +24,4 @@ Chain to the shared workflow self-improvement health check at `{nextStepFile}`.
22
24
  Attempt to load `{nextStepFile}`.
23
25
 
24
26
  - **If `{nextStepFile}` loads successfully:** Read it fully, then execute it.
25
- - **If `{nextStepFile}` cannot be resolved or loaded** (e.g., running against a partial installation, module root not resolvable, or the file has been removed): log exactly `health-check unavailable at {path}` (substitute the attempted resolved path) to the user-visible output and exit the workflow cleanly. Do NOT HALT with an error — the health check is an optional self-improvement hook, and the feasibility report (written in step-06) is the authoritative workflow output. Exit cleanly so CI and headless runs do not fail on a missing optional hook.
27
+ - **If `{nextStepFile}` cannot be resolved or loaded** (e.g., running against a partial installation, module root not resolvable, or the file has been removed): log exactly `health-check unavailable at {path}` (substitute the attempted resolved path) to the user-visible output and exit the workflow cleanly. Do NOT HALT with an error — the health check is an optional self-improvement hook, and the feasibility report (written in step 6) is the authoritative workflow output. Exit cleanly so CI and headless runs do not fail on a missing optional hook.