bmad-module-skill-forge 1.4.1 → 1.5.1

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 (231) 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 +147 -16
  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-manifest-ops.py +22 -6
  35. package/src/shared/scripts/skf-merge-ccc-exclusions.py +34 -4
  36. package/src/shared/scripts/skf-pair-intersect.py +250 -0
  37. package/src/shared/scripts/skf-provenance-gap-dispatch.py +433 -0
  38. package/src/shared/scripts/skf-qmd-classify-collections.py +42 -8
  39. package/src/shared/scripts/skf-recommend-scope-type.py +2 -2
  40. package/src/shared/scripts/skf-render-quick-metadata.py +2 -2
  41. package/src/shared/scripts/skf-resolve-authoritative-files.py +504 -0
  42. package/src/shared/scripts/skf-scan-manifests.py +738 -0
  43. package/src/shared/scripts/skf-scan-skill-md-structure.py +375 -0
  44. package/src/shared/scripts/skf-update-active-symlink.py +315 -0
  45. package/src/shared/scripts/skf-validate-brief-inputs.py +5 -5
  46. package/src/shared/scripts/skf-validate-brief-schema.py +348 -0
  47. package/src/shared/scripts/skf-write-skill-brief.py +61 -5
  48. package/src/skf-analyze-source/SKILL.md +69 -16
  49. package/src/skf-analyze-source/assets/skill-brief-schema.md +1 -1
  50. package/src/skf-analyze-source/customize.toml +55 -0
  51. package/src/skf-analyze-source/{steps-c/step-01b-continue.md → references/continue.md} +12 -12
  52. package/src/skf-analyze-source/{steps-c/step-06-generate-briefs.md → references/generate-briefs.md} +29 -10
  53. package/src/skf-analyze-source/{steps-c/step-07-health-check.md → references/health-check.md} +5 -3
  54. package/src/skf-analyze-source/{steps-c/step-03-identify-units.md → references/identify-units.md} +48 -14
  55. package/src/skf-analyze-source/{steps-c/step-01-init.md → references/init.md} +32 -9
  56. package/src/skf-analyze-source/{steps-c/step-04-map-and-detect.md → references/map-and-detect.md} +52 -25
  57. package/src/skf-analyze-source/{steps-c/step-05-recommend.md → references/recommend.md} +15 -8
  58. package/src/skf-analyze-source/{steps-c/step-02-scan-project.md → references/scan-project.md} +16 -10
  59. package/src/skf-analyze-source/references/unit-detection-heuristics.md +2 -0
  60. package/src/skf-analyze-source/templates/analysis-report-template.md +6 -6
  61. package/src/skf-audit-skill/SKILL.md +66 -15
  62. package/src/skf-audit-skill/assets/drift-report-template.md +6 -5
  63. package/src/skf-audit-skill/customize.toml +49 -0
  64. package/src/skf-audit-skill/{steps-c/step-07-health-check.md → references/health-check.md} +5 -3
  65. package/src/skf-audit-skill/{steps-c/step-01-init.md → references/init.md} +63 -19
  66. package/src/skf-audit-skill/{steps-c/step-02-re-index.md → references/re-index.md} +11 -11
  67. package/src/skf-audit-skill/{steps-c/step-06-report.md → references/report.md} +25 -7
  68. package/src/skf-audit-skill/{steps-c/step-04-semantic-diff.md → references/semantic-diff.md} +6 -6
  69. package/src/skf-audit-skill/{steps-c/step-05-severity-classify.md → references/severity-classify.md} +5 -5
  70. package/src/skf-audit-skill/references/severity-rules.md +2 -0
  71. package/src/skf-audit-skill/{steps-c/step-03-structural-diff.md → references/structural-diff.md} +35 -17
  72. package/src/skf-brief-skill/SKILL.md +49 -19
  73. package/src/skf-brief-skill/assets/description-voice-examples.md +1 -1
  74. package/src/skf-brief-skill/assets/skill-brief-schema.md +32 -2
  75. package/src/skf-brief-skill/customize.toml +44 -0
  76. package/src/skf-brief-skill/{steps-c/step-02-analyze-target.md → references/analyze-target.md} +27 -15
  77. package/src/skf-brief-skill/{steps-c/step-04-confirm-brief.md → references/confirm-brief.md} +13 -10
  78. package/src/skf-brief-skill/references/draft-checkpoint.md +4 -4
  79. package/src/skf-brief-skill/{steps-c/step-01-gather-intent.md → references/gather-intent.md} +35 -29
  80. package/src/skf-brief-skill/references/headless-args.md +9 -9
  81. package/src/skf-brief-skill/references/headless-source-authority-detection.md +1 -1
  82. package/src/skf-brief-skill/{steps-c/step-06-health-check.md → references/health-check.md} +4 -2
  83. package/src/skf-brief-skill/references/portfolio-similarity-check.md +2 -2
  84. package/src/skf-brief-skill/references/qmd-collection-registration.md +2 -2
  85. package/src/skf-brief-skill/{steps-c/step-03-scope-definition.md → references/scope-definition.md} +27 -20
  86. package/src/skf-brief-skill/references/version-resolution.md +2 -2
  87. package/src/skf-brief-skill/{steps-c/step-05-write-brief.md → references/write-brief.md} +29 -16
  88. package/src/skf-create-skill/SKILL.md +25 -19
  89. package/src/skf-create-skill/assets/compile-assembly-rules.md +3 -3
  90. package/src/skf-create-skill/assets/skill-sections.md +5 -5
  91. package/src/skf-create-skill/assets/tessl-dismissal-rules.md +11 -11
  92. package/src/skf-create-skill/customize.toml +35 -0
  93. package/src/skf-create-skill/references/authoritative-files-protocol.md +142 -0
  94. package/src/skf-create-skill/{steps-c/step-05-compile.md → references/compile.md} +16 -16
  95. package/src/skf-create-skill/{steps-c/step-03d-component-extraction.md → references/component-extraction.md} +16 -16
  96. package/src/skf-create-skill/{steps-c/step-02-ecosystem-check.md → references/ecosystem-check.md} +4 -4
  97. package/src/skf-create-skill/{steps-c/step-04-enrich.md → references/enrich.md} +3 -3
  98. package/src/skf-create-skill/{steps-c/step-03-extract.md → references/extract.md} +52 -120
  99. package/src/skf-create-skill/references/extraction-patterns.md +10 -8
  100. package/src/skf-create-skill/{steps-c/step-07-generate-artifacts.md → references/generate-artifacts.md} +11 -11
  101. package/src/skf-create-skill/{steps-c/step-09-health-check.md → references/health-check.md} +4 -2
  102. package/src/skf-create-skill/{steps-c/step-01-load-brief.md → references/load-brief.md} +40 -32
  103. package/src/skf-create-skill/{steps-c/step-08-report.md → references/report.md} +8 -8
  104. package/src/skf-create-skill/references/source-resolution-protocols.md +6 -6
  105. package/src/skf-create-skill/{steps-c/sub/step-02b-ccc-discover.md → references/sub/ccc-discover.md} +5 -5
  106. package/src/skf-create-skill/{steps-c/sub/step-03c-fetch-docs.md → references/sub/fetch-docs.md} +28 -12
  107. package/src/skf-create-skill/{steps-c/sub/step-03b-fetch-temporal.md → references/sub/fetch-temporal.md} +81 -50
  108. package/src/skf-create-skill/{steps-c/step-06-validate.md → references/validate.md} +48 -28
  109. package/src/skf-create-stack-skill/SKILL.md +76 -17
  110. package/src/skf-create-stack-skill/assets/provenance-map-schema.md +102 -0
  111. package/src/skf-create-stack-skill/assets/stack-skill-template.md +1 -1
  112. package/src/skf-create-stack-skill/customize.toml +46 -0
  113. package/src/skf-create-stack-skill/{steps-c/step-06-compile-stack.md → references/compile-stack.md} +6 -5
  114. package/src/skf-create-stack-skill/references/compose-mode-rules.md +3 -1
  115. package/src/skf-create-stack-skill/{steps-c/step-05-detect-integrations.md → references/detect-integrations.md} +37 -11
  116. package/src/skf-create-stack-skill/{steps-c/step-02-detect-manifests.md → references/detect-manifests.md} +32 -28
  117. package/src/skf-create-stack-skill/{steps-c/step-07-generate-output.md → references/generate-output.md} +11 -85
  118. package/src/skf-create-stack-skill/{steps-c/step-10-health-check.md → references/health-check.md} +4 -2
  119. package/src/skf-create-stack-skill/{steps-c/step-01-init.md → references/init.md} +70 -4
  120. package/src/skf-create-stack-skill/references/integration-patterns.md +2 -0
  121. package/src/skf-create-stack-skill/references/manifest-patterns.md +2 -0
  122. package/src/skf-create-stack-skill/{steps-c/step-04-parallel-extract.md → references/parallel-extract.md} +44 -17
  123. package/src/skf-create-stack-skill/{steps-c/step-03-rank-and-confirm.md → references/rank-and-confirm.md} +5 -4
  124. package/src/skf-create-stack-skill/{steps-c/step-09-report.md → references/report.md} +3 -3
  125. package/src/skf-create-stack-skill/{steps-c/step-08-validate.md → references/validate.md} +6 -6
  126. package/src/skf-drop-skill/SKILL.md +84 -12
  127. package/src/skf-drop-skill/customize.toml +57 -0
  128. package/src/skf-drop-skill/{steps-c/step-02-execute.md → references/execute.md} +49 -34
  129. package/src/skf-drop-skill/{steps-c/step-04-health-check.md → references/health-check.md} +6 -4
  130. package/src/skf-drop-skill/{steps-c/step-03-report.md → references/report.md} +13 -5
  131. package/src/skf-drop-skill/{steps-c/step-01-select.md → references/select.md} +63 -15
  132. package/src/skf-export-skill/SKILL.md +85 -16
  133. package/src/skf-export-skill/assets/managed-section-format.md +3 -3
  134. package/src/skf-export-skill/assets/snippet-format.md +2 -2
  135. package/src/skf-export-skill/customize.toml +49 -0
  136. package/src/skf-export-skill/{steps-c/step-03-generate-snippet.md → references/generate-snippet.md} +11 -11
  137. package/src/skf-export-skill/{steps-c/step-07-health-check.md → references/health-check.md} +6 -4
  138. package/src/skf-export-skill/{steps-c/step-01-load-skill.md → references/load-skill.md} +11 -49
  139. package/src/skf-export-skill/references/manifest-rebuild.md +68 -0
  140. package/src/skf-export-skill/references/multi-skill-mode.md +38 -0
  141. package/src/skf-export-skill/references/orphan-context-detection.md +75 -0
  142. package/src/skf-export-skill/references/orphan-row-detection.md +102 -0
  143. package/src/skf-export-skill/{steps-c/step-02-package.md → references/package.md} +7 -7
  144. package/src/skf-export-skill/references/preflight-snippet-root-probe.md +79 -0
  145. package/src/skf-export-skill/{steps-c/step-06-summary.md → references/summary.md} +23 -11
  146. package/src/skf-export-skill/{steps-c/step-05-token-report.md → references/token-report.md} +5 -5
  147. package/src/skf-export-skill/{steps-c/step-04-update-context.md → references/update-context.md} +109 -113
  148. package/src/skf-quick-skill/SKILL.md +63 -123
  149. package/src/skf-quick-skill/customize.toml +44 -0
  150. package/src/skf-quick-skill/references/batch-mode.md +102 -0
  151. package/src/skf-quick-skill/{steps-c/step-04-compile.md → references/compile.md} +10 -10
  152. package/src/skf-quick-skill/{steps-c/step-02-ecosystem-check.md → references/ecosystem-check.md} +5 -5
  153. package/src/skf-quick-skill/{steps-c/step-06-finalize.md → references/finalize.md} +7 -7
  154. package/src/skf-quick-skill/{steps-c/step-07-health-check.md → references/health-check.md} +3 -3
  155. package/src/skf-quick-skill/{steps-c/step-03-quick-extract.md → references/quick-extract.md} +5 -5
  156. package/src/skf-quick-skill/references/registry-resolution.md +2 -0
  157. package/src/skf-quick-skill/{steps-c/step-01-resolve-target.md → references/resolve-target.md} +14 -10
  158. package/src/skf-quick-skill/{steps-c/step-05-write-and-validate.md → references/write-and-validate.md} +4 -4
  159. package/src/skf-refine-architecture/SKILL.md +86 -16
  160. package/src/skf-refine-architecture/customize.toml +49 -0
  161. package/src/skf-refine-architecture/{steps-c/step-05-compile.md → references/compile.md} +4 -4
  162. package/src/skf-refine-architecture/{steps-c/step-02-gap-analysis.md → references/gap-analysis.md} +5 -5
  163. package/src/skf-refine-architecture/{steps-c/step-07-health-check.md → references/health-check.md} +6 -4
  164. package/src/skf-refine-architecture/{steps-c/step-04-improvements.md → references/improvements.md} +5 -5
  165. package/src/skf-refine-architecture/references/init.md +144 -0
  166. package/src/skf-refine-architecture/{steps-c/step-03-issue-detection.md → references/issue-detection.md} +5 -5
  167. package/src/skf-refine-architecture/references/refinement-rules.md +2 -0
  168. package/src/skf-refine-architecture/{steps-c/step-06-report.md → references/report.md} +14 -5
  169. package/src/skf-rename-skill/SKILL.md +82 -12
  170. package/src/skf-rename-skill/customize.toml +52 -0
  171. package/src/skf-rename-skill/{steps-c/step-02-execute.md → references/execute.md} +94 -99
  172. package/src/skf-rename-skill/references/health-check.md +30 -0
  173. package/src/skf-rename-skill/references/rebuild-context.md +110 -0
  174. package/src/skf-rename-skill/{steps-c/step-03-report.md → references/report.md} +13 -5
  175. package/src/skf-rename-skill/{steps-c/step-01-select.md → references/select.md} +59 -20
  176. package/src/skf-setup/SKILL.md +35 -35
  177. package/src/skf-setup/customize.toml +33 -0
  178. package/src/skf-setup/{steps-c/step-03-auto-index.md → references/auto-index.md} +10 -18
  179. package/src/skf-setup/{steps-c/step-01b-ccc-index.md → references/ccc-index.md} +16 -31
  180. package/src/skf-setup/{steps-c/step-01-detect-and-tier.md → references/detect-and-tier.md} +23 -10
  181. package/src/skf-setup/{steps-c/step-05-health-check.md → references/health-check.md} +1 -1
  182. package/src/skf-setup/{steps-c/step-04-report.md → references/report.md} +21 -19
  183. package/src/skf-setup/references/tier-rules.md +1 -1
  184. package/src/skf-setup/{steps-c/step-02-write-config.md → references/write-config.md} +14 -13
  185. package/src/skf-test-skill/SKILL.md +77 -15
  186. package/src/skf-test-skill/customize.toml +54 -0
  187. package/src/skf-test-skill/{steps-c/step-04-coherence-check.md → references/coherence-check.md} +37 -73
  188. package/src/skf-test-skill/{steps-c/step-03-coverage-check.md → references/coverage-check.md} +16 -39
  189. package/src/skf-test-skill/{steps-c/step-02-detect-mode.md → references/detect-mode.md} +4 -26
  190. package/src/skf-test-skill/{steps-c/step-04b-external-validators.md → references/external-validators.md} +6 -28
  191. package/src/skf-test-skill/references/health-check.md +14 -0
  192. package/src/skf-test-skill/{steps-c/step-01-init.md → references/init.md} +21 -37
  193. package/src/skf-test-skill/references/migration-section-rules.md +4 -2
  194. package/src/skf-test-skill/{steps-c/step-06-report.md → references/report.md} +41 -51
  195. package/src/skf-test-skill/{steps-c/step-05-score.md → references/score.md} +26 -43
  196. package/src/skf-test-skill/references/scoring-rules.md +8 -6
  197. package/src/skf-test-skill/references/source-access-protocol.md +7 -5
  198. package/src/skf-test-skill/scripts/compute-score.py +88 -17
  199. package/src/skf-test-skill/templates/test-report-template.md +13 -13
  200. package/src/skf-update-skill/SKILL.md +23 -14
  201. package/src/skf-update-skill/customize.toml +44 -0
  202. package/src/skf-update-skill/{steps-c/step-02-detect-changes.md → references/detect-changes.md} +176 -68
  203. package/src/skf-update-skill/references/health-check.md +32 -0
  204. package/src/skf-update-skill/{steps-c/step-01-init.md → references/init.md} +56 -8
  205. package/src/skf-update-skill/references/manual-section-rules.md +4 -0
  206. package/src/skf-update-skill/references/merge-conflict-rules.md +4 -0
  207. package/src/skf-update-skill/{steps-c/step-04-merge.md → references/merge.md} +8 -8
  208. package/src/skf-update-skill/{steps-c/step-03-re-extract.md → references/re-extract.md} +53 -44
  209. package/src/skf-update-skill/references/remote-source-resolution.md +5 -1
  210. package/src/skf-update-skill/references/report.md +214 -0
  211. package/src/skf-update-skill/{steps-c/step-05-validate.md → references/validate.md} +5 -5
  212. package/src/skf-update-skill/{steps-c/step-06-write.md → references/write.md} +73 -51
  213. package/src/skf-verify-stack/SKILL.md +89 -17
  214. package/src/skf-verify-stack/assets/feasibility-report-template.md +4 -4
  215. package/src/skf-verify-stack/customize.toml +50 -0
  216. package/src/skf-verify-stack/references/coverage-patterns.md +2 -2
  217. package/src/skf-verify-stack/{steps-c/step-02-coverage.md → references/coverage.md} +13 -9
  218. package/src/skf-verify-stack/{steps-c/step-07-health-check.md → references/health-check.md} +7 -5
  219. package/src/skf-verify-stack/references/init.md +170 -0
  220. package/src/skf-verify-stack/references/integration-verification-rules.md +1 -1
  221. package/src/skf-verify-stack/{steps-c/step-03-integrations.md → references/integrations.md} +18 -14
  222. package/src/skf-verify-stack/{steps-c/step-06-report.md → references/report.md} +27 -42
  223. package/src/skf-verify-stack/{steps-c/step-04-requirements.md → references/requirements.md} +13 -9
  224. package/src/skf-verify-stack/{steps-c/step-05-synthesize.md → references/synthesize.md} +14 -10
  225. package/tools/validate-docs-drift.js +1 -1
  226. package/src/skf-refine-architecture/steps-c/step-01-init.md +0 -136
  227. package/src/skf-rename-skill/steps-c/step-04-health-check.md +0 -22
  228. package/src/skf-test-skill/steps-c/step-07-health-check.md +0 -25
  229. package/src/skf-update-skill/steps-c/step-07-report.md +0 -148
  230. package/src/skf-update-skill/steps-c/step-08-health-check.md +0 -22
  231. package/src/skf-verify-stack/steps-c/step-01-init.md +0 -178
@@ -1,8 +1,10 @@
1
1
  ---
2
2
  outputFile: '{forge_version}/drift-report-{timestamp}.md'
3
- nextStepFile: './step-07-health-check.md'
3
+ nextStepFile: 'health-check.md'
4
4
  ---
5
5
 
6
+ <!-- Config: communicate in {communication_language}. Drift report prose in {document_output_language}. -->
7
+
6
8
  # Step 6: Generate Report
7
9
 
8
10
  ## STEP GOAL:
@@ -18,8 +20,6 @@ Finalize the drift report by completing the Audit Summary with calculated metric
18
20
 
19
21
  ## MANDATORY SEQUENCE
20
22
 
21
- **CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise unless user explicitly requests a change.
22
-
23
23
  ### 1. Complete Audit Summary
24
24
 
25
25
  Update the ## Audit Summary section at the top of {outputFile} with final calculated values:
@@ -77,10 +77,10 @@ Append to {outputFile}:
77
77
  {IF any CRITICAL or HIGH findings:}
78
78
  **Recommended:** Run `[US] Update Skill` workflow to apply priority remediations automatically.
79
79
 
80
- {IF `audit_ref != baseline_ref` (source version bump detected in step-01 §5b):}
81
- **Version preservation (non-destructive).** `update-skill` preserves the prior version at `{skill_group}/{baseline_version}/` unchanged and writes the new skill to `{skill_group}/{audit_version}/` (see `skf-update-skill/steps-c/step-04-merge.md` §6b, which creates the new version directory and leaves the previous one on disk). The `active` symlink at `{skill_group}/active` repoints to the new version (see `skf-update-skill/steps-c/step-06-write.md` §5b). On the next export, the prior version's export-manifest entry transitions to `status: archived` — files retained for rollback (see `skf-export-skill/steps-c/step-04-update-context.md`). Do **not** recommend `skf-drop-skill` + `skf-create-skill` for a version bump — that destroys the prior version's artifacts.
80
+ {IF `audit_ref != baseline_ref` (source version bump detected in step 1 §5b):}
81
+ **Version preservation (non-destructive).** `update-skill` preserves the prior version at `{skill_group}/{baseline_version}/` unchanged and writes the new skill to `{skill_group}/{audit_version}/` (see `skf-update-skill/references/merge.md` §6b, which creates the new version directory and leaves the previous one on disk). The `active` symlink at `{skill_group}/active` repoints to the new version (see `skf-update-skill/references/write.md` §5b). On the next export, the prior version's export-manifest entry transitions to `status: archived` — files retained for rollback (see `skf-export-skill/references/update-context.md`). Do **not** recommend `skf-drop-skill` + `skf-create-skill` for a version bump — that destroys the prior version's artifacts.
82
82
 
83
- **Surface new entry points for the brief gate.** If the audit observed new top-level modules, renamed package trees, or new public entry points (new `__init__.py`, `index.ts`, `lib.rs`, or equivalent) that were not in the brief's original scope, call them out here. `update-skill` step-02 §1b detects new candidate files via heuristic and prompts `[P]romote` / `[S]kip` / `[U]pdate-brief`; surfacing them in advance makes that gate faster to resolve, or lets the user refine scope via `skf-brief-skill` before running update-skill.
83
+ **Surface new entry points for the brief gate.** If the audit observed new top-level modules, renamed package trees, or new public entry points (new `__init__.py`, `index.ts`, `lib.rs`, or equivalent) that were not in the brief's original scope, call them out here. `update-skill` step 2 §1b detects new candidate files via heuristic and prompts `[P]romote` / `[S]kip` / `[U]pdate-brief`; surfacing them in advance makes that gate faster to resolve, or lets the user refine scope via `skf-brief-skill` before running update-skill.
84
84
 
85
85
  {IF only MEDIUM or LOW findings:}
86
86
  **Optional:** Minor drift detected. Manual updates sufficient, or run `[US] Update Skill` for automated remediation.
@@ -120,7 +120,7 @@ Append to {outputFile}:
120
120
  ### 4. Update Report Frontmatter
121
121
 
122
122
  Update {outputFile} frontmatter:
123
- - Append `'step-06-report'` to `stepsCompleted`
123
+ - Append `'report'` to `stepsCompleted`
124
124
  - Set `drift_score` to final calculated score
125
125
  - Set `nextWorkflow` to `'update-skill'` if CRITICAL or HIGH findings, otherwise leave empty
126
126
 
@@ -170,6 +170,24 @@ Update {outputFile} frontmatter:
170
170
 
171
171
  Write the result contract per `shared/references/output-contract-schema.md`: the per-run record at `{forge_version}/audit-skill-result-{YYYYMMDD-HHmmss}.json` (UTC timestamp, resolution to seconds) and a copy at `{forge_version}/audit-skill-result-latest.json` (stable path for pipeline consumers — copy, not symlink). Include the drift report path in `outputs`; include `drift_count` and `severity` (CLEAN/MINOR/SIGNIFICANT/CRITICAL) in `summary`.
172
172
 
173
+ **Stdout envelope (headless only).** When `{headless_mode}` is true, emit a single-line JSON envelope to **stdout** immediately after the on-disk result contract is written, so chaining workflows can consume `drift_score`, `report_path`, and `next_workflow` from a captured stdout line without polling the filesystem. The shape matches the "Result Contract (Headless)" section in SKILL.md verbatim:
174
+
175
+ ```
176
+ SKF_AUDIT_RESULT_JSON: {"status":"success","skill_name":"{skill_name}","drift_score":"{CLEAN|MINOR|SIGNIFICANT|CRITICAL}","report_path":"{outputFile}","next_workflow":"{update-skill|null}","audit_ref":"{audit_ref}","exit_code":0,"halt_reason":null}
177
+ ```
178
+
179
+ Field rules: `next_workflow` is `"update-skill"` when CRITICAL or HIGH findings exist (matches the frontmatter `nextWorkflow` set in §4), otherwise `null`. `audit_ref` carries the resolved value from step 1 §5b (`baseline_ref` when no upstream drift was detected, `latest_tag` or `remote_head` when the operator chose `[C] Checkout-and-audit-against-latest`).
180
+
181
+ **HALT envelope mirror (headless only).** For every HARD HALT raised in this workflow (skill-not-found at init.md §1, forge-tier missing at §2, source-dir missing at §5, write-failed at §6, user-cancelled at any `[X]` selection), emit the same envelope shape on **stderr** with `status: "error"`, `drift_score: null` (or last known value if classification ran), `report_path: null` if the report write failed, `exit_code` matching the Exit Codes table, and `halt_reason` set to the failure class from the table (`"skill-not-found"`, `"forge-tier-missing"`, `"source-dir-missing"`, `"write-failed"`, `"user-cancelled"`). This is the only signal a wrapping pipeline receives on failure — log it before exiting.
182
+
183
+ **Post-audit hook (optional).** If `{onCompleteCommand}` is non-empty (resolved at SKILL.md On Activation §3 from `workflow.on_complete`), invoke it as:
184
+
185
+ ```bash
186
+ {onCompleteCommand} --result-path={result_json_path}
187
+ ```
188
+
189
+ where `{result_json_path}` is the per-run record path written above (`{forge_version}/audit-skill-result-{YYYYMMDD-HHmmss}.json`). Log success/failure to `workflow_warnings[]` — never fail the workflow on a hook error. The hook runs after the result contract is finalized so notifiers, ticket-tracker integrations, or downstream pipelines see a complete record. When `{onCompleteCommand}` is empty (bundled default), skip the invocation entirely.
190
+
173
191
  ### 6. Chain to Health Check
174
192
 
175
193
  ONLY WHEN the report has been written, presented, and the result contract saved will you then load, read the full file, and execute `{nextStepFile}`. The health-check step is the true terminal step — do not stop here even though the user-facing summary reads as final.
@@ -1,8 +1,10 @@
1
1
  ---
2
- nextStepFile: './step-05-severity-classify.md'
2
+ nextStepFile: 'severity-classify.md'
3
3
  outputFile: '{forge_version}/drift-report-{timestamp}.md'
4
4
  ---
5
5
 
6
+ <!-- Config: communicate in {communication_language}. -->
7
+
6
8
  # Step 4: Semantic Diff
7
9
 
8
10
  ## STEP GOAL:
@@ -18,8 +20,6 @@ Compare QMD knowledge context between the original skill creation and current st
18
20
 
19
21
  ## MANDATORY SEQUENCE
20
22
 
21
- **CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise unless user explicitly requests a change.
22
-
23
23
  ### 1. Check Forge Tier
24
24
 
25
25
  **IF forge tier is Quick, Forge, or Forge+:**
@@ -34,7 +34,7 @@ Append to {outputFile}:
34
34
  Semantic analysis compares QMD knowledge context for meaning-level changes that structural diff cannot detect. To enable semantic diff, run setup with QMD available to unlock Deep tier.
35
35
  ```
36
36
 
37
- Update frontmatter: append `'step-04-semantic-diff'` to `stepsCompleted`
37
+ Update frontmatter: append `'semantic-diff'` to `stepsCompleted`
38
38
 
39
39
  "**Semantic diff skipped (requires Deep tier). Proceeding to severity classification...**"
40
40
 
@@ -55,7 +55,7 @@ Launch a subprocess (Pattern 3 — data operations) that:
55
55
  - Fall through to the **direct-content fallback** below instead of skipping outright.
56
56
  - **Registry entry present and populated.** Use the `name` field from the registry entry as the collection to query. Proceed to bullet 2.
57
57
 
58
- **Direct-content fallback** (used when the collection is registered but empty): load `SKILL.md` and `references/*.md` from the audited skill, then spot-check each documented export against the current source tree under `{source_root}` using the Deep-tier AST tooling this step already requires (ast_bridge; see step-02 §1 "Deep tier"). This fallback is reachable only from Deep tier — §1 short-circuits Quick/Forge/Forge+ before §2 runs, so AST tooling is guaranteed available here. Record findings with confidence label `T1-low-fallback` rather than T2 — this is direct content inspection, not QMD-backed semantic analysis. The step's output schema is otherwise unchanged; set `qmd_collection = null` in the Semantic Drift header and annotate: "Semantic diff ran in direct-content fallback mode — QMD collection was registered but empty."
58
+ **Direct-content fallback** (used when the collection is registered but empty): load `SKILL.md` and `references/*.md` from the audited skill, then spot-check each documented export against the current source tree under `{source_root}` using the Deep-tier AST tooling this step already requires (ast_bridge; see step 2 §1 "Deep tier"). This fallback is reachable only from Deep tier — §1 short-circuits Quick/Forge/Forge+ before §2 runs, so AST tooling is guaranteed available here. Record findings with confidence label `T1-low-fallback` rather than T2 — this is direct content inspection, not QMD-backed semantic analysis. The step's output schema is otherwise unchanged; set `qmd_collection = null` in the Semantic Drift header and annotate: "Semantic diff ran in direct-content fallback mode — QMD collection was registered but empty."
59
59
 
60
60
  2. Queries for knowledge context around each export documented in the skill
61
61
  3. Retrieves: usage patterns, conventions, architectural context, dependency relationships
@@ -128,7 +128,7 @@ Append to {outputFile}:
128
128
  ### 5. Update Report and Auto-Proceed
129
129
 
130
130
  Update {outputFile} frontmatter:
131
- - Append `'step-04-semantic-diff'` to `stepsCompleted`
131
+ - Append `'semantic-diff'` to `stepsCompleted`
132
132
 
133
133
  ### 6. Present MENU OPTIONS
134
134
 
@@ -1,9 +1,11 @@
1
1
  ---
2
- nextStepFile: './step-06-report.md'
2
+ nextStepFile: 'report.md'
3
3
  outputFile: '{forge_version}/drift-report-{timestamp}.md'
4
4
  severityRulesFile: 'references/severity-rules.md'
5
5
  ---
6
6
 
7
+ <!-- Config: communicate in {communication_language}. -->
8
+
7
9
  # Step 5: Severity Classification
8
10
 
9
11
  ## STEP GOAL:
@@ -18,8 +20,6 @@ Grade every drift finding from Steps 03 and 04 by severity level (CRITICAL/HIGH/
18
20
 
19
21
  ## MANDATORY SEQUENCE
20
22
 
21
- **CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise unless user explicitly requests a change.
22
-
23
23
  ### 1. Load Severity Rules
24
24
 
25
25
  Launch a subprocess (Pattern 3 — data operations) that:
@@ -85,7 +85,7 @@ Apply scoring rules from {severityRulesFile}:
85
85
 
86
86
  ### 5. Compile Severity Classification Section
87
87
 
88
- **Rollup inherits from step-03.** If step-03 §5 collapsed ≥ 10 same-kind findings into a single rollup row (deleted source file, renamed module, entire package tree removed), carry that rollup through to the matching severity table as one row — do not re-expand it here. Keep the existing 6-column severity table shape; the rollup encodes root cause, count, and representative symbols **inline in the `Finding` cell** rather than adding new columns, so rollup and per-item rows render cleanly in one table. Changed-signature and cross-file findings remain per-row; they were not eligible for rollup in step-03 and are not eligible here.
88
+ **Rollup inherits from step 3.** If step 3 §5 collapsed ≥ 10 same-kind findings into a single rollup row (deleted source file, renamed module, entire package tree removed), carry that rollup through to the matching severity table as one row — do not re-expand it here. Keep the existing 6-column severity table shape; the rollup encodes root cause, count, and representative symbols **inline in the `Finding` cell** rather than adding new columns, so rollup and per-item rows render cleanly in one table. Changed-signature and cross-file findings remain per-row; they were not eligible for rollup in step 3 and are not eligible here.
89
89
 
90
90
  **Rollup row form (any severity table):**
91
91
 
@@ -138,7 +138,7 @@ Append to {outputFile}:
138
138
  ### 6. Update Report and Auto-Proceed
139
139
 
140
140
  Update {outputFile} frontmatter:
141
- - Append `'step-05-severity-classify'` to `stepsCompleted`
141
+ - Append `'severity-classify'` to `stepsCompleted`
142
142
  - Set `drift_score` to calculated overall score
143
143
 
144
144
  ### 7. Present MENU OPTIONS
@@ -1,3 +1,5 @@
1
+ <!-- Config: communicate in {communication_language}. -->
2
+
1
3
  # Severity Classification Rules
2
4
 
3
5
  ## Severity Levels
@@ -1,8 +1,16 @@
1
1
  ---
2
- nextStepFile: './step-04-semantic-diff.md'
2
+ nextStepFile: 'semantic-diff.md'
3
3
  outputFile: '{forge_version}/drift-report-{timestamp}.md'
4
+ loadProvenanceProbeOrder:
5
+ - '{project-root}/_bmad/skf/shared/scripts/skf-load-provenance.py'
6
+ - '{project-root}/src/shared/scripts/skf-load-provenance.py'
7
+ compareFileHashesProbeOrder:
8
+ - '{project-root}/_bmad/skf/shared/scripts/skf-compare-file-hashes.py'
9
+ - '{project-root}/src/shared/scripts/skf-compare-file-hashes.py'
4
10
  ---
5
11
 
12
+ <!-- Config: communicate in {communication_language}. -->
13
+
6
14
  # Step 3: Structural Diff
7
15
 
8
16
  ## STEP GOAL:
@@ -17,8 +25,6 @@ Compare the original provenance map extractions from create-skill against the cu
17
25
 
18
26
  ## MANDATORY SEQUENCE
19
27
 
20
- **CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise unless user explicitly requests a change.
21
-
22
28
  ### 1. Prepare Comparison Sets
23
29
 
24
30
  Load both datasets:
@@ -29,19 +35,19 @@ Load both datasets:
29
35
  **Current (from Step 02 extraction):**
30
36
  - Export list with names, types, signatures, file paths, line numbers
31
37
 
32
- **Canonicalize extractor methodology differences before matching.** The extractor used by `skf-create-skill` at baseline time and the re-extractor used by step-02 can differ in cosmetic detail (quote style, module qualification, re-export resolution). Without normalization, those cosmetic differences surface as false-positive "Changed" and "Removed" entries even when the source commit has not moved. Apply these transforms to both sets symmetrically:
38
+ **Canonicalize extractor methodology differences before matching.** The extractor used by `skf-create-skill` at baseline time and the re-extractor used by step 2 can differ in cosmetic detail (quote style, module qualification, re-export resolution). Without normalization, those cosmetic differences surface as false-positive "Changed" and "Removed" entries even when the source commit has not moved. Apply these transforms to both sets symmetrically:
33
39
 
34
40
  - **Quote style on string defaults.** Normalize string-literal defaults in signatures to a single style — e.g., `kind: str = "Hnsw"` ↔ `kind: str = 'Hnsw'`. Pick one canonical form and apply to both sides.
35
41
  - **Module qualification of stdlib helpers.** Strip module prefixes on well-known stdlib helpers when the unqualified form is importable at the call site: `dataclasses.field(...)` → `field(...)`, `typing.Optional[...]` → `Optional[...]`, `typing.List[...]` → `List[...]`. Do not collapse user-defined namespaces.
36
- - **Public-API re-export resolution.** When `{source_root}/**/__init__.py` re-exports an internal symbol under a different public name (`from .internal import _Impl as Public`, or via `__all__`), resolve both sides to the public name before key-matching — otherwise a renamed re-export in the current scan shows up as "Removed `_Impl`" + "Added `Public`" instead of matching the baseline entry. Build the re-export map once per package by walking `__init__.py` files.
42
+ - **Public-API re-export resolution.** When `{source_root}/**/__init__.py` re-exports an internal symbol under a different public name (`from .internal import _Impl as Public`, or via `__all__`), resolve both sides to the public name before key-matching — otherwise a renamed re-export in the current scan shows up as "Removed `_Impl`" + "Added `Public`" instead of matching the baseline entry. The re-export map is already in workflow context as `{reexport_map}` (produced by `skf-load-provenance.py normalize` in step 1 §4). Apply it directly without re-walking `__init__.py` files.
37
43
 
38
- Record the set of transforms actually applied in workflow context — step-06 surfaces them in the Provenance section so a reviewer can tell which differences the diff collapsed and which were real.
44
+ Record the set of transforms actually applied in workflow context — step 6 surfaces them in the Provenance section so a reviewer can tell which differences the diff collapsed and which were real.
39
45
 
40
46
  Normalize both sets for comparison:
41
47
  - Match by canonicalized export name (primary key)
42
48
  - Group by file for location-aware comparison
43
49
 
44
- > **Longer-term fix.** The principled remedy is to persist `skf-create-skill`'s ast-grep ruleset to `{forge_version}/extraction-rules.yaml` at create time and have step-02 replay that exact ruleset. When the file is present, step-02 extraction becomes reproducible against the baseline and the canonicalization pass above becomes a no-op. Until then, normalization is the salvage remediation for provenance maps that predate extractor pinning.
50
+ > **Longer-term fix.** The principled remedy is to persist `skf-create-skill`'s ast-grep ruleset to `{forge_version}/extraction-rules.yaml` at create time and have step 2 replay that exact ruleset. When the file is present, step 2 extraction becomes reproducible against the baseline and the canonicalization pass above becomes a no-op. Until then, normalization is the salvage remediation for provenance maps that predate extractor pinning.
45
51
 
46
52
  ### 2. Detect Added Exports
47
53
 
@@ -87,16 +93,28 @@ For each changed export, record:
87
93
 
88
94
  **Only execute if provenance-map.json contains `file_entries`.**
89
95
 
90
- For each entry in `file_entries`:
91
- 1. Locate the source file at the original `source_file` path
92
- 2. Compute current SHA-256 content hash (bare hex `hashlib.sha256(...).hexdigest()`, `sha256sum`, and `openssl dgst` all produce this form)
93
- 3. **Normalize the stored hash before comparison.** `skf-create-skill` writes `content_hash` with a leading algorithm-name prefix (`"sha256:879bfcc2…"`). A bare-hex hash from `hashlib` will never equal the prefixed value byte-for-byte, so without normalization every `file_entry` flags as CHANGED on every audit. Strip the algorithm prefix before comparing — accept any leading lowercase-alphanumeric prefix terminated by `:` (e.g. `sha256:`, `sha1:`, `md5:`); if no prefix is present, leave the value unchanged. The reader-side normalization is unconditionally safe — applying it to bare-hex values produced by a fixed writer is a no-op.
94
- 4. Compare the normalized stored hash against the freshly computed hash:
95
- - CHANGED: hash mismatch record as script/asset content drift
96
- - MISSING: source file no longer exists → record as removed
97
- - NEW: source contains files matching script/asset patterns not in `file_entries` → record as added
96
+ **Resolve `{compareFileHashesHelper}`** from `{compareFileHashesProbeOrder}`; first existing path wins. HALT if no candidate exists.
97
+
98
+ Run one deterministic comparison subprocess it walks tracked file_entries[] AND the inverse direction (source-tree candidate set in standard script/asset/doc directories) so the LLM does not orchestrate per-file hashing:
99
+
100
+ ```bash
101
+ uv run {compareFileHashesHelper} compare {provenanceMap} {sourceRoot}
102
+ ```
103
+
104
+ Parse the emitted JSON:
105
+
106
+ ```
107
+ {
108
+ "added": ["<rel-path>", ...], // present on disk in tracked dirs, NOT in file_entries
109
+ "removed": ["<rel-path>", ...], // in file_entries, missing on disk
110
+ "changed": [{"path": "...", "stored_hash": "sha256:...", "current_hash": "sha256:..."}],
111
+ "stats": {"added": N, "removed": N, "changed": N, "unchanged": N}
112
+ }
113
+ ```
114
+
115
+ Hash-prefix normalization (writer-vs-reader compatibility — `skf-create-skill` writes `content_hash` with a `"sha256:"` prefix, a bare-hex hash from `hashlib` would otherwise never match) is handled inside the script. Downstream consumers read `added`/`removed`/`changed` directly with no further normalization.
98
116
 
99
- Append results to the Structural Drift section as "### Script/Asset Drift ({count})".
117
+ Append the three lists into the Structural Drift section as "### Script/Asset Drift ({stats.added + stats.removed + stats.changed})".
100
118
 
101
119
  ### Stack-Specific Structural Diff
102
120
 
@@ -164,7 +182,7 @@ Append to {outputFile}:
164
182
  ### 6. Update Report and Auto-Proceed
165
183
 
166
184
  Update {outputFile} frontmatter:
167
- - Append `'step-03-structural-diff'` to `stepsCompleted`
185
+ - Append `'structural-diff'` to `stepsCompleted`
168
186
 
169
187
  ### 7. Present MENU OPTIONS
170
188
 
@@ -13,6 +13,14 @@ A good skill brief sets a tight, cohesive boundary: one capability with 3-8 prim
13
13
 
14
14
  Brief-skill is split from create-skill so the scoping conversation runs *once*, on cheap signals (manifests, top-level exports, intent), without paying for AST extraction. Compilation is expensive; scoping decisions are cheap to revise. Keeping them in separate workflows lets a user iterate on the brief, share it for review, and re-run create-skill against the same brief whenever the upstream version moves.
15
15
 
16
+ ## Conventions
17
+
18
+ - Bare paths (e.g. `references/<name>.md`) resolve from the skill root.
19
+ - `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.
20
+ - `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives, if present).
21
+ - `{project-root}`-prefixed paths resolve from the project working directory.
22
+ - `{skill-name}` resolves to the skill directory's basename.
23
+
16
24
  ## Role
17
25
 
18
26
  You are a skill scoping architect collaborating with a developer who wants to create an agent skill. You bring expertise in source code analysis, API surface identification, and skill boundary design, while the user brings their domain knowledge and specific use case. Work together as equals.
@@ -21,11 +29,9 @@ You are a skill scoping architect collaborating with a developer who wants to cr
21
29
 
22
30
  These rules apply to every step in this workflow:
23
31
 
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
- - **Lazy-load references and assets:** `references/*.md` and `assets/*.md` files are loaded inside the section that needs them, not at step entry. If a section is skipped (e.g. `version-resolution.md` when `{extractPublicApiScript}` already returned a version, `scope-templates.md` for the `docs-only` branch that bypasses §2c), do not load that file. Each unnecessary load costs context (~5-10 KB per reference) and biases the LLM toward consulting material the current path does not need.
28
- - Always communicate in `{communication_language}` (the language for user-facing prose). Written artifact text — the `description`, `notes`, and other free-form fields persisted into `skill-brief.yaml` — is in `{document_output_language}`; per-step rules call this out where it applies (see step-05). The two values may be the same.
33
+ - **Lazy-load references and assets:** `references/*.md` and `assets/*.md` files are loaded inside the section that needs them, not at step entry. If a section is skipped (e.g. `version-resolution.md` when `{extractPublicApiHelper}` already returned a version, `scope-templates.md` for the `docs-only` branch that bypasses §2c), do not load that file. Each unnecessary load costs context (~5-10 KB per reference) and biases the LLM toward consulting material the current path does not need.
34
+ - Always communicate in `{communication_language}` (the language for user-facing prose). Written artifact text — the `description`, `notes`, and other free-form fields persisted into `skill-brief.yaml` — is in `{document_output_language}`; per-step rules call this out where it applies (see step 5). The two values may be the same.
29
35
  - If `{headless_mode}` is true, auto-proceed through confirmation gates with their default action and log each auto-decision
30
36
 
31
37
  ## On Activation
@@ -35,27 +41,51 @@ These rules apply to every step in this workflow:
35
41
 
36
42
  2. **Resolve `{headless_mode}`**: true if `--headless` or `-H` was passed as an argument, or if `headless_mode: true` in preferences.yaml. Default: false.
37
43
 
38
- 3. Load, read the full file, and execute `./steps-c/step-01-gather-intent.md`.
44
+ 3. **Resolve workflow customization.** Run:
45
+
46
+ ```bash
47
+ python3 {project-root}/_bmad/scripts/resolve_customization.py \
48
+ --skill {skill-root} --key workflow
49
+ ```
50
+
51
+ The script merges the three customization layers per `bmad-customize`'s structural merge rules (scalars override, arrays append):
52
+
53
+ - `{skill-root}/customize.toml` — bundled defaults
54
+ - `_bmad/custom/<skill-name>.toml` under `{project-root}` — team overrides (committed)
55
+ - `_bmad/custom/<skill-name>.user.toml` under `{project-root}` — personal overrides (gitignored)
56
+
57
+ 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.
58
+
59
+ Apply the path-scalar fallback now so stage files don't have to repeat the conditional logic. For each of the three scalars, if the merged value is empty or absent, use the bundled default:
60
+
61
+ - `{descriptionVoiceExamplesPath}` ← `workflow.description_voice_examples_path` if non-empty, else `assets/description-voice-examples.md`
62
+ - `{scopeTemplatesPath}` ← `workflow.scope_templates_path` if non-empty, else `assets/scope-templates.md`
63
+ - `{briefSchemaPath}` ← `workflow.brief_schema_path` if non-empty, else `assets/skill-brief-schema.md`
64
+
65
+ Stash all three as workflow-context variables. Stage files reference `{descriptionVoiceExamplesPath}` / `{scopeTemplatesPath}` / `{briefSchemaPath}` directly — no conditional at the usage site. Empty-string overrides cleanly fall through to the bundled default; non-empty values let orgs swap in house-style copies without forking the skill.
66
+
67
+ 4. Load, read the full file, and execute `references/gather-intent.md`.
39
68
 
40
69
  ## Stages
41
70
 
42
71
  | # | Step | File | Auto-proceed |
43
72
  |---|------|------|--------------|
44
- | 1 | Gather Intent | steps-c/step-01-gather-intent.md | No (interactive) |
45
- | 2 | Analyze Target | steps-c/step-02-analyze-target.md | Yes |
46
- | 3 | Scope Definition | steps-c/step-03-scope-definition.md | No (interactive) |
47
- | 4 | Confirm Brief | steps-c/step-04-confirm-brief.md | No (confirm) |
48
- | 5 | Write Brief | steps-c/step-05-write-brief.md | Yes |
49
- | 6 | Workflow Health Check (terminal) | steps-c/step-06-health-check.md | Yes |
73
+ | 1 | Gather Intent | references/gather-intent.md | No (interactive) |
74
+ | 2 | Analyze Target | references/analyze-target.md | Yes |
75
+ | 3 | Scope Definition | references/scope-definition.md | No (interactive) |
76
+ | 4 | Confirm Brief | references/confirm-brief.md | No (confirm) |
77
+ | 5 | Write Brief | references/write-brief.md | Yes |
78
+ | 6 | Workflow Health Check (terminal) | references/health-check.md | Yes |
50
79
 
51
80
  ## Invocation Contract
52
81
 
53
82
  | Aspect | Detail |
54
83
  |--------|--------|
55
84
  | **Inputs** | `target_repo` [required], `skill_name` [required], `scope_hint` [optional], `language_hint` [optional], `target_version` [optional], `source_authority` [optional: official/community/internal, default community], `source_type` [optional: source/docs-only, default source], `doc_urls` [optional: list of `url[,label]` for source_type=docs-only or supplemental], `scope_type` [optional: full-library/specific-modules/public-api/component-library/reference-app/docs-only], `include` [optional: comma-separated globs], `exclude` [optional: comma-separated globs], `scripts_intent` [optional: detect/none/free-text, default detect], `assets_intent` [optional: detect/none/free-text, default detect], `intent` [optional: free-text used to derive description], `force` [optional: overwrite existing brief without prompting] |
56
- | **Gates** | step-01: Input Gate [use args] | step-03: Confirm Gate [C] | step-04: Confirm Gate [C] |
85
+ | **Gates** | step 1: Input Gate [use args] | step 3: Confirm Gate [C] | step 4: Confirm Gate [C] |
57
86
  | **Outputs** | `skill-brief.yaml` at `{forge_data_folder}/{skill-name}/skill-brief.yaml`; final `SKF_BRIEF_RESULT_JSON` line on stdout when `{headless_mode}` is true |
58
87
  | **Headless** | All gates auto-resolve with heuristic-driven or default action when `{headless_mode}` is true; pre-supplied inputs consumed at the gates that would otherwise prompt; absent `source_authority` and `scope_type` are resolved by signal-driven detection (see `references/headless-args.md`); existing briefs are preserved unless `--force` was supplied (HALT with `overwrite-cancelled` otherwise) |
88
+ | **Transient-failure retry** | This workflow does **not** auto-retry network or subprocess failures. A failed `gh` fetch (analyze-target.md §1, portfolio-similarity-check.md), QMD probe, or extraction script is logged and surfaced in the final result envelope as a warning, but the workflow continues with whatever signal it has. Headless pipelines that want retry semantics should wrap the invocation at their orchestrator level (e.g. CI re-runner on non-zero exit). Rationale: brief-skill is read-mostly with one terminal write (the YAML at step 5); a partial-signal retry has more failure modes than just re-running the whole workflow, which is cheap. |
59
89
  | **Exit codes** | See "Exit Codes" below |
60
90
 
61
91
  ## Exit Codes
@@ -64,16 +94,16 @@ Every HARD HALT in this workflow exits with a stable code so headless automators
64
94
 
65
95
  | Code | Meaning | Raised by |
66
96
  | ---- | -------------------- | ------------------------------------------------------------------------------------------ |
67
- | 0 | success | step-06 (terminal) |
68
- | 2 | input-missing / input-invalid | step-01 GATE — required headless arg absent (`target_repo`, `skill_name`, or `doc_urls` when `source_type=docs-only`) → `input-missing`; enum violation, malformed semver, non-kebab `skill_name`, or step-05 brief-context schema validation failure → `input-invalid` |
69
- | 3 | resolution-failure | step-01 §1 (`forge-tier.yaml` missing); step-02 §1 (target inaccessible / `gh auth` fails) |
70
- | 4 | write-failure | step-01 §1 pre-flight write probe (data folder unwritable: read-only mount, disk full, permissions denied); step-05 §4 (write to `{forge_data_folder}/{skill-name}/skill-brief.yaml` failed) |
71
- | 5 | overwrite-cancelled | step-05 §2 (existing brief, `force` not supplied) |
72
- | 6 | user-cancelled | any interactive menu in step-01/03/04 (user selected `[X]` Cancel and exit) |
97
+ | 0 | success | step 6 (terminal) |
98
+ | 2 | input-missing / input-invalid | step 1 GATE — required headless arg absent (`target_repo`, `skill_name`, or `doc_urls` when `source_type=docs-only`) → `input-missing`; enum violation, malformed semver, non-kebab `skill_name`, or step 5 brief-context schema validation failure → `input-invalid` |
99
+ | 3 | resolution-failure | step 1 §1 (`forge-tier.yaml` missing); step 2 §1 (target inaccessible / `gh auth` fails) |
100
+ | 4 | write-failure | step 1 §1 pre-flight write probe (data folder unwritable: read-only mount, disk full, permissions denied); step 5 §4 (write to `{forge_data_folder}/{skill-name}/skill-brief.yaml` failed) |
101
+ | 5 | overwrite-cancelled | step 5 §2 (existing brief, `force` not supplied) |
102
+ | 6 | user-cancelled | any interactive menu in step 1/03/04 (user selected `[X]` Cancel and exit) |
73
103
 
74
104
  ## Result Contract (Headless)
75
105
 
76
- When `{headless_mode}` is true, step-05 emits a single-line JSON envelope on **stdout** before chaining to step-06, and every HARD HALT emits the same envelope shape on **stderr** with `status: "error"`:
106
+ When `{headless_mode}` is true, step 5 emits a single-line JSON envelope on **stdout** before chaining to step 6, and every HARD HALT emits the same envelope shape on **stderr** with `status: "error"`:
77
107
 
78
108
  ```
79
109
  SKF_BRIEF_RESULT_JSON: {"status":"success|error","brief_path":"…|null","skill_name":"…","version":"…|null","language":"…|null","scope_type":"…|null","exit_code":0,"halt_reason":null}
@@ -1,6 +1,6 @@
1
1
  # Description Voice Examples
2
2
 
3
- Loaded by step-01 §7b only. The five examples below show the *range* of acceptable voices for the `description` field — they vary in lead, structure, and trigger phrasing on purpose. The point is to anchor the LLM to "two facts must come through (what the skill is, when to use it); everything else is voice — do not template-stamp."
3
+ Loaded by step 1 §7b only. The five examples below show the *range* of acceptable voices for the `description` field — they vary in lead, structure, and trigger phrasing on purpose. The point is to anchor the LLM to "two facts must come through (what the skill is, when to use it); everything else is voice — do not template-stamp."
4
4
 
5
5
  ## Examples
6
6
 
@@ -46,7 +46,7 @@ If the source is a remote GitHub repo, use `gh api repos/{owner}/{repo}/contents
46
46
 
47
47
  If detection succeeds, use the detected version. If it fails or returns a non-semver value, fall back to `"1.0.0"`.
48
48
 
49
- The create-skill workflow (step-03-extract) also performs version reconciliation at extraction time — if the source version has changed since the brief was created, the extraction step warns and uses the source version.
49
+ The create-skill workflow (extract) also performs version reconciliation at extraction time — if the source version has changed since the brief was created, the extraction step warns and uses the source version.
50
50
 
51
51
  **Target version override:** When `target_version` is present in the brief, it takes precedence over auto-detection. Auto-detection still runs for informational purposes (displayed as "Detected version" alongside the user-specified "Target version"), but the `target_version` value is used as the brief's `version` field. This is particularly useful for docs-only skills (where no package manifest exists) and when the user wants to compile a skill for a specific older version.
52
52
 
@@ -67,6 +67,14 @@ scope:
67
67
  # - "code/core/src/manager-api/**"
68
68
  # - "code/core/src/preview-api/**"
69
69
  notes: "Optional notes about scope decisions"
70
+ # Optional: authoring-time scope-type rationale (written once by brief-skill 2c)
71
+ # rationale:
72
+ # recommended: full-library
73
+ # chosen: public-api
74
+ # accepted_recommendation: false
75
+ # heuristic: narrow-public-api
76
+ # reason: "user overrode full-library->public-api: only documented API ships"
77
+ # recorded: "2026-05-18"
70
78
  # Optional: amendment log for scope decisions made during create-skill §2a,
71
79
  # update-skill §1b (auth-doc), and update-skill §1c (scope-expansion).
72
80
  # amendments:
@@ -94,6 +102,28 @@ scope:
94
102
  # - "**/*.stories.*"
95
103
  ```
96
104
 
105
+ ### Scope Rationale (Optional)
106
+
107
+ `scope.rationale` is a single optional object recording **why the scope type was chosen at authoring time**. Unlike `scope.amendments[]` (an additive log that accumulates post-authoring decisions across workflow runs), `scope.rationale` is one decision, written once by `skf-brief-skill` step 03 §2c and revised in place on a step-4 `[R]` re-entry. It sits structurally beside `scope.amendments`, reusing the same structured / script-readable / human-auditable ethos rather than a prose decision log.
108
+
109
+ **Fields:**
110
+
111
+ | Field | Type | Required | Source |
112
+ |---|---|---|---|
113
+ | `recommended` | string (one of the six `scope.type` values) | yes | `skf-recommend-scope-type.py` → `scope_type` |
114
+ | `chosen` | string (one of the six) | yes | final `scope.type` |
115
+ | `accepted_recommendation` | bool | yes | `chosen == recommended` |
116
+ | `heuristic` | string | yes | script `matched_heuristic` |
117
+ | `reason` | string | yes | accepted → script `rationale` verbatim; overridden → user's stated reason, or `"user overrode {recommended}->{chosen}; reason not stated"` |
118
+ | `recorded` | string (ISO date `YYYY-MM-DD`) | yes | current date — mirrors `amendments[].date` |
119
+
120
+ **Who reads `scope.rationale`:**
121
+
122
+ - Humans reviewing the brief — it records why the boundary was drawn the way it was.
123
+ - `skf-update-skill` Update intent MAY later surface conflicts against it (e.g., a scope change that contradicts the original authoring decision). **Not implemented now — deferred.** The field is forward-compatible; the reader is wired later.
124
+
125
+ **Backward compatibility:** `scope.rationale` is optional. Briefs without this field validate unchanged — treat missing as absent (null). Mirrors the `scope.amendments` backward-compat rule.
126
+
97
127
  ### Scope Amendments (Optional)
98
128
 
99
129
  `scope.amendments[]` is an additive, optional audit log of scope decisions made by workflows after the brief was first authored. Two writer paths exist today:
@@ -171,7 +201,7 @@ scope:
171
201
 
172
202
  ## Human-Readable Presentation Format
173
203
 
174
- The runtime template lives in `steps-c/step-04-confirm-brief.md` §2 — that is the single source of truth for how the brief is rendered for user confirmation (brief-skill step-04 only; analyze-source batch generation does not render). If the rendering format needs to change, edit the step file. This asset documents the data contract; the step owns the presentation.
204
+ The runtime template lives in `references/confirm-brief.md` §2 — that is the single source of truth for how the brief is rendered for user confirmation (brief-skill step 4 only; analyze-source batch generation does not render). If the rendering format needs to change, edit the step file. This asset documents the data contract; the step owns the presentation.
175
205
 
176
206
  ## Validation Rules
177
207
 
@@ -0,0 +1,44 @@
1
+ # DO NOT EDIT -- overwritten on every update.
2
+ #
3
+ # Workflow customization surface for skf-brief-skill.
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 brief authoring 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
+ # (house style, naming conventions, description-voice guardrails).
25
+ # Overrides append.
26
+ #
27
+ # Each entry is either:
28
+ # - a literal sentence, e.g. "Skill briefs must cite an authoritative source."
29
+ # - a file reference prefixed with `file:`, e.g.
30
+ # "file:{project-root}/docs/brief-style.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
+ description_voice_examples_path = ""
43
+ scope_templates_path = ""
44
+ brief_schema_path = ""
@@ -1,11 +1,19 @@
1
1
  ---
2
- nextStepFile: './step-03-scope-definition.md'
2
+ nextStepFile: 'scope-definition.md'
3
3
  versionResolutionFile: 'references/version-resolution.md'
4
- extractPublicApiScript: '{project-root}/src/shared/scripts/skf-extract-public-api.py'
5
- detectWorkspacesScript: '{project-root}/src/shared/scripts/skf-detect-workspaces.py'
6
- detectLanguageScript: '{project-root}/src/shared/scripts/skf-detect-language.py'
4
+ extractPublicApiProbeOrder:
5
+ - '{project-root}/_bmad/skf/shared/scripts/skf-extract-public-api.py'
6
+ - '{project-root}/src/shared/scripts/skf-extract-public-api.py'
7
+ detectWorkspacesProbeOrder:
8
+ - '{project-root}/_bmad/skf/shared/scripts/skf-detect-workspaces.py'
9
+ - '{project-root}/src/shared/scripts/skf-detect-workspaces.py'
10
+ detectLanguageProbeOrder:
11
+ - '{project-root}/_bmad/skf/shared/scripts/skf-detect-language.py'
12
+ - '{project-root}/src/shared/scripts/skf-detect-language.py'
7
13
  ---
8
14
 
15
+ <!-- Config: communicate in {communication_language}. -->
16
+
9
17
  # Step 2: Analyze Target
10
18
 
11
19
  ## STEP GOAL:
@@ -21,8 +29,6 @@ To analyze the target repository by resolving its location, reading its structur
21
29
 
22
30
  ## MANDATORY SEQUENCE
23
31
 
24
- **CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise unless user explicitly requests a change.
25
-
26
32
  ### 1. Resolve Target Location
27
33
 
28
34
  **For GitHub URLs:**
@@ -58,11 +64,13 @@ Display: "**Resolving target...**"
58
64
 
59
65
  ### 1b. Detect Monorepo / Workspace Layout
60
66
 
61
- Delegate workspace detection to `{detectWorkspacesScript}` instead of reasoning through manifest rules in prose. Build a payload from the tree fetched in §1 plus the small set of root manifests the detector needs, then invoke the script:
67
+ **Resolve `{detectWorkspacesHelper}`** from `{detectWorkspacesProbeOrder}`; first existing path wins. HALT if no candidate exists.
68
+
69
+ Delegate workspace detection to `{detectWorkspacesHelper}` instead of reasoning through manifest rules in prose. Build a payload from the tree fetched in §1 plus the small set of root manifests the detector needs, then invoke the script:
62
70
 
63
71
  ```bash
64
72
  echo '{"tree": [<flat list of repo-relative file paths>], "manifests": {"package.json": "<raw text>", "Cargo.toml": "<raw text>", "pnpm-workspace.yaml": "<raw text>", "lerna.json": "<raw text>"}}' | \
65
- uv run {detectWorkspacesScript}
73
+ uv run {detectWorkspacesHelper}
66
74
  ```
67
75
 
68
76
  - **`tree`** — pass the flat list of repo-relative file paths already fetched in §1 (for GitHub: the `path` values from the `gh api .../git/trees/HEAD?recursive=1` response; for local: the equivalent listing).
@@ -79,7 +87,7 @@ This looks like a monorepo ({manifest_kind}) with these workspaces:
79
87
  1. {workspaces[0].name} ({workspaces[0].path})
80
88
  2. {workspaces[1].name} ({workspaces[1].path})
81
89
  ...
82
- Which one should the skill cover? Pick a number, type 'all' to scope at the repo root, or 'list' to keep listing more.
90
+ Which one should the skill cover? Pick a number, or type 'all' to scope at the repo root.
83
91
  ```
84
92
 
85
93
  Interactive: wait for the user choice. On a numbered choice, store `monorepo_workspace: {path}` and rebase §2-§4b against that path. On `'all'`, leave `monorepo_workspace` unset and proceed at the repo root with a note in the analysis summary that scope is unfiltered.
@@ -104,10 +112,12 @@ List the top-level directory structure:
104
112
 
105
113
  ### 3. Detect Primary Language
106
114
 
107
- Delegate the rule walk to `{detectLanguageScript}` instead of evaluating manifest presence and extension frequency in prose:
115
+ **Resolve `{detectLanguageHelper}`** from `{detectLanguageProbeOrder}`; first existing path wins. HALT if no candidate exists.
116
+
117
+ Delegate the rule walk to `{detectLanguageHelper}` instead of evaluating manifest presence and extension frequency in prose:
108
118
 
109
119
  ```bash
110
- echo '{"tree": [<flat list of repo-relative file paths from §1>]}' | uv run {detectLanguageScript}
120
+ echo '{"tree": [<flat list of repo-relative file paths from §1>]}' | uv run {detectLanguageHelper}
111
121
  ```
112
122
 
113
123
  The script returns `{language, confidence, detection_source, fallback_to_extension_frequency}` after walking the documented rule table (manifest presence first — package.json with tsconfig.json disambiguation, Cargo.toml, pyproject.toml/setup.py/setup.cfg, go.mod, pom.xml, build.gradle.kts, build.gradle Groovy with Java/Kotlin disambiguation, *.csproj/*.sln, Gemfile — then extension-frequency fallback over recognized source extensions). Use the returned values directly:
@@ -120,7 +130,9 @@ If `confidence` is `low` (or `unknown` is returned for `language`): flag for use
120
130
 
121
131
  ### 4. List Top-Level Modules and Exports
122
132
 
123
- Identify the public API surface. **Delegate the parsing to `{extractPublicApiScript}` whenever the detected language is supported** — the script is the single source of truth for manifest parsing, export discovery, and version detection across the whole SKF pipeline. Hand-rolling these in prose creates drift seams the LLM cannot fully close.
133
+ **Resolve `{extractPublicApiHelper}`** from `{extractPublicApiProbeOrder}`; first existing path wins. HALT if no candidate exists.
134
+
135
+ Identify the public API surface. **Delegate the parsing to `{extractPublicApiHelper}` whenever the detected language is supported** — the script is the single source of truth for manifest parsing, export discovery, and version detection across the whole SKF pipeline. Hand-rolling these in prose creates drift seams the LLM cannot fully close.
124
136
 
125
137
  **Script-supported languages** (use the script): `js`, `ts`, `javascript`, `typescript`, `python`, `rust`, `go`, `java`, `kotlin`.
126
138
 
@@ -153,7 +165,7 @@ This section runs exactly one of §4.1 (script path) or §4.2 (fallback path) ba
153
165
  3. Invoke the script and parse its JSON stdout:
154
166
 
155
167
  ```bash
156
- echo '<payload-json>' | uv run {extractPublicApiScript} --language <lang> --mode quick
168
+ echo '<payload-json>' | uv run {extractPublicApiHelper} --mode quick
157
169
  ```
158
170
 
159
171
  On a non-zero exit (codes 1 or 2 per the script's docstring), capture stderr, log it, and fall through to §4.2 (the prose-fallback path) — never HALT just because the script choked on an unusual manifest.
@@ -200,7 +212,7 @@ If CCC is unavailable or returns no results: skip this subsection silently.
200
212
 
201
213
  ### 4b. Detect Source Version
202
214
 
203
- **When the language was script-supported (§4 took the script path):** the `version` field returned by `{extractPublicApiScript}` IS the detected version — do not re-derive it and do not load `{versionResolutionFile}`. The script already implements the language-specific lookups documented in that reference, so loading the reference here only burns context.
215
+ **When the language was script-supported (§4 took the script path):** the `version` field returned by `{extractPublicApiHelper}` IS the detected version — do not re-derive it and do not load `{versionResolutionFile}`. The script already implements the language-specific lookups documented in that reference, so loading the reference here only burns context.
204
216
 
205
217
  **When the language was not script-supported:** load `{versionResolutionFile}` and follow the prose Detection Algorithm directly (Ruby / C# / Swift / etc. fall outside the script's coverage).
206
218
 
@@ -268,5 +280,5 @@ Pause briefly for user input. If the user provides corrections or asks questions
268
280
 
269
281
  ## CRITICAL STEP COMPLETION NOTE
270
282
 
271
- ONLY WHEN the analysis is complete and the summary has been presented to the user will you load and read fully `./step-03-scope-definition.md` to begin scope definition.
283
+ ONLY WHEN the analysis is complete and the summary has been presented to the user will you load and read fully `scope-definition.md` to begin scope definition.
272
284