bmad-module-skill-forge 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (235) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.nvmrc +1 -1
  3. package/docs/_data/pinned.yaml +1 -1
  4. package/package.json +2 -2
  5. package/src/knowledge/skill-lifecycle.md +1 -1
  6. package/src/module-help.csv +2 -2
  7. package/src/shared/scripts/skf-comention-pairs.py +350 -0
  8. package/src/shared/scripts/skf-count-tokens.py +222 -0
  9. package/src/shared/scripts/skf-detect-docs.py +232 -1
  10. package/src/shared/scripts/skf-detect-language.py +77 -0
  11. package/src/shared/scripts/skf-detect-tools.py +105 -2
  12. package/src/shared/scripts/skf-enumerate-stack-skills.py +111 -2
  13. package/src/shared/scripts/skf-find-cycles.py +246 -0
  14. package/src/shared/scripts/skf-hash-content.py +487 -2
  15. package/src/shared/scripts/skf-manifest-ops.py +67 -1
  16. package/src/shared/scripts/skf-rebuild-managed-sections.py +180 -0
  17. package/src/shared/scripts/skf-recommend-scope-type.py +1 -2
  18. package/src/shared/scripts/skf-render-metadata-stats.py +499 -0
  19. package/src/shared/scripts/skf-rewrite-skill-name.py +308 -0
  20. package/src/shared/scripts/skf-shard-body.py +461 -0
  21. package/src/shared/scripts/skf-skill-inventory.py +139 -3
  22. package/src/shared/scripts/skf-structural-diff.py +307 -67
  23. package/src/shared/scripts/skf-validate-brief-schema.py +39 -1
  24. package/src/shared/scripts/skf-validate-feasibility-report.py +234 -0
  25. package/src/shared/scripts/skf-validate-frontmatter.py +17 -12
  26. package/src/shared/scripts/skf-validate-output.py +443 -10
  27. package/src/shared/scripts/skf-validate-pins.py +1 -1
  28. package/src/shared/scripts/skf-verify-no-trace.py +214 -0
  29. package/src/shared/scripts/skf-verify-provenance-completeness.py +439 -0
  30. package/src/skf-analyze-source/SKILL.md +17 -32
  31. package/src/skf-analyze-source/customize.toml +2 -0
  32. package/src/skf-analyze-source/references/auto-docs-only.md +116 -0
  33. package/src/skf-analyze-source/references/continue.md +8 -13
  34. package/src/skf-analyze-source/references/generate-briefs.md +28 -12
  35. package/src/skf-analyze-source/references/headless-contract.md +33 -0
  36. package/src/skf-analyze-source/references/health-check.md +1 -2
  37. package/src/skf-analyze-source/references/identify-units.md +25 -36
  38. package/src/skf-analyze-source/references/init.md +12 -25
  39. package/src/skf-analyze-source/references/map-and-detect.md +8 -20
  40. package/src/skf-analyze-source/references/recommend.md +4 -14
  41. package/src/skf-analyze-source/references/scan-project.md +3 -11
  42. package/src/skf-analyze-source/references/step-auto-scope.md +42 -180
  43. package/src/skf-analyze-source/references/unit-detection-heuristics.md +2 -2
  44. package/src/skf-audit-skill/SKILL.md +9 -6
  45. package/src/skf-audit-skill/customize.toml +2 -0
  46. package/src/skf-audit-skill/references/init.md +58 -32
  47. package/src/skf-audit-skill/references/re-index.md +15 -34
  48. package/src/skf-audit-skill/references/report.md +11 -58
  49. package/src/skf-audit-skill/references/semantic-diff.md +4 -22
  50. package/src/skf-audit-skill/references/severity-classify.md +53 -87
  51. package/src/skf-audit-skill/references/step-doc-drift.md +49 -19
  52. package/src/skf-audit-skill/references/structural-diff.md +43 -68
  53. package/src/skf-brief-skill/SKILL.md +7 -36
  54. package/src/skf-brief-skill/assets/scope-templates.md +1 -1
  55. package/src/skf-brief-skill/customize.toml +14 -0
  56. package/src/skf-brief-skill/references/analyze-target.md +6 -14
  57. package/src/skf-brief-skill/references/confirm-brief.md +2 -14
  58. package/src/skf-brief-skill/references/draft-checkpoint.md +8 -8
  59. package/src/skf-brief-skill/references/gather-intent.md +19 -22
  60. package/src/skf-brief-skill/references/headless-args.md +1 -1
  61. package/src/skf-brief-skill/references/health-check.md +1 -22
  62. package/src/skf-brief-skill/references/invocation-contract.md +37 -0
  63. package/src/skf-brief-skill/references/scope-definition.md +4 -14
  64. package/src/skf-brief-skill/references/step-auto-brief.md +1 -5
  65. package/src/skf-brief-skill/references/step-auto-validate.md +1 -5
  66. package/src/skf-brief-skill/references/version-resolution.md +1 -1
  67. package/src/skf-brief-skill/references/write-brief.md +17 -10
  68. package/src/skf-campaign/SKILL.md +15 -84
  69. package/src/skf-campaign/customize.toml +2 -0
  70. package/src/skf-campaign/manifest.yaml +4 -0
  71. package/src/skf-campaign/references/campaign-contracts.md +67 -0
  72. package/src/skf-campaign/references/campaign-directive-spec.md +14 -103
  73. package/src/skf-campaign/references/step-01-setup.md +4 -5
  74. package/src/skf-campaign/references/step-02-strategy.md +8 -3
  75. package/src/skf-campaign/references/step-03-pins.md +1 -1
  76. package/src/skf-campaign/references/step-04-provenance.md +1 -1
  77. package/src/skf-campaign/references/step-05-skill-loop.md +1 -1
  78. package/src/skf-campaign/references/step-06-batch.md +7 -6
  79. package/src/skf-campaign/references/step-11-maintenance.md +2 -2
  80. package/src/skf-campaign/references/step-resume.md +9 -8
  81. package/src/skf-campaign/scripts/campaign-deps.py +10 -1
  82. package/src/skf-campaign/scripts/campaign-render-batch.py +199 -0
  83. package/src/skf-campaign/scripts/campaign-status.py +162 -0
  84. package/src/skf-campaign/templates/campaign-brief-template.yaml +1 -1
  85. package/src/skf-create-skill/SKILL.md +14 -3
  86. package/src/skf-create-skill/assets/compile-assembly-rules.md +17 -38
  87. package/src/skf-create-skill/assets/skill-sections.md +9 -100
  88. package/src/skf-create-skill/assets/tessl-dismissal-rules.md +4 -13
  89. package/src/skf-create-skill/customize.toml +13 -0
  90. package/src/skf-create-skill/references/authoritative-files-protocol.md +7 -7
  91. package/src/skf-create-skill/references/compile.md +34 -47
  92. package/src/skf-create-skill/references/component-extraction.md +8 -35
  93. package/src/skf-create-skill/references/ecosystem-check.md +9 -25
  94. package/src/skf-create-skill/references/enrich.md +4 -17
  95. package/src/skf-create-skill/references/extract.md +14 -29
  96. package/src/skf-create-skill/references/extraction-patterns-tracing.md +1 -1
  97. package/src/skf-create-skill/references/extraction-patterns.md +7 -7
  98. package/src/skf-create-skill/references/generate-artifacts.md +9 -23
  99. package/src/skf-create-skill/references/health-check.md +1 -1
  100. package/src/skf-create-skill/references/load-brief.md +16 -18
  101. package/src/skf-create-skill/references/report.md +12 -15
  102. package/src/skf-create-skill/references/source-resolution-protocols.md +3 -3
  103. package/src/skf-create-skill/references/step-auto-shard.md +52 -25
  104. package/src/skf-create-skill/references/step-doc-rot.md +30 -12
  105. package/src/skf-create-skill/references/step-doc-sources.md +2 -2
  106. package/src/skf-create-skill/references/sub/ccc-discover.md +2 -13
  107. package/src/skf-create-skill/references/sub/fetch-docs.md +8 -50
  108. package/src/skf-create-skill/references/sub/fetch-temporal.md +5 -20
  109. package/src/skf-create-skill/references/tier-degradation-rules.md +6 -8
  110. package/src/skf-create-skill/references/validate.md +59 -28
  111. package/src/skf-create-skill/scripts/scan-doc-rot.py +245 -0
  112. package/src/skf-create-stack-skill/SKILL.md +15 -9
  113. package/src/skf-create-stack-skill/assets/provenance-map-schema.md +1 -1
  114. package/src/skf-create-stack-skill/customize.toml +10 -0
  115. package/src/skf-create-stack-skill/references/compile-stack.md +7 -8
  116. package/src/skf-create-stack-skill/references/compose-mode-rules.md +2 -13
  117. package/src/skf-create-stack-skill/references/detect-integrations.md +49 -54
  118. package/src/skf-create-stack-skill/references/detect-manifests.md +37 -30
  119. package/src/skf-create-stack-skill/references/generate-output.md +24 -75
  120. package/src/skf-create-stack-skill/references/init.md +9 -81
  121. package/src/skf-create-stack-skill/references/manifest-patterns.md +5 -35
  122. package/src/skf-create-stack-skill/references/parallel-extract.md +12 -27
  123. package/src/skf-create-stack-skill/references/rank-and-confirm.md +6 -6
  124. package/src/skf-create-stack-skill/references/report.md +27 -62
  125. package/src/skf-create-stack-skill/references/validate.md +35 -31
  126. package/src/skf-drop-skill/SKILL.md +20 -23
  127. package/src/skf-drop-skill/customize.toml +10 -0
  128. package/src/skf-drop-skill/references/execute.md +51 -31
  129. package/src/skf-drop-skill/references/headless-contract.md +18 -0
  130. package/src/skf-drop-skill/references/health-check.md +1 -13
  131. package/src/skf-drop-skill/references/report.md +42 -10
  132. package/src/skf-drop-skill/references/select.md +88 -48
  133. package/src/skf-drop-skill/scripts/dir-sizes.py +116 -0
  134. package/src/skf-export-skill/SKILL.md +17 -14
  135. package/src/skf-export-skill/assets/managed-section-format.md +2 -5
  136. package/src/skf-export-skill/customize.toml +10 -6
  137. package/src/skf-export-skill/references/generate-snippet.md +21 -35
  138. package/src/skf-export-skill/references/load-skill.md +44 -42
  139. package/src/skf-export-skill/references/multi-skill-mode.md +1 -1
  140. package/src/skf-export-skill/references/orphan-context-detection.md +11 -3
  141. package/src/skf-export-skill/references/package.md +27 -33
  142. package/src/skf-export-skill/references/preflight-snippet-root-probe.md +24 -5
  143. package/src/skf-export-skill/references/result-envelope.md +28 -0
  144. package/src/skf-export-skill/references/summary.md +11 -5
  145. package/src/skf-export-skill/references/token-report.md +42 -24
  146. package/src/skf-export-skill/references/update-context.md +32 -33
  147. package/src/skf-forger/SKILL.md +27 -39
  148. package/src/skf-forger/references/pipeline-mode.md +34 -0
  149. package/src/skf-forger/scripts/parse-pipeline.py +270 -0
  150. package/src/skf-quick-skill/SKILL.md +10 -60
  151. package/src/skf-quick-skill/customize.toml +9 -0
  152. package/src/skf-quick-skill/references/batch-mode.md +6 -4
  153. package/src/skf-quick-skill/references/compile.md +15 -52
  154. package/src/skf-quick-skill/references/ecosystem-check.md +5 -20
  155. package/src/skf-quick-skill/references/finalize.md +12 -6
  156. package/src/skf-quick-skill/references/halt-contract.md +54 -0
  157. package/src/skf-quick-skill/references/health-check.md +3 -4
  158. package/src/skf-quick-skill/references/quick-extract.md +7 -18
  159. package/src/skf-quick-skill/references/registry-resolution.md +1 -23
  160. package/src/skf-quick-skill/references/resolve-target.md +27 -34
  161. package/src/skf-quick-skill/references/write-and-validate.md +10 -25
  162. package/src/skf-refine-architecture/SKILL.md +14 -7
  163. package/src/skf-refine-architecture/customize.toml +9 -0
  164. package/src/skf-refine-architecture/references/compile.md +9 -7
  165. package/src/skf-refine-architecture/references/gap-analysis.md +21 -50
  166. package/src/skf-refine-architecture/references/health-check.md +1 -1
  167. package/src/skf-refine-architecture/references/improvements.md +9 -25
  168. package/src/skf-refine-architecture/references/init.md +9 -16
  169. package/src/skf-refine-architecture/references/issue-detection.md +10 -25
  170. package/src/skf-refine-architecture/references/refinement-rules.md +4 -16
  171. package/src/skf-refine-architecture/references/report.md +13 -10
  172. package/src/skf-rename-skill/SKILL.md +11 -21
  173. package/src/skf-rename-skill/customize.toml +10 -0
  174. package/src/skf-rename-skill/references/execute.md +107 -78
  175. package/src/skf-rename-skill/references/exit-codes.md +12 -0
  176. package/src/skf-rename-skill/references/report.md +16 -8
  177. package/src/skf-rename-skill/references/select.md +69 -42
  178. package/src/skf-rename-skill/scripts/skf-validate-rename-name.py +161 -0
  179. package/src/skf-setup/SKILL.md +20 -12
  180. package/src/skf-setup/customize.toml +10 -0
  181. package/src/skf-setup/references/auto-index.md +9 -10
  182. package/src/skf-setup/references/ccc-index.md +14 -15
  183. package/src/skf-setup/references/detect-and-tier.md +6 -8
  184. package/src/skf-setup/references/report.md +22 -31
  185. package/src/skf-setup/references/tier-rules.md +2 -32
  186. package/src/skf-setup/references/write-config.md +9 -10
  187. package/src/skf-test-skill/SKILL.md +10 -8
  188. package/src/skf-test-skill/customize.toml +2 -0
  189. package/src/skf-test-skill/references/coherence-check.md +19 -31
  190. package/src/skf-test-skill/references/coverage-check.md +109 -75
  191. package/src/skf-test-skill/references/detect-mode.md +10 -41
  192. package/src/skf-test-skill/references/external-validators.md +11 -19
  193. package/src/skf-test-skill/references/init.md +38 -20
  194. package/src/skf-test-skill/references/migration-section-rules.md +4 -4
  195. package/src/skf-test-skill/references/report.md +60 -40
  196. package/src/skf-test-skill/references/score.md +32 -64
  197. package/src/skf-test-skill/references/scoring-rules.md +6 -62
  198. package/src/skf-test-skill/references/source-access-protocol.md +6 -6
  199. package/src/skf-test-skill/references/step-hard-gate.md +1 -3
  200. package/src/skf-test-skill/scripts/aggregate-coherence.py +276 -0
  201. package/src/skf-test-skill/scripts/check-metadata-coherence.py +359 -0
  202. package/src/skf-test-skill/scripts/combine-external-scores.py +190 -0
  203. package/src/skf-test-skill/scripts/compute-score.py +131 -1
  204. package/src/skf-test-skill/scripts/reconcile-coverage.py +327 -0
  205. package/src/skf-test-skill/scripts/validate-inventory.py +251 -0
  206. package/src/skf-test-skill/scripts/verify-declared-numerator.py +192 -0
  207. package/src/skf-update-skill/SKILL.md +17 -5
  208. package/src/skf-update-skill/customize.toml +14 -0
  209. package/src/skf-update-skill/references/detect-changes.md +19 -37
  210. package/src/skf-update-skill/references/health-check.md +3 -9
  211. package/src/skf-update-skill/references/init.md +39 -32
  212. package/src/skf-update-skill/references/manual-section-rules.md +1 -2
  213. package/src/skf-update-skill/references/merge-conflict-rules.md +1 -52
  214. package/src/skf-update-skill/references/merge.md +13 -57
  215. package/src/skf-update-skill/references/re-extract.md +12 -24
  216. package/src/skf-update-skill/references/report.md +14 -7
  217. package/src/skf-update-skill/references/validate.md +32 -30
  218. package/src/skf-update-skill/references/write.md +86 -51
  219. package/src/skf-update-skill/scripts/skf-new-file-diff.py +167 -0
  220. package/src/skf-verify-stack/SKILL.md +11 -21
  221. package/src/skf-verify-stack/customize.toml +12 -3
  222. package/src/skf-verify-stack/references/coverage-patterns.md +1 -29
  223. package/src/skf-verify-stack/references/coverage.md +21 -10
  224. package/src/skf-verify-stack/references/exit-codes.md +14 -0
  225. package/src/skf-verify-stack/references/health-check.md +1 -1
  226. package/src/skf-verify-stack/references/init.md +20 -25
  227. package/src/skf-verify-stack/references/integration-verification-rules.md +10 -19
  228. package/src/skf-verify-stack/references/integrations.md +44 -49
  229. package/src/skf-verify-stack/references/report.md +28 -34
  230. package/src/skf-verify-stack/references/requirements.md +3 -3
  231. package/src/skf-verify-stack/references/synthesize.md +36 -39
  232. package/src/skf-verify-stack/scripts/skf-coverage-tally.py +196 -0
  233. package/src/skf-verify-stack/scripts/skf-report-delta.py +256 -0
  234. package/src/skf-verify-stack/scripts/skf-verdict-rollup.py +258 -0
  235. package/src/skf-rename-skill/references/rebuild-context.md +0 -110
@@ -7,7 +7,7 @@ description: Fast skill from a package name or GitHub URL — no brief needed. U
7
7
 
8
8
  ## Overview
9
9
 
10
- The fastest path to a skill — accept a GitHub URL or package name, resolve to source, extract the public API surface, and produce a best-effort SKILL.md with context snippet and metadata. No brief needed. Quick Skill is tier-unaware by design — all output is produced at community-tier quality regardless of available tools.
10
+ The fastest path to a skill — accept a GitHub URL or package name, resolve to source, extract the public API surface, and produce a best-effort SKILL.md with context snippet and metadata. No brief needed. Output is always community-tier quality, regardless of which tools are available.
11
11
 
12
12
  ## Conventions
13
13
 
@@ -28,7 +28,7 @@ These rules apply to every step in this workflow:
28
28
  - Never fabricate content — all data must come from source extraction or user input
29
29
  - Only load one step file at a time — never preload future steps
30
30
  - Always communicate in `{communication_language}`
31
- - **Universal cancel-line affordance** — at any interactive prompt the user may type `cancel`, `exit`, `:q`, or select the `[X] Cancel and exit` menu option (where surfaced) to leave cleanly. HARD HALT with **exit code 6 (user-cancelled)** and emit the error result contract per "Result Contract on HARD HALT" with `error.code: "user-cancelled"`. In step 4 §6 the equivalent affordance is `[Q] Quit without writing` — same exit code, same envelope contract.
31
+ - **Universal cancel-line affordance** — at any interactive prompt the user may type `cancel`, `exit`, `:q`, or select the `[X] Cancel and exit` menu option (where surfaced) to leave cleanly. HARD HALT with **exit code 6 (user-cancelled)** and emit the error result contract per `references/halt-contract.md` with `error.code: "user-cancelled"`. In step 4 §6 the equivalent affordance is `[Q] Quit without writing` — same exit code, same envelope contract.
32
32
  - If `{headless_mode}` is true, auto-proceed through confirmation gates with their default action and log each auto-decision
33
33
  - If `{headless_mode}` is true, emit a single-line JSON progress event to **stderr** at each step's entry and exit so pipeline schedulers can stream live progress instead of post-mortem-parsing the result contract:
34
34
  - entry: `{"step":N,"name":"<slug>","status":"start"}`
@@ -55,61 +55,14 @@ These rules apply to every step in this workflow:
55
55
  |--------|--------|
56
56
  | **Inputs** | target (GitHub URL or package name) [required for single-target mode], language_hint [optional], scope_hint [optional] |
57
57
  | **Overrides** | `--description`, `--exports`, `--skip-snippet`, `--no-active-pointer`, `--batch <file>`, `--fail-fast` — see On Activation step 4 |
58
- | **Gates** | step 1: Input Gate [use args]; step 2: Choice Gate [P] (if match); step 4: Review Gate [C/E/S/Q] |
58
+ | **Gates** | step 1: target input, multi-language disambiguation [C/A]; step 2: ecosystem match [P/I/A] (if match); step 3: repo-shape [C/A] + zero-exports rescue [R/P/A]; step 4: review [C/E/S/Q]; step 5: overwrite [Y/N] |
59
59
  | **Outputs** | SKILL.md, context-snippet.md, metadata.json, active pointer, result contract (timestamped + `-latest` copy). Snippet and active pointer can be skipped per overrides. |
60
60
  | **Headless** | All gates auto-resolve with default action when `{headless_mode}` is true |
61
- | **Exit codes** | See "Exit Codes" below |
61
+ | **Exit codes** | See `references/halt-contract.md` |
62
62
 
63
- ## Exit Codes
63
+ ## Exit Codes & HARD HALT Contract
64
64
 
65
- Every HARD HALT in this workflow exits with a stable, documented code so headless automators can branch on the failure class without grepping message text:
66
-
67
- | Code | Meaning | Raised by |
68
- | ---- | ---------------------- | ----------------------------------------------------------- |
69
- | 0 | success | step 7 (terminal) |
70
- | 3 | resolution-failure | step 1 §2c (prose input), step 1 §3 (registry chain failed) |
71
- | 4 | write-failure | step 5 §2 (deliverable write failed) |
72
- | 5 | overwrite-cancelled | step 5 §1 (user selected [N]) |
73
- | 6 | user-cancelled | step 1 §1 ([X] Cancel and exit, or cancel-line affordance); step 2 §3 ([A] Abort at ecosystem-match gate); step 4 §6 (user selected [Q]) — originally `compile-cancelled`, generalised to cover any interactive gate |
74
- | 7 | finalize-blocked | step 6 §1 (active-pointer flip refused — non-link in place) |
75
- | 8 | ecosystem-redirect | step 2 §3 ([I] Install at ecosystem-match gate — user opted to install the existing official skill instead of compiling a custom community skill) |
76
-
77
- Reserved: `validator-missing` may be promoted from advisory log to fatal exit code in a future revision.
78
-
79
- ## Result Contract on HARD HALT
80
-
81
- In addition to the success-variant result contract written by step 6 §3, every HARD HALT must surface an **error variant** so headless automators don't silently break when `quick-skill-result-latest.json` is missing on failed runs.
82
-
83
- **Always (every HARD HALT, regardless of phase)** — emit a single line on **stderr**:
84
-
85
- ```
86
- SKF_QUICK_SKILL_RESULT_JSON: {"status":"error","exit_code":<N>,"phase":"<slug>","error":{"code":"<class>","message":"<short>"},"outputs":{},"summary":{},"skill_package":"<path-or-null>"}
87
- ```
88
-
89
- One line, no pretty-print. Matches the prefix-and-envelope convention used by `skf-emit-result-envelope.py`.
90
-
91
- **Additionally, when `{skill_package}` is known** (HALT at step 5 §1 onward) — write the same JSON object (without the `SKF_QUICK_SKILL_RESULT_JSON: ` prefix) to disk:
92
-
93
- ```
94
- {skill_package}/quick-skill-result-{YYYYMMDD-HHmmss}.json
95
- {skill_package}/quick-skill-result-latest.json (copy, not symlink)
96
- ```
97
-
98
- so consumers that hardcode the `-latest.json` path see a deterministic file even on failed runs. HALTs at step 1/02/03/04 cannot write to disk because `{skill_package}` is computed only in step 5 §1; for those, the stderr envelope plus exit code is the contract.
99
-
100
- **Schema:**
101
-
102
- | Field | Type | Notes |
103
- | --------------- | -------------- | ----------------------------------------------------------------------------------------------------------- |
104
- | `status` | string | always `"error"` for HARD HALTs |
105
- | `exit_code` | integer | matches the Exit Codes table |
106
- | `phase` | string | step slug where the HALT occurred (e.g. `resolve-target`, `compile`) |
107
- | `error.code` | string | one of: `resolution-failure`, `write-failure`, `overwrite-cancelled`, `user-cancelled` (formerly `compile-cancelled`), `finalize-blocked`, `ecosystem-redirect` |
108
- | `error.message` | string | the user-facing message that was displayed |
109
- | `error.details` | any | optional — phase-specific context (e.g. the failed file path) |
110
- | `outputs` | object | empty `{}` on early HALTs; partial when files were already written |
111
- | `summary` | object | empty `{}` on early HALTs |
112
- | `skill_package` | string \| null | absolute path when known, `null` when HALT preceded step 5 §1 |
65
+ See `references/halt-contract.md` for the exit-code map and the error-result envelope every HARD HALT emits (the `SKF_QUICK_SKILL_RESULT_JSON:` stderr line, the on-disk `-latest.json` write once `{skill_package}` is known, and the schema). Steps load it on their failure path so the wire format survives compaction.
113
66
 
114
67
  ## On Activation
115
68
 
@@ -139,8 +92,11 @@ so consumers that hardcode the `-latest.json` path see a deterministic file even
139
92
  - `{skillTemplatePath}` ← `workflow.skill_template_path` if non-empty, else `assets/skill-template.md`
140
93
  - `{registryResolutionPath}` ← `workflow.registry_resolution_path` if non-empty, else `references/registry-resolution.md`
141
94
  - `{batchOutputPath}` ← `workflow.batch_output_path` if non-empty, else `{skills_output_folder}/_batch/`
95
+ - `{onCompleteCommand}` ← `workflow.on_complete` if non-empty, else empty (no-op — step 6 §3 skips the hook invocation entirely)
142
96
 
143
- Stash all three as workflow-context variables. Stage files reference `{skillTemplatePath}` / `{registryResolutionPath}` / `{batchOutputPath}` directly — no conditional at the usage site. Empty-string overrides cleanly fall through to the bundled default; non-empty values let orgs swap in house-style copies without forking the skill.
97
+ Stash all four as workflow-context variables. Stage files reference `{skillTemplatePath}` / `{registryResolutionPath}` / `{batchOutputPath}` / `{onCompleteCommand}` directly — no conditional at the usage site. Empty-string overrides cleanly fall through to the bundled default; non-empty values let orgs swap in house-style copies (custom template, registry chain, batch output dir) or wire in a post-completion hook (git-add, register, notify) without forking the skill.
98
+
99
+ **Apply the array surfaces** so the declared overrides are not silent no-ops: execute each entry in `workflow.activation_steps_prepend` in order now; treat every entry in `workflow.persistent_facts` as standing context for the whole run (`file:`-prefixed entries are paths or globs whose contents load as facts — the bundled default loads any `project-context.md`); then, after activation completes and before the first stage runs, execute each entry in `workflow.activation_steps_append` in order.
144
100
 
145
101
  4. **Parse CLI overrides** — capture optional override flags into the workflow context as `{overrides}`. Each override is opt-in; when omitted, the workflow runs as today.
146
102
 
@@ -156,9 +112,3 @@ so consumers that hardcode the `-latest.json` path see a deterministic file even
156
112
  5. **If `--batch` is set**, force `{headless_mode} = true` (log "headless: coerced by --batch" if it was false), then load and read `references/batch-mode.md` in full before proceeding. Follow its protocol to read the batch file, parse the target list, and drive the batch loop that wraps the step 1 → step 7 pipeline that follows.
157
113
 
158
114
  6. Load, read the full file, and then execute `references/resolve-target.md` to begin the workflow. (In batch mode, control returns here for each subsequent target after step 7 completes; see `references/batch-mode.md`.)
159
-
160
- ## Batch Mode
161
-
162
- When `--batch <file>` is supplied, quick-skill processes a list of targets from a text file in sequence rather than a single argument.
163
-
164
- See `references/batch-mode.md` for the full protocol (input format, execution loop, summary contract, headless events, exit code).
@@ -1,6 +1,8 @@
1
1
  # DO NOT EDIT -- overwritten on every update.
2
2
  #
3
3
  # Workflow customization surface for skf-quick-skill.
4
+ # Team overrides: _bmad/custom/skf-quick-skill.toml (under {project-root})
5
+ # Personal overrides: _bmad/custom/skf-quick-skill.user.toml (under {project-root})
4
6
 
5
7
  [workflow]
6
8
 
@@ -42,3 +44,10 @@ persistent_facts = [
42
44
  skill_template_path = ""
43
45
  registry_resolution_path = ""
44
46
  batch_output_path = ""
47
+
48
+ # Optional post-completion hook. When non-empty, invoked with
49
+ # `--skill-package=<path>` after the result contract is finalized in step 6.
50
+ # Failures are logged but never fail the workflow. Use for git-add,
51
+ # skill-registry registration, or a notifier on the freshly compiled skill.
52
+
53
+ on_complete = ""
@@ -6,7 +6,7 @@ nextStepFile: 'resolve-target.md'
6
6
 
7
7
  # Batch Mode
8
8
 
9
- When `--batch <file>` is supplied, quick-skill processes a list of targets from a text file in sequence rather than a single target from arguments. Designed for unattended bulk runs (CI pipelines, mass-rebuilds, the skf-batch-skills meta-workflow when it lands).
9
+ When `--batch <file>` is supplied, quick-skill processes a list of targets from a text file in sequence rather than a single target from arguments. Designed for unattended bulk runs CI pipelines, mass-rebuilds, and batch meta-workflows.
10
10
 
11
11
  ## Input format
12
12
 
@@ -43,17 +43,19 @@ Per-line modifiers shadow the global `--description` / `--exports` / `--skip-sni
43
43
  3. After step 7 completes (success or HARD HALT), record the per-target outcome (target, status, exit_code, skill_package, error.code) into the batch result list.
44
44
  4. If `--fail-fast` is set and the target failed, exit the batch loop immediately. Otherwise continue with the next target.
45
45
 
46
- Per-target output lands in `{skill_package}/` as today, with the per-target result contract at `{skill_package}/quick-skill-result-latest.json` (success or error variant per "Result Contract on HARD HALT" above).
46
+ Per-target output lands in `{skill_package}/` as today, with the per-target result contract at `{skill_package}/quick-skill-result-latest.json` (success or error variant per `references/halt-contract.md`).
47
47
 
48
48
  ## Batch summary contract
49
49
 
50
50
  After the last target completes (or `--fail-fast` triggers an early exit), write the batch summary at:
51
51
 
52
52
  ```
53
- {skills_output_folder}/_batch/quick-skill-batch-{YYYYMMDD-HHmmss}.json
54
- {skills_output_folder}/_batch/quick-skill-batch-latest.json (copy, not symlink)
53
+ {batchOutputPath}quick-skill-batch-{YYYYMMDD-HHmmss}.json
54
+ {batchOutputPath}quick-skill-batch-latest.json (copy, not symlink)
55
55
  ```
56
56
 
57
+ `{batchOutputPath}` is resolved at SKILL.md On Activation §3 from `workflow.batch_output_path` (bundled default `{skills_output_folder}/_batch/`, trailing slash included).
58
+
57
59
  Schema:
58
60
 
59
61
  ```json
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  nextStepFile: 'write-and-validate.md'
3
- skillTemplateData: 'assets/skill-template.md'
3
+ skillTemplateData: '{skillTemplatePath}'
4
4
  quickMetadataRendererProbeOrder:
5
5
  - '{project-root}/_bmad/skf/shared/scripts/skf-render-quick-metadata.py'
6
6
  - '{project-root}/src/shared/scripts/skf-render-quick-metadata.py'
@@ -20,7 +20,7 @@ To assemble the best-effort SKILL.md document, context-snippet.md in Vercel-alig
20
20
  - Follow template structure exactly from {skillTemplateData}
21
21
  - Mark any sections with insufficient data as best-effort
22
22
 
23
- ## MANDATORY SEQUENCE
23
+ ## Steps
24
24
 
25
25
  ### 1. Load Skill Template
26
26
 
@@ -31,57 +31,28 @@ Load {skillTemplateData} to understand:
31
31
 
32
32
  ### 2. Assemble SKILL.md
33
33
 
34
- Using the template structure, populate each section from extraction_inventory:
34
+ Populate the SKILL.md section structure from `{skillTemplateData}` § "SKILL.md Section Structure" (the frontmatter skeleton and the Required/Optional section list live there) using extraction_inventory. The rules below are the deltas the template does not encode:
35
35
 
36
- **Frontmatter (REQUIRED — agentskills.io compliance):**
37
-
38
- The SKILL.md MUST begin with YAML frontmatter:
39
-
40
- ```yaml
41
- ---
42
- name: {skill_name}
43
- description: >
44
- {Trigger-optimized description from extraction_inventory.description.
45
- 1-1024 chars. Include what it does, when to use it, and what NOT to use it for.}
46
- ---
47
- ```
48
-
49
- **Frontmatter rules:**
36
+ **Frontmatter rules (agentskills.io compliance):**
50
37
  - `name`: lowercase alphanumeric + hyphens only, must match the skill output directory name. Prefer gerund form (`processing-pdfs`) for clarity.
51
- - `description`: non-empty, max 1024 chars, optimized for agent discovery. MUST use third-person voice ("Processes..." not "I can..." or "You can...").
38
+ - `description`: non-empty, max 1024 chars, optimized for agent discovery. Use third-person voice ("Processes..." not "I can..." / "You can...") so it reads correctly in the agent's skill index.
52
39
  - No other frontmatter fields — only `name` and `description` for community skills
53
40
 
54
- **Required sections (after frontmatter):**
55
- - **Overview:** Package name, repository, language, source authority, generation date
41
+ **Per-section override wiring:**
56
42
  - **Description:** From `{overrides.description}` if set (subject to the same length/voice checks as extracted descriptions); otherwise from extraction_inventory.description (README-derived)
57
43
  - **Key Exports:** From `{overrides.exports}` if set (comma-separated names parsed and trimmed; empty items skipped); otherwise from extraction_inventory.exports — list each with name, type, brief description
58
- - **Usage Patterns:** From extraction_inventory.usage_patterns (README examples)
59
44
 
60
- **Optional sections (include when data available):**
61
- - **Configuration:** If configuration options were found in source
62
- - **Dependencies:** Key dependencies from manifest
63
- - **Notes:** Caveats, limitations, extraction confidence level
64
- - **Scripts & Assets Note** (if source contains `scripts/`, `bin/`, `assets/`, `templates/`, or `schemas/` directories): "This package may include scripts and assets. Run create-skill for full extraction with provenance tracking."
45
+ **Scripts & Assets Note** (add as an optional section if source contains `scripts/`, `bin/`, `assets/`, `templates/`, or `schemas/` directories): "This package may include scripts and assets. Run create-skill for full extraction with provenance tracking."
65
46
 
66
- **If confidence is low:**
67
- - Include a note: "This skill was generated with limited source data. Consider running create-skill for a more thorough compilation."
47
+ **If confidence is low** — include a note: "This skill was generated with limited source data. Consider running create-skill for a more thorough compilation."
68
48
 
69
49
  ### 3. Generate Context Snippet
70
50
 
71
51
  **If `{overrides.skip_snippet}` is true** — skip generation and note in the §5 preview: "context-snippet.md skipped per `--skip-snippet` override." Step-05 §2 will skip the corresponding write; step 5 §5 advisory snippet validation will report a "skipped" entry.
72
52
 
73
- Otherwise, create context-snippet.md in Vercel-aligned indexed format (~80-120 tokens):
53
+ Otherwise, produce context-snippet.md in the Vercel-aligned indexed format from `{skillTemplateData}` § "context-snippet.md Format" (~80-120 tokens).
74
54
 
75
- ```
76
- [{skill_name} v{version}]|root: skills/{skill_name}/
77
- |IMPORTANT: {skill_name} v{version} — read SKILL.md before writing {skill_name} code. Do NOT rely on training data.
78
- |quick-start:{SKILL.md#usage-patterns}
79
- |api: {top-5 exports with () for functions}
80
- |key-types:{SKILL.md#key-exports} — {inline summary of most important type values}
81
- |gotchas: {2-3 most critical pitfalls or breaking changes, inline}
82
- ```
83
-
84
- The anchors point to the QS template's actual headings — `#usage-patterns` (Usage Patterns) and `#key-exports` (Key Exports). The QS template has no `## Quick Start` / `## Key Types` headings (those are Deep-tier sections), so the Deep-tier anchors `#quick-start` / `#key-types` would dangle. If the assembled SKILL.md is missing the referenced heading, omit that line rather than emit a dangling anchor.
55
+ The snippet anchors point to the QS template's actual headings — `#usage-patterns` (Usage Patterns) and `#key-exports` (Key Exports). The QS template has no `## Quick Start` / `## Key Types` headings (those are Deep-tier sections), so the Deep-tier anchors `#quick-start` / `#key-types` would dangle. If the assembled SKILL.md is missing the referenced heading, omit that line rather than emit a dangling anchor.
85
56
 
86
57
  **If fewer than 5 exports:** Use all available exports.
87
58
  **If no exports:** Omit the api line.
@@ -91,7 +62,7 @@ The anchors point to the QS template's actual headings — `#usage-patterns` (Us
91
62
 
92
63
  Run the shared renderer against the assembled state. The helper applies the constants, echoes input-derived fields, computes export counts and the ISO 8601 UTC timestamp, and emits the canonical envelope per `{skillTemplateData}` § "metadata.json Format".
93
64
 
94
- **Resolve `{quickMetadataRenderer}`** from `{quickMetadataRendererProbeOrder}`; first existing path wins. If no candidate exists, fall back to in-prompt rendering using the constants + input-derived rules previously documented in this section (the helper replaces but does not eliminate those rules — they live in the helper now).
65
+ **Resolve `{quickMetadataRenderer}`** from `{quickMetadataRendererProbeOrder}`; first existing path wins. If no candidate exists, fall back to in-prompt rendering of the canonical envelope per `{skillTemplateData}` § "metadata.json Format".
95
66
 
96
67
  **Probe `tool_versions.skf` first** (the helper expects it as input — the filesystem walk stays here because the helper does no I/O):
97
68
 
@@ -108,8 +79,6 @@ echo '{"name":"<name>","version":"<v>","description":"<desc>","language":"<lang>
108
79
 
109
80
  The renderer emits the rendered metadata.json on stdout. Capture the output as `metadata` for the §5 preview and step 5 §2's deliverable write.
110
81
 
111
- **Schema is canonical in the renderer.** When `{skillTemplateData}` adds a field, the renderer is updated to populate it (constants gain a row; input-derived fields gain a payload key). Do not hand-edit the rendered envelope here — the helper is the single source of truth for the population logic.
112
-
113
82
  ### 5. Present Compiled Output for Review
114
83
 
115
84
  **If `{headless_mode}` is true** — skip the inline preview (no human reviewer reads it) and emit a one-line summary instead:
@@ -156,18 +125,12 @@ Display: **Select:** [C] Continue to Validation · [E] Edit description · [S] A
156
125
  - **IF C** — Load, read entire file, then execute {nextStepFile}.
157
126
  - **IF E** — Ask the user for a replacement description ("New description (1–1024 chars):"). Update SKILL.md frontmatter `description` and `metadata.json.description` in the in-memory compiled output, then re-render the §5 preview and redisplay this menu. Do not re-run extraction.
158
127
  - **IF S** — Ask the user for an adjusted `scope_hint` ("New scope (e.g. `src/server/`, `packages/core/`):") and optionally a `language_hint`. Update the extraction context with the new hints, then load `quick-extract.md` to re-extract. The new extraction returns to §1 of this step on completion. Discards the prior compiled output.
159
- - **IF Q** — HARD HALT with **exit code 6 (user-cancelled)** per the SKILL.md exit-code map: "Compilation cancelled. No files written." Before exiting, emit the error result contract per SKILL.md "Result Contract on HARD HALT" (`phase: "compile"`, `error.code: "user-cancelled"`, `skill_package: null`). Do not proceed to validation; do not write any artifacts.
128
+ - **IF Q** — HARD HALT with **exit code 6 (user-cancelled)** per the exit-code map in `references/halt-contract.md`: "Compilation cancelled. No files written." Before exiting, emit the error result contract per `references/halt-contract.md` (`phase: "compile"`, `error.code: "user-cancelled"`, `skill_package: null`). Do not proceed to validation; do not write any artifacts.
160
129
  - **IF Any other** — Help the user adjust the compiled output (treated as a free-form revision request), then redisplay the menu.
161
130
 
162
- #### EXECUTION RULES:
131
+ #### Gate:
163
132
 
164
- - ALWAYS halt and wait for user input after presenting compiled output
133
+ - Halt and wait for user input after presenting the compiled output; only [C] (or a headless auto-approve) chains to `{nextStepFile}` for validation.
165
134
  - **GATE [default: C]** — If `{headless_mode}`: auto-proceed with [C] Continue, log: "headless: auto-approve compiled output"
166
- - ONLY proceed to validation when the user selects 'C' (or headless auto-approve)
167
- - [E] is local: re-renders the preview without re-running extraction
168
- - [S] is the heavy option: it discards the compiled output and re-runs step 3 with new hints
169
-
170
- ## CRITICAL STEP COMPLETION NOTE
171
-
172
- ONLY WHEN the user reviews the compiled output and selects 'C' (or [Q] HALTs / [S] re-runs / [E] redisplays) will you load and read fully `{nextStepFile}` to execute validation.
135
+ - [E] re-renders the preview without re-running extraction; [S] discards the compiled output and re-runs step 3 with new hints.
173
136
 
@@ -12,11 +12,10 @@ To query the agentskills.io ecosystem for an existing official skill matching th
12
12
 
13
13
  ## Rules
14
14
 
15
- - This check is advisory — never block the workflow on failure
16
15
  - 5-second timeout on ecosystem queries; tool unavailability is a silent skip, not an error
17
16
  - Do not begin extraction or compilation
18
17
 
19
- ## MANDATORY SEQUENCE
18
+ ## Steps
20
19
 
21
20
  ### 1. Query Ecosystem
22
21
 
@@ -54,34 +53,20 @@ An official skill already exists. You can:
54
53
  **[I] Install** — Install the existing official skill instead (exits this workflow)
55
54
  **[A] Abort** — Cancel compilation"
56
55
 
57
- ### 3. Handle Match Menu (ONLY if match found)
56
+ ### 3. Handle Match Menu (only when a match was found)
58
57
 
59
58
  #### Menu Handling Logic:
60
59
 
61
60
  - IF P: Set `ecosystem_status: match-proceed`, then load, read entire file, then execute {nextStepFile}
62
- - IF I: Display install instructions for the official skill, emit the HARD HALT envelope per SKILL.md "Result Contract on HARD HALT" (`phase: "ecosystem-check"`, `error.code: "ecosystem-redirect"`, `error.message: "User opted to install existing official skill instead of compiling a custom community skill."`, `skill_package: null`), exit with code 8 (ecosystem-redirect). Skill package is unknown at this phase — no on-disk result file is written.
61
+ - IF I: Display install instructions for the official skill, emit the HARD HALT envelope per `references/halt-contract.md` (`phase: "ecosystem-check"`, `error.code: "ecosystem-redirect"`, `error.message: "User opted to install existing official skill instead of compiling a custom community skill."`, `skill_package: null`), exit with code 8 (ecosystem-redirect). Skill package is unknown at this phase — no on-disk result file is written.
63
62
  - IF A: Display "Compilation cancelled.", emit the HARD HALT envelope (`phase: "ecosystem-check"`, `error.code: "user-cancelled"`, `error.message: "User aborted at ecosystem-match gate."`, `skill_package: null`), exit with code 6 (user-cancelled). Skill package is unknown at this phase — no on-disk result file is written.
64
63
  - IF Any other: help user, then redisplay the match menu
65
64
 
66
- #### EXECUTION RULES:
65
+ #### Gate:
67
66
 
68
- - ONLY display this menu when ecosystem_status is match
69
- - ALWAYS halt and wait for user input when match is found
70
67
  - **GATE [default: P]** — If `{headless_mode}` and match found: auto-proceed with [P] Proceed (compile custom skill anyway), log: "headless: ecosystem match found, auto-proceeding with custom compilation"
71
- - For no-match and skip cases, auto-proceed without menu
72
68
 
73
69
  ### 4. Auto-Proceed (No Match or Skip)
74
70
 
75
- #### Menu Handling Logic:
76
-
77
- - After no-match or skip determination, immediately load, read entire file, then execute {nextStepFile}
78
-
79
- #### EXECUTION RULES:
80
-
81
- - This is an auto-proceed path — no user interaction needed
82
- - Proceed directly to extraction step
83
-
84
- ## CRITICAL STEP COMPLETION NOTE
85
-
86
- ONLY WHEN ecosystem check completes (match with user choice, no-match, or skip) will you load and read fully `{nextStepFile}` to proceed to source extraction.
71
+ For no-match and skip, load and execute {nextStepFile} to proceed to source extraction.
87
72
 
@@ -19,7 +19,7 @@ To finalize the skill by creating the active-version pointer, displaying the com
19
19
  - Create the active pointer via the shared helper — never `rm` + `ln -s` manually
20
20
  - Result contract writing is mandatory (pipeline consumers depend on it)
21
21
 
22
- ## MANDATORY SEQUENCE
22
+ ## Steps
23
23
 
24
24
  ### 1. Create Active Pointer (atomic flip, Windows-safe)
25
25
 
@@ -29,7 +29,7 @@ To finalize the skill by creating the active-version pointer, displaying the com
29
29
 
30
30
  Create or update the `active` pointer at `{skill_group}/active` pointing to `{version}` using the shared atomic-flip helper. The helper acquires an `flock` on `{skill_group}/active.skf-lock`, refuses to replace a non-link at `{skill_group}/active` (protecting against accidental `rm -rf` of a real directory), and uses a rename-over-symlink pattern so the update is atomic from a concurrent reader's perspective. On Windows the helper automatically falls back to a directory junction (`mklink /J`) when `os.symlink` fails with `PRIVILEGE_NOT_HELD` / `ACCESS_DENIED` — junctions require no admin elevation and resolve identically for `skf-skill-inventory`'s consumers:
31
31
 
32
- **Resolve `{atomicWriteHelper}`** from `{atomicWriteProbeOrder}`; first existing path wins. HALT if no candidate exists — the active-pointer flip MUST go through the atomic helper.
32
+ **Resolve `{atomicWriteHelper}`** from `{atomicWriteProbeOrder}`; first existing path wins. If no candidate exists, skip the flip the same way `--no-active-pointer` does: log "Active pointer: skipped atomic-write helper unavailable", omit the active-pointer line from the completion summary and outputs, and record `active_pointer: "skipped-helper-missing"` in the result-contract summary (§3) so consumers see why the pointer is absent. The deliverables are already on disk, so a missing helper degrades to "no pointer" rather than a failed run. There is no manual fallback: a hand-rolled `rm` + `ln -s` loses the helper's atomicity and non-link guard, risking a half-flipped pointer or an `rm -rf` into a real directory.
33
33
 
34
34
  ```bash
35
35
  python3 {atomicWriteHelper} flip-link \
@@ -37,9 +37,7 @@ python3 {atomicWriteHelper} flip-link \
37
37
  --target {version}
38
38
  ```
39
39
 
40
- The helper returns non-zero (helper exit 2) if `{skill_group}/active` already exists as a real directory or file rather than a link — in that case, HARD HALT the workflow with **exit code 7 (finalize-blocked)** per the SKILL.md exit-code map: "Refusing to flip `{skill_group}/active` — existing path is not a symlink or junction. Investigate manually; expected a link pointing at a version directory." Before exiting, emit the error result contract per SKILL.md "Result Contract on HARD HALT" (`phase: "finalize"`, `error.code: "finalize-blocked"`, `skill_package` set, `outputs` listing the deliverables already on disk from step 5). A common cause on Windows is a prior run that executed `ln -s` under git-bash without Developer Mode enabled, which silently wrote a full directory copy; remove that copy and retry.
41
-
42
- **Never `rm` + `ln -s` the active pointer manually.** The bare-rm pattern has two failure modes: (1) a concurrent reader sees a missing `active` mid-flip, and (2) a bug or typo that replaces `{skill_group}/active` with a plain directory turns the next manual `rm -rf {skill_group}/active` into data loss. The helper encapsulates both guards and the Windows junction fallback.
40
+ The helper returns non-zero (helper exit 2) if `{skill_group}/active` already exists as a real directory or file rather than a link — in that case, HARD HALT the workflow with **exit code 7 (finalize-blocked)** per the exit-code map in `references/halt-contract.md`: "Refusing to flip `{skill_group}/active` — existing path is not a symlink or junction. Investigate manually; expected a link pointing at a version directory." Before exiting, emit the error result contract per `references/halt-contract.md` (`phase: "finalize"`, `error.code: "finalize-blocked"`, `skill_package` set, `outputs` listing the deliverables already on disk from step 5). A common cause on Windows is a prior run that executed `ln -s` under git-bash without Developer Mode enabled, which silently wrote a full directory copy; remove that copy and retry.
43
41
 
44
42
  Confirm: "Active pointer: {skill_group}/active -> {version} ({kind})" where `{kind}` is `symlink` or `junction` as returned by the helper.
45
43
 
@@ -76,6 +74,14 @@ Confirm: "Active pointer: {skill_group}/active -> {version} ({kind})" where `{ki
76
74
 
77
75
  Write the result contract per `shared/references/output-contract-schema.md`: the per-run record at `{skill_package}/quick-skill-result-{YYYYMMDD-HHmmss}.json` (UTC timestamp, resolution to seconds) and a copy at `{skill_package}/quick-skill-result-latest.json` (stable path for pipeline consumers — copy, not symlink). Include `SKILL.md`, `context-snippet.md`, and `metadata.json` paths in `outputs` and export count in `summary`.
78
76
 
77
+ **Post-completion hook (optional).** If `{onCompleteCommand}` is non-empty (resolved at SKILL.md On Activation §3 from `workflow.on_complete`), invoke it after the result contract is finalized:
78
+
79
+ ```bash
80
+ {onCompleteCommand} --skill-package={skill_package}
81
+ ```
82
+
83
+ Log success/failure but never fail the workflow on a hook error — the skill is already written. The hook runs last so a git-add, registry registration, or notifier sees a complete package. When `{onCompleteCommand}` is empty (bundled default), skip the invocation entirely.
84
+
79
85
  ### 4. Chain to Health Check
80
86
 
81
- ONLY WHEN the active pointer has been created and the completion summary and result contract have been written will you then load, read the full file, and proceed to `{nextStepFile}`. The health-check step is the true terminal step — do not stop here even though the summary reads as final.
87
+ Once the active pointer, completion summary, result contract, and any post-completion hook are done, load and execute {nextStepFile}. Do not stop here health-check is the true terminal step even though the summary reads as final.
@@ -0,0 +1,54 @@
1
+ <!-- Config: communicate in {communication_language}. -->
2
+
3
+ # HARD HALT Contract
4
+
5
+ The exit-code map and error-result envelope every step emits on a HARD HALT. Any step loads this file on its failure path, so the wire format is available even if SKILL.md has been compacted mid-run.
6
+
7
+ ## Exit Codes
8
+
9
+ Every HARD HALT in this workflow exits with a stable, documented code so headless automators can branch on the failure class without grepping message text:
10
+
11
+ | Code | Meaning | Raised by |
12
+ | ---- | ---------------------- | ----------------------------------------------------------- |
13
+ | 0 | success | step 7 (terminal) |
14
+ | 3 | resolution-failure | step 1 (prose input §2, registry chain §3, version-tag miss §3a, language abort §4); step 3 (non-library shape §1.5, zero-exports §4.5) |
15
+ | 4 | write-failure | step 5 §2 (deliverable write failed) |
16
+ | 5 | overwrite-cancelled | step 5 §1 (user selected [N]) |
17
+ | 6 | user-cancelled | step 1 §1 ([X] Cancel and exit, or cancel-line affordance); step 2 §3 ([A] Abort at ecosystem-match gate); step 4 §6 (user selected [Q]) |
18
+ | 7 | finalize-blocked | step 6 §1 (active-pointer flip refused — non-link in place) |
19
+ | 8 | ecosystem-redirect | step 2 §3 ([I] Install at ecosystem-match gate — user opted to install the existing official skill instead of compiling a custom community skill) |
20
+
21
+ ## Result Contract on HARD HALT
22
+
23
+ In addition to the success-variant result contract written by step 6 §3, every HARD HALT must surface an **error variant** so headless automators don't silently break when `quick-skill-result-latest.json` is missing on failed runs.
24
+
25
+ **Always (every HARD HALT, regardless of phase)** — emit a single line on **stderr**:
26
+
27
+ ```
28
+ SKF_QUICK_SKILL_RESULT_JSON: {"status":"error","exit_code":<N>,"phase":"<slug>","error":{"code":"<class>","message":"<short>"},"outputs":{},"summary":{},"skill_package":"<path-or-null>"}
29
+ ```
30
+
31
+ One line, no pretty-print. Matches the prefix-and-envelope convention used by `skf-emit-result-envelope.py`.
32
+
33
+ **Additionally, when `{skill_package}` is known** (HALT at step 5 §1 onward) — write the same JSON object (without the `SKF_QUICK_SKILL_RESULT_JSON: ` prefix) to disk:
34
+
35
+ ```
36
+ {skill_package}/quick-skill-result-{YYYYMMDD-HHmmss}.json
37
+ {skill_package}/quick-skill-result-latest.json (copy, not symlink)
38
+ ```
39
+
40
+ so consumers that hardcode the `-latest.json` path see a deterministic file even on failed runs. HALTs at step 1/02/03/04 cannot write to disk because `{skill_package}` is computed only in step 5 §1; for those, the stderr envelope plus exit code is the contract.
41
+
42
+ **Schema:**
43
+
44
+ | Field | Type | Notes |
45
+ | --------------- | -------------- | ----------------------------------------------------------------------------------------------------------- |
46
+ | `status` | string | always `"error"` for HARD HALTs |
47
+ | `exit_code` | integer | matches the Exit Codes table above |
48
+ | `phase` | string | step slug where the HALT occurred (e.g. `resolve-target`, `compile`) |
49
+ | `error.code` | string | one of: `resolution-failure`, `write-failure`, `overwrite-cancelled`, `user-cancelled`, `finalize-blocked`, `ecosystem-redirect` |
50
+ | `error.message` | string | the user-facing message that was displayed |
51
+ | `error.details` | any | optional — phase-specific context (e.g. the failed file path) |
52
+ | `outputs` | object | empty `{}` on early HALTs; partial when files were already written |
53
+ | `summary` | object | empty `{}` on early HALTs |
54
+ | `skill_package` | string \| null | absolute path when known, `null` when HALT preceded step 5 §1 |
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  # `shared/health-check.md` resolves relative to the SKF module root
3
3
  # (`{project-root}/_bmad/skf/` when installed, `{project-root}/src/` during
4
- # development), NOT relative to this step file.
4
+ # development), not relative to this step file.
5
5
  nextStepFile: 'shared/health-check.md'
6
6
  ---
7
7
 
@@ -16,9 +16,8 @@ Chain to the shared workflow self-improvement health check at `{nextStepFile}`.
16
16
  ## Rules
17
17
 
18
18
  - No user-facing reports, file writes, or result contracts in this step — those belong in step 6
19
- - Delegate directly to `{nextStepFile}` with no additional commentary
20
- - Do not attempt any other action between loading this step and executing `{nextStepFile}`
19
+ - Delegate directly to `{nextStepFile}` with no additional commentary or intervening action
21
20
 
22
- ## MANDATORY SEQUENCE
21
+ ## Steps
23
22
 
24
23
  Load `{nextStepFile}`, read it fully, then proceed to execute it.
@@ -19,7 +19,7 @@ To read the resolved GitHub repository source and extract the public API surface
19
19
  - Do not begin compilation or write output files
20
20
  - If no exports found, use README content as fallback
21
21
 
22
- ## MANDATORY SEQUENCE
22
+ ## Steps
23
23
 
24
24
  **Ref-aware source reading:** When `source_ref` is set from tag resolution (see step 1), append `?ref={source_ref}` to all GitHub API content and tree requests (e.g., `gh api repos/{owner}/{repo}/contents/{path}?ref={source_ref}`) to read from the tagged version. When using web browsing, use the tagged URL format (e.g., `github.com/{owner}/{repo}/blob/{source_ref}/{path}`). This ensures extraction reads from the same source version resolved during tag resolution.
25
25
 
@@ -57,7 +57,7 @@ Quick-skill is designed to wrap a library's public API. The compiled SKILL.md wi
57
57
  Select: [C] Continue anyway · [A] Abort"
58
58
 
59
59
  - **IF C** — log "user accepted `{shape}` shape" and proceed to §2. Set `extraction_inventory.repo_shape` to the detected shape so the result contract carries the signal for automators.
60
- - **IF A** — HARD HALT with **exit code 3 (resolution-failure)** per the SKILL.md exit-code map: "Aborted. `{shape}` repos are best wrapped manually with `/skf-create-skill` from a brief, not auto-extracted." Before exiting, emit the error result contract per SKILL.md "Result Contract on HARD HALT" (`phase: "quick-extract"`, `error.code: "resolution-failure"`, `error.details: {repo_shape: "{shape}"}`, `skill_package: null`).
60
+ - **IF A** — HARD HALT with **exit code 3 (resolution-failure)** per the exit-code map in `references/halt-contract.md`: "Aborted. `{shape}` repos are best wrapped manually with `/skf-create-skill` from a brief, not auto-extracted." Before exiting, emit the error result contract per `references/halt-contract.md` (`phase: "quick-extract"`, `error.code: "resolution-failure"`, `error.details: {repo_shape: "{shape}"}`, `skill_package: null`).
61
61
 
62
62
  **GATE [default: C]** — In headless mode, log "headless: detected `{shape}` repo, continuing anyway" and proceed; the result contract's `summary.repo_shape` carries the signal so automators can flag low-quality outputs without re-parsing logs.
63
63
 
@@ -76,13 +76,13 @@ Fetch the manifest file and the top-level entry-point file(s) for the detected l
76
76
 
77
77
  **If `scope_hint` provided:** focus the entry-point fetch on the specified directories instead of repo root.
78
78
 
79
- For multi-module Maven (`<modules>`) and multi-project Gradle (`include(...)`) builds, fetch the parent manifest first, then loop §2+§3 per module. Sub-module fetches are safe to issue as one batched tool-call message N module fetches collapse to O(1) wall-clock time.
79
+ For multi-module Maven (`<modules>`) and multi-project Gradle (`include(...)`) builds, fetch the parent manifest first, then loop §2+§3 per module. Batch the sub-module fetches per the parallel-fetch directive at the top of this step.
80
80
 
81
81
  ### 3. Parse Manifest and Scan Exports
82
82
 
83
83
  Run the shared extractor against the contents fetched in §2. The helper does manifest parse + export scan in one invocation and emits a structured envelope ready to feed §4's inventory.
84
84
 
85
- **Resolve `{publicApiExtractor}`** from `{publicApiExtractorProbeOrder}`; first existing path wins. If no candidate exists, fall back to in-prompt parsing (the legacy per-language regex tables that this section replaces).
85
+ **Resolve `{publicApiExtractor}`** from `{publicApiExtractorProbeOrder}`; first existing path wins. If no candidate exists, fall back to in-prompt per-language regex parsing of the manifest and entry-point files.
86
86
 
87
87
  Build the input payload from §2's fetched files and pipe it to the helper:
88
88
 
@@ -129,7 +129,7 @@ extraction_inventory:
129
129
 
130
130
  ### 4.5. Zero-Exports Soft Gate (rescue mode)
131
131
 
132
- Run this gate **only when** `extraction_inventory.exports.length == 0` AND `extraction_inventory.description` is empty (no usable README content either). When either is non-empty, the README-fallback in §4 produces a usable skill and this section is skipped.
132
+ Run this gate **only when** `extraction_inventory.exports.length == 0` and `extraction_inventory.description` is empty (no usable README content either). When either is non-empty, the README-fallback in §4 produces a usable skill and this section is skipped.
133
133
 
134
134
  When both are empty, the compiled SKILL.md would be effectively empty — no API surface to document and no description to fall back on. Offer the user a chance to retry with hints before producing a degenerate output:
135
135
 
@@ -146,7 +146,7 @@ Select: [R] Retry with new hints · [P] Proceed anyway (low-confidence skill) ·
146
146
 
147
147
  - **IF R** — prompt for new `scope_hint` ("New scope hint (e.g. `src/server/`):") and optional new `language_hint` ("New language hint (or empty to keep `{language}`):"). Update the extraction context with the new hints, then **re-execute step 3 from §1** with the new values. Discards the prior empty inventory.
148
148
  - **IF P** — log "user accepted zero-exports outcome" and proceed to §5. The compiled skill will be README-content-only with confidence `low`. Record `zero_exports_rescue: "user-accepted"` in the inventory so the result contract summary surfaces it.
149
- - **IF A** — HARD HALT with **exit code 3 (resolution-failure)**: "Aborted. Run `/skf-create-skill` from a brief if you want a guided extraction with provenance tracking." Before exiting, emit the error result contract per SKILL.md "Result Contract on HARD HALT" (`phase: "quick-extract"`, `error.code: "resolution-failure"`, `error.details: {exports_found: 0, description_empty: true, language: "{language}", scope: "{scope_hint or 'entire repo'}"}`, `skill_package: null`).
149
+ - **IF A** — HARD HALT with **exit code 3 (resolution-failure)**: "Aborted. Run `/skf-create-skill` from a brief if you want a guided extraction with provenance tracking." Before exiting, emit the error result contract per `references/halt-contract.md` (`phase: "quick-extract"`, `error.code: "resolution-failure"`, `error.details: {exports_found: 0, description_empty: true, language: "{language}", scope: "{scope_hint or 'entire repo'}"}`, `skill_package: null`).
150
150
 
151
151
  **GATE [default: P]** — In headless mode, log "headless: zero exports + empty description, proceeding with low-confidence skill" and proceed; record `zero_exports_rescue: "auto-proceeded"` in the result contract summary so batch automators can re-queue these targets with stricter hints downstream. [P] preserves the pre-rescue behaviour for unattended pipelines.
152
152
 
@@ -164,16 +164,5 @@ Select: [R] Retry with new hints · [P] Proceed anyway (low-confidence skill) ·
164
164
 
165
165
  ### 6. Auto-Proceed to Compilation
166
166
 
167
- #### Menu Handling Logic:
168
-
169
- - After extraction summary, immediately load, read entire file, then execute {nextStepFile}
170
-
171
- #### EXECUTION RULES:
172
-
173
- - This is an auto-proceed step — extraction results flow directly to compilation
174
- - Proceed directly to next step after summary
175
-
176
- ## CRITICAL STEP COMPLETION NOTE
177
-
178
- ONLY WHEN extraction is complete and extraction_inventory is assembled (even if minimal/low-confidence) will you load and read fully `{nextStepFile}` to execute compilation.
167
+ Once extraction_inventory is assembled (even if minimal or low-confidence), load and execute {nextStepFile} to compile.
179
168
 
@@ -70,26 +70,4 @@ Please provide the GitHub URL directly, or check:
70
70
 
71
71
  **Hard halt** — cannot proceed without a resolved source.
72
72
 
73
- ## Language Detection
74
-
75
- After resolving to a GitHub repo, detect primary language from:
76
-
77
- 1. Manifest file presence:
78
- - `package.json` → JavaScript/TypeScript
79
- - `pyproject.toml` or `setup.py` → Python
80
- - `Cargo.toml` → Rust
81
- - `go.mod` → Go
82
- - `pom.xml` or `build.gradle` → Java
83
- 2. User-provided language hint (overrides detection)
84
- 3. GitHub API language field (if accessible)
85
-
86
- ## Manifest File Priority
87
-
88
- For each language, the primary manifest to read:
89
-
90
- | Language | Manifest | Key Fields |
91
- |----------|----------------|--------------------------------------------------------------------------|
92
- | JS/TS | package.json | name, version, description, main, exports, dependencies |
93
- | Python | pyproject.toml | project.name, project.version, project.description, project.dependencies |
94
- | Rust | Cargo.toml | package.name, package.version, package.description, dependencies |
95
- | Go | go.mod | module path, require list |
73
+ Language detection is authoritative in `resolve-target.md` §4 (Detect Language) — this file covers only the package-to-repo registry chain.