bmad-module-skill-forge 2.2.0 → 3.0.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 (435) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/README.md +49 -49
  3. package/docs/404.md +10 -8
  4. package/docs/_data/pinned.yaml +22 -13
  5. package/docs/_internal/STABILITY.md +58 -35
  6. package/docs/agents.md +39 -53
  7. package/docs/architecture.md +65 -51
  8. package/docs/bmad-synergy.md +53 -51
  9. package/docs/campaign.md +127 -75
  10. package/docs/concepts.md +34 -28
  11. package/docs/examples.md +70 -68
  12. package/docs/forge-auto.md +34 -31
  13. package/docs/getting-started.md +118 -57
  14. package/docs/how-it-works.md +25 -21
  15. package/docs/index.md +15 -15
  16. package/docs/skill-model.md +70 -59
  17. package/docs/troubleshooting.md +135 -18
  18. package/docs/verifying-a-skill.md +83 -57
  19. package/docs/why-skf.md +24 -22
  20. package/docs/workflows.md +274 -110
  21. package/package.json +18 -10
  22. package/src/forger/preferences.yaml +8 -1
  23. package/src/knowledge/agentskills-spec.md +2 -0
  24. package/src/knowledge/ccc-bridge.md +40 -24
  25. package/src/knowledge/confidence-tiers.md +9 -5
  26. package/src/knowledge/overview.md +3 -3
  27. package/src/knowledge/progressive-capability.md +8 -8
  28. package/src/knowledge/provenance-tracking.md +9 -5
  29. package/src/knowledge/qmd-registry.md +2 -2
  30. package/src/knowledge/skf-knowledge-index.csv +2 -2
  31. package/src/knowledge/skill-lifecycle.md +18 -11
  32. package/src/knowledge/split-body-strategy.md +0 -3
  33. package/src/knowledge/tool-resolution.md +4 -2
  34. package/src/knowledge/version-paths.md +101 -15
  35. package/src/module-help.csv +3 -3
  36. package/src/module.yaml +10 -0
  37. package/src/shared/data/ast-grep-recipes.yaml +608 -0
  38. package/src/shared/data/ide-context-files.json +30 -0
  39. package/src/shared/health-check.md +32 -12
  40. package/src/shared/references/description-guard-protocol.md +12 -9
  41. package/src/shared/references/feasibility-report-schema.md +19 -13
  42. package/src/shared/references/headless-gate-convention.md +55 -3
  43. package/src/shared/references/output-contract-schema.md +19 -8
  44. package/src/shared/references/pipeline-contracts.md +94 -29
  45. package/src/shared/references/tessl-review.md +77 -0
  46. package/src/shared/scripts/schemas/skf-analyze-result-envelope.v1.json +194 -0
  47. package/src/shared/scripts/schemas/skf-audit-result-envelope.v1.json +192 -0
  48. package/src/shared/scripts/schemas/skf-brief-result-envelope.v1.json +32 -4
  49. package/src/shared/scripts/schemas/skf-campaign-result-envelope.v1.json +174 -0
  50. package/src/shared/scripts/schemas/skf-create-skill-result-envelope.v1.json +284 -0
  51. package/src/shared/scripts/schemas/skf-drop-skill-result-envelope.v1.json +164 -0
  52. package/src/shared/scripts/schemas/skf-export-result-envelope.v1.json +160 -0
  53. package/src/shared/scripts/schemas/skf-quick-skill-result-envelope.v1.json +261 -0
  54. package/src/shared/scripts/schemas/skf-refine-architecture-result-envelope.v1.json +192 -0
  55. package/src/shared/scripts/schemas/skf-rename-skill-result-envelope.v1.json +179 -0
  56. package/src/shared/scripts/schemas/skf-setup-result-envelope.v1.json +27 -11
  57. package/src/shared/scripts/schemas/skf-stack-result-envelope.v1.json +176 -0
  58. package/src/shared/scripts/schemas/skf-test-result-envelope.v1.json +173 -0
  59. package/src/shared/scripts/schemas/skf-update-result-envelope.v1.json +19 -5
  60. package/src/shared/scripts/schemas/skf-verify-stack-result-envelope.v1.json +180 -0
  61. package/src/shared/scripts/schemas/skill-brief.v1.json +34 -0
  62. package/src/shared/scripts/schemas/workspace-detection.v1.json +1 -1
  63. package/src/shared/scripts/skf-atomic-write.py +30 -14
  64. package/src/shared/scripts/skf-build-change-manifest.py +2203 -24
  65. package/src/shared/scripts/skf-ccc-git-hygiene.py +532 -0
  66. package/src/shared/scripts/skf-check-unit-records.py +184 -0
  67. package/src/shared/scripts/skf-check-workspace-drift.py +538 -9
  68. package/src/shared/scripts/skf-classify-changed-files.py +694 -0
  69. package/src/shared/scripts/skf-comention-pairs.py +1333 -123
  70. package/src/shared/scripts/skf-compare-file-hashes.py +1 -1
  71. package/src/shared/scripts/skf-count-imports.py +1867 -0
  72. package/src/shared/scripts/skf-count-tokens.py +1 -1
  73. package/src/shared/scripts/skf-derive-assembly-shape.py +3 -2
  74. package/src/shared/scripts/skf-description-guard.py +99 -11
  75. package/src/shared/scripts/skf-detect-docs.py +694 -2
  76. package/src/shared/scripts/skf-detect-language.py +486 -107
  77. package/src/shared/scripts/skf-detect-registry.py +887 -0
  78. package/src/shared/scripts/skf-detect-scripts-assets.py +1 -1
  79. package/src/shared/scripts/skf-detect-tools.py +209 -27
  80. package/src/shared/scripts/skf-detect-workspaces.py +506 -30
  81. package/src/shared/scripts/skf-disqualify-candidates.py +821 -182
  82. package/src/shared/scripts/skf-emit-brief-result-envelope.py +69 -191
  83. package/src/shared/scripts/skf-emit-result-envelope.py +1604 -106
  84. package/src/shared/scripts/skf-enumerate-stack-skills.py +986 -117
  85. package/src/shared/scripts/skf-extract-public-api.py +4084 -85
  86. package/src/shared/scripts/skf-extraction-inventory.py +746 -0
  87. package/src/shared/scripts/skf-extraction-snapshot.py +539 -0
  88. package/src/shared/scripts/skf-fetch-temporal.py +674 -0
  89. package/src/shared/scripts/skf-find-cycles.py +97 -29
  90. package/src/shared/scripts/skf-find-test-report.py +476 -0
  91. package/src/shared/scripts/skf-forge-tier-rw.py +444 -203
  92. package/src/shared/scripts/skf-github-fetch.py +365 -0
  93. package/src/shared/scripts/skf-github-probe.py +661 -0
  94. package/src/shared/scripts/skf-hash-content.py +166 -12
  95. package/src/shared/scripts/skf-language-corpora.py +1 -1
  96. package/src/shared/scripts/skf-load-provenance.py +159 -27
  97. package/src/shared/scripts/skf-manifest-ops.py +1 -1
  98. package/src/shared/scripts/skf-merge-ccc-exclusions.py +2307 -223
  99. package/src/shared/scripts/skf-merge-doc-urls.py +1 -1
  100. package/src/shared/scripts/skf-names-present.py +221 -0
  101. package/src/shared/scripts/skf-pair-intersect.py +119 -28
  102. package/src/shared/scripts/skf-parse-gaps.py +1384 -0
  103. package/src/shared/scripts/skf-preapply.py +1 -1
  104. package/src/shared/scripts/skf-preflight.py +161 -27
  105. package/src/shared/scripts/skf-promote-staged.py +430 -0
  106. package/src/shared/scripts/skf-provenance-gap-dispatch.py +39 -7
  107. package/src/shared/scripts/skf-qmd-classify-collections.py +229 -45
  108. package/src/shared/scripts/skf-quick-batch.py +774 -0
  109. package/src/shared/scripts/skf-rebuild-managed-sections.py +972 -88
  110. package/src/shared/scripts/skf-recommend-scope-type.py +323 -156
  111. package/src/shared/scripts/skf-render-metadata-stats.py +156 -12
  112. package/src/shared/scripts/skf-render-quick-metadata.py +132 -28
  113. package/src/shared/scripts/skf-render-stack-metadata.py +976 -0
  114. package/src/shared/scripts/skf-resolve-authoritative-files.py +128 -13
  115. package/src/shared/scripts/skf-resolve-package.py +523 -106
  116. package/src/shared/scripts/skf-rewrite-skill-name.py +433 -47
  117. package/src/shared/scripts/skf-run-lock.py +577 -0
  118. package/src/shared/scripts/skf-scan-manifests.py +998 -57
  119. package/src/shared/scripts/skf-scan-skill-md-structure.py +1341 -37
  120. package/src/shared/scripts/skf-severity-classify.py +712 -108
  121. package/src/shared/scripts/skf-shape-detect.py +298 -204
  122. package/src/shared/scripts/skf-shard-body.py +9 -8
  123. package/src/shared/scripts/skf-skill-inventory.py +2412 -89
  124. package/src/shared/scripts/skf-skills-module.py +472 -0
  125. package/src/shared/scripts/skf-source-tree.py +1796 -0
  126. package/src/shared/scripts/skf-structural-diff.py +670 -119
  127. package/src/shared/scripts/skf-tessl-review.py +706 -0
  128. package/src/shared/scripts/skf-update-active-symlink.py +5 -5
  129. package/src/shared/scripts/skf-update-run-state.py +624 -0
  130. package/src/shared/scripts/skf-validate-brief-inputs.py +92 -29
  131. package/src/shared/scripts/skf-validate-brief-schema.py +4 -1
  132. package/src/shared/scripts/skf-validate-feasibility-report.py +577 -66
  133. package/src/shared/scripts/skf-validate-frontmatter.py +103 -26
  134. package/src/shared/scripts/skf-validate-output.py +712 -64
  135. package/src/shared/scripts/skf-validate-pins.py +1 -1
  136. package/src/shared/scripts/skf-verify-no-trace.py +116 -10
  137. package/src/shared/scripts/skf-verify-provenance-completeness.py +2919 -54
  138. package/src/shared/scripts/skf-write-skill-brief.py +367 -19
  139. package/src/shared/tool-requirements.yaml +201 -0
  140. package/src/skf-analyze-source/SKILL.md +41 -36
  141. package/src/skf-analyze-source/assets/skill-brief-schema.md +7 -8
  142. package/src/skf-analyze-source/customize.toml +36 -24
  143. package/src/skf-analyze-source/references/auto-docs-only.md +58 -20
  144. package/src/skf-analyze-source/references/continue.md +2 -13
  145. package/src/skf-analyze-source/references/discover-additional-source.md +147 -0
  146. package/src/skf-analyze-source/references/generate-briefs.md +121 -55
  147. package/src/skf-analyze-source/references/headless-contract.md +42 -15
  148. package/src/skf-analyze-source/references/identify-units.md +96 -110
  149. package/src/skf-analyze-source/references/init.md +73 -71
  150. package/src/skf-analyze-source/references/map-and-detect.md +123 -105
  151. package/src/skf-analyze-source/references/map-unit-exports.md +68 -0
  152. package/src/skf-analyze-source/references/recommend.md +51 -70
  153. package/src/skf-analyze-source/references/scan-project.md +60 -84
  154. package/src/skf-analyze-source/references/scan-root.md +39 -0
  155. package/src/skf-analyze-source/references/step-auto-scope-coexistence.md +47 -0
  156. package/src/skf-analyze-source/references/step-auto-scope-corpora.md +53 -0
  157. package/src/skf-analyze-source/references/step-auto-scope-split.md +91 -0
  158. package/src/skf-analyze-source/references/step-auto-scope.md +208 -293
  159. package/src/skf-analyze-source/references/step-shape-detect.md +14 -12
  160. package/src/skf-analyze-source/references/unit-detection-heuristics.md +37 -42
  161. package/src/skf-audit-skill/SKILL.md +43 -51
  162. package/src/skf-audit-skill/assets/drift-report-template.md +27 -3
  163. package/src/skf-audit-skill/customize.toml +41 -20
  164. package/src/skf-audit-skill/references/constituent-freshness.md +91 -0
  165. package/src/skf-audit-skill/references/doc-drift.md +141 -0
  166. package/src/skf-audit-skill/references/headless-contract.md +29 -0
  167. package/src/skf-audit-skill/references/init.md +148 -210
  168. package/src/skf-audit-skill/references/re-index.md +96 -108
  169. package/src/skf-audit-skill/references/report.md +96 -33
  170. package/src/skf-audit-skill/references/semantic-diff.md +27 -18
  171. package/src/skf-audit-skill/references/severity-classify.md +79 -65
  172. package/src/skf-audit-skill/references/severity-rules.md +15 -6
  173. package/src/skf-audit-skill/references/structural-diff.md +75 -90
  174. package/src/skf-audit-skill/references/upstream-checkout.md +77 -0
  175. package/src/skf-audit-skill/scripts/render-drift-tables.py +685 -0
  176. package/src/skf-brief-skill/SKILL.md +36 -25
  177. package/src/skf-brief-skill/assets/description-voice-examples.md +1 -1
  178. package/src/skf-brief-skill/assets/scope-templates.md +17 -24
  179. package/src/skf-brief-skill/assets/skill-brief-schema.md +29 -15
  180. package/src/skf-brief-skill/customize.toml +48 -20
  181. package/src/skf-brief-skill/references/analyze-target.md +142 -125
  182. package/src/skf-brief-skill/references/confirm-brief.md +10 -8
  183. package/src/skf-brief-skill/references/draft-checkpoint.md +36 -17
  184. package/src/skf-brief-skill/references/gather-intent-ratify.md +68 -0
  185. package/src/skf-brief-skill/references/gather-intent.md +87 -182
  186. package/src/skf-brief-skill/references/headless-args.md +84 -16
  187. package/src/skf-brief-skill/references/health-check.md +1 -1
  188. package/src/skf-brief-skill/references/invocation-contract.md +18 -13
  189. package/src/skf-brief-skill/references/portfolio-similarity-check.md +1 -1
  190. package/src/skf-brief-skill/references/qmd-collection-registration.md +7 -10
  191. package/src/skf-brief-skill/references/scope-definition.md +123 -47
  192. package/src/skf-brief-skill/references/step-auto-brief.md +24 -80
  193. package/src/skf-brief-skill/references/step-auto-validate.md +20 -121
  194. package/src/skf-brief-skill/references/version-resolution.md +3 -2
  195. package/src/skf-brief-skill/references/write-brief.md +66 -57
  196. package/src/skf-campaign/SKILL.md +31 -34
  197. package/src/skf-campaign/assets/campaign-state-schema.json +25 -4
  198. package/src/skf-campaign/customize.toml +47 -16
  199. package/src/skf-campaign/references/campaign-contracts.md +39 -29
  200. package/src/skf-campaign/references/campaign-directive-spec.md +4 -2
  201. package/src/skf-campaign/references/health-check.md +7 -16
  202. package/src/skf-campaign/references/step-01-setup.md +46 -84
  203. package/src/skf-campaign/references/step-02-strategy.md +31 -30
  204. package/src/skf-campaign/references/step-03-pins.md +26 -18
  205. package/src/skf-campaign/references/step-04-provenance.md +24 -23
  206. package/src/skf-campaign/references/step-05-skill-loop.md +67 -48
  207. package/src/skf-campaign/references/step-06-batch.md +41 -34
  208. package/src/skf-campaign/references/step-07-capstone.md +40 -25
  209. package/src/skf-campaign/references/step-08-verify.md +28 -29
  210. package/src/skf-campaign/references/step-09-refine.md +29 -30
  211. package/src/skf-campaign/references/step-10-export.md +48 -36
  212. package/src/skf-campaign/references/step-11-maintenance.md +31 -34
  213. package/src/skf-campaign/references/step-resume.md +37 -68
  214. package/src/skf-campaign/scripts/campaign-deps.py +57 -18
  215. package/src/skf-campaign/scripts/campaign-parse-manifest.py +361 -54
  216. package/src/skf-campaign/scripts/campaign-provenance.py +96 -53
  217. package/src/skf-campaign/scripts/campaign-quality-gate.py +592 -0
  218. package/src/skf-campaign/scripts/campaign-render-batch.py +257 -49
  219. package/src/skf-campaign/scripts/campaign-render-kickoff.py +343 -50
  220. package/src/skf-campaign/scripts/campaign-report.py +204 -37
  221. package/src/skf-campaign/scripts/campaign-state.py +1128 -0
  222. package/src/skf-campaign/scripts/campaign-status.py +10 -74
  223. package/src/skf-campaign/scripts/campaign-validate-pins.py +30 -3
  224. package/src/skf-campaign/scripts/campaign-validate-state.py +34 -4
  225. package/src/skf-campaign/templates/campaign-brief-template.yaml +4 -5
  226. package/src/skf-campaign/templates/campaign-report-template.md +5 -1
  227. package/src/skf-campaign/templates/kickoff-template.md +0 -14
  228. package/src/skf-create-skill/SKILL.md +27 -20
  229. package/src/skf-create-skill/assets/compile-assembly-rules.md +6 -5
  230. package/src/skf-create-skill/assets/skill-sections.md +15 -5
  231. package/src/skf-create-skill/customize.toml +20 -8
  232. package/src/skf-create-skill/references/authoritative-files-protocol.md +41 -42
  233. package/src/skf-create-skill/references/batch-mode.md +81 -0
  234. package/src/skf-create-skill/references/ccc-index-check.md +27 -0
  235. package/src/skf-create-skill/references/compile.md +107 -29
  236. package/src/skf-create-skill/references/component-extraction.md +113 -91
  237. package/src/skf-create-skill/references/enrich.md +41 -23
  238. package/src/skf-create-skill/references/entry-points-by-hand.md +20 -0
  239. package/src/skf-create-skill/references/extract.md +200 -161
  240. package/src/skf-create-skill/references/extraction-patterns-by-hand.md +141 -0
  241. package/src/skf-create-skill/references/extraction-patterns-tracing.md +2 -2
  242. package/src/skf-create-skill/references/extraction-patterns.md +584 -196
  243. package/src/skf-create-skill/references/generate-artifacts.md +145 -93
  244. package/src/skf-create-skill/references/health-check.md +1 -1
  245. package/src/skf-create-skill/references/load-brief.md +53 -36
  246. package/src/skf-create-skill/references/relabel-rule.md +12 -0
  247. package/src/skf-create-skill/references/report.md +28 -59
  248. package/src/skf-create-skill/references/source-resolution-protocols.md +49 -155
  249. package/src/skf-create-skill/references/step-auto-shard.md +20 -93
  250. package/src/skf-create-skill/references/step-doc-rot.md +44 -60
  251. package/src/skf-create-skill/references/step-doc-sources.md +28 -19
  252. package/src/skf-create-skill/references/sub/ccc-discover.md +18 -7
  253. package/src/skf-create-skill/references/sub/fetch-docs.md +106 -59
  254. package/src/skf-create-skill/references/sub/fetch-temporal.md +53 -166
  255. package/src/skf-create-skill/references/tier-degradation-rules.md +18 -9
  256. package/src/skf-create-skill/references/validate.md +173 -99
  257. package/src/skf-create-skill/scripts/scan-doc-rot.py +232 -99
  258. package/src/skf-create-stack-skill/SKILL.md +29 -56
  259. package/src/skf-create-stack-skill/assets/metadata-contract.md +51 -0
  260. package/src/skf-create-stack-skill/assets/provenance-map-schema.md +15 -15
  261. package/src/skf-create-stack-skill/assets/stack-skill-template.md +23 -57
  262. package/src/skf-create-stack-skill/customize.toml +23 -12
  263. package/src/skf-create-stack-skill/references/compile-stack.md +57 -66
  264. package/src/skf-create-stack-skill/references/compose-mode-rules.md +24 -44
  265. package/src/skf-create-stack-skill/references/detect-integrations.md +92 -95
  266. package/src/skf-create-stack-skill/references/detect-manifests.md +46 -71
  267. package/src/skf-create-stack-skill/references/generate-output.md +138 -128
  268. package/src/skf-create-stack-skill/references/init.md +90 -32
  269. package/src/skf-create-stack-skill/references/integration-patterns.md +1 -17
  270. package/src/skf-create-stack-skill/references/invocation-contract.md +34 -0
  271. package/src/skf-create-stack-skill/references/manifest-patterns.md +32 -20
  272. package/src/skf-create-stack-skill/references/parallel-extract.md +112 -38
  273. package/src/skf-create-stack-skill/references/rank-and-confirm.md +57 -75
  274. package/src/skf-create-stack-skill/references/report.md +39 -33
  275. package/src/skf-create-stack-skill/references/validate.md +20 -39
  276. package/src/skf-drop-skill/SKILL.md +28 -51
  277. package/src/skf-drop-skill/customize.toml +44 -30
  278. package/src/skf-drop-skill/references/execute.md +79 -146
  279. package/src/skf-drop-skill/references/invocation-contract.md +64 -0
  280. package/src/skf-drop-skill/references/report.md +46 -30
  281. package/src/skf-drop-skill/references/select.md +118 -124
  282. package/src/skf-drop-skill/scripts/dir-sizes.py +54 -26
  283. package/src/skf-drop-skill/scripts/drop-roster.py +322 -0
  284. package/src/skf-export-skill/SKILL.md +40 -62
  285. package/src/skf-export-skill/assets/managed-section-format.md +14 -50
  286. package/src/skf-export-skill/assets/snippet-format.md +3 -1
  287. package/src/skf-export-skill/customize.toml +42 -13
  288. package/src/skf-export-skill/references/generate-snippet.md +54 -46
  289. package/src/skf-export-skill/references/health-check.md +2 -0
  290. package/src/skf-export-skill/references/invocation-contract.md +15 -0
  291. package/src/skf-export-skill/references/load-skill.md +88 -62
  292. package/src/skf-export-skill/references/manifest-rebuild.md +9 -10
  293. package/src/skf-export-skill/references/multi-skill-mode.md +4 -4
  294. package/src/skf-export-skill/references/orphan-context-detection.md +13 -5
  295. package/src/skf-export-skill/references/orphan-row-detection.md +31 -22
  296. package/src/skf-export-skill/references/package.md +15 -73
  297. package/src/skf-export-skill/references/preflight-snippet-root-probe.md +51 -70
  298. package/src/skf-export-skill/references/result-envelope.md +31 -16
  299. package/src/skf-export-skill/references/summary.md +41 -17
  300. package/src/skf-export-skill/references/token-report.md +4 -12
  301. package/src/skf-export-skill/references/update-context.md +118 -237
  302. package/src/skf-forger/SKILL.md +61 -37
  303. package/src/skf-forger/bmad-skill-manifest.yaml +4 -1
  304. package/src/skf-forger/customize.toml +43 -0
  305. package/src/skf-forger/references/pipeline-mode.md +73 -18
  306. package/src/skf-forger/scripts/forge-status.py +299 -0
  307. package/src/skf-forger/scripts/parse-pipeline.py +322 -54
  308. package/src/skf-forger/scripts/pipeline-gate.py +428 -0
  309. package/src/skf-forger/scripts/pipeline-journal.py +1052 -0
  310. package/src/skf-quick-skill/SKILL.md +54 -53
  311. package/src/skf-quick-skill/assets/skill-template.md +4 -2
  312. package/src/skf-quick-skill/customize.toml +51 -20
  313. package/src/skf-quick-skill/references/batch-mode.md +74 -21
  314. package/src/skf-quick-skill/references/compile.md +30 -31
  315. package/src/skf-quick-skill/references/ecosystem-check.md +7 -57
  316. package/src/skf-quick-skill/references/finalize.md +69 -18
  317. package/src/skf-quick-skill/references/halt-contract.md +41 -29
  318. package/src/skf-quick-skill/references/health-check.md +5 -3
  319. package/src/skf-quick-skill/references/quick-extract.md +114 -45
  320. package/src/skf-quick-skill/references/registry-resolution.md +9 -64
  321. package/src/skf-quick-skill/references/resolve-target.md +116 -66
  322. package/src/skf-quick-skill/references/write-and-validate.md +79 -40
  323. package/src/skf-refine-architecture/SKILL.md +43 -53
  324. package/src/skf-refine-architecture/customize.toml +49 -20
  325. package/src/skf-refine-architecture/references/compile.md +97 -54
  326. package/src/skf-refine-architecture/references/exit-codes.md +30 -0
  327. package/src/skf-refine-architecture/references/finding-storage.md +21 -0
  328. package/src/skf-refine-architecture/references/gap-analysis.md +101 -38
  329. package/src/skf-refine-architecture/references/improvements.md +14 -20
  330. package/src/skf-refine-architecture/references/init.md +98 -57
  331. package/src/skf-refine-architecture/references/issue-detection.md +32 -39
  332. package/src/skf-refine-architecture/references/refinement-rules.md +37 -48
  333. package/src/skf-refine-architecture/references/report.md +65 -54
  334. package/src/skf-refine-architecture/scripts/skf-check-preservation.py +1619 -0
  335. package/src/skf-rename-skill/SKILL.md +19 -54
  336. package/src/skf-rename-skill/customize.toml +32 -26
  337. package/src/skf-rename-skill/references/execute.md +230 -184
  338. package/src/skf-rename-skill/references/exit-codes.md +7 -7
  339. package/src/skf-rename-skill/references/health-check.md +1 -7
  340. package/src/skf-rename-skill/references/invocation-contract.md +25 -0
  341. package/src/skf-rename-skill/references/report.md +63 -52
  342. package/src/skf-rename-skill/references/select.md +197 -115
  343. package/src/skf-rename-skill/scripts/skf-validate-rename-name.py +161 -21
  344. package/src/skf-setup/SKILL.md +26 -26
  345. package/src/skf-setup/customize.toml +14 -10
  346. package/src/skf-setup/references/auto-index.md +50 -63
  347. package/src/skf-setup/references/ccc-index.md +29 -90
  348. package/src/skf-setup/references/detect-and-tier.md +58 -67
  349. package/src/skf-setup/references/health-check.md +2 -0
  350. package/src/skf-setup/references/invocation-contract.md +14 -0
  351. package/src/skf-setup/references/report.md +43 -166
  352. package/src/skf-setup/references/tier-rules.md +5 -5
  353. package/src/skf-setup/references/write-config.md +34 -57
  354. package/src/skf-test-skill/SKILL.md +17 -57
  355. package/src/skf-test-skill/assets/output-section-formats.md +33 -34
  356. package/src/skf-test-skill/customize.toml +27 -13
  357. package/src/skf-test-skill/references/coherence-check.md +134 -62
  358. package/src/skf-test-skill/references/coverage-check-tiers.md +35 -0
  359. package/src/skf-test-skill/references/coverage-check.md +217 -254
  360. package/src/skf-test-skill/references/detect-mode.md +5 -5
  361. package/src/skf-test-skill/references/external-validators.md +94 -82
  362. package/src/skf-test-skill/references/health-check.md +6 -7
  363. package/src/skf-test-skill/references/init.md +163 -88
  364. package/src/skf-test-skill/references/invocation-contract.md +66 -0
  365. package/src/skf-test-skill/references/migration-section-rules.md +5 -2
  366. package/src/skf-test-skill/references/report.md +162 -142
  367. package/src/skf-test-skill/references/score.md +80 -107
  368. package/src/skf-test-skill/references/scoring-rules.md +41 -155
  369. package/src/skf-test-skill/references/source-access-protocol.md +19 -92
  370. package/src/skf-test-skill/references/step-hard-gate.md +51 -33
  371. package/src/skf-test-skill/scripts/aggregate-coherence.py +218 -30
  372. package/src/skf-test-skill/scripts/build-result-context.py +287 -0
  373. package/src/skf-test-skill/scripts/check-metadata-coherence.py +37 -4
  374. package/src/skf-test-skill/scripts/combine-external-scores.py +23 -6
  375. package/src/skf-test-skill/scripts/compute-score.py +223 -45
  376. package/src/skf-test-skill/scripts/gap-ledger.py +1381 -0
  377. package/src/skf-test-skill/scripts/hard-gate.py +203 -0
  378. package/src/skf-test-skill/scripts/load-coverage-inputs.py +760 -0
  379. package/src/skf-test-skill/scripts/locate-export-segments.py +835 -0
  380. package/src/skf-test-skill/scripts/reconcile-coverage.py +273 -79
  381. package/src/skf-test-skill/scripts/score-signatures.py +459 -0
  382. package/src/skf-test-skill/scripts/stage-helper-payload.py +148 -0
  383. package/src/skf-test-skill/scripts/validate-inventory.py +311 -16
  384. package/src/skf-test-skill/scripts/verify-declared-numerator.py +127 -52
  385. package/src/skf-test-skill/templates/test-report-template.md +21 -15
  386. package/src/skf-update-skill/SKILL.md +38 -25
  387. package/src/skf-update-skill/customize.toml +27 -12
  388. package/src/skf-update-skill/references/detect-changes.md +233 -222
  389. package/src/skf-update-skill/references/gap-driven.md +336 -0
  390. package/src/skf-update-skill/references/health-check.md +31 -5
  391. package/src/skf-update-skill/references/init.md +250 -84
  392. package/src/skf-update-skill/references/invocation-contract.md +12 -0
  393. package/src/skf-update-skill/references/manual-section-rules.md +6 -23
  394. package/src/skf-update-skill/references/merge.md +180 -47
  395. package/src/skf-update-skill/references/re-extract.md +53 -262
  396. package/src/skf-update-skill/references/report.md +100 -35
  397. package/src/skf-update-skill/references/write.md +331 -149
  398. package/src/skf-update-skill/scripts/skf-new-file-diff.py +29 -7
  399. package/src/skf-verify-stack/SKILL.md +23 -42
  400. package/src/skf-verify-stack/assets/feasibility-report-template.md +11 -5
  401. package/src/skf-verify-stack/customize.toml +55 -22
  402. package/src/skf-verify-stack/references/coverage-patterns.md +17 -8
  403. package/src/skf-verify-stack/references/coverage.md +67 -64
  404. package/src/skf-verify-stack/references/exit-codes.md +21 -8
  405. package/src/skf-verify-stack/references/init.md +107 -62
  406. package/src/skf-verify-stack/references/integration-verification-rules.md +12 -13
  407. package/src/skf-verify-stack/references/integrations.md +106 -65
  408. package/src/skf-verify-stack/references/report.md +59 -42
  409. package/src/skf-verify-stack/references/requirements.md +32 -9
  410. package/src/skf-verify-stack/references/synthesize.md +53 -39
  411. package/src/skf-verify-stack/scripts/skf-coverage-tally.py +398 -52
  412. package/src/skf-verify-stack/scripts/skf-previous-report.py +330 -0
  413. package/src/skf-verify-stack/scripts/skf-report-delta.py +453 -49
  414. package/src/skf-verify-stack/scripts/skf-verdict-rollup.py +240 -27
  415. package/tools/cli/commands/install.js +11 -4
  416. package/tools/cli/commands/status.js +15 -3
  417. package/tools/cli/commands/update.js +11 -4
  418. package/tools/cli/lib/tool-check.js +320 -0
  419. package/tools/cli/lib/version-check.js +22 -9
  420. package/tools/cli/skf-cli.js +4 -1
  421. package/.gitattributes +0 -16
  422. package/.nvmrc +0 -1
  423. package/docs/_internal/RELEASING.md +0 -679
  424. package/release-audits/v1.0.0-launch-audit.md +0 -728
  425. package/src/skf-audit-skill/references/step-doc-drift.md +0 -177
  426. package/src/skf-brief-skill/references/headless-source-authority-detection.md +0 -26
  427. package/src/skf-campaign/manifest.yaml +0 -15
  428. package/src/skf-create-skill/assets/tessl-dismissal-rules.md +0 -106
  429. package/src/skf-create-skill/references/ecosystem-check.md +0 -74
  430. package/src/skf-drop-skill/references/headless-contract.md +0 -18
  431. package/src/skf-update-skill/references/merge-conflict-rules.md +0 -15
  432. package/src/skf-update-skill/references/remote-source-resolution.md +0 -98
  433. package/src/skf-update-skill/references/validate.md +0 -124
  434. package/tools/validate-docs-drift.js +0 -233
  435. package/tools/validate-docs-links.js +0 -665
@@ -1,11 +1,13 @@
1
1
  ---
2
2
  nextStepFile: 'health-check.md'
3
- # Resolve `{atomicWriteHelper}` by probing `{atomicWriteProbeOrder}` in order
4
- # (installed SKF module path first, src/ dev-checkout fallback); first existing
5
- # path wins. HALT if neither resolves.
3
+ # §2b copies the -latest result file to the stack group root with the
4
+ # atomic writer; without it, §2b skips that copy with a warning.
6
5
  atomicWriteProbeOrder:
7
6
  - '{project-root}/_bmad/skf/shared/scripts/skf-atomic-write.py'
8
7
  - '{project-root}/src/shared/scripts/skf-atomic-write.py'
8
+ emitEnvelopeProbeOrder:
9
+ - '{project-root}/_bmad/skf/shared/scripts/skf-emit-result-envelope.py'
10
+ - '{project-root}/src/shared/scripts/skf-emit-result-envelope.py'
9
11
  ---
10
12
 
11
13
  <!-- Config: communicate in {communication_language}. Artifact text in {document_output_language}. -->
@@ -18,76 +20,80 @@ Display the final summary of the forged stack skill with confidence distribution
18
20
 
19
21
  ## Rules
20
22
 
21
- - Do not write or modify any files — report is console output only
23
+ - Write only the §2b result contract (the per-run record and its `-latest` copy in `{forge_version}/`, and the `-latest` copy at the stack group root), then delete the run folder (§3). The rest of the report is console output only
22
24
  - Lead with the positive summary, then details, then warnings
23
25
  - Recommend next workflows based on what was produced
24
26
  - Chains to the local health-check step via `{nextStepFile}` after completion — the user-facing report is NOT the terminal step
25
27
 
26
28
  ## MANDATORY SEQUENCE
27
29
 
30
+ **Warnings.** Each `workflow_warnings[]` entry this step appends is recorded at once: write its `[{step}/{severity}] {code}: {message}` line to `{run_dir}/warning.txt` with a file write, then run `uv run {emitEnvelopeHelper} record --run-dir "{run_dir}" --warning "$(cat "{run_dir}/warning.txt")"`, resolving `{emitEnvelopeHelper}` from `{emitEnvelopeProbeOrder}` if it is not bound.
31
+
28
32
  ### 1. Report the Forge Result
29
33
 
30
34
  Surface the forge result to the console, leading with the win:
31
35
 
32
- - **Headline:** stack `{project_name}-stack` — `{lib_count}` libraries, `{integration_count}` integration patterns, forge tier `{tier}`.
33
- - **Confidence distribution:** the T1 / T1-low / T2 counts (T1 = AST-verified structural extraction, T1-low = source-reading inference, T2 = QMD-enriched temporal context). **In compose-mode**, note the tiers are inherited from the source skills — they reflect the extraction method used when those skills were originally generated, not the current compose run.
36
+ - **Headline:** stack `{stack_name}`: `{lib_count}` libraries, `{integration_count}` integration patterns, forge tier `{tier}`.
37
+ - **Confidence (libraries per tier, from `metadata.json` `confidence_distribution`):** T1 {n}, T1-low {n}, T2 {n}, T3 {n}. In code mode, T1 = an ast-grep rule matched every export and T1-low = at least one export was read by eye, or none was recorded. **In compose-mode**, each library keeps its constituent's own tier (`evidence_tier`), which reflects how that skill was generated, not the current compose run.
34
38
  - **Output files:** the `{skill_package}` deliverables (SKILL.md, context-snippet.md with `{token_estimate}` tokens, metadata.json, `references/` per-library files, and `references/integrations/` pair files when integrations exist), the `{forge_version}` workspace (provenance-map.json, evidence-report.md), and the `{skill_group}/active -> {version}` symlink.
35
39
  - **Validation:** all checks passed, or `{warning_count}` finding(s) each with its description.
36
- - **Warnings — only if `workflow_warnings[]` is non-empty:** the accumulated entries rendered as `[{step}/{severity}] {code}: {message}`. `workflow_warnings[]` (defined in SKILL.md's *Workflow state contract*) is the single sink surfacing every warning pushed during the run; if it is empty, omit this section.
40
+ - **Warnings, only if `workflow_warnings[]` is non-empty:** each line of `{run_dir}/warnings.jsonl` decoded as the JSON string it holds, which is in the `[{step}/{severity}] {code}: {message}` form. That sink (SKILL.md's *Workflow state contract*) holds every warning recorded during the run; if it is empty, omit this section.
37
41
 
38
42
  ### 2. Recommend Next Workflows
39
43
 
40
44
  "**Next steps:**
41
- - **[TS] test-skill** — Validate the stack skill against its own assertions
42
- - **[EX] export-skill** — Package for distribution or agent loading
45
+ - **[TS] test-skill**: Validate the stack skill against its own assertions
46
+ - **[EX] export-skill**: Validate the package, write its context snippet and update the managed section in CLAUDE.md, AGENTS.md or .cursorrules
43
47
 
44
- - **[VS] verify-stack** — Validate the stack's integration feasibility against your architecture document{IF compose_mode:} (re-run to confirm feasibility after any architecture changes from **[RA] refine-architecture**){END IF}"
48
+ - **[VS] verify-stack**: Validate the stack's integration feasibility against your architecture document{IF compose_mode:} (re-run to confirm feasibility after any architecture changes from **[RA] refine-architecture**){END IF}"
45
49
 
46
50
  ### 2b. Result Contract
47
51
 
48
- Write the result contract per `shared/references/output-contract-schema.md` using the shared atomic writer. Two artifacts — both written via `skf-atomic-write.py write`:
52
+ The shared emitter writes the result contract (`shared/references/output-contract-schema.md`) and builds the success envelope in one call. Resolve the atomic writer first (see **Missing atomic writer** below), and `{emitEnvelopeHelper}` from `{emitEnvelopeProbeOrder}` if it is not bound. Stage `{run_dir}/result-context.json`:
53
+
54
+ ```json
55
+ {"status": "success", "skill_package": "{skill_package}", "skill_name": "{stack_name}",
56
+ "stack_libraries": ["<library>"], "mode": "code|compose", "quality_score": null, "halt_reason": null,
57
+ "result_contract": {"skill": "skf-create-stack-skill", "status": "success",
58
+ "outputs": [{"type": "skill", "path": "{skill_package}/SKILL.md"},
59
+ {"type": "skill", "path": "{skill_package}/context-snippet.md"},
60
+ {"type": "skill", "path": "{skill_package}/metadata.json"},
61
+ {"type": "report", "path": "{forge_version}/evidence-report.md"}],
62
+ "summary": {"lib_count": 0, "integration_count": 0, "forge_tier": "<tier>", "confidence_tier": "<tier>",
63
+ "confidence_distribution": {}, "quality_score": null}}}
64
+ ```
49
65
 
50
- **Per-run record (inside the version dir):**
66
+ `skill_package` is the absolute path to the committed package and `stack_libraries` the committed `metadata.json`'s `libraries`. Both `quality_score` fields are `{quality_score}`, the skill-check score step 8 §3 bound (`null` when skill-check did not run), never a test-skill score. The summary's counts, `confidence_tier` and `confidence_distribution` are the committed `metadata.json`'s `library_count`, `integration_count`, `confidence_tier` and `confidence_distribution`, and `forge_tier` its run tier. Then run:
51
67
 
52
68
  ```bash
53
- <json-content> | python3 {atomicWriteHelper} write \
54
- --target {forge_version}/create-stack-skill-result-{YYYYMMDD-HHmmss}-{pid}-{rand}.json
69
+ uv run {emitEnvelopeHelper} emit --workflow skf-create-stack-skill --run-dir "{run_dir}" --result-dir "{forge_version}" < "{run_dir}/result-context.json"
55
70
  ```
56
71
 
57
- - `{YYYYMMDD-HHmmss}` is a UTC timestamp with seconds resolution.
58
- - Append `-{pid}-{rand}` (process id + short random suffix) to the filename to avoid same-second collisions when multiple runs land in the same second (S16).
72
+ The emitter stamps `timestamp`, `run_id`, the run's auto-decisions and its warnings into the record, writes `create-stack-skill-result-<YYYYMMDD-HHmmss>.json` (it picks the name, with `-2` for a run that ends in the same second as another) and its `create-stack-skill-result-latest.json` copy in `{forge_version}`, and prints the success line on stdout: display it when `{headless_mode}` is true. A file it cannot write becomes a `result_file_write_failed` warning in the envelope, with `result_path` `null` when the per-run record is the one that failed. If the emitter exits non-zero, fix the payload its stderr names and run it once more; if it fails again, print its error and continue: the result contract is advisory and never halts the report.
59
73
 
60
- **Stable latest pointer (ABOVE the version dir, at the stack group root):**
74
+ **Stable latest pointer at the stack group root.** Pipeline consumers read `{forge_data_folder}/{stack_name}/create-stack-skill-result-latest.json`, above the version folder, without knowing the current version. Copy the record there (a copy, not a symlink, so no consumer chases a link across version folders):
61
75
 
62
76
  ```bash
63
- <json-content> | python3 {atomicWriteHelper} write \
64
- --target {forge_data_folder}/{project_name}-stack/create-stack-skill-result-latest.json
77
+ python3 {atomicWriteHelper} write --target {forge_data_folder}/{stack_name}/create-stack-skill-result-latest.json < {forge_version}/create-stack-skill-result-latest.json
65
78
  ```
66
79
 
67
- - Note the path: the `-latest.json` lives at `{forge_data_folder}/{project_name}-stack/` (the stack group root), NOT inside `{forge_version}/`. Pipeline consumers read this stable path without knowing the current version.
68
- - Write the same JSON body as the timestamped record (this is a copy, not a symlink, so pipeline consumers never chase a link across version boundaries).
69
-
70
- Include `SKILL.md`, `context-snippet.md`, and `metadata.json` paths in `outputs`; include `lib_count`, `integration_count`, `forge_tier`, `confidence_tier`, and confidence distribution in `summary`.
71
-
72
- If either atomic write fails, log the error, leave any prior `-latest.json` untouched, and continue — the report is advisory and should not block the health-check chain.
80
+ Skip the copy when the emitter printed no line, or when its envelope's `warnings` hold a `result_file_write_failed` entry naming `create-stack-skill-result-latest.json` or `{forge_version}` itself: the `-latest` file there may then hold an earlier run's record. If the copy is skipped or fails, print "The group-root copy of the result contract was not written: {the reason}", leave any prior group-root `-latest.json` untouched, and continue: §1 has already listed the warnings.
73
81
 
74
- **Headless success envelope.** When `{headless_mode}` is true, emit the single-line result envelope on **stdout** (the success counterpart to the error envelopes every HARD HALT emits on stderr) before chaining to step 10. `skill_package` is the absolute path to the committed package; `stack_libraries` is the included library names:
75
-
76
- ```
77
- SKF_STACK_RESULT_JSON: {"status":"success","skill_package":"{skill_package}","skill_name":"{project_name}-stack","stack_libraries":["<lib>", "..."],"mode":"{code|compose}","exit_code":0,"halt_reason":null}
78
- ```
82
+ **Missing atomic writer.** Resolve `{atomicWriteHelper}` from `{atomicWriteProbeOrder}`; first existing path wins. If no candidate exists, append `{step: "step-09", severity: "warn", code: "result-contract-skipped", message: "group-root result copy skipped: skf-atomic-write.py not found (re-install SKF)"}` to `workflow_warnings[]` before the emit, so the envelope and the result files carry it, print its message, since §1 has already listed the warnings, and make no group-root copy; any prior one stays untouched. The emitter still writes the result files in `{forge_version}`, so a missing writer never halts the report.
79
83
 
80
84
  ### 2c. Post-Completion Hook (optional)
81
85
 
82
- If `{onCompleteCommand}` (resolved at SKILL.md On Activation §3 from `workflow.on_complete`) is non-empty, invoke it now — after the result contract (§2b) is written, before chaining to health-check:
86
+ If `{onCompleteCommand}` (resolved at SKILL.md On Activation §3 from `workflow.on_complete`) is non-empty, invoke it now, after §2b and before chaining to health-check:
83
87
 
84
88
  ```bash
85
89
  {onCompleteCommand}
86
90
  ```
87
91
 
88
- Run it with a bounded timeout (default 60s). On success, continue. On non-zero exit, timeout, or any failure, append the reason to `workflow_warnings[]` (e.g. `on_complete — failed (exit {N}): {stderr_first_line}`) and continue. **The hook must never fail the workflow** — it is integration glue (catalog registration, downstream pipeline notify) orthogonal to the forged stack. When `{onCompleteCommand}` is empty (bundled default), skip this section entirely.
92
+ The hook runs even when §2b updated no `create-stack-skill-result-latest.json` (a failed write or emit); that file then still holds an earlier forge's record, if any.
93
+
94
+ Run it with a bounded timeout (default 60s). On success, continue. On non-zero exit, timeout, or any failure, print one report line, `on_complete failed (exit {N}): {stderr_first_line}`, and continue: §1 has already listed the warnings and §2b has emitted the envelope, so that line is where the failure shows. **The hook must never fail the workflow**: it is integration glue (catalog registration, downstream pipeline notify) orthogonal to the forged stack. When `{onCompleteCommand}` is empty (bundled default), skip this section entirely.
89
95
 
90
96
  ### 3. Chain to Health Check
91
97
 
92
- After the report sections above are handled, load, read the full file, and execute `{nextStepFile}`. The health-check step is the true terminal step — do not stop here even though the report reads as final.
98
+ After the report sections above are handled, delete the run folder, whose warnings and decisions the envelope and the result files now hold: `rm -rf "{run_dir}"`. 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 report reads as final.
93
99
 
@@ -15,7 +15,8 @@ Validate all written output files against their expected structure and verify co
15
15
 
16
16
  ## Rules
17
17
 
18
- - Validate structure and completeness, not content quality — validation is read-only
18
+ - Validate structure and completeness, not content quality
19
+ - Only §3 writes to the committed package: `skill-check --fix` may rewrite `SKILL.md`, and a `body.max_lines` finding moves sections into `references/` (or runs `split-body --write`). Every other section leaves the package as step 7 committed it
19
20
  - Advisory mode: always proceed to report regardless of findings
20
21
 
21
22
  ## MANDATORY SEQUENCE
@@ -25,7 +26,7 @@ Validate all written output files against their expected structure and verify co
25
26
  Run the shared deterministic output validator once against the committed package — it checks the three core deliverable files' existence, SKILL.md frontmatter, and context-snippet format/token in a single call, so this step consumes its JSON rather than re-deriving those by hand. Resolve `{outputValidator}` from `{outputValidatorProbeOrder}` (first existing path wins). If neither candidate exists, log a WARNING (`"output validator unavailable — skf-validate-output.py missing"`) and fall back to the manual file/frontmatter/snippet checks below.
26
27
 
27
28
  ```bash
28
- python3 {outputValidator} {skill_package} --generated-by create-stack-skill --skill-type stack
29
+ python3 {outputValidator} {skill_package} --generated-by create-stack-skill --skill-type stack --forge-tier {forge_tier}
29
30
  ```
30
31
 
31
32
  Consume from its JSON:
@@ -34,8 +35,9 @@ Consume from its JSON:
34
35
  - `validation.skill_md.frontmatter` — feeds the frontmatter check in §3 (manual-fallback path).
35
36
  - `validation.context_snippet.issues` — feeds §8.
36
37
  - `validation.stack_counts` — the stack count-equalities, derived deterministically from disk + metadata by the `--skill-type stack` pass: `issues[]` (each `{severity, field, message}`, one per mismatch of `library_count` / `integration_count` / `confidence_distribution`; empty when all agree) and `observed` (`library_count_meta`, `ref_file_count`, `integration_count_meta`, `pair_file_count`, `confidence_sum`). Feeds the count rows in §5 and the confidence-sum row in §7 — do not re-count files or re-sum the distribution by hand.
38
+ - `validation.stack_structure`: the stack structure pass. The `check` of each `issues[]` entry (`{severity, check, field, message}`) names the section below that records it: `skill_md` (§4), `metadata` (§5), `references` (§6) or `tier_labels` (§7). Do not re-read the output files to check what it checks.
37
39
 
38
- **Under `--skill-type stack`, `validation.skill_md.body` and `validation.metadata` are emitted as `{"skipped": ...}` markers** — the *individual-skill* schema (which looks for `## Overview` / `Description` / `Key Exports` / `Usage` sections and a `source_repo` field) does not apply to a stack package, so the validator skips those passes and runs `validation.stack_counts` instead. Stack-shaped body structure and the remaining (non-count) metadata fields are checked in §4 / §5.
40
+ Under `--skill-type stack` the validator skips the individual-skill body and metadata passes (their `{"skipped": ...}` markers are no finding) and runs these two instead. When §3 changes the package it runs this command again, and §4 to §8 read the latest run. When the validator is unavailable, §4 to §7 each record one **WARNING** finding that their checks did not run.
39
41
 
40
42
  Then confirm the remaining files the validator does not cover:
41
43
 
@@ -62,7 +64,7 @@ timeout 10s npx --no-install skill-check -h
62
64
  ```
63
65
 
64
66
  - If exits 0: Use skill-check for automated validation in sections 3, 9.
65
- - If exits non-zero, times out, or returns "command not found": Use manual fallback paths. Mark `metadata.validation_status: "manual-only"` (do this in step 7 when appropriate) and record every skipped check in the evidence report.
67
+ - If exits non-zero, times out, or returns "command not found": Use manual fallback paths, append a `workflow_warnings[]` entry (`step: "step-08"`, `severity: "warn"`, `code: "skill-check-unavailable"`, `message: "skill-check unavailable: manual fallback checks used, security scan skipped"`) so step 9 does not report the run as skill-check validated, recording it at once (write its `[step-08/warn] skill-check-unavailable: {message}` line to `{run_dir}/warning.txt` with a file write, then run `uv run {emitEnvelopeHelper} record --run-dir "{run_dir}" --warning "$(cat "{run_dir}/warning.txt")"`), and list every skipped check in the §10 validation results.
66
68
 
67
69
  **Important:** Do not assume availability — empirical check required.
68
70
 
@@ -72,60 +74,39 @@ timeout 10s npx --no-install skill-check -h
72
74
 
73
75
  This validates frontmatter, description, body limits, links, formatting — and auto-fixes deterministic issues. Parse JSON for `scores[].score` (match the entry by `relativePath`/`skillId`; falls back to a top-level `qualityScore` on older skill-check builds), `diagnostics[]`, `fixed[]`.
74
76
 
75
- **Post-fix provenance drift guard (S15):** If `fixed[]` is non-empty, `skill-check --fix` has modified `SKILL.md` after step 7 wrote it — so the `metadata.json` hashes/provenance recorded against the pre-fix body may now be stale. Emit a **WARNING** finding listing each auto-fix (`"skill-check --fix modified SKILL.md: {fix_description} — metadata.json hashes/provenance may be out of date"`) rather than silently accepting the fixes, so the drift is surfaced. If the caller wants authoritative metadata, they should re-run the workflow.
76
-
77
- **If `body.max_lines` reported**, prefer selective split: extract only the largest Tier 2 section(s) to `references/`, keeping Tier 1 content inline (inline passive context achieves 100% task accuracy vs 79% for on-demand retrieval). For a stack capstone the canonical split is the catalog (`Library Reference Index` + `Per-Library Summaries`) → `references/stack-catalog.md`, leaving an inline pointer (see `{stackSkillTemplatePath}` "Sizing Guidance"). This is the **intended** large-stack layout, not a violation: §4 below accepts the pointer form, so clearing the skill-check body ERROR this way does not also trip the structure check. Fall back to `npx skill-check split-body <skill-dir> --write` if not feasible. Verify any in-SKILL.md anchor links (e.g. to the catalog/pointer or other moved sections) still resolve after the split. Then re-validate.
77
+ Bind `{quality_score}` ← that score, from the latest skill-check run (§3 runs it again after a split); `{quality_score}` is null when skill-check is unavailable. It is the skill-check score, not a test-skill score, and step 9 puts it in the result envelope and the result contract.
78
78
 
79
- **If unavailable**, do not hand-walk the frontmatter — use `validation.skill_md.frontmatter` from the §1 output-validator run, which checks delimiters, `name` format + directory match (`{project_name}-stack`), `description` presence/length, and unknown fields against the agentskills.io allow-set. Record each reported issue at its severity as a **WARNING** finding. (If the output validator was *also* unavailable in §1, fall back to the manual checklist: `---` delimiters; `name` lowercase-alphanumeric-plus-hyphens 1-64 chars matching `{project_name}-stack`; `description` present and 1-1024 chars; only `name`/`description`/`license`/`compatibility`/`metadata`/`allowed-tools` permitted.) Invalid frontmatter will fail `npx skills add` and `npx skill-check check`.
79
+ **Post-fix provenance drift guard (S15):** If `fixed[]` is non-empty, `skill-check --fix` has modified `SKILL.md` after step 7 wrote it — so the `metadata.json` hashes/provenance recorded against the pre-fix body may now be stale. Emit a **WARNING** finding listing each auto-fix (`"skill-check --fix modified SKILL.md: {fix_description} — metadata.json hashes/provenance may be out of date"`) rather than silently accepting the fixes, so the drift is surfaced. If the caller wants authoritative metadata, they should re-run the workflow.
80
80
 
81
- ### 4. Validate SKILL.md Body Structure
81
+ **If `body.max_lines` reported**, prefer selective split: extract only the largest Tier 2 section(s) to `references/`, keeping Tier 1 content inline (inline passive context achieves 100% task accuracy vs 79% for on-demand retrieval). For a stack capstone the canonical split is the catalog (`Library Reference Index` + `Per-Library Summaries`) → `references/stack-catalog.md`, leaving an inline pointer (see `{stackSkillTemplatePath}` "Sizing Guidance"). The moved catalog's links resolve from `references/`, so rewrite each `[ref](references/{name}.md)` in it to `[ref]({name}.md)`. This is the **intended** large-stack layout, not a violation: §4 below accepts the pointer form, so clearing the skill-check body ERROR this way does not also trip the structure check. Fall back to `npx skill-check split-body <skill-dir> --write` if not feasible. After the split, verify that any in-SKILL.md anchor links (e.g. to the catalog/pointer or other moved sections) still resolve, and that every link inside a moved section resolves from its new file.
82
82
 
83
- Load `{stackSkillTemplatePath}` and verify SKILL.md contains expected sections:
83
+ **Re-validate a changed package.** When `fixed[]` is non-empty or a split ran, run the §1 `{outputValidator}` command again (after a split, skill-check too), so §4 to §8 record the package as it now stands.
84
84
 
85
- - [ ] Header with project name, library count, integration count, forge tier
86
- - [ ] Integration Patterns section (before per-library summaries)
87
- - [ ] Conventions section
88
- - [ ] **Catalog** — `Library Reference Index` table + `Per-Library Summaries`, in **either** form:
89
- - *Inline* (small stacks): both sections present in SKILL.md, **or**
90
- - *Pointer* (large stacks): a `Library Catalog` pointer to `references/stack-catalog.md`, **and** that file exists and contains both sections.
85
+ **If unavailable**, do not hand-walk the frontmatter: use `validation.skill_md.frontmatter` from the §1 output-validator run, which checks delimiters, `name` format + directory match (`{stack_name}`), `description` presence/length, and unknown fields against the agentskills.io allow-set. Record each reported issue at its severity as a **WARNING** finding. (If the output validator was *also* unavailable in §1, fall back to the manual checklist: `---` delimiters; `name` lowercase-alphanumeric-plus-hyphens 1-64 chars matching `{stack_name}`; `description` present and 1-1024 chars; only `name`/`description`/`license`/`compatibility`/`metadata`/`allowed-tools` permitted.) Invalid frontmatter will fail `npx skills add` and `npx skill-check check`.
91
86
 
92
- Accept either form — do not WARN when the catalog has been extracted to clear the `body.max_lines` budget (§3). Only record a **WARNING** when *neither* the inline sections *nor* a pointer-plus-`stack-catalog.md` is present, or when the pointer's target file is missing.
87
+ ### 4. Validate SKILL.md Body Structure
93
88
 
94
- Record other missing sections (Header, Integration Patterns, Conventions) as **WARNING** findings.
89
+ Record each `validation.stack_structure.issues[]` entry whose `check` is `skill_md` as a **WARNING** finding. The catalog's pointer form (a `## Library Catalog` section linking `references/stack-catalog.md`) is the intended large-stack layout (§3), not a violation.
95
90
 
96
91
  ### 5. Validate metadata.json Fields
97
92
 
98
- Parse metadata.json and verify required fields:
99
-
100
- - [ ] `skill_type` equals "stack"
101
- - [ ] `name` matches `{project_name}-stack`
102
- - [ ] `version` and `generation_date` present
103
- - [ ] `forge_tier` is present and matches the forge tier from step 01 (`Quick|Forge|Forge+|Deep`)
104
- - [ ] `confidence_tier` is present and is exactly one of `T1|T1-low|T2|T3` — the dominant T-code computed from `confidence_distribution` (pick the tier with the highest count; ties resolve to the weaker tier: T1-low > T1, T2 > T1-low, T3 > T2 for tie-break so the reported tier never overstates confidence)
105
- - [ ] `libraries` array present and non-empty
106
- - [ ] `confidence_distribution` object present with `t1`, `t1_low`, `t2`, `t3` keys (lowercase, matching template definition)
93
+ Record each `validation.stack_structure.issues[]` entry whose `check` is `metadata` as a **WARNING** finding.
107
94
 
108
- **Count equalities (library / integration)** — do NOT re-count files here; take them from `validation.stack_counts` in the §1 output-validator run (invoked with `--skill-type stack`), which derived them deterministically from disk. The `library_count` vs per-library reference files and `integration_count` vs integration pair files checks surface as `field: "library_count"` / `field: "integration_count"` entries in `validation.stack_counts.issues[]` (absent when they agree); echo the exact numbers from `validation.stack_counts.observed` (`library_count_meta` / `ref_file_count`, `integration_count_meta` / `pair_file_count`). The `confidence_distribution`-sum equality is covered in §7.
95
+ **Count equalities (library / integration):** do NOT re-count files here; take them from `validation.stack_counts` in the latest output-validator run (§1, or §3's re-run), which derived them deterministically from disk. The `library_count` vs per-library reference files and `integration_count` vs integration pair files checks surface as `field: "library_count"` / `field: "integration_count"` entries in `validation.stack_counts.issues[]` (absent when they agree); echo the exact numbers from `validation.stack_counts.observed` (`library_count_meta` / `ref_file_count`, `integration_count_meta` / `pair_file_count`). The `confidence_distribution`-sum equality is covered in §7.
109
96
 
110
- Record each `validation.stack_counts.issues[]` count entry (`library_count` / `integration_count`) and any other mismatch above as **WARNING** findings.
97
+ Record each `validation.stack_counts.issues[]` count entry (`library_count` / `integration_count`) as a **WARNING** finding.
111
98
 
112
99
  ### 6. Validate Reference File Completeness
113
100
 
114
- For each confirmed library, verify `references/{library}.md` contains: library name header, version from manifest (**in compose-mode**: version from source skill metadata), Key Exports section, Usage Patterns section.
115
-
116
- For each integration pair, verify `references/integrations/{libraryA}-{libraryB}.md` contains: integration pair header, type classification, Integration Pattern section, Key Files section.
117
-
118
- Record missing or incomplete files as **WARNING** findings.
101
+ Record each `validation.stack_structure.issues[]` entry whose `check` is `references` as a **WARNING** finding.
119
102
 
120
103
  ### 7. Validate Confidence Tier Labels
121
104
 
122
- Scan all output files for confidence tier coverage:
105
+ Record each `validation.stack_structure.issues[]` entry whose `check` is `tier_labels` as a **WARNING** finding.
123
106
 
124
- - [ ] SKILL.md: each per-library summary and integration pair entry has a confidence label
125
- - [ ] Reference files: each has a confidence label in its header
126
- - [ ] metadata.json: `confidence_distribution` sums to `library_count` — take this from the §1 output-validator run (`--skill-type stack`): the `field: "confidence_distribution"` entry in `validation.stack_counts.issues[]` is present only on mismatch, with `validation.stack_counts.observed.confidence_sum` vs `library_count_meta` for the exact numbers. Do not re-sum the distribution by hand.
107
+ - [ ] metadata.json: `confidence_distribution` sums to `library_count`: take this from the latest output-validator run (`--skill-type stack`): the `field: "confidence_distribution"` entry in `validation.stack_counts.issues[]` is present only on mismatch, with `validation.stack_counts.observed.confidence_sum` vs `library_count_meta` for the exact numbers. Do not re-sum the distribution by hand.
127
108
 
128
- Record missing tier labels and any `validation.stack_counts` `confidence_distribution` issue as **WARNING** findings.
109
+ Record the `validation.stack_counts` `confidence_distribution` issue, if any, as a **WARNING** finding.
129
110
 
130
111
  ### 8. Validate context-snippet.md
131
112
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: skf-drop-skill
3
- description: Drop a specific skill version or an entire skill — soft (deprecate) or hard (purge) with platform context rebuild. Use when the user requests to "drop" or "remove a skill."
3
+ description: Deprecates or purges a skill version or a whole skill, then rebuilds the platform context files. Use when the user requests to "drop a skill" or "remove a skill".
4
4
  ---
5
5
 
6
6
  # Drop Skill
@@ -12,12 +12,13 @@ Drops a specific skill version or an entire skill, either as a soft deprecation
12
12
  ## Conventions
13
13
 
14
14
  - Bare paths (e.g. `references/<name>.md`) resolve from the skill root.
15
- - `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.
15
+ - `references/` holds prompt content carved out of SKILL.md (workflow stages chained via frontmatter `nextStepFile`, plus static reference docs); `scripts/` holds its helpers (`dir-sizes.py`, `drop-roster.py`).
16
16
  - `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives, if present).
17
17
  - `{project-root}`-prefixed paths resolve from the project working directory.
18
18
  - `{skill-name}` resolves to the skill directory's basename.
19
- - **Module-level path exception:** paths starting with `knowledge/` or `shared/` resolve from the SKF module root, not the skill root — install layout puts both at `{project-root}/_bmad/skf/`. The `versionPathsKnowledge: 'knowledge/version-paths.md'` frontmatter scalar in stage files uses this convention; same for `shared/health-check.md` chained from the terminal step.
20
- - **Cross-skill data coupling:** `references/execute.md` reads `skf-export-skill/assets/managed-section-format.md` for the IDE→context-file mapping table and the four-case (Create / Append / Regenerate / Malformed) logic when rebuilding context files. Drop-skill assumes that asset is present at install time and that its semantics are stable across the two skills' versions.
19
+ - **Module-level path exception:** bare paths beginning with `knowledge/` or `shared/` resolve from the SKF module root (`{project-root}/_bmad/skf/` installed, `src/` in dev), not the skill root.
20
+ - **Sibling skills:** a path that names another SKF skill's folder (`skf-<name>/...`) resolves from the SKF module root, and that skill must be installed with this one.
21
+ - **Shared context-file rebuild:** `references/select.md` and `references/execute.md` resolve the context files and rebuild their managed sections through `shared/scripts/skf-rebuild-managed-sections.py`, the helper export-skill writes them with, so the three skills that write the section produce the same bytes from one IDE mapping. `skf-export-skill/assets/managed-section-format.md` documents that format.
21
22
 
22
23
  ## Role
23
24
 
@@ -29,8 +30,9 @@ These rules apply to every step in this workflow:
29
30
 
30
31
  - Never delete files in purge mode without clearing the §10 confirmation gate (auto-resolved with its default in headless)
31
32
  - Never drop an active version when other non-deprecated versions exist — enforce the active version guard
33
+ - Never purge content SKF did not generate: select.md §8b takes the purge verdict for the skill folder and its forge folder from the inventory helper; a forge folder SKF did not generate is left in place, and a purge SKF cannot check is refused
32
34
  - Only load one step file at a time — never preload future steps
33
- - If any instruction references a subprocess or tool you lack, achieve the outcome in your main context thread
35
+ - If any instruction references a subprocess or tool you lack, achieve the outcome in your main context thread, with two exceptions. A helper On-Activation §4 resolves is never replaced by hand (a missing one halts the run before the first prompt): never type an envelope or edit the manifest or a context file yourself. And never decide by hand whether SKF generated a folder: without the inventory helper, select.md offers manifest skills only and refuses every purge
34
36
  - Always communicate in `{communication_language}`
35
37
  - At any interactive prompt, the inputs `cancel`, `exit`, `[X]`, `q`, or `:q` exit cleanly with exit code 6 (`halt_reason: "user-cancelled"`)
36
38
  - If `{headless_mode}` is true, auto-proceed through confirmation gates with their default action and log each auto-decision
@@ -46,72 +48,47 @@ These rules apply to every step in this workflow:
46
48
 
47
49
  ## Invocation Contract
48
50
 
49
- | Aspect | Detail |
50
- |--------|--------|
51
- | **Inputs** | skill_name [required], mode (deprecate/purge) [required], version (all/specific) [required] |
52
- | **Flags** | `--headless` / `-H` (auto-resolve all gates); `--dry-run` (run selection + display the §10 confirmation block, then exit with `status="dry-run"` — no manifest mutation, no file deletion). Useful for "show me what this would touch before I commit." |
53
- | **Gates** | step 1: Input Gate [use args], Confirm Gate [Y] |
54
- | **Outputs** | Updated manifest, rebuilt context files, (purge: deleted directories), `drop-skill-result-{timestamp}.json` and `drop-skill-result-latest.json` |
55
- | **Headless** | Gates auto-resolve with their default action (see Workflow Rules). When `forbid_purge_in_headless` is `"true"` in `customize.toml` AND the effective drop mode is `"purge"` (defined in On-Activation §4 — explicit `mode=purge` or `default_mode` purge), §4 HALTs with exit code 6 (`halt_reason: "headless-purge-forbidden"`) before any work begins. |
56
- | **Exit codes** | See "Exit Codes" below |
57
-
58
- ## Exit Codes
59
-
60
- Every hard HALT exits with a stable code so headless automators branch on the failure class without grepping message text. The `Raised by` column names the HALT class per code; the authoritative per-site declarations (with exact `halt_reason`) live in the step files.
61
-
62
- | Code | Meaning | Raised by (class) |
63
- | ---- | -------------------- | ----------------- |
64
- | 0 | success | step 4 (terminal) |
65
- | 2 | input-missing / input-invalid | step 1 headless input gates — missing or unmatched `skill_name`, `version`, or `--mode` value (§4 / §6 / §8) |
66
- | 3 | resolution-failure | step 1 manifest/skill-list resolution (§2 corrupt manifest, §3 nothing to drop) |
67
- | 4 | write-failure | On-Activation write probe; step 2 manifest write / context rebuild / full-purge failure |
68
- | 5 | state-conflict | step 1 active-version guard (§7) |
69
- | 6 | user-cancelled | any interactive cancel or confirm-gate `[N]`; On-Activation headless-purge guard |
70
-
71
- ## Result Contract (Headless)
72
-
73
- When `{headless_mode}` is true, step 3 emits a single-line `SKF_DROP_SKILL_RESULT_JSON:` envelope on **stdout**; every HARD HALT emits the same shape on **stderr** with `status: "error"`. The template, `status`/`halt_reason` semantics, `exit_code` (per the Exit Codes table above), and full enum live in `references/headless-contract.md` — the emitting stages load it directly, so an error path never depends on this file.
51
+ Headless callers and pipelines: the inputs, flags, gate map, exit codes and `SKF_DROP_SKILL_RESULT_JSON` envelope live in `references/invocation-contract.md`. Interactive runs do not need it.
74
52
 
75
53
  ## On Activation
76
54
 
77
55
  1. Load config from `{project-root}/_bmad/skf/config.yaml` and resolve:
78
56
  - `project_name`, `output_folder`, `user_name`, `communication_language`, `document_output_language`
79
57
  - `skills_output_folder`, `forge_data_folder`, `sidecar_path`
80
- - `snippet_skill_root_override` (optional string) — when set, the context-file rebuild in step 2 preserves any snippet `root:` prefix that matches the override instead of rewriting it to the target IDE's skill root. See `skf-export-skill/assets/managed-section-format.md` for full semantics.
81
- - Generate and store `timestamp` as `YYYYMMDD-HHmmss` format. This value is fixed for the entire workflow run.
58
+ - `snippet_skill_root_override` (optional string): when set, the context-file rebuild in step 2 passes it to `assemble` as `--skill-root-override`, so every row's `root:` takes it instead of the target IDE's skill root. See `skf-export-skill/assets/managed-section-format.md` for full semantics.
82
59
 
83
60
  2. **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.
84
61
 
85
62
  3. **Resolve workflow customization.** Run:
86
63
 
87
64
  ```bash
88
- python3 {project-root}/_bmad/scripts/resolve_customization.py \
89
- --skill {skill-root} --key workflow
65
+ uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --project-root {project-root} --key workflow
90
66
  ```
91
67
 
92
- The script merges the three customization layers per `bmad-customize`'s structural merge rules (scalars override, arrays append):
68
+ It merges the bundled `{skill-root}/customize.toml` with `{project-root}/_bmad/custom/skf-drop-skill.toml` (team overrides, committed) and `.user.toml` (personal overrides, gitignored). When it exits non-zero, prints no JSON or is missing, print one line, `[activation/warn] customization_resolver_unavailable: <reason>` (`<reason>`: its first stderr line, `not found` when the script is missing, `no JSON` when it printed none). If the resolver cannot run, read `{skill-root}/customize.toml` alone and use its bundled defaults: the `{project-root}/_bmad/custom/` overrides do not apply to this run. Keep the reason as `{customization_resolver_unavailable}` (unset when the resolver ran): the run folder does not exist yet, so step 4 records it.
93
69
 
94
- - `{skill-root}/customize.toml` — bundled defaults
95
- - `_bmad/custom/<skill-name>.toml` under `{project-root}` — team overrides (committed)
96
- - `_bmad/custom/<skill-name>.user.toml` under `{project-root}` — personal overrides (gitignored)
70
+ Bind each scalar to its bundled default when the merged value is empty or absent:
97
71
 
98
- 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 scalar.
72
+ - `{forbidPurgeInHeadless}` ← on when `workflow.forbid_purge_in_headless` holds any value other than the empty string (a TOML `true`, `false` or `"false"` included), else off
73
+ - `{onCompleteCommand}` ← `workflow.on_complete`, else empty (step 3 then runs no hook)
99
74
 
100
- Apply the scalar fallback now so stage files don't have to repeat the conditional logic. For each of the five scalars, if the merged value is empty or absent, the bundled default applies:
75
+ Also apply the array surfaces: run `workflow.activation_steps_prepend` now, keep `workflow.persistent_facts` as standing context (`file:` entries load their contents: the bundled default loads every `project-context.md` under `{project-root}`; an entry prefixed `!` drops each earlier entry it names and loads nothing itself, so an override's `"!file:{project-root}/**/project-context.md"` turns that default off), then run `workflow.activation_steps_append` after.
101
76
 
102
- - `{defaultMode}` ← `workflow.default_mode` (empty = always prompt; `"deprecate"` or `"purge"` = skip §8 Ask Mode)
103
- - `{forbidPurgeInHeadless}` ← `workflow.forbid_purge_in_headless` (empty or non-`"true"` = no guard)
104
- - `{unknownIdeDefaultContextFile}` ← `workflow.unknown_ide_default_context_file` if non-empty, else `AGENTS.md`
105
- - `{unknownIdeDefaultSkillRoot}` ← `workflow.unknown_ide_default_skill_root` if non-empty, else `.agents/skills/`
106
- - `{onCompleteCommand}` ← `workflow.on_complete` if non-empty, else empty (no-op — step 3 skips the post-drop hook entirely)
77
+ 4. **Pre-flight: helpers, run folder, write probe and headless-purge guard.** All of it runs before the first prompt, so a broken install or a read-only folder stops the run before the user answers anything. Each HALT below names its exit code, `halt_reason` and phase: in headless mode it prints its envelope as the Halt Envelope section of `references/invocation-contract.md` says, and an interactive HALT displays its message only.
78
+
79
+ First, resolve `{emitEnvelopeHelper}`, `{manifestOpsHelper}` and `{rebuildManagedSectionsHelper}`, each ← the first that exists of `{project-root}/_bmad/skf/shared/scripts/<script>` (installed) and `{project-root}/src/shared/scripts/<script>` (development tree), where `<script>` is `skf-emit-result-envelope.py`, `skf-manifest-ops.py` and `skf-rebuild-managed-sections.py` in turn. Then create the run folder for the envelope payloads, and bind `{run_dir}` ← the path it prints (step 3, a `--dry-run` at the confirmation gate, or an interactive HALT in step 1 or 2 deletes it; any other HALT keeps it):
80
+
81
+ ```bash
82
+ mkdir -p "{project-root}/_bmad-output/.skf-run" && mktemp -d "{project-root}/_bmad-output/.skf-run/skf-drop-skill-XXXXXXXX"
83
+ ```
107
84
 
108
- Stash all five as workflow-context variables. Stage files reference them directly — no conditional at the usage site.
85
+ If the run folder cannot be created, HALT (exit code 4, `halt_reason: "write-failed"`, phase `on-activation:run-folder`): "SKF cannot create its run folder under `{project-root}/_bmad-output/.skf-run/`: {the first stderr line}. Nothing was changed."
109
86
 
110
- Also apply the array surfaces: run `workflow.activation_steps_prepend` now, keep `workflow.persistent_facts` as standing context (`file:` entries load their contents), then run `workflow.activation_steps_append` after.
87
+ When a helper resolved to no path, HALT (exit code 4, `halt_reason: "write-failed"`, phase `on-activation:helpers`): "SKF cannot drop a skill without `{the missing script}`, which is not installed. Nothing was changed. Re-install SKF." A `--dry-run` stops here too.
111
88
 
112
- 4. **Pre-flight write probe + headless-purge guard.**
89
+ When `{customization_resolver_unavailable}` is set, record it now, so every envelope from here on carries it: write `customization_resolver_unavailable: <reason>` to `{run_dir}/resolver-warning.txt` with a file write (a resolver error can hold quotes or `$( )`, so never echo it or type it into an argument), then run `uv run {emitEnvelopeHelper} record --run-dir "{run_dir}" --warning "$(cat "{run_dir}/resolver-warning.txt")"` from `{project-root}`.
113
90
 
114
- First, verify `{skills_output_folder}` is writable. A read-only mount, full disk, or permissions-denied path otherwise only surfaces at step 2's manifest write — by then the user has already gone through every selection prompt:
91
+ Next, check that `{skills_output_folder}` is writable:
115
92
 
116
93
  ```bash
117
94
  mkdir -p "{skills_output_folder}" && \
@@ -119,8 +96,8 @@ When `{headless_mode}` is true, step 3 emits a single-line `SKF_DROP_SKILL_RESUL
119
96
  rm "{skills_output_folder}/.skf-write-probe"
120
97
  ```
121
98
 
122
- 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 `skill: null` and `drop_mode: null` (neither is resolved yet at activation time).
99
+ On any non-zero exit: HALT (exit code 4, `halt_reason: "write-failed"`, phase `on-activation:write-probe`, path `{skills_output_folder}`): "SKF cannot write to `{skills_output_folder}`: {the first stderr line}. Nothing was changed."
123
100
 
124
- Second, enforce the headless-purge guard. First compute the **effective drop mode**: it is `"purge"` when the parsed `mode` arg is `"purge"`, OR when no `mode` arg was passed AND `{defaultMode}` (resolved in §3) is `"purge"` — a purge reached via `default_mode` is still an unattended irreversible purge and must be caught here, not only an explicit `--mode purge`. If `{headless_mode}` is true AND `{forbidPurgeInHeadless}` is `"true"` AND the effective drop mode is `"purge"`: HALT with exit code 6 and `halt_reason: "headless-purge-forbidden"`, emit the error envelope, and exit immediately. The operator must re-run with an explicit `mode=deprecate` (an explicit arg overrides `default_mode`) or set `forbid_purge_in_headless = ""` (or omit the override entirely) to proceed.
101
+ Last, the headless-purge guard. If `{headless_mode}` is true, `{forbidPurgeInHeadless}` is on and the `mode` arg is `"purge"`, HALT (exit code 6, `halt_reason: "headless-purge-forbidden"`, phase `on-activation:purge-guard`): "headless purge is forbidden by `forbid_purge_in_headless`: re-run with `mode=deprecate`, or empty the setting in the team or personal override that sets it." A draft skill cannot be deprecated, so it needs an interactive run or the guard off; select.md §8 purges a draft headless only on `mode=purge`, so this guard covers that purge too.
125
102
 
126
103
  5. Load, read the full file, and then execute `references/select.md` to begin the workflow.
@@ -10,15 +10,18 @@
10
10
  # scalars: override wins • arrays (persistent_facts, activation_steps_*): append
11
11
  # arrays-of-tables with `code`/`id`: replace matching items, append new ones.
12
12
 
13
- # Steps to run before the standard activation (uv probe, config load).
14
- # Overrides append. Use for org-wide pre-flight checks (audit-log emit,
15
- # ticket-reference enforcement) that must precede any destructive work.
13
+ # Steps to run once On Activation has loaded config.yaml and resolved this
14
+ # customization, before its pre-flight (helper check, run folder, write
15
+ # probe and headless-purge guard) and before the first prompt. Overrides
16
+ # append. Use for org-wide checks (audit-log emit, ticket-reference
17
+ # enforcement) that must precede any destructive work.
16
18
 
17
19
  activation_steps_prepend = []
18
20
 
19
- # Steps to run after activation but before the first stage executes.
20
- # Overrides append. Use for context loads or banner customization that
21
- # should run once activation completes successfully.
21
+ # Steps to run right after the prepend steps and the persistent facts,
22
+ # still before the pre-flight: a run that then HALTs on a missing helper,
23
+ # an unwritable folder or the headless-purge guard has already run them.
24
+ # Overrides append. Use for context loads or banner customization.
22
25
 
23
26
  activation_steps_append = []
24
27
 
@@ -26,42 +29,53 @@ activation_steps_append = []
26
29
  # (drop-policy reminders, retention guardrails, audit-trail rules).
27
30
  # Overrides append.
28
31
  #
29
- # Each entry is either:
32
+ # Each entry is one of:
30
33
  # - a literal sentence, e.g. "Purges of skills tagged `compliance` require ticket reference."
31
34
  # - a file reference prefixed with `file:`, e.g.
32
35
  # "file:{project-root}/docs/drop-policy.md" (globs supported; file
33
36
  # contents are loaded and treated as facts).
37
+ # - an entry prefixed with `!`, which loads nothing and drops each earlier
38
+ # entry it names.
39
+ #
40
+ # The default below loads every project-context.md under {project-root}.
41
+ # Overrides append, so they cannot delete it; to stop loading those files,
42
+ # set in {project-root}/_bmad/custom/skf-drop-skill.toml:
43
+ # [workflow]
44
+ # persistent_facts = ["!file:{project-root}/**/project-context.md"]
34
45
 
35
46
  persistent_facts = [
36
47
  "file:{project-root}/**/project-context.md",
37
48
  ]
38
49
 
39
- # Optional post-drop hook. When non-empty, invoked with
40
- # `--result-path=<path>` after the drop-skill result JSON is finalized
41
- # (references/report.md). Failures are logged to workflow_warnings[] but
42
- # never fail the workflow — useful for audit-log emit, a notifier, or a
43
- # ticket-tracker integration after an irreversible purge.
50
+ # Optional post-drop hook: a shell command, run as
51
+ # `<command> --result-path=<path>` once step 3 (references/report.md) has
52
+ # written the drop's result record. It runs only after a drop whose record
53
+ # the emitter wrote (report.md skips it when `result_path` is null), so a
54
+ # dry run, a HALT or a failed record write never calls it. A hook that
55
+ # exits non-zero is shown as a line of its own and never fails the drop,
56
+ # which may already be irreversible. Useful for an audit-log emit, a
57
+ # notifier or a ticket-tracker update after a purge.
44
58
 
45
59
  on_complete = ""
46
60
 
47
- # --- Optional safety + default scalars ---
61
+ # --- Optional safety scalar ---
48
62
  #
49
- # Default drop mode. Empty string = always prompt the user at §8 Ask Mode.
50
- # Set to "deprecate" or "purge" to skip the prompt — the headless
51
- # auto-decision log records the override source.
52
-
53
- default_mode = ""
54
-
55
- # Hard-block hard-purge in headless mode. When set to "true", a headless
56
- # invocation with `mode=purge` HALTs at activation with exit code 6
57
- # (`halt_reason: "headless-purge-forbidden"`) instead of silently deleting
58
- # files. Operators must either re-run with `mode=deprecate` or unset this
59
- # flag for that run. Empty string = no guard (default).
63
+ # Block a purge in headless mode. Any value other than the empty string
64
+ # turns the guard on ("true", a TOML true, and even "false" or false), so a
65
+ # mistyped value that still parses blocks the purge rather than allowing it.
66
+ # An override file that fails to parse (an unquoted True, yes or on, or a
67
+ # bad line elsewhere in it) stops the resolver: the run warns
68
+ # customization_resolver_unavailable and uses this file alone, so the guard
69
+ # is off. Quote the value, as in "true". In
70
+ # {project-root}/_bmad/custom/skf-drop-skill.toml (or .user.toml) write it
71
+ # under the table, as two lines: `[workflow]` then
72
+ # `forbid_purge_in_headless = "true"`. A key above the `[workflow]` line is
73
+ # ignored without a warning, which leaves the guard off. With the guard
74
+ # on, a headless run with `mode=purge` HALTs at activation with exit code 6
75
+ # (`halt_reason: "headless-purge-forbidden"`) instead of deleting files:
76
+ # re-run with `mode=deprecate`, or interactively. A draft skill with no
77
+ # manifest entry cannot be deprecated, so it needs an interactive run or
78
+ # the guard off. The drop mode has no default: every run passes `mode` or
79
+ # answers the prompt. Empty string = no guard (default).
60
80
 
61
81
  forbid_purge_in_headless = ""
62
-
63
- # Fallback IDE → context-file mapping for unknown IDEs in `config.yaml.ides`.
64
- # Empty string = use bundled defaults (AGENTS.md / .agents/skills/).
65
-
66
- unknown_ide_default_context_file = ""
67
- unknown_ide_default_skill_root = ""