bmad-module-skill-forge 1.9.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 (281) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.nvmrc +1 -1
  3. package/README.md +10 -5
  4. package/docs/_data/pinned.yaml +2 -2
  5. package/docs/agents.md +11 -2
  6. package/docs/architecture.md +5 -4
  7. package/docs/bmad-synergy.md +30 -7
  8. package/docs/campaign.md +172 -0
  9. package/docs/examples.md +7 -3
  10. package/docs/forge-auto.md +90 -0
  11. package/docs/getting-started.md +9 -0
  12. package/docs/how-it-works.md +6 -4
  13. package/docs/index.md +4 -3
  14. package/docs/skill-model.md +1 -1
  15. package/docs/troubleshooting.md +17 -1
  16. package/docs/verifying-a-skill.md +2 -2
  17. package/docs/why-skf.md +1 -1
  18. package/docs/workflows.md +64 -24
  19. package/package.json +2 -2
  20. package/src/knowledge/skill-lifecycle.md +1 -1
  21. package/src/module-help.csv +4 -3
  22. package/src/shared/data/language-corpora.json +32 -0
  23. package/src/shared/references/pipeline-contracts.md +6 -3
  24. package/src/shared/scripts/schemas/skill-brief.v1.json +6 -1
  25. package/src/shared/scripts/skf-comention-pairs.py +350 -0
  26. package/src/shared/scripts/skf-count-tokens.py +222 -0
  27. package/src/shared/scripts/skf-derive-assembly-shape.py +107 -0
  28. package/src/shared/scripts/skf-detect-docs.py +240 -4
  29. package/src/shared/scripts/skf-detect-language.py +82 -3
  30. package/src/shared/scripts/skf-detect-tools.py +105 -2
  31. package/src/shared/scripts/skf-emit-result-envelope.py +17 -0
  32. package/src/shared/scripts/skf-enumerate-stack-skills.py +111 -2
  33. package/src/shared/scripts/skf-extract-public-api.py +53 -0
  34. package/src/shared/scripts/skf-find-cycles.py +246 -0
  35. package/src/shared/scripts/skf-hash-content.py +487 -2
  36. package/src/shared/scripts/skf-language-corpora.py +100 -0
  37. package/src/shared/scripts/skf-manifest-ops.py +67 -1
  38. package/src/shared/scripts/skf-merge-doc-urls.py +244 -0
  39. package/src/shared/scripts/skf-preapply.py +1 -1
  40. package/src/shared/scripts/skf-rebuild-managed-sections.py +180 -0
  41. package/src/shared/scripts/skf-recommend-scope-type.py +1 -2
  42. package/src/shared/scripts/skf-render-metadata-stats.py +499 -0
  43. package/src/shared/scripts/skf-rewrite-skill-name.py +308 -0
  44. package/src/shared/scripts/skf-shape-detect.py +576 -25
  45. package/src/shared/scripts/skf-shard-body.py +461 -0
  46. package/src/shared/scripts/skf-skill-inventory.py +139 -3
  47. package/src/shared/scripts/skf-structural-diff.py +307 -67
  48. package/src/shared/scripts/skf-validate-brief-schema.py +41 -6
  49. package/src/shared/scripts/skf-validate-feasibility-report.py +234 -0
  50. package/src/shared/scripts/skf-validate-frontmatter.py +17 -12
  51. package/src/shared/scripts/skf-validate-output.py +443 -10
  52. package/src/shared/scripts/skf-validate-pins.py +3 -3
  53. package/src/shared/scripts/skf-verify-no-trace.py +214 -0
  54. package/src/shared/scripts/skf-verify-provenance-completeness.py +439 -0
  55. package/src/shared/scripts/skf-write-skill-brief.py +21 -5
  56. package/src/skf-analyze-source/SKILL.md +17 -32
  57. package/src/skf-analyze-source/assets/skill-brief-schema.md +1 -1
  58. package/src/skf-analyze-source/customize.toml +2 -0
  59. package/src/skf-analyze-source/references/auto-docs-only.md +116 -0
  60. package/src/skf-analyze-source/references/continue.md +8 -13
  61. package/src/skf-analyze-source/references/generate-briefs.md +28 -12
  62. package/src/skf-analyze-source/references/headless-contract.md +33 -0
  63. package/src/skf-analyze-source/references/health-check.md +1 -2
  64. package/src/skf-analyze-source/references/identify-units.md +25 -36
  65. package/src/skf-analyze-source/references/init.md +12 -25
  66. package/src/skf-analyze-source/references/map-and-detect.md +8 -20
  67. package/src/skf-analyze-source/references/recommend.md +4 -14
  68. package/src/skf-analyze-source/references/scan-project.md +3 -11
  69. package/src/skf-analyze-source/references/step-auto-scope.md +211 -197
  70. package/src/skf-analyze-source/references/step-shape-detect.md +20 -13
  71. package/src/skf-analyze-source/references/unit-detection-heuristics.md +2 -2
  72. package/src/skf-audit-skill/SKILL.md +9 -6
  73. package/src/skf-audit-skill/customize.toml +2 -0
  74. package/src/skf-audit-skill/references/init.md +58 -32
  75. package/src/skf-audit-skill/references/re-index.md +15 -34
  76. package/src/skf-audit-skill/references/report.md +11 -58
  77. package/src/skf-audit-skill/references/semantic-diff.md +4 -22
  78. package/src/skf-audit-skill/references/severity-classify.md +53 -87
  79. package/src/skf-audit-skill/references/step-doc-drift.md +49 -19
  80. package/src/skf-audit-skill/references/structural-diff.md +43 -68
  81. package/src/skf-brief-skill/SKILL.md +7 -36
  82. package/src/skf-brief-skill/assets/scope-templates.md +1 -1
  83. package/src/skf-brief-skill/assets/skill-brief-schema.md +1 -1
  84. package/src/skf-brief-skill/customize.toml +14 -0
  85. package/src/skf-brief-skill/references/analyze-target.md +13 -18
  86. package/src/skf-brief-skill/references/confirm-brief.md +2 -15
  87. package/src/skf-brief-skill/references/draft-checkpoint.md +8 -8
  88. package/src/skf-brief-skill/references/gather-intent.md +27 -24
  89. package/src/skf-brief-skill/references/headless-args.md +1 -1
  90. package/src/skf-brief-skill/references/health-check.md +1 -22
  91. package/src/skf-brief-skill/references/invocation-contract.md +37 -0
  92. package/src/skf-brief-skill/references/scope-definition.md +6 -15
  93. package/src/skf-brief-skill/references/step-auto-brief.md +22 -9
  94. package/src/skf-brief-skill/references/step-auto-validate.md +3 -7
  95. package/src/skf-brief-skill/references/version-resolution.md +1 -1
  96. package/src/skf-brief-skill/references/write-brief.md +19 -13
  97. package/src/skf-campaign/SKILL.md +121 -0
  98. package/src/skf-campaign/assets/campaign-state-schema.json +191 -0
  99. package/src/skf-campaign/customize.toml +75 -0
  100. package/src/skf-campaign/manifest.yaml +15 -0
  101. package/src/skf-campaign/references/campaign-contracts.md +67 -0
  102. package/src/skf-campaign/references/campaign-directive-spec.md +32 -0
  103. package/src/skf-campaign/references/health-check.md +35 -0
  104. package/src/skf-campaign/references/step-01-setup.md +121 -0
  105. package/src/skf-campaign/references/step-02-strategy.md +102 -0
  106. package/src/skf-campaign/references/step-03-pins.md +56 -0
  107. package/src/skf-campaign/references/step-04-provenance.md +63 -0
  108. package/src/skf-campaign/references/step-05-skill-loop.md +103 -0
  109. package/src/skf-campaign/references/step-06-batch.md +88 -0
  110. package/src/skf-campaign/references/step-07-capstone.md +63 -0
  111. package/src/skf-campaign/references/step-08-verify.md +75 -0
  112. package/src/skf-campaign/references/step-09-refine.md +83 -0
  113. package/src/skf-campaign/references/step-10-export.md +106 -0
  114. package/src/skf-campaign/references/step-11-maintenance.md +84 -0
  115. package/src/skf-campaign/references/step-resume.md +115 -0
  116. package/src/skf-campaign/scripts/.gitkeep +0 -0
  117. package/src/skf-campaign/scripts/campaign-deps.py +244 -0
  118. package/src/skf-campaign/scripts/campaign-parse-manifest.py +119 -0
  119. package/src/skf-campaign/scripts/campaign-provenance.py +247 -0
  120. package/src/skf-campaign/scripts/campaign-render-batch.py +199 -0
  121. package/src/skf-campaign/scripts/campaign-render-kickoff.py +158 -0
  122. package/src/skf-campaign/scripts/campaign-report.py +249 -0
  123. package/src/skf-campaign/scripts/campaign-status.py +162 -0
  124. package/src/skf-campaign/scripts/campaign-validate-pins.py +174 -0
  125. package/src/skf-campaign/scripts/campaign-validate-state.py +207 -0
  126. package/src/skf-campaign/templates/campaign-brief-template.yaml +34 -0
  127. package/src/skf-campaign/templates/campaign-report-template.md +54 -0
  128. package/src/skf-campaign/templates/kickoff-template.md +48 -0
  129. package/src/skf-create-skill/SKILL.md +15 -4
  130. package/src/skf-create-skill/assets/compile-assembly-rules.md +35 -34
  131. package/src/skf-create-skill/assets/skill-sections.md +9 -100
  132. package/src/skf-create-skill/assets/tessl-dismissal-rules.md +4 -13
  133. package/src/skf-create-skill/customize.toml +13 -0
  134. package/src/skf-create-skill/references/authoritative-files-protocol.md +7 -7
  135. package/src/skf-create-skill/references/compile.md +37 -47
  136. package/src/skf-create-skill/references/component-extraction.md +8 -35
  137. package/src/skf-create-skill/references/ecosystem-check.md +9 -25
  138. package/src/skf-create-skill/references/enrich.md +4 -17
  139. package/src/skf-create-skill/references/extract.md +20 -27
  140. package/src/skf-create-skill/references/extraction-patterns-tracing.md +1 -1
  141. package/src/skf-create-skill/references/extraction-patterns.md +10 -8
  142. package/src/skf-create-skill/references/generate-artifacts.md +20 -25
  143. package/src/skf-create-skill/references/health-check.md +2 -2
  144. package/src/skf-create-skill/references/load-brief.md +16 -18
  145. package/src/skf-create-skill/references/report.md +27 -14
  146. package/src/skf-create-skill/references/source-resolution-protocols.md +4 -4
  147. package/src/skf-create-skill/references/step-auto-shard.md +52 -25
  148. package/src/skf-create-skill/references/step-doc-rot.md +33 -15
  149. package/src/skf-create-skill/references/step-doc-sources.md +13 -4
  150. package/src/skf-create-skill/references/sub/ccc-discover.md +2 -13
  151. package/src/skf-create-skill/references/sub/fetch-docs.md +33 -46
  152. package/src/skf-create-skill/references/sub/fetch-temporal.md +5 -20
  153. package/src/skf-create-skill/references/tier-degradation-rules.md +6 -8
  154. package/src/skf-create-skill/references/validate.md +69 -29
  155. package/src/skf-create-skill/scripts/scan-doc-rot.py +245 -0
  156. package/src/skf-create-stack-skill/SKILL.md +15 -9
  157. package/src/skf-create-stack-skill/assets/provenance-map-schema.md +1 -1
  158. package/src/skf-create-stack-skill/customize.toml +10 -0
  159. package/src/skf-create-stack-skill/references/compile-stack.md +7 -8
  160. package/src/skf-create-stack-skill/references/compose-mode-rules.md +2 -13
  161. package/src/skf-create-stack-skill/references/detect-integrations.md +49 -54
  162. package/src/skf-create-stack-skill/references/detect-manifests.md +37 -30
  163. package/src/skf-create-stack-skill/references/generate-output.md +24 -75
  164. package/src/skf-create-stack-skill/references/init.md +9 -81
  165. package/src/skf-create-stack-skill/references/manifest-patterns.md +5 -35
  166. package/src/skf-create-stack-skill/references/parallel-extract.md +12 -27
  167. package/src/skf-create-stack-skill/references/rank-and-confirm.md +6 -6
  168. package/src/skf-create-stack-skill/references/report.md +27 -62
  169. package/src/skf-create-stack-skill/references/validate.md +35 -31
  170. package/src/skf-drop-skill/SKILL.md +20 -23
  171. package/src/skf-drop-skill/customize.toml +10 -0
  172. package/src/skf-drop-skill/references/execute.md +67 -36
  173. package/src/skf-drop-skill/references/headless-contract.md +18 -0
  174. package/src/skf-drop-skill/references/health-check.md +1 -13
  175. package/src/skf-drop-skill/references/report.md +44 -10
  176. package/src/skf-drop-skill/references/select.md +93 -48
  177. package/src/skf-drop-skill/scripts/dir-sizes.py +116 -0
  178. package/src/skf-export-skill/SKILL.md +17 -14
  179. package/src/skf-export-skill/assets/managed-section-format.md +2 -5
  180. package/src/skf-export-skill/customize.toml +10 -6
  181. package/src/skf-export-skill/references/generate-snippet.md +21 -35
  182. package/src/skf-export-skill/references/load-skill.md +44 -42
  183. package/src/skf-export-skill/references/multi-skill-mode.md +1 -1
  184. package/src/skf-export-skill/references/orphan-context-detection.md +11 -3
  185. package/src/skf-export-skill/references/package.md +27 -33
  186. package/src/skf-export-skill/references/preflight-snippet-root-probe.md +24 -5
  187. package/src/skf-export-skill/references/result-envelope.md +28 -0
  188. package/src/skf-export-skill/references/summary.md +11 -5
  189. package/src/skf-export-skill/references/token-report.md +42 -24
  190. package/src/skf-export-skill/references/update-context.md +32 -33
  191. package/src/skf-forger/SKILL.md +32 -39
  192. package/src/skf-forger/references/pipeline-mode.md +34 -0
  193. package/src/skf-forger/scripts/parse-pipeline.py +270 -0
  194. package/src/skf-quick-skill/SKILL.md +10 -60
  195. package/src/skf-quick-skill/customize.toml +9 -0
  196. package/src/skf-quick-skill/references/batch-mode.md +6 -4
  197. package/src/skf-quick-skill/references/compile.md +15 -52
  198. package/src/skf-quick-skill/references/ecosystem-check.md +5 -20
  199. package/src/skf-quick-skill/references/finalize.md +12 -6
  200. package/src/skf-quick-skill/references/halt-contract.md +54 -0
  201. package/src/skf-quick-skill/references/health-check.md +3 -4
  202. package/src/skf-quick-skill/references/quick-extract.md +7 -18
  203. package/src/skf-quick-skill/references/registry-resolution.md +1 -23
  204. package/src/skf-quick-skill/references/resolve-target.md +27 -34
  205. package/src/skf-quick-skill/references/write-and-validate.md +10 -25
  206. package/src/skf-refine-architecture/SKILL.md +16 -8
  207. package/src/skf-refine-architecture/customize.toml +9 -0
  208. package/src/skf-refine-architecture/references/compile.md +10 -8
  209. package/src/skf-refine-architecture/references/gap-analysis.md +21 -50
  210. package/src/skf-refine-architecture/references/health-check.md +1 -1
  211. package/src/skf-refine-architecture/references/improvements.md +9 -25
  212. package/src/skf-refine-architecture/references/init.md +9 -16
  213. package/src/skf-refine-architecture/references/issue-detection.md +10 -25
  214. package/src/skf-refine-architecture/references/refinement-rules.md +4 -16
  215. package/src/skf-refine-architecture/references/report.md +14 -11
  216. package/src/skf-rename-skill/SKILL.md +11 -21
  217. package/src/skf-rename-skill/customize.toml +10 -0
  218. package/src/skf-rename-skill/references/execute.md +112 -82
  219. package/src/skf-rename-skill/references/exit-codes.md +12 -0
  220. package/src/skf-rename-skill/references/report.md +16 -8
  221. package/src/skf-rename-skill/references/select.md +69 -42
  222. package/src/skf-rename-skill/scripts/skf-validate-rename-name.py +161 -0
  223. package/src/skf-setup/SKILL.md +21 -13
  224. package/src/skf-setup/customize.toml +10 -0
  225. package/src/skf-setup/references/auto-index.md +11 -10
  226. package/src/skf-setup/references/ccc-index.md +14 -15
  227. package/src/skf-setup/references/detect-and-tier.md +10 -8
  228. package/src/skf-setup/references/report.md +26 -32
  229. package/src/skf-setup/references/tier-rules.md +2 -32
  230. package/src/skf-setup/references/write-config.md +9 -10
  231. package/src/skf-test-skill/SKILL.md +10 -8
  232. package/src/skf-test-skill/customize.toml +2 -0
  233. package/src/skf-test-skill/references/coherence-check.md +19 -31
  234. package/src/skf-test-skill/references/coverage-check.md +111 -67
  235. package/src/skf-test-skill/references/detect-mode.md +10 -41
  236. package/src/skf-test-skill/references/external-validators.md +11 -19
  237. package/src/skf-test-skill/references/init.md +39 -21
  238. package/src/skf-test-skill/references/migration-section-rules.md +4 -4
  239. package/src/skf-test-skill/references/report.md +60 -40
  240. package/src/skf-test-skill/references/score.md +32 -64
  241. package/src/skf-test-skill/references/scoring-rules.md +6 -62
  242. package/src/skf-test-skill/references/source-access-protocol.md +15 -5
  243. package/src/skf-test-skill/references/step-hard-gate.md +1 -3
  244. package/src/skf-test-skill/scripts/aggregate-coherence.py +276 -0
  245. package/src/skf-test-skill/scripts/check-metadata-coherence.py +359 -0
  246. package/src/skf-test-skill/scripts/combine-external-scores.py +190 -0
  247. package/src/skf-test-skill/scripts/compute-score.py +135 -4
  248. package/src/skf-test-skill/scripts/reconcile-coverage.py +327 -0
  249. package/src/skf-test-skill/scripts/validate-inventory.py +251 -0
  250. package/src/skf-test-skill/scripts/verify-declared-numerator.py +192 -0
  251. package/src/skf-update-skill/SKILL.md +17 -5
  252. package/src/skf-update-skill/customize.toml +11 -6
  253. package/src/skf-update-skill/references/detect-changes.md +48 -36
  254. package/src/skf-update-skill/references/health-check.md +5 -11
  255. package/src/skf-update-skill/references/init.md +40 -32
  256. package/src/skf-update-skill/references/manual-section-rules.md +1 -2
  257. package/src/skf-update-skill/references/merge-conflict-rules.md +1 -52
  258. package/src/skf-update-skill/references/merge.md +13 -57
  259. package/src/skf-update-skill/references/re-extract.md +27 -25
  260. package/src/skf-update-skill/references/report.md +14 -7
  261. package/src/skf-update-skill/references/validate.md +32 -30
  262. package/src/skf-update-skill/references/write.md +86 -51
  263. package/src/skf-update-skill/scripts/skf-new-file-diff.py +167 -0
  264. package/src/skf-verify-stack/SKILL.md +11 -21
  265. package/src/skf-verify-stack/customize.toml +12 -3
  266. package/src/skf-verify-stack/references/coverage-patterns.md +1 -29
  267. package/src/skf-verify-stack/references/coverage.md +21 -10
  268. package/src/skf-verify-stack/references/exit-codes.md +14 -0
  269. package/src/skf-verify-stack/references/health-check.md +1 -1
  270. package/src/skf-verify-stack/references/init.md +20 -25
  271. package/src/skf-verify-stack/references/integration-verification-rules.md +10 -19
  272. package/src/skf-verify-stack/references/integrations.md +44 -49
  273. package/src/skf-verify-stack/references/report.md +28 -34
  274. package/src/skf-verify-stack/references/requirements.md +3 -3
  275. package/src/skf-verify-stack/references/synthesize.md +36 -39
  276. package/src/skf-verify-stack/scripts/skf-coverage-tally.py +196 -0
  277. package/src/skf-verify-stack/scripts/skf-report-delta.py +256 -0
  278. package/src/skf-verify-stack/scripts/skf-verdict-rollup.py +258 -0
  279. package/tools/cli/lib/ui.js +3 -2
  280. package/docs/deepwiki.md +0 -89
  281. package/src/skf-rename-skill/references/rebuild-context.md +0 -110
@@ -122,7 +122,7 @@ Target file contains `<!-- SKF:BEGIN` but no matching `<!-- SKF:END -->` marker.
122
122
  When regenerating (Case 3) or creating/appending (Cases 1-2), rebuild the skill index from the **exported skill set** only:
123
123
 
124
124
  1. Read `{skills_output_folder}/.export-manifest.json` (v2 schema — see `knowledge/version-paths.md`) to determine which skills have been explicitly exported and their `active_version` (if no manifest exists, only the current export target qualifies)
125
- 2. For each skill in the exported set, resolve the snippet at `{skills_output_folder}/{skill-name}/{active_version}/{skill-name}/context-snippet.md` (i.e., `{skill_package}/context-snippet.md`). Do NOT use glob patterns across version directories — always resolve via manifest `active_version` or `active` symlink
125
+ 2. For each skill in the exported set, resolve the snippet at `{skills_output_folder}/{skill-name}/{active_version}/{skill-name}/context-snippet.md` (i.e., `{skill_package}/context-snippet.md`). Do NOT use glob patterns across version directories — always resolve via manifest `active_version` or `active` symlink, falling back to the flat `{skills_output_folder}/{skill-name}/context-snippet.md` path for a skill not yet migrated to the versioned layout
126
126
  3. Count total skills and stack skills (from filtered set only)
127
127
  4. Assemble filtered snippets into managed section
128
128
  5. Sort alphabetically by skill name
@@ -132,7 +132,4 @@ When regenerating (Case 3) or creating/appending (Cases 1-2), rebuild the skill
132
132
 
133
133
  ## Safety Rules
134
134
 
135
- - NEVER modify content outside the `<!-- SKF:BEGIN/END -->` markers
136
- - ALWAYS preserve existing file content above and below markers
137
- - ALWAYS verify file was written correctly after write
138
- - If write fails, report error — do not attempt partial writes
135
+ Only the bytes between `<!-- SKF:BEGIN -->` and `<!-- SKF:END -->` are yours to rewrite; everything above and below is the user's own file (their CLAUDE.md/AGENTS.md/.cursorrules) and must survive byte-for-byte — rewriting outside the markers destroys their content. On write failure, report and stop — never leave a partial write. Route writes through the atomic-write / rebuild-managed-sections helpers: they verify byte-identity of the content outside the markers after each write, so no separate hand-check is needed.
@@ -1,6 +1,8 @@
1
1
  # DO NOT EDIT -- overwritten on every update.
2
2
  #
3
3
  # Workflow customization surface for skf-export-skill.
4
+ # Team overrides: _bmad/custom/skf-export-skill.toml (under {project-root})
5
+ # Personal overrides: _bmad/custom/skf-export-skill.user.toml (under {project-root})
4
6
 
5
7
  [workflow]
6
8
 
@@ -34,6 +36,14 @@ persistent_facts = [
34
36
  "file:{project-root}/**/project-context.md",
35
37
  ]
36
38
 
39
+ # Optional post-export hook. When non-empty, invoked with
40
+ # `--result-path=<path>` after step 6 finalizes the per-run result JSON
41
+ # (before the terminal health-check step). Useful for downstream
42
+ # distribution, notification, or pipeline chaining. Failures are logged to
43
+ # workflow_warnings[] but never fail the workflow. Empty = no-op (default).
44
+
45
+ on_complete = ""
46
+
37
47
  # --- Optional asset overrides ---
38
48
  #
39
49
  # Lift the canonical asset paths so orgs can substitute house-style copies
@@ -41,9 +51,3 @@ persistent_facts = [
41
51
 
42
52
  managed_section_format_path = ""
43
53
  snippet_format_path = ""
44
-
45
- # Override the manifest location. Empty = use
46
- # {skills_output_folder}/.export-manifest.json. Useful for orgs that want
47
- # a cross-project manifest at a stable path (e.g. ~/.skf/export-manifest.json).
48
-
49
- export_manifest_path = ""
@@ -1,6 +1,14 @@
1
1
  ---
2
2
  nextStepFile: 'update-context.md'
3
3
  snippetFormatData: '{snippetFormatPath}'
4
+ # Resolve `{countTokensHelper}` by probing `{countTokensProbeOrder}` in order
5
+ # (installed SKF module path first, src/ dev-checkout fallback); the first
6
+ # existing path wins. §5 uses it to report the written snippet's authoritative
7
+ # token count (char-over-four, matching step 5's token report) instead of the
8
+ # in-prompt `words * 1.3` heuristic.
9
+ countTokensProbeOrder:
10
+ - '{project-root}/_bmad/skf/shared/scripts/skf-count-tokens.py'
11
+ - '{project-root}/src/shared/scripts/skf-count-tokens.py'
4
12
  ---
5
13
 
6
14
  <!-- Config: communicate in {communication_language}. Generate snippet content in {document_output_language}. -->
@@ -73,36 +81,17 @@ Store `{skill_root}` for use in snippet generation. The context-snippet.md writt
73
81
  - **If NO new gotchas are derived AND `prior_gotchas` exists AND `prior_gotchas_already_carried == true`:** Expiry reached (re-export only — first-export branch above takes precedence) — drop the gotchas line entirely. Emit warning: "**Stale gotchas dropped** — the prior gotchas were already carried forward once and cannot be derived from the current evidence report. The snippet now has no gotchas line. If the prior gotchas are still relevant, re-add them to the evidence report's T2-future section and re-run export."
74
82
  - **If NO new gotchas derived AND no `prior_gotchas`:** Omit the gotchas line.
75
83
 
76
- Generate:
77
- ```
78
- [{skill-name} v{version}]|root: {skill_root}{skill-name}/
79
- |IMPORTANT: {skill-name} v{version} — read SKILL.md before writing {skill-name} code. Do NOT rely on training data.
80
- |quick-start:{SKILL.md#quick-start}
81
- |api: {export-1}(), {export-2}(), {export-3}, {export-4}(), {export-5}
82
- |key-types:{SKILL.md#key-types} — {inline summary ~10 words}
83
- |gotchas: {pitfall-1}, {pitfall-2}
84
- ```
85
-
86
- **If fewer exports than limit:** List all available.
87
- **If no exports:** Omit the api line.
88
- **If no gotchas derivable AND no prior gotchas to carry forward:** Omit the gotchas line.
84
+ Emit the single-skill template from {snippetFormatData} (loaded in §2), filling `api` from the exports selected above (list all if fewer than the limit; omit the line if there are none), `key-types` from the inline summary extracted above, and `gotchas` per the carry-forward decision tree above (omit the line when it resolves to none).
89
85
 
90
86
  **For stack skills (`skill_type: "stack"`):**
91
87
 
92
- Generate:
93
- ```
94
- [{project}-stack v{version}]|root: {skill_root}{project}-stack/
95
- |IMPORTANT: {project}-stack — read SKILL.md before writing integration code. Do NOT rely on training data.
96
- |stack: {dep-1}@{v1}, {dep-2}@{v2}, {dep-3}@{v3}
97
- |integrations: {pattern-1}, {pattern-2}
98
- |gotchas: {pitfall-1}, {pitfall-2}
99
- ```
88
+ Emit the stack-skill template from {snippetFormatData}, filling `stack` from metadata.json `components` and `integrations` from metadata.json `integrations`.
100
89
 
101
90
  **Stack skill gotchas carry-forward:** Same one-cycle expiry logic as single skills. If no new gotchas derived and `prior_gotchas_already_carried == false`, preserve with the `[CARRIED]` prefix. If already carried once (`prior_gotchas_already_carried == true`), drop the line and warn loudly. See the single-skill steps for the complete protocol.
102
91
 
103
92
  ### 4. Verify Token Count
104
93
 
105
- Estimate token count of generated snippet (approximate: words * 1.3).
94
+ Estimate the generated snippet's token count with the **char-over-four** convention (`len(snippet)//4`) over the content held in context — the same convention `skf-count-tokens.py` uses for step 5's token report, so the two numbers agree. The freshly generated snippet is only in context here (not yet on disk), so this pre-write estimate stays in-prompt to drive the trim decision below; step 5 confirms it authoritatively against the written file via the helper.
106
95
 
107
96
  - Target: ~80-120 tokens per skill (aspirational for Quick/Forge tiers)
108
97
  - Warning threshold: >300 tokens (hard ceiling — Deep tier may legitimately exceed 120 when gotchas carry load-bearing breaking-change notices)
@@ -122,12 +111,20 @@ Estimate token count of generated snippet (approximate: words * 1.3).
122
111
 
123
112
  **Estimated tokens:** {count}"
124
113
 
125
- Hold content in context for step 4.
114
+ Use the §4 char-over-four estimate for `{count}` — nothing is written in dry-run, so the helper has no on-disk snippet to measure. Hold content in context for step 4.
126
115
 
127
116
  **If NOT dry-run:**
128
117
 
129
118
  Write the generated content to `{resolved_skill_package}/context-snippet.md`.
130
119
 
120
+ Then confirm the token count authoritatively: resolve `{countTokensHelper}` from `{countTokensProbeOrder}` (first existing path wins) and run it against the written package, reading the `context-snippet.md` row's `tokens` value:
121
+
122
+ ```bash
123
+ python3 {countTokensHelper} {resolved_skill_package}
124
+ ```
125
+
126
+ Use that value as `{count}` — it matches step 5's token report exactly. If the helper cannot run (no Python/uv), fall back to the §4 char-over-four estimate.
127
+
131
128
  "**context-snippet.md written.**
132
129
  **Path:** `{resolved_skill_package}/context-snippet.md`
133
130
  **Estimated tokens:** {count}"
@@ -136,16 +133,5 @@ Write the generated content to `{resolved_skill_package}/context-snippet.md`.
136
133
 
137
134
  Display: "**Proceeding to context update...**"
138
135
 
139
- #### Menu Handling Logic:
140
-
141
- - After snippet generation completes, immediately load, read entire file, then execute {nextStepFile}
142
-
143
- #### EXECUTION RULES:
144
-
145
- - This is an auto-proceed step with no user choices
146
- - Proceed directly to next step after generation
147
-
148
- ## CRITICAL STEP COMPLETION NOTE
149
-
150
- ONLY WHEN snippet generation is complete (or skipped due to passive_context opt-out) will you load and read fully `{nextStepFile}` to execute context update.
136
+ Auto-proceed (no user choices): once snippet generation is complete (or skipped via the `passive_context` opt-out), load, read entirely, and execute `{nextStepFile}`.
151
137
 
@@ -1,5 +1,16 @@
1
1
  ---
2
2
  nextStepFile: 'package.md'
3
+ managedSectionData: '{managedSectionFormatPath}'
4
+ # Resolve `{validateOutputHelper}` by probing `{validateOutputProbeOrder}` in
5
+ # order (installed SKF module path first, src/ dev-checkout fallback); first
6
+ # existing path wins. §2 runs it with `--export-gate` to obtain the
7
+ # agentskills.io export verdict — required-field presence, enum membership,
8
+ # JSON validity, and the SKILL.md Section 7b <-> scripts/assets cross-reference
9
+ # — as one deterministic JSON result, instead of re-deriving those checks
10
+ # in-prompt each run. package.md §1-4 renders its status from the same verdict.
11
+ validateOutputProbeOrder:
12
+ - '{project-root}/_bmad/skf/shared/scripts/skf-validate-output.py'
13
+ - '{project-root}/src/shared/scripts/skf-validate-output.py'
3
14
  ---
4
15
 
5
16
  <!-- Config: communicate in {communication_language}. -->
@@ -25,18 +36,20 @@ Determine the skill(s) to export and any flags:
25
36
 
26
37
  **Skill Path Discovery (version-aware — see `knowledge/version-paths.md`):**
27
38
  - If user provided one or more skill names or paths as arguments, use that list directly
28
- - If `--all` was passed, build the list from every skill in `{skills_output_folder}/.export-manifest.json.exports` whose `active_version` entry is not `status: "deprecated"` (deprecated skills are excluded from all exports — see step 4 §4b)
29
- - If no explicit skill and no `--all`, discover available skills using the export manifest:
30
- 1. Read `{skills_output_folder}/.export-manifest.json` — list skill names from `exports`
31
- 2. For each skill group directory in `{skills_output_folder}/`, check for `{skill_group}/active/{skill-name}/SKILL.md`
32
- 3. If neither manifest nor `active` symlink yields results, fall back to flat path: `{skills_output_folder}/{skill-name}/SKILL.md`
39
+ - If `--all` was passed, build the list from every skill in `{skills_output_folder}/.export-manifest.json.exports` whose `active_version` entry is not `status: "deprecated"` (deprecated skills are excluded from all exports — see step 4 §4b). **First-export fallback:** if the manifest is absent or its `exports` object is empty (a fresh repo with skills on disk but no prior export), do not resolve to an empty set — enumerate skills on disk instead, using the same discovery ladder as the no-argument branch below (`active` symlinks at `{skills_output_folder}/{skill-name}/active/{skill-name}/SKILL.md`, then flat `{skills_output_folder}/{skill-name}/SKILL.md`). Every disk-discovered skill is non-deprecated by definition — deprecation status lives only in the manifest.
40
+ - If no explicit skill and no `--all`, then:
41
+ - **Headless guard:** if `{headless_mode}` is true, HALT (exit code 2, `halt_reason: "input-missing"`)a non-interactive run cannot answer the skill-selection menu; the operator must pass an explicit `skill_name` or `--all`. Emit the error envelope per `references/result-envelope.md` with `skills: []`, `context_files_updated: []`, `manifest_path: null`.
42
+ - **Interactive:** discover available skills using the export manifest:
43
+ 1. Read `{skills_output_folder}/.export-manifest.json` list skill names from `exports`
44
+ 2. For each skill group directory in `{skills_output_folder}/`, check for `{skill_group}/active/{skill-name}/SKILL.md`
45
+ 3. If neither manifest nor `active` symlink yields results, fall back to flat path: `{skills_output_folder}/{skill-name}/SKILL.md`
33
46
  - If multiple skills are found, present the list and accept either a single selection or a comma-/space-separated multi-selection (e.g. `1, 2, 3` or `all`)
34
- - If no skills found, halt: "No skills found in {skills_output_folder}/. Run create-skill first."
47
+ - If no skills found, HALT (exit code 3, `halt_reason: "resolution-failure"`): "No skills found in {skills_output_folder}/. Run create-skill first." In headless, emit the error envelope per `references/result-envelope.md` with `skills: []`, `context_files_updated: []`, `manifest_path: null`.
35
48
 
36
49
  Store the resolved selection as `skill_batch` — a list of one or more skill names. `len(skill_batch) > 1` activates multi-skill mode (see §1c below).
37
50
 
38
51
  **Flag Parsing:**
39
- - `--all` flag: Check if provided. When true and no explicit skill list was given, `skill_batch` is the full non-deprecated manifest set (see above).
52
+ - `--all` flag: Check if provided. When true and no explicit skill list was given, `skill_batch` is the full non-deprecated manifest set — or, when no manifest exists yet, the full on-disk discovery set (see the first-export fallback above).
40
53
  - `--context-file` flag: Check if explicitly provided (CLAUDE.md, .cursorrules, or AGENTS.md). Replaces the old `--platform` flag.
41
54
  - `--dry-run` flag: Check if provided. Default: `false`
42
55
 
@@ -44,16 +57,9 @@ Store the resolved selection as `skill_batch` — a list of one or more skill na
44
57
 
45
58
  If `--context-file` is explicitly provided, use that single context file as the sole target. Determine the skill root from the first configured IDE that maps to that context file (or `.agents/skills/` for AGENTS.md if no matching IDE is configured). If other IDEs are configured in config.yaml, emit a note: "**Note:** Exporting to {context-file} only. config.yaml also lists: {other-ides}. Run without `--context-file` to export to all configured IDEs."
46
59
 
47
- If `--context-file` is NOT provided, read the `ides` list from config.yaml and map each IDE to its context file and skill root using the "IDE → Context File Mapping" table in `skf-export-skill/assets/managed-section-format.md`. Every IDE the installer offers has an explicit mapping — no silent skips.
60
+ If `--context-file` is NOT provided, read the `ides` list from config.yaml and map each entry to its `context_file` and `skill_root` using the "IDE → Context File Mapping" table plus the "Resolution rules" in `{managedSectionData}` — that canonical file carries the deduplication (group by context file; first configured IDE's skill root wins), the unknown-IDE default-and-warn, and the missing-`ides`-key (treat as empty list) behavior, each with its exact warning/report string. Every IDE the installer offers has an explicit mapping — no silent skips.
48
61
 
49
- For each IDE in `config.yaml.ides`:
50
-
51
- 1. Look up its `context_file` and `skill_root` from the canonical mapping table
52
- 2. If the IDE is not in the table, default to AGENTS.md / `.agents/skills/` and warn: "Unknown IDE '{value}' in config.yaml — defaulting to AGENTS.md with `.agents/skills/`"
53
-
54
- **Deduplication:** Group by `context_file`. When multiple IDE entries map to the same context file (e.g. both `codex` and `cline` map to AGENTS.md), deduplicate so each context file appears in `target_context_files` only once. Use the **first configured IDE's** `skill_root` for that context file. Report the deduplication: "Multiple IDEs target AGENTS.md — using {first-ide}'s skill root (`{skill_root}`). Each IDE's skills are installed to its own directory."
55
-
56
- **Missing-key handling:** If the `ides` key is absent from config.yaml (older installation or manually edited file), treat it as an empty list.
62
+ Apply those rules to `config.yaml.ides`, then:
57
63
 
58
64
  - If mapping produces one or more context files (after dedup), store as `target_context_files` list — each entry has `{context_file, skill_root}`
59
65
  - If mapping produces zero entries (empty ides list and no recognized entries), fall back to `[{context_file: "AGENTS.md", skill_root: ".agents/skills/"}]` with note: "No IDEs configured in config.yaml — defaulting to AGENTS.md with `.agents/skills/`."
@@ -64,13 +70,13 @@ For each IDE in `config.yaml.ides`:
64
70
 
65
71
  ### 1b. Detect Snippet Root Prefix Mismatch
66
72
 
67
- **Skip entirely if `snippet_skill_root_override` is set in `config.yaml`** — the authoring-repo escape hatch is already configured and any on-disk prefix that matches it is ground truth (see `assets/managed-section-format.md` override rules).
73
+ **Skip entirely if `snippet_skill_root_override` is set in `config.yaml`** — the authoring-repo escape hatch is already configured and any on-disk prefix that matches it is ground truth (see `{managedSectionData}` override rules).
68
74
 
69
75
  **Otherwise:** load `references/preflight-snippet-root-probe.md` and follow its probe + (a) Set override / (b) Proceed with IDE mapping / (c) Cancel gate protocol. The reference handles candidate snippet collection (manifest-driven), prefix observation, the mismatch warning, and headless default ((b) Proceed). Returns control to §1c on no-mismatch fast path or after a (b) choice.
70
76
 
71
77
  ### 1c. Multi-skill Mode (when `len(skill_batch) > 1`)
72
78
 
73
- **If `len(skill_batch) == 1`:** single-skill mode (legacy behavior) — every section below operates on the one skill without iteration. Skip this subsection.
79
+ **If `len(skill_batch) == 1`:** single-skill mode — every section below operates on the one skill without iteration. Skip this subsection.
74
80
 
75
81
  **If `len(skill_batch) > 1`:** load `references/multi-skill-mode.md` and apply its per-step behavior matrix. The reference partitions work so that step 1 §2–5 iterates per skill, step 1 §6 presents a single consolidated [C] gate, step 4 batches once across the whole run, and step 7 health check runs once. It also defines the all-or-nothing halt semantics if any single skill fails §2 validation.
76
82
 
@@ -95,15 +101,22 @@ Load all files from `{resolved_skill_package}`:
95
101
  - `references/` — Progressive disclosure directory
96
102
  - `context-snippet.md` — Existing snippet (will be regenerated)
97
103
 
98
- **Validation Checks:**
99
- 1. `SKILL.md` exists and is non-empty
100
- 2. `metadata.json` exists and is valid JSON
101
- 3. `metadata.json` contains required fields: `name`, `version`, `skill_type`, `source_authority`, `exports`, `generation_date`, `confidence_tier`
102
- 4. `metadata.json.exports` is a non-empty array (warn if empty — graceful handling)
104
+ **Validation (deterministic — the export gate):**
105
+
106
+ Run the export gate against the resolved package. Resolve `{validateOutputHelper}` from `{validateOutputProbeOrder}` (first existing path wins):
107
+
108
+ ```bash
109
+ python3 {validateOutputHelper} {resolved_skill_package} --export-gate
110
+ ```
111
+
112
+ The script emits one JSON verdict covering every check this step used to derive by hand: `SKILL.md` present and non-empty; `metadata.json` present and valid JSON; the required agentskills.io fields present (`name`, `version`, `skill_type`, `source_authority`, `exports`, `generation_date`, `confidence_tier`); enum membership (`skill_type` ∈ single/stack, `source_authority` ∈ official/internal/community, `confidence_tier` ∈ Quick/Forge/Forge+/Deep); a non-empty `exports` array (empty is a low warning, not a halt); and the SKILL.md Section 7b ↔ on-disk `scripts/`/`assets/` cross-reference (a §7b-named file absent on disk is a high issue; an unreferenced on-disk file is a low orphan warning). Read `result` (PASS/FAIL), `export_status` (READY/WARNINGS/NOT_READY), and the issue arrays under `validation.metadata.{issues,enum_issues}` and `validation.crossref_7b.{missing,orphans}`. **Retain this JSON as the export verdict** — step 2 (`package.md`) renders its status from it without re-deriving the checks.
103
113
 
104
- **If any required validation fails:**
105
- "**Export cannot proceed.** Missing or invalid: {list failures}
114
+ **If the script cannot run** (no `uv`/Python — e.g. claude.ai web): perform the equivalent checks by hand; `python3 {validateOutputHelper} --help` documents exactly what it verifies.
115
+
116
+ **If `result` is `FAIL` / `export_status` is `NOT_READY`** (any high-severity issue in `validation.*`):
117
+ "**Export cannot proceed.** Missing or invalid: {list the high-severity issue messages from the script's `validation.metadata.{issues,enum_issues}` and `validation.crossref_7b.missing`}
106
118
  Run create-skill to generate a complete skill first."
119
+ Then HALT (exit code 3, `halt_reason: "resolution-failure"`). In headless, emit the error envelope per `references/result-envelope.md` with the resolved `skills`, `context_files_updated: []`, `manifest_path: null`.
107
120
 
108
121
  ### 3. Read Skill Metadata
109
122
 
@@ -196,23 +209,12 @@ Continue to step 5 regardless — this is advisory, not blocking.
196
209
 
197
210
  **Are these the correct skills to export?**"
198
211
 
199
- ### 6. Present MENU OPTIONS
200
-
201
- Display: "**Select:** [C] Continue to packaging | [X] Cancel and exit (or type `cancel` / `exit` / `:q`)" (multi-skill mode: the single [C] gate covers the whole batch)
202
-
203
- #### Menu Handling Logic:
204
-
205
- - IF C: Proceed with loaded skill data, then load, read entire file, then execute {nextStepFile}
206
- - IF X (or `cancel` / `exit` / `:q`): Display "Cancelled — no packaging or context file writes were performed." and HALT (exit code 6, `halt_reason: "user-cancelled"`). In headless, emit the error envelope per SKILL.md "Result Contract (Headless)" with the resolved `skills`, `context_files_updated: []`, and `manifest_path: null`.
207
- - IF Any other: help user respond, then [Redisplay Menu Options](#6-present-menu-options)
208
-
209
- #### EXECUTION RULES:
210
-
211
- - ALWAYS halt and wait for user input after presenting menu
212
- - **GATE [default: C]** — If `{headless_mode}`: auto-proceed with [C] Continue, log: "headless: auto-continue past skill confirmation"
213
- - ONLY proceed to next step when user selects 'C'
212
+ ### 6. Confirmation Gate
214
213
 
215
- ## CRITICAL STEP COMPLETION NOTE
214
+ Display: "**Select:** [C] Continue to packaging | [X] Cancel and exit (or type `cancel` / `exit` / `:q`)" (multi-skill mode: the single [C] gate covers the whole batch), then wait for the reply.
216
215
 
217
- ONLY WHEN the user confirms the correct skill is loaded by selecting 'C' will you load and read fully `{nextStepFile}` to execute packaging.
216
+ - **[C]** proceed with the loaded skill data: load, read entirely, and execute `{nextStepFile}`.
217
+ - **[X]** / `cancel` / `exit` / `:q` — Display "Cancelled — no packaging or context file writes were performed." and HALT (exit code 6, `halt_reason: "user-cancelled"`). In headless, emit the error envelope per `references/result-envelope.md` with the resolved `skills`, `context_files_updated: []`, and `manifest_path: null`.
218
+ - **Any other input** — help the user respond, then redisplay this gate.
219
+ - **Headless** [default C]: auto-proceed with [C], log "headless: auto-continue past skill confirmation".
218
220
 
@@ -35,4 +35,4 @@ If any single skill fails validation in step 1 §2 (required-file or metadata-fi
35
35
 
36
36
  ## Single-skill mode (reference)
37
37
 
38
- `len(skill_batch) == 1` preserves the legacy behavior: every section operates on the one skill without iteration, no gate consolidation, no per-step table consultation. This file does not need to be loaded.
38
+ `len(skill_batch) == 1` runs the single-skill path: every section operates on the one skill without iteration, no gate consolidation, no per-step table consultation. This file does not need to be loaded.
@@ -43,10 +43,18 @@ Wait for user choice.
43
43
 
44
44
  ### (a) clear
45
45
 
46
+ The marker excision is deterministic surgery with one correct answer per input — a mis-parsed boundary silently corrupts the user's surrounding content. Delegate it to the tested `clear` action of `skf-rebuild-managed-sections.py`, the same helper `update-context.md` §9 uses for the between-marker swap; do not excise markers in-prompt. Resolve `{rebuildManagedSectionsHelper}` from `update-context.md`'s `{rebuildManagedSectionsProbeOrder}` frontmatter (first existing path wins). If no candidate exists, HALT (exit code 4, `halt_reason: "context-rebuild-failed"`) per `update-context.md` §9 — falling through to an in-prompt excision would regress the atomic-write + post-clear verify guarantee.
47
+
46
48
  For each file in `orphaned_context_files`:
47
49
 
48
- 1. Replace everything between `<!-- SKF:BEGIN` and `<!-- SKF:END -->` (inclusive) with an empty string, preserving surrounding content byte-exactly.
49
- 2. Append the file path to `orphans_cleared` (workflow-context list, surfaced in the §6 result contract).
50
+ 1. Run:
51
+
52
+ ```bash
53
+ python3 {rebuildManagedSectionsHelper} {file_path} clear
54
+ ```
55
+
56
+ The `clear` action removes the entire `<!-- SKF:BEGIN -->`…`<!-- SKF:END -->` block (and its surrounding blank lines), leaves the rest of the file intact, and performs an atomic temp-file + rename write with a post-clear verify that the section is gone. Treat any non-zero exit (or a `status: "error"` envelope) as a clear failure — HALT (exit code 4, `halt_reason: "context-rebuild-failed"`) reporting `{file_path}: {captured stderr}`. This branch is interactive-only (the headless default is (b) keep), so it emits no result envelope here.
57
+ 2. On success (`status: "ok"`, `action: "cleared"`), append the file path to `orphans_cleared`. On a non-empty list, record it in the §6 result contract as a `deviations[]` entry (`kind: "clear_orphan_context"`, `files: [...]`) — the extensible deviations mechanism summary.md §6 documents for choices that diverge from the canonical export path.
50
58
 
51
59
  ### (b) keep
52
60
 
@@ -58,7 +66,7 @@ Add each entry in `orphaned_context_files` to a separate `rewrite_context_files`
58
66
 
59
67
  Use `.agents/skills/` as the default skill root for rewritten orphans (the IDE-neutral path used when the original IDE mapping is no longer available).
60
68
 
61
- Record each rewritten file in `orphans_rewritten` (workflow-context list, surfaced in the §6 result contract).
69
+ Record each rewritten file in `orphans_rewritten`. On a non-empty list, record it in the §6 result contract as a `deviations[]` entry (`kind: "rewrite_orphan_context"`, `files: [...]`) — the same extensible deviations mechanism summary.md §6 documents.
62
70
 
63
71
  ## Downstream contract
64
72
 
@@ -1,5 +1,13 @@
1
1
  ---
2
2
  nextStepFile: 'generate-snippet.md'
3
+ # `{validateOutputHelper}` resolves from `{validateOutputProbeOrder}` (first
4
+ # existing path wins). Step 1 §2 already ran `--export-gate` and retained the
5
+ # JSON verdict; this step renders its status from that verdict. Only re-run the
6
+ # command below if the step-1 JSON is not in context (e.g. package.md entered
7
+ # directly). The verdict is deterministic — same package → same result.
8
+ validateOutputProbeOrder:
9
+ - '{project-root}/_bmad/skf/shared/scripts/skf-validate-output.py'
10
+ - '{project-root}/src/shared/scripts/skf-validate-output.py'
3
11
  ---
4
12
 
5
13
  <!-- Config: communicate in {communication_language}. Validate package contents in {document_output_language}. -->
@@ -34,19 +42,16 @@ Verify the skill package at `{resolved_skill_package}` (resolved in step 1 via m
34
42
  └── assets/ ← Optional: Templates, schemas, configs
35
43
  ```
36
44
 
37
- **Check each component:**
38
- 1. `SKILL.md` — Verify has frontmatter with `name` field
39
- 2. `metadata.json` Verify required agentskills.io fields:
40
- - `name` (string, non-empty)
41
- - `version` (string, semver format preferred)
42
- - `skill_type` ("single" or "stack")
43
- - `source_authority` ("official", "internal", or "community")
44
- - `exports` (array)
45
- - `generation_date` (ISO date string)
46
- - `confidence_tier` ("Quick", "Forge", "Forge+", or "Deep")
47
- 3. `references/` — If exists, check at least one .md file present
48
- 4. `scripts/` — If exists, verify at least one file present and each file referenced in SKILL.md Section 7b exists. Warn for orphaned scripts (present but not referenced).
49
- 5. `assets/` — If exists, verify at least one file present and each file referenced in SKILL.md Section 7b exists. Warn for orphaned assets (present but not referenced).
45
+ **Component checks — from the export-gate verdict (do not re-derive):**
46
+
47
+ Step 1 §2 already ran the export gate (`python3 {validateOutputHelper} {resolved_skill_package} --export-gate`) and retained its JSON. Read that verdict rather than re-listing the required fields, enum values, or Section 7b rules here — it deterministically covers all of it:
48
+
49
+ - `SKILL.md` present and non-empty; `metadata.json` present and valid JSON — `validation.skill_md.issues` / `validation.metadata.issues`
50
+ - Required agentskills.io fields present (`name`, `version`, `skill_type`, `source_authority`, `exports`, `generation_date`, `confidence_tier`) — `validation.metadata.issues`
51
+ - Enum membership (`skill_type`, `source_authority`, `confidence_tier`) `validation.metadata.enum_issues`
52
+ - SKILL.md Section 7b ↔ on-disk `scripts/`/`assets/` cross-reference — `validation.crossref_7b.missing` (high: §7b-named file absent on disk) and `validation.crossref_7b.orphans` (low: on-disk file not referenced in §7b)
53
+
54
+ If the step-1 JSON is not in context (e.g. this step was entered directly), re-run the command above to regenerate it — the verdict is deterministic. `references/` presence (at least one `.md`) remains a simple on-disk observation for the §4 report.
50
55
 
51
56
  ### 2. Validate Metadata Completeness
52
57
 
@@ -62,26 +67,26 @@ Check metadata.json for recommended (non-required) fields:
62
67
 
63
68
  ### 3. Assess Package Readiness
64
69
 
65
- Determine package status:
70
+ Read `export_status` directly from the export-gate verdict (step 1 §2) — do not re-compute the status by hand:
66
71
 
67
- **READY:** All required files present, all required metadata fields valid
68
- **WARNINGS:** Ready but with missing recommended fields or empty references/
69
- **NOT READY:** Missing required files or required metadata fields (should not reach here step 1 would have halted)
72
+ - **READY** the verdict has no issues (`export_status: "READY"`).
73
+ - **WARNINGS** only medium/low issues remain (`export_status: "WARNINGS"`): §7b orphans, an empty `exports` array, or the recommended-field notes from §2 above.
74
+ - **NOT READY** any high-severity issue (`export_status: "NOT_READY"`). Step 1 §2 halts on this, so a healthy run never reaches here; if it does, surface the high-severity messages and halt.
70
75
 
71
76
  ### 4. Report Package Status
72
77
 
73
78
  "**Package structure validated.**
74
79
 
75
- **Status:** {READY / WARNINGS}
80
+ **Status:** {export_status: READY / WARNINGS}
76
81
 
77
82
  **Required Components:**
78
83
  - SKILL.md: ✅
79
- - metadata.json: ✅ ({count} required fields valid)
84
+ - metadata.json: ✅ (required fields valid per export-gate verdict)
80
85
  - references/: {✅ present ({count} files) / ⚠️ not present}
81
86
 
82
- {If warnings:}
87
+ {If warnings (export_status: WARNINGS):}
83
88
  **Warnings:**
84
- - {list missing recommended fields}
89
+ - {list missing recommended fields from §2, plus any `validation.crossref_7b.orphans` and an empty `exports` warning from the verdict}
85
90
 
86
91
  **Package is ready for snippet generation.**"
87
92
 
@@ -89,16 +94,5 @@ Determine package status:
89
94
 
90
95
  Display: "**Proceeding to snippet generation...**"
91
96
 
92
- #### Menu Handling Logic:
93
-
94
- - After package validation completes, immediately load, read entire file, then execute {nextStepFile}
95
-
96
- #### EXECUTION RULES:
97
-
98
- - This is an auto-proceed step with no user choices
99
- - Proceed directly to next step after validation
100
-
101
- ## CRITICAL STEP COMPLETION NOTE
102
-
103
- ONLY WHEN package validation is complete will you load and read fully `{nextStepFile}` to execute snippet generation.
97
+ Auto-proceed (no user choices): once package validation is complete, load, read entirely, and execute `{nextStepFile}`.
104
98
 
@@ -5,6 +5,15 @@
5
5
  # truth by contract — no probe needed and the entire authoring-repo
6
6
  # escape hatch is already configured. Loaded once per export run, not
7
7
  # per skill.
8
+ # Resolve `{rebuildManagedSectionsHelper}` by probing
9
+ # `{rebuildManagedSectionsProbeOrder}` in order (installed SKF module
10
+ # path first, src/ dev-checkout fallback); first existing path wins.
11
+ # The `root-probe` action reads each candidate snippet's first line,
12
+ # parses/strips the `root:` prefix, and returns `observed_prefixes` +
13
+ # `mismatch` — deterministic prefix comparison the LLM must not re-derive.
14
+ rebuildManagedSectionsProbeOrder:
15
+ - '{project-root}/_bmad/skf/shared/scripts/skf-rebuild-managed-sections.py'
16
+ - '{project-root}/src/shared/scripts/skf-rebuild-managed-sections.py'
8
17
  ---
9
18
 
10
19
  <!-- Config: communicate in {communication_language}. Render the warning and gate prompt in {document_output_language}. -->
@@ -26,16 +35,26 @@ Loaded by `load-skill.md` §1b after `target_context_files` is resolved and `sni
26
35
 
27
36
  ## Probe Algorithm
28
37
 
29
- 1. Collect candidate snippet paths:
38
+ 1. Collect candidate snippet paths (manifest-driven orchestration — stays in-prompt):
30
39
  - Read `{skills_output_folder}/.export-manifest.json` if it exists. For each skill in `exports` with a resolvable `active_version`, add `{skills_output_folder}/{skill-name}/{active_version}/{skill-name}/context-snippet.md`.
31
40
  - Also include the current skill's snippet if present.
32
- 2. For each snippet that exists on disk, read the first line and parse the `root:` value. Strip the trailing `{skill-name}/` to extract the prefix (e.g. `skills/`, `.claude/skills/`).
33
- 3. Collect unique prefixes into `observed_prefixes`.
34
- 4. Compare against `target_context_files[0].skill_root` (the reference).
41
+ 2. **Read the prefixes and compare via the helper** — reading each snippet's first line, parsing/stripping the `root:` prefix, collecting the unique set, and comparing against the reference is deterministic prefix arithmetic with one correct answer per input. Resolve `{rebuildManagedSectionsHelper}` from `{rebuildManagedSectionsProbeOrder}` (frontmatter first existing path wins; if no candidate exists, skip the probe and continue to §2 without a warning rather than blocking export on a missing dev-only helper), then run:
42
+
43
+ ```bash
44
+ python3 {rebuildManagedSectionsHelper} root-probe {candidate-snippet-1} {candidate-snippet-2} … --reference-root {target_context_files[0].skill_root}
45
+ ```
46
+
47
+ Pass every candidate snippet path from step 1 as a positional argument and the reference `skill_root` as `--reference-root`. The helper reads each snippet that exists, parses its first-line `root:` value, strips the trailing `{skill-name}/` (recovered from the row's own `[skill-name v...]` header) to extract the prefix, and returns:
48
+
49
+ ```json
50
+ {"status": "ok", "reference_root": "…", "observed_prefixes": ["…"], "mismatch": true}
51
+ ```
52
+
53
+ Set `observed_prefixes = result["observed_prefixes"]` (already unique and sorted; missing or root-less snippets contribute nothing). `result["mismatch"]` is `true` when any observed prefix differs from the reference `skill_root` — the trigger for the Mismatch Gate below.
35
54
 
36
55
  ## Mismatch Gate
37
56
 
38
- **If `observed_prefixes` contains any value that does not match the reference `skill_root`:**
57
+ **If `result["mismatch"]` is `true`** (some value in `observed_prefixes` does not match the reference `skill_root`):
39
58
 
40
59
  Emit a single warning (once, not per snippet) and present resolution options before continuing to §2:
41
60
 
@@ -0,0 +1,28 @@
1
+ <!-- Config: emit exactly as specified — this is a machine-parsed contract. Loaded standalone by any halting stage; it back-references no other file. -->
2
+
3
+ # Headless Result Envelope
4
+
5
+ The single-line JSON envelope export-skill emits on non-interactive (`{headless_mode}`) runs. Pipeline consumers parse it to branch on the run's outcome, so its shape must be reproduced exactly. This file stands alone — every HARD-HALT stage can load it without SKILL.md in context.
6
+
7
+ ## Emission rule
8
+
9
+ - **Success / dry-run:** step 6 (`summary.md`) emits the envelope on **stdout**, once, before chaining to step 7.
10
+ - **Every HARD HALT:** emit the same envelope shape on **stderr** with `status: "error"`, then exit with the matching code.
11
+
12
+ ## Shape
13
+
14
+ ```
15
+ SKF_EXPORT_RESULT_JSON: {"status":"success|error|dry-run","skills":[],"context_files_updated":[],"manifest_path":"…|null","headless_decisions":[],"exit_code":0,"halt_reason":null}
16
+ ```
17
+
18
+ ## Fields
19
+
20
+ - `status` — `"success"` on the terminal happy path, `"dry-run"` when `--dry-run` skipped the §4 context and manifest writes (the run still reaches the terminal step), `"error"` on any HALT.
21
+ - `skills` — resolved skill names in the batch (JSON array).
22
+ - `context_files_updated` — context files successfully written this run (JSON array; `[]` when a HALT preceded any write).
23
+ - `manifest_path` — the written manifest path, or `null` when no manifest write completed.
24
+ - `headless_decisions` — the `{gate, default_action, taken_action, reason}` entries logged as each gate auto-resolved (JSON array).
25
+ - `exit_code` — 0 success/dry-run · 2 input-missing · 3 resolution-failure · 4 write-failure · 5 state-conflict · 6 user-cancelled.
26
+ - `halt_reason` — `null` on success/dry-run, else one of: `"input-missing"`, `"resolution-failure"`, `"malformed-markers"`, `"manifest-write-failed"`, `"context-rebuild-failed"`, `"write-failed"`, `"user-cancelled"`. Each value is emitted by a real HALT site (see the SKILL.md Exit Codes table for the code↔reason map); the enum lists no value that no stage emits.
27
+
28
+ A halting stage sets the branch-specific fields inline (e.g. `manifest_path: null`, `context_files_updated: []`) and fills the rest from the shape above.
@@ -132,7 +132,7 @@ No files were written. To run the export for real:
132
132
 
133
133
  Write the result contract per `shared/references/output-contract-schema.md`: the per-run record at `{skills_output_folder}/export-skill-result-{timestamp}.json` (reuse the activation-stored `{timestamp}`, resolution to seconds) and a copy at `{skills_output_folder}/export-skill-result-latest.json` (stable path for pipeline consumers — copy, not symlink). Include all context files and target managed-section files in `outputs`; include total always-on and on-trigger token counts in `summary`.
134
134
 
135
- When `{headless_mode}` is true, also emit the single-line envelope on **stdout** before chaining to step 7 (matches the SKILL.md "Result Contract (Headless)" shape):
135
+ When `{headless_mode}` is true, also emit the single-line envelope on **stdout** before chaining to step 7 (per `references/result-envelope.md`):
136
136
 
137
137
  ```
138
138
  SKF_EXPORT_RESULT_JSON: {"status":"success","skills":{skill_batch_names},"context_files_updated":{context_files_updated},"manifest_path":"{skills_output_folder}/.export-manifest.json","headless_decisions":{headless_decisions},"exit_code":0,"halt_reason":null}
@@ -156,11 +156,17 @@ Substitute `{skill_batch_names}`, `{context_files_updated}`, and `{headless_deci
156
156
 
157
157
  Other workflow choices that diverge from the strict spec path may add their own entries with a distinct `kind` value — auditors then have one place to look for "what did this run choose to do differently from the canonical flow." Omit the field when there are no deviations rather than writing an empty array, so the absence is readable as "ran the canonical path."
158
158
 
159
- ### 7. Chain to Health Check
159
+ ### 6b. Post-Export Hook (Optional)
160
+
161
+ If `{onCompleteCommand}` (resolved at SKILL.md On Activation §4 from `workflow.on_complete`) is non-empty, invoke it now — after both the per-run and `-latest` result JSON have been written:
160
162
 
161
- ONLY WHEN the export summary, distribution instructions, and result contract are complete will you then load, read the full file, and execute `{nextStepFile}`. The health-check step is the true terminal step — do not stop here even though the summary reads as final.
163
+ ```bash
164
+ {onCompleteCommand} --result-path={skills_output_folder}/export-skill-result-{timestamp}.json
165
+ ```
162
166
 
163
- ## CRITICAL STEP COMPLETION NOTE
167
+ Run it with a bounded timeout. On success, continue. On non-zero exit, timeout, or any failure, append the reason to `workflow_warnings[]` (e.g. `on_complete — failed (exit {N}): {stderr_first_line}`) and continue. **The hook must never fail the workflow** — it is integration glue (downstream distribution, notifier, pipeline chain) and any failure there is orthogonal to the export outcome. When `{onCompleteCommand}` is empty (bundled default), skip this section entirely.
168
+
169
+ ### 7. Chain to Health Check
164
170
 
165
- This step chains to the local health-check step (`{nextStepFile}`), which in turn delegates to `shared/health-check.md`. After the health check completes, the export-skill workflow is fully done.
171
+ ONLY WHEN the export summary, distribution instructions, result contract, and on-complete hook (or its skip on an empty `{onCompleteCommand}`) are complete will you then load, read the full file, and execute `{nextStepFile}`. The health-check step is the true terminal step — do not stop here even though the summary reads as final.
166
172