bmad-module-skill-forge 2.2.0 → 4.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 (437) 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 +143 -18
  18. package/docs/verifying-a-skill.md +87 -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 +3 -3
  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 +31 -59
  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 +233 -64
  64. package/src/shared/scripts/skf-build-change-manifest.py +2753 -28
  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 +772 -0
  69. package/src/shared/scripts/skf-comention-pairs.py +1333 -123
  70. package/src/shared/scripts/skf-compare-file-hashes.py +267 -105
  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 +21 -3
  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 +197 -55
  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 +5247 -96
  86. package/src/shared/scripts/skf-extraction-inventory.py +1280 -0
  87. package/src/shared/scripts/skf-extraction-snapshot.py +664 -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 +469 -205
  92. package/src/shared/scripts/skf-github-fetch.py +365 -0
  93. package/src/shared/scripts/skf-github-probe.py +700 -0
  94. package/src/shared/scripts/skf-hash-content.py +180 -20
  95. package/src/shared/scripts/skf-language-corpora.py +1 -1
  96. package/src/shared/scripts/skf-load-provenance.py +161 -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 +143 -20
  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 +176 -28
  105. package/src/shared/scripts/skf-promote-staged.py +430 -0
  106. package/src/shared/scripts/skf-provenance-gap-dispatch.py +64 -8
  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 +155 -14
  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 +787 -121
  127. package/src/shared/scripts/skf-tessl-review.py +706 -0
  128. package/src/shared/scripts/skf-update-active-symlink.py +120 -67
  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 +23 -2
  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 +3945 -152
  138. package/src/shared/scripts/skf-write-skill-brief.py +406 -25
  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 +28 -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/health-check.md +2 -0
  168. package/src/skf-audit-skill/references/init.md +149 -210
  169. package/src/skf-audit-skill/references/re-index.md +103 -110
  170. package/src/skf-audit-skill/references/report.md +96 -33
  171. package/src/skf-audit-skill/references/semantic-diff.md +34 -25
  172. package/src/skf-audit-skill/references/severity-classify.md +79 -65
  173. package/src/skf-audit-skill/references/severity-rules.md +15 -6
  174. package/src/skf-audit-skill/references/structural-diff.md +80 -90
  175. package/src/skf-audit-skill/references/upstream-checkout.md +77 -0
  176. package/src/skf-audit-skill/scripts/render-drift-tables.py +712 -0
  177. package/src/skf-brief-skill/SKILL.md +37 -26
  178. package/src/skf-brief-skill/assets/description-voice-examples.md +1 -1
  179. package/src/skf-brief-skill/assets/scope-templates.md +18 -25
  180. package/src/skf-brief-skill/assets/skill-brief-schema.md +30 -23
  181. package/src/skf-brief-skill/customize.toml +48 -20
  182. package/src/skf-brief-skill/references/analyze-target.md +144 -127
  183. package/src/skf-brief-skill/references/confirm-brief.md +11 -9
  184. package/src/skf-brief-skill/references/draft-checkpoint.md +36 -17
  185. package/src/skf-brief-skill/references/gather-intent-ratify.md +68 -0
  186. package/src/skf-brief-skill/references/gather-intent.md +87 -182
  187. package/src/skf-brief-skill/references/headless-args.md +84 -16
  188. package/src/skf-brief-skill/references/health-check.md +1 -1
  189. package/src/skf-brief-skill/references/invocation-contract.md +18 -13
  190. package/src/skf-brief-skill/references/portfolio-similarity-check.md +1 -1
  191. package/src/skf-brief-skill/references/qmd-collection-registration.md +7 -10
  192. package/src/skf-brief-skill/references/scope-definition.md +123 -47
  193. package/src/skf-brief-skill/references/step-auto-brief.md +26 -100
  194. package/src/skf-brief-skill/references/step-auto-validate.md +20 -121
  195. package/src/skf-brief-skill/references/version-resolution.md +7 -10
  196. package/src/skf-brief-skill/references/write-brief.md +66 -57
  197. package/src/skf-campaign/SKILL.md +31 -34
  198. package/src/skf-campaign/assets/campaign-state-schema.json +25 -4
  199. package/src/skf-campaign/customize.toml +47 -16
  200. package/src/skf-campaign/references/campaign-contracts.md +39 -29
  201. package/src/skf-campaign/references/campaign-directive-spec.md +4 -2
  202. package/src/skf-campaign/references/health-check.md +7 -16
  203. package/src/skf-campaign/references/step-01-setup.md +46 -84
  204. package/src/skf-campaign/references/step-02-strategy.md +31 -30
  205. package/src/skf-campaign/references/step-03-pins.md +26 -18
  206. package/src/skf-campaign/references/step-04-provenance.md +24 -23
  207. package/src/skf-campaign/references/step-05-skill-loop.md +67 -48
  208. package/src/skf-campaign/references/step-06-batch.md +41 -34
  209. package/src/skf-campaign/references/step-07-capstone.md +40 -25
  210. package/src/skf-campaign/references/step-08-verify.md +28 -29
  211. package/src/skf-campaign/references/step-09-refine.md +29 -30
  212. package/src/skf-campaign/references/step-10-export.md +48 -36
  213. package/src/skf-campaign/references/step-11-maintenance.md +31 -34
  214. package/src/skf-campaign/references/step-resume.md +37 -68
  215. package/src/skf-campaign/scripts/campaign-deps.py +57 -18
  216. package/src/skf-campaign/scripts/campaign-parse-manifest.py +361 -54
  217. package/src/skf-campaign/scripts/campaign-provenance.py +96 -53
  218. package/src/skf-campaign/scripts/campaign-quality-gate.py +592 -0
  219. package/src/skf-campaign/scripts/campaign-render-batch.py +257 -49
  220. package/src/skf-campaign/scripts/campaign-render-kickoff.py +343 -50
  221. package/src/skf-campaign/scripts/campaign-report.py +204 -37
  222. package/src/skf-campaign/scripts/campaign-state.py +1128 -0
  223. package/src/skf-campaign/scripts/campaign-status.py +10 -74
  224. package/src/skf-campaign/scripts/campaign-validate-pins.py +30 -3
  225. package/src/skf-campaign/scripts/campaign-validate-state.py +34 -4
  226. package/src/skf-campaign/templates/campaign-brief-template.yaml +4 -5
  227. package/src/skf-campaign/templates/campaign-report-template.md +5 -1
  228. package/src/skf-campaign/templates/kickoff-template.md +0 -14
  229. package/src/skf-create-skill/SKILL.md +27 -20
  230. package/src/skf-create-skill/assets/compile-assembly-rules.md +11 -8
  231. package/src/skf-create-skill/assets/skill-sections.md +21 -11
  232. package/src/skf-create-skill/customize.toml +20 -8
  233. package/src/skf-create-skill/references/authoritative-files-protocol.md +36 -58
  234. package/src/skf-create-skill/references/batch-mode.md +81 -0
  235. package/src/skf-create-skill/references/ccc-index-check.md +27 -0
  236. package/src/skf-create-skill/references/compile.md +119 -70
  237. package/src/skf-create-skill/references/component-extraction.md +113 -91
  238. package/src/skf-create-skill/references/enrich.md +41 -23
  239. package/src/skf-create-skill/references/entry-points-by-hand.md +37 -0
  240. package/src/skf-create-skill/references/extract.md +204 -162
  241. package/src/skf-create-skill/references/extraction-patterns-by-hand.md +141 -0
  242. package/src/skf-create-skill/references/extraction-patterns-tracing.md +11 -11
  243. package/src/skf-create-skill/references/extraction-patterns.md +588 -201
  244. package/src/skf-create-skill/references/generate-artifacts.md +145 -93
  245. package/src/skf-create-skill/references/health-check.md +1 -1
  246. package/src/skf-create-skill/references/load-brief.md +53 -36
  247. package/src/skf-create-skill/references/relabel-rule.md +12 -0
  248. package/src/skf-create-skill/references/report.md +37 -57
  249. package/src/skf-create-skill/references/source-resolution-protocols.md +58 -169
  250. package/src/skf-create-skill/references/step-auto-shard.md +20 -93
  251. package/src/skf-create-skill/references/step-doc-rot.md +44 -60
  252. package/src/skf-create-skill/references/step-doc-sources.md +28 -19
  253. package/src/skf-create-skill/references/sub/ccc-discover.md +18 -7
  254. package/src/skf-create-skill/references/sub/fetch-docs.md +106 -59
  255. package/src/skf-create-skill/references/sub/fetch-temporal.md +53 -166
  256. package/src/skf-create-skill/references/tier-degradation-rules.md +18 -9
  257. package/src/skf-create-skill/references/validate.md +173 -99
  258. package/src/skf-create-skill/scripts/scan-doc-rot.py +232 -99
  259. package/src/skf-create-stack-skill/SKILL.md +29 -56
  260. package/src/skf-create-stack-skill/assets/metadata-contract.md +51 -0
  261. package/src/skf-create-stack-skill/assets/provenance-map-schema.md +15 -15
  262. package/src/skf-create-stack-skill/assets/stack-skill-template.md +23 -57
  263. package/src/skf-create-stack-skill/customize.toml +23 -12
  264. package/src/skf-create-stack-skill/references/compile-stack.md +57 -66
  265. package/src/skf-create-stack-skill/references/compose-mode-rules.md +24 -44
  266. package/src/skf-create-stack-skill/references/detect-integrations.md +92 -95
  267. package/src/skf-create-stack-skill/references/detect-manifests.md +46 -71
  268. package/src/skf-create-stack-skill/references/generate-output.md +138 -128
  269. package/src/skf-create-stack-skill/references/init.md +90 -32
  270. package/src/skf-create-stack-skill/references/integration-patterns.md +1 -17
  271. package/src/skf-create-stack-skill/references/invocation-contract.md +34 -0
  272. package/src/skf-create-stack-skill/references/manifest-patterns.md +32 -20
  273. package/src/skf-create-stack-skill/references/parallel-extract.md +112 -38
  274. package/src/skf-create-stack-skill/references/rank-and-confirm.md +57 -75
  275. package/src/skf-create-stack-skill/references/report.md +39 -33
  276. package/src/skf-create-stack-skill/references/validate.md +20 -39
  277. package/src/skf-drop-skill/SKILL.md +28 -51
  278. package/src/skf-drop-skill/customize.toml +44 -30
  279. package/src/skf-drop-skill/references/execute.md +83 -146
  280. package/src/skf-drop-skill/references/health-check.md +2 -0
  281. package/src/skf-drop-skill/references/invocation-contract.md +64 -0
  282. package/src/skf-drop-skill/references/report.md +46 -30
  283. package/src/skf-drop-skill/references/select.md +122 -124
  284. package/src/skf-drop-skill/scripts/dir-sizes.py +54 -26
  285. package/src/skf-drop-skill/scripts/drop-roster.py +322 -0
  286. package/src/skf-export-skill/SKILL.md +40 -62
  287. package/src/skf-export-skill/assets/managed-section-format.md +14 -50
  288. package/src/skf-export-skill/assets/snippet-format.md +3 -1
  289. package/src/skf-export-skill/customize.toml +42 -13
  290. package/src/skf-export-skill/references/generate-snippet.md +54 -46
  291. package/src/skf-export-skill/references/health-check.md +2 -0
  292. package/src/skf-export-skill/references/invocation-contract.md +15 -0
  293. package/src/skf-export-skill/references/load-skill.md +88 -62
  294. package/src/skf-export-skill/references/manifest-rebuild.md +9 -10
  295. package/src/skf-export-skill/references/multi-skill-mode.md +4 -4
  296. package/src/skf-export-skill/references/orphan-context-detection.md +13 -5
  297. package/src/skf-export-skill/references/orphan-row-detection.md +31 -22
  298. package/src/skf-export-skill/references/package.md +15 -73
  299. package/src/skf-export-skill/references/preflight-snippet-root-probe.md +51 -70
  300. package/src/skf-export-skill/references/result-envelope.md +31 -16
  301. package/src/skf-export-skill/references/summary.md +41 -17
  302. package/src/skf-export-skill/references/token-report.md +4 -12
  303. package/src/skf-export-skill/references/update-context.md +118 -237
  304. package/src/skf-forger/SKILL.md +61 -37
  305. package/src/skf-forger/bmad-skill-manifest.yaml +4 -1
  306. package/src/skf-forger/customize.toml +43 -0
  307. package/src/skf-forger/references/pipeline-mode.md +73 -18
  308. package/src/skf-forger/scripts/forge-status.py +299 -0
  309. package/src/skf-forger/scripts/parse-pipeline.py +322 -54
  310. package/src/skf-forger/scripts/pipeline-gate.py +428 -0
  311. package/src/skf-forger/scripts/pipeline-journal.py +1052 -0
  312. package/src/skf-quick-skill/SKILL.md +54 -53
  313. package/src/skf-quick-skill/assets/skill-template.md +4 -2
  314. package/src/skf-quick-skill/customize.toml +51 -20
  315. package/src/skf-quick-skill/references/batch-mode.md +74 -21
  316. package/src/skf-quick-skill/references/compile.md +30 -31
  317. package/src/skf-quick-skill/references/ecosystem-check.md +7 -57
  318. package/src/skf-quick-skill/references/finalize.md +69 -18
  319. package/src/skf-quick-skill/references/halt-contract.md +41 -29
  320. package/src/skf-quick-skill/references/health-check.md +5 -3
  321. package/src/skf-quick-skill/references/quick-extract.md +114 -45
  322. package/src/skf-quick-skill/references/registry-resolution.md +9 -64
  323. package/src/skf-quick-skill/references/resolve-target.md +116 -66
  324. package/src/skf-quick-skill/references/write-and-validate.md +79 -40
  325. package/src/skf-refine-architecture/SKILL.md +43 -53
  326. package/src/skf-refine-architecture/customize.toml +49 -20
  327. package/src/skf-refine-architecture/references/compile.md +97 -54
  328. package/src/skf-refine-architecture/references/exit-codes.md +30 -0
  329. package/src/skf-refine-architecture/references/finding-storage.md +21 -0
  330. package/src/skf-refine-architecture/references/gap-analysis.md +101 -38
  331. package/src/skf-refine-architecture/references/improvements.md +14 -20
  332. package/src/skf-refine-architecture/references/init.md +98 -57
  333. package/src/skf-refine-architecture/references/issue-detection.md +32 -39
  334. package/src/skf-refine-architecture/references/refinement-rules.md +37 -48
  335. package/src/skf-refine-architecture/references/report.md +65 -54
  336. package/src/skf-refine-architecture/scripts/skf-check-preservation.py +1619 -0
  337. package/src/skf-rename-skill/SKILL.md +19 -54
  338. package/src/skf-rename-skill/customize.toml +32 -26
  339. package/src/skf-rename-skill/references/execute.md +230 -184
  340. package/src/skf-rename-skill/references/exit-codes.md +7 -7
  341. package/src/skf-rename-skill/references/health-check.md +1 -7
  342. package/src/skf-rename-skill/references/invocation-contract.md +25 -0
  343. package/src/skf-rename-skill/references/report.md +63 -52
  344. package/src/skf-rename-skill/references/select.md +197 -115
  345. package/src/skf-rename-skill/scripts/skf-validate-rename-name.py +161 -21
  346. package/src/skf-setup/SKILL.md +26 -26
  347. package/src/skf-setup/customize.toml +14 -10
  348. package/src/skf-setup/references/auto-index.md +50 -63
  349. package/src/skf-setup/references/ccc-index.md +29 -90
  350. package/src/skf-setup/references/detect-and-tier.md +58 -67
  351. package/src/skf-setup/references/health-check.md +2 -0
  352. package/src/skf-setup/references/invocation-contract.md +14 -0
  353. package/src/skf-setup/references/report.md +43 -166
  354. package/src/skf-setup/references/tier-rules.md +5 -5
  355. package/src/skf-setup/references/write-config.md +34 -57
  356. package/src/skf-test-skill/SKILL.md +17 -57
  357. package/src/skf-test-skill/assets/output-section-formats.md +33 -34
  358. package/src/skf-test-skill/customize.toml +27 -13
  359. package/src/skf-test-skill/references/coherence-check.md +134 -62
  360. package/src/skf-test-skill/references/coverage-check-tiers.md +35 -0
  361. package/src/skf-test-skill/references/coverage-check.md +209 -264
  362. package/src/skf-test-skill/references/detect-mode.md +5 -5
  363. package/src/skf-test-skill/references/external-validators.md +94 -82
  364. package/src/skf-test-skill/references/health-check.md +6 -7
  365. package/src/skf-test-skill/references/init.md +164 -91
  366. package/src/skf-test-skill/references/invocation-contract.md +66 -0
  367. package/src/skf-test-skill/references/migration-section-rules.md +5 -2
  368. package/src/skf-test-skill/references/report.md +164 -142
  369. package/src/skf-test-skill/references/score.md +80 -107
  370. package/src/skf-test-skill/references/scoring-rules.md +42 -155
  371. package/src/skf-test-skill/references/source-access-protocol.md +18 -94
  372. package/src/skf-test-skill/references/step-hard-gate.md +51 -33
  373. package/src/skf-test-skill/scripts/aggregate-coherence.py +218 -30
  374. package/src/skf-test-skill/scripts/build-result-context.py +380 -0
  375. package/src/skf-test-skill/scripts/check-metadata-coherence.py +37 -4
  376. package/src/skf-test-skill/scripts/combine-external-scores.py +23 -6
  377. package/src/skf-test-skill/scripts/compute-score.py +223 -45
  378. package/src/skf-test-skill/scripts/gap-ledger.py +1666 -0
  379. package/src/skf-test-skill/scripts/hard-gate.py +203 -0
  380. package/src/skf-test-skill/scripts/load-coverage-inputs.py +1198 -0
  381. package/src/skf-test-skill/scripts/locate-export-segments.py +835 -0
  382. package/src/skf-test-skill/scripts/reconcile-coverage.py +547 -79
  383. package/src/skf-test-skill/scripts/score-signatures.py +479 -0
  384. package/src/skf-test-skill/scripts/stage-helper-payload.py +148 -0
  385. package/src/skf-test-skill/scripts/validate-inventory.py +311 -16
  386. package/src/skf-test-skill/scripts/verify-declared-numerator.py +133 -56
  387. package/src/skf-test-skill/templates/test-report-template.md +21 -15
  388. package/src/skf-update-skill/SKILL.md +38 -25
  389. package/src/skf-update-skill/customize.toml +27 -12
  390. package/src/skf-update-skill/references/detect-changes.md +253 -223
  391. package/src/skf-update-skill/references/gap-driven.md +336 -0
  392. package/src/skf-update-skill/references/health-check.md +31 -5
  393. package/src/skf-update-skill/references/init.md +254 -84
  394. package/src/skf-update-skill/references/invocation-contract.md +12 -0
  395. package/src/skf-update-skill/references/manual-section-rules.md +6 -23
  396. package/src/skf-update-skill/references/merge.md +182 -49
  397. package/src/skf-update-skill/references/re-extract.md +53 -262
  398. package/src/skf-update-skill/references/report.md +102 -35
  399. package/src/skf-update-skill/references/write.md +357 -155
  400. package/src/skf-update-skill/scripts/skf-new-file-diff.py +183 -46
  401. package/src/skf-verify-stack/SKILL.md +23 -42
  402. package/src/skf-verify-stack/assets/feasibility-report-template.md +11 -5
  403. package/src/skf-verify-stack/customize.toml +55 -22
  404. package/src/skf-verify-stack/references/coverage-patterns.md +17 -8
  405. package/src/skf-verify-stack/references/coverage.md +67 -64
  406. package/src/skf-verify-stack/references/exit-codes.md +21 -8
  407. package/src/skf-verify-stack/references/init.md +107 -62
  408. package/src/skf-verify-stack/references/integration-verification-rules.md +12 -13
  409. package/src/skf-verify-stack/references/integrations.md +106 -65
  410. package/src/skf-verify-stack/references/report.md +59 -42
  411. package/src/skf-verify-stack/references/requirements.md +32 -9
  412. package/src/skf-verify-stack/references/synthesize.md +53 -39
  413. package/src/skf-verify-stack/scripts/skf-coverage-tally.py +398 -52
  414. package/src/skf-verify-stack/scripts/skf-previous-report.py +330 -0
  415. package/src/skf-verify-stack/scripts/skf-report-delta.py +453 -49
  416. package/src/skf-verify-stack/scripts/skf-verdict-rollup.py +240 -27
  417. package/tools/cli/commands/install.js +11 -4
  418. package/tools/cli/commands/status.js +15 -3
  419. package/tools/cli/commands/update.js +11 -4
  420. package/tools/cli/lib/tool-check.js +320 -0
  421. package/tools/cli/lib/version-check.js +22 -9
  422. package/tools/cli/skf-cli.js +4 -1
  423. package/.gitattributes +0 -16
  424. package/.nvmrc +0 -1
  425. package/docs/_internal/RELEASING.md +0 -679
  426. package/release-audits/v1.0.0-launch-audit.md +0 -728
  427. package/src/skf-audit-skill/references/step-doc-drift.md +0 -177
  428. package/src/skf-brief-skill/references/headless-source-authority-detection.md +0 -26
  429. package/src/skf-campaign/manifest.yaml +0 -15
  430. package/src/skf-create-skill/assets/tessl-dismissal-rules.md +0 -106
  431. package/src/skf-create-skill/references/ecosystem-check.md +0 -74
  432. package/src/skf-drop-skill/references/headless-contract.md +0 -18
  433. package/src/skf-update-skill/references/merge-conflict-rules.md +0 -15
  434. package/src/skf-update-skill/references/remote-source-resolution.md +0 -98
  435. package/src/skf-update-skill/references/validate.md +0 -124
  436. package/tools/validate-docs-drift.js +0 -233
  437. package/tools/validate-docs-links.js +0 -665
package/docs/workflows.md CHANGED
@@ -5,6 +5,8 @@ description: All 15 SKF workflows with commands, steps, and connection diagram
5
5
 
6
6
  Trigger workflows by typing commands to [Ferris](/docs/agents.md). See [Concepts](/docs/concepts.md) for definitions.
7
7
 
8
+ Each workflow is also a skill you can run directly, without Ferris: `/skf-setup` (SF), `/skf-brief-skill` (BS), `/skf-create-skill` (CS), `/skf-update-skill` (US), `/skf-quick-skill` (QS), `/skf-create-stack-skill` (SS), `/skf-analyze-source` (AN), `/skf-audit-skill` (AS), `/skf-test-skill` (TS), `/skf-verify-stack` (VS), `/skf-refine-architecture` (RA), `/skf-export-skill` (EX), `/skf-rename-skill` (RS), `/skf-drop-skill` (DS) and `/skf-campaign` (campaign).
9
+
8
10
  > Already using BMAD? See [BMAD Synergy](/docs/bmad-synergy.md) for when to invoke each SKF workflow during BMM phases and alongside TEA, BMB, and GDS.
9
11
 
10
12
  ---
@@ -15,19 +17,19 @@ Trigger workflows by typing commands to [Ferris](/docs/agents.md). See [Concepts
15
17
 
16
18
  **Command:** `@Ferris SF`
17
19
 
18
- **Purpose:** Initialize forge environment, detect tools (ast-grep, ccc, gh, qmd), set capability tier, index project in CCC (Forge+), verify QMD collection health (Deep).
20
+ **Purpose:** Initialize the forge environment: detect tools (ast-grep, ccc, gh, qmd), set the capability tier, index the project in CCC when ccc is installed, and check QMD collection health (Deep). The tier follows the tools you have: Quick needs none, Forge needs ast-grep, Forge+ needs ast-grep and ccc, and Deep needs ast-grep, gh and qmd. Each of these tools counts only at its minimum version or newer (the minimums are in [`src/shared/tool-requirements.yaml`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/shared/tool-requirements.yaml)), so an ast-grep older than 0.45.3 leaves you at Quick. A tool below its minimum gets an upgrade line in FORGE STATUS and a `tool_below_minimum` warning in `SKF_SETUP_RESULT_JSON`.
19
21
 
20
- **When to Use:** First time using SKF in a project. Run once per project.
22
+ **When to Use:** First time using SKF in a project. Run it again after you install, upgrade or remove one of these tools, so SKF picks up the new tier.
21
23
 
22
- **Key Steps:** Detect tools + Determine tier → CCC index check (Forge+) → Write forge-tier.yaml → QMD + CCC registry hygiene (Deep/Forge+) → Status report
24
+ **Key Steps:** Detect tools + Determine tier → CCC index check (when ccc is installed) → Write forge-tier.yaml → QMD + CCC registry hygiene (QMD at Deep, CCC whenever ccc is installed) → Status report
23
25
 
24
26
  **Flags:**
25
27
 
26
- - `--require-tier=<Quick|Forge|Forge+|Deep>` — fail-fast for CI: if the calculated tier does not satisfy the requested tier (tool-prerequisite check, not a name comparison — Deep does NOT subsume Forge+ because Deep does not require ccc), the workflow halts with a "REQUIRED TIER NOT MET" block and exits without chaining to the health check. Pipelines branch on the JSON envelope's `require_tier_satisfied` field.
27
- - `--orphan-action=<keep|remove>` — resolve the orphan QMD-collection removal gate non-interactively, even outside `--headless`.
28
- - `--ccc-skip-index` — skip CCC indexing (envelope `ccc_index.status` becomes `"skipped"`) — the fast re-probe lane to refresh the detected tier without paying the full re-index cost.
29
- - `--quiet` — suppress the human-readable FORGE STATUS banner and emit the envelope only.
30
- - `--headless` / `-H` — see [Headless Mode](#headless-mode) below. For `/skf-setup` specifically, headless mode emits a single-line `SKF_SETUP_RESULT_JSON: {…}` envelope to stdout (schema-locked, includes `status` — the primary branch field — plus `tier`, `previous_tier`, `tier_changed`, `tools`, `tools_added`/`removed`, `files_written`, `warnings`, `error`) and SUPPRESSES the human-readable banner — the entire payload pipelines need is on one parseable line.
28
+ - `--require-tier=<Quick|Forge|Forge+|Deep>` (or `--require-tier <tier>`): stop early in CI when the detected tier is not enough. The value must be one of the four tier names exactly, capitals included. Any other value, such as `deep`, is no miss: setup halts before it probes a tool, with a reason that names the valid tiers (and suggests `Deep` for `deep`), and a `--headless` or `--quiet` run ends `blocked` with `error.phase` `step 1:detect-tools`. SKF checks the tools the requested tier needs, not the tier names, so Deep does not count as Forge+ (Deep does not need ccc). On a miss the workflow halts without running the health check. A miss also skips a due ccc index build (the envelope's `ccc_index.status` is `"skipped"`) and the registry cleanup, so it removes no QMD collection, even under `--orphan-action=remove`. Interactive runs show a "REQUIRED TIER NOT MET" block; `--headless` and `--quiet` runs show only the envelope, with `status: "tier_failure"`. Pipelines branch on the envelope's `status` field, which is `tier_failure` for a miss.
29
+ - `--orphan-action=<keep|remove>`: answer the question about removing orphaned QMD collections without a prompt, even outside `--headless`. Without it, `--headless` and `--quiet` keep the orphaned collections. Any other value halts the run before setup does anything (`error.phase` `on-activation:orphan-action-invalid`).
30
+ - `--ccc-skip-index`: skip building the CCC index (the envelope's `ccc_index.status` becomes `"skipped"`). SKF still prepares the ccc settings and keeps its exclusions current. Use it to refresh the detected tier quickly without paying for a full re-index.
31
+ - `--quiet`: an alias of `--headless`, for pipelines and expert re-runs, and a forger pipeline runs setup the same way. The `SKF_SETUP_RESULT_JSON` envelope replaces the FORGE STATUS banner and the health-check output, and the orphan question keeps orphaned collections instead of asking (recorded as `quiet-default` in the envelope's `warnings`).
32
+ - `--headless` / `-H`: see [Headless Mode](#headless-mode) below. For `/skf-setup`, headless mode prints a single-line `SKF_SETUP_RESULT_JSON: {…}` envelope to stdout in place of the status banner and the health-check output. The envelope follows a fixed schema: `status` is the field to branch on, and it also carries `tier`, `previous_tier`, `tier_changed`, `tools`, `tools_added`/`removed`, `files_written`, `warnings` and `error`. Everything a pipeline needs is on that one line, and it is the run's final message, so it is all `claude -p` prints.
31
33
 
32
34
  **Agent:** Ferris (Architect mode)
33
35
 
@@ -43,6 +45,18 @@ Trigger workflows by typing commands to [Ferris](/docs/agents.md). See [Concepts
43
45
 
44
46
  **Key Steps:** Gather intent → Analyze target → Define scope → Confirm brief → Write skill-brief.yaml
45
47
 
48
+ **Target:** The interactive target prompt takes a GitHub URL or a local path, and also a package name or its registry page (`zod`, `requests==2.31.0`, or an npmjs.com, pypi.org or crates.io URL). Brief Skill resolves a package to the GitHub repository it is published from, lists every candidate when the name may belong to more than one project, and pre-fills `target_version` from a pinned version such as `==2.31.0`. A partial pin such as `react@18` is not kept: Brief Skill names it and asks for the full version, or a blank answer to auto-detect it. A headless run, such as the one the `forge` pipeline starts, still needs a URL or a path.
49
+
50
+ **The brief file.** Brief Skill writes `forge-data/<name>/skill-brief.yaml`. You can edit it before Create Skill runs. The fields you are most likely to change:
51
+
52
+ - `name`: the skill's folder name, in kebab-case.
53
+ - `source_repo`: a GitHub URL or local path. Set `source_type: docs-only` and list `doc_urls` to build from documentation instead.
54
+ - `target_version` pins a version. `target_ref` names the exact tag or branch when the tags do not match the version.
55
+ - `scope.type` (`full-library`, `specific-modules`, `public-api`, `component-library`, `reference-app` or `docs-only`), with `scope.include` and `scope.exclude` globs.
56
+ - `description`: one to three sentences that must contain the words `Use when`.
57
+ - `source_authority`: `community` by default. Set `official` only if you maintain the library, or `internal` for your team's own code.
58
+ - `scripts_intent` and `assets_intent`: `detect` (the default), `none`, or a short description of what you expect.
59
+
46
60
  **Agent:** Ferris (Architect mode)
47
61
 
48
62
  ---
@@ -55,7 +69,13 @@ Trigger workflows by typing commands to [Ferris](/docs/agents.md). See [Concepts
55
69
 
56
70
  **When to Use:** After Brief Skill, or with an existing skill-brief.yaml.
57
71
 
58
- **Key Steps:** Load brief → Ecosystem check → Extract (AST + scripts/assets) → QMD enrich (Deep) → Compile → Doc sources → Auto-shard → Doc-rot → Validate → Generate
72
+ **Key Steps:** Load brief → Extract (AST + scripts/assets) → QMD enrich (Deep) → Compile → Doc sources → Auto-shard → Doc-rot → Validate (skill-check; Tessl Review when you opt in) → Generate
73
+
74
+ **Which brief:** Name the brief by its path or by the skill's name. With no brief path, skill name or `--batch`, CS loads the only brief in `forge_data_folder` and names it in its opening banner. When the folder holds several, an interactive run asks which one to compile, and a headless run stops with exit `2` (`brief-missing`), naming them.
75
+
76
+ **Batch mode:** The paths after `--batch` name `skill-brief.yaml` files or folders of briefs; with no path, CS takes the briefs in `forge_data_folder`. Every brief is validated before the first one compiles, and the plan lists the briefs to compile and each refused brief: one that fails the brief schema, with the validator's first message, or one whose `name` an earlier brief of the batch already has. A HARD HALT ends only its own brief. The batch writes `create-skill-batch-<timestamp>.json` and `create-skill-batch-latest.json` under `<skills_output_folder>/_batch/` and exits with the highest exit code among its briefs, `0` when every brief finished. Run again with the same briefs, a batch that an ended session left goes on where it stopped.
77
+
78
+ **Safety:** Writes a version only into a skill folder SKF generated, or a new one. When `skills_output_folder` already holds a folder with the skill's name that SKF did not generate, or a version folder SKF did not generate, it stops before writing anything (`not-skf-output`); an SKF skill still in the old flat layout stops with `flat-layout` until `@Ferris TS` moves it. Set a different `name` in the brief to create the skill beside a folder SKF did not generate.
59
79
 
60
80
  **Agent:** Ferris (Architect mode)
61
81
 
@@ -65,11 +85,21 @@ Trigger workflows by typing commands to [Ferris](/docs/agents.md). See [Concepts
65
85
 
66
86
  **Command:** `@Ferris US`
67
87
 
68
- **Purpose:** Regenerates the skill while preserving `[MANUAL]` sections. Detects individual vs stack internally.
88
+ **Purpose:** Regenerates the skill while preserving `[MANUAL]` sections.
69
89
 
70
90
  **When to Use:** After source code changes when an existing skill needs updating.
71
91
 
72
- **Key Steps:** Load existing → Detect changes (incl. scripts/assets) → Re-extract → Merge (preserve MANUAL) → Validate → Write → Report
92
+ **Key Steps:** Load existing → Fetch the source at the skill's ref → Detect changes (incl. scripts/assets) → Re-extract → Merge (preserve MANUAL) → Write and validate (records the commit it read) → Report
93
+
94
+ **Source:** For a skill built from a remote repository, Update Skill reads the commit the skill's `source_ref` (a tag, a branch or the default branch) points to now, in a checkout of its own, and records that commit as the skill's `source_commit` when it writes. Pass `--target-ref <tag|branch|HEAD|commit>` to move the skill to another ref, such as a newer release, or to one exact commit (give the full 40-character hash). `--detect-only` and `--dry-run` read the same way and write nothing. A skill built from a local folder is read as that folder stands, and a gap-driven run (`--from-test-report`) reads the commit the skill is pinned to.
95
+
96
+ **Versions:** An update that writes produces a new version of the skill, in a folder of its own beside the previous version, which stays unchanged. For a skill built from a remote repository, the new version is the source's version when that is higher; otherwise it is the next patch version. `active` then points at the new version, and the next update starts from it, exported or not. Update Skill stops rather than overwrite a version that already exists. A gap-driven run updates the current version in place.
97
+
98
+ **Modes:** By default, Update Skill compares the skill with its source and rebuilds what changed. To repair the gaps a failed test found, run `@Ferris US <name> --from-test-report`: it reads the newest test report and fixes the skill at its pinned commit. It routes each gap by its category, so a missing export, which Test Skill rates Medium, is still re-extracted from the files its remediation names. A default run first looks for an unconsumed test report: a failed or pass-with-drift report newer than the skill that no repair has applied. It then offers to repair that report's gaps (`[G]`) or to check the source for changes (`[S]`), and a headless run checks the source and adds an `unconsumed-test-report` warning. Stack skills are not updated here. Update Skill sends you to `@Ferris SS` to rebuild the stack.
99
+
100
+ **Preview:** `--detect-only` lists the changes and stops. `--dry-run` also re-extracts and shows what would change. Neither writes anything.
101
+
102
+ **Headless:** A headless run needs the skill's name or folder path as its argument: without one it stops `blocked` before it reads anything (`error.phase` `init:skill-name`, with an `error.reason` that starts `input-missing`). A skill with no `provenance-map.json`, such as one made by Quick Skill, needs a full rebuild. A headless run stops with `blocked` there unless you pass `--allow-degraded`. `--from-test-report` needs the map, interactive or headless: without one it stops `blocked` before any gate, so run a normal update first, which offers the rebuild and writes the map, then re-run Test Skill. Files outside the skill's scope that a headless run finds, such as a new AI documentation file, are left for a person: the run records each one as `deferred-headless` in the skill brief, and the next interactive run asks about it. A normal or gap-driven run that finds no change still writes its result files and runs `on_complete`, with the status `no-changes`. In the `SKF_UPDATE_RESULT_JSON` line, `skf_update.status` values `success`, `no-changes`, `detect-only` and `dry-run` all mean the run went fine.
73
103
 
74
104
  **Agent:** Ferris (Surgeon mode)
75
105
 
@@ -83,24 +113,36 @@ Trigger workflows by typing commands to [Ferris](/docs/agents.md). See [Concepts
83
113
 
84
114
  **Purpose:** Brief-less fast skill with package-to-repo resolution.
85
115
 
86
- **Note:** QS is **tier-unaware** — it always runs at community tier and does not use ast-grep, CCC, or QMD even when your forge is configured at Forge+/Deep. For tier-aware compilation, use `BS → CS`, `forge`, or `forge-auto`. See [Skill Model](/docs/skill-model.md).
116
+ **Note:** QS ignores your forge tier. Every Quick Skill is built the Quick-tier way (its `metadata.json` records `confidence_tier: "Quick"` and `source_authority: "community"`) and uses none of ast-grep, CCC or QMD, even when your forge is set to Forge+ or Deep. For a skill built at your forge tier, use `BS → CS`, `forge`, or `forge-auto`. See [Skill Model](/docs/skill-model.md).
117
+
118
+ **When to Use:** When you need a skill quickly, with no brief. Accepts package names, a package's npm, PyPI or crates.io page, or GitHub URLs. Append `@version` to target a specific version (for example `@Ferris QS cognee@1.0.0`).
119
+
120
+ **Package names:** QS looks a package name up on every registry of npm, PyPI and crates.io; a JavaScript, TypeScript, Python or Rust language hint asks only that language's registry. When more than one registry answers, an interactive run lists every candidate and asks which project to build, or takes another GitHub URL. A headless run keeps the first registry's pick (npm, then PyPI, then crates.io) and records an `also_found_in` warning in its result envelope. To build another candidate, pass its GitHub URL, its registry page URL or a language hint (`language=` on a batch line).
87
121
 
88
- **When to Use:** When you need a skill quickly — no brief needed. Accepts package names or GitHub URLs. Append `@version` to target a specific version (e.g., `@Ferris QS cognee@1.0.0`).
122
+ **Key Steps:** Resolve target → Ecosystem check (skipped until agentskills.io offers a registry API) → Quick extract → Compile → Write and validate → Finalize
89
123
 
90
- **Key Steps:** Resolve target → Ecosystem check → Quick extract → Compile → Validate → Write
124
+ **Skills modules:** Quick Skill also recognizes a repository that ships agent skills rather than code, such as a BMAD module or a plain Agent Skills package (`repo_shape: skills-module`). It reads each skill's `SKILL.md` frontmatter and the module's `module-help.csv` when there is one, lists the skill names and menu codes as the skill's Key Exports and in the `exports` of its `metadata.json`, and takes Usage Patterns from the `module-help.csv` rows. The skills come from the folder your scope hint names (`--scope-hint <path>`, or `scope=<path>` on a batch line). Without one, they come from the repository root or a top-level folder that holds `module.yaml` or `module-help.csv`, or from a folder of skill folders when the repository root has no package manifest, or one that publishes no code, so a library that ships an agent skill beside its code stays a library. When a run that stays a library finds no exports but the repository holds skill folders, its extraction note names the folder to re-run with as the scope hint. A repository of skills written in Markdown alone, with no code, is built as a skills module with the language `markdown`.
125
+
126
+ **Languages:** When SKF's language detector finds more than one language in the repository, an interactive run lists them, numbered, and offers `[C]` to keep the first, `[2]` to `[n]` to use that one, or `[A]` to abort (exit `3`). A headless run keeps the first and records the choice. A language hint (`--language-hint`, or `language=` on a batch line) sets the language and skips the question.
91
127
 
92
128
  **Headless / batch flags:**
93
129
 
94
- - `--headless` / `-H` — auto-proceed all confirmation gates with documented defaults; emits structured stderr progress events and exit codes (see [Headless Mode](#headless-mode))
95
- - `--batch <file>` — process N targets from a text file in sequence (one target per line, `#` comments and `language=<lang>` / `scope=<path>` per-line modifiers supported); implies `--headless`
96
- - `--fail-fast` — only with `--batch`; abort the whole batch on the first per-target failure instead of recording it and proceeding
130
+ - `--headless` / `-H`: auto-proceed through every confirmation gate with its documented default, print structured progress events to stderr, and exit with stable codes (see [Headless Mode](#headless-mode))
131
+ - `--batch <file>`: process several targets from a text file in sequence (one target per line; `#` comments and the per-line modifiers `language=<lang>` and `scope=<path>` are supported). Implies `--headless`.
132
+ - `--fail-fast`: only with `--batch`. Stop the whole batch at the first failed target instead of recording the failure and moving on.
133
+
134
+ **Per-target overrides** (`--skip-snippet` and `--no-active-pointer` also apply to every target in `--batch`):
97
135
 
98
- **Per-target overrides** (apply to a single-target run, or globally to every target in `--batch`):
136
+ - `--language-hint <lang>`: set the language, with no detection and no multi-language gate (a batch line's `language=` does the same). Single-target runs only.
137
+ - `--scope-hint <path>`: the folder to read the entry points or skill folders from (a batch line's `scope=` does the same). Single-target runs only.
138
+ - `--description "<string>"`: replace the LLM-derived description used in the `SKILL.md` frontmatter and `metadata.json`. Single-target runs only.
139
+ - `--exports "name1,name2,..."`: replace the extracted export list (comma-separated). Single-target runs only.
140
+ - `--skip-snippet`: skip writing `context-snippet.md`
141
+ - `--no-active-pointer`: leave the `active` pointer where it is at the end of the run (the files still land in `{skill_package}`)
99
142
 
100
- - `--description "<string>"` — override the LLM-derived description used in `SKILL.md` frontmatter and `metadata.json`
101
- - `--exports "name1,name2,..."` — override the extracted export list (comma-separated)
102
- - `--skip-snippet` — skip `context-snippet.md` generation and write
103
- - `--no-active-pointer` — skip the active-pointer flip in finalize (deliverables still land in `{skill_package}`)
143
+ `--description` and `--exports` do not combine with `--batch`, because one description or export list cannot fit every target: such a run stops before its first target with exit `2` (`input-invalid`) and writes no batch summary. To give a target its own description or export list, run it on its own. `--language-hint` and `--scope-hint` are refused with `--batch` too (exit `2`, `input-invalid`): put `language=` or `scope=` on the batch line instead.
144
+
145
+ **Safety:** Writes a version only into a skill folder SKF generated, or a new one; otherwise it stops with exit `9` (`not-skf-output`, or `flat-layout` for an SKF skill in the old flat layout) before writing anything. Quick Skill names a skill after its target, so use `BS` → `CS` to create it under another name. When the version it writes already holds a build another workflow made (a Create Skill build, for example), the overwrite question names that build, and a yes replaces the whole package with the quick skill (the build's forge data folder stays, and the summary names it); a headless run stops there instead, with exit `5` (`overwrite-cancelled`) and `error.details.existing_generator` naming the generator.
104
146
 
105
147
  **Agent:** Ferris (Architect mode)
106
148
 
@@ -110,14 +152,22 @@ Trigger workflows by typing commands to [Ferris](/docs/agents.md). See [Concepts
110
152
 
111
153
  **Command:** `@Ferris SS`
112
154
 
113
- **Purpose:** Consolidated project stack skill with integration patterns. Supports two modes: **code-mode** (analyzes a codebase) and **compose-mode** (synthesizes from existing skills + architecture document, no codebase required).
155
+ **Purpose:** Consolidated project stack skill with integration patterns. Supports two modes: **code-mode** (analyzes a codebase) and **compose-mode** (builds the stack from skills you already generated, plus an architecture document if you have one; no codebase needed).
114
156
 
115
- **When to Use:** When you want your agent to understand your entire project stack — not just individual libraries. Use code-mode for existing projects; compose-mode activates automatically after the VS → RA verification path when skills exist but no codebase is present.
157
+ **When to Use:** When you want your agent to understand your entire project stack, not just individual libraries. Use code-mode for existing projects. SS uses compose-mode when you give it an architecture document or ask for compose mode. It also offers compose-mode when the project has no dependency manifests but SKF-generated skills exist, and headless runs accept that offer. Compose-mode is the usual next step after the VS → RA verification path.
116
158
 
117
159
  **Key Steps (code-mode):** Detect manifests → Rank dependencies → Scope confirmation → Parallel extract → Detect integrations → Compile stack → Generate references
118
160
 
119
161
  **Key Steps (compose-mode):** Load existing skills → Confirm scope → Detect integrations from architecture doc → Compile stack → Generate references
120
162
 
163
+ **Inputs:** `project_path` (the folder code mode scans, by default the project root; an interactive run asks once when the manifests sit in several folders), `skills` (the libraries to rank, or in compose mode the constituent skills, as skill names or package paths, comma-separated or one per line in a file), `stack_name` (by default `<project>-stack`; `-stack` is appended when the name lacks it), `scope_overrides`, `architecture_doc_path` and `mode` (`code` or `compose`). A value SS cannot use, such as a `stack_name` that is not a skill name, stops the run with exit `2` (`input-invalid`). Code mode counts each dependency's importing files with SKF's import-count helper.
164
+
165
+ **Run state:** A run keeps its state in a run folder under `_bmad-output/.skf-run/`: its warnings, auto-decisions, import counts, extraction bundle and draft. The folder is deleted when the run finishes or you cancel it. The review before SS writes the stack (step 6) shows the stats and the draft's path; it shows the full draft only when you ask, and never in a headless run.
166
+
167
+ **Halts:** SS stops with exit `3` (`helper-missing`) when a shared helper it needs is missing, and with exit `2` (`unknown-verdict-token`) when a Verify Stack report holds a verdict token outside the schema's set.
168
+
169
+ **Safety:** Writes the stack only into the folder `stack_name` names (by default `<project>-stack`) when SKF generated it, or a new one; otherwise it stops with exit `5` (`not-skf-output` or `flat-layout`) before writing anything. Compose-mode loads only the skills SKF generated.
170
+
121
171
  **Agent:** Ferris (Architect mode)
122
172
 
123
173
  ---
@@ -132,12 +182,16 @@ Trigger workflows by typing commands to [Ferris](/docs/agents.md). See [Concepts
132
182
 
133
183
  **Key Steps:** Init → Scan project → Identify units → Map exports & detect integrations → Recommend → Generate briefs
134
184
 
135
- **Note:** Supports resume — if the session is interrupted mid-analysis, re-run `@Ferris AN` and Ferris will resume from where it left off.
185
+ **Questions:** Init uses what the invocation already gives (the target path, the goal and the scope) and asks at most one opening question for what is missing. In an interactive run, the map-and-detect and recommend menus also offer `[D]` Discover Additional Source, which adds one more project path to the analysis.
186
+
187
+ **Note:** Run `@Ferris AN` again after an interruption and an unfinished analysis of the same target resumes where it left off. A finished analysis, an unfinished `AN[auto]` one (interrupted, or ended by a merge or skip choice) unless it switched to the step-by-step analysis, an unfinished one when the new run is `AN[auto]`, one of a different target, and one the new run gives a different `--target-ref`, `--target-refs`, `--scope-hint` or `--intent-hint` are archived in `forge_data_folder` as `analyze-source-report-<project>-<YYYYMMDD-HHmmss>.md`, and a fresh analysis starts.
136
188
 
137
189
  **Agent:** Ferris (Architect mode)
138
190
 
139
191
  ---
140
192
 
193
+ ## Quality Workflows
194
+
141
195
  ### Audit Skill (AS)
142
196
 
143
197
  **Command:** `@Ferris AS`
@@ -148,7 +202,19 @@ Trigger workflows by typing commands to [Ferris](/docs/agents.md). See [Concepts
148
202
 
149
203
  **Key Steps:** Load skill → Re-index source → Structural diff (incl. script/asset drift) → Semantic diff (Deep) → Classify severity → Doc drift → Report
150
204
 
151
- **Stack skill support:** Code-mode stacks are audited per-library against their sources. Compose-mode stacks check constituent freshness via metadata hash comparison — if a constituent skill was updated after the stack was composed, audit flags it as constituent drift. Stack skills that need updating are redirected to `@Ferris SS` for re-composition (surgical update is not supported for stacks).
205
+ **Version read:** An audit reads the version the skill's `active` link names, also when the export manifest still names an older one (after an update, before the next export). In that case an interactive run offers `[M]` to audit the manifest's version instead.
206
+
207
+ **Upstream:** When the source repository has a newer ref than the one the skill was built from, an interactive audit asks: `[C]` audit the newer ref, read into a private tree of the run's own while SKF's clone stays as it is, `[S]` stay on the baseline and recommend `@Ferris US <name> --target-ref <ref>`, or `[X]` stop. A headless run takes `[C]` unless `upstream_drift_choice=S` or `X` is passed. The `dirty_worktree_choice` and `force` inputs are gone.
208
+
209
+ **Baseline:** An audit compares the skill with the baseline it recorded when it was built. An interactive audit shows its baseline summary and analysis plan and goes straight on. It stops to ask only when this run's forge tier is below the tier the skill was compiled at (so the diff can report as drift what only the tools changed; a compose-mode stack or a docs-only skill re-reads no source and never stops for this), or when the provenance map is more than 90 days old. At that stop, `[C]` continues, and `[X]` stops the run with exit `6` (`user-cancelled`) and keeps the drift report, which then holds the baseline only. A headless run continues. A skill with no provenance map, such as a Quick Skill, stops with `no-baseline` (exit `3`) in every mode, and the message points to `@Ferris TS` (test it against its source) or `@Ferris CS` (create it again so it can be audited). A docs-only skill is audited by its documents: each tracked document's hash is compared with the one recorded at compile time, and a changed document is graded HIGH, so the score is SIGNIFICANT, with `next_workflow` `update-skill`, or CLEAN when nothing changed. A docs-only skill that records no hash stops with `no-baseline`, one with no document that could be compared stops with `source-unreadable` (exit `3`), and a partial comparison adds a `doc_fetch_failed` or `doc_not_hashed` warning. The audit checks `uv` and its helpers before its first question and stops with `helper-missing` (exit `3`) when one is missing. The `degraded` input and the `severity_rules_path` setting are gone.
210
+
211
+ **Provenance labels:** An export's labels, its confidence tier and its extraction method, follow the tool that read it, so a later read can change them, such as T1 to T1-low when ast-grep could not parse the file this time, or back. The drift report lists such changes in a **Provenance label differences (not drift)** table: they are not drift, are not counted in Total Drift Items and move no score. For a `public-api` skill, the new exports off the public surface Create Skill and Update Skill keep the provenance map to are listed apart, named in an **Off the public surface** note, and not counted in Total Drift Items; when the audit cannot read the surface (at Quick tier, for example), every new export is reported as added and the run warns `public_surface_not_applied`.
212
+
213
+ **Doc drift:** A skill compiled before SKF 3.0.0 recorded its README as a `blob/main` page, or as a URL with no scheme, so doc drift keeps flagging its README until Create Skill compiles it again and records the raw README at the ref the skill was built from.
214
+
215
+ **Stack skill support:** Code-mode stacks are audited library by library against their sources. Compose-mode stacks check that each constituent skill is still current by comparing metadata hashes: if a constituent skill was updated after the stack was composed, the audit flags it as constituent drift. Update Skill cannot patch a stack. When a stack needs updating, Update Skill sends you to `@Ferris SS` to compose it again.
216
+
217
+ **Output:** A drift report at `forge-data/<name>/<version>/drift-report-<timestamp>.md`. Its overall drift score is CLEAN, MINOR, SIGNIFICANT or CRITICAL. CLEAN means the skill matches the source at the ref the audit read: the ref it was built from, or the newer ref `[C]` audits. When the upstream has moved past the built ref, the report still ends with `@Ferris US <name> --target-ref <upstream_ref>` (`next_workflow` is `update-skill` whatever the drift score). Otherwise the report ends with the next step, usually `@Ferris US <name>`. Each run also keeps the JSON its score came from (the structural diff, the findings built from it and their classification) beside the drift report, in `forge-data/<name>/<version>/.skf-audit/<timestamp>/`.
152
218
 
153
219
  **Agent:** Ferris (Audit mode)
154
220
 
@@ -158,13 +224,28 @@ Trigger workflows by typing commands to [Ferris](/docs/agents.md). See [Concepts
158
224
 
159
225
  **Command:** `@Ferris TS`
160
226
 
161
- **Purpose:** Verifies whether a skill covers its target completely and accurately. Naive and contextual modes. Quality gate before export.
227
+ **Purpose:** Verifies whether a skill covers its target completely and accurately. An individual skill is tested in naive mode (coverage of its public API). A stack skill is tested in contextual mode, which also checks that its references and integration patterns hold together. Quality gate before export.
162
228
 
163
229
  **When to Use:** After creating or updating a skill, before exporting.
164
230
 
165
- **Key Steps:** Load skill → Detect mode → Coverage check → Coherence check → External validation (skill-check, tessl) → Hard gate → Score → Gap report
231
+ **Key Steps:** Load skill → Detect mode → Coverage check → Coherence check → External validation (skill-check; Tessl Review when you opt in) → Hard gate → Score → Gap report
232
+
233
+ **Scored Categories:** Export Coverage, Signature Accuracy, Type Coverage, Coherence and External Validation, weighted by the kind of skill. An individual skill (naive mode) does not score Coherence, and its weights are 45%, 25%, 20% and 10%. A stack skill (contextual mode) starts from 36%, 22%, 14%, 18% and 10%, but Signature Accuracy and Type Coverage are not scored for a stack, because they would grade other libraries' APIs, so their weight moves to the other three categories. At Quick tier, Signature Accuracy and Type Coverage are skipped for every skill in the same way.
166
234
 
167
- **Scored Categories:** Export Coverage (36%), Signature Accuracy (22%), Type Coverage (14%), Coherence (18%), External Validation (10%). Default pass threshold: **80%** (per-pipeline defaults: forge-auto 90%, forge 80%). Pass routes to Export Skill; fail routes to Update Skill with a gap report. See [Completeness Scoring](/docs/verifying-a-skill.md#how-the-score-is-computed) for the full formula and tier adjustments.
235
+ Default pass threshold: **80%**. Inside a pipeline the default follows the alias: `forge-auto` uses 90%, `forge` and `forge-quick` use 80%, and a campaign uses 90%. Pass `--threshold=<N>` to set your own bar. When the bar is above 80% and a skill scores at least 80% but under the bar, it still passes at the 80% floor, and Test Skill writes `evidence-report-fallback.md` to record the gap. A run that a cap failed stays a FAIL at any threshold. Pass routes to Export Skill; fail routes to Update Skill with a gap report. See [Completeness Scoring](/docs/verifying-a-skill.md#how-the-score-is-computed) for the full formula and tier adjustments.
236
+
237
+ **Flags:**
238
+
239
+ - `--threshold=<N>` sets the pass score for this run. It wins over pipeline defaults.
240
+ - `--tier=<Quick|Forge|Forge+|Deep>` tests at that tier without reading `forge-tier.yaml`, which helps in CI before setup has run.
241
+ - `--no-discovery` leaves the discovery-testing block out of the report.
242
+ - `--no-health-check` skips the health check that ends the run.
243
+ - `--discovery-catalog=all` widens the discovery catalog to the skills in `.claude/skills/` and `_bmad/agents/`.
244
+ - `--allow-workspace-drift` reads the source at its current commit instead of the pinned one (see [Verifying a Skill](/docs/verifying-a-skill.md#workflow-time-enforcement)). Update Skill with `--from-test-report` takes the same flag, but takes nothing from that commit: it never moves or records a provenance line from it and reads no signature, parameter list, return type or node kind there, so a test report with a new or changed export, whatever its severity, stops it with `halted-for-workspace-drift` before it changes the skill. A rescope (a removed export) stops it the same way, because its public API recount needs the pinned tree: the run has not written the brief amendment yet, so the brief stays as it was and a re-run asks again. When no gap needs the source, the stats keep the public API counts `metadata.json` records.
245
+
246
+ **Skill name:** A headless run with no skill name halts `input-missing`; an interactive run lists the skills there are to test and asks which one.
247
+
248
+ **Verdicts and exit codes (headless):** Each outcome has its exit code: `0` PASS, `2` FAIL, `3` INCONCLUSIVE, `4` pass-with-drift, and `1` for a halt before any verdict. A skill run cannot set the exit status of the agent that runs it (`claude -p` exits `0` whatever the run decided), so automators read `exit_code` from the `SKF_TEST_RESULT_JSON` line, or from `skf-test-skill-result-latest.json`. In headless mode that line, which carries the same verdict and score, is the run's last line. A run the hard gate blocks on a Critical or High gap is a FAIL as well: it still writes the Gap Report and a FAIL result record, runs `on_complete` and the health check, and its result line, printed on stderr instead of stdout, has `exit_code` `2`, `status: "error"`, `halt_reason: "hard-gate-blocked"` and no score.
168
249
 
169
250
  **Agent:** Ferris (Audit mode)
170
251
 
@@ -178,10 +259,16 @@ Trigger workflows by typing commands to [Ferris](/docs/agents.md). See [Concepts
178
259
 
179
260
  **Purpose:** Pre-code stack feasibility verification. Cross-references generated skills against architecture and PRD documents with three passes: coverage, integration compatibility, and requirements.
180
261
 
181
- **When to Use:** After generating individual skills with CS/QS, before building a stack skill — to verify the tech stack can support the architecture.
262
+ **When to Use:** After generating individual skills with CS or QS, and before building a stack skill, to check that the tech stack can support the architecture.
182
263
 
183
264
  **Key Steps:** Load skills + docs → Coverage analysis → Integration verification → Requirements check → Synthesize verdict → Present report
184
265
 
266
+ **Skills read:** Only the skills SKF generated. Other skills in `skills_output_folder`, such as a module's own, are listed once as "Skipped (not SKF output)" and count toward no inventory check or pair. A `metadata.json` SKF cannot read still counts as one warning, because SKF then cannot tell whether it generated that skill.
267
+
268
+ **Inputs:** Your architecture document (required), a PRD (optional), and at least two SKF skills in `skills_output_folder`. **Output:** `feasibility-report-<project>-<timestamp>.md` plus a `-latest.md` copy in `forge-data/`, with an overall verdict of FEASIBLE, CONDITIONALLY_FEASIBLE or NOT_FEASIBLE. When an earlier report exists, VS offers to compare against it so you see what changed. VS writes the `-latest.md` copy only once the finished report passes its check, so a halted run leaves the previous `-latest` in place, and it compares against the newest earlier report that finished and passed that check.
269
+
270
+ **Verdicts:** `FEASIBLE` means every technology the architecture keeps has a skill, every integration pair is `Verified` (one of its two skills cites the other literally) and, when you gave a PRD, every requirement is met. VS takes integration pairs from the architecture document's prose, never from a Mermaid diagram. A run that finds no pair between two or more covered technologies, as when the integrations are drawn only in a diagram, ends `CONDITIONALLY_FEASIBLE`, because no integration was verified, and recommends describing them in prose. A weak result never stops VS early: a run that covers none of the technologies, finds every one marked for removal, or finds every pair `Blocked` prints a warning and finishes `NOT_FEASIBLE`, with a recommendation for each gap, such as a replacement library or a bridge for each Blocked pair.
271
+
185
272
  **Agent:** Ferris (Audit mode)
186
273
 
187
274
  ---
@@ -190,11 +277,19 @@ Trigger workflows by typing commands to [Ferris](/docs/agents.md). See [Concepts
190
277
 
191
278
  **Command:** `@Ferris RA`
192
279
 
193
- **Purpose:** Improves an architecture document using verified skill data as evidence. Takes the original architecture doc + generated skills + optional VS report, fills gaps, flags contradictions, and suggests improvements — all citing specific APIs.
280
+ **Purpose:** Improves an architecture document using verified skill data as evidence. Takes the original architecture doc, the generated skills and an optional VS report, then fills gaps, flags contradictions and suggests improvements, each citing specific APIs.
194
281
 
195
282
  **When to Use:** After VS confirms feasibility, before running SS in compose-mode. Produces a refined architecture ready for stack skill composition.
196
283
 
197
- **Key Steps:** Load inputs → Gap analysis → Issue detection → Improvement detection → Compile refined doc → Present report
284
+ **Key Steps:** Load inputs → Gap analysis (confirms a derived scope) → Issue detection → Improvement detection → Compile a draft and review it (`[R]` walks through each refinement with its evidence, before you approve with `[C]`) → Present report
285
+
286
+ **Scope:** RA refines the document with the skills in its scope: the ones you name with `--scope-skills`, or else the ones the document mentions (a skill whose relevance is unclear stays in scope). When it works out the scope itself and leaves skills out, it shows which skills are in and out of scope before it reads their APIs: type `C` to keep the scope, a skill's name to bring it in, or `-<name>` to take it out. A headless run keeps the derived scope and logs that decision. Integration pairs, VS verdicts and improvement suggestions that involve an out-of-scope skill are listed for awareness only and stay out of the refined document.
287
+
288
+ **Skills read:** Only the skills SKF generated. Other skills in `skills_output_folder`, such as a module's own, are listed once as "Skipped (not SKF output)" and count toward no inventory check or pair. A `metadata.json` SKF cannot read still counts as one warning, because SKF then cannot tell whether it generated that skill.
289
+
290
+ **Feasibility report:** RA finds the newest Verify Stack report itself, `feasibility-report-<slug>-latest.md` in `forge_data_folder`, and offers it as the default: press Enter to use it, or give another path. A headless run uses it and logs that it did. Pass `--vs-report-path <path>` to use another report, or `--vs-report-path none` to refine without one. RA checks the report against the feasibility-report contract before it reads it, and stops with exit `2` (`input-invalid`) on one that breaks it (see [Headless Mode](#headless-mode) for every RA exit code).
291
+
292
+ **Output:** RA builds a draft and writes `refined-architecture-<project>.md` in `output_folder` (`_bmad-output/` in a standalone install) only when you approve the review with `[C]`, and leaves your architecture document as it is. An earlier file of that name is first renamed `refined-architecture-<project>-<YYYYMMDD-HHmmss>.md`. Every refinement sits between `<!-- RA:BEGIN ... -->` and `<!-- RA:END -->` markers, so when you give RA a document it already refined, the new run replaces its earlier blocks, and text you moved outside the markers stays. Findings a review dismissed are kept in `.ra-dismissed-<project>.json` in the output folder, written only when the review is approved with `[C]`, so a later run does not raise them again. A run that leaves skills out of scope records an `out_of_scope_skills` warning that names them. The Refinement Summary counts the gaps, issues and improvements, and its `Not verified (no skill)` row names the libraries, databases and services the document mentions but no skill covers: nothing checked what the document says about them. A `VS Coverage` row shows the Verify Stack report's coverage when RA used one. The final report of an interactive run does not repeat the summary's count table, which the review already showed; a headless run reports the counts in its result line. When technologies are not verified, the next steps say to create their skills with `@Ferris CS` or `@Ferris QS` and run RA again before Stack Skill.
198
293
 
199
294
  **Agent:** Ferris (Architect mode)
200
295
 
@@ -212,6 +307,15 @@ Trigger workflows by typing commands to [Ferris](/docs/agents.md). See [Concepts
212
307
 
213
308
  **Key Steps:** Load skill → Validate package → Generate snippet → Update context file (CLAUDE.md/AGENTS.md/.cursorrules) → Token report → Summary
214
309
 
310
+ **Flags:**
311
+
312
+ - Name several skills (`@Ferris EX skill-a skill-b`) to export them in one run. Each confirmation covers the whole batch, not one skill at a time.
313
+ - `--all` exports every skill listed in `.export-manifest.json`, except deprecated ones. On a first export, with no manifest yet, it exports every SKF skill in `skills_output_folder`.
314
+ - `--dry-run` shows the snippet, context-file and manifest changes and writes nothing.
315
+ - `--context-file <file>` writes only that context file (`CLAUDE.md`, `AGENTS.md` or `.cursorrules`) instead of every file the configured IDEs map to. Any other value stops the run with exit `3` (`resolution-failure`).
316
+
317
+ **Good to know:** Export warns when a skill has no test report, failed its last test, or its last test was inconclusive or passed only under `--allow-workspace-drift`, but it still exports if you confirm. With passive context on (the default), it writes each skill's `context-snippet.md` last, after you confirm the context-file change, so a cancelled or halted export leaves the snippet as it was. Set `passive_context: false` in your preferences to package skills without touching `CLAUDE.md`, `AGENTS.md` or `.cursorrules`: such a run writes no snippet. When no earlier export chose a snippet root, an interactive run asks one layout question, and a headless run takes the IDE skill folder, recorded as the `load-skill.snippet-root-layout` decision. When an earlier export's root differs from the IDE mapping, a headless run keeps the earlier root for that run when only that folder holds the skills, and uses the IDE mapping otherwise. A repo whose skills live in `skills/` sets `snippet_skill_root_override: skills/` in `config.yaml`. Export finds every helper it needs before its first prompt, so a missing one stops the run with exit `4` (`context-rebuild-failed`) before you answer anything.
318
+
215
319
  **Agent:** Ferris (Delivery mode)
216
320
 
217
321
  ---
@@ -220,13 +324,15 @@ Trigger workflows by typing commands to [Ferris](/docs/agents.md). See [Concepts
220
324
 
221
325
  ### Campaign Orchestration
222
326
 
223
- **Command:** `@Ferris campaign`
327
+ **Command:** `@Ferris CA` or `@Ferris campaign`
328
+
329
+ `@Ferris campaign` starts a campaign, or offers to resume one that exists. `@Ferris campaign resume [--from=<skill>]` resumes from the last active skill or the one you name, and `@Ferris campaign status` shows progress without changing anything. Pass `--brief <file>` or `--manifest <file>` to seed the target list from a file; either one runs the campaign headless. See [Campaign Orchestration](/docs/campaign.md).
224
330
 
225
331
  **Purpose:** Orchestrate multi-library skill production across sessions with dependency tracking and resume.
226
332
 
227
- **When to Use:** When you need to produce 15+ coordinated skills with dependency ordering — too many for manual one-at-a-time pipeline runs.
333
+ **When to Use:** When you need to produce 15 or more coordinated skills in dependency order, too many to run one pipeline at a time by hand.
228
334
 
229
- **Key Steps:** Setup → Strategy → Pin Validation → Provenance → Skill Loop → Tier B Batch → Capstone → Verify → Refine → Export → Maintenance
335
+ **Key Steps:** Setup → Strategy → Pin Validation → Provenance → Skill Loop (the full pipeline for each Tier A skill) → Tier B Batch (secondary dependencies, built in one Quick Skill batch) → Capstone (one stack skill that ties all the skills together) → Verify → Refine → Export (waits for your approval, except in headless runs) → Maintenance
230
336
 
231
337
  **Agent:** Ferris (Management mode)
232
338
 
@@ -240,11 +346,13 @@ Trigger workflows by typing commands to [Ferris](/docs/agents.md). See [Concepts
240
346
 
241
347
  **Purpose:** Rename a skill across all its versions. Because the agentskills.io spec requires `name` to match parent directory name, this is a coordinated move across outer/inner directories, SKILL.md frontmatter, metadata.json, context snippets, provenance maps, the export manifest, and platform context files.
242
348
 
243
- **When to Use:** You need to change a skill's name — for example, graduating a `QS`-generated skill (named from the repo) to a formal name, or adding a suffix like `-community` to distinguish from an official skill.
349
+ **When to Use:** You need to change a skill's name. For example, give a `QS`-generated skill (named after its repo) a formal name, or add a suffix like `-community` to tell it apart from an official skill.
244
350
 
245
351
  **Key Steps:** Select skill + new name → Transactional copy → Update all references → Rebuild context files → Delete old name (point of no return)
246
352
 
247
- **Safety:** Transactional — if any step fails before the final delete, the old skill remains intact. Warns if `source_authority: "official"` (rename is local-only; published registry skill won't change).
353
+ **Safety:** Transactional: if any step fails before the final delete, the old skill stays intact. Warns if `source_authority: "official"` (rename is local-only; published registry skill won't change), and a headless rename of an `official` skill stops with `source-authority-blocked` unless you pass `--acknowledge-official`. Names given with the invocation (`rename cognee to cognee-ai`) are used in interactive runs too, which then ask only for a name that is missing or invalid. Renames only skills SKF generated in the versioned layout: a folder whose `metadata.json` carries no SKF marker, or one that also holds files SKF did not generate, is refused, and a skill still in the old flat layout must first be moved into the versioned layout by running `@Ferris TS` (or `US`, `AS`, `EX`) on it. It moves the skill's folder in `forge_data_folder` only when SKF generated it: it refuses one that also holds other files or that is a link, is not a folder, or cannot be listed, and leaves another tool's folder of the same name where it is. A rename interrupted after it re-keyed the export manifest is caught when you run the same rename again: the run stops with `name-collision` (exit `5`), lists the old folders left on disk and gives the checked delete (`skf-skill-inventory.py guarded-delete`) that finishes the rename; then `@Ferris EX` rebuilds the context files. Rename does not rename a copy `npx skills add` installed in the IDE skill folder a context file's managed section points at, such as `.claude/skills/<old-name>/`: the report names each one it finds with its reinstall step, and the run's warnings, in the envelope and the result file, carry `installed-copy-not-renamed` for each. No check runs when `snippet_skill_root_override` is set.
354
+
355
+ **Preview first:** Add `--dry-run` to `@Ferris RS` or `@Ferris DS` to see which folders, manifest entries and context files would change. Nothing is written or deleted.
248
356
 
249
357
  **Agent:** Ferris (Management mode)
250
358
 
@@ -254,13 +362,15 @@ Trigger workflows by typing commands to [Ferris](/docs/agents.md). See [Concepts
254
362
 
255
363
  **Command:** `@Ferris DS`
256
364
 
257
- **Purpose:** Drop a specific skill version or an entire skill. Soft drop (default) marks the version as deprecated in the manifest and keeps files on disk. Hard drop (`--purge`) also deletes the files.
365
+ **Purpose:** Drop a specific skill version or an entire skill. Soft drop (default) marks the version as deprecated in the manifest and keeps files on disk. Hard drop (`--mode purge`) also deletes the files.
258
366
 
259
367
  **When to Use:** Retire a deprecated version (e.g., drop an older cognee skill version because it's obsolete), free disk space, or remove a skill you no longer need.
260
368
 
261
369
  **Key Steps:** Select skill → Select version(s) + mode → Update manifest → Rebuild context files → Delete files (if purge)
262
370
 
263
- **Safety:** Active version guard — cannot drop the currently active version when other non-deprecated versions exist (switch active first, or drop all). Soft drop is reversible by editing the manifest.
371
+ **Safety:** Active version guard: you cannot drop the currently active version while other non-deprecated versions exist. To drop it and keep another version, make the version you keep active first: point the skill's `active` link at it (`uv run _bmad/skf/shared/scripts/skf-atomic-write.py flip-link --link <skills_output_folder>/<name>/active --target <version to keep>`, which works in Git Bash, PowerShell and WSL2), run `@Ferris EX` on the skill, which exports that version and archives the old one, then drop the old one. To drop the whole skill instead, choose the All versions option. Soft drop is reversible by editing the manifest. Drop offers a skill folder SKF did not generate only when the manifest lists it, and then only for deprecate. A purge deletes only SKF output: a whole-skill purge of a folder that also holds other files is refused, and so is a purge through a link. The same goes for the skill's folder in `forge_data_folder`, except that a folder there SKF did not generate (another tool's folder of the same name, or a link) is left in place and named in the report. A headless drop of a skill with no manifest entry needs `--mode purge`. A headless drop of a skill in the export manifest needs `version=all` or the one version to drop: without it, the run stops with exit `2` (`input-missing`) before it changes anything. A specific version for a draft skill (one with no manifest entry) stops with exit `2` (`input-invalid`) in every mode, since a draft is dropped whole.
372
+
373
+ **Preview first:** Add `--dry-run` to `@Ferris RS` or `@Ferris DS` to see which folders, manifest entries and context files would change. Nothing is written or deleted.
264
374
 
265
375
  **Agent:** Ferris (Management mode)
266
376
 
@@ -272,15 +382,15 @@ Trigger workflows by typing commands to [Ferris](/docs/agents.md). See [Concepts
272
382
 
273
383
  ```mermaid
274
384
  flowchart TD
275
- SF[Setup Forge — one-time] --> AN[Analyze Source]
385
+ SF["Setup Forge (run once)"] --> AN[Analyze Source]
276
386
  SF --> QS[Quick Skill]
277
- SF --> SS_code[Stack Skill — code-mode]
387
+ SF --> SS_code["Stack Skill (code-mode)"]
278
388
 
279
389
  AN --> BS[Brief Skill]
280
390
  BS --> CS[Create Skill]
281
391
  AN -->|direct| CS
282
392
 
283
- CS --> TS[Test Skill — quality gate]
393
+ CS --> TS["Test Skill (quality gate)"]
284
394
  QS --> TS
285
395
  SS_code --> TS
286
396
 
@@ -294,9 +404,9 @@ flowchart TD
294
404
 
295
405
  ```mermaid
296
406
  flowchart TD
297
- GEN["Create Skill | Quick Skill ×N<br/>(per library)"] --> VS[Verify Stack — feasibility report]
298
- VS --> RA[Refine Architecture — refined doc]
299
- RA --> SS_compose[Stack Skill — compose-mode]
407
+ GEN["Create Skill or Quick Skill ×N<br/>(per library)"] --> VS["Verify Stack (feasibility report)"]
408
+ VS --> RA["Refine Architecture (refined doc)"]
409
+ RA --> SS_compose["Stack Skill (compose-mode)"]
300
410
  SS_compose --> TS[Test Skill]
301
411
  TS --> EX[Export Skill]
302
412
  ```
@@ -307,15 +417,15 @@ flowchart TD
307
417
  flowchart TD
308
418
  CAMPAIGN[Campaign Orchestration] --> SETUP[Setup + Strategy]
309
419
  SETUP --> PINS[Pin Validation + Provenance]
310
- PINS --> LOOP["Skill Loop<br/>(BS → CS → TS → EX per skill)"]
420
+ PINS --> LOOP["Skill Loop<br/>(AN → BS → CS → TS per skill)"]
311
421
  LOOP --> BATCH[Tier B Batch]
312
- BATCH --> CAP[Capstone — Stack Skill]
422
+ BATCH --> CAP["Capstone: Stack Skill"]
313
423
  CAP --> VER[Verify + Refine]
314
- VER --> EXPORT[Export — write-gate HALT]
424
+ VER --> EXPORT["Export (write-gate HALT)"]
315
425
  EXPORT --> MAINT[Maintenance + Campaign Report]
316
426
  ```
317
427
 
318
- > **One workflow per session** (unless using pipeline mode or campaign). Each arrow in the standard and compose-mode diagrams represents a new conversation session. Campaign manages its own multi-session orchestration internally — see [Campaign Orchestration](/docs/campaign.md). Clear your context between workflows for best results — or use pipeline mode to chain them automatically. See [Pipeline Mode](#pipeline-mode) below.
428
+ > **One workflow per session** (unless you use pipeline mode or a campaign). Each arrow in the standard and compose-mode diagrams stands for a new conversation session. A campaign runs its own sessions; see [Campaign Orchestration](/docs/campaign.md). Clear your context between workflows for best results, or use pipeline mode to chain them automatically. See [Pipeline Mode](#pipeline-mode) below.
319
429
 
320
430
  ---
321
431
 
@@ -328,7 +438,7 @@ flowchart TD
328
438
  | Quality | AS, TS | Detect skill drift (AS) and verify skill completeness (TS) |
329
439
  | Architecture Verification | VS, RA | Pre-code architecture feasibility and refinement |
330
440
  | Orchestration | Campaign | Multi-library skill production with dependency tracking and resume |
331
- | Management | RS, DS | Rename and drop skill versions with transactional safety |
441
+ | Management | RS, DS | Rename a skill across all its versions, or drop one version or a whole skill |
332
442
  | Utility | EX | Package and export for consumption |
333
443
  | In-Agent | WS, KI | WS: show lifecycle position, active briefs, and forge tier; KI: list knowledge fragments (both in-agent, no file-based workflow) |
334
444
 
@@ -340,72 +450,78 @@ Instead of running one workflow per session, you can chain multiple workflows in
340
450
 
341
451
  ### Syntax
342
452
 
343
- ```
344
- @Ferris BS CS TS EX — space-separated codes
345
- @Ferris QS[cocoindex] TS EX — with target argument in brackets
346
- @Ferris CS TS[min:80] EX — with circuit breaker threshold override
347
- @Ferris forge-quick cognee — named alias with target
348
- ```
453
+ | Command | What it does |
454
+ | --- | --- |
455
+ | `@Ferris QS[cocoindex] TS EX` | Runs the codes left to right, separated by spaces, and passes QS its target in brackets |
456
+ | `@Ferris QS[cocoindex] -> TS -> EX` | The same run, with arrows between the codes |
457
+ | `@Ferris QS[cocoindex] TS[min:80] EX` | The same run, with TS's circuit breaker threshold set to 80 |
458
+ | `@Ferris forge-quick cognee` | Runs a named alias with its target |
349
459
 
350
460
  ### Pipeline Aliases
351
461
 
352
- The `forge-auto` alias is the recommended way to create skills — one command, zero configuration. It chains five workflows with auto-mode flags so you get a verified skill without touching a brief or scope file.
462
+ The `forge-auto` alias is the recommended way to create skills: one command, no configuration. It chains five workflows with auto-mode flags, so you get a verified skill without writing a brief or a scope file.
463
+
464
+ | Alias | Expands To | First Workflow | Required Target |
465
+ | ------------- | ------------------------------------ | -------------- | -------------------------------------------------------------- |
466
+ | `forge-auto` | `AN[auto] BS[auto] CS TS[min:90] EX` | AN | Repo URL, local path or doc URL (add `--pin <version>` to pin a version) |
467
+ | `forge` | `BS CS TS EX` | BS | GitHub URL or local path **+** skill name |
468
+ | `forge-quick` | `QS TS EX` | QS | GitHub URL **or** package name |
469
+ | `maintain` | `AS US TS EX` | AS | Existing skill name |
353
470
 
354
- | Alias | Expands To | First Workflow | Required Target |
355
- | ------------- | -------------------------------------- | -------------- | -------------------------------------------- |
356
- | `forge-auto` | `AN[auto] BS[auto] CS TS[min:90] EX` | AN | GitHub URL, doc URL, or `--pin <version>` |
357
- | `forge` | `BS CS TS EX` | BS | GitHub URL or local path **+** skill name |
358
- | `forge-quick` | `QS TS EX` | QS | GitHub URL **or** package name |
359
- | `maintain` | `AS US TS EX` | AS | Existing skill name |
471
+ **The first workflow's input contract defines what arguments the pipeline needs.** A bare package name works for `forge-quick` (QS resolves packages through the registry) but **not** for `forge`, because BS needs both an unambiguous target (URL or path) and a skill name.
360
472
 
361
- **The first workflow's input contract defines what arguments the pipeline needs.** A bare package name works for `forge-quick` (QS resolves packages via the registry) but **not** for `forge` — BS requires both an unambiguous target (URL or path) and a skill name.
473
+ An alias given without its argument asks for it, and a headless run, such as one started with `--headless`, halts instead, before any workflow runs. A chain of codes does the same: when its first code has no target in brackets and its input is not among the arguments, as in `@Ferris QS TS EX`, Ferris asks for that input and runs the chain as `QS[<input>] TS EX`. A chain of codes takes that input only in brackets: a word after the codes, as in `QS TS EX cognee`, is an unknown code, so Ferris names it and asks for a corrected invocation, and a headless run halts on it. A headless run stops before any workflow runs, with a halt reason that, for an input a bracket gives, reads `<CODE> needs <input> before the pipeline can start: give it as <CODE>[<input>]`, such as `QS needs a target before the pipeline can start: give it as QS[<target>]`. SF and SS take no input: a chain that starts with SS runs as given, and Ferris looks past a leading SF, so `SF QS TS EX` asks for the target of QS. A chain led by `CS` never halts before it starts: in an interactive run Ferris asks for its skill name unless its bracket holds `auto`, and a `CS` left without one has Create Skill compile the only brief, or halt (`brief-missing`) when it finds none, or several, which it names. A bracket holds one value, so a chain led by `BS` gets its target and skill name only as `forge <repo-url-or-path> <skill-name>`: a chain of the `forge` alias's codes, such as a bare `BS CS TS EX`, with at most a target in BS's bracket and no other bracket but an ignored `min:N`, asks for what BS lacks and runs as that alias. Any other chain led by `BS`, one led by `RS` or `DS` (run those on their own), and one led by any other code but `CS` whose bracket already holds `auto`, or by AN or TS with a `min:N` in its bracket (such as `TS[min:80] EX`), have no bracket for that input: Ferris says why and asks for another invocation, and a headless run halts with that reason. A `min:N` on another code is ignored, so Ferris asks for that code's input as if its bracket were empty.
362
474
 
363
475
  ### How It Works
364
476
 
365
- - Pipelines **automatically activate headless mode** — all confirmation gates auto-proceed with their default action
366
- - **Data flows automatically** — once the first workflow completes, the brief path or skill name becomes the input for downstream workflows
367
- - **Circuit breakers** halt the pipeline if quality drops below a threshold (e.g., test score < 60 blocks export)
368
- - **Anti-pattern warnings** — Ferris warns if you chain workflows in a problematic order (e.g., exporting before testing)
369
- - **Progress reporting** — Ferris reports completion of each workflow before starting the next
370
- - **Safe halt on ambiguity** — headless mode won't guess. If the initial target doesn't satisfy the first workflow's contract (e.g., `forge cognee` — ambiguous, not a URL or path), the pipeline halts at step 1 before any work happens and suggests concrete next steps.
477
+ - Pipelines **automatically turn on headless mode**: every confirmation gate auto-proceeds with its default action
478
+ - **Data flows automatically**: once the first workflow completes, its brief path or skill name becomes the input for the next workflows
479
+ - **Circuit breakers** stop the pipeline when a step's result is not good enough: AN finds nothing worth making into a skill, CS hits a hard error, AS finds CRITICAL drift, TS settles any verdict but PASS, or VS covers none of the technologies the architecture keeps. TS stops the pipeline on every FAIL (a Critical or High gap, a score below its threshold, or a FAIL that a cap forced although the score clears the threshold), on INCONCLUSIVE and on pass-with-drift. A TS score between 80% and a higher pipeline target (90% for `forge-auto`) passes with a fallback evidence report. VS stops the pipeline only on zero coverage, so a `NOT_FEASIBLE` verdict with coverage goes on to RA, which takes each `Blocked` pair as a critical issue.
480
+ - **`maintain` skips what it does not need.** When AS finds no drift (CLEAN), Update Skill is skipped, unless the source moved past the ref the skill was built from: then US runs with `--target-ref <upstream_ref>`, the ref the audit found. When AS finds CRITICAL drift, `maintain` stops so you can review the drift report; then run `@Ferris US <name>` yourself.
481
+ - **Resume:** each pipeline keeps its state in a journal, `pipeline-journal.json`, in its own run folder under `_bmad-output/.skf-run/`, written after every workflow. If one stopped partway, the next time you start Ferris he offers to rerun the step it stopped on with the recorded plan, then the rest. A quality halt gets its repair route instead: after a TS FAIL, `US <name> --from-test-report`, then TS and EX at the recorded threshold. You can also drop the offer, which deletes that run folder. When the chain ends, Ferris writes its result to `pipeline-result-latest.json` in his sidecar folder.
482
+ - **Anti-pattern warnings**: Ferris warns if you chain workflows in a problematic order (for example, exporting before testing)
483
+ - **Progress reporting**: Ferris reports each workflow's completion before starting the next
484
+ - **Safe halt on a missing input**: headless mode won't guess. When an alias lacks one of its arguments (for example `forge cognee`, which gives a target but no skill name) or a chain's first workflow lacks its input, the pipeline halts at step 1 before any work happens and names what is missing, except a chain led by `CS`. The parse does not judge a target's form: `forge cognee cognee` starts Brief Skill, whose input check only warns that `cognee` does not look like a URL or a path.
485
+ - Codes can be separated by spaces or by arrows: `AN[https://github.com/honojs/hono] -> CS -> TS -> EX`.
371
486
 
372
487
  ### Examples
373
488
 
374
- ```
375
- @Ferris forge-auto https://github.com/honojs/hono — zero-ceremony skill
376
- @Ferris forge-auto https://docs.example.com — docs-only skill
377
- @Ferris forge-auto https://github.com/honojs/hono --pin v4.6.0 — pinned version
378
- @Ferris forge-quick @tanstack/query — QS + TS + EX for TanStack Query
379
- @Ferris forge https://github.com/topoteretes/cognee cognee — BS + CS + TS + EX, explicit URL + name
380
- @Ferris forge https://github.com/topoteretes/cognee cognee "public API only" — with scope hint
381
- @Ferris maintain cocoindex — AS + US + TS + EX for an existing cocoindex skill
382
- ```
489
+ | Command | What it does |
490
+ | --- | --- |
491
+ | `@Ferris forge-auto https://github.com/honojs/hono` | Zero-ceremony skill |
492
+ | `@Ferris forge-auto https://docs.example.com` | Docs-only skill |
493
+ | `@Ferris forge-auto https://github.com/honojs/hono --pin v4.6.0` | Pinned version |
494
+ | `@Ferris forge-quick @tanstack/query` | QS + TS + EX for TanStack Query |
495
+ | `@Ferris forge https://github.com/topoteretes/cognee cognee` | BS + CS + TS + EX with an explicit URL and name |
496
+ | `@Ferris maintain cocoindex` | AS + US + TS + EX for an existing cocoindex skill |
383
497
 
384
498
  ---
385
499
 
386
500
  ## Headless Mode
387
501
 
388
- Add `--headless` or `-H` to any workflow command to skip all confirmation gates. Ferris auto-proceeds with default actions (typically "Continue") and logs each auto-decision. Progress output is still shown — headless skips interaction, not reporting.
502
+ Add `--headless` or `-H` to any workflow command to skip all confirmation gates. Ferris auto-proceeds with the default actions (typically "Continue") and logs each auto-decision. Progress output is still shown: headless skips interaction, not reporting.
389
503
 
390
- ```
391
- @Ferris QS cocoindex --headless — quick skill with no interaction gates
392
- @Ferris TS --headless — test a skill without the review pause
393
- @Ferris EX -H — export with auto-approved context update
394
- ```
504
+ | Command | What it does |
505
+ | --- | --- |
506
+ | `@Ferris QS cocoindex --headless` | Quick skill with no interaction gates |
507
+ | `@Ferris TS cocoindex --headless` | Tests the cocoindex skill and ends with its `SKF_TEST_RESULT_JSON` line |
508
+ | `@Ferris EX cocoindex -H` | Exports the cocoindex skill with an auto-approved context update. A headless export needs a skill name or `--all` |
395
509
 
396
- You can also set `headless_mode: true` in your forge preferences (`_bmad/_memory/forger-sidecar/preferences.yaml`) to make headless the default for all workflows.
510
+ You can also set `headless_mode: true` in your forge preferences (`_bmad/_memory/forger-sidecar/preferences.yaml`) to make headless the default for all workflows. Headless never turns Tessl Review on: create-skill and test-skill send a skill to Tessl only when `tessl_review_workspace` is set in the same file, and then they do so in headless runs too.
397
511
 
398
- **Exception — `/skf-setup` headless emits a single-line JSON envelope.** Unlike other workflows, headless `/skf-setup` SUPPRESSES the human-readable status banner entirely and emits exactly one prefixed line on stdout:
512
+ **Exception: `/skf-setup` headless emits a single-line JSON envelope.** Unlike other workflows, headless (or `--quiet`) `/skf-setup` skips its status banner, progress lines and health-check output and ends on one prefixed envelope line. What setup guarantees is that this line is the run's final message, so it is exactly what `claude -p` prints; an interactive session or a `stream-json` reader may still see brief agent notes between tool calls. On success the health check runs first and the envelope follows it. On a tier miss or a halt the health check does not run, and the `status: "tier_failure"` envelope, or a `status: "blocked"` envelope whose `error.reason` carries the diagnostic, is the final message. Two cases have no envelope: when SKF's scripts are not installed in the project (a directory that is not an SKF project, or a helper-missing halt because they are gone), there is no helper to build one, and when an early halt (config missing or malformed, or `uv` missing) finds neither `uv` nor a Python interpreter (`python3`, `python` or `py -3`) to run the helper. Either way the run's one line is the bare halt reason. Pipelines should treat a missing envelope as a failure. When the forger runs `SF` as one step of a pipeline, setup displays the same line and hands control back to the forger, which keeps chaining. The success envelope looks like this:
399
513
 
400
514
  ```
401
515
  SKF_SETUP_RESULT_JSON: {"skf_setup":{"status":"success","tier":"Deep","previous_tier":"Forge","tier_changed":true,"tools":{...},"tools_added":[...],"tools_removed":[],"config_path":"...","ccc_index":{...},"files_written":[...],"tier_override_active":false,"tier_override_invalid":false,"require_tier_satisfied":null,"warnings":[],"error":null}}
402
516
  ```
403
517
 
404
- Parent skills and CI pipelines `grep` one line out of the workflow log to learn the outcome — no ASCII-art parsing, no race against the [`forge-tier.yaml`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/skf-setup/references/write-config.md) writer. Branch on the top-level `status` field (`success`, `tier_failure`, `write_failure`, or `blocked`) rather than composing the outcome from `require_tier_satisfied` + `error`. The envelope schema is versioned at [`src/shared/scripts/schemas/skf-setup-result-envelope.v1.json`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/shared/scripts/schemas/skf-setup-result-envelope.v1.json) and asserted against on every emit.
518
+ Parent skills and CI pipelines `grep` one line out of the workflow log to learn the outcome, with no ASCII-art parsing and no race against the [`forge-tier.yaml`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/skf-setup/references/write-config.md) writer. Branch on the top-level `status` field (`success`, `tier_failure`, or `blocked`) rather than composing the outcome from `require_tier_satisfied` + `error`. A write failure arrives as `blocked`, with an `error.phase` of `step 2:write-tools` or `step 2:forge-data-dir`. The envelope schema is versioned at [`src/shared/scripts/schemas/skf-setup-result-envelope.v1.json`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/shared/scripts/schemas/skf-setup-result-envelope.v1.json) and asserted against on every emit.
519
+
520
+ Setup is not the only workflow whose result line is the run's final message: a headless Test Skill, Quick Skill (one target, not `--batch`), Brief Skill (also under `[auto]`), Update Skill, Audit Skill, Drop Skill, Export Skill (a `--dry-run` too) or campaign run hands its `SKF_TEST_RESULT_JSON`, `SKF_QUICK_SKILL_RESULT_JSON`, `SKF_BRIEF_RESULT_JSON`, `SKF_UPDATE_RESULT_JSON`, `SKF_AUDIT_RESULT_JSON`, `SKF_DROP_SKILL_RESULT_JSON`, `SKF_EXPORT_RESULT_JSON` or `SKF_CAMPAIGN_RESULT_JSON` line to the shared health check, which displays it last, after everything else it shows (under `--no-health-check`, Test Skill displays it itself as its last line). A Drop Skill `--dry-run` stops at its confirmation gate and displays its line itself, last.
405
521
 
406
- **Exception — `/skf-quick-skill` headless emits structured progress + result envelopes.** Headless `/skf-quick-skill` runs are first-class building blocks for batch automators. Three operational contracts beyond per-gate auto-proceed:
522
+ **Exception: `/skf-quick-skill` headless emits structured progress and result envelopes.** Headless `/skf-quick-skill` runs are first-class building blocks for batch automators. Four operational contracts go beyond per-gate auto-proceed:
407
523
 
408
- 1. **Per-step JSON progress events to `stderr`** at each step's entry / exit / HARD HALT — one line per event, no pretty-print:
524
+ 1. **Per-step JSON progress events to `stderr`** at each step's entry, exit and HARD HALT, one line per event, with no pretty-printing:
409
525
 
410
526
  ```
411
527
  {"step":3,"name":"quick-extract","status":"start"}
@@ -420,19 +536,24 @@ Parent skills and CI pipelines `grep` one line out of the workflow log to learn
420
536
  | Code | Meaning |
421
537
  | ---- | ------------------- |
422
538
  | 0 | success |
539
+ | 2 | input-invalid |
423
540
  | 3 | resolution-failure |
424
541
  | 4 | write-failure |
425
542
  | 5 | overwrite-cancelled |
426
543
  | 6 | user-cancelled |
427
544
  | 7 | finalize-blocked |
545
+ | 8 | ecosystem-redirect |
546
+ | 9 | state-conflict |
428
547
 
429
- 3. **Error-variant result contract on every HARD HALT.** A `SKF_QUICK_SKILL_RESULT_JSON: {…}` envelope is emitted on `stderr` (always) and copied to `{skill_package}/quick-skill-result-latest.json` when the skill package is known (HALTs at step 5 §1 onward). The schema and full population rules live in [`src/skf-quick-skill/SKILL.md`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/skf-quick-skill/SKILL.md) § "Result Contract on HARD HALT".
548
+ 3. **Error-variant result contract on every HARD HALT.** A `SKF_QUICK_SKILL_RESULT_JSON: {…}` envelope is emitted on `stderr` (always) and copied to `{skill_package}/quick-skill-result-latest.json` once the skill package holds `metadata.json` (any HALT from the write step onward, except the exit `9` ownership halt, which writes nothing on disk). The full population rules live in [`src/skf-quick-skill/references/halt-contract.md`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/skf-quick-skill/references/halt-contract.md) § "Result Contract on HARD HALT", and the envelope's schema is [`src/shared/scripts/schemas/skf-quick-skill-result-envelope.v1.json`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/shared/scripts/schemas/skf-quick-skill-result-envelope.v1.json).
430
549
 
431
- **Batch mode (`--batch <file>`).** Drives N targets through the full pipeline (steps 1–7 each) in sequence. Input format: one target per line, `#` comments and blank lines ignored, optional per-line modifiers `language=<lang>` and `scope=<path>`. Per-target output lands in `{skill_package}/` as today; an aggregated summary writes to `{skills_output_folder}/_batch/quick-skill-batch-{ts}.json` (with `quick-skill-batch-latest.json` copy). Per-target boundary events (`{"batch":N,"target":"…","status":"start|done|fail",…}`) and a final `{"batch_summary":true,…}` event extend the per-step event stream above. Full input grammar, summary schema, and exit-code semantics in [`src/skf-quick-skill/SKILL.md`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/skf-quick-skill/SKILL.md) § "Batch Mode".
550
+ 4. **Success result contract.** A finished run prints one `SKF_QUICK_SKILL_RESULT_JSON: {…}` line on `stdout`. Its `summary` carries `quality_score` (the skill-check score of the written package, not a Test Skill score), `validation_issues`, `repo_shape`, `language_resolution` and `active_pointer`, beside the top-level `headless_decisions` and `warnings`, such as `also_found_in` when a headless run kept the first registry's pick of a package name another registry also holds. The run also writes `quick-skill-result-latest.json` in the skill package.
432
551
 
433
- **Exception — `/skf-brief-skill` headless emits a final result envelope and supports presets.** Headless `/skf-brief-skill` is a first-class building block for scripted brief generation (e.g. seeding briefs for N SaaS SDKs that share scope/authority defaults). Three operational contracts beyond per-gate auto-proceed:
552
+ **Batch mode (`--batch <file>`).** Drives N targets in sequence: each target runs steps 1 to 6, and the health check runs once, after the batch summary. Input format: one target per line, `#` comments and blank lines ignored, optional per-line modifiers `language=<lang>` and `scope=<path>`. Each target's output lands in its own `{skill_package}/`; an aggregated summary writes to `{skills_output_folder}/_batch/quick-skill-batch-{ts}.json` (with `quick-skill-batch-latest.json` copy). Per-target boundary events (`{"batch":N,"target":"…","status":"start|done|fail",…}`) and a final `{"batch_summary":true,…}` event extend the per-step event stream above. The batch exits with the highest exit code among its failed targets (`0` when none failed); `--fail-fast` stops it at the first failed target and exits with that target's code. A batch refused before its first target writes no summary and exits `2`, or `4` when its run folder cannot be written. Full input grammar, summary schema, and exit-code rules in [`src/skf-quick-skill/references/batch-mode.md`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/skf-quick-skill/references/batch-mode.md).
434
553
 
435
- 1. **Pre-supplied inputs replace prompts.** Headless args are consumed at step 1's GATE in place of the interactive menus: `target_repo`, `skill_name`, `target_version`, `language`, `source_type`, `source_authority`, `doc_urls`, `scope_type`, `scripts_intent`, `force`, `preset`. Required-arg shape depends on `source_type` (`target_repo` + `skill_name` for source-backed; `doc_urls` + `skill_name` for `docs-only`). Absent `source_authority` and `scope_type` are NOT guessed — they're resolved by signal-driven detection (`gh api user` vs. repo owner for authority; the 5-rule heuristic ladder for scope). Full grammar in [`src/skf-brief-skill/references/headless-args.md`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/skf-brief-skill/references/headless-args.md).
554
+ **Exception: `/skf-brief-skill` headless emits a final result envelope and supports presets.** Headless `/skf-brief-skill` is a first-class building block for scripted brief generation (for example, seeding briefs for N SaaS SDKs that share scope and authority defaults). Three operational contracts go beyond per-gate auto-proceed:
555
+
556
+ 1. **Pre-supplied inputs replace prompts.** Headless arguments are read at step 1's gate in place of the interactive menus: `target_repo`, `skill_name`, `from_brief`, `target_version`, `language_hint`, `scope_hint`, `source_type`, `source_authority`, `doc_urls`, `scope_type`, `include`, `exclude`, `scripts_intent`, `assets_intent`, `intent`, `force`, `preset`. Which arguments are required depends on what you ask for: `target_repo` and `skill_name` for a new brief, plus `doc_urls` when `source_type` is `docs-only`, or only `from_brief` to review an existing brief and write it to `forge-data/<name>/skill-brief.yaml`, in place when it already lives there (another brief already at that path needs `force`). SKF never guesses a missing `source_authority` or `scope_type`. It detects them from signals instead: `gh api user` against the repo owner for authority, and a five-rule heuristic ladder for scope. Without `include`, each `scope_type` takes a default, which the envelope's `warnings` names (`warn: headless boundary default <type>: ...`): `full-library` takes the modules the analysis found; `public-api` the files that define the names the entry points export, or the full-library boundaries when those cannot be traced; `component-library` the full-library boundaries plus the registry and demo patterns and every design-system variant; `specific-modules` the modules `intent` or `scope_hint` names. A `specific-modules` type that came only from the module-count rule falls back to full-library and records that in `scope.rationale`. `scope_type=reference-app` without `include`, and `scope_type=specific-modules` naming no module, halt with `input-missing` (exit `2`). Full grammar in [`src/skf-brief-skill/references/headless-args.md`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/skf-brief-skill/references/headless-args.md).
436
557
 
437
558
  2. **Structured exit-code map.** Every HARD HALT exits with a stable code so pipelines branch on the failure class without grepping message text:
438
559
 
@@ -445,49 +566,92 @@ Parent skills and CI pipelines `grep` one line out of the workflow log to learn
445
566
  | 5 | overwrite-cancelled |
446
567
  | 6 | user-cancelled |
447
568
 
448
- 3. **Final result envelope on every terminal exit.** Step-05 emits a single-line `SKF_BRIEF_RESULT_JSON: {…}` envelope on **stdout** before chaining to step 6 on success; every HARD HALT emits the same envelope shape on **stderr** with `status: "error"` and a typed `halt_reason` (`input-missing`, `input-invalid`, `forge-tier-missing`, `target-inaccessible`, `gh-auth-failed`, `write-failed`, `overwrite-cancelled`, `user-cancelled`). Full envelope schema and population rules in [`src/skf-brief-skill/SKILL.md`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/skf-brief-skill/SKILL.md) § "Result Contract (Headless)".
569
+ 3. **Final result envelope on every terminal exit.** Step 5 emits a single-line `SKF_BRIEF_RESULT_JSON: {…}` envelope on **stdout** on success, held until the health check, which displays it as the run's last line; every HARD HALT emits the same envelope shape on **stderr** with `status: "error"` and a typed `halt_reason` (`input-missing`, `input-invalid`, `forge-tier-missing`, `target-inaccessible`, `gh-auth-failed`, `write-failed`, `overwrite-cancelled`, `user-cancelled`). Full envelope schema and population rules in [`src/skf-brief-skill/references/invocation-contract.md`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/skf-brief-skill/references/invocation-contract.md) § "Result Contract (Headless)".
570
+
571
+ **Presets (`--preset <name>`).** Loads `{sidecar_path}/brief-presets/{name}.yaml` and merges its keys as defaults when Brief Skill reads the headless arguments, before it checks them. Headless arguments you pass explicitly override preset values. The preset file is YAML holding any subset of the headless arguments above; unknown fields are ignored with a warning. Presets help with repeated patterns, for example briefing 5 SaaS SDKs that all share `source_authority=community`, `scope_type=full-library` and `scripts_intent=none`.
572
+
573
+ **Other workflows emit result envelopes too.** In headless mode, AN, US, SS, AS, TS, VS, EX and campaign each print a single-line result envelope when they finish or halt: `SKF_ANALYZE_RESULT_JSON`, `SKF_UPDATE_RESULT_JSON`, `SKF_STACK_RESULT_JSON`, `SKF_AUDIT_RESULT_JSON`, `SKF_TEST_RESULT_JSON`, `SKF_VERIFY_STACK_RESULT_JSON`, `SKF_EXPORT_RESULT_JSON` and `SKF_CAMPAIGN_RESULT_JSON`. CS prints one `SKF_CREATE_SKILL_RESULT_JSON` line per finished brief on stdout (each `--batch` brief included) and one on stderr at every HARD HALT, in every mode, and once the skill's version folder under `forge_data_folder` exists (every finished brief, and a halt after step 7 creates it) writes `create-skill-result-<timestamp>.json` and its `-latest.json` copy there. SS checks its line against [`src/shared/scripts/schemas/skf-stack-result-envelope.v1.json`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/shared/scripts/schemas/skf-stack-result-envelope.v1.json). Drop Skill, Rename Skill and Refine Architecture, described below, each emit a single-line `SKF_*_RESULT_JSON: {…}` envelope on every terminal exit (`status: "success"` on the happy path, `status: "error"` with a typed `halt_reason` on any HARD HALT) and exit with a stable code, so automators branch on the failure class without grepping message text. All three honour the universal `cancel`/`exit`/`:q` affordance at any prompt (exit `6`, `halt_reason: "user-cancelled"`).
574
+
575
+ - **`/skf-drop-skill` (DS)**: exit `2` `input-missing`/`input-invalid` (including `--mode deprecate` on a skill with no manifest entry), `3` resolution-failure (`manifest-corrupt`, `nothing-to-drop`), `4` write-failure (`manifest-write-failed`, `context-rebuild-failed`, `delete-failed` for a failed full purge, `write-failed`), `5` state-conflict (`active-version-guard-refused`; `not-skf-output` for a folder SKF did not generate, a purge it cannot confirm, or a skill whose folder in `forge_data_folder` also holds other files), `6` `user-cancelled` or `headless-purge-forbidden`. Besides `status`, `exit_code` and `halt_reason`, the envelope carries `would_delete` (in a dry run of a purge, the folders the purge would delete), `result_path` (the per-run result file, `null` for a dry run or a halt) and `error` (the `phase` and `reason` of a halt). A `success` drop can still carry `warnings` that name what needs a manual fix (`context_rebuild_failed`, `active_link_dangling`, `delete_failed`, `verification_failed`), and any run can carry `customization_resolver_unavailable` when the customization resolver could not run. Exit codes in [`src/skf-drop-skill/references/invocation-contract.md`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/skf-drop-skill/references/invocation-contract.md) § "Exit Codes"; the envelope and full `halt_reason` list in the same file's § "Result Contract (Headless)".
576
+ - **`/skf-rename-skill` (RS)**: exit `2` `input-missing`/`input-invalid`, `3` resolution-failure (`manifest-corrupt`, `nothing-to-rename`), `4` write-failure (`copy-failed`, `write-failed`, `manifest-write-failed`; the context-file rebuild is best-effort and never halts), `5` state-conflict (`name-collision`, `source-authority-blocked`, `halted-for-concurrent-run` while another rename of the same skill holds its run lock or when this run's own lock went stale while it waited at a prompt, `not-skf-output` for a folder SKF did not generate, or a forge folder that also holds other files or that is a link, is not a folder, or cannot be listed; `flat-layout` for a skill not yet migrated; `verify-failed` when the old name is still in the renamed files, which rolls the rename back with the old skill intact, see [Troubleshooting](/docs/troubleshooting.md)). The run lock is `.skf-rename-<name>.lock` in `forge_data_folder`, and it goes stale 60 minutes after it was taken or renewed: when no other rename of that skill is running, delete the lock file the message names, or wait until the time it gives, then run the rename again. When this run's own lock went stale at a prompt, nothing was changed: run the rename again. Exit codes in [`src/skf-rename-skill/references/exit-codes.md`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/skf-rename-skill/references/exit-codes.md); the envelope in [`src/skf-rename-skill/references/invocation-contract.md`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/skf-rename-skill/references/invocation-contract.md) § "Result Contract (Headless)".
577
+ - **`/skf-refine-architecture` (RA)**: exit `2` `input-missing`/`input-invalid` (`input-invalid` also covers a Verify Stack report with a `schemaVersion` other than `1.0`, a missing or doubled verdict table, or an unknown verdict token), `3` resolution-failure (`output-folder-unconfigured`, `forge-folder-unconfigured`, and `resolution-failure` when the result emitter or `scripts/skf-check-preservation.py` cannot start, when the refinement rules cannot be read, lack one of their six tables or break a tier rule (phase `init:rules`), or when the skill inventory helper (phase `init:inventory`) or the co-mention helper (phase `gap-analysis:comention`) is missing or its call fails, or the Verify Stack report validator (phase `init:feasibility-validator`) is missing), `4` write-failure (`write-failed`, and `preservation-failed` when the draft would lose or change a line of the original: at once in a headless run, or when the promotion still finds it after one rebuild), `5` state-conflict (`insufficient-skills`: no skill SKF generated was found), `7` `inventory-unreliable`, `8` `recovery-failed` (at step 3, the Verify Stack report cannot be read again, Verify Stack rewrote it during the run, or the refinement rules no longer pass step 1's check; the saved state is not enough to rebuild the findings; or a record of the draft's build or promotion is missing at step 6). Exit codes and the envelope in [`src/skf-refine-architecture/references/exit-codes.md`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/skf-refine-architecture/references/exit-codes.md).
578
+
579
+ **Reading the result lines.** Check each line's `status` field first (for US, `skf_update.status`). For most workflows it only says whether the run finished or stopped on an error, so read the outcome from the fields below: a TS run whose skill scores below its threshold still reports `status: "success"`, with `verdict: "FAIL"`. AN, CS, SS, AS, TS, EX and VS also give each outcome a stable exit code, which the line carries as `exit_code` (a CS halt has `2` to `6`).
580
+
581
+ | Workflow | Result line | Fields worth reading |
582
+ | --- | --- | --- |
583
+ | AN | `SKF_ANALYZE_RESULT_JSON` | `brief_paths`, `unit_counts` |
584
+ | CS | `SKF_CREATE_SKILL_RESULT_JSON` | `status`, `exit_code`, `phase`, `summary.halt_reason` |
585
+ | SS | `SKF_STACK_RESULT_JSON` | `mode` (`code` or `compose`), `stack_libraries`, `skill_package`, `quality_score` (the skill-check score SS records for the committed stack, `null` when skill-check did not run; not a Test Skill score), `run_id`, `result_path`, `headless_decisions` and `warnings`, plus `exit_code`, `halt_reason` and `error` on a halt |
586
+ | US | `SKF_UPDATE_RESULT_JSON` | `skf_update.status`: `success`, `no-changes`, `detect-only` and `dry-run` are all good outcomes |
587
+ | AS | `SKF_AUDIT_RESULT_JSON` | `drift_score`, `next_workflow` (`update-skill` whenever upstream moved), `upstream_moved`, `upstream_ref` (a `maintain` pipeline passes it to US as `--target-ref`) |
588
+ | TS | `SKF_TEST_RESULT_JSON` | `verdict`, `score`, `threshold` |
589
+ | EX | `SKF_EXPORT_RESULT_JSON` | `context_files_updated` |
590
+ | VS | `SKF_VERIFY_STACK_RESULT_JSON` | `overall_verdict`, `coverage_percentage` |
449
591
 
450
- **Presets (`--preset <name>`).** Loads `{sidecar_path}/brief-presets/{name}.yaml` and merges its keys as defaults at step 1 §8; explicit headless args override preset values. The preset file is YAML containing any subset of the headless args above; unknown fields are ignored with a warning. Useful for repeated patterns — e.g. briefing 5 SaaS SDKs that all share `source_authority=community`, `scope_type=full-library`, `scripts_intent=skip`.
592
+ To run these without questions, pass their inputs as flags. Analyze Source takes `--project-path`, `--scope-hint` and `--intent-hint`. Both hints apply to an `AN[auto]` run too, and an interactive run defers the units outside `--intent-hint` before step 4 (you can restore them), where a headless run only ranks by it. Analyze Source also takes `--target-ref <ref>`, one tag or branch for every project path, written into every brief (not with `[auto]`, which pins with `--pin`), or `--target-refs <path:ref,...>`, one ref per path, written into each unit's brief (not with `--target-ref` or `[auto]`). Verify Stack takes `--architecture-doc`, `--prd` and `--previous-report`. Refine Architecture takes `--architecture-doc`, `--vs-report-path` and `--scope-skills`.
451
593
 
452
- **Exception — the management and verification workflows emit structured result envelopes too.** Beyond per-gate auto-proceed, Drop Skill, Rename Skill, and Refine Architecture each emit a single-line `SKF_*_RESULT_JSON: {…}` envelope on every terminal exit (`status: "success"` on the happy path, `status: "error"` with a typed `halt_reason` on any HARD HALT) and exit with a stable code so automators branch on the failure class without grepping message text. All three honour the universal `cancel`/`exit`/`:q` affordance at any prompt (exit `6`, `halt_reason: "user-cancelled"`).
594
+ ---
595
+
596
+ ## Customizing a Workflow
597
+
598
+ Every workflow ships a `customize.toml` with settings you can change. Do not edit that file: updates overwrite it. Put your changes in `_bmad/custom/<skill-name>.toml` (shared with your team) or `_bmad/custom/<skill-name>.user.toml` (just for you), for example `_bmad/custom/skf-test-skill.toml`. Start the file with a `[workflow]` line, as the bundled file does: a setting above it is ignored without a warning. A single value replaces the default; a list adds to it.
599
+
600
+ These overrides are read by BMAD Method's customization script, which the BMAD Method installer adds. Every workflow, and Ferris, runs that script through `uv` when it starts. When the script cannot run, the run prints one warning, `[activation/warn] customization_resolver_unavailable: <reason>`, and uses the bundled defaults, ignoring `_bmad/custom/`. A workflow also adds a warning naming `customization_resolver_unavailable` and its reason to the run's warnings, in the result envelope and result file of a run that writes them (Campaign logs it in its decision log, a `--quiet` or headless Setup Forge run shows it only in its envelope, and an interactive Export Skill run only prints it). In a project with SKF alone, that script is missing, so every run warns `customization_resolver_unavailable: not found` and uses the bundled defaults.
601
+
602
+ Ferris reads `_bmad/custom/skf-forger.toml` and `_bmad/custom/skf-forger.user.toml` the same way when he starts, under an `[agent]` line, as his bundled file does (a `[workflow]` table there is ignored). An override there can add `activation_steps_prepend`, which runs once his config is loaded, `persistent_facts` (a `!` entry drops each earlier entry it names) and `activation_steps_append`, which runs after his greeting. His name, title and the other agent roster values stay as shipped, and he has no `on_complete`. When the script cannot run, the warning line opens his greeting.
453
603
 
454
- - **`/skf-drop-skill` (DS)** — exit `2` `input-missing`/`input-invalid`, `4` `write-failure` (covers manifest-write, context-rebuild, and full-purge `delete-failed`), `5` state-conflict (active-version guard). Schema and `halt_reason` list in [`src/skf-drop-skill/SKILL.md`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/skf-drop-skill/SKILL.md) § "Exit Codes" / "Result Contract (Headless)".
455
- - **`/skf-rename-skill` (RS)** — exit `2` `input-missing`/`input-invalid`, `4` `write-failure` (`copy-failed`, `write-failed`, `manifest-write-failed`; the §7 context rebuild is best-effort and never halts), `5` state-conflict (name-collision, source-authority, concurrent-run lock). Schema in [`src/skf-rename-skill/SKILL.md`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/skf-rename-skill/SKILL.md) § "Exit Codes" / "Result Contract (Headless)".
456
- - **`/skf-refine-architecture` (RA)** — exit `2` `input-missing`/`input-invalid`, `4` `write-failure`, `7` `inventory-unreliable`, `8` `recovery-failed` (durability state insufficient to reconstruct findings, or the compiled doc is missing its `## Refinement Summary`). Schema in [`src/skf-refine-architecture/SKILL.md`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/skf-refine-architecture/SKILL.md) § "Exit Codes" / "Result Contract (Headless)".
604
+ Settings every workflow has:
605
+
606
+ - `persistent_facts`: rules the workflow keeps in mind for the whole run. Every workflow except Setup Forge loads any `project-context.md` in your project by default. In a team or personal override, an entry that starts with `!` drops each earlier entry it names and loads nothing itself. To turn that default off for one workflow, add `persistent_facts = ["!file:{project-root}/**/project-context.md"]` under `[workflow]` in `_bmad/custom/<skill-name>.toml`. Every workflow that loads the default honours such an entry, and Campaign's kickoff loader drops the default from each skill's kickoff the same way.
607
+ - `activation_steps_prepend` and `activation_steps_append`: extra steps to run before or after start-up.
608
+ - `on_complete`: a command to run after the workflow writes its result file, such as a notifier. Every workflow except Campaign, Stack Skill, Verify Stack and Setup Forge (Quick Skill included) calls it with `--result-path=<result file>` (for Brief Skill, the `skill-brief.yaml` it wrote), and the hook is skipped when the emitter wrote no result file. Quick Skill's hook gets `--result-path=<skill package>/quick-skill-result-latest.json`, where the skill package is that file's folder, and is skipped when the emitter wrote no result file, or did not write that `-latest` copy. Campaign passes `--report-path=<report>` when it wrote its report, Stack Skill runs the command with no argument, and Setup Forge and Verify Stack carry it out as an instruction once they finish. A failing command never fails the workflow.
609
+
610
+ Useful settings in specific workflows:
611
+
612
+ - Test Skill `default_threshold`: the pass score when no flag or pipeline sets one (default 80).
613
+ - Drop Skill `forbid_purge_in_headless`: any non-empty value blocks a headless purge (exit `6`, `headless-purge-forbidden`). The drop mode always comes from `--mode` or the prompt. An override file that fails to parse, the team one or your personal one, stops the customization script: the run warns as above and ignores both override files, which leaves the guard off, so write the value quoted, such as `"true"`. Write it as two lines, `[workflow]` then `forbid_purge_in_headless = "true"`.
614
+ - Rename Skill: pass `--acknowledge-official` to let one headless run rename an `official` skill, and the decision is recorded in `headless_decisions`. `force_source_authority_in_headless = "true"` (or the TOML boolean `true`) in a team or personal override is the standing approval for every headless run.
615
+ - Refine Architecture `output_folder_path`: where it writes the refined document and the files beside it. Verify Stack's report always lands in `forge_data_folder`.
616
+ - Refine Architecture `refinement_rules_path`: your own copy of its refinement rules, started from the bundled `references/refinement-rules.md`. It swaps only the six house-style tables (Gap Classification, Issue Classification, Issue Severity, VS Report Integration, Improvement Classification and Improvement Value), and a copy must keep the tier rules, or RA stops at its first step (exit `3`, `resolution-failure`).
617
+ - Verify Stack `persistent_facts`: a fact that gives the other names a document uses for a skill, such as "Our documents call the postgresql skill Postgres or PG.", lets coverage count those names too.
618
+ - `report_template_path` (Verify Stack and Campaign) and the other `*_template_path` settings, such as Test Skill's `test_report_template_path`, Audit Skill's `drift_report_template_path` and Analyze Source's `analysis_report_template_path`, point a workflow at your own copy of a template. `scoring_rules_path` and `output_formats_path` are gone: Test Skill's scripts own its scoring rules.
457
619
 
458
620
  ---
459
621
 
460
622
  ## Terminal Step: Health Check
461
623
 
462
- All 15 workflows above share the same final step — a **health check** defined in [`src/shared/health-check.md`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/shared/health-check.md). This isn't a workflow you invoke directly; there's no command code and no menu entry. Each workflow ends with a dedicated local `step-NN-health-check.md` whose `nextStepFile` points at the shared file, so the health check fires automatically once the main work is done. After the main work is done, Ferris reflects internally on the execution:
624
+ All 15 workflows above share the same final step, a **health check** defined in [`src/shared/health-check.md`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/shared/health-check.md). This isn't a workflow you invoke directly; there's no command code and no menu entry. Each workflow ends with a local relay step, `references/health-check.md`, which points at the shared file, so the health check fires automatically once the main work is done. Ferris then reflects internally on the run:
463
625
 
464
626
  - Did any step instruction lead the agent astray or cause unnecessary back-and-forth?
465
627
  - Was any step ambiguous, forcing the agent to guess?
466
628
  - Did a scenario arise that the workflow didn't account for?
467
629
  - Were any instructions wrong or contradictory?
468
630
 
469
- If the answer to all of these is "no", the health check exits in one line (`Clean run. No workflow issues to report.`). If real friction was observed, Ferris presents structured findings, waits for your review, and — on your approval — routes them to this repo.
631
+ If the answer to all of these is "no", the health check ends with one line (`Health Check: Clean run. No workflow issues to report.`). If real friction was observed, Ferris presents structured findings, waits for your review and, on your approval, routes them to this repo.
632
+
633
+ In headless mode the review gate takes its listed default, **[Q] Queue locally**: every finding is saved to `{forge_data_folder}/improvement-queue/` and nothing is submitted. Under `/skf-setup --headless` or `--quiet` the health check displays nothing of its own: it closes setup with the setup envelope, and any findings go to the local queue for you to review later.
470
634
 
471
635
  **Zero overhead for clean runs. High leverage when something breaks.** The health check is honest-by-default: zero findings is the expected outcome. Fabricated issues would hurt the signal, so Ferris only reports what the agent actually experienced.
472
636
 
473
637
  ### How findings are routed
474
638
 
475
- - **Severity gate.** Only `bug` findings submit live as GitHub issues by default. `friction` and `gap` findings — the most subjective categories — go to a **local queue** at `{forge_data_folder}/improvement-queue/` unless you explicitly opt in to submit them live during the review gate. This keeps the high-signal reports (real defects) flowing to maintainers while the softer observations sit safely on your disk for you to batch or revisit.
476
- - **Fingerprint dedup.** Every finding gets a deterministic 7-hex fingerprint computed from `sha1(severity|workflow|step_file|section)` — no LLM similarity judgment, just a tuple hash. Before Ferris opens a new issue, it searches the repo for an existing open issue with the same `fp-*` label. If one exists, you're offered a choice: add a 👍 reaction (silent upvote), react + post a one-sentence environment delta, open a new issue anyway (if you're certain it's distinct), or skip. Re-reporting the same fingerprint is safe — it just adds to the signal-count on the canonical issue.
639
+ - **Severity gate.** Only `bug` findings are submitted live as GitHub issues by default. `friction` and `gap` findings, the most subjective categories, go to a **local queue** at `{forge_data_folder}/improvement-queue/` unless you explicitly opt in to submit them live during the review gate. This keeps the high-signal reports (real defects) flowing to maintainers while the softer observations stay on your disk for you to batch or revisit.
640
+ - **Fingerprint dedup.** Every finding gets a 7-character fingerprint, a `sha1` hash of `severity|workflow|step_file|section`, so the same finding always gets the same fingerprint, with no LLM similarity judgment. Before Ferris opens a new issue, it searches the repo for an open issue whose title carries the same fingerprint. If one exists, you choose: add a 👍 reaction (silent upvote), react and post a one-sentence note on how your environment differs, open a new issue anyway (only if you're certain it's distinct), or skip. Re-reporting the same fingerprint is safe: it just adds to the signal count on the canonical issue.
477
641
  - **Global seen-cache.** Once you've submitted or reacted for a given fingerprint, it's recorded at `~/.skf/health-check-seen.json` so the same user doesn't re-report the same defect across sessions or across different projects on the same machine, for as long as the issue it points at stays open. Once that issue is closed as completed, the suppression lifts on purpose: a fresh sighting of a fixed defect is a regression, and it gets reported and linked back to the original.
478
642
  - **Server-side safety net.** If two users race past the client-side search and both open issues with the same fingerprint, a GitHub Action on this repo catches it: the later issue is auto-closed as a duplicate, linked to the canonical (lowest-numbered) issue, and a 👍 is added there to preserve the signal-count. Manual filers using the [issue template](https://github.com/armelhbobdad/bmad-module-skill-forge/issues/new/choose) feed the same pipeline.
479
643
 
480
- **Net effect:** 1,000 users hitting the same bug produce **one canonical issue** with a reaction-count of roughly 1,000 — not 1,000 duplicate issues or a 1,000-comment thread. The maintainer sees population impact at a glance, and your report is never lost.
644
+ **Net effect:** 1,000 users hitting the same bug produce **one canonical issue** with a reaction count of roughly 1,000, not 1,000 duplicate issues or a 1,000-comment thread. The maintainer sees population impact at a glance, and your report is never lost.
481
645
 
482
646
  ### Please let workflows run to completion
483
647
 
484
- If you cancel a workflow early, or interrupt the agent before the terminal step, the health check doesn't run — and any friction from that session is lost. When you have time, let each workflow reach its natural end. The health check is how SKF learns to do better.
648
+ If you cancel a workflow early, or interrupt the agent before the terminal step, the health check doesn't run, and any friction from that session is lost. When you have time, let each workflow reach its natural end. The health check is how SKF learns to do better.
485
649
 
486
650
  ### If the health check didn't run
487
651
 
488
652
  You have two recovery options:
489
653
 
490
- 1. **Ask Ferris to run it now** — while the session context is still fresh:
654
+ 1. **Ask Ferris to run it now**, while the session context is still fresh:
491
655
 
492
656
  ```
493
657
  @Ferris please run the workflow health check for this session
@@ -495,8 +659,8 @@ You have two recovery options:
495
659
 
496
660
  Ferris will load `shared/health-check.md` and reflect on what just happened, exactly as if the workflow had reached its natural end.
497
661
 
498
- 2. **Open an issue directly** — use the [Workflow Health Check issue template](https://github.com/armelhbobdad/bmad-module-skill-forge/issues/new/choose) on this repo. Any concrete, evidence-based report helps — cite the specific step file and section where the friction occurred, and describe what you actually observed (not what you think the problem is).
662
+ 2. **Open an issue directly** with the [Workflow Health Check issue template](https://github.com/armelhbobdad/bmad-module-skill-forge/issues/new/choose) on this repo. Any concrete, evidence-based report helps: cite the specific step file and section where the friction occurred, and describe what you actually observed (not what you think the problem is).
499
663
 
500
- Both paths feed the same improvement queue.
664
+ Option 1 routes findings the same way a normal health check does (a GitHub issue, or your local queue). With option 2, you file the issue on GitHub yourself.
501
665
 
502
- > **Note:** Some gates cannot be skipped even in headless mode — for example, merge conflicts in Update Skill always require human judgment.
666
+ > **Note:** Some gates cannot be skipped even in headless mode. For example, merge conflicts in Update Skill always need human judgment.