bmad-module-skill-forge 2.1.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (435) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/README.md +51 -49
  3. package/docs/404.md +10 -8
  4. package/docs/_data/pinned.yaml +22 -13
  5. package/docs/_internal/STABILITY.md +58 -35
  6. package/docs/agents.md +39 -53
  7. package/docs/architecture.md +65 -51
  8. package/docs/bmad-synergy.md +53 -51
  9. package/docs/campaign.md +127 -75
  10. package/docs/concepts.md +34 -28
  11. package/docs/examples.md +70 -68
  12. package/docs/forge-auto.md +34 -31
  13. package/docs/getting-started.md +118 -57
  14. package/docs/how-it-works.md +25 -21
  15. package/docs/index.md +15 -15
  16. package/docs/skill-model.md +70 -59
  17. package/docs/troubleshooting.md +135 -18
  18. package/docs/verifying-a-skill.md +83 -57
  19. package/docs/why-skf.md +24 -22
  20. package/docs/workflows.md +274 -110
  21. package/package.json +18 -10
  22. package/src/forger/preferences.yaml +8 -1
  23. package/src/knowledge/agentskills-spec.md +2 -0
  24. package/src/knowledge/ccc-bridge.md +40 -24
  25. package/src/knowledge/confidence-tiers.md +9 -5
  26. package/src/knowledge/overview.md +3 -3
  27. package/src/knowledge/progressive-capability.md +8 -8
  28. package/src/knowledge/provenance-tracking.md +9 -5
  29. package/src/knowledge/qmd-registry.md +2 -2
  30. package/src/knowledge/skf-knowledge-index.csv +2 -2
  31. package/src/knowledge/skill-lifecycle.md +18 -11
  32. package/src/knowledge/split-body-strategy.md +0 -3
  33. package/src/knowledge/tool-resolution.md +4 -2
  34. package/src/knowledge/version-paths.md +101 -15
  35. package/src/module-help.csv +3 -3
  36. package/src/module.yaml +10 -0
  37. package/src/shared/data/ast-grep-recipes.yaml +608 -0
  38. package/src/shared/data/ide-context-files.json +30 -0
  39. package/src/shared/health-check.md +32 -12
  40. package/src/shared/references/description-guard-protocol.md +14 -9
  41. package/src/shared/references/feasibility-report-schema.md +19 -13
  42. package/src/shared/references/headless-gate-convention.md +55 -3
  43. package/src/shared/references/output-contract-schema.md +19 -8
  44. package/src/shared/references/pipeline-contracts.md +94 -29
  45. package/src/shared/references/tessl-review.md +77 -0
  46. package/src/shared/scripts/schemas/skf-analyze-result-envelope.v1.json +194 -0
  47. package/src/shared/scripts/schemas/skf-audit-result-envelope.v1.json +192 -0
  48. package/src/shared/scripts/schemas/skf-brief-result-envelope.v1.json +32 -4
  49. package/src/shared/scripts/schemas/skf-campaign-result-envelope.v1.json +174 -0
  50. package/src/shared/scripts/schemas/skf-create-skill-result-envelope.v1.json +284 -0
  51. package/src/shared/scripts/schemas/skf-drop-skill-result-envelope.v1.json +164 -0
  52. package/src/shared/scripts/schemas/skf-export-result-envelope.v1.json +160 -0
  53. package/src/shared/scripts/schemas/skf-quick-skill-result-envelope.v1.json +261 -0
  54. package/src/shared/scripts/schemas/skf-refine-architecture-result-envelope.v1.json +192 -0
  55. package/src/shared/scripts/schemas/skf-rename-skill-result-envelope.v1.json +179 -0
  56. package/src/shared/scripts/schemas/skf-setup-result-envelope.v1.json +27 -11
  57. package/src/shared/scripts/schemas/skf-stack-result-envelope.v1.json +176 -0
  58. package/src/shared/scripts/schemas/skf-test-result-envelope.v1.json +173 -0
  59. package/src/shared/scripts/schemas/skf-update-result-envelope.v1.json +19 -5
  60. package/src/shared/scripts/schemas/skf-verify-stack-result-envelope.v1.json +180 -0
  61. package/src/shared/scripts/schemas/skill-brief.v1.json +34 -0
  62. package/src/shared/scripts/schemas/workspace-detection.v1.json +1 -1
  63. package/src/shared/scripts/skf-atomic-write.py +30 -14
  64. package/src/shared/scripts/skf-build-change-manifest.py +2203 -24
  65. package/src/shared/scripts/skf-ccc-git-hygiene.py +532 -0
  66. package/src/shared/scripts/skf-check-unit-records.py +184 -0
  67. package/src/shared/scripts/skf-check-workspace-drift.py +538 -9
  68. package/src/shared/scripts/skf-classify-changed-files.py +694 -0
  69. package/src/shared/scripts/skf-comention-pairs.py +1333 -123
  70. package/src/shared/scripts/skf-compare-file-hashes.py +1 -1
  71. package/src/shared/scripts/skf-count-imports.py +1867 -0
  72. package/src/shared/scripts/skf-count-tokens.py +1 -1
  73. package/src/shared/scripts/skf-derive-assembly-shape.py +3 -2
  74. package/src/shared/scripts/skf-description-guard.py +117 -9
  75. package/src/shared/scripts/skf-detect-docs.py +892 -4
  76. package/src/shared/scripts/skf-detect-language.py +486 -107
  77. package/src/shared/scripts/skf-detect-registry.py +887 -0
  78. package/src/shared/scripts/skf-detect-scripts-assets.py +1 -1
  79. package/src/shared/scripts/skf-detect-tools.py +215 -27
  80. package/src/shared/scripts/skf-detect-workspaces.py +506 -30
  81. package/src/shared/scripts/skf-disqualify-candidates.py +821 -182
  82. package/src/shared/scripts/skf-emit-brief-result-envelope.py +69 -191
  83. package/src/shared/scripts/skf-emit-result-envelope.py +1604 -106
  84. package/src/shared/scripts/skf-enumerate-stack-skills.py +986 -117
  85. package/src/shared/scripts/skf-extract-public-api.py +4084 -85
  86. package/src/shared/scripts/skf-extraction-inventory.py +746 -0
  87. package/src/shared/scripts/skf-extraction-snapshot.py +539 -0
  88. package/src/shared/scripts/skf-fetch-temporal.py +674 -0
  89. package/src/shared/scripts/skf-find-cycles.py +97 -29
  90. package/src/shared/scripts/skf-find-test-report.py +476 -0
  91. package/src/shared/scripts/skf-forge-tier-rw.py +444 -203
  92. package/src/shared/scripts/skf-github-fetch.py +365 -0
  93. package/src/shared/scripts/skf-github-probe.py +661 -0
  94. package/src/shared/scripts/skf-hash-content.py +166 -12
  95. package/src/shared/scripts/skf-language-corpora.py +1 -1
  96. package/src/shared/scripts/skf-load-provenance.py +159 -27
  97. package/src/shared/scripts/skf-manifest-ops.py +1 -1
  98. package/src/shared/scripts/skf-merge-ccc-exclusions.py +2307 -223
  99. package/src/shared/scripts/skf-merge-doc-urls.py +1 -1
  100. package/src/shared/scripts/skf-names-present.py +221 -0
  101. package/src/shared/scripts/skf-pair-intersect.py +119 -28
  102. package/src/shared/scripts/skf-parse-gaps.py +1384 -0
  103. package/src/shared/scripts/skf-preapply.py +1 -1
  104. package/src/shared/scripts/skf-preflight.py +161 -27
  105. package/src/shared/scripts/skf-promote-staged.py +430 -0
  106. package/src/shared/scripts/skf-provenance-gap-dispatch.py +39 -7
  107. package/src/shared/scripts/skf-qmd-classify-collections.py +229 -45
  108. package/src/shared/scripts/skf-quick-batch.py +774 -0
  109. package/src/shared/scripts/skf-rebuild-managed-sections.py +972 -88
  110. package/src/shared/scripts/skf-recommend-scope-type.py +323 -156
  111. package/src/shared/scripts/skf-render-metadata-stats.py +156 -12
  112. package/src/shared/scripts/skf-render-quick-metadata.py +132 -28
  113. package/src/shared/scripts/skf-render-stack-metadata.py +976 -0
  114. package/src/shared/scripts/skf-resolve-authoritative-files.py +128 -13
  115. package/src/shared/scripts/skf-resolve-package.py +523 -106
  116. package/src/shared/scripts/skf-rewrite-skill-name.py +433 -47
  117. package/src/shared/scripts/skf-run-lock.py +577 -0
  118. package/src/shared/scripts/skf-scan-manifests.py +998 -57
  119. package/src/shared/scripts/skf-scan-skill-md-structure.py +1341 -37
  120. package/src/shared/scripts/skf-severity-classify.py +712 -108
  121. package/src/shared/scripts/skf-shape-detect.py +298 -204
  122. package/src/shared/scripts/skf-shard-body.py +9 -8
  123. package/src/shared/scripts/skf-skill-inventory.py +2412 -89
  124. package/src/shared/scripts/skf-skills-module.py +472 -0
  125. package/src/shared/scripts/skf-source-tree.py +1796 -0
  126. package/src/shared/scripts/skf-structural-diff.py +670 -119
  127. package/src/shared/scripts/skf-tessl-review.py +706 -0
  128. package/src/shared/scripts/skf-update-active-symlink.py +5 -5
  129. package/src/shared/scripts/skf-update-run-state.py +624 -0
  130. package/src/shared/scripts/skf-validate-brief-inputs.py +92 -29
  131. package/src/shared/scripts/skf-validate-brief-schema.py +4 -1
  132. package/src/shared/scripts/skf-validate-feasibility-report.py +577 -66
  133. package/src/shared/scripts/skf-validate-frontmatter.py +103 -26
  134. package/src/shared/scripts/skf-validate-output.py +712 -64
  135. package/src/shared/scripts/skf-validate-pins.py +1 -1
  136. package/src/shared/scripts/skf-verify-no-trace.py +116 -10
  137. package/src/shared/scripts/skf-verify-provenance-completeness.py +2919 -54
  138. package/src/shared/scripts/skf-write-skill-brief.py +367 -19
  139. package/src/shared/tool-requirements.yaml +201 -0
  140. package/src/skf-analyze-source/SKILL.md +41 -36
  141. package/src/skf-analyze-source/assets/skill-brief-schema.md +7 -8
  142. package/src/skf-analyze-source/customize.toml +36 -24
  143. package/src/skf-analyze-source/references/auto-docs-only.md +58 -20
  144. package/src/skf-analyze-source/references/continue.md +2 -13
  145. package/src/skf-analyze-source/references/discover-additional-source.md +147 -0
  146. package/src/skf-analyze-source/references/generate-briefs.md +121 -55
  147. package/src/skf-analyze-source/references/headless-contract.md +42 -15
  148. package/src/skf-analyze-source/references/identify-units.md +96 -110
  149. package/src/skf-analyze-source/references/init.md +73 -71
  150. package/src/skf-analyze-source/references/map-and-detect.md +123 -105
  151. package/src/skf-analyze-source/references/map-unit-exports.md +68 -0
  152. package/src/skf-analyze-source/references/recommend.md +51 -70
  153. package/src/skf-analyze-source/references/scan-project.md +60 -84
  154. package/src/skf-analyze-source/references/scan-root.md +39 -0
  155. package/src/skf-analyze-source/references/step-auto-scope-coexistence.md +47 -0
  156. package/src/skf-analyze-source/references/step-auto-scope-corpora.md +53 -0
  157. package/src/skf-analyze-source/references/step-auto-scope-split.md +91 -0
  158. package/src/skf-analyze-source/references/step-auto-scope.md +208 -293
  159. package/src/skf-analyze-source/references/step-shape-detect.md +14 -12
  160. package/src/skf-analyze-source/references/unit-detection-heuristics.md +37 -42
  161. package/src/skf-audit-skill/SKILL.md +43 -51
  162. package/src/skf-audit-skill/assets/drift-report-template.md +27 -3
  163. package/src/skf-audit-skill/customize.toml +41 -20
  164. package/src/skf-audit-skill/references/constituent-freshness.md +91 -0
  165. package/src/skf-audit-skill/references/doc-drift.md +141 -0
  166. package/src/skf-audit-skill/references/headless-contract.md +29 -0
  167. package/src/skf-audit-skill/references/init.md +148 -210
  168. package/src/skf-audit-skill/references/re-index.md +96 -108
  169. package/src/skf-audit-skill/references/report.md +96 -33
  170. package/src/skf-audit-skill/references/semantic-diff.md +27 -18
  171. package/src/skf-audit-skill/references/severity-classify.md +79 -65
  172. package/src/skf-audit-skill/references/severity-rules.md +15 -6
  173. package/src/skf-audit-skill/references/structural-diff.md +75 -90
  174. package/src/skf-audit-skill/references/upstream-checkout.md +77 -0
  175. package/src/skf-audit-skill/scripts/render-drift-tables.py +685 -0
  176. package/src/skf-brief-skill/SKILL.md +36 -25
  177. package/src/skf-brief-skill/assets/description-voice-examples.md +1 -1
  178. package/src/skf-brief-skill/assets/scope-templates.md +17 -24
  179. package/src/skf-brief-skill/assets/skill-brief-schema.md +29 -15
  180. package/src/skf-brief-skill/customize.toml +48 -20
  181. package/src/skf-brief-skill/references/analyze-target.md +142 -125
  182. package/src/skf-brief-skill/references/confirm-brief.md +10 -8
  183. package/src/skf-brief-skill/references/draft-checkpoint.md +36 -17
  184. package/src/skf-brief-skill/references/gather-intent-ratify.md +68 -0
  185. package/src/skf-brief-skill/references/gather-intent.md +87 -182
  186. package/src/skf-brief-skill/references/headless-args.md +84 -16
  187. package/src/skf-brief-skill/references/health-check.md +1 -1
  188. package/src/skf-brief-skill/references/invocation-contract.md +18 -13
  189. package/src/skf-brief-skill/references/portfolio-similarity-check.md +1 -1
  190. package/src/skf-brief-skill/references/qmd-collection-registration.md +7 -10
  191. package/src/skf-brief-skill/references/scope-definition.md +123 -47
  192. package/src/skf-brief-skill/references/step-auto-brief.md +24 -80
  193. package/src/skf-brief-skill/references/step-auto-validate.md +20 -121
  194. package/src/skf-brief-skill/references/version-resolution.md +3 -2
  195. package/src/skf-brief-skill/references/write-brief.md +66 -57
  196. package/src/skf-campaign/SKILL.md +31 -34
  197. package/src/skf-campaign/assets/campaign-state-schema.json +25 -4
  198. package/src/skf-campaign/customize.toml +47 -16
  199. package/src/skf-campaign/references/campaign-contracts.md +39 -29
  200. package/src/skf-campaign/references/campaign-directive-spec.md +4 -2
  201. package/src/skf-campaign/references/health-check.md +7 -16
  202. package/src/skf-campaign/references/step-01-setup.md +46 -84
  203. package/src/skf-campaign/references/step-02-strategy.md +31 -30
  204. package/src/skf-campaign/references/step-03-pins.md +26 -18
  205. package/src/skf-campaign/references/step-04-provenance.md +24 -23
  206. package/src/skf-campaign/references/step-05-skill-loop.md +67 -48
  207. package/src/skf-campaign/references/step-06-batch.md +41 -34
  208. package/src/skf-campaign/references/step-07-capstone.md +40 -25
  209. package/src/skf-campaign/references/step-08-verify.md +28 -29
  210. package/src/skf-campaign/references/step-09-refine.md +29 -30
  211. package/src/skf-campaign/references/step-10-export.md +48 -36
  212. package/src/skf-campaign/references/step-11-maintenance.md +31 -34
  213. package/src/skf-campaign/references/step-resume.md +37 -68
  214. package/src/skf-campaign/scripts/campaign-deps.py +57 -18
  215. package/src/skf-campaign/scripts/campaign-parse-manifest.py +361 -54
  216. package/src/skf-campaign/scripts/campaign-provenance.py +96 -53
  217. package/src/skf-campaign/scripts/campaign-quality-gate.py +592 -0
  218. package/src/skf-campaign/scripts/campaign-render-batch.py +257 -49
  219. package/src/skf-campaign/scripts/campaign-render-kickoff.py +343 -50
  220. package/src/skf-campaign/scripts/campaign-report.py +204 -37
  221. package/src/skf-campaign/scripts/campaign-state.py +1128 -0
  222. package/src/skf-campaign/scripts/campaign-status.py +10 -74
  223. package/src/skf-campaign/scripts/campaign-validate-pins.py +30 -3
  224. package/src/skf-campaign/scripts/campaign-validate-state.py +34 -4
  225. package/src/skf-campaign/templates/campaign-brief-template.yaml +4 -5
  226. package/src/skf-campaign/templates/campaign-report-template.md +5 -1
  227. package/src/skf-campaign/templates/kickoff-template.md +0 -14
  228. package/src/skf-create-skill/SKILL.md +27 -20
  229. package/src/skf-create-skill/assets/compile-assembly-rules.md +6 -5
  230. package/src/skf-create-skill/assets/skill-sections.md +17 -6
  231. package/src/skf-create-skill/customize.toml +20 -8
  232. package/src/skf-create-skill/references/authoritative-files-protocol.md +41 -42
  233. package/src/skf-create-skill/references/batch-mode.md +81 -0
  234. package/src/skf-create-skill/references/ccc-index-check.md +27 -0
  235. package/src/skf-create-skill/references/compile.md +107 -29
  236. package/src/skf-create-skill/references/component-extraction.md +113 -91
  237. package/src/skf-create-skill/references/enrich.md +41 -23
  238. package/src/skf-create-skill/references/entry-points-by-hand.md +20 -0
  239. package/src/skf-create-skill/references/extract.md +200 -161
  240. package/src/skf-create-skill/references/extraction-patterns-by-hand.md +141 -0
  241. package/src/skf-create-skill/references/extraction-patterns-tracing.md +2 -2
  242. package/src/skf-create-skill/references/extraction-patterns.md +584 -196
  243. package/src/skf-create-skill/references/generate-artifacts.md +145 -93
  244. package/src/skf-create-skill/references/health-check.md +1 -1
  245. package/src/skf-create-skill/references/load-brief.md +53 -36
  246. package/src/skf-create-skill/references/relabel-rule.md +12 -0
  247. package/src/skf-create-skill/references/report.md +28 -59
  248. package/src/skf-create-skill/references/source-resolution-protocols.md +49 -155
  249. package/src/skf-create-skill/references/step-auto-shard.md +20 -93
  250. package/src/skf-create-skill/references/step-doc-rot.md +44 -60
  251. package/src/skf-create-skill/references/step-doc-sources.md +55 -18
  252. package/src/skf-create-skill/references/sub/ccc-discover.md +18 -7
  253. package/src/skf-create-skill/references/sub/fetch-docs.md +106 -57
  254. package/src/skf-create-skill/references/sub/fetch-temporal.md +53 -166
  255. package/src/skf-create-skill/references/tier-degradation-rules.md +18 -9
  256. package/src/skf-create-skill/references/validate.md +173 -99
  257. package/src/skf-create-skill/scripts/scan-doc-rot.py +232 -99
  258. package/src/skf-create-stack-skill/SKILL.md +29 -56
  259. package/src/skf-create-stack-skill/assets/metadata-contract.md +51 -0
  260. package/src/skf-create-stack-skill/assets/provenance-map-schema.md +15 -15
  261. package/src/skf-create-stack-skill/assets/stack-skill-template.md +23 -57
  262. package/src/skf-create-stack-skill/customize.toml +23 -12
  263. package/src/skf-create-stack-skill/references/compile-stack.md +57 -66
  264. package/src/skf-create-stack-skill/references/compose-mode-rules.md +24 -44
  265. package/src/skf-create-stack-skill/references/detect-integrations.md +92 -95
  266. package/src/skf-create-stack-skill/references/detect-manifests.md +46 -71
  267. package/src/skf-create-stack-skill/references/generate-output.md +138 -128
  268. package/src/skf-create-stack-skill/references/init.md +90 -32
  269. package/src/skf-create-stack-skill/references/integration-patterns.md +1 -17
  270. package/src/skf-create-stack-skill/references/invocation-contract.md +34 -0
  271. package/src/skf-create-stack-skill/references/manifest-patterns.md +32 -20
  272. package/src/skf-create-stack-skill/references/parallel-extract.md +112 -38
  273. package/src/skf-create-stack-skill/references/rank-and-confirm.md +57 -75
  274. package/src/skf-create-stack-skill/references/report.md +39 -33
  275. package/src/skf-create-stack-skill/references/validate.md +20 -39
  276. package/src/skf-drop-skill/SKILL.md +28 -51
  277. package/src/skf-drop-skill/customize.toml +44 -30
  278. package/src/skf-drop-skill/references/execute.md +79 -146
  279. package/src/skf-drop-skill/references/invocation-contract.md +64 -0
  280. package/src/skf-drop-skill/references/report.md +46 -30
  281. package/src/skf-drop-skill/references/select.md +118 -124
  282. package/src/skf-drop-skill/scripts/dir-sizes.py +54 -26
  283. package/src/skf-drop-skill/scripts/drop-roster.py +322 -0
  284. package/src/skf-export-skill/SKILL.md +40 -62
  285. package/src/skf-export-skill/assets/managed-section-format.md +14 -50
  286. package/src/skf-export-skill/assets/snippet-format.md +3 -1
  287. package/src/skf-export-skill/customize.toml +42 -13
  288. package/src/skf-export-skill/references/generate-snippet.md +54 -46
  289. package/src/skf-export-skill/references/health-check.md +2 -0
  290. package/src/skf-export-skill/references/invocation-contract.md +15 -0
  291. package/src/skf-export-skill/references/load-skill.md +88 -62
  292. package/src/skf-export-skill/references/manifest-rebuild.md +9 -10
  293. package/src/skf-export-skill/references/multi-skill-mode.md +4 -4
  294. package/src/skf-export-skill/references/orphan-context-detection.md +13 -5
  295. package/src/skf-export-skill/references/orphan-row-detection.md +31 -22
  296. package/src/skf-export-skill/references/package.md +15 -73
  297. package/src/skf-export-skill/references/preflight-snippet-root-probe.md +51 -70
  298. package/src/skf-export-skill/references/result-envelope.md +31 -16
  299. package/src/skf-export-skill/references/summary.md +41 -17
  300. package/src/skf-export-skill/references/token-report.md +4 -12
  301. package/src/skf-export-skill/references/update-context.md +118 -237
  302. package/src/skf-forger/SKILL.md +61 -37
  303. package/src/skf-forger/bmad-skill-manifest.yaml +4 -1
  304. package/src/skf-forger/customize.toml +43 -0
  305. package/src/skf-forger/references/pipeline-mode.md +73 -18
  306. package/src/skf-forger/scripts/forge-status.py +299 -0
  307. package/src/skf-forger/scripts/parse-pipeline.py +322 -54
  308. package/src/skf-forger/scripts/pipeline-gate.py +428 -0
  309. package/src/skf-forger/scripts/pipeline-journal.py +1052 -0
  310. package/src/skf-quick-skill/SKILL.md +54 -53
  311. package/src/skf-quick-skill/assets/skill-template.md +4 -2
  312. package/src/skf-quick-skill/customize.toml +51 -20
  313. package/src/skf-quick-skill/references/batch-mode.md +74 -21
  314. package/src/skf-quick-skill/references/compile.md +30 -31
  315. package/src/skf-quick-skill/references/ecosystem-check.md +7 -57
  316. package/src/skf-quick-skill/references/finalize.md +69 -18
  317. package/src/skf-quick-skill/references/halt-contract.md +41 -29
  318. package/src/skf-quick-skill/references/health-check.md +5 -3
  319. package/src/skf-quick-skill/references/quick-extract.md +114 -45
  320. package/src/skf-quick-skill/references/registry-resolution.md +9 -64
  321. package/src/skf-quick-skill/references/resolve-target.md +116 -66
  322. package/src/skf-quick-skill/references/write-and-validate.md +79 -40
  323. package/src/skf-refine-architecture/SKILL.md +43 -53
  324. package/src/skf-refine-architecture/customize.toml +49 -20
  325. package/src/skf-refine-architecture/references/compile.md +97 -54
  326. package/src/skf-refine-architecture/references/exit-codes.md +30 -0
  327. package/src/skf-refine-architecture/references/finding-storage.md +21 -0
  328. package/src/skf-refine-architecture/references/gap-analysis.md +101 -38
  329. package/src/skf-refine-architecture/references/improvements.md +14 -20
  330. package/src/skf-refine-architecture/references/init.md +98 -57
  331. package/src/skf-refine-architecture/references/issue-detection.md +32 -39
  332. package/src/skf-refine-architecture/references/refinement-rules.md +37 -48
  333. package/src/skf-refine-architecture/references/report.md +65 -54
  334. package/src/skf-refine-architecture/scripts/skf-check-preservation.py +1619 -0
  335. package/src/skf-rename-skill/SKILL.md +19 -54
  336. package/src/skf-rename-skill/customize.toml +32 -26
  337. package/src/skf-rename-skill/references/execute.md +230 -184
  338. package/src/skf-rename-skill/references/exit-codes.md +7 -7
  339. package/src/skf-rename-skill/references/health-check.md +1 -7
  340. package/src/skf-rename-skill/references/invocation-contract.md +25 -0
  341. package/src/skf-rename-skill/references/report.md +63 -52
  342. package/src/skf-rename-skill/references/select.md +197 -115
  343. package/src/skf-rename-skill/scripts/skf-validate-rename-name.py +161 -21
  344. package/src/skf-setup/SKILL.md +26 -26
  345. package/src/skf-setup/customize.toml +14 -10
  346. package/src/skf-setup/references/auto-index.md +50 -63
  347. package/src/skf-setup/references/ccc-index.md +29 -89
  348. package/src/skf-setup/references/detect-and-tier.md +58 -66
  349. package/src/skf-setup/references/health-check.md +2 -0
  350. package/src/skf-setup/references/invocation-contract.md +14 -0
  351. package/src/skf-setup/references/report.md +43 -166
  352. package/src/skf-setup/references/tier-rules.md +5 -5
  353. package/src/skf-setup/references/write-config.md +34 -57
  354. package/src/skf-test-skill/SKILL.md +17 -57
  355. package/src/skf-test-skill/assets/output-section-formats.md +33 -34
  356. package/src/skf-test-skill/customize.toml +27 -13
  357. package/src/skf-test-skill/references/coherence-check.md +134 -62
  358. package/src/skf-test-skill/references/coverage-check-tiers.md +35 -0
  359. package/src/skf-test-skill/references/coverage-check.md +217 -254
  360. package/src/skf-test-skill/references/detect-mode.md +5 -5
  361. package/src/skf-test-skill/references/external-validators.md +94 -82
  362. package/src/skf-test-skill/references/health-check.md +6 -7
  363. package/src/skf-test-skill/references/init.md +163 -88
  364. package/src/skf-test-skill/references/invocation-contract.md +66 -0
  365. package/src/skf-test-skill/references/migration-section-rules.md +5 -2
  366. package/src/skf-test-skill/references/report.md +162 -142
  367. package/src/skf-test-skill/references/score.md +80 -107
  368. package/src/skf-test-skill/references/scoring-rules.md +41 -155
  369. package/src/skf-test-skill/references/source-access-protocol.md +19 -92
  370. package/src/skf-test-skill/references/step-hard-gate.md +51 -33
  371. package/src/skf-test-skill/scripts/aggregate-coherence.py +218 -30
  372. package/src/skf-test-skill/scripts/build-result-context.py +287 -0
  373. package/src/skf-test-skill/scripts/check-metadata-coherence.py +37 -4
  374. package/src/skf-test-skill/scripts/combine-external-scores.py +23 -6
  375. package/src/skf-test-skill/scripts/compute-score.py +223 -45
  376. package/src/skf-test-skill/scripts/gap-ledger.py +1381 -0
  377. package/src/skf-test-skill/scripts/hard-gate.py +203 -0
  378. package/src/skf-test-skill/scripts/load-coverage-inputs.py +760 -0
  379. package/src/skf-test-skill/scripts/locate-export-segments.py +835 -0
  380. package/src/skf-test-skill/scripts/reconcile-coverage.py +273 -79
  381. package/src/skf-test-skill/scripts/score-signatures.py +459 -0
  382. package/src/skf-test-skill/scripts/stage-helper-payload.py +148 -0
  383. package/src/skf-test-skill/scripts/validate-inventory.py +311 -16
  384. package/src/skf-test-skill/scripts/verify-declared-numerator.py +127 -52
  385. package/src/skf-test-skill/templates/test-report-template.md +21 -15
  386. package/src/skf-update-skill/SKILL.md +38 -25
  387. package/src/skf-update-skill/customize.toml +27 -12
  388. package/src/skf-update-skill/references/detect-changes.md +233 -222
  389. package/src/skf-update-skill/references/gap-driven.md +336 -0
  390. package/src/skf-update-skill/references/health-check.md +31 -5
  391. package/src/skf-update-skill/references/init.md +250 -84
  392. package/src/skf-update-skill/references/invocation-contract.md +12 -0
  393. package/src/skf-update-skill/references/manual-section-rules.md +6 -23
  394. package/src/skf-update-skill/references/merge.md +180 -47
  395. package/src/skf-update-skill/references/re-extract.md +53 -262
  396. package/src/skf-update-skill/references/report.md +100 -35
  397. package/src/skf-update-skill/references/write.md +331 -149
  398. package/src/skf-update-skill/scripts/skf-new-file-diff.py +29 -7
  399. package/src/skf-verify-stack/SKILL.md +23 -42
  400. package/src/skf-verify-stack/assets/feasibility-report-template.md +11 -5
  401. package/src/skf-verify-stack/customize.toml +55 -22
  402. package/src/skf-verify-stack/references/coverage-patterns.md +17 -8
  403. package/src/skf-verify-stack/references/coverage.md +67 -64
  404. package/src/skf-verify-stack/references/exit-codes.md +21 -8
  405. package/src/skf-verify-stack/references/init.md +107 -62
  406. package/src/skf-verify-stack/references/integration-verification-rules.md +12 -13
  407. package/src/skf-verify-stack/references/integrations.md +106 -65
  408. package/src/skf-verify-stack/references/report.md +59 -42
  409. package/src/skf-verify-stack/references/requirements.md +32 -9
  410. package/src/skf-verify-stack/references/synthesize.md +53 -39
  411. package/src/skf-verify-stack/scripts/skf-coverage-tally.py +398 -52
  412. package/src/skf-verify-stack/scripts/skf-previous-report.py +330 -0
  413. package/src/skf-verify-stack/scripts/skf-report-delta.py +453 -49
  414. package/src/skf-verify-stack/scripts/skf-verdict-rollup.py +240 -27
  415. package/tools/cli/commands/install.js +11 -4
  416. package/tools/cli/commands/status.js +15 -3
  417. package/tools/cli/commands/update.js +11 -4
  418. package/tools/cli/lib/tool-check.js +320 -0
  419. package/tools/cli/lib/version-check.js +22 -9
  420. package/tools/cli/skf-cli.js +4 -1
  421. package/.gitattributes +0 -16
  422. package/.nvmrc +0 -1
  423. package/docs/_internal/RELEASING.md +0 -645
  424. package/release-audits/v1.0.0-launch-audit.md +0 -728
  425. package/src/skf-audit-skill/references/step-doc-drift.md +0 -177
  426. package/src/skf-brief-skill/references/headless-source-authority-detection.md +0 -26
  427. package/src/skf-campaign/manifest.yaml +0 -15
  428. package/src/skf-create-skill/assets/tessl-dismissal-rules.md +0 -106
  429. package/src/skf-create-skill/references/ecosystem-check.md +0 -74
  430. package/src/skf-drop-skill/references/headless-contract.md +0 -18
  431. package/src/skf-update-skill/references/merge-conflict-rules.md +0 -15
  432. package/src/skf-update-skill/references/remote-source-resolution.md +0 -98
  433. package/src/skf-update-skill/references/validate.md +0 -124
  434. package/tools/validate-docs-drift.js +0 -233
  435. package/tools/validate-docs-links.js +0 -665
@@ -1,8 +1,8 @@
1
1
  ---
2
- # Static reference loaded by update-context.md §4a only when manifest
3
- # schema documentation is needed (the in-prompt schema is otherwise
4
- # delegated to skf-manifest-ops.py which handles v2 enforcement and
5
- # v1→v2 migration internally).
2
+ # Static reference named by update-context.md §9b, loaded only when
3
+ # manifest schema documentation is needed (skf-manifest-ops.py enforces
4
+ # the v2 shape and migrates v1 internally, so no step edits the manifest
5
+ # in the prompt).
6
6
  ---
7
7
 
8
8
  <!-- Config: communicate in {communication_language}. -->
@@ -11,7 +11,7 @@
11
11
 
12
12
  ## Purpose
13
13
 
14
- Reference for the v2 export manifest schema enforced by `skf-manifest-ops.py` and consumed by every workflow that touches `{skills_output_folder}/.export-manifest.json`. This file is the source of truth for the v2 shape; the helper script implements it; downstream skills (drop-skill, rename-skill, update-skill) read this same file to stay aligned.
14
+ Reference for the v2 export manifest schema that `skf-manifest-ops.py` enforces for every workflow that touches `{skills_output_folder}/.export-manifest.json`. This file documents the v2 shape and the helper implements it: export-skill, drop-skill and rename-skill read and edit manifest entries through the helper (`read`, `get`, `set`, `deprecate`, `remove`, `rename`), and `skf-rebuild-managed-sections.py assemble` reads it through the same code. Rename-skill's rollback is the one write outside it: it restores the byte copy of the manifest it kept before the re-key.
15
15
 
16
16
  ## v2 Schema
17
17
 
@@ -54,12 +54,11 @@ Reference for the v2 export manifest schema enforced by `skf-manifest-ops.py` an
54
54
 
55
55
  Pre-rename v2 manifests used a `platforms` array at the version level. If a version entry contains `platforms` instead of (or in addition to) `ides`, the helper treats `platforms` as `ides` and rewrites it on the next manifest write — silent in-place upgrade, no user prompt.
56
56
 
57
- For v1 manifests (no `schema_version` field), the helper migrates in-place on the first read:
57
+ For v1 manifests (no `schema_version` field), every read returns the v2 shape, and the next write through the helper stores it:
58
58
 
59
- 1. For each entry in `exports`, read its `last_exported`
60
- 2. Resolve the skill's current version from `{resolved_skill_package}/metadata.json`
61
- 3. Wrap in v2 structure: `active_version` ← resolved version, single entry in `versions` with `status: "active"`, `ides: []` (unknown — fills on next successful export), and `last_exported`
62
- 4. Set `schema_version: "2"` at root
59
+ 1. Each entry's `versions` list becomes a map with one record per version: `ides: []` (unknown, filled on the next successful export) and `last_exported` from the manifest's `updated_at`
60
+ 2. The entry's `active_version` keeps its value; that version's record gets `status: "active"`, or `"deprecated"` when the entry carries `deprecated: true`, and every other version `status: "archived"`
61
+ 3. The `deprecated` and `deprecated_versions` keys are dropped and `schema_version: "2"` is set at the root
63
62
 
64
63
  Workflows that load the manifest via `skf-manifest-ops.py read` receive a `{"status": "ok", "manifest": {...}}` envelope; the `manifest` value is always in canonical v2 shape regardless of on-disk state (parse `result["manifest"]`, not the top-level object).
65
64
 
@@ -23,15 +23,15 @@ Loaded by `load-skill.md` §1c when `len(skill_batch) > 1`.
23
23
  | step 1 §2–5 | **Iterate per skill** — load, validate, read metadata, and check the test report for every skill in `skill_batch`. Collect per-skill results. |
24
24
  | step 1 §6 | **Single gate** — present one consolidated summary table (one row per skill) and a single [C] gate for the whole batch. |
25
25
  | step 2 | **Iterate per skill** — validate each skill's package structure and collect per-skill readiness. |
26
- | step 3 | **Iterate per skill** — regenerate each skill's `context-snippet.md` independently (each skill has its own prior-gotchas carry-forward state). |
27
- | step 4 | **Batch once** — §3b orphan detection, §4 skill-index rebuild, §5 managed-section assembly, and §6–9 diff + write all execute once for the entire batch. The exported skill set in §4b already enumerates every skill in the manifest — it does not need per-skill iteration. §9b adds/updates a manifest entry per skill in `skill_batch` (not just the last one), then writes the manifest once. |
26
+ | step 3 | **Iterate per skill**: regenerate each skill's `context-snippet.md` independently (each skill has its own prior-gotchas carry-forward state), staging and measuring each draft in the run's one stage folder. |
27
+ | step 4 | **Batch once**: §3b orphan detection, §4 section build, §5 to §9 check, preview, gate and write all run once for the entire batch. Each `assemble` call names every skill in `skill_batch` with `--include`, beside every skill of the manifest, so no batch member is left out, even on a first export. §9b records every skill in `skill_batch` with one `set` each, and §9c then writes each skill's snippet. |
28
28
  | step 5 | **Iterate per skill** — compute token counts per skill, then present one aggregate report. |
29
- | step 6 | **One batch summary + one result contract** — the files-written table lists every skill; the result contract JSON covers the whole run, and `outputs` enumerates every context-snippet + target context file touched. |
29
+ | step 6 | **One batch summary + one result contract**: the files-written table lists every skill; the result contract JSON covers the whole run, and `outputs` enumerates every context-snippet, every target context file touched and the manifest. |
30
30
  | step 7 | **Runs once** — health check is per-workflow-run, not per-skill. |
31
31
 
32
32
  ## Halt semantics
33
33
 
34
- If any single skill fails validation in step 1 §2 (required-file or metadata-field failure), halt the entire batch before step 4 §5 — do not partially export. Report which skill failed and why. The principle: a multi-skill run is a unit of work, not a per-skill best-effort sweep — partial exports leave the manifest and managed sections in an ambiguous state that's expensive for the operator to reconcile.
34
+ If any single skill fails validation in step 1 §2 (required-file or metadata-field failure) or is refused by the §2 ownership gate (`not-skf-output`: a flat skill SKF did not generate), halt the entire batch before step 4: do not partially export. Report which skill failed and why. The principle: a multi-skill run is a unit of work, not a per-skill best-effort sweep: partial exports leave the manifest and managed sections in an ambiguous state that's expensive for the operator to reconcile.
35
35
 
36
36
  ## Single-skill mode (reference)
37
37
 
@@ -37,13 +37,21 @@ Emit the warning and gate:
37
37
 
38
38
  Wait for user choice.
39
39
 
40
- **Headless / non-interactive default:** when `{headless_mode}` (or dry-run, or unattended), default to **(b) keep** and print the warning only — no destructive action without explicit consent.
40
+ **GATE [default: b]**, headless or non-interactive: when `{headless_mode}` (or dry-run, or unattended), default to **(b) keep** and print the warning only: no destructive action without explicit consent.
41
+
42
+ When `{headless_mode}` is true, also record the decision in the run sink, listing each orphaned file's `file_path` with `/` in place of `\` so it stays a JSON string. If `record` exits non-zero, display its error line and go on (a failed `record` never stops the run):
43
+
44
+ ```bash
45
+ uv run {emitEnvelopeHelper} record --workflow skf-export-skill --run-dir "{run_dir}" --decision <<'SKF_JSON'
46
+ {"gate":"update-context.orphan-context-files","default_action":"b","taken_action":"b","reason":"headless: orphaned context files kept untouched","evidence":{"files":["{file_path}"]}}
47
+ SKF_JSON
48
+ ```
41
49
 
42
50
  ## Choice handling
43
51
 
44
52
  ### (a) clear
45
53
 
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.
54
+ 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 writes the section with; do not excise markers in-prompt. `{rebuildManagedSectionsHelper}` is the path SKILL.md's On Activation resolved, and activation halts (exit code 4, `halt_reason: "context-rebuild-failed"`) when no candidate exists: falling through to an in-prompt excision would regress the atomic-write + post-clear verify guarantee.
47
55
 
48
56
  For each file in `orphaned_context_files`:
49
57
 
@@ -62,7 +70,7 @@ Record nothing. The orphaned files remain on disk, untouched. Proceed.
62
70
 
63
71
  ### (c) rewrite
64
72
 
65
- Add each entry in `orphaned_context_files` to a separate `rewrite_context_files` list. This list is kept distinct from `target_context_files` so the user's intent to only export to configured IDEs is preserved in the manifest update at §9b — `rewrite_context_files` participates in the §4–§9a write loop for this run only and is not promoted into the manifest's `ides` arrays.
73
+ Add each entry in `orphaned_context_files` to a separate `rewrite_context_files` list. This list is kept distinct from `target_context_files` so the user's intent to only export to configured IDEs is preserved in the manifest update at §9b: `rewrite_context_files` joins the §4 to §9 writes for this run only and is not promoted into the manifest's `ides` arrays.
66
74
 
67
75
  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).
68
76
 
@@ -74,9 +82,9 @@ After this protocol completes, §3b returns control to §4 with these workflow-c
74
82
 
75
83
  - `orphans_cleared: []` — set when the user chose (a) or stayed empty otherwise
76
84
  - `orphans_rewritten: []` — set when the user chose (c) or stayed empty otherwise
77
- - `rewrite_context_files: []` — extends the per-context-file iteration in §4–§9a when the user chose (c)
85
+ - `rewrite_context_files: []`: joins the targets of §4 to §9 when the user chose (c)
78
86
 
79
- The §4–§9a loop iterates over `target_context_files + rewrite_context_files`. The §9b manifest update reads only `target_context_files` (rewritten orphans are not promoted into the manifest).
87
+ §4 to §9 run over `target_context_files + rewrite_context_files`. The §9b manifest update reads only `target_context_files` (rewritten orphans are not promoted into the manifest).
80
88
 
81
89
  ## Scope note
82
90
 
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  # Static reference loaded by update-context.md §4c.1 only when
3
- # `orphan_managed_rows` is non-empty (i.e. the cheap pre-check in
4
- # §4c.1 found `[skill-name v...]` entries in the prior managed
5
- # section that are absent from the manifest-driven exported skill
6
- # set built in §4b). The reference carries the (a)/(b)/(c) gate
7
- # protocol, headless default, deviations[] contract, and §6
8
- # result-contract integration; the trigger detection itself stays
9
- # inline in §4c.1 so the LLM knows when to invoke this protocol.
3
+ # `orphan_rows` is non-empty (the §4b `assemble` results list
4
+ # `[skill-name v...]` rows of the current managed sections whose skill
5
+ # neither the export manifest nor this run's batch holds). The
6
+ # reference carries the (a)/(b)/(c) gate protocol, headless default,
7
+ # deviations[] contract, and step 6 result-contract integration; the
8
+ # trigger itself stays inline in §4c.1 so the LLM knows when to invoke
9
+ # this protocol.
10
10
  ---
11
11
 
12
12
  <!-- Config: communicate in {communication_language}. Render the orphan list and gate prompt in {document_output_language}. -->
@@ -15,13 +15,13 @@
15
15
 
16
16
  ## Purpose
17
17
 
18
- Handle the (a) Drop / (b) Preserve verbatim / (c) Cancel gate when the prior managed section in the first target context file contains `[skill-name v...]` rows for skills that are not in the manifest-driven exported skill set — typically externally-installed skills authored in a different repo and dropped into `{skills_output_folder}` without going through export-skill.
18
+ Handle the (a) Drop / (b) Preserve verbatim / (c) Cancel gate when the managed section of a target context file holds `[skill-name v...]` rows for skills that neither the export manifest nor this run's batch holds: typically externally-installed skills authored in a different repo and dropped into `{skills_output_folder}` without going through export-skill.
19
19
 
20
20
  Strict ADR-K would silently drop such rows, but the user's managed section is load-bearing — silent removal of an installed skill is a regression. The convention captured in `skills/export-skill-result-latest.json` deviations is to make this an explicit operator (or `{headless_mode}`) choice.
21
21
 
22
22
  ## Inputs
23
23
 
24
- - `orphan_managed_rows` — list of `{skill_name, version, snippet_text, source_files: []}` entries built by §4c.1's pre-check across **every** target context file, deduplicated by `(skill_name, version)`. `source_files` carries the file paths the orphan appeared in (one entry per file in which the row was found). `snippet_text` is the original snippet line(s) captured verbatim from the first encountered occurrence, used for re-emission if (b) is chosen.
24
+ - `orphan_rows`: the `{skill_name, version, snippet_text, source_files: [], skill_type}` entries `assemble` returned in §4b, found across **every** target context file and deduplicated by `(skill_name, version)`. `source_files` carries the file paths the orphan appeared in (one entry per file in which the row was found). `snippet_text` is the original row captured verbatim from the first file that holds it, which (b) writes back unchanged.
25
25
  - `target_context_files` — the full IDE → context-file list (referenced in the gate's framing copy so the user understands the consolidation scope)
26
26
  - `{headless_mode}` — boolean flag from workflow context
27
27
 
@@ -33,17 +33,25 @@ Emit the gate:
33
33
  >
34
34
  > {list each as `- {skill_name} v{version} (in: {comma-separated source_files})`}
35
35
  >
36
- > These skills appear in one or more existing managed sections but no entry exists in `.export-manifest.json` and no source draft exists under `{skills_output_folder}/{skill_name}/`. They were likely installed from a different repo and never run through export-skill in this project. Options:
36
+ > These skills appear in one or more existing managed sections, but `.export-manifest.json` has no entry for them and this export does not include them. They were likely installed from a different repo and never run through export-skill in this project. Options:
37
37
  >
38
38
  > - **(a) Drop** — remove these rows from the rebuilt managed section across **all** target context files (strict ADR-K behavior). The skills' on-disk files are not touched, but they will no longer appear in any context file's managed index.
39
39
  > - **(b) Preserve verbatim** — copy each orphan's existing snippet line(s) into the rebuilt managed section across **all** target context files unchanged (one canonical row per `(skill, version)` written everywhere — orphans become symmetric across IDEs as a side effect, which is the correct outcome since the user's intent is "these external skills should appear in my managed index"). Records `deviations[].kind = "preserve_external_skills"` with the affected skill names, versions, and `source_files` in the result contract for audit.
40
- > - **(c) Cancel** — abort export. Run export-skill against each external skill (or remove the orphan rows from the context files manually) before re-running.
40
+ > - **(c) Cancel** — abort export. Before re-running, run export-skill on each of these skills that SKF generated (its `metadata.json` carries an SKF marker) to add it to the manifest, and remove the rows of the other skills from the context files yourself.
41
41
 
42
42
  Wait for user choice.
43
43
 
44
- **Headless default** (when `{headless_mode}`): auto-select **(b) Preserve verbatim**, with the same `deviations[]` entry. Emit a loud log line:
44
+ **GATE [default: b]** (when `{headless_mode}`): auto-select **(b) Preserve verbatim**, with the same `deviations[]` entry. Emit a loud log line:
45
45
 
46
- > `headless: {N} managed-section rows had no manifest entry; preserving verbatim with deviations[].kind = preserve_external_skills. Run export-skill against each to migrate them into the manifest.`
46
+ > `headless: {N} managed-section rows had no manifest entry; preserving verbatim with deviations[].kind = preserve_external_skills. Run export-skill on each skill SKF generated to add it to the manifest; remove the rows of other skills from the context files yourself.`
47
+
48
+ Record the decision in the run sink, listing each orphan row as `{skill_name} v{version}`. If `record` exits non-zero, display its error line and go on (a failed `record` never stops the run):
49
+
50
+ ```bash
51
+ uv run {emitEnvelopeHelper} record --workflow skf-export-skill --run-dir "{run_dir}" --decision <<'SKF_JSON'
52
+ {"gate":"update-context.orphan-rows","default_action":"b","taken_action":"b","reason":"headless: managed-section rows with no manifest entry preserved verbatim","evidence":{"rows":["{skill_name} v{version}"]}}
53
+ SKF_JSON
54
+ ```
47
55
 
48
56
  Silent drop under automation would regress the user's managed section without consent; cancel under automation would block the whole export over an externally-installed skill the user did not author. Preservation matches the prior-attentive-operator convention.
49
57
 
@@ -51,19 +59,19 @@ Silent drop under automation would regress the user's managed section without co
51
59
 
52
60
  ### (a) Drop
53
61
 
54
- Do not include any orphan rows in the rebuilt section. Record:
62
+ Run update-context.md §4b again for every target with `--orphans drop`, so no rebuilt section holds an orphan row. Record:
55
63
 
56
64
  ```
57
65
  orphans_dropped = [{skill_name, version}, …]
58
66
  ```
59
67
 
60
- in workflow context for the §6 result contract.
68
+ in workflow context for the step 6 result contract.
61
69
 
62
70
  ### (b) Preserve verbatim
63
71
 
64
- Append each captured `snippet_text` to the assembled section after the manifest-driven entries, preserving alphabetical order in the merged list (sort the combined set of `manifest-driven` + `orphan` snippets by `skill_name`). Each `(skill, version)` is written **once** per rebuilt managed section — the deduplication done by §4c.1 means there is no per-file divergence to reconcile here.
72
+ Keep the bodies §4b staged: `assemble` already wrote each orphan's `snippet_text` into them verbatim, sorted with the other rows by skill name, **once** per section, and counted it as a stack skill when its row has a `|stack:` line. Nothing is merged by hand.
65
73
 
66
- Append the following entry to the `deviations[]` array in the §6 result contract:
74
+ Append the following entry to the `deviations[]` array in the step 6 result contract:
67
75
 
68
76
  ```json
69
77
  {
@@ -77,7 +85,7 @@ Append the following entry to the `deviations[]` array in the §6 result contrac
77
85
 
78
86
  `source_files` per skill records the prior context files the orphan was found in (asymmetric provenance preserved for audit) — useful when an operator later debugs which IDE's managed section originally carried the row.
79
87
 
80
- The same orphans are written to **every** target context file in the §4–§9a loop, so all configured IDEs end up with consistent managed sections (asymmetric prior orphans become symmetric — the correct outcome for the "preserve external skills" intent).
88
+ Every §4b call scans every target file in the same order, so the same orphans are written to **every** target context file: all configured IDEs end up with consistent managed sections (asymmetric prior orphans become symmetric, the correct outcome for the "preserve external skills" intent).
81
89
 
82
90
  ### (c) Cancel
83
91
 
@@ -86,17 +94,18 @@ HALT the workflow:
86
94
  - Do not rewrite any context file.
87
95
  - Do not update the manifest.
88
96
  - Do not produce a result contract.
97
+ - Delete the `{export_stage_dir}` folder, as every exit from update-context.md does.
89
98
  - Exit code 6, `halt_reason: "user-cancelled"` (matches the §8 Menu cancel semantics).
90
99
  - In headless mode this branch is never taken (headless default is (b)), so this exit path is interactive-only.
91
100
 
92
101
  ## Downstream contract
93
102
 
94
- After this protocol completes, §4c.1 returns control to §4d with these workflow-context variables populated:
103
+ After this protocol completes, §4c.1 returns control to §5 with these workflow-context variables populated:
95
104
 
96
- - `orphans_dropped: []` — set when the user chose (a) or stayed empty otherwise
105
+ - `orphans_dropped: []`: set when the user chose (a), else empty
97
106
  - `deviations[]` — extended with the `preserve_external_skills` entry when the user chose (b)
98
- - The assembled managed section contains the orphan rows verbatim when (b) was chosen, and excludes them when (a) was chosen
107
+ - The staged bodies hold the orphan rows verbatim when (b) was chosen, and leave them out when (a) was chosen
99
108
 
100
109
  ## Scope note
101
110
 
102
- This detection runs once per export run (not per target context file) — the §4c.1 pre-check iterates **every** entry in `target_context_files` and deduplicates by `(skill_name, version)` before invoking this protocol, so the gate's choice applies globally and asymmetric orphans (a row present in `.cursorrules` but not in `CLAUDE.md`, or vice versa) are detected and surfaced with `source_files` provenance.
111
+ This gate runs once per export run, not per target context file: every §4b call passes every target file as `--orphan-sources`, so each result lists the same orphans, deduplicated by `(skill_name, version)`. The gate's choice applies globally, and asymmetric orphans (a row present in `.cursorrules` but not in `CLAUDE.md`, or vice versa) are detected and surfaced with `source_files` provenance.
@@ -1,98 +1,40 @@
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'
11
3
  ---
12
4
 
13
- <!-- Config: communicate in {communication_language}. Validate package contents in {document_output_language}. -->
5
+ <!-- Config: communicate in {communication_language}. Render the package status in {document_output_language}. -->
14
6
 
15
7
  # Step 2: Package
16
8
 
17
9
  ## STEP GOAL:
18
10
 
19
- To assemble and validate an agentskills.io-compliant package structure from the loaded skill artifacts, ensuring all required components are present and properly formatted for distribution.
11
+ To report each skill's package status from the export-gate verdict step 1 §2 retained, without checking the package again.
20
12
 
21
13
  ## Rules
22
14
 
23
- - Focus only on package structure assembly and validation — do not modify SKILL.md content
15
+ - Read the verdict, never re-derive a check it covers, and never modify the package
24
16
  - Auto-proceed when complete
25
- - **Multi-skill mode:** when step 1 loaded more than one skill (`len(skill_batch) > 1`), iterate sections 1–4 below per skill using each skill's `{resolved_skill_package}`. Collect per-skill status; report the aggregate in §4 as one row per skill. Halt the batch if any skill is NOT READY. See step 1 §1c.
17
+ - **Multi-skill mode:** when step 1 loaded more than one skill (`len(skill_batch) > 1`), report one row per skill, each from its own verdict. See step 1 §1c.
26
18
 
27
19
  ## MANDATORY SEQUENCE
28
20
 
29
- ### 1. Validate Package Structure
21
+ ### 1. Read the Verdict
30
22
 
31
- Verify the skill package at `{resolved_skill_package}` (resolved in step 1 via manifest or `active` symlink — see `knowledge/version-paths.md`) contains the expected agentskills.io package layout:
23
+ Use the export-gate JSON step 1 §2 retained for `{resolved_skill_package}`. Only when it is not in context, run `python3 {validateOutputHelper} {resolved_skill_package} --export-gate` again: the same package gives the same verdict. Step 1 §2 halts on `NOT_READY`, so `export_status` is `READY` or `WARNINGS` here.
32
24
 
33
- ```
34
- {skill_package} = {skills_output_folder}/{skill-name}/{version}/{skill-name}/
35
- ├── SKILL.md ← Required: Active skill document
36
- ├── metadata.json ← Required: Machine-readable metadata
37
- ├── context-snippet.md ← Will be generated/updated in step 3
38
- ├── references/ ← Optional: Progressive disclosure
39
- │ ├── {function-a}.md
40
- │ └── {function-b}.md
41
- ├── scripts/ ← Optional: Executable automation
42
- └── assets/ ← Optional: Templates, schemas, configs
43
- ```
25
+ ### 2. Report Package Status
44
26
 
45
- **Component checks — from the export-gate verdict (do not re-derive):**
27
+ "**Package checked.**
46
28
 
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:
29
+ **Status:** {export_status}
30
+ **references/:** {the count of `.md` files under `{resolved_skill_package}/references/`, or none}
48
31
 
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)
32
+ {If export_status is WARNINGS:}
33
+ **Warnings** (none of them stops the export):
34
+ - {the `field` of each `validation.metadata.recommended_missing` entry, each path in `validation.crossref_7b.orphans`, and the message of each low issue in `validation.metadata.issues`, such as an empty `exports` array or a forge tier in an older stack's `confidence_tier`}"
53
35
 
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.
55
-
56
- ### 2. Validate Metadata Completeness
57
-
58
- Check metadata.json for recommended (non-required) fields:
59
-
60
- - `description` — Brief skill description
61
- - `source_repo` — Source repository URL
62
- - `language` — Primary language of source code
63
- - `ast_node_count` — Number of AST nodes analyzed
64
- - `tool_versions` — Tools used during generation
65
-
66
- **For each missing recommended field:** Note as warning, do not halt.
67
-
68
- ### 3. Assess Package Readiness
69
-
70
- Read `export_status` directly from the export-gate verdict (step 1 §2) — do not re-compute the status by hand:
71
-
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.
75
-
76
- ### 4. Report Package Status
77
-
78
- "**Package structure validated.**
79
-
80
- **Status:** {export_status: READY / WARNINGS}
81
-
82
- **Required Components:**
83
- - SKILL.md: ✅
84
- - metadata.json: ✅ (required fields valid per export-gate verdict)
85
- - references/: {✅ present ({count} files) / ⚠️ not present}
86
-
87
- {If warnings (export_status: WARNINGS):}
88
- **Warnings:**
89
- - {list missing recommended fields from §2, plus any `validation.crossref_7b.orphans` and an empty `exports` warning from the verdict}
90
-
91
- **Package is ready for snippet generation.**"
92
-
93
- ### 5. Proceed to Snippet Generation
36
+ ### 3. Proceed to Snippet Generation
94
37
 
95
38
  Display: "**Proceeding to snippet generation...**"
96
39
 
97
- Auto-proceed (no user choices): once package validation is complete, load, read entirely, and execute `{nextStepFile}`.
98
-
40
+ Auto-proceed (no user choices): load, read entirely, and execute `{nextStepFile}`.
@@ -1,98 +1,79 @@
1
1
  ---
2
- # Static reference loaded by load-skill.md §1b only when
3
- # `snippet_skill_root_override` is UNSET in config.yaml. When the
4
- # override is set, every existing snippet's on-disk prefix is ground
5
- # truth by contract — no probe needed and the entire authoring-repo
6
- # escape hatch is already configured. Loaded once per export run, not
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'
2
+ # Loaded by load-skill.md §1b, once per run, only when config.yaml sets no
3
+ # `snippet_skill_root_override`.
17
4
  ---
18
5
 
19
- <!-- Config: communicate in {communication_language}. Render the warning and gate prompt in {document_output_language}. -->
6
+ <!-- Config: communicate in {communication_language}. Render the question, the warning and the gate prompt in {document_output_language}. -->
20
7
 
21
- # Snippet Root Prefix Mismatch — Pre-flight Probe
8
+ # Snippet Root Probe
22
9
 
23
10
  ## Purpose
24
11
 
25
- Catch the authoring-repo case before step 4 silently rewrites root paths. In an authoring repo, skills typically live under a single shared directory (`skills/`) that does not match any per-IDE `skill_root` (`.claude/skills/`, `.cursor/skills/`, etc.). Without this probe, step 4's root-rewrite algorithm would replace the on-disk prefix with an IDE-mapped one that the snippet files do not actually reside under.
12
+ Decide where the managed section points each skill before step 3 writes a `root:` path. A consuming project points at its IDE's skill folder (`.claude/skills/`, `.cursor/skills/` and so on), where `npx skills add` installs each skill. An authoring repo keeps its skills in one shared folder, such as `skills/`, and sets `snippet_skill_root_override` in `config.yaml`. Only a root an earlier export chose shows the layout: create-skill, create-stack-skill, quick-skill and update-skill write the draft root `skills/{skill-name}/` into every snippet they build, whatever the layout. So a repo whose skills live in `skills/` sets `snippet_skill_root_override: skills/`: a `skills/{skill-name}/` root an earlier export wrote reads as a draft root, and without the override the probe asks the Layout Question, whose headless default is the IDE skill folder.
26
13
 
27
- Loaded by `load-skill.md` §1b after `target_context_files` is resolved and `snippet_skill_root_override` is confirmed unset.
14
+ `{reference_root}` is `target_context_files[0].skill_root`, the root step 3 writes when nothing overrides it.
28
15
 
29
- ## Inputs
16
+ ## Probe
30
17
 
31
- - `target_context_files[0].skill_root` — the reference IDE-mapped skill root (used because step 3 §2.7 picks this same entry for snippet generation when no override is set)
32
- - `{skills_output_folder}` — for manifest-driven candidate enumeration
33
- - Current skill's snippet path (resolved via manifest / `active` symlink / flat path per `knowledge/version-paths.md`)
34
- - `{headless_mode}` — boolean flag from workflow context
18
+ List the snippet of each version the export manifest records: for each skill in step 1 §1's `result.manifest.exports` whose `active_version` has an entry under `versions`, `{skills_output_folder}/{skill-name}/{active_version}/{skill-name}/context-snippet.md`. A skill the manifest does not list was never exported, so its snippet holds the draft root only. With no snippet to list, go to the Layout Question. Otherwise run:
35
19
 
36
- ## Probe Algorithm
20
+ ```bash
21
+ python3 {rebuildManagedSectionsHelper} root-probe {snippet-1} {snippet-2} … --reference-root "{reference_root}" --project-root "{project-root}"
22
+ ```
37
23
 
38
- 1. Collect candidate snippet paths (manifest-driven orchestration — stays in-prompt):
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`.
40
- - Also include the current skill's snippet if present.
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:
24
+ The helper reads each snippet's `root:` prefix and leaves out a snippet that is missing, has no root, or holds the draft root (it lists those skills in `draft_roots`). It returns `observed_prefixes`, `mismatch` (true when one of them is not `{reference_root}`), `mismatched_skills`, and `disk_root`: `{reference_root}` when that folder holds every mismatched skill, else the one observed prefix when that folder holds them all, else null. Then:
42
25
 
43
- ```bash
44
- python3 {rebuildManagedSectionsHelper} root-probe {candidate-snippet-1} {candidate-snippet-2} … --reference-root {target_context_files[0].skill_root}
45
- ```
26
+ - `observed_prefixes` is empty: no earlier export chose a root. Ask the Layout Question.
27
+ - `mismatch` is false: every earlier export chose `{reference_root}`. Ask nothing and return to load-skill.md §1b.
28
+ - `mismatch` is true: take the Mismatch Gate.
46
29
 
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:
30
+ ## Layout Question
48
31
 
49
- ```json
50
- {"status": "ok", "reference_root": "…", "observed_prefixes": ["…"], "mismatch": true}
51
- ```
32
+ > **Where should the managed section point your skills?** No earlier export has chosen yet. By default each row points at `{reference_root}{skill-name}/`, your IDE's skill folder, where `npx skills add` installs the skill (step 6 prints the command).
33
+ >
34
+ > - **[I] IDE skill folder** (default): point at `{reference_root}`.
35
+ > - **[S] Shared skills folder**: point at the skills where SKF writes them, for a repo that keeps them there. Export, drop-skill and rename-skill read that choice from `config.yaml`.
36
+ > - **[X] Cancel**
52
37
 
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.
38
+ Wait for the user's choice.
54
39
 
55
- ## Mismatch Gate
40
+ - **[I]**: return to load-skill.md §1b.
41
+ - **[S]**: display "Add `snippet_skill_root_override: {skills_prefix}` to `{project-root}/_bmad/skf/config.yaml`, then re-run the export." and HALT (exit code 6, `halt_reason: "user-cancelled"`): the workflow never edits `config.yaml`. `{skills_prefix}` is the path of `{skills_output_folder}` from `{project-root}`, with a trailing `/`, such as `skills/`.
42
+ - **[X]** / `cancel` / `exit` / `:q`: HALT (exit code 6, `halt_reason: "user-cancelled"`). Nothing was written.
43
+ - **GATE [default: I]**: headless, record the decision in the run sink with the command below, log "headless: no earlier export chose a snippet root, using the IDE skill folder", then take [I]. If `record` exits non-zero, display its error line and go on: a failed `record` never stops the run.
56
44
 
57
- **If `result["mismatch"]` is `true`** (some value in `observed_prefixes` does not match the reference `skill_root`):
45
+ ```bash
46
+ uv run {emitEnvelopeHelper} record --workflow skf-export-skill --run-dir "{run_dir}" --decision <<'SKF_JSON'
47
+ {"gate":"load-skill.snippet-root-layout","default_action":"I","taken_action":"I","reason":"headless: no earlier export chose a snippet root, using the IDE skill folder","evidence":{"reference_root":"{reference_root}"}}
48
+ SKF_JSON
49
+ ```
58
50
 
59
- Emit a single warning (once, not per snippet) and present resolution options before continuing to §2:
51
+ ## Mismatch Gate
60
52
 
61
53
  > **Snippet root prefix mismatch detected.**
62
- > Existing snippets use: `{observed_prefixes}`
63
- > IDE-mapped skill_root: `{target_context_files[0].skill_root}`
54
+ > Earlier exports point at: `{observed_prefixes}`
55
+ > The IDE mapping points at: `{reference_root}`
64
56
  >
65
- > This usually means you are in an authoring repo where skills live under a single shared directory. Options:
57
+ > - **(a) Set override**: add `snippet_skill_root_override: {observed_prefix}` to `config.yaml`, which export, drop-skill and rename-skill all read. Snippets keep their on-disk prefix.
58
+ > - **(b) Proceed with IDE mapping**: every row's root becomes `{reference_root}`. Use this when that folder holds the skills, or will once you install them there.
59
+ > - **(c) Cancel**: abort the export and investigate.
60
+ > - **(d) Use the observed prefix for this run only**: every row's root stays `{observed_prefix}`, and `config.yaml` is not changed. (Offered only when exactly one prefix was observed.)
66
61
  >
67
- > - **(a) Set override** — add `snippet_skill_root_override: {observed_prefix}` to `config.yaml`. Snippets keep their on-disk prefix; the managed section references the real location.
68
- > - **(b) Proceed with IDE mapping** — step 4 will rewrite every snippet's root path to the IDE's skill_root. Use this only if the IDE's skill directory actually contains the skill files.
69
- > - **(c) Cancel** — abort export and investigate.
70
- > - **(d) Use observed prefix for this run only** — set the effective snippet root to the single observed on-disk prefix for this export run, without writing to `config.yaml`. The managed section references the real on-disk location. (Only offered when exactly one prefix was observed.)
71
- >
72
- > If multiple distinct prefixes were observed, the snippets disagree with each other — investigate before choosing (a) or (d).
73
-
74
- Wait for user choice.
75
-
76
- **Headless default:** when `{headless_mode}`, default to **(b) Proceed with IDE mapping** and log the observed prefix(es) so the mismatch is visible in run logs (not silent).
77
-
78
- ## Choice handling
79
-
80
- ### (a) Set override
81
-
82
- Halt and instruct the user to update `config.yaml` with `snippet_skill_root_override: {observed_prefix}`, then re-run export. Exit code 6, `halt_reason: "user-cancelled"` (configuration change is out-of-band — workflow does not edit config.yaml on the user's behalf).
83
-
84
- ### (b) Proceed with IDE mapping
85
-
86
- Continue to §2. Step 4's root-rewrite algorithm will rewrite every snippet's prefix to the reference `skill_root`. The user is accepting that the IDE's skill directory contains the actual files; if it does not, the resulting managed section will reference paths that don't resolve.
87
-
88
- ### (c) Cancel
62
+ > If several prefixes were observed, the snippets disagree with each other: investigate before choosing (a).
89
63
 
90
- HALT. Exit code 6, `halt_reason: "user-cancelled"`. No files written.
64
+ Wait for the user's choice.
91
65
 
92
- ### (d) Use observed prefix for this run only
66
+ **GATE [default: (d) or (b), by the disk]**: headless, take (d) when `disk_root` is the observed prefix (that folder holds the skills and `{reference_root}` does not), else (b): `{reference_root}` holds them, or no folder does yet, as in a project that installs its skills after the export. `{choice}` is the option taken. Log it with the observed prefixes, record the decision in the run sink with the command below (`{disk_root}` is `none` when it is null), then take that option. If `record` exits non-zero, display its error line and go on: a failed `record` never stops the run.
93
67
 
94
- **Only available when `observed_prefixes` contains exactly one value.** Set the effective snippet root for this run to that single observed prefix — do NOT mutate `config.yaml`. Step 4's root-rewrite algorithm uses this value as the reference instead of `target_context_files[0].skill_root`, so snippets keep their on-disk prefix and the managed section resolves to the real location. Print a one-line hint: "Persist `snippet_skill_root_override: {observed_prefix}` in config.yaml to skip this prompt on future exports." Continue to §2.
68
+ ```bash
69
+ uv run {emitEnvelopeHelper} record --workflow skf-export-skill --run-dir "{run_dir}" --decision <<'SKF_JSON'
70
+ {"gate":"load-skill.snippet-root-probe","default_action":"{choice}","taken_action":"{choice}","reason":"headless: snippet root prefix mismatch, option {choice} by the folder on disk that holds the skills","evidence":{"observed_prefixes":{observed_prefixes},"reference_root":"{reference_root}","disk_root":"{disk_root}"}}
71
+ SKF_JSON
72
+ ```
95
73
 
96
- ## No-mismatch fast path
74
+ ### Choice handling
97
75
 
98
- **If all observed prefixes match the reference `skill_root` (or no existing snippets were found):** no warning, no gate. Return control to §1b and proceed silently to §2.
76
+ - **(a) Set override**: display "Add `snippet_skill_root_override: {observed_prefix}` to `{project-root}/_bmad/skf/config.yaml`, then re-run the export." and HALT (exit code 6, `halt_reason: "user-cancelled"`): the workflow never edits `config.yaml`.
77
+ - **(b) Proceed with IDE mapping**: return to load-skill.md §1b. Step 4 writes `{reference_root}` as every row's root.
78
+ - **(c) Cancel**: HALT (exit code 6, `halt_reason: "user-cancelled"`). Nothing was written.
79
+ - **(d) Use the observed prefix for this run only**: bind `{snippet_skill_root_override}` ← the observed prefix for this run, without editing `config.yaml`. Step 3 §2.7 and step 4 §4b read it as they read the `config.yaml` value, so every snippet and row keeps that root. Display "Persist `snippet_skill_root_override: {observed_prefix}` in `{project-root}/_bmad/skf/config.yaml` to skip this question next time: drop-skill and rename-skill read only `config.yaml` when they rebuild the section." Return to load-skill.md §1b.
@@ -1,28 +1,43 @@
1
- <!-- Config: emit exactly as specified — this is a machine-parsed contract. Loaded standalone by any halting stage; it back-references no other file. -->
1
+ <!-- Config: a machine-parsed contract. The shared emitter builds every line; never type one. -->
2
2
 
3
3
  # Headless Result Envelope
4
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.
5
+ The single-line `SKF_EXPORT_RESULT_JSON: {…}` envelope export-skill emits on non-interactive (`{headless_mode}`) runs. Pipeline consumers parse it to branch on the run's outcome; `shared/scripts/schemas/skf-export-result-envelope.v1.json` describes each field. The shared emitter builds every line from the payload the run passes it on stdin, checks it against that schema and prints it.
6
+
7
+ `{emitEnvelopeHelper}` is the emitter SKILL.md's On Activation resolved: the first existing path of `{project-root}/_bmad/skf/shared/scripts/skf-emit-result-envelope.py` and `{project-root}/src/shared/scripts/skf-emit-result-envelope.py`. `{run_dir}` is the run folder a headless run created under `{project-root}/_bmad-output/.skf-run/`: its sink holds the auto-decision each gate recorded, which the emitter folds into every line as `headless_decisions`.
6
8
 
7
9
  ## Emission rule
8
10
 
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
+ - **Success / dry-run:** step 6 (`summary.md` §6) runs `emit` once, on **stdout**, before chaining to step 7.
12
+ - **Every HARD HALT** of a headless run: run `emit-halt` as below, which prints the line on **stderr** with `status: "error"`, then exit with the halt's code (Exit Codes below). An interactive halt displays its message only.
11
13
 
12
- ## Shape
14
+ ## Emitting a Halt
13
15
 
16
+ Each HARD HALT a headless run can reach names its exit code, its `halt_reason` and its phase in the step files; every other field follows the run's state as below. Pass the halt's payload in a quoted heredoc, so no value is expanded. Each value is a JSON string: write a path with `/` in place of `\`, and a quote inside the message as a backtick.
17
+
18
+ ```bash
19
+ uv run {emitEnvelopeHelper} emit-halt --workflow skf-export-skill [--run-dir "{run_dir}"] --target stderr <<'SKF_JSON'
20
+ {"phase":"<phase>","reason":"<the halt message>","halt_reason":"<halt_reason>","skills":["<name>"]}
21
+ SKF_JSON
14
22
  ```
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
23
 
18
- ## Fields
24
+ - `phase` is the phase the halt site names, `<step file> §<section>` (for example `update-context §9`), and `reason` is the message the halt displays, on one line.
25
+ - `halt_reason` is the value the halt site names. The emitter derives `exit_code` from it and sets `status: "error"`; leave both out.
26
+ - Always pass `skills`, the resolved batch (`[]` only before step 1 bound `skill_batch`, as at every On Activation halt).
27
+ - Add `context_files_updated`, the context files step 4 §9 wrote before the halt, once it has written one, and `manifest_path`, the `{manifest_path}` step 4 §9b bound, once the manifest is written. Before that, leave each out: the emitter gives `context_files_updated` `[]` and `manifest_path` `null`.
28
+ - Pass `--run-dir` once On Activation bound `{run_dir}`, so the line carries the decisions taken before the halt. A halt writes no result file.
29
+
30
+ Display the line the emitter prints. If it exits non-zero or prints no line, display the halt reason alone.
31
+
32
+ ## Exit Codes
19
33
 
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.
34
+ Every HARD HALT exits with a stable code, so headless automators can branch on the failure class without grepping message text:
27
35
 
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.
36
+ | Code | Meaning | Raised by (halt site → `halt_reason`) |
37
+ | ---- | -------------------- | -------------------------------------------------------------------------------------------- |
38
+ | 0 | success | step 7 (terminal); also `status="dry-run"` when `--dry-run` is set |
39
+ | 2 | input-missing | step 1 §1: a headless run with no `skill_name` and no `--all` (a non-interactive run cannot answer the skill-selection menu) → `input-missing` |
40
+ | 3 | resolution-failure | step 1 §1 (discovery finds no skills on disk / in the manifest; the export manifest does not parse; context-file resolution refuses an unknown `--context-file` value or cannot read the IDE mapping); step 1 §2 (the inventory helper finds no version of a named skill to export, or its required artifacts are missing or its metadata is invalid: export-gate FAIL); multi-skill batch (any skill failing §2 validation halts the whole batch) → `resolution-failure`; step 1 §2 flat fallback (a flat `SKILL.md` with no SKF marker in its `metadata.json`, so SKF will not migrate or export it) → `not-skf-output` |
41
+ | 4 | write-failure | On-Activation §4 (the run folder cannot be created) or §5 pre-flight write check, or step 4 §9c (a snippet write fails) → `write-failed`; On-Activation §4 (a required helper is missing), step 3 §4 (the token counter fails), step 4 §3b (an orphaned file's clear fails), §4b (the body cannot be built, for example a context file that is not UTF-8 text) or §9 (a write fails its check) → `context-rebuild-failed`; step 4 §9b manifest write → `manifest-write-failed` |
42
+ | 5 | state-conflict | step 4 §4b or §5: `check` finds a `<!-- SKF:BEGIN` marker that no `<!-- SKF:END -->` closes in a target context file → `malformed-markers` |
43
+ | 6 | user-cancelled | step 1 §6 gate `[X]`/cancel; step 1 §1b snippet root: the layout question [S]/[X] or the mismatch gate (a)/(c); step 4 §8 gate `[X]`/cancel; step 4 §4c.1 orphan-row (c) Cancel; any prompt accepting `cancel`/`exit`/`:q` → `user-cancelled` |