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
@@ -11,12 +11,14 @@ Helps the user define what to skill — target repo, scope, language, inclusion/
11
11
 
12
12
  A good skill brief sets a tight, cohesive boundary: one capability with 3-8 primary functions, an unambiguous public API surface, and a description short enough to fit in a registry row. Briefs that try to cover several unrelated concerns (e.g. authentication *and* data visualization) compile into skills that no agent can route to confidently — a brief covering too much is a worse failure mode than a brief covering too little, and this workflow steers toward the smaller, sharper version when scope is unclear. Scope on cheap signals — manifests, top-level exports, intent — not full AST extraction.
13
13
 
14
- **Ratify path.** A pre-authored `skill-brief.yaml` (typically from `skf-analyze-source`'s `generate-briefs` step) can be *ratified* — reviewed and rewritten in place — instead of re-derived from scratch. Interactively, pass its path at the first prompt; headlessly, pass `from_brief <path>`. See the `from_brief` Inputs cell in `references/invocation-contract.md` for the full ratify contract.
14
+ **Ratify path.** A pre-authored `skill-brief.yaml` (typically from `skf-analyze-source`) can be *ratified*: reviewed and written to `{forge_data_folder}/{name}/skill-brief.yaml` (in place when it already lives there) instead of derived again. Interactively, pass its path at the first prompt; headlessly, pass `from_brief <path>`. `references/invocation-contract.md` states the full ratify contract.
15
15
 
16
16
  ## Conventions
17
17
 
18
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.
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; e.g. `knowledge/tool-resolution.md` and `shared/health-check.md`.
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
+ - `references/` holds prompt content carved out of SKILL.md (workflow stages chained via frontmatter `nextStepFile`, plus static reference docs); `assets/` holds the brief schema, the scope templates and the description voice examples.
20
22
  - `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives, if present).
21
23
  - `{project-root}`-prefixed paths resolve from the project working directory.
22
24
  - `{skill-name}` resolves to the skill directory's basename.
@@ -33,56 +35,65 @@ These rules apply to every step in this workflow:
33
35
  - **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
36
  - 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.
35
37
  - If `{headless_mode}` is true, auto-proceed through confirmation gates with their default action and log each auto-decision
38
+ - Keep one list of the run's warnings, `workflow_warnings[]`, in the order they are raised: each `warn:` line a step logs, each entry of a helper's `warnings[]` that a step surfaces, and each degraded signal the run goes on past (a truncated tree listing, a failed doc detection or QMD step), one line of text each. A helper warning that is an object, such as the `{field, message}` entries skf-validate-brief-inputs.py and skf-validate-brief-schema.py return, goes in as one line, `<field>: <message>`: the emitter takes only strings, and one object in `warnings` makes it exit non-zero and print no line. The run's `SKF_BRIEF_RESULT_JSON` envelope carries the list as `warnings`, at the end of a successful run and at a halt
39
+
40
+ ## Halt Contract
41
+
42
+ Every HALT that names a `halt_reason`, in any step file, emits the `SKF_BRIEF_RESULT_JSON` error envelope before it stops when `{headless_mode}` or `{auto_mode}` is true, through the emitter On Activation step 4 resolves:
43
+
44
+ ```bash
45
+ uv run {emitBriefEnvelopeHelper} emit --target stderr <<'SKF_BRIEF_HALT'
46
+ {"status":"error","skill_name":"<skill name>","halt_reason":"<halt_reason>","mode":<"auto" or null>,"warnings":[<workflow_warnings[] as JSON strings>]}
47
+ SKF_BRIEF_HALT
48
+ ```
49
+
50
+ Give the halt's own `halt_reason`: the helper derives `exit_code` from it. `skill_name` is the resolved skill name, or `unknown` while step 1 has not resolved one; `mode` is `"auto"` while `{auto_mode}` is true, else `null`; `warnings` holds `workflow_warnings[]` (`[]` when it is empty). The quoted heredoc hands the payload to the helper as written, so a quote inside a warning needs no shell escaping. Display the line the helper prints verbatim, then HALT. If `{emitBriefEnvelopeHelper}` has no path, or the helper exits non-zero or prints no line, display the halt message alone: a pipeline that sees no envelope line treats the run as not completed cleanly. An interactive run outside `[auto]` mode displays the halt message and emits nothing. A HALT that names no `halt_reason`, such as a helper with no installed path (an install fault: re-install SKF), emits nothing in any mode.
36
51
 
37
52
  ## On Activation
38
53
 
39
54
  1. Load config from `{project-root}/_bmad/skf/config.yaml` and resolve:
40
- - `project_name`, `output_folder`, `user_name`, `communication_language`, `forge_data_folder`, `sidecar_path`
55
+ - `project_name`, `output_folder`, `user_name`, `communication_language`, `document_output_language`, `forge_data_folder`, `sidecar_path`
41
56
 
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.
57
+ 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.
58
+
59
+ **Resolve `{auto_mode}`**: true when the invocation carries the `[auto]` flag (a pipeline's `BS[auto]`, which step 1 §1b routes to the auto stages), else false.
43
60
 
44
61
  3. **Resolve workflow customization.** Run:
45
62
 
46
63
  ```bash
47
- python3 {project-root}/_bmad/scripts/resolve_customization.py \
48
- --skill {skill-root} --key workflow
64
+ uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --project-root {project-root} --key workflow
49
65
  ```
50
66
 
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.
67
+ It merges the bundled `{skill-root}/customize.toml` with `{project-root}/_bmad/custom/skf-brief-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. In that case add `customization_resolver_unavailable: <reason>` to `workflow_warnings[]` as the run's first warning.
58
68
 
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:
69
+ Bind the values the stage files use, taking the bundled default when the merged value is empty or absent:
60
70
 
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
- - `{onCompleteCommand}` ← `workflow.on_complete` if non-empty, else empty string (no-op — write-brief.md skips the hook invocation entirely)
71
+ - `{descriptionVoiceExamplesPath}` ← `workflow.description_voice_examples_path`, else `assets/description-voice-examples.md`
72
+ - `{scopeTemplatesPath}` ← `workflow.scope_templates_path`, else `assets/scope-templates.md`
73
+ - `{onCompleteCommand}` ← `workflow.on_complete`, else empty: no hook, so write-brief.md §6b and step-auto-validate.md §3, the two places it runs, skip it
65
74
 
66
- Stash all four as workflow-context variables. Stage files reference `{descriptionVoiceExamplesPath}` / `{scopeTemplatesPath}` / `{briefSchemaPath}` / `{onCompleteCommand}` 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 (or wire in a pipeline hook) without forking the skill.
75
+ Also apply the array surfaces so they are not silent no-ops: execute each entry in `workflow.activation_steps_prepend` in order now; treat every entry in `workflow.persistent_facts` as standing context for the whole run (`file:`-prefixed entries are paths or globs whose contents load as facts, and the bundled default loads any `project-context.md` under `{project-root}`; an entry prefixed `!` loads nothing and drops each earlier entry it names); then, after activation completes and before step 5 loads the first stage, execute each entry in `workflow.activation_steps_append` in order.
67
76
 
68
- Also apply the array surfaces so they are not silent no-ops: execute each entry in `workflow.activation_steps_prepend` in order now; treat every entry in `workflow.persistent_facts` as standing context for the whole run (`file:`-prefixed entries are paths or globs whose contents load as facts — the bundled default loads any `project-context.md` under `{project-root}`); then, after activation completes and before step 4 loads the first stage, execute each entry in `workflow.activation_steps_append` in order.
77
+ 4. **Resolve the envelope emitter** before any stage can halt: `{emitBriefEnvelopeHelper}` ← `{project-root}/_bmad/skf/shared/scripts/skf-emit-brief-result-envelope.py`, else `{project-root}/src/shared/scripts/skf-emit-brief-result-envelope.py`, the first that exists (no path when neither does). It prints every `SKF_BRIEF_RESULT_JSON` line of the run: a halt's through the Halt Contract above, the success line in write-brief.md §4b or step-auto-validate.md §3. `references/invocation-contract.md` defines the envelope.
69
78
 
70
- 4. Load, read the full file, and execute `references/gather-intent.md`.
79
+ 5. Load, read the full file, and execute `references/gather-intent.md`.
71
80
 
72
81
  ## Stages
73
82
 
74
83
  | # | Step | File | Auto-proceed |
75
84
  |---|------|------|--------------|
76
85
  | 1 | Gather Intent | references/gather-intent.md | No (interactive) |
86
+ | 1h | Headless Input Gate (headless only) | references/headless-args.md | Yes |
87
+ | 1r | Ratify an Existing Brief (ratify only) | references/gather-intent-ratify.md | No (interactive menu; headless takes [R]) |
77
88
  | 1a | Auto-Brief Generation (auto mode only) | references/step-auto-brief.md | Yes |
78
- | 1b | Auto-Brief Validation (auto mode only) | references/step-auto-validate.md | No (interactive gate — headless auto-approves) |
79
- | 2 | Analyze Target | references/analyze-target.md | Yes |
89
+ | 1b | Auto-Brief Validation (auto mode only) | references/step-auto-validate.md | Yes |
90
+ | 2 | Analyze Target | references/analyze-target.md | Conditional (a truncated tree, a monorepo) |
80
91
  | 3 | Scope Definition | references/scope-definition.md | No (interactive) |
81
92
  | 4 | Confirm Brief | references/confirm-brief.md | No (confirm) |
82
- | 5 | Write Brief | references/write-brief.md | Yes |
93
+ | 5 | Write Brief | references/write-brief.md | Conditional (the brief exists) |
83
94
  | 6 | Workflow Health Check (terminal) | references/health-check.md | Yes |
84
95
 
85
- Stages 1a-1b are conditional — they replace stages 2-5 when BS is invoked with the `[auto]` flag via pipeline context. The routing decision is made in stage 1 (gather-intent.md §1b). In auto mode, the chain is: gather-intent.md §1 (forge tier) → §1b (auto check) → step-auto-brief.md → step-auto-validate.md → health-check.md (on [A]pprove or [E]dit) or → confirm-brief.md → write-brief.md → health-check.md (on [R]eject).
96
+ Every run starts in gather-intent.md, whose §1 (run folder, forge tier) serves every mode; its §1b routes by mode. `[auto]` (a pipeline's `BS[auto]`): step-auto-brief.md → step-auto-validate.md → health-check.md, in place of stages 2-5 except stage 5's §3b QMD registration, which step-auto-validate.md runs at Deep tier. It stays a separate route by design: the forge-auto pipeline contract gives it doc enrichment (step-auto-brief.md §2-§3), which the ratify and derive routes do not run, and an envelope with `mode: "auto"`. Headless: headless-args.md validates the arguments before any stage uses them, then continues at stage 2. Interactive: the rest of gather-intent.md. A brief to ratify (a brief path at the first prompt, or a headless `from_brief`) goes through gather-intent-ratify.md straight to stage 4, skipping stages 2 and 3.
86
97
 
87
98
  ## Invocation Contract
88
99
 
@@ -1,6 +1,6 @@
1
1
  # Description Voice Examples
2
2
 
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."
3
+ Loaded by step 1 only: §4 shows the examples to a first-time user, and §7b, or the headless input gate, composes the description from them. 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
 
@@ -42,8 +42,8 @@ Default inclusions:
42
42
  - All public modules: {list from analysis}
43
43
 
44
44
  Default exclusions:
45
- - Test files (`**/*.test.*`, `**/*.spec.*`, `**/test/`, `**/tests/`)
46
- - Build artifacts (`**/dist/`, `**/build/`, `**/target/`)
45
+ - Test files (`**/*.test.*`, `**/*.spec.*`, `**/test/**`, `**/tests/**`)
46
+ - Build artifacts (`**/dist/**`, `**/build/**`, `**/target/**`)
47
47
  - Configuration files
48
48
  - Documentation source files
49
49
 
@@ -51,12 +51,12 @@ Prompt: "Any additional exclusions you'd like to add? Or adjustments to these de
51
51
 
52
52
  ### Specific Modules Boundaries
53
53
 
54
- **Phase 1 — Module selection:**
54
+ **Phase 1: Module selection**
55
55
 
56
56
  Present numbered list of modules from step 02 with brief descriptions.
57
57
  Prompt: "Which modules would you like to include? (Enter numbers, comma-separated):"
58
58
 
59
- **Phase 2 — Granularity within selected modules:**
59
+ **Phase 2: Granularity within selected modules**
60
60
 
61
61
  For selected modules, ask:
62
62
  - **A)** Everything in those modules (all files)
@@ -66,30 +66,30 @@ Prompt: "Any files or patterns to explicitly exclude within these modules?"
66
66
 
67
67
  ### Public API Only Boundaries
68
68
 
69
- **Phase 1 — Export selection:**
69
+ **Phase 1: Export selection**
70
70
 
71
71
  Present numbered list of exports/entry points from step 02.
72
72
  Prompt: "Which of these would you like to include? (Enter numbers, or 'all'):"
73
73
 
74
- **Phase 2 — Confirm exclusions:**
74
+ **Phase 2: Confirm exclusions**
75
75
 
76
76
  Exclusions will include all internal implementation files, tests, and utilities.
77
77
  Prompt: "Any additional items you'd like to include or exclude?"
78
78
 
79
79
  ### Reference App Boundaries
80
80
 
81
- **Phase 1 — Pattern surface intent:**
81
+ **Phase 1: Pattern surface intent**
82
82
 
83
83
  Ask: "What is the authored pattern surface for this skill? List the files (or directories) the user must touch to adopt the pattern — entry points, config files, lifecycle hooks, build scripts."
84
84
 
85
85
  - Record the user's list as `scope.tier_a_include` when narrower than a broad `scope.include`. Reference-app briefs benefit strongly from `tier_a_include` because the denominator is small and precise.
86
86
  - Prompt follow-up: "Any files outside that list that should still be in scope for completeness (tests, fixtures, supporting configs)?"
87
87
 
88
- **Phase 2 — Scope.include and exclusions:**
88
+ **Phase 2: Scope.include and exclusions**
89
89
 
90
90
  Set `scope.include` to the pattern-surface file list (or broader union when the author flagged supporting files). Default exclusions mirror the Full Library defaults (tests, build artifacts, docs source). Record `scope.notes` with a one-sentence description of the pattern (e.g., "Embedded Python sidecar pattern for Electron apps — lifecycle orchestration, RPC proxy, build-copy wiring").
91
91
 
92
- **Phase 3 — Confirmation:**
92
+ **Phase 3: Confirmation**
93
93
 
94
94
  Summary showing: pattern surface count, `tier_a_include` vs `include` distinction, notes. Prompt: "Does this reference-app scope look right? Adjust before continuing."
95
95
 
@@ -105,35 +105,28 @@ Prompt: "Any additional documentation URLs to include? Or URLs to exclude from t
105
105
 
106
106
  ### Component Library Boundaries
107
107
 
108
- **Phase 1 — Registry Detection:**
108
+ On a step 4 `[R]` re-entry, `scope.registry_path`, `scope.demo_patterns` and `scope.ui_variants` hold the previous pass's answers: present each as the current answer of its phase, for the user to keep or change.
109
109
 
110
- Auto-detect or accept explicit `registry_path` from user. Scan source tree for files matching common registry patterns:
111
- - Files named `registry.ts`, `components.ts`, `index.ts` in `registry/`, `catalog/`, or `components/` directories
112
- - Arrays of objects with `{ id, name, component }` structure and 10+ entries
113
- - Files with `Component[]` type annotations
110
+ **Phase 1: Registry Detection**
114
111
 
115
- Present detected registry candidate(s) to user for confirmation.
112
+ Present the registry candidates step 3's component library detection found (`selected` first, then any other qualifying candidate, each with its score out of 9 and its entry count, and the recommender's `registry_path` when it is none of them) for the user to confirm, or accept an explicit `registry_path` from the user. Record the confirmed path as `scope.registry_path`.
116
113
  Prompt: "I found what looks like a component registry at {path} ({count} entries). Is this correct? Or provide the registry path:"
117
114
 
118
- **Phase 2 — Demo/Example Exclusion:**
115
+ **Phase 2: Demo/Example Exclusion**
119
116
 
120
- Auto-detect demo directories and file patterns:
121
- - Directories: `demo/`, `demos/`, `stories/`, `examples/`, `__stories__/`, `storybook/`
122
- - Files: `*.stories.*`, `*.story.*`, `*.example.*`, `*.demo.*`
123
-
124
- Show detected patterns to the user for confirmation before applying them, rather than excluding files silently.
117
+ Show the demo patterns step 3's component library detection found (each glob with its file count and sample files) to the user for confirmation before applying them, rather than excluding files silently. Record the confirmed patterns as `scope.demo_patterns` and add them to the exclusions.
125
118
  Prompt: "**Auto-detected {N} demo/example files** in {M} directories. Confirm exclusion? [Y/n] Or adjust patterns:"
126
119
 
127
- **Phase 3 — Variant Selection (if applicable):**
120
+ **Phase 3: Variant Selection (if applicable)**
128
121
 
129
122
  If multiple design system variant directories detected (e.g., `react-shadcn/`, `react-baseui/`, `react-carbon/`):
130
123
  - Present detected variants with component counts per variant
131
124
  - User selects primary variant and which variants to include
132
- - Record as `ui_variants` in brief
125
+ - Record them as `scope.ui_variants`, one `{name, package}` entry per variant
133
126
 
134
127
  Prompt: "I detected {count} design system variants: {list with counts}. Which is the primary variant? Include all? [Y/n]"
135
128
 
136
- **Phase 4 — Scope Confirmation:**
129
+ **Phase 4: Scope Confirmation**
137
130
 
138
131
  Summary showing: component count, excluded demo count, variant summary, include/exclude patterns.
139
132
  Prompt: "Does this component library scope look right? Adjust before continuing."
@@ -27,6 +27,9 @@
27
27
  | `source_authority` | string | `official` / `community` / `internal` | Default `community`. Set to `official` only when the skill creator is the library maintainer. Forced to `community` when `source_type: "docs-only"`. |
28
28
  | `source_ref` | string | Git ref (tag/branch/HEAD) | Resolved git ref used for source access. Set automatically during tag resolution — do not set manually. |
29
29
  | `scope.tier_a_include` | array | Glob patterns (min 1, non-empty) | Optional. Narrower tier-A include list for a curated-subset skill — stratified monorepo packages, single-crate `specific-modules` scopes, and multi-entry exports-map packages. When present, `skf-test-skill` re-derives the coverage denominator from this list instead of the coarse `scope.include`, so the denominator reflects the authoring surface rather than incidentally-matched internal infrastructure. **It also exempts the brief from the denominator deflation guard**, so supply it only when it genuinely narrows the surface — never as an empty list, and never as a way to widen (listing files outside `scope.include` inverts its meaning). See `skf-test-skill/references/source-access-protocol.md` stratified-scope resolution. |
30
+ | `scope.registry_path` | string | Path from the source root (non-empty) | Optional, for `scope.type: "component-library"`. The component registry file. `skf-create-skill` step 3d reads it instead of detecting a registry, and writes it back, with a `demo-and-registry` amendment, when the user confirms a detected registry or gives its path. |
31
+ | `scope.ui_variants` | array | `{name, package?}` objects (`name` non-empty) | Optional, for `scope.type: "component-library"`. The design system variants, the first one primary. |
32
+ | `scope.demo_patterns` | array | Glob patterns (non-empty strings) | Optional, for `scope.type: "component-library"`. The demo and example files `skf-create-skill` step 3d leaves out. Step 3d reads them instead of detecting demo files, and writes them back, with a `demo-and-registry` amendment per glob, when the user confirms or adjusts the detected ones. |
30
33
 
31
34
  When `source_type: "docs-only"`:
32
35
  - `source_repo` becomes optional (set to doc site URL for reference)
@@ -43,7 +46,7 @@ During brief creation, attempt to auto-detect the source version before defaulti
43
46
  - **Rust:** `Cargo.toml` `[package] version` (static) → if `version = { workspace = true }`, resolve from workspace root `Cargo.toml` → `git describe --tags --abbrev=0`
44
47
  - **Go:** version tag from `go.mod` or `git describe --tags --abbrev=0`
45
48
 
46
- If the source is a remote GitHub repo, use `gh api repos/{owner}/{repo}/contents/{file}` to read the version file. If the source is local, read the file directly.
49
+ If the source is a remote GitHub repo, read the version file step 2 fetched into the run folder with `skf-github-fetch.py`, which needs `gh` only for a private repository. If the source is local, read the file directly.
47
50
 
48
51
  If detection succeeds, use the detected version. If it fails or returns a non-semver value, fall back to `"1.0.0"`.
49
52
 
@@ -77,22 +80,30 @@ scope:
77
80
  # reason: "user overrode full-library->public-api: only documented API ships"
78
81
  # recorded: "2026-05-18"
79
82
  # Optional: amendment log for scope decisions made during create-skill §2a,
80
- # update-skill §1b (auth-doc), and update-skill §1c (scope-expansion).
83
+ # update-skill §1b (auth-doc), update-skill §1c (scope-expansion) and
84
+ # create-skill step 3d (demo-and-registry).
81
85
  # amendments:
82
86
  # - path: "apps/docs/public/llms.txt"
83
- # action: "promoted" # "promoted" | "skipped" | "demoted-include" | "demoted-exclude"
84
- # category: "auth-doc" # "auth-doc" (default for legacy entries) | "scope-expansion"
87
+ # action: "promoted" # "promoted" | "skipped" | "excluded" | "demoted-include" | "demoted-exclude" | "demo-excluded" | "registry-confirmed"
88
+ # category: "auth-doc" # "auth-doc" (default for legacy entries) | "scope-expansion" | "demo-and-registry"
85
89
  # reason: "authoritative AI docs — only source for canonical install command"
86
- # heuristic: "llms.txt" # required for auth-doc; absent for scope-expansion
90
+ # heuristic: "llms.txt" # required for auth-doc; absent for scope-expansion and demo-and-registry
87
91
  # date: "2026-04-11"
88
92
  # workflow: "skf-create-skill"
89
93
  # - path: "python/cocoindex/_internal/api.py"
90
94
  # action: "promoted"
91
95
  # category: "scope-expansion"
92
- # reason: "out-of-scope new public API — drift report drift-report-20260424-212355.md"
96
+ # reason: "out-of-scope new public API: drift report drift-report-20260424-212355.md"
93
97
  # evidence: "~70 new exports flagged out-of-scope by audit"
94
98
  # date: "2026-04-25"
95
99
  # workflow: "skf-update-skill"
100
+ # - path: "registry/index.ts"
101
+ # action: "registry-confirmed"
102
+ # category: "demo-and-registry"
103
+ # reason: "user confirmed the detected registry at create-skill step 3d"
104
+ # evidence: "score 8/9, 52 entries"
105
+ # date: "2026-10-01"
106
+ # workflow: "skf-create-skill"
96
107
  # Additional fields when scope.type is "component-library":
97
108
  # registry_path: "path/to/registry.ts" # Optional — auto-detected if omitted
98
109
  # ui_variants: # Optional — design system variants
@@ -114,7 +125,7 @@ scope:
114
125
  | `recommended` | string (one of the six `scope.type` values) | yes | `skf-recommend-scope-type.py` → `scope_type` |
115
126
  | `chosen` | string (one of the six) | yes | final `scope.type` |
116
127
  | `accepted_recommendation` | bool | yes | `chosen == recommended` |
117
- | `heuristic` | string | yes | script `matched_heuristic` |
128
+ | `heuristic` | string | yes | script `matched_heuristic` (values listed in `skf-recommend-scope-type.py`); `user-supplied-arg` when a headless run passed `scope_type`; older briefs may carry `reference-app-keywords` |
118
129
  | `reason` | string | yes | accepted → script `rationale` verbatim; overridden → user's stated reason, or `"user overrode {recommended}->{chosen}; reason not stated"` |
119
130
  | `recorded` | string (ISO date `YYYY-MM-DD`) | yes | current date — mirrors `amendments[].date` |
120
131
 
@@ -127,21 +138,22 @@ scope:
127
138
 
128
139
  ### Scope Amendments (Optional)
129
140
 
130
- `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:
141
+ `scope.amendments[]` is an additive, optional audit log of scope decisions made by workflows after the brief was first authored. Three writer paths exist today:
131
142
 
132
143
  - **Auth-doc promotions** (`category: "auth-doc"`) — `skf-create-skill` §2a and its mirror `skf-update-skill` §1b append entries when extraction discovers authoritative AI documentation files (`llms.txt`, `AGENTS.md`, etc.) that the original scope patterns excluded.
133
144
  - **Scope-expansion promotions** (`category: "scope-expansion"`) — `skf-update-skill` §1c appends entries when an audit drift report flags out-of-scope new public API paths (typically a major-version restructure where the brief's `scope.include` no longer reflects the real surface).
145
+ - **Demo-and-registry decisions** (`category: "demo-and-registry"`): `skf-create-skill` step 3d appends one entry per demo glob and one for the registry file when the user confirms or gives them at its component-library gates, and writes the values to `scope.demo_patterns` and `scope.registry_path`. A headless run never writes one: its automatic decisions stay in the run's audit trail.
134
146
 
135
147
  **Entry fields:**
136
148
 
137
149
  | Field | Type | Required | Description |
138
150
  |---|---|---|---|
139
- | `path` | string | yes | Relative path (or glob, for `category: "scope-expansion"`) from source root to the file or tree being amended. For `promoted` actions this matches the literal entry added to `scope.include`. |
140
- | `action` | string | yes | One of: `promoted` (path added to `scope.include`), `skipped` (user declined promotion; decision recorded to prevent re-prompting), `excluded` (path added to `scope.exclude` — only valid with `category: "scope-expansion"`; used by gap-driven rescope to remove an internal / `#[doc(hidden)]` / out-of-scope export from the public surface), `demoted-include` (path removed from `scope.include` — only valid with `category: "scope-expansion"`), `demoted-exclude` (path removed from `scope.exclude` — only valid with `category: "scope-expansion"`). |
141
- | `category` | string | no | One of: `auth-doc` (default for entries without this field — the historical sole use case), `scope-expansion`. Distinguishes which workflow path wrote the entry and which writer-rules apply on re-runs. |
151
+ | `path` | string | yes | Relative path (or glob, for `category: "scope-expansion"` and a `demo-and-registry` demo pattern) from source root to the file or tree being amended. For `promoted` actions this matches the literal entry added to `scope.include`. |
152
+ | `action` | string | yes | One of: `promoted` (path added to `scope.include`), `skipped` (user declined promotion; decision recorded to prevent re-prompting), `excluded` (path added to `scope.exclude`, only valid with `category: "scope-expansion"`; used by gap-driven rescope to remove an internal / `#[doc(hidden)]` / out-of-scope export from the public surface), `demoted-include` (path removed from `scope.include`, only valid with `category: "scope-expansion"`), `demoted-exclude` (path removed from `scope.exclude`, only valid with `category: "scope-expansion"`), `demo-excluded` (the glob is written to `scope.demo_patterns`: only valid with `category: "demo-and-registry"`), `registry-confirmed` (the file is written to `scope.registry_path`: only valid with `category: "demo-and-registry"`). |
153
+ | `category` | string | no | One of: `auth-doc` (default for entries without this field: the historical sole use case), `scope-expansion`, `demo-and-registry`. Distinguishes which workflow path wrote the entry and which writer-rules apply on re-runs. |
142
154
  | `reason` | string | yes | Human-readable sentence explaining the decision. Either user-provided at prompt time or auto-generated. |
143
155
  | `heuristic` | string | conditional | Required for `category: "auth-doc"` — the basename that matched (`llms.txt`, `AGENTS.md`, etc.). Omit for `category: "scope-expansion"`. |
144
- | `evidence` | string | conditional | Required for `category: "scope-expansion"` — short rationale from the source signal (e.g., a drift-report finding's evidence one-liner). Omit for `category: "auth-doc"`. |
156
+ | `evidence` | string | conditional | Required for `category: "scope-expansion"` and `category: "demo-and-registry"`: short rationale from the source signal (a drift-report finding's evidence one-liner; the files a demo glob matched, or the registry's score and entry count). Omit for `category: "auth-doc"`. |
145
157
  | `date` | string | yes | ISO date (`YYYY-MM-DD`) when the amendment was recorded. |
146
158
  | `workflow` | string | yes | Workflow name that wrote the amendment (`skf-create-skill`, `skf-update-skill`). Identifies which workflow made the decision. |
147
159
 
@@ -151,7 +163,7 @@ scope:
151
163
 
152
164
  **Demotion (scope-expansion only):** `demoted-include` removes a previously-promoted path from `scope.include` — used when a prior `[P]` decision is reversed. `demoted-exclude` removes a path from `scope.exclude` — used when a previously excluded path needs to be re-evaluated. Both write the structural change and append the amendment so future runs see the rationale. Demotion is not valid for `category: "auth-doc"`: auth-doc skips already prevent re-prompting without scope mutation.
153
165
 
154
- **Exclusion (scope-expansion only):** `excluded` adds a path to `scope.exclude` — written by `skf-update-skill` gap-driven rescope (detect-changes §0 rule R1) when a coverage gap's remediation is removal (the export is internal, `#[doc(hidden)]`, or out of scope). The amendment is the audit trail; the `scope.exclude` write is what shrinks the source barrel, so the legitimate scope reduction is expressed in the brief rather than by editing `metadata.stats`. This keeps the reduction visible to `skf-test-skill`'s denominator-deflation check, which re-derives the barrel from `scope.include` filtered by `scope.exclude`. Not valid for `category: "auth-doc"`.
166
+ **Exclusion (scope-expansion only):** `excluded` adds a path to `scope.exclude`, written by `skf-update-skill` gap-driven rescope (gap-driven.md §1 rule R1) when a coverage gap's remediation is removal (the export is internal, `#[doc(hidden)]`, or out of scope). The amendment is the audit trail; the `scope.exclude` write is what shrinks the source barrel, so the legitimate scope reduction is expressed in the brief rather than by editing `metadata.stats`. This keeps the reduction visible to `skf-test-skill`'s denominator-deflation check, which re-derives the barrel from `scope.include` filtered by `scope.exclude`. Not valid for `category: "auth-doc"`.
155
167
 
156
168
  **Backward compatibility:** `scope.amendments` is optional. Briefs without this field validate unchanged. Treat missing as an empty list. Existing entries without `category` are equivalent to `category: "auth-doc"` — readers must default the field when absent.
157
169
 
@@ -160,6 +172,7 @@ scope:
160
172
  - `skf-create-skill` §2a consults it to avoid re-prompting on decided auth-doc files.
161
173
  - `skf-update-skill` §1b (mirror of §2a) consults it for the same auth-doc reason.
162
174
  - `skf-update-skill` §1c consults it to avoid re-prompting on decided scope-expansion candidates and to honor prior `demoted-*` decisions.
175
+ - `skf-create-skill` step 3d does not read the log: it reads `scope.demo_patterns` and `scope.registry_path`, which the same write sets. The auth-doc and scope-expansion readers act only on their own actions, so a `demo-and-registry` entry on the same path never stands in for one of their decisions.
163
176
  - `skf-audit-skill` may optionally report on stale promotions (promoted paths that no longer exist in source) as a future enhancement — not currently implemented.
164
177
  - Humans reading the brief see the audit trail of non-obvious scope decisions.
165
178
 
@@ -168,7 +181,8 @@ scope:
168
181
  - `skf-create-skill` §2a (Discovered Authoritative Files Protocol) — `category: "auth-doc"`
169
182
  - `skf-update-skill` §1b (mirror of §2a applied during change detection) — `category: "auth-doc"`
170
183
  - `skf-update-skill` §1c (Major-Version Scope Reconciliation) — `category: "scope-expansion"`
171
- - `skf-update-skill` gap-driven rescope (detect-changes §0 rule R1) — `category: "scope-expansion"`, `action: "excluded"`
184
+ - `skf-update-skill` gap-driven rescope (gap-driven.md §1 rule R1): `category: "scope-expansion"`, `action: "excluded"`
185
+ - `skf-create-skill` step 3d (component-library demo exclusion and registry detection): `category: "demo-and-registry"`, `action: "demo-excluded"` or `"registry-confirmed"`, only for an answer a user gave
172
186
  - Manual edits by the brief author are permitted but should include all required fields above (and `category` when the entry is not an auth-doc decision).
173
187
 
174
188
  ## YAML Template
@@ -211,7 +225,7 @@ The runtime template lives in `references/confirm-brief.md` §2 — that is the
211
225
  ## Validation Rules
212
226
 
213
227
  1. `name` must be unique within {forge_data_folder}
214
- 2. `source_repo` must be accessible (gh api for GitHub, path exists for local)
228
+ 2. `source_repo` must be accessible (listed by skf-github-probe.py for a GitHub URL, which needs gh only for a private repository; path exists for local)
215
229
  3. `language` must be a recognized programming language
216
230
  4. `scope.type` must be one of the six defined types
217
231
  5. `scope.include` must have at least one pattern (exception: `docs-only` scope, where include patterns are optional since no source code is available)
@@ -1,8 +1,8 @@
1
1
  # DO NOT EDIT -- overwritten on every update.
2
2
  #
3
3
  # Workflow customization surface for skf-brief-skill.
4
- # Team overrides: _bmad/custom/skf-brief-skill.toml (under {project-root})
5
- # Personal overrides: _bmad/custom/skf-brief-skill.user.toml (under {project-root})
4
+ # Team overrides: {project-root}/_bmad/custom/skf-brief-skill.toml
5
+ # Personal overrides: {project-root}/_bmad/custom/skf-brief-skill.user.toml
6
6
 
7
7
  [workflow]
8
8
 
@@ -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 (auth, network,
15
- # compliance) that must precede any brief authoring work.
13
+ # Steps SKILL.md On Activation step 3 runs once this file resolves: after
14
+ # config.yaml is loaded and {headless_mode} and {auto_mode} are resolved, so
15
+ # config values such as {forge_data_folder} and {sidecar_path} are available,
16
+ # and before any stage loads. Overrides append. Use for org-wide pre-flight
17
+ # checks (auth, network, compliance) that must precede any brief authoring
18
+ # work.
16
19
 
17
20
  activation_steps_prepend = []
18
21
 
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.
22
+ # Steps to run once activation completes (the envelope emitter resolved),
23
+ # just before step 1 (references/gather-intent.md) loads. Overrides append.
24
+ # Use for context loads or banner customization.
22
25
 
23
26
  activation_steps_append = []
24
27
 
@@ -26,11 +29,18 @@ activation_steps_append = []
26
29
  # (house style, naming conventions, description-voice guardrails).
27
30
  # Overrides append.
28
31
  #
29
- # Each entry is either:
32
+ # Each entry is one of:
30
33
  # - a literal sentence, e.g. "Skill briefs must cite an authoritative source."
31
34
  # - a file reference prefixed with `file:`, e.g.
32
35
  # "file:{project-root}/docs/brief-style.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-brief-skill.toml:
43
+ # persistent_facts = ["!file:{project-root}/**/project-context.md"]
34
44
 
35
45
  persistent_facts = [
36
46
  "file:{project-root}/**/project-context.md",
@@ -38,21 +48,39 @@ persistent_facts = [
38
48
 
39
49
  # --- Optional asset overrides ---
40
50
  #
41
- # Lift the canonical asset paths so orgs can substitute house-style copies
42
- # without forking the skill. Empty string = use the bundled default.
51
+ # Each names the file a stage loads, as a path from the skill root. To use an
52
+ # org copy, point at it with a {project-root}/... path. An empty string means
53
+ # the default named below.
54
+
55
+ # The five voice examples step 1 shows a first-time user and composes the
56
+ # skill description from. A copy keeps five examples, each leading a
57
+ # different way, and the "do not template-stamp" guidance; whatever it says,
58
+ # step 1 still requires a literal `Use when` clause in every description.
59
+
60
+ description_voice_examples_path = "assets/description-voice-examples.md"
61
+
62
+ # The scope types step 3 offers and the boundary flow of each. A copy keeps
63
+ # the five letter-keyed types ([F] full-library, [M] specific-modules,
64
+ # [P] public-api, [C] component-library, [R] reference-app), a boundary
65
+ # section for each and the Docs-Only boundaries: step 3 maps the letters to
66
+ # the scope types the brief writer accepts. Headless boundary defaults are
67
+ # not read from it: step 3 states them.
43
68
 
44
- description_voice_examples_path = ""
45
- scope_templates_path = ""
46
- brief_schema_path = ""
69
+ scope_templates_path = "assets/scope-templates.md"
47
70
 
48
- # Pipeline-integration hook invoked once the brief is written and the result
49
- # contract is finalized (write-brief.md, step 5), before the workflow chains to
50
- # the terminal health-check step. The command is called as:
71
+ # Pipeline-integration hook: a shell command, not an instruction, invoked
72
+ # once the brief is written (and, in a headless or [auto] run, the result
73
+ # envelope is built), before the workflow chains to the terminal
74
+ # health-check step. Every successful run calls it once: write-brief.md §6b
75
+ # on the interactive, headless and ratify paths, and step-auto-validate.md §3
76
+ # on the [auto] path, right after its envelope. The command is called as:
51
77
  # <on_complete> --result-path=<absolute_path_to_skill-brief.yaml>
52
78
  # Useful for chaining into create-skill, Slack notifications, dashboard ingest,
53
- # or CI hooks. Override wins. Failures are logged to workflow_warnings[] but
54
- # never fail the workflow.
79
+ # or CI hooks. Override wins. A failure never fails the workflow: the run
80
+ # displays one line, "on_complete hook failed (exit <code>): <stderr>", which
81
+ # the result envelope, built before the hook runs and displayed last by the
82
+ # health check, does not carry.
55
83
  #
56
- # Empty string = no-op (default).
84
+ # Empty string = no hook (default).
57
85
 
58
86
  on_complete = ""