bmad-module-skill-forge 2.2.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (435) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/README.md +49 -49
  3. package/docs/404.md +10 -8
  4. package/docs/_data/pinned.yaml +22 -13
  5. package/docs/_internal/STABILITY.md +58 -35
  6. package/docs/agents.md +39 -53
  7. package/docs/architecture.md +65 -51
  8. package/docs/bmad-synergy.md +53 -51
  9. package/docs/campaign.md +127 -75
  10. package/docs/concepts.md +34 -28
  11. package/docs/examples.md +70 -68
  12. package/docs/forge-auto.md +34 -31
  13. package/docs/getting-started.md +118 -57
  14. package/docs/how-it-works.md +25 -21
  15. package/docs/index.md +15 -15
  16. package/docs/skill-model.md +70 -59
  17. package/docs/troubleshooting.md +135 -18
  18. package/docs/verifying-a-skill.md +83 -57
  19. package/docs/why-skf.md +24 -22
  20. package/docs/workflows.md +274 -110
  21. package/package.json +18 -10
  22. package/src/forger/preferences.yaml +8 -1
  23. package/src/knowledge/agentskills-spec.md +2 -0
  24. package/src/knowledge/ccc-bridge.md +40 -24
  25. package/src/knowledge/confidence-tiers.md +9 -5
  26. package/src/knowledge/overview.md +3 -3
  27. package/src/knowledge/progressive-capability.md +8 -8
  28. package/src/knowledge/provenance-tracking.md +9 -5
  29. package/src/knowledge/qmd-registry.md +2 -2
  30. package/src/knowledge/skf-knowledge-index.csv +2 -2
  31. package/src/knowledge/skill-lifecycle.md +18 -11
  32. package/src/knowledge/split-body-strategy.md +0 -3
  33. package/src/knowledge/tool-resolution.md +4 -2
  34. package/src/knowledge/version-paths.md +101 -15
  35. package/src/module-help.csv +3 -3
  36. package/src/module.yaml +10 -0
  37. package/src/shared/data/ast-grep-recipes.yaml +608 -0
  38. package/src/shared/data/ide-context-files.json +30 -0
  39. package/src/shared/health-check.md +32 -12
  40. package/src/shared/references/description-guard-protocol.md +12 -9
  41. package/src/shared/references/feasibility-report-schema.md +19 -13
  42. package/src/shared/references/headless-gate-convention.md +55 -3
  43. package/src/shared/references/output-contract-schema.md +19 -8
  44. package/src/shared/references/pipeline-contracts.md +94 -29
  45. package/src/shared/references/tessl-review.md +77 -0
  46. package/src/shared/scripts/schemas/skf-analyze-result-envelope.v1.json +194 -0
  47. package/src/shared/scripts/schemas/skf-audit-result-envelope.v1.json +192 -0
  48. package/src/shared/scripts/schemas/skf-brief-result-envelope.v1.json +32 -4
  49. package/src/shared/scripts/schemas/skf-campaign-result-envelope.v1.json +174 -0
  50. package/src/shared/scripts/schemas/skf-create-skill-result-envelope.v1.json +284 -0
  51. package/src/shared/scripts/schemas/skf-drop-skill-result-envelope.v1.json +164 -0
  52. package/src/shared/scripts/schemas/skf-export-result-envelope.v1.json +160 -0
  53. package/src/shared/scripts/schemas/skf-quick-skill-result-envelope.v1.json +261 -0
  54. package/src/shared/scripts/schemas/skf-refine-architecture-result-envelope.v1.json +192 -0
  55. package/src/shared/scripts/schemas/skf-rename-skill-result-envelope.v1.json +179 -0
  56. package/src/shared/scripts/schemas/skf-setup-result-envelope.v1.json +27 -11
  57. package/src/shared/scripts/schemas/skf-stack-result-envelope.v1.json +176 -0
  58. package/src/shared/scripts/schemas/skf-test-result-envelope.v1.json +173 -0
  59. package/src/shared/scripts/schemas/skf-update-result-envelope.v1.json +19 -5
  60. package/src/shared/scripts/schemas/skf-verify-stack-result-envelope.v1.json +180 -0
  61. package/src/shared/scripts/schemas/skill-brief.v1.json +34 -0
  62. package/src/shared/scripts/schemas/workspace-detection.v1.json +1 -1
  63. package/src/shared/scripts/skf-atomic-write.py +30 -14
  64. package/src/shared/scripts/skf-build-change-manifest.py +2203 -24
  65. package/src/shared/scripts/skf-ccc-git-hygiene.py +532 -0
  66. package/src/shared/scripts/skf-check-unit-records.py +184 -0
  67. package/src/shared/scripts/skf-check-workspace-drift.py +538 -9
  68. package/src/shared/scripts/skf-classify-changed-files.py +694 -0
  69. package/src/shared/scripts/skf-comention-pairs.py +1333 -123
  70. package/src/shared/scripts/skf-compare-file-hashes.py +1 -1
  71. package/src/shared/scripts/skf-count-imports.py +1867 -0
  72. package/src/shared/scripts/skf-count-tokens.py +1 -1
  73. package/src/shared/scripts/skf-derive-assembly-shape.py +3 -2
  74. package/src/shared/scripts/skf-description-guard.py +99 -11
  75. package/src/shared/scripts/skf-detect-docs.py +694 -2
  76. package/src/shared/scripts/skf-detect-language.py +486 -107
  77. package/src/shared/scripts/skf-detect-registry.py +887 -0
  78. package/src/shared/scripts/skf-detect-scripts-assets.py +1 -1
  79. package/src/shared/scripts/skf-detect-tools.py +209 -27
  80. package/src/shared/scripts/skf-detect-workspaces.py +506 -30
  81. package/src/shared/scripts/skf-disqualify-candidates.py +821 -182
  82. package/src/shared/scripts/skf-emit-brief-result-envelope.py +69 -191
  83. package/src/shared/scripts/skf-emit-result-envelope.py +1604 -106
  84. package/src/shared/scripts/skf-enumerate-stack-skills.py +986 -117
  85. package/src/shared/scripts/skf-extract-public-api.py +4084 -85
  86. package/src/shared/scripts/skf-extraction-inventory.py +746 -0
  87. package/src/shared/scripts/skf-extraction-snapshot.py +539 -0
  88. package/src/shared/scripts/skf-fetch-temporal.py +674 -0
  89. package/src/shared/scripts/skf-find-cycles.py +97 -29
  90. package/src/shared/scripts/skf-find-test-report.py +476 -0
  91. package/src/shared/scripts/skf-forge-tier-rw.py +444 -203
  92. package/src/shared/scripts/skf-github-fetch.py +365 -0
  93. package/src/shared/scripts/skf-github-probe.py +661 -0
  94. package/src/shared/scripts/skf-hash-content.py +166 -12
  95. package/src/shared/scripts/skf-language-corpora.py +1 -1
  96. package/src/shared/scripts/skf-load-provenance.py +159 -27
  97. package/src/shared/scripts/skf-manifest-ops.py +1 -1
  98. package/src/shared/scripts/skf-merge-ccc-exclusions.py +2307 -223
  99. package/src/shared/scripts/skf-merge-doc-urls.py +1 -1
  100. package/src/shared/scripts/skf-names-present.py +221 -0
  101. package/src/shared/scripts/skf-pair-intersect.py +119 -28
  102. package/src/shared/scripts/skf-parse-gaps.py +1384 -0
  103. package/src/shared/scripts/skf-preapply.py +1 -1
  104. package/src/shared/scripts/skf-preflight.py +161 -27
  105. package/src/shared/scripts/skf-promote-staged.py +430 -0
  106. package/src/shared/scripts/skf-provenance-gap-dispatch.py +39 -7
  107. package/src/shared/scripts/skf-qmd-classify-collections.py +229 -45
  108. package/src/shared/scripts/skf-quick-batch.py +774 -0
  109. package/src/shared/scripts/skf-rebuild-managed-sections.py +972 -88
  110. package/src/shared/scripts/skf-recommend-scope-type.py +323 -156
  111. package/src/shared/scripts/skf-render-metadata-stats.py +156 -12
  112. package/src/shared/scripts/skf-render-quick-metadata.py +132 -28
  113. package/src/shared/scripts/skf-render-stack-metadata.py +976 -0
  114. package/src/shared/scripts/skf-resolve-authoritative-files.py +128 -13
  115. package/src/shared/scripts/skf-resolve-package.py +523 -106
  116. package/src/shared/scripts/skf-rewrite-skill-name.py +433 -47
  117. package/src/shared/scripts/skf-run-lock.py +577 -0
  118. package/src/shared/scripts/skf-scan-manifests.py +998 -57
  119. package/src/shared/scripts/skf-scan-skill-md-structure.py +1341 -37
  120. package/src/shared/scripts/skf-severity-classify.py +712 -108
  121. package/src/shared/scripts/skf-shape-detect.py +298 -204
  122. package/src/shared/scripts/skf-shard-body.py +9 -8
  123. package/src/shared/scripts/skf-skill-inventory.py +2412 -89
  124. package/src/shared/scripts/skf-skills-module.py +472 -0
  125. package/src/shared/scripts/skf-source-tree.py +1796 -0
  126. package/src/shared/scripts/skf-structural-diff.py +670 -119
  127. package/src/shared/scripts/skf-tessl-review.py +706 -0
  128. package/src/shared/scripts/skf-update-active-symlink.py +5 -5
  129. package/src/shared/scripts/skf-update-run-state.py +624 -0
  130. package/src/shared/scripts/skf-validate-brief-inputs.py +92 -29
  131. package/src/shared/scripts/skf-validate-brief-schema.py +4 -1
  132. package/src/shared/scripts/skf-validate-feasibility-report.py +577 -66
  133. package/src/shared/scripts/skf-validate-frontmatter.py +103 -26
  134. package/src/shared/scripts/skf-validate-output.py +712 -64
  135. package/src/shared/scripts/skf-validate-pins.py +1 -1
  136. package/src/shared/scripts/skf-verify-no-trace.py +116 -10
  137. package/src/shared/scripts/skf-verify-provenance-completeness.py +2919 -54
  138. package/src/shared/scripts/skf-write-skill-brief.py +367 -19
  139. package/src/shared/tool-requirements.yaml +201 -0
  140. package/src/skf-analyze-source/SKILL.md +41 -36
  141. package/src/skf-analyze-source/assets/skill-brief-schema.md +7 -8
  142. package/src/skf-analyze-source/customize.toml +36 -24
  143. package/src/skf-analyze-source/references/auto-docs-only.md +58 -20
  144. package/src/skf-analyze-source/references/continue.md +2 -13
  145. package/src/skf-analyze-source/references/discover-additional-source.md +147 -0
  146. package/src/skf-analyze-source/references/generate-briefs.md +121 -55
  147. package/src/skf-analyze-source/references/headless-contract.md +42 -15
  148. package/src/skf-analyze-source/references/identify-units.md +96 -110
  149. package/src/skf-analyze-source/references/init.md +73 -71
  150. package/src/skf-analyze-source/references/map-and-detect.md +123 -105
  151. package/src/skf-analyze-source/references/map-unit-exports.md +68 -0
  152. package/src/skf-analyze-source/references/recommend.md +51 -70
  153. package/src/skf-analyze-source/references/scan-project.md +60 -84
  154. package/src/skf-analyze-source/references/scan-root.md +39 -0
  155. package/src/skf-analyze-source/references/step-auto-scope-coexistence.md +47 -0
  156. package/src/skf-analyze-source/references/step-auto-scope-corpora.md +53 -0
  157. package/src/skf-analyze-source/references/step-auto-scope-split.md +91 -0
  158. package/src/skf-analyze-source/references/step-auto-scope.md +208 -293
  159. package/src/skf-analyze-source/references/step-shape-detect.md +14 -12
  160. package/src/skf-analyze-source/references/unit-detection-heuristics.md +37 -42
  161. package/src/skf-audit-skill/SKILL.md +43 -51
  162. package/src/skf-audit-skill/assets/drift-report-template.md +27 -3
  163. package/src/skf-audit-skill/customize.toml +41 -20
  164. package/src/skf-audit-skill/references/constituent-freshness.md +91 -0
  165. package/src/skf-audit-skill/references/doc-drift.md +141 -0
  166. package/src/skf-audit-skill/references/headless-contract.md +29 -0
  167. package/src/skf-audit-skill/references/init.md +148 -210
  168. package/src/skf-audit-skill/references/re-index.md +96 -108
  169. package/src/skf-audit-skill/references/report.md +96 -33
  170. package/src/skf-audit-skill/references/semantic-diff.md +27 -18
  171. package/src/skf-audit-skill/references/severity-classify.md +79 -65
  172. package/src/skf-audit-skill/references/severity-rules.md +15 -6
  173. package/src/skf-audit-skill/references/structural-diff.md +75 -90
  174. package/src/skf-audit-skill/references/upstream-checkout.md +77 -0
  175. package/src/skf-audit-skill/scripts/render-drift-tables.py +685 -0
  176. package/src/skf-brief-skill/SKILL.md +36 -25
  177. package/src/skf-brief-skill/assets/description-voice-examples.md +1 -1
  178. package/src/skf-brief-skill/assets/scope-templates.md +17 -24
  179. package/src/skf-brief-skill/assets/skill-brief-schema.md +29 -15
  180. package/src/skf-brief-skill/customize.toml +48 -20
  181. package/src/skf-brief-skill/references/analyze-target.md +142 -125
  182. package/src/skf-brief-skill/references/confirm-brief.md +10 -8
  183. package/src/skf-brief-skill/references/draft-checkpoint.md +36 -17
  184. package/src/skf-brief-skill/references/gather-intent-ratify.md +68 -0
  185. package/src/skf-brief-skill/references/gather-intent.md +87 -182
  186. package/src/skf-brief-skill/references/headless-args.md +84 -16
  187. package/src/skf-brief-skill/references/health-check.md +1 -1
  188. package/src/skf-brief-skill/references/invocation-contract.md +18 -13
  189. package/src/skf-brief-skill/references/portfolio-similarity-check.md +1 -1
  190. package/src/skf-brief-skill/references/qmd-collection-registration.md +7 -10
  191. package/src/skf-brief-skill/references/scope-definition.md +123 -47
  192. package/src/skf-brief-skill/references/step-auto-brief.md +24 -80
  193. package/src/skf-brief-skill/references/step-auto-validate.md +20 -121
  194. package/src/skf-brief-skill/references/version-resolution.md +3 -2
  195. package/src/skf-brief-skill/references/write-brief.md +66 -57
  196. package/src/skf-campaign/SKILL.md +31 -34
  197. package/src/skf-campaign/assets/campaign-state-schema.json +25 -4
  198. package/src/skf-campaign/customize.toml +47 -16
  199. package/src/skf-campaign/references/campaign-contracts.md +39 -29
  200. package/src/skf-campaign/references/campaign-directive-spec.md +4 -2
  201. package/src/skf-campaign/references/health-check.md +7 -16
  202. package/src/skf-campaign/references/step-01-setup.md +46 -84
  203. package/src/skf-campaign/references/step-02-strategy.md +31 -30
  204. package/src/skf-campaign/references/step-03-pins.md +26 -18
  205. package/src/skf-campaign/references/step-04-provenance.md +24 -23
  206. package/src/skf-campaign/references/step-05-skill-loop.md +67 -48
  207. package/src/skf-campaign/references/step-06-batch.md +41 -34
  208. package/src/skf-campaign/references/step-07-capstone.md +40 -25
  209. package/src/skf-campaign/references/step-08-verify.md +28 -29
  210. package/src/skf-campaign/references/step-09-refine.md +29 -30
  211. package/src/skf-campaign/references/step-10-export.md +48 -36
  212. package/src/skf-campaign/references/step-11-maintenance.md +31 -34
  213. package/src/skf-campaign/references/step-resume.md +37 -68
  214. package/src/skf-campaign/scripts/campaign-deps.py +57 -18
  215. package/src/skf-campaign/scripts/campaign-parse-manifest.py +361 -54
  216. package/src/skf-campaign/scripts/campaign-provenance.py +96 -53
  217. package/src/skf-campaign/scripts/campaign-quality-gate.py +592 -0
  218. package/src/skf-campaign/scripts/campaign-render-batch.py +257 -49
  219. package/src/skf-campaign/scripts/campaign-render-kickoff.py +343 -50
  220. package/src/skf-campaign/scripts/campaign-report.py +204 -37
  221. package/src/skf-campaign/scripts/campaign-state.py +1128 -0
  222. package/src/skf-campaign/scripts/campaign-status.py +10 -74
  223. package/src/skf-campaign/scripts/campaign-validate-pins.py +30 -3
  224. package/src/skf-campaign/scripts/campaign-validate-state.py +34 -4
  225. package/src/skf-campaign/templates/campaign-brief-template.yaml +4 -5
  226. package/src/skf-campaign/templates/campaign-report-template.md +5 -1
  227. package/src/skf-campaign/templates/kickoff-template.md +0 -14
  228. package/src/skf-create-skill/SKILL.md +27 -20
  229. package/src/skf-create-skill/assets/compile-assembly-rules.md +6 -5
  230. package/src/skf-create-skill/assets/skill-sections.md +15 -5
  231. package/src/skf-create-skill/customize.toml +20 -8
  232. package/src/skf-create-skill/references/authoritative-files-protocol.md +41 -42
  233. package/src/skf-create-skill/references/batch-mode.md +81 -0
  234. package/src/skf-create-skill/references/ccc-index-check.md +27 -0
  235. package/src/skf-create-skill/references/compile.md +107 -29
  236. package/src/skf-create-skill/references/component-extraction.md +113 -91
  237. package/src/skf-create-skill/references/enrich.md +41 -23
  238. package/src/skf-create-skill/references/entry-points-by-hand.md +20 -0
  239. package/src/skf-create-skill/references/extract.md +200 -161
  240. package/src/skf-create-skill/references/extraction-patterns-by-hand.md +141 -0
  241. package/src/skf-create-skill/references/extraction-patterns-tracing.md +2 -2
  242. package/src/skf-create-skill/references/extraction-patterns.md +584 -196
  243. package/src/skf-create-skill/references/generate-artifacts.md +145 -93
  244. package/src/skf-create-skill/references/health-check.md +1 -1
  245. package/src/skf-create-skill/references/load-brief.md +53 -36
  246. package/src/skf-create-skill/references/relabel-rule.md +12 -0
  247. package/src/skf-create-skill/references/report.md +28 -59
  248. package/src/skf-create-skill/references/source-resolution-protocols.md +49 -155
  249. package/src/skf-create-skill/references/step-auto-shard.md +20 -93
  250. package/src/skf-create-skill/references/step-doc-rot.md +44 -60
  251. package/src/skf-create-skill/references/step-doc-sources.md +28 -19
  252. package/src/skf-create-skill/references/sub/ccc-discover.md +18 -7
  253. package/src/skf-create-skill/references/sub/fetch-docs.md +106 -59
  254. package/src/skf-create-skill/references/sub/fetch-temporal.md +53 -166
  255. package/src/skf-create-skill/references/tier-degradation-rules.md +18 -9
  256. package/src/skf-create-skill/references/validate.md +173 -99
  257. package/src/skf-create-skill/scripts/scan-doc-rot.py +232 -99
  258. package/src/skf-create-stack-skill/SKILL.md +29 -56
  259. package/src/skf-create-stack-skill/assets/metadata-contract.md +51 -0
  260. package/src/skf-create-stack-skill/assets/provenance-map-schema.md +15 -15
  261. package/src/skf-create-stack-skill/assets/stack-skill-template.md +23 -57
  262. package/src/skf-create-stack-skill/customize.toml +23 -12
  263. package/src/skf-create-stack-skill/references/compile-stack.md +57 -66
  264. package/src/skf-create-stack-skill/references/compose-mode-rules.md +24 -44
  265. package/src/skf-create-stack-skill/references/detect-integrations.md +92 -95
  266. package/src/skf-create-stack-skill/references/detect-manifests.md +46 -71
  267. package/src/skf-create-stack-skill/references/generate-output.md +138 -128
  268. package/src/skf-create-stack-skill/references/init.md +90 -32
  269. package/src/skf-create-stack-skill/references/integration-patterns.md +1 -17
  270. package/src/skf-create-stack-skill/references/invocation-contract.md +34 -0
  271. package/src/skf-create-stack-skill/references/manifest-patterns.md +32 -20
  272. package/src/skf-create-stack-skill/references/parallel-extract.md +112 -38
  273. package/src/skf-create-stack-skill/references/rank-and-confirm.md +57 -75
  274. package/src/skf-create-stack-skill/references/report.md +39 -33
  275. package/src/skf-create-stack-skill/references/validate.md +20 -39
  276. package/src/skf-drop-skill/SKILL.md +28 -51
  277. package/src/skf-drop-skill/customize.toml +44 -30
  278. package/src/skf-drop-skill/references/execute.md +79 -146
  279. package/src/skf-drop-skill/references/invocation-contract.md +64 -0
  280. package/src/skf-drop-skill/references/report.md +46 -30
  281. package/src/skf-drop-skill/references/select.md +118 -124
  282. package/src/skf-drop-skill/scripts/dir-sizes.py +54 -26
  283. package/src/skf-drop-skill/scripts/drop-roster.py +322 -0
  284. package/src/skf-export-skill/SKILL.md +40 -62
  285. package/src/skf-export-skill/assets/managed-section-format.md +14 -50
  286. package/src/skf-export-skill/assets/snippet-format.md +3 -1
  287. package/src/skf-export-skill/customize.toml +42 -13
  288. package/src/skf-export-skill/references/generate-snippet.md +54 -46
  289. package/src/skf-export-skill/references/health-check.md +2 -0
  290. package/src/skf-export-skill/references/invocation-contract.md +15 -0
  291. package/src/skf-export-skill/references/load-skill.md +88 -62
  292. package/src/skf-export-skill/references/manifest-rebuild.md +9 -10
  293. package/src/skf-export-skill/references/multi-skill-mode.md +4 -4
  294. package/src/skf-export-skill/references/orphan-context-detection.md +13 -5
  295. package/src/skf-export-skill/references/orphan-row-detection.md +31 -22
  296. package/src/skf-export-skill/references/package.md +15 -73
  297. package/src/skf-export-skill/references/preflight-snippet-root-probe.md +51 -70
  298. package/src/skf-export-skill/references/result-envelope.md +31 -16
  299. package/src/skf-export-skill/references/summary.md +41 -17
  300. package/src/skf-export-skill/references/token-report.md +4 -12
  301. package/src/skf-export-skill/references/update-context.md +118 -237
  302. package/src/skf-forger/SKILL.md +61 -37
  303. package/src/skf-forger/bmad-skill-manifest.yaml +4 -1
  304. package/src/skf-forger/customize.toml +43 -0
  305. package/src/skf-forger/references/pipeline-mode.md +73 -18
  306. package/src/skf-forger/scripts/forge-status.py +299 -0
  307. package/src/skf-forger/scripts/parse-pipeline.py +322 -54
  308. package/src/skf-forger/scripts/pipeline-gate.py +428 -0
  309. package/src/skf-forger/scripts/pipeline-journal.py +1052 -0
  310. package/src/skf-quick-skill/SKILL.md +54 -53
  311. package/src/skf-quick-skill/assets/skill-template.md +4 -2
  312. package/src/skf-quick-skill/customize.toml +51 -20
  313. package/src/skf-quick-skill/references/batch-mode.md +74 -21
  314. package/src/skf-quick-skill/references/compile.md +30 -31
  315. package/src/skf-quick-skill/references/ecosystem-check.md +7 -57
  316. package/src/skf-quick-skill/references/finalize.md +69 -18
  317. package/src/skf-quick-skill/references/halt-contract.md +41 -29
  318. package/src/skf-quick-skill/references/health-check.md +5 -3
  319. package/src/skf-quick-skill/references/quick-extract.md +114 -45
  320. package/src/skf-quick-skill/references/registry-resolution.md +9 -64
  321. package/src/skf-quick-skill/references/resolve-target.md +116 -66
  322. package/src/skf-quick-skill/references/write-and-validate.md +79 -40
  323. package/src/skf-refine-architecture/SKILL.md +43 -53
  324. package/src/skf-refine-architecture/customize.toml +49 -20
  325. package/src/skf-refine-architecture/references/compile.md +97 -54
  326. package/src/skf-refine-architecture/references/exit-codes.md +30 -0
  327. package/src/skf-refine-architecture/references/finding-storage.md +21 -0
  328. package/src/skf-refine-architecture/references/gap-analysis.md +101 -38
  329. package/src/skf-refine-architecture/references/improvements.md +14 -20
  330. package/src/skf-refine-architecture/references/init.md +98 -57
  331. package/src/skf-refine-architecture/references/issue-detection.md +32 -39
  332. package/src/skf-refine-architecture/references/refinement-rules.md +37 -48
  333. package/src/skf-refine-architecture/references/report.md +65 -54
  334. package/src/skf-refine-architecture/scripts/skf-check-preservation.py +1619 -0
  335. package/src/skf-rename-skill/SKILL.md +19 -54
  336. package/src/skf-rename-skill/customize.toml +32 -26
  337. package/src/skf-rename-skill/references/execute.md +230 -184
  338. package/src/skf-rename-skill/references/exit-codes.md +7 -7
  339. package/src/skf-rename-skill/references/health-check.md +1 -7
  340. package/src/skf-rename-skill/references/invocation-contract.md +25 -0
  341. package/src/skf-rename-skill/references/report.md +63 -52
  342. package/src/skf-rename-skill/references/select.md +197 -115
  343. package/src/skf-rename-skill/scripts/skf-validate-rename-name.py +161 -21
  344. package/src/skf-setup/SKILL.md +26 -26
  345. package/src/skf-setup/customize.toml +14 -10
  346. package/src/skf-setup/references/auto-index.md +50 -63
  347. package/src/skf-setup/references/ccc-index.md +29 -90
  348. package/src/skf-setup/references/detect-and-tier.md +58 -67
  349. package/src/skf-setup/references/health-check.md +2 -0
  350. package/src/skf-setup/references/invocation-contract.md +14 -0
  351. package/src/skf-setup/references/report.md +43 -166
  352. package/src/skf-setup/references/tier-rules.md +5 -5
  353. package/src/skf-setup/references/write-config.md +34 -57
  354. package/src/skf-test-skill/SKILL.md +17 -57
  355. package/src/skf-test-skill/assets/output-section-formats.md +33 -34
  356. package/src/skf-test-skill/customize.toml +27 -13
  357. package/src/skf-test-skill/references/coherence-check.md +134 -62
  358. package/src/skf-test-skill/references/coverage-check-tiers.md +35 -0
  359. package/src/skf-test-skill/references/coverage-check.md +217 -254
  360. package/src/skf-test-skill/references/detect-mode.md +5 -5
  361. package/src/skf-test-skill/references/external-validators.md +94 -82
  362. package/src/skf-test-skill/references/health-check.md +6 -7
  363. package/src/skf-test-skill/references/init.md +163 -88
  364. package/src/skf-test-skill/references/invocation-contract.md +66 -0
  365. package/src/skf-test-skill/references/migration-section-rules.md +5 -2
  366. package/src/skf-test-skill/references/report.md +162 -142
  367. package/src/skf-test-skill/references/score.md +80 -107
  368. package/src/skf-test-skill/references/scoring-rules.md +41 -155
  369. package/src/skf-test-skill/references/source-access-protocol.md +19 -92
  370. package/src/skf-test-skill/references/step-hard-gate.md +51 -33
  371. package/src/skf-test-skill/scripts/aggregate-coherence.py +218 -30
  372. package/src/skf-test-skill/scripts/build-result-context.py +287 -0
  373. package/src/skf-test-skill/scripts/check-metadata-coherence.py +37 -4
  374. package/src/skf-test-skill/scripts/combine-external-scores.py +23 -6
  375. package/src/skf-test-skill/scripts/compute-score.py +223 -45
  376. package/src/skf-test-skill/scripts/gap-ledger.py +1381 -0
  377. package/src/skf-test-skill/scripts/hard-gate.py +203 -0
  378. package/src/skf-test-skill/scripts/load-coverage-inputs.py +760 -0
  379. package/src/skf-test-skill/scripts/locate-export-segments.py +835 -0
  380. package/src/skf-test-skill/scripts/reconcile-coverage.py +273 -79
  381. package/src/skf-test-skill/scripts/score-signatures.py +459 -0
  382. package/src/skf-test-skill/scripts/stage-helper-payload.py +148 -0
  383. package/src/skf-test-skill/scripts/validate-inventory.py +311 -16
  384. package/src/skf-test-skill/scripts/verify-declared-numerator.py +127 -52
  385. package/src/skf-test-skill/templates/test-report-template.md +21 -15
  386. package/src/skf-update-skill/SKILL.md +38 -25
  387. package/src/skf-update-skill/customize.toml +27 -12
  388. package/src/skf-update-skill/references/detect-changes.md +233 -222
  389. package/src/skf-update-skill/references/gap-driven.md +336 -0
  390. package/src/skf-update-skill/references/health-check.md +31 -5
  391. package/src/skf-update-skill/references/init.md +250 -84
  392. package/src/skf-update-skill/references/invocation-contract.md +12 -0
  393. package/src/skf-update-skill/references/manual-section-rules.md +6 -23
  394. package/src/skf-update-skill/references/merge.md +180 -47
  395. package/src/skf-update-skill/references/re-extract.md +53 -262
  396. package/src/skf-update-skill/references/report.md +100 -35
  397. package/src/skf-update-skill/references/write.md +331 -149
  398. package/src/skf-update-skill/scripts/skf-new-file-diff.py +29 -7
  399. package/src/skf-verify-stack/SKILL.md +23 -42
  400. package/src/skf-verify-stack/assets/feasibility-report-template.md +11 -5
  401. package/src/skf-verify-stack/customize.toml +55 -22
  402. package/src/skf-verify-stack/references/coverage-patterns.md +17 -8
  403. package/src/skf-verify-stack/references/coverage.md +67 -64
  404. package/src/skf-verify-stack/references/exit-codes.md +21 -8
  405. package/src/skf-verify-stack/references/init.md +107 -62
  406. package/src/skf-verify-stack/references/integration-verification-rules.md +12 -13
  407. package/src/skf-verify-stack/references/integrations.md +106 -65
  408. package/src/skf-verify-stack/references/report.md +59 -42
  409. package/src/skf-verify-stack/references/requirements.md +32 -9
  410. package/src/skf-verify-stack/references/synthesize.md +53 -39
  411. package/src/skf-verify-stack/scripts/skf-coverage-tally.py +398 -52
  412. package/src/skf-verify-stack/scripts/skf-previous-report.py +330 -0
  413. package/src/skf-verify-stack/scripts/skf-report-delta.py +453 -49
  414. package/src/skf-verify-stack/scripts/skf-verdict-rollup.py +240 -27
  415. package/tools/cli/commands/install.js +11 -4
  416. package/tools/cli/commands/status.js +15 -3
  417. package/tools/cli/commands/update.js +11 -4
  418. package/tools/cli/lib/tool-check.js +320 -0
  419. package/tools/cli/lib/version-check.js +22 -9
  420. package/tools/cli/skf-cli.js +4 -1
  421. package/.gitattributes +0 -16
  422. package/.nvmrc +0 -1
  423. package/docs/_internal/RELEASING.md +0 -679
  424. package/release-audits/v1.0.0-launch-audit.md +0 -728
  425. package/src/skf-audit-skill/references/step-doc-drift.md +0 -177
  426. package/src/skf-brief-skill/references/headless-source-authority-detection.md +0 -26
  427. package/src/skf-campaign/manifest.yaml +0 -15
  428. package/src/skf-create-skill/assets/tessl-dismissal-rules.md +0 -106
  429. package/src/skf-create-skill/references/ecosystem-check.md +0 -74
  430. package/src/skf-drop-skill/references/headless-contract.md +0 -18
  431. package/src/skf-update-skill/references/merge-conflict-rules.md +0 -15
  432. package/src/skf-update-skill/references/remote-source-resolution.md +0 -98
  433. package/src/skf-update-skill/references/validate.md +0 -124
  434. package/tools/validate-docs-drift.js +0 -233
  435. package/tools/validate-docs-links.js +0 -665
@@ -1,9 +1,15 @@
1
1
  ---
2
2
  outputFile: '{forge_data_folder}/analyze-source-report-{project_name}.md'
3
- schemaFile: '{briefSchemaPath}'
3
+ schemaFile: 'assets/skill-brief-schema.md'
4
+ writeSkillBriefProbeOrder:
5
+ - '{project-root}/_bmad/skf/shared/scripts/skf-write-skill-brief.py'
6
+ - '{project-root}/src/shared/scripts/skf-write-skill-brief.py'
4
7
  validateBriefSchemaProbeOrder:
5
8
  - '{project-root}/_bmad/skf/shared/scripts/skf-validate-brief-schema.py'
6
9
  - '{project-root}/src/shared/scripts/skf-validate-brief-schema.py'
10
+ scanManifestsProbeOrder:
11
+ - '{project-root}/_bmad/skf/shared/scripts/skf-scan-manifests.py'
12
+ - '{project-root}/src/shared/scripts/skf-scan-manifests.py'
7
13
  nextStepFile: 'health-check.md'
8
14
  ---
9
15
 
@@ -13,71 +19,112 @@ nextStepFile: 'health-check.md'
13
19
 
14
20
  ## STEP GOAL:
15
21
 
16
- To generate a valid skill-brief.yaml file for each confirmed unit using the schema, write the files to the forge data folder, append generation results to the analysis report, and recommend the appropriate next workflow for each unit — completing the analyze-source workflow.
22
+ To write a valid skill-brief.yaml for each confirmed unit through the brief writer, append the generation results to the analysis report, recommend the next workflow for each unit and end the run with its result files and envelope, completing the analyze-source workflow (also when no unit was confirmed).
17
23
 
18
24
  ## Rules
19
25
 
20
26
  - Generate only for units in confirmed_units — no extras, no omissions
21
- - Do not modify recommendations or re-ask for confirmations
27
+ - Do not revisit the per-unit decisions of step 5: the §4 preview confirms only the write
22
28
  - Every generated field must trace back to data collected in steps 02-05
29
+ - Briefs are written only by the brief writer, from a context file: never render or hand-edit brief YAML
23
30
  - Chains to the local health-check step via `{nextStepFile}` after completion — the user-facing summary is not the terminal step
24
31
 
25
32
  ## MANDATORY SEQUENCE
26
33
 
34
+ Every HARD HALT in this step names its exit code, `halt_reason` and phase. When `{headless_mode}` is true it first prints its envelope on stderr through the shared emitter (`{emitEnvelopeHelper}` and `{run_dir}` come from SKILL.md On Activation): stage `{run_dir}/halt.json` as `{"phase": "<phase>", "reason": "<the halt message>", "halt_reason": "<halt_reason>", "mode": "interactive", "report_path": "{outputFile as an absolute path}"}`, plus `"path"` when the halt names one and the envelope fields the site names, then run
35
+
36
+ ```bash
37
+ uv run {emitEnvelopeHelper} emit-halt --workflow skf-analyze-source --run-dir "{run_dir}" --target stderr < "{run_dir}/halt.json"
38
+ ```
39
+
40
+ and display the line it prints verbatim. Write the payload as valid JSON: in the halt message and `path`, replace each backslash with / and each double quote with a backtick. If the emitter exits non-zero or prints no line, display the halt message alone. An interactive HALT displays its message and emits nothing.
41
+
27
42
  ### 1. Load Context
28
43
 
29
44
  Read {outputFile} completely to obtain:
30
45
  - `confirmed_units` from frontmatter (names of units approved in step 05)
31
- - `project_paths`, `forge_tier`, `user_name`, `forge_data_folder` from frontmatter
32
- - Recommendation cards from "## Recommendations" section (proposed brief fields per unit)
46
+ - `confirmed_composites` from frontmatter (composites approved in step 04, each with its constituents' names and paths)
47
+ - `project_paths`, `refs`, `forge_tier`, `user_name`, `forge_data_folder` from frontmatter
48
+ - Recommendation cards from "## Recommendations" section (proposed brief fields and the project path of each unit)
33
49
  - Export map and integration data from prior sections
34
50
 
35
51
  Load {schemaFile} for validation reference.
36
52
 
37
- **Guard clause:** If `confirmed_units` is empty, present:
53
+ **No confirmed unit:** If `confirmed_units` is empty, present:
38
54
  "**No confirmed units to generate briefs for.** The analysis is complete with no skill briefs produced. Run analyze-source again with different scope or parameters if needed."
39
- Mark workflow complete and halt.
55
+ The run still ends through the same sequence as one that wrote briefs: skip §2 to §6 and continue at §7, which appends the Generation Results with no brief and adds `generate-briefs` to `stepsCompleted` (so a re-run starts a fresh analysis instead of resuming into this guard), then §8, §9 (an envelope and result contract with `brief_paths: []` and `unit_counts.confirmed: 0`), §9b and §10.
56
+
57
+ ### 2. Build Each Brief's Context
40
58
 
41
- ### 2. Generate Skill-Brief YAML Per Unit
59
+ **Resolve `{writeSkillBriefHelper}`** from `{writeSkillBriefProbeOrder}` and **`{validateBriefSchemaHelper}`** from `{validateBriefSchemaProbeOrder}`; first existing path wins for each. If one has no candidate, HARD HALT (exit code 3, `halt_reason: "resolution-failure"`, phase `generate-briefs:2`): "`{the missing script}` is missing. Re-install SKF."
42
60
 
43
- For each unit in `confirmed_units`, construct a skill-brief.yaml using:
61
+ The brief writer renders, checks and writes each brief, and applies the version precedence (`target_version`, then `detected_version`, then `1.0.0`): this step supplies the values. For each unit in `confirmed_units`, take them from:
44
62
 
45
63
  **Field mapping:**
46
64
 
47
65
  | Field | Source |
48
66
  |-------|--------|
49
- | name | Confirmed name from step 05 recommendation card |
50
- | version | Auto-detect from source (see schema Version Detection), fall back to `1.0.0` |
51
- | source_repo | `{project_paths[0]}` from frontmatter (or per-unit path if multi-repo) |
67
+ | name | Confirmed name from step 05 recommendation card: the name identify-units Step C derived, unless step 5 renamed the unit |
68
+ | version | Not set here: `detected_version` comes by {schemaFile}'s **Version Detection**, for the unit's own manifest in its project path's manifest scan, `{run_dir}/manifests-{i}.json` (scan-project and discover-additional-source write it). When that file is missing, as in a session that resumed the report, run `uv run {scanManifestsHelper} scan "{scan_root}" > "{run_dir}/manifests-{i}.json"` first, `{scanManifestsHelper}` the first existing path of `{scanManifestsProbeOrder}` |
69
+ | source_repo | The unit's project path, the `project_paths[]` entry it was found under (a composite's constituents share one) |
70
+ | target_ref | The unit's ref: its project path's entry in `refs`, else null. Never a version: `target_version` stays null |
52
71
  | language | Language the skill **documents** (primary language detected in step 03). For a language / spec reference this is the *documented* language, which may differ from the source language it is extracted from — e.g. a SurrealQL reference extracted from a Rust engine records `surrealql`, not `rust` (see {schemaFile} "Documented vs source language") |
53
72
  | scope.type | Scope type from step 05 recommendation card |
54
- | scope.include | Include patterns from step 05 recommendation card |
73
+ | scope.include | Include patterns from step 05 recommendation card, plus, for a composite (`Boundary: Composite` on its card), `<path>/**` for every constituent path of its `confirmed_composites` entry (such as `crates/animato-core/**`), so the brief spans every constituent. Find the entry by those paths, which the card's Path lists, not by name: step 05 may rename the unit |
55
74
  | scope.exclude | Inferred from heuristics (test files, generated code) |
56
75
  | scope.tier_a_include | Optional — narrower tier-A surface for stratified-scope monorepos and `reference-app` pattern surfaces; usually left to skf-brief-skill to refine |
57
76
  | scope.notes | Rationale from step 05 recommendation card |
58
77
  | description | Description from step 05 recommendation card |
59
78
  | forge_tier | `{forge_tier}` from frontmatter |
60
- | created | Current date as a **quoted** string in ISO format `'YYYY-MM-DD'` — quote it so YAML stores it as text, not a parsed date object (the schema, and the §3a gate, require a string) |
79
+ | created | Current date, `YYYY-MM-DD` |
61
80
  | created_by | `{user_name}` from frontmatter |
62
81
 
82
+ Write each unit's context as `{run_dir}/brief-{unit-name}.json`, a file and never an echo'd string:
83
+
84
+ ```json
85
+ {
86
+ "name": "{unit-name}",
87
+ "target_version": null,
88
+ "target_ref": "{the unit's ref, or null}",
89
+ "detected_version": "{version, or null}",
90
+ "source_type": "source",
91
+ "source_repo": "{source_repo}",
92
+ "language": "{language}",
93
+ "description": "{description}",
94
+ "forge_tier": "{forge_tier}",
95
+ "created": "{current_date}",
96
+ "created_by": "{user_name}",
97
+ "scope_type": "{scope.type}",
98
+ "scope_include": ["{scope.include}"],
99
+ "scope_exclude": ["{scope.exclude}"],
100
+ "scope_notes": "{scope.notes}",
101
+ "scope_rationale": null,
102
+ "scope_tier_a_include": null,
103
+ "scope_amendments": null,
104
+ "scope_registry_path": null,
105
+ "scope_ui_variants": null,
106
+ "scope_demo_patterns": null,
107
+ "doc_urls": null,
108
+ "scripts_intent": null,
109
+ "assets_intent": null,
110
+ "source_authority": null,
111
+ "source_ref": null
112
+ }
113
+ ```
114
+
63
115
  ### 3. Validate Each Brief
64
116
 
65
- Validation has two parts: a **deterministic schema gate** (authoritative for structure) and **semantic cross-checks** the schema cannot express. Run the schema gate first.
117
+ Validation has two parts: a **deterministic gate** (authoritative for structure) and **semantic cross-checks** the schema cannot express. Run the gate first.
66
118
 
67
- **3a. Deterministic schema gate.** Resolve `{validateBriefSchemaHelper}` from `{validateBriefSchemaProbeOrder}` (first existing path wins; HALT with a clear message if no candidate exists). For each generated brief, pipe the *exact* assembled YAML to the helper:
119
+ **3a. Deterministic gate.** Render each brief into the run folder, then run on it the schema check `skf-brief-skill` runs when it reads a brief, so a brief that passes here is not rejected there for structural reasons:
68
120
 
69
121
  ```bash
70
- uv run {validateBriefSchemaHelper} - <<'YAML'
71
- {assembled-brief-yaml}
72
- YAML
122
+ uv run {writeSkillBriefHelper} write --target "{run_dir}/briefs/{unit-name}/skill-brief.yaml" --from-flat < "{run_dir}/brief-{unit-name}.json"
123
+ uv run {validateBriefSchemaHelper} "{run_dir}/briefs/{unit-name}/skill-brief.yaml"
73
124
  ```
74
125
 
75
- The script returns JSON `{valid, errors[], warnings[], halt_reason, brief}` — the same validator and contract `skf-brief-skill` runs at consumption time, so a brief that passes here will not be rejected there for structural reasons. Apply the result:
76
-
77
- - **`valid: false`** — the `errors[]` name the offending field (e.g. a `description` mis-indented under `scope:`, which leaves the required top-level `description` absent). Repair the assembled YAML and re-run the helper until `valid: true`. A brief is written only after it passes this gate.
78
- - **`valid: true`** — carry any non-empty `warnings[]` into the §4 preview, then proceed.
79
-
80
- This catches structural YAML errors where they are created, rather than letting them surface downstream as a HALT in `skf-brief-skill`'s ratify path.
126
+ - **The writer exits non-zero, or the validator answers `valid: false`:** the `message` and `field` of the writer's stderr JSON, or the validator's `errors[]`, name the offending field. Correct that value in `{run_dir}/brief-{unit-name}.json` when it is a value you mistyped from the recommendation card, and run both commands again; a value the user must decide is presented in §4 for correction (`M`). In headless mode a brief still rejected after one correction is a HARD HALT (exit code 4, `halt_reason: "write-failed"`, phase `generate-briefs:3`, path `{forge_data_folder}/{unit-name}/skill-brief.yaml`, with `unit_counts` from step 5): "The brief for {unit-name} was rejected: {the message}." A brief is written only after it passes this gate.
127
+ - **Both pass:** carry the writer's and the validator's non-empty `warnings` into the §4 preview, then proceed.
81
128
 
82
129
  **3b. Semantic cross-checks** (not expressible in the JSON schema — apply in addition to 3a):
83
130
 
@@ -90,7 +137,8 @@ This catches structural YAML errors where they are created, rather than letting
90
137
 
91
138
  **If any check fails:**
92
139
  - Document the failure with specific field and reason
93
- - Repair (3a structural errors) or present to user for correction (3b semantic issues) before writing — an invalid brief is not written
140
+ - Correct the context (3a) or present to user for correction (3b semantic issues) before writing: an invalid brief is not written
141
+ - In headless mode no one corrects it: correct what the recommendation card and the report settle and check again, once; a brief still failing a 3b check is a HARD HALT (exit code 4, `halt_reason: "write-failed"`, phase `generate-briefs:3`, path `{forge_data_folder}/{unit-name}/skill-brief.yaml`, with `unit_counts` from step 5), as in 3a: "The brief for {unit-name} failed the {check} check: {the reason}."
94
142
 
95
143
  ### 4. Present Generation Preview
96
144
 
@@ -100,9 +148,9 @@ This catches structural YAML errors where they are created, rather than letting
100
148
 
101
149
  {For each unit:}
102
150
  ---
103
- **{unit-name}** → `{forge_data_folder}/{unit-name}/skill-brief.yaml`
151
+ **{unit-name}** → `{forge_data_folder}/{unit-name}/skill-brief.yaml`{, replacing the earlier brief there when the unit is in `existing_briefs`}
104
152
  ```yaml
105
- {complete YAML content}
153
+ {the content of {run_dir}/briefs/{unit-name}/skill-brief.yaml, as the writer rendered it}
106
154
  ```
107
155
  ---
108
156
 
@@ -113,20 +161,29 @@ This catches structural YAML errors where they are created, rather than letting
113
161
 
114
162
  Wait for explicit user confirmation before writing files.
115
163
 
116
- **GATE [default: Y]** — If `{headless_mode}` is true: auto-confirm [Y], write all briefs, and log: "headless: auto-write {count} briefs". Do not stall at this gate — it is the deliverable-producing step of a headless/pipeline run.
164
+ **GATE [default: Y]**: if `{headless_mode}` is true, auto-confirm [Y] and write all briefs, and record that decision the moment it is taken: stage `{run_dir}/decision.json` as `{"gate": "generate-briefs.write", "default_action": "Y", "taken_action": "Y", "reason": "headless: auto-write {count} briefs", "evidence": {"briefs": [<each unit name>]}}`, then run
165
+
166
+ ```bash
167
+ uv run {emitEnvelopeHelper} record --workflow skf-analyze-source --run-dir "{run_dir}" --decision < "{run_dir}/decision.json"
168
+ ```
169
+
170
+ If the command fails, go on: only that entry is lost. Do not stall at this gate: it is the deliverable-producing step of a headless or pipeline run.
117
171
 
118
172
  ### 5. Write Files
119
173
 
120
174
  **IF user confirms (Y):**
121
175
 
122
- For each confirmed brief:
123
- 1. Create directory `{forge_data_folder}/{unit-name}/` if it does not exist
124
- 2. Write `skill-brief.yaml` to `{forge_data_folder}/{unit-name}/skill-brief.yaml` — write the exact YAML that passed the §3a schema gate verbatim; do not re-serialize, so the bytes on disk are the bytes that validated
125
- 3. Verify the file was written; if the write fails, HARD HALT with exit code 4 (`write-failed`) per `references/headless-contract.md`
176
+ Write each brief to its place from the context that passed §3 (the writer renders the same bytes the preview showed, creates the folder and writes atomically):
177
+
178
+ ```bash
179
+ uv run {writeSkillBriefHelper} write --target "{forge_data_folder}/{unit-name}/skill-brief.yaml" --from-flat < "{run_dir}/brief-{unit-name}.json"
180
+ ```
181
+
182
+ Keep each `brief_path` it prints for §9. If it exits non-zero, HARD HALT (exit code 4, `halt_reason: "write-failed"`, phase `generate-briefs:5`, path `{forge_data_folder}/{unit-name}/skill-brief.yaml`, with `unit_counts` from step 5 and the `brief_paths` written so far): "The brief for {unit-name} could not be written: {its `message`}."
126
183
 
127
184
  **IF user modifies (M):**
128
185
  - Ask which brief and what to change
129
- - Update the YAML, re-validate, present again
186
+ - Update `{run_dir}/brief-{unit-name}.json`, run the §3 gate again, present again
130
187
  - Return to confirmation prompt
131
188
 
132
189
  **IF user skips writing (N):**
@@ -134,7 +191,7 @@ For each confirmed brief:
134
191
  - Skip file writing, proceed to report update
135
192
 
136
193
  **IF user cancels (X):**
137
- - HARD HALT with exit code 6 (`user-cancelled`). Emit the error envelope on stderr with `halt_reason: "user-cancelled"`, `brief_paths: []`, and `unit_counts` reflecting the confirmed/skipped/maybe state from step 5 (shape in `references/headless-contract.md`)
194
+ - HARD HALT (exit code 6, `halt_reason: "user-cancelled"`, phase `generate-briefs:4`), with `brief_paths: []` and `unit_counts` reflecting the confirmed/skipped/maybe state from step 5 in its payload: "Cancelled before any brief was written."
138
195
 
139
196
  ### 6. Determine Next Workflow Per Unit
140
197
 
@@ -204,41 +261,50 @@ nextWorkflow: '{primary recommendation}'
204
261
 
205
262
  To refine any brief, run the recommended next workflow. To re-analyze with different scope, run analyze-source again."
206
263
 
207
- ### 9. Result Contract
208
-
209
- Write the result contract per `shared/references/output-contract-schema.md`: the per-run record at `{forge_data_folder}/analyze-source-result-{YYYYMMDD-HHmmss}.json` (UTC timestamp, resolution to seconds) and a copy at `{forge_data_folder}/analyze-source-result-latest.json` (stable path for pipeline consumers — copy, not symlink). Include all generated `skill-brief.yaml` paths in `outputs` and brief counts in `summary`. If the per-run record cannot be written, HARD HALT with exit code 4 (`write-failed`) per `references/headless-contract.md`.
210
-
211
- ### 9a. Emit Result Envelope
264
+ ### 9. End the Run
265
+
266
+ The shared emitter writes the result files and prints the envelope; this section stages their content, in every mode. Write `{run_dir}/result-context.json`:
267
+
268
+ ```json
269
+ {
270
+ "status": "success",
271
+ "report_path": "{outputFile as an absolute path}",
272
+ "brief_paths": ["{the brief_path of each brief §5 wrote}"],
273
+ "unit_counts": {"confirmed": <confirmed count from step 5>, "skipped": <rejected count from step 5>, "maybe": 0},
274
+ "mode": "interactive",
275
+ "result_contract": {
276
+ "skill": "skf-analyze-source",
277
+ "status": "success",
278
+ "outputs": [{"type": "report", "path": "{outputFile as an absolute path}"}, {"type": "brief", "path": "{each brief_path}"}],
279
+ "summary": {"mode": "interactive", "brief_count": <briefs written>, "confirmed_units": <confirmed count>, "stack_skill_candidates": <count>, "next_workflow": "{primary recommendation}"}
280
+ }
281
+ }
282
+ ```
212
283
 
213
- When `{headless_mode}` is true, emit the `SKF_ANALYZE_RESULT_JSON` envelope on **stdout** — the success signal for the interactive path, alongside §9's on-disk record (both are produced):
284
+ `brief_paths` is empty, and so is the brief part of `outputs`, when no unit was confirmed or the user skipped writing with [N]. Then run:
214
285
 
286
+ ```bash
287
+ uv run {emitEnvelopeHelper} emit --workflow skf-analyze-source --run-dir "{run_dir}" --result-dir "{forge_data_folder}" < "{run_dir}/result-context.json"
215
288
  ```
216
- SKF_ANALYZE_RESULT_JSON: {"status":"success","report_path":"{outputFile_abs_path}","brief_paths":["{brief_path_1}",…,"{brief_path_N}"],"unit_counts":{"confirmed":N,"skipped":N,"maybe":N},"exit_code":0,"halt_reason":null,"mode":"interactive"}
217
- ```
218
-
219
- - `report_path` — absolute path to {outputFile}.
220
- - `brief_paths` — every `skill-brief.yaml` written in §5 (empty array when the user skipped writing with [N]).
221
- - `unit_counts` — confirmed/skipped counts from step 5 (`maybe` reserved; see `references/headless-contract.md`).
222
289
 
223
- When `{headless_mode}` is false (interactive human run), skip this section — there is no pipeline consumer to signal.
290
+ The emitter stamps the UTC time and the run id into the record, writes `{forge_data_folder}/analyze-source-result-{YYYYMMDD-HHmmss}.json` and its `analyze-source-result-latest.json` copy (the stable path pipeline consumers read), and prints the `SKF_ANALYZE_RESULT_JSON:` line on stdout (field rules in `references/headless-contract.md`). When `{headless_mode}` is true, display the line verbatim: it is the success signal of a headless run. A result file that could not be written leaves the line's `result_path` null and a `result_file_write_failed` warning in it, and the run still finishes. If the emitter exits non-zero, correct `result-context.json` from the message on its stderr and run it once more; if it fails again, HARD HALT (exit code 4, `halt_reason: "write-failed"`, phase `generate-briefs:9`, path `{forge_data_folder}`, with `brief_paths` and `unit_counts` from the payload): "The result contract could not be written: {its message}."
224
291
 
225
292
  ### 9b. On-Complete Hook (pipeline integration)
226
293
 
227
- If `{onCompleteCommand}` is non-empty, invoke it now — after the timestamped result JSON and the `analyze-source-result-latest.json` copy have both been written:
294
+ If `{onCompleteCommand}` is non-empty and the §9 line's `result_path` is not null, invoke it now, after the emitter wrote the timestamped result JSON and its `analyze-source-result-latest.json` copy:
228
295
 
229
296
  ```
230
- {onCompleteCommand} --result-path={result_json_path}
297
+ {onCompleteCommand} --result-path={forge_data_folder}/analyze-source-result-latest.json
231
298
  ```
232
299
 
233
- Where `{result_json_path}` is the absolute path to the freshly written `analyze-source-result-latest.json` (stable path is preferred over the timestamped copy so downstream consumers don't need to discover the timestamp).
300
+ The stable `-latest` path is preferred over the timestamped copy so downstream consumers don't need to discover the timestamp.
234
301
 
235
- - On success: log to `workflow_warnings[]` as informational only if the hook emitted stderr (`on_complete hook stderr: …`); otherwise no entry.
236
- - On non-zero exit / process error: log to `workflow_warnings[]` (`on_complete hook failed (exit {code}): {stderr_snippet}`).
302
+ - On success: display the hook's stderr, if it wrote any, as information (`on_complete hook stderr: …`).
303
+ - On non-zero exit / process error: display the hook failure (`on_complete hook failed (exit {code}): {stderr_snippet}`); it never fails the run.
237
304
  - **Never fail the workflow on hook errors** — the hook is for pipeline integration (Slack, dashboards, CI), not for gating skill-brief production.
238
305
 
239
306
  If `{onCompleteCommand}` is empty, skip this section entirely (default behavior — no hook configured).
240
307
 
241
308
  ### 10. Chain to Health Check
242
309
 
243
- After the briefs are written (or skipped per user abort), the report updated, the summary presented, the result contract saved, and the on-complete hook invoked (or skipped per empty `{onCompleteCommand}`), load, read the full file, and execute `{nextStepFile}`. The health-check step is the true terminal step — continue past the summary even though it reads as final.
244
-
310
+ After the briefs are written (or skipped, or none was confirmed), the report updated, the summary presented, the run ended in §9 and the on-complete hook invoked (or skipped per empty `{onCompleteCommand}`), delete the run folder, whose payloads the emitter has read: `rm -rf "{run_dir}"`. Then load, read the full file, and execute `{nextStepFile}`. The health-check step is the true terminal step: continue past the summary even though it reads as final.
@@ -1,24 +1,51 @@
1
1
  # Headless Result Contract & Exit Codes
2
2
 
3
- Canonical headless/pipeline contract for skf-analyze-source. Step files emit the envelope and exit with the codes defined here.
3
+ Canonical headless/pipeline contract for skf-analyze-source. The shared emitter, `shared/scripts/skf-emit-result-envelope.py` (`{emitEnvelopeHelper}`, bound at SKILL.md On Activation §1), builds every line from the payload a step stages in `{run_dir}` and checks it against `shared/scripts/schemas/skf-analyze-result-envelope.v1.json`, so no step types an envelope.
4
4
 
5
5
  ## Result Envelope
6
6
 
7
- When `{headless_mode}` is true, step 6 (interactive) or step 1a (auto) emits a single-line JSON envelope on **stdout** before chaining to step 7. Every HARD HALT emits the same envelope shape on **stderr** with `status: "error"`, using the exit code and `halt_reason` named at that HALT — so an automator branches on the failure class without grepping message text.
7
+ The step that ends a run (step 6 §9, step 1a §9, or the docs-only branch §5) prints the envelope on **stdout** before chaining to step 7, and displays it when `{headless_mode}` is true. Every HARD HALT of a headless run prints it on **stderr** with `status: "error"`, so an automator branches on the failure class without grepping message text.
8
8
 
9
9
  ```
10
- SKF_ANALYZE_RESULT_JSON: {"status":"success|error|redirect|skipped","report_path":"…|null","brief_paths":["…"],"unit_counts":{"confirmed":N,"skipped":N,"maybe":N},"exit_code":0,"halt_reason":null,"mode":"interactive|auto"}
10
+ SKF_ANALYZE_RESULT_JSON: {"status":"success|error|redirect|skipped","report_path":"…|null","brief_paths":["…"],"unit_counts":{"confirmed":N,"skipped":N,"maybe":N},"exit_code":0,"halt_reason":null,"mode":"interactive|auto","result_path":"…|null"}
11
11
  ```
12
12
 
13
- - `status` — `"success"` on the terminal happy path, `"error"` on any HALT, `"redirect"` when coexistence routes to US (merge), `"skipped"` when the user skips a conflicting target.
14
- - `halt_reason` — one of `null` (success), `"input-missing"`, `"resolution-failure"`, `"pin-invalid"`, `"write-failed"`, `"user-cancelled"`.
15
- - `exit_code` — matches the table below.
16
- - `report_path` — absolute path to the analysis report, or `null` on an early HALT.
17
- - `brief_paths` — array of absolute paths to every generated `skill-brief.yaml` (empty array if none).
13
+ - `status`: `"success"` when the run ends, also with zero confirmed units (`brief_paths: []`, `unit_counts.confirmed: 0`); `"error"` on any HALT; `"redirect"` when coexistence routes to US (merge); `"skipped"` when the user skips a conflicting target.
14
+ - `halt_reason`: `null` unless the run halted, else one of `"input-missing"`, `"resolution-failure"`, `"pin-invalid"`, `"write-failed"`, `"user-cancelled"`. A brief the writer or the brief schema gate rejects halts with `"write-failed"`.
15
+ - `exit_code`: the emitter derives it from `halt_reason`, per the table below.
16
+ - `report_path`: absolute path to the analysis report, or `null` on a redirect, a skip and an early HALT.
17
+ - `brief_paths`: absolute path of every `skill-brief.yaml` the run wrote (empty array if none). A brief is written only after it passed the brief writer and, outside the docs-only branch, the schema gate.
18
18
  - `unit_counts` — `confirmed` (units approved for briefs) and `skipped` (rejected in step 5, or the skipped target in coexistence §0c) counts; auto mode reports `confirmed:N, skipped:0`. `maybe` is a reserved slot, currently always `0`.
19
- - `mode` — `"auto"` when the `[auto]` flag was active, `"interactive"` otherwise.
19
+ - `mode`: `"auto"` when the invocation carries `[auto]`, from activation through step 1a and the docs-only branch; `"interactive"` otherwise, also in the step-by-step chain an `[auto]` run falls back to (step 1a §3, exit 1).
20
+ - `result_path`: the per-run result file the emitter wrote, stamped by it; `null` for a HALT, which writes no result file, and when the write failed (a `result_file_write_failed` warning then says why).
21
+ - `error`: on a HALT only, `{"phase", "reason"}` plus `path` when the halt names one.
22
+ - `headless_decisions`: present when the run recorded an auto-decision: step 1a's §3b merge-or-split decision (gate `auto-scope.cohesion`), its §4 choices of shape for a repository on a framework or a parser library (gate `auto-scope.shape`) and its §5 choice of the documented language (gate `auto-scope.language`), and each gate default a headless run of the step-by-step chain took: `scan-project.scan`, `identify-units.classifications`, `map-and-detect.findings` (with the composite merges it accepted), `recommend.recommendations` and `generate-briefs.write`.
23
+ - `warnings`: present when the run recorded at least one.
20
24
 
21
- In auto mode the envelope also carries `coexistence` (the §0c decision) and, when a pin resolves, `pinned_ref`/`pinned_version` — `step-auto-scope.md` §0b/§0c define those field semantics. The docs-only path adds `source_type: "docs-only"`.
25
+ In auto mode the envelope also carries `coexistence` (the §0c decision) and, when a pin resolves, `pinned_ref`/`pinned_version`; `step-auto-scope.md` §0b/§0c define those field semantics. A redirect adds `redirect_to`, `skill_name` and `skill_path`, a skip `skipped_reason`, and the docs-only path `source_type: "docs-only"`.
26
+
27
+ ## Ending a Run
28
+
29
+ The step that ends the run stages `{run_dir}/result-context.json` with the envelope fields it knows and a `result_contract` object, the record the result files hold (`skill`, `status`, `outputs`, `summary`, per `shared/references/output-contract-schema.md`), and runs the emitter in every mode:
30
+
31
+ ```bash
32
+ uv run {emitEnvelopeHelper} emit --workflow skf-analyze-source --run-dir "{run_dir}" --result-dir "{forge_data_folder}" < "{run_dir}/result-context.json"
33
+ ```
34
+
35
+ The emitter stamps the UTC time, the run id, the decisions and warnings the run recorded into the record, writes `{forge_data_folder}/analyze-source-result-{YYYYMMDD-HHmmss}.json` and its `analyze-source-result-latest.json` copy, and prints the line. A result file that could not be written leaves `result_path` null and a `result_file_write_failed` warning in the line, and the run still finishes. If the emitter exits non-zero, the step corrects the payload from the message on its stderr and runs it once more; if it fails again, it HARD HALTs with exit code 4 (`write-failed`). Then `{onCompleteCommand}` runs, when it is set and `result_path` is not null, with `--result-path={forge_data_folder}/analyze-source-result-latest.json`; a hook failure is displayed and never fails the run. Last, the step deletes `{run_dir}` and chains to step 7.
36
+
37
+ ## Halt Envelope
38
+
39
+ Every HARD HALT names its exit code, `halt_reason` and phase where it stops. In headless mode it prints its envelope before it stops: it stages `{run_dir}/halt.json` as `{"phase": "<phase>", "reason": "<the halt message>", "halt_reason": "<halt_reason>", "mode": "<auto or interactive>"}`, plus `"path"` when the halt names one, runs the first command below and displays the line it prints verbatim. A halt before SKILL.md On Activation §5 created `{run_dir}` hands that payload, on one line, to the second command. Write the payload as valid JSON: in the halt message and `path`, replace each backslash with / and each double quote with a backtick. The emitter gives every field the payload leaves out its default (`null`, `[]`, zero counts, `"interactive"`) and derives `exit_code` from `halt_reason`. When the helper is missing, exits non-zero or prints no line, display the halt message alone. An interactive HALT displays its message and emits nothing. A halt writes no result file and keeps `{run_dir}`.
40
+
41
+ ```bash
42
+ uv run {emitEnvelopeHelper} emit-halt --workflow skf-analyze-source --run-dir "{run_dir}" --target stderr < "{run_dir}/halt.json"
43
+ uv run {emitEnvelopeHelper} emit-halt --workflow skf-analyze-source --target stderr <<'SKF_ANALYZE_HALT'
44
+ {"phase": "on-activation:config", "reason": "<the halt message>", "halt_reason": "input-missing", "mode": "interactive"}
45
+ SKF_ANALYZE_HALT
46
+ ```
47
+
48
+ Each step file states this rule in its own opening, so the HALTs of a step never depend on this file.
22
49
 
23
50
  ## Exit Codes
24
51
 
@@ -26,8 +53,8 @@ Every HARD HALT exits with a stable code so headless automators can branch on th
26
53
 
27
54
  | Code | Meaning | Raised by |
28
55
  | ---- | -------------------- | ------------------------------------------------------------------------------------------ |
29
- | 0 | success / skipped / redirect | step 7 (terminal — health check completion); coexistence `"skipped"`/`"redirect"` statuses from §0c |
30
- | 2 | input-missing | On Activation (config.yaml not loadable); step 1 §3 (project path empty/invalid in headless mode); step 1 §2b (auto mode without `--project-path`) |
31
- | 3 | resolution-failure | step 1 §2 (`forge-tier.yaml` missing at `{sidecar_path}/forge-tier.yaml`); step 1 §3 (project path does not exist or remote URL inaccessible); step 1a §0a (docs-only URL unreachable); step 1a §0b (`halt_reason: "pin-invalid"` when the supplied `--pin` matches no tag or branch); step 1a §3 (shape detection script error, exit code 2) |
32
- | 4 | write-failed | a failed write of the analysis report (step 1 §6 / step 1a §7 / §0a), a `skill-brief.yaml` (step 6 §5 / step 1a §8 / §0a), or the result contract (step 6 §9 / step 1a §10 / §0a) |
33
- | 6 | user-cancelled | any interactive menu in steps 2/3/5/6 (user selected `[X]` Cancel and exit) |
56
+ | 0 | success / skipped / redirect | the step that ends the run: step 6 §9 (briefs written, or none when no unit was confirmed), step 1a §9, docs-only §5; coexistence `"skipped"`/`"redirect"` statuses from §0c |
57
+ | 2 | input-missing | On Activation §2 (config.yaml not loadable); step 1 §2b (auto mode without `--project-path`); step 1 §3 (no project path in headless mode); step 1 §4 (`--target-refs` given with `--target-ref`, or a `--target-refs` key that matches no project path) |
58
+ | 3 | resolution-failure | step 1 §2 (`forge-tier.yaml` missing at `{sidecar_path}/forge-tier.yaml`); step 1 §2b and §4 (project path does not exist or remote URL inaccessible, headless); step 1a §0 (a documentation URL that git reads as a repository, which on most hosts is the repository's main page, one whose server asks for credentials, or one that gives git no answer in 20 s: rerun with its `.git` clone URL, its address without https:// or its SSH address, or a documentation URL that answers; a repository browser page git cannot read at that address, such as a Bitbucket Data Center `/projects/<p>/repos/<r>` page, a SourceForge or Launchpad code page or a link to a file or folder inside a repository, is still read as documentation, so give its clone URL); step 1a §0a (docs-only URL unreachable); step 1a §0b (`halt_reason: "pin-invalid"` when the supplied `--pin` matches no tag or branch, `resolution-failure` when the pin helper fails); step 1a §2 (a remote path cannot be fetched, another path halts as in §0, or the target's files cannot be listed); step 1a §3 (shape detection script error, exit code 2); step 2 §2 (a project path cannot be fetched at its ref); step 3 §1 and step 4 §1 (a scan root a resumed session makes again cannot be fetched); a shared helper script found at none of its probe paths (On Activation §1; step 1 §5; step 1a §0, §0b, §2, §3, §5 and §8, and its split branch; docs-only §2 and §4; step 2 §2; step 3 §2 and §4; step 4 §2, §3 and §5, and the [D] discover file of steps 4 and 5; step 6 §2) |
59
+ | 4 | write-failed | On Activation §5 (the run folder cannot be created); step 1 §1 (an earlier report cannot be archived); a failed write of the analysis report (step 1 §6 / step 1a §7 / docs-only §3); a brief the writer or the schema gate rejects, or a brief write that fails (step 6 §3 and §5 / step 1a §8 / docs-only §4), and a brief that still fails a semantic check of step 6 §3 in headless mode; the emitter failing twice when the run ends (step 6 §9 / step 1a §9 / docs-only §5) |
60
+ | 6 | user-cancelled | any interactive menu in steps 2/3/4/5/6 (user selected `[X]` Cancel and exit) |