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
@@ -8,16 +8,16 @@ Rules for cross-referencing API surfaces between two skills to determine integra
8
8
 
9
9
  ## Verdict Definitions
10
10
 
11
- Token set is defined canonically in the SKF shared feasibility report schema (`_bmad/skf/shared/references/feasibility-report-schema.md` in installed mode; `src/shared/references/feasibility-report-schema.md` in a dev checkout) — the table below restates the same set with this skill's evidence obligations. Tokens are case-sensitive (`Verified`, `Plausible`, `Risky`, `Blocked`); emitting any other token is a schema violation.
11
+ Token set is defined canonically in the SKF shared feasibility report schema (`{project-root}/_bmad/skf/shared/references/feasibility-report-schema.md` in installed mode; `{project-root}/src/shared/references/feasibility-report-schema.md` in a dev checkout); the table below restates the same set with this skill's evidence obligations. Tokens are case-sensitive (`Verified`, `Plausible`, `Risky`, `Blocked`); emitting any other token is a schema violation.
12
12
 
13
- | Verdict | Meaning | Required Evidence |
14
- |---------------|------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
15
- | **Verified** | APIs demonstrably connect and docs cross-reference each other | Check 1 (language) passes with declared evidence; Check 3 (types) passes from cited `exports` signatures; **Check 4 (docs cross-reference) passes with a literal substring/name citation** — without Check 4 evidence, cap at `Plausible`. Check 2 is best-effort only and cannot by itself promote to `Verified`. |
16
- | **Plausible** | Checks pass but rely on inferred or indirect evidence | Language + type checks pass; Check 2 uses inferred `protocols_inferred`/`data_formats_inferred` (prose scan); Check 4 is weak or missing (no literal cross-reference). This is the mandatory cap whenever Check 4 does not surface a literal citation. |
17
- | **Risky** | Type mismatch, protocol gap, or language boundary requiring a bridge | A clear gap exists (e.g., TypeScript↔Rust FFI needed) but a workaround is architecturally feasible — cite a named workaround in the recommendation |
18
- | **Blocked** | Fundamental incompatibility — no feasible integration path even with a bridge or adapter layer | The two libraries cannot exchange data in any documented way; requires replacing one of the libraries |
13
+ | Verdict | Meaning | Required Evidence |
14
+ |---|---|---|
15
+ | **Verified** | APIs demonstrably connect and at least one skill cites the other | Check 1 (language) passes with declared evidence; Check 2 (protocol) flags no risk; Check 3 (types) passes from cited `exports` signatures; **Check 4 (docs cross-reference) passes with a literal substring/name citation** |
16
+ | **Plausible** | The checks pass, but neither skill cites the other | Checks 1 to 3 pass as for `Verified`; Check 4 finds no literal citation, so the Plausible cap below applies |
17
+ | **Risky** | Type mismatch, protocol gap, or language boundary requiring a bridge | A clear gap exists (e.g., TypeScript↔Rust FFI needed) but a workaround is architecturally feasible: cite a named workaround in the recommendation |
18
+ | **Blocked** | Fundamental incompatibility: no feasible integration path even with a bridge or adapter layer | The two libraries cannot exchange data in any documented way; requires replacing one of the libraries |
19
19
 
20
- **Promotion rule:** `Verified` requires Check 4 evidence. If Checks 1 and 3 pass but Check 4 fails (no literal substring/name citation from either skill's SKILL.md), the verdict is capped at `Plausible`. This rule is enforced by step 3 §4 and is the producer obligation declared in the shared schema.
20
+ **Plausible cap:** when Check 4 finds no literal citation in either direction, cap the pair at `Plausible`: it can be `Plausible`, `Risky` or `Blocked`, never `Verified`. This is the only cap. Check 2 reads protocol and data-format tokens inferred from each skill's prose, so it can flag a risk, but it never promotes a pair to `Verified` and never caps one at `Plausible`. A pair whose Checks 1 to 3 pass and whose Check 4 finds a literal citation is `Verified`. This is the producer obligation the shared schema declares.
21
21
 
22
22
  ---
23
23
 
@@ -32,6 +32,7 @@ For each integration pair (Library A ↔ Library B):
32
32
 
33
33
  ### 2. Protocol Compatibility Check
34
34
 
35
+ - Input: each skill's `protocols_inferred` and `data_formats_inferred` tokens, inferred from its SKILL.md prose. Conflicting transports or formats with no adapter in the stack flag a risk. A shared or complementary token (e.g. "HTTP client" and "HTTP server"), or no token on either side, flags none: the tokens are too weak to prove compatibility, and a library pair that names no transport usually calls in-process.
35
36
  - Matching transports are compatible modulo format alignment: both in-process → direct calls; both HTTP/REST → compatible if endpoints match; both WebSocket → check message-format compatibility; both shared-filesystem → async, check format.
36
37
  - The load-bearing nudge: **two embedded databases may conflict on lock files — check for multi-writer support** before treating them as compatible.
37
38
 
@@ -43,11 +44,9 @@ For each integration pair (Library A ↔ Library B):
43
44
 
44
45
  ### 4. Documentation Cross-Reference (required for `Verified`)
45
46
 
46
- - Search Skill A's SKILL.md for a literal substring/name citation of Library B
47
- - Search Skill B's SKILL.md for the reciprocal citation
48
- - Accept literal names or aliases declared in that skill's metadata; a paraphrase or fuzzy match does not satisfy Check 4
49
- - A pass requires at least one literal citation in at least one direction; record the exact substring and location in the evidence block
50
- - If neither skill literally cites the other, Check 4 fails and the per-pair verdict caps at `Plausible` (not `Verified`)
47
+ - Search Skill A's SKILL.md for a literal substring/name citation of Library B, and Skill B's SKILL.md for the reciprocal citation. The shared SKILL.md scanner runs that search (`skf-scan-skill-md-structure.py cross-reference`, integrations.md §4): a citation is a hit it lists, never a line read from a SKILL.md
48
+ - A hit that only matches a common word does not count (`the next step` for a skill named `next`): quote the first hit whose excerpt names the library, and a direction whose hits name only the common word has no citation
49
+ - A pass requires at least one literal citation in at least one direction; record the exact substring and its line in the evidence block. A fail brings the Plausible cap above into play.
51
50
 
52
51
  ---
53
52
 
@@ -1,18 +1,32 @@
1
1
  ---
2
2
  nextStepFile: 'requirements.md'
3
- integrationRulesData: '{integrationRulesPath}'
4
- coveragePatternsData: '{coveragePatternsPath}'
3
+ integrationRulesData: 'references/integration-verification-rules.md'
4
+ coverageTallyScript: 'scripts/skf-coverage-tally.py'
5
5
  feasibilitySchemaProbeOrder:
6
6
  - '{project-root}/_bmad/skf/shared/references/feasibility-report-schema.md'
7
7
  - '{project-root}/src/shared/references/feasibility-report-schema.md'
8
8
  atomicWriteProbeOrder:
9
9
  - '{project-root}/_bmad/skf/shared/scripts/skf-atomic-write.py'
10
10
  - '{project-root}/src/shared/scripts/skf-atomic-write.py'
11
+ # §3 re-enumerates the skills against step 1's inventory (--expect-hashes)
12
+ # to find a skill that changed mid-run.
13
+ enumerateStackSkillsProbeOrder:
14
+ - '{project-root}/_bmad/skf/shared/scripts/skf-enumerate-stack-skills.py'
15
+ - '{project-root}/src/shared/scripts/skf-enumerate-stack-skills.py'
16
+ # §4 lists the literal citations between the paired skills' SKILL.md
17
+ # (Check 4 evidence and the cycle edges) with its cross-reference mode.
18
+ scanSkillMdStructureProbeOrder:
19
+ - '{project-root}/_bmad/skf/shared/scripts/skf-scan-skill-md-structure.py'
20
+ - '{project-root}/src/shared/scripts/skf-scan-skill-md-structure.py'
11
21
  cycleFinderProbeOrder:
12
22
  - '{project-root}/_bmad/skf/shared/scripts/skf-find-cycles.py'
13
23
  - '{project-root}/src/shared/scripts/skf-find-cycles.py'
14
24
  outputFile: '{outputFolderPath}/feasibility-report-{project_slug}-{timestamp}.md'
15
- outputFileLatest: '{outputFolderPath}/feasibility-report-{project_slug}-latest.md'
25
+ emitEnvelopeProbeOrder:
26
+ - '{project-root}/_bmad/skf/shared/scripts/skf-emit-result-envelope.py'
27
+ - '{project-root}/src/shared/scripts/skf-emit-result-envelope.py'
28
+ inventoryFile: '{run_dir}/skill-inventory.json'
29
+ docMentionsFile: '{run_dir}/doc-mentions.json'
16
30
  ---
17
31
 
18
32
  <!-- Config: communicate in {communication_language}. Append the Integration Verdicts section to the report in {document_output_language}. -->
@@ -26,12 +40,20 @@ Cross-reference API surfaces between library pairs that the architecture documen
26
40
  ## Rules
27
41
 
28
42
  - Focus only on integration pair verification using skill API surfaces
29
- - Do not evaluate requirements coverage (Step 04) or parse Mermaid diagrams
43
+ - Do not evaluate requirements coverage (Step 04) or read the architecture document again: step 2's mentions run holds its candidate pairs
30
44
  - Every verdict must include evidence citations from the skills
31
45
 
32
46
  ## MANDATORY SEQUENCE
33
47
 
34
- **Resolve `{feasibilitySchemaRef}`** from `{feasibilitySchemaProbeOrder}`; first existing path wins (installed SKF module path first, dev-checkout `src/` fallback) — used by the verdict-cap references and the append step below.
48
+ **Halt envelope.** Every HALT in this step names its exit code, `halt_reason` and phase. In headless mode, stage `{run_dir}/halt.json` as `{"phase": "<phase>", "reason": "<the halt message>", "halt_reason": "<halt_reason>", "report_path": "{outputFile}"}`, adding `"path"` when the halt names one, resolve `{emitEnvelopeHelper}` from `{emitEnvelopeProbeOrder}` if it is not bound (first existing path wins), then run:
49
+
50
+ ```bash
51
+ uv run {emitEnvelopeHelper} emit-halt --workflow skf-verify-stack --run-dir "{run_dir}" --target stderr < "{run_dir}/halt.json"
52
+ ```
53
+
54
+ Display the line it prints, then stop with the halt's exit code (`references/exit-codes.md` describes the envelope). If no candidate exists, or the emitter exits non-zero or prints no line, display the halt message alone. An interactive HALT displays its message and emits nothing.
55
+
56
+ **Resolve `{feasibilitySchemaRef}`** from `{feasibilitySchemaProbeOrder}`; first existing path wins (installed SKF module path first, dev-checkout `src/` fallback). The append step below uses it.
35
57
 
36
58
  ### 1. Load Integration Verification Rules
37
59
 
@@ -41,32 +63,24 @@ Extract: verification checks (language boundary, protocol compatibility, type co
41
63
 
42
64
  ### 2. Extract Integration Claims
43
65
 
44
- **Source preference:** If a stack skill assembled by `skf-create-stack-skill` is present in the inventory and its manifest (`bmad-skill-manifest.yaml` or its `metadata.json`) declares `integration_patterns`, use THAT as the primary source of integration claims. Record `source: stack manifest` on each resulting pair. Fall back to prose co-mention (below) only when no such manifest is available, and record `source: prose co-mention` on those pairs.
45
-
46
- Parse the architecture document for statements describing two or more technologies working together.
47
-
48
- **Detection method — prose-based co-mention analysis (fallback only):**
49
- - Identify sentences or paragraphs where two or more technology names appear together
50
- - Look for integration verbs: "connects to", "communicates with", "wraps", "extends", "consumes", "produces", "bridges", "integrates with", "sits between"
51
- - Look for data flow descriptions: "{A} sends data to {B}", "{A} results are consumed by {B}"
52
- - Look for layer boundary descriptions: "{A} at the API layer connects to {B} at the data layer"
53
-
54
- **Mermaid Diagram Handling:** See `{coveragePatternsData}` → "Mermaid Diagram Handling" for the canonical rule (single source of truth). Summary: do not parse Mermaid diagram syntax for co-mention detection; use only prose text.
66
+ **Prose co-mention:** step 2's mentions run already found the candidate pairs. Take each entry of `candidates[]` in `{docMentionsFile}` whose two skills (`a` and `b`) are both Covered in Step 02, and judge it from its `evidence[]` (`unit_excerpt`, with its `header` and `unit_line`): it is an integration claim when an entry describes an *integration relationship* (data flowing between the two, one wrapping, bridging, extending or consuming the other, or a layer boundary connecting them), not mere co-mention in the same text. A pair outside `candidates[]` is not claimed: no paragraph names both, the document only lists them together, or it draws them only in fenced code, such as a Mermaid diagram, which the mentions helper never reads.
55
67
 
56
68
  **Build integration pairs list:**
57
69
  - Each pair: `{library_a, library_b, architectural_context}`
58
- - `architectural_context`: the quoted text or paraphrased description of their relationship
70
+ - `architectural_context`: the quoted `unit_excerpt` of the evidence entry that shows the relationship
59
71
 
60
- **Filter:** Only include pairs where BOTH libraries have a corresponding skill (Covered in Step 02). Skip pairs involving Missing skills — they cannot be verified.
72
+ **Filter:** Only include pairs where BOTH libraries have a corresponding skill (Covered in Step 02). Skip pairs involving Missing skills: they cannot be verified. Drop a pair whose two technologies step 2 matched to the same skill: it is one library, with no integration to verify, and §5 lists it.
73
+
74
+ **Stage the pairs** for the §4 citation scan: write `{run_dir}/integration-pairs.json` as `{"pairs": [["<skill_a>", "<skill_b>"], ...]}`, naming each pair once by the two skills step 2 matched its technologies to (the Skill Match column), as `{inventoryFile}` names them. With no pair, write `{"pairs": []}`.
61
75
 
62
76
  ### 3. Load Skill API Surfaces
63
77
 
64
78
  <!-- Subagent delegation: read SKILL.md files in parallel, return compact JSON -->
65
79
 
66
- For each library in an integration pair, delegate SKILL.md reading to a parallel subagent. Launch up to **8 subagents concurrently** (batch if needed — same 8-way cap as step 1 §2; keeps aggregate token window manageable while still parallelizing typical stack sizes). Each subagent receives one skill's SKILL.md path and:
80
+ For every skill step 2 matched to a Covered technology (the Skill Match column), in an integration pair or not, delegate SKILL.md reading to a parallel subagent: step 4 maps requirements from these summaries, so no later stage reads a SKILL.md in this context. Launch up to **8 subagents concurrently**, in batches of 8 when more skills need reading (the cap keeps the aggregate token window manageable while still parallelizing typical stack sizes). Each subagent receives one skill's SKILL.md path and:
67
81
  1. Reads the SKILL.md file
68
- 2. Extracts the API surface
69
- 3. Returns only this compact JSON — no prose, no extra commentary:
82
+ 2. Extracts the API surface and what the library can do
83
+ 3. Returns only this compact JSON, with no prose and no extra commentary:
70
84
 
71
85
  ```json
72
86
  {
@@ -74,72 +88,97 @@ For each library in an integration pair, delegate SKILL.md reading to a parallel
74
88
  "language": "...",
75
89
  "exports": ["functionName(params): ReturnType", "..."],
76
90
  "protocols_inferred": ["HTTP", "gRPC", "WebSocket", "message queue", "file I/O", "IPC"],
77
- "data_formats_inferred": ["JSON", "protobuf", "CSV", "binary", "streaming"]
91
+ "data_formats_inferred": ["JSON", "protobuf", "CSV", "binary", "streaming"],
92
+ "capabilities": ["offline-first sync", "server-side rendering", "..."]
78
93
  }
79
94
  ```
80
95
 
81
96
  **Extraction rules for subagents:**
82
97
  - `skill_name`, `language`: mirror the skill's metadata fields
83
98
  - `exports`: exported functions with signatures, exported types/interfaces/classes (extracted from SKILL.md prose)
84
- - `protocols_inferred`: best-effort prose scan — protocol tokens mentioned in SKILL.md descriptions/examples; not a declared field in `metadata.json`
85
- - `data_formats_inferred`: best-effort prose scan — format tokens mentioned in SKILL.md descriptions/examples; not a declared field in `metadata.json`
99
+ - `protocols_inferred`, `data_formats_inferred`: protocol and format tokens mentioned in the SKILL.md descriptions and examples
100
+ - `capabilities`: up to 10 short phrases naming what the library does, from the SKILL.md description and its sections (the requirements stage matches each requirement against them)
86
101
  - If a field has no matches, return an empty array `[]`
87
102
 
88
- **These fields are inferred, not declared.** `protocols` and `data_formats` do not exist in any skill's `metadata.json` — treat them as weak evidence from prose scanning only. When either list is used to justify compatibility in Check 2, cap the per-pair verdict at `Plausible` (see the schema's producer obligations — `{feasibilitySchemaRef}`).
103
+ **When subagents are unavailable**, read the SKILL.md files yourself, one at a time and in the same order: for each skill, read its SKILL.md, write its compact JSON by the rules above and append it to `{run_dir}/skill-summaries.json` at once, then go on to the next. The 20% budget below counts subagent replies only.
104
+
105
+ **These two lists are inferred from prose, not declared** (no skill's `metadata.json` has `protocols` or `data_formats`), so they are weak evidence: Check 2 reads them as `{integrationRulesData}` says.
106
+
107
+ **Schema validation (parent):** Each subagent response must contain the required keys (`skill_name`, `language`, `exports`, `capabilities`). Reject responses missing required keys and exclude that skill from pair evaluation and from the requirements stage; if more than **20%** of subagent calls return malformed JSON, HALT (exit code 7, `halt_reason: "inventory-unreliable"`) at phase `integrations:api-surfaces` with "API-surface extraction unreliable: more than 20% of subagent reads returned malformed JSON. Re-run [VS] after skills stabilize."
89
108
 
90
- **Schema validation (parent):** Each subagent response must contain the required keys (`skill_name`, `language`, `exports`). Reject responses missing required keys and exclude that skill from pair evaluation; if more than **20%** (same failure-budget threshold as step 1 §2; see the justification there) of subagent calls return malformed JSON, HALT (exit code 7, `halt_reason: "inventory-unreliable"`) with "API-surface extraction unreliable — more than 20% of subagent reads returned malformed JSON. Re-run [VS] after skills stabilize." In headless, emit the error envelope.
109
+ **Parent collects all JSON summaries.** Apart from the one-at-a-time reads of the sequential fallback, never load a full SKILL.md into the parent context. Append the accepted summaries of each batch to `{run_dir}/skill-summaries.json`, one JSON array, as the batch returns: the requirements stage reads them from there, so they survive context compaction.
91
110
 
92
- **Parent collects all subagent JSON summaries.** Do not load full SKILL.md content into parent context.
111
+ **From `skill_inventory` (step 1 §2), also take** each skill's `language` (a string, or a list for a stack; it is authoritative and overrides the subagent's `language` when the two disagree), `exports` (empty for a stack skill) and `exports_documented` (the export count), reading them from `{inventoryFile}`. The enumerate helper read them from `metadata.json`, so the parent never opens it.
112
+
113
+ **Mid-run change check.** Resolve `{enumerateStackSkillsHelper}` from `{enumerateStackSkillsProbeOrder}`; first existing path wins. Re-enumerate against the inventory step 1 wrote, which compares each skill's `metadata_hash` with the one recorded then:
114
+
115
+ ```bash
116
+ uv run {enumerateStackSkillsHelper} enumerate {skills_output_folder} --expect-hashes "{inventoryFile}" > "{run_dir}/inventory-recheck.json"
117
+ ```
93
118
 
94
- **From metadata.json (read in parent — lightweight), also extract:**
95
- - `language` — primary programming language (authoritative — overrides subagent `language` if they disagree)
96
- - `exports` — export names array (populated for individual skills; empty for stack skills)
97
- - `stats.exports_documented` — export count
98
- - `confidence_tier` — extraction confidence level
119
+ If no candidate exists, or the command exits non-zero, HALT (exit code 3, `halt_reason: "resolution-failure"`) at phase `integrations:change-check`. Read only its `changed_skills` and `missing_skills`: a pair involving one of those skills is not rated. Its row in every table and in `verdict-rows.json` (§4) carries the verdict `Risky` and the rationale "skill modified mid-run: re-run [VS]", and each such skill is recorded once in the run sink:
99
120
 
100
- **mtime re-verification:** Re-stat each `metadata.json` and compare against the mtime captured in step 1. If any mtime moved during the run, abort any pair involving that skill with rationale "skill modified mid-run — re-run [VS]".
121
+ ```bash
122
+ uv run {emitEnvelopeHelper} record --run-dir "{run_dir}" --warning 'skill_modified_mid_run: <skill>'
123
+ ```
101
124
 
102
- Store collected API surface summaries for cross-referencing.
125
+ The recheck's `new_skills` appeared after step 1 and are not part of this run.
103
126
 
104
127
  ### 4. Cross-Reference Each Integration Pair
105
128
 
106
- For each integration pair `{library_a, library_b}`, run the four-check protocol and assign the per-pair verdict per `{integrationRulesData}` (loaded in §1): the Cross-Reference Protocol defines Check 1 (language boundary), Check 2 (protocol compatibility), Check 3 (type compatibility), and Check 4 (documentation cross-reference, required for `Verified`); the Verdict Definitions table and promotion rule define the `Verified` / `Plausible` / `Risky` / `Blocked` thresholds and the cap-at-`Plausible` rule that applies whenever Check 4 surfaces no literal citation. Do not restate those mechanics here.
129
+ For each integration pair `{library_a, library_b}`, run the four-check protocol and assign the per-pair verdict per `{integrationRulesData}` (loaded in §1): its Cross-Reference Protocol defines Checks 1 to 4, and its Verdict Definitions define the four verdicts and the Plausible cap. Apply them as written there. Check 2 reads the `protocols_inferred` / `data_formats_inferred` lists from §3.
130
+
131
+ **Run the citation scan once**, before rating the first pair. Resolve `{scanSkillMdStructureHelper}` from `{scanSkillMdStructureProbeOrder}`; first existing path wins. Then run:
132
+
133
+ ```bash
134
+ uv run {scanSkillMdStructureHelper} cross-reference --skills "{inventoryFile}" --skills-root "{skills_output_folder}" --pairs "{run_dir}/integration-pairs.json" > "{run_dir}/citations.json"
135
+ ```
107
136
 
108
- **Step-specific input for Check 2:** Check 2 draws only on the `protocols_inferred` / `data_formats_inferred` lists surfaced by the §3 subagent prose scan. A shared or complementary token (e.g., "HTTP client" ↔ "HTTP server") reads as inferred compatibility; no token on either side, or conflicting tokens with no adapter, flags a risk. Any pair whose compatibility rests on this inferred evidence caps at `Plausible` per §3.
137
+ If no candidate exists, or the command exits non-zero, HALT (exit code 3, `halt_reason: "resolution-failure"`) at phase `integrations:citations`, naming its first stderr line. Check 4 reads each citing direction of `citations[]` in `{run_dir}/citations.json`: `from`, `to` and its `hits[]`, each with its `line`, the `substring` as written and an `excerpt`. Its `warnings[]` name a SKILL.md the scanner could not read, whose skill then cites nothing.
109
138
 
110
139
  **Each verdict includes:**
111
140
  - Which checks passed and which flagged
112
141
  - Evidence citations: specific exports, types, or literal substrings from the skills
113
- - `source: stack manifest` or `source: prose co-mention` tag (per section 2)
114
- - For `Verified`: the exact Check 4 literal citation (e.g., `"see also: {lib_b}"` quoted from Skill A's SKILL.md, line N)
115
- - **Tier annotation:** For each contributing skill, append `(evidence from Tier {n} skill)` citing that skill's `confidence_tier` (e.g., `(evidence from Tier 1 skill)`). This lets reviewers weigh evidence strength by extraction confidence.
142
+ - For `Verified`: the Check 4 citation from `{run_dir}/citations.json`, its `substring` and `line` in the citing skill's SKILL.md with the hit's `excerpt` (e.g., `"react-query"` at line 42 of `next`'s SKILL.md)
143
+ - **Tier annotation:** For each contributing skill, append `(evidence from a {evidence_tier} skill)` with that skill's `evidence_tier` from `skill_inventory` (e.g., `(evidence from a T1 skill)`), so reviewers weigh the evidence by the tier its skill rests on.
116
144
 
117
- **Cycle detection (after all pairs evaluated):** Deciding the edge set is a Check-4 judgment and stays here; the traversal is deterministic and is delegated to the shared helper (the in-prose DFS misses real multi-hop cycles or invents spurious ones as the pair count grows).
145
+ **Cycle detection (after all pairs evaluated):** an edge `A → B` exists when skill A literally cites skill B (Check 4). Two skills that cite each other are not a cycle: their mutual citation is Check 4 evidence for their own pair, and a loop built only from such pairs is no cycle either. The traversal is deterministic and is delegated to the shared helper (the in-prose DFS misses real multi-hop cycles or invents spurious ones as the pair count grows).
118
146
 
119
- 1. **Build the directed pair graph in the prompt:** an edge `A → B` exists when skill A literally cites skill B via Check 4. Serialize the edges as JSON: `{"edges": [["A", "B"], ["B", "C"], ...]}` (each `[from, to]` pair is one Check-4 citation direction).
120
- 2. **Resolve `{cycleFinderHelper}`** from `{cycleFinderProbeOrder}`; first existing path wins. Enumerate cycles deterministically (run `uv run {cycleFinderHelper} find --help` for the contract):
147
+ 1. **Record the rejected directions:** write `{run_dir}/rejected-edges.json` as `{"edges": [["<from>", "<to>"], ...]}`, one entry per citing direction of `{run_dir}/citations.json` whose every hit Check 4 rejected as a common word, and `{"edges": []}` when it rejected none.
148
+ 2. **Resolve `{cycleFinderHelper}`** from `{cycleFinderProbeOrder}`; first existing path wins. If no candidate exists: HALT (exit code 3, `halt_reason: "resolution-failure"`) at phase `integrations:cycles`. Enumerate cycles deterministically (run `uv run {cycleFinderHelper} find --help` for the contract):
121
149
 
122
150
  ```bash
123
- uv run {cycleFinderHelper} find --edges -
151
+ uv run {cycleFinderHelper} find --edges "{run_dir}/citations.json" --exclude-edges "{run_dir}/rejected-edges.json" --skip-mutual > "{run_dir}/cycles.json"
124
152
  ```
125
- piping the edges JSON on stdin (use a temp file under `{forge_data_folder}/` if stdin piping is unavailable). The script emits:
153
+ It reads the `edges` of the citations file (one `[from, to]` pair per citing direction), leaves out the rejected directions and every cycle whose edges are all mutual citations, and writes:
126
154
  ```json
127
155
  {"cycles": [["A", "B", "C", "A"], ...], "cycle_count": N}
128
156
  ```
129
- Each `cycles[]` entry is a closed node path (first node repeated at the end); every simple directed cycle appears exactly once, de-duplicated across rotations.
157
+ Each `cycles[]` entry is a closed node path (first node repeated at the end) through three or more skills, with at least one one-way citation; every such cycle appears exactly once, de-duplicated across rotations. With no pair it writes an empty list.
158
+ 3. **For each cycle** in `cycles[]`, the canonical table holds one more `Risky` row, which §6 renders after the pair rows. Its `lib_a`, `cycle`, keeps the row apart from every pair row, since the next run's delta keys rows on their two libraries. Leave the pair verdicts as they are.
159
+
160
+ **Count the verdicts deterministically.** Rating each pair is judgment; counting the rows of the canonical table has one correct answer, so delegate it. Write `{run_dir}/verdict-rows.json` as `{"rows": [{"lib_a": "…", "lib_b": "…", "verdict": "Verified|Plausible|Risky|Blocked", "rationale": "<the checks and evidence behind the verdict, one line>"}, …]}`, one row per pair and no cycle row (§6 renders the canonical rows from it), and run:
161
+
162
+ ```bash
163
+ uv run {coverageTallyScript} --kind integrations --cycles "{run_dir}/cycles.json" --stdin < "{run_dir}/verdict-rows.json"
164
+ ```
130
165
 
131
- **Graceful degradation:** if no `{cycleFinderProbeOrder}` candidate exists (e.g. `uv` unavailable on claude.ai web), run the equivalent DFS (visited set + recursion stack) directly per the `--help` contract and proceed with the same cycle set.
132
- 3. **For each cycle** in `cycles[]`, append a synthetic row to the verdict table with verdict `Risky` and rationale "circular integration dependency detected: `{A → B → C → A}`" (render the arrow chain from the cycle's node path). Do not otherwise modify the individual pair verdicts.
166
+ It returns `pairs_verified`, `pairs_plausible`, `pairs_risky` (each cycle counted as one `Risky` row), `pairs_blocked`, `pair_count`, `cycle_count` and `row_count` (run `uv run {coverageTallyScript} --help` for the contract). When it exits non-zero, it rejected its input and says why (its JSON `error`): fix the rows and run it again. Section 5 displays these counts and section 6 persists them.
133
167
 
134
168
  ### 5. Display Integration Results
135
169
 
170
+ The Summary line shows the §4 tally's counts (`pairs_risky` includes each cycle row).
171
+
136
172
  "**Pass 2: Integration Verification**
137
173
 
138
- | Library A | Library B | Context | Source | Verdict | Evidence |
139
- |-----------|-----------|---------|--------|---------|----------|
140
- | {lib_a} | {lib_b} | {brief context} | {stack manifest / prose co-mention} | {Verified/Plausible/Risky/Blocked} | {key evidence, including Check 4 literal citation if Verified} |
174
+ | Library A | Library B | Context | Verdict | Evidence |
175
+ |-----------|-----------|---------|---------|----------|
176
+ | {lib_a} | {lib_b} | {brief context} | {Verified/Plausible/Risky/Blocked} | {key evidence, including Check 4 literal citation if Verified} |
177
+
178
+ **Summary:** {pairs_verified} Verified, {pairs_plausible} Plausible, {pairs_risky} Risky, {pairs_blocked} Blocked
141
179
 
142
- **Summary:** {verified_count} Verified, {plausible_count} Plausible, {risky_count} Risky, {blocked_count} Blocked
180
+ {IF §2 dropped a pair whose technologies are one skill:}
181
+ **Not verified (one skill):** `{tech_a}` and `{tech_b}` both match `{skill}`, so there is no integration between two skills to check.
143
182
 
144
183
  {IF zero integration pairs found:}
145
184
  **No integration claims detected in the architecture document prose.** Ensure your architecture document describes relationships between technologies in text form (not exclusively in Mermaid diagrams). Coverage-only analysis was performed.
@@ -156,27 +195,29 @@ For each integration pair `{library_a, library_b}`, run the four-check protocol
156
195
 
157
196
  ### 6. Append to Report
158
197
 
159
- **Resolve `{atomicWriteHelper}`** from `{atomicWriteProbeOrder}`; first existing path wins. If no candidate exists: HALT (exit code 3, `halt_reason: "resolution-failure"`); in headless, emit the error envelope.
198
+ **Resolve `{atomicWriteHelper}`** from `{atomicWriteProbeOrder}`; first existing path wins. If no candidate exists: HALT (exit code 3, `halt_reason: "resolution-failure"`) at phase `integrations:report`.
160
199
 
161
- Write the **Integration Verdicts** section to `{outputFile}` (heading is fixed — consumers grep for `## Integration Verdicts`; the table header is the canonical `| lib_a | lib_b | verdict | rationale |` per `{feasibilitySchemaRef}`, and consumers parse that exact header, so a different one breaks them; the skill-local display table with the extra Context/Source/Evidence columns can be rendered beneath it for human readers):
162
- - Emit the canonical `| lib_a | lib_b | verdict | rationale |` table first (verdict tokens are exactly one of `Verified`, `Plausible`, `Risky`, `Blocked`, case-sensitive — any other token is a schema violation consumers reject)
163
- - Include the extended table with Context, Source, and Evidence columns below it
164
- - Include recommendations for Risky and Blocked pairs (each Blocked recommendation cites a named candidate per step 5 H6, or the explicit no-candidate notice)
165
- - Update frontmatter: append `'integrations'` to `stepsCompleted`; set `pairsVerified`, `pairsPlausible`, `pairsRisky`, `pairsBlocked` counts
166
- - Pipe the updated full content through `python3 {atomicWriteHelper} write --target {outputFile}` and again with `--target {outputFileLatest}`
200
+ Write the **Integration Verdicts** section of `{outputFile}`. The report template already holds the canonical table under `## Integration Verdicts`: the header `| lib_a | lib_b | verdict | rationale |` (per `{feasibilitySchemaRef}`) and its delimiter row. Consumers read that table and reject a report that holds it twice, so fill it in place instead of appending another one:
201
+ - Render its rows from the §4 rows file and the cycles, one per pair and one per §4 cycle, each verdict a schema token and each rationale kept in its cell:
167
202
 
168
- ### 7. Auto-Proceed to Next Step
203
+ ```bash
204
+ uv run {coverageTallyScript} --kind integrations --render --cycles "{run_dir}/cycles.json" --stdin < "{run_dir}/verdict-rows.json"
205
+ ```
169
206
 
170
- **Early halt guard:** If ALL integration pairs are Blocked, present: "**All integrations are Blocked** — fundamental incompatibilities detected across all library pairs. Remaining analysis will produce limited value. **[X] Halt workflow (recommended)** | **[C] Continue anyway**" — wait for user input.
207
+ Put the lines it prints under the template's header, as printed; on a non-zero exit, fix the row its JSON `error` names and run it again. With zero integration pairs, leave the table with its header and delimiter rows only.
208
+ - After one blank line, add the display table with the extra Context and Evidence columns for human readers (a separate table, so consumers skip it).
209
+ - Include recommendations for Risky and Blocked pairs (a Blocked one that proposes a replacement names at least one alternative library with a one-line justification, or says no named candidate was found and gives the selection criteria)
210
+ - Update frontmatter: append `'integrations'` to `stepsCompleted`; from the §4 tally, set `pairsVerified` ← `pairs_verified`, `pairsPlausible` ← `pairs_plausible`, `pairsRisky` ← `pairs_risky` (each cycle row included) and `pairsBlocked` ← `pairs_blocked`
211
+ - Pipe the updated full content through `python3 {atomicWriteHelper} write --target {outputFile}`. On a non-zero exit: HALT (exit code 4, `halt_reason: "write-failed"`) at phase `integrations:report`, with `"path": "{outputFile}"`.
171
212
 
172
- **GATE [default: C]** — Interactive-only guard. If `{headless_mode}`: auto-proceed with [C] Continue, log: "headless: continuing past all-Blocked integration gate". Headless never takes [X], so step 6 still emits the result contract — any Blocked pair resolves the run to `NOT_FEASIBLE` in synthesize.
213
+ ### 7. Auto-Proceed to Next Step
173
214
 
174
- - If X: halt with: "**Workflow halted — all integrations blocked.** Integration Verdicts saved to `{outputFile}`. Run **[VS]** after applying architectural changes. **Blocked integrations:** {list each blocked pair with reason}." HALT (exit code 8, `halt_reason: "analysis-halted"`).
175
- - If C: continue.
215
+ {IF the §4 tally's `pair_count` is not 0 and its `pairs_blocked` equals `pair_count` (every pair is Blocked):} display one warning line (headless: log it), record it in the run sink, and continue, so synthesize can recommend a way past each Blocked pair: "**Warning:** every integration pair is Blocked; the run will resolve to `NOT_FEASIBLE`, and the report will name a replacement library or a bridge for each Blocked pair."
176
216
 
177
- {IF NOT halted (user selected C, or early halt guard did not trigger):}
217
+ ```bash
218
+ uv run {emitEnvelopeHelper} record --run-dir "{run_dir}" --warning 'all_pairs_blocked: every integration pair is Blocked'
219
+ ```
178
220
 
179
221
  "**Proceeding to requirements verification...**"
180
222
 
181
223
  Load, read the full file and then execute `{nextStepFile}`.
182
-
@@ -1,8 +1,9 @@
1
1
  ---
2
- # {outputFile} and {outputFileLatest} resolve from the activation-stored
3
- # {project_slug}, {timestamp}, and {outputFolderPath} variables (set in
4
- # SKILL.md On Activation §2 + §4) — same template as init.md frontmatter
5
- # so every stage sees the same path.
2
+ # {outputFile} and {outputFileLatest} resolve from {timestamp} (fixed in
3
+ # SKILL.md On Activation §2), {project_slug} (bound at the top of init.md)
4
+ # and {outputFolderPath} (On Activation §4), with the same template as the
5
+ # init.md frontmatter, so every stage sees the same path. §1 is the only
6
+ # place that writes {outputFileLatest}: once the report passes its check.
6
7
  outputFile: '{outputFolderPath}/feasibility-report-{project_slug}-{timestamp}.md'
7
8
  outputFileLatest: '{outputFolderPath}/feasibility-report-{project_slug}-latest.md'
8
9
  feasibilitySchemaProbeOrder:
@@ -14,6 +15,9 @@ atomicWriteProbeOrder:
14
15
  validateFeasibilityReportProbeOrder:
15
16
  - '{project-root}/_bmad/skf/shared/scripts/skf-validate-feasibility-report.py'
16
17
  - '{project-root}/src/shared/scripts/skf-validate-feasibility-report.py'
18
+ emitEnvelopeProbeOrder:
19
+ - '{project-root}/_bmad/skf/shared/scripts/skf-emit-result-envelope.py'
20
+ - '{project-root}/src/shared/scripts/skf-emit-result-envelope.py'
17
21
  nextStepFile: 'health-check.md'
18
22
  ---
19
23
 
@@ -23,7 +27,7 @@ nextStepFile: 'health-check.md'
23
27
 
24
28
  ## STEP GOAL:
25
29
 
26
- Present the complete feasibility report to the user. Display the overall verdict prominently, walk through key findings from each analysis pass, present actionable next steps based on the verdict, and offer the user options to review the full report or exit.
30
+ Present the complete feasibility report to the user. Display the overall verdict prominently, walk through key findings from each analysis pass, present actionable next steps based on the verdict, write the result contract, and finish.
27
31
 
28
32
  ## Rules
29
33
 
@@ -32,30 +36,43 @@ Present the complete feasibility report to the user. Display the overall verdict
32
36
 
33
37
  ## MANDATORY SEQUENCE
34
38
 
39
+ **Halt envelope.** Every HALT in this step names its exit code, `halt_reason` and phase. In headless mode, stage `{run_dir}/halt.json` as `{"phase": "<phase>", "reason": "<the halt message>", "halt_reason": "<halt_reason>", "report_path": "{outputFile}"}`, adding `"path"` when the halt names one, resolve `{emitEnvelopeHelper}` from `{emitEnvelopeProbeOrder}` if it is not bound (first existing path wins), then run:
40
+
41
+ ```bash
42
+ uv run {emitEnvelopeHelper} emit-halt --workflow skf-verify-stack --run-dir "{run_dir}" --target stderr < "{run_dir}/halt.json"
43
+ ```
44
+
45
+ Display the line it prints, then stop with the halt's exit code (`references/exit-codes.md` describes the envelope). If no candidate exists, or the emitter exits non-zero or prints no line, display the halt message alone. An interactive HALT displays its message and emits nothing.
46
+
35
47
  ### 1. Load Complete Report
36
48
 
37
49
  Read the entire `{outputFile}` to have all data available for presentation.
38
50
 
39
51
  **Resolve `{feasibilitySchemaRef}`** from `{feasibilitySchemaProbeOrder}`; first existing path wins (installed SKF module path first, dev-checkout `src/` fallback).
40
52
 
41
- **Validate report structure and schema version (deterministic gate).** Resolve `{validateFeasibilityReportHelper}` from `{validateFeasibilityReportProbeOrder}`; first existing path wins (installed SKF module path first, dev-checkout `src/` fallback). Then run:
53
+ **Validate the report (deterministic gate).** Resolve `{validateFeasibilityReportHelper}` from `{validateFeasibilityReportProbeOrder}`; first existing path wins (installed SKF module path first, dev-checkout `src/` fallback). If no candidate exists: HALT (exit code 3, `halt_reason: "resolution-failure"`) at phase `report:check`. Then run:
42
54
 
43
55
  ```bash
44
- python3 {validateFeasibilityReportHelper} {outputFile}
56
+ uv run {validateFeasibilityReportHelper} "{outputFile}" -o "{run_dir}/report-check.json"
45
57
  ```
46
58
 
47
- The script (see `--help`) deterministically confirms the five required body sections — `## Executive Summary`, `## Coverage Analysis`, `## Integration Verdicts`, `## Recommendations`, `## Evidence Sources` — are all present and in canonical order per `{feasibilitySchemaRef}`, **and** that frontmatter `schemaVersion == "1.0"`. It emits a JSON verdict on stdout (`headingsOk`, `missingHeadings`, `orderViolations`, `schemaVersionOk`, `schemaVersionFound`, `violation`) and exits `0` when valid, `1` on a schema violation, `2` on an IO/parse error.
59
+ The script (see `--help`) checks the report against `{feasibilitySchemaRef}`: the five required body sections (`## Executive Summary`, `## Coverage Analysis`, `## Integration Verdicts`, `## Recommendations`, `## Evidence Sources`) in canonical order, frontmatter `schemaVersion == "1.0"`, and whatever else its `--help` lists. It writes a JSON verdict to `{run_dir}/report-check.json` (`violation` names the class; the detail fields say what failed; `overallVerdict` and `coveragePercentage` are the report's own) and exits `0` when valid, `1` on a schema violation, `2` when the report cannot be read.
48
60
 
49
- **Graceful degradation:** if no `{validateFeasibilityReportProbeOrder}` candidate exists (e.g. partial installation, or `python3` unavailable), perform the equivalent structural check inline — confirm the five headings above are all present and in that exact order, and that frontmatter `schemaVersion` is `"1.0"` — and apply the same halt semantics below. The report is already on disk from steps 1-5, so a missing validator degrades to the inline check rather than blocking presentation.
61
+ On any non-zero exit, HALT (exit code 5, `halt_reason: "schema-violation"`) at phase `report:check`: do not display partial results, and leave `{outputFileLatest}` as it is. Report the specific violation from the JSON:
50
62
 
51
- On any non-zero exit (or an inline check that fails), HALT (exit code 5, `halt_reason: "schema-violation"`) — do not display partial results. Report the specific violation from the JSON:
63
+ - a missing or out-of-order section (`missingHeadings` / `orderViolations`);
64
+ - a schemaVersion mismatch: "Report frontmatter schemaVersion `{schemaVersionFound}` does not match producer schema `1.0`: report was corrupted between steps. Re-run [VS]." (The producer never proceeds past a schema mismatch.)
65
+ - any other detail the JSON carries, such as a missing or doubled canonical verdict table or an unknown verdict token.
52
66
 
53
- - a missing or out-of-order section (`missingHeadings` / `orderViolations`); or
54
- - a schemaVersion mismatch — "Report frontmatter schemaVersion `{schemaVersionFound}` does not match producer schema `1.0` — report was corrupted between steps. Re-run [VS]." (Producer never proceeds past a schema mismatch.)
67
+ **Publish the checked report.** With the gate passed, resolve `{atomicWriteHelper}` from `{atomicWriteProbeOrder}` (first existing path wins; if no candidate exists: HALT (exit code 3, `halt_reason: "resolution-failure"`) at phase `report:publish`) and copy the report over its stable `-latest` copy, which consumers such as campaign, create-stack-skill and refine-architecture read:
55
68
 
56
- In headless, emit the error envelope per SKILL.md "Result Contract (Headless)" with `report_path: "{outputFile}"`, `overall_verdict: null`.
69
+ ```bash
70
+ python3 {atomicWriteHelper} write --target "{outputFileLatest}" < "{outputFile}"
71
+ ```
72
+
73
+ It is a copy, not a symlink (per the shared schema). This is the run's only write of `{outputFileLatest}`: every stage before this one wrote only `{outputFile}`, so a run that halted earlier left the previous finished report at the stable path. On a non-zero exit: HALT (exit code 4, `halt_reason: "write-failed"`) at phase `report:publish`, with `"path": "{outputFileLatest}"`; the atomic write leaves the previous copy intact.
57
74
 
58
- With the deterministic gate passed (sections present + in order, `schemaVersion == "1.0"`), **extract metrics from `{outputFile}` frontmatter** (per shared schema in `{feasibilitySchemaRef}`): `skillsAnalyzed`, `coveragePercentage`, `pairsVerified` (as `verified_count`), `pairsPlausible` (as `plausible_count`), `pairsRisky` (as `risky_count`), `pairsBlocked` (as `blocked_count`), `requirementsFulfilled` (as `fulfilled_count`), `requirementsPartial` (as `partial_count`), `requirementsNotAddressed` (as `not_addressed_count`), `requirementsPass`, `overallVerdict`, and `recommendationCount`. Use these mapped display names in the summary table and next steps below.
75
+ With the deterministic gate passed, **extract metrics from `{outputFile}` frontmatter** (per shared schema in `{feasibilitySchemaRef}`): `skillsAnalyzed`, `coveragePercentage`, `pairsVerified` (as `verified_count`), `pairsPlausible` (as `plausible_count`), `pairsRisky` (as `risky_count`), `pairsBlocked` (as `blocked_count`), `requirementsFulfilled` (as `fulfilled_count`), `requirementsPartial` (as `partial_count`), `requirementsNotAddressed` (as `not_addressed_count`), `requirementsPass`, `overallVerdict`, and `recommendationCount`. Use these mapped display names in the summary table and next steps below.
59
76
 
60
77
  ### 2. Present Summary
61
78
 
@@ -88,52 +105,52 @@ With the deterministic gate passed (sections present + in order, `schemaVersion
88
105
 
89
106
  ### 3. Present Detailed Findings
90
107
 
91
- Walk through the highlights — coverage gaps, risky/blocked integrations, and partial/unaddressed requirements (when a PRD pass ran). Cite specific items by name; cap at the top ~5 per category to keep the summary scannable. The full detail is in `{outputFile}` for the user to inspect via the [R] Review menu (§5).
108
+ Walk through the highlights: coverage gaps, risky/blocked integrations, and partial/unaddressed requirements (when a PRD pass ran). Cite specific items by name; cap at the top ~5 per category to keep the summary scannable. The full detail is in `{outputFile}`.
92
109
 
93
110
  ### 4. Present Next Steps
94
111
 
95
112
  Step 05 already wrote a **Suggested next workflow** block (keyed on the case-sensitive `overallVerdict` token) at the end of `## Recommendations`. Surface that block from the §1 load rather than re-deriving it, prefixed with the one-line verdict-specific framing:
96
113
 
97
- - **`FEASIBLE`:** "**Your stack is verified.** All technologies are covered, integrations are compatible, and requirements are all fulfilled (or requirements pass was skipped)."
114
+ - **`FEASIBLE`:** "**Your stack is verified.**" Then give the verdict rationale from the report's `## Executive Summary`: synthesize wrote there what was verified, including when there was no integration pair to verify.
98
115
  - **`CONDITIONALLY_FEASIBLE`:** "**Your stack is conditionally feasible.** There are {recommendationCount} items to address before proceeding." — then list the specific recommendations from the report's `## Recommendations` section.
99
116
  - **`NOT_FEASIBLE`:** "**Critical blockers must be resolved.** The stack cannot support the architecture as described." — then list the blocked-integration and missing-skill recommendations from the report's `## Recommendations` section.
100
117
 
101
118
  ### 4b. Result Contract
102
119
 
103
- **Resolve `{atomicWriteHelper}`** from `{atomicWriteProbeOrder}`; first existing path wins. If no candidate exists: HALT (exit code 3, `halt_reason: "resolution-failure"`); in headless, emit the error envelope.
104
-
105
- Write the result contract per `shared/references/output-contract-schema.md` (this path resolves relative to the SKF module root — `{project-root}/_bmad/skf/` when installed, `{project-root}/src/` during development — not relative to this step file): the per-run record at `{forge_data_folder}/verify-stack-result-{YYYYMMDD-HHmmss}.json` (UTC timestamp, resolution to seconds) and a copy at `{forge_data_folder}/verify-stack-result-latest.json` (stable path for pipeline consumers — copy, not symlink). Include the feasibility report path (both `{outputFile}` and `{outputFileLatest}`) in `outputs`; include `overallVerdict` (`FEASIBLE` / `CONDITIONALLY_FEASIBLE` / `NOT_FEASIBLE`), `coveragePercentage`, and `recommendationCount` in `summary` — use the case-sensitive schema tokens.
106
-
107
- Write both JSON files through `python3 {atomicWriteHelper} write --target ...` to avoid partial-write corruption. On any non-zero exit: HALT (exit code 4, `halt_reason: "write-failed"`) and emit the error envelope.
108
-
109
- When `{headless_mode}` is true, also emit the single-line envelope on **stdout** before chaining to step 7 (matches the SKILL.md "Result Contract (Headless)" shape):
110
-
111
- ```
112
- SKF_VERIFY_STACK_RESULT_JSON: {"status":"success","report_path":"{outputFile}","report_latest_path":"{outputFileLatest}","overall_verdict":"{overallVerdict}","coverage_percentage":{coveragePercentage},"recommendation_count":{recommendationCount},"exit_code":0,"halt_reason":null}
120
+ The shared emitter writes the result contract (per `shared/references/output-contract-schema.md`, which resolves relative to the SKF module root: `{project-root}/_bmad/skf/` when installed, `{project-root}/src/` during development) and prints the envelope; this step stages their content, every count from a file a helper wrote. Write `{run_dir}/result-context.json`:
121
+
122
+ ```json
123
+ {
124
+ "status": "success",
125
+ "report_path": "{outputFile}",
126
+ "report_latest_path": "{outputFileLatest}",
127
+ "overall_verdict": "<overallVerdict>",
128
+ "coverage_percentage": <coveragePercentage>,
129
+ "recommendation_count": <recommendationCount>,
130
+ "result_contract": {
131
+ "skill": "skf-verify-stack",
132
+ "status": "success",
133
+ "outputs": [{"type": "report", "path": "{outputFile}"}, {"type": "report", "path": "{outputFileLatest}"}],
134
+ "summary": {"overallVerdict": "<overallVerdict>", "coveragePercentage": <coveragePercentage>, "recommendationCount": <recommendationCount>}
135
+ }
136
+ }
113
137
  ```
114
138
 
115
- `{overallVerdict}` uses the schema tokens (`FEASIBLE` / `CONDITIONALLY_FEASIBLE` / `NOT_FEASIBLE`).
139
+ `<overallVerdict>` and `<coveragePercentage>` are the `overallVerdict` (a case-sensitive schema token: `FEASIBLE`, `CONDITIONALLY_FEASIBLE` or `NOT_FEASIBLE`) and `coveragePercentage` §1's check read into `{run_dir}/report-check.json`; `<recommendationCount>` is the report frontmatter's `recommendationCount`, the count synthesize took from its verdict rollup. Then run, in every mode (the emitter writes result files only into a folder that exists):
116
140
 
117
- **Result-contract ordering:** The result contract is written exactly once on the first entry to step 6 (the `[X] Exit verification` path). Re-walks of the report via the `[R] Review full report` menu option do not regenerate it — the contract captures the run, not the presentation loop. If the user selects `[R]` repeatedly before exiting, the single on-disk contract written on first entry remains authoritative.
118
-
119
- ### 5. Present Menu
141
+ ```bash
142
+ mkdir -p "{forge_data_folder}" || uv run {emitEnvelopeHelper} record --run-dir "{run_dir}" --warning 'result_file_write_failed: cannot create the forge data folder'
143
+ uv run {emitEnvelopeHelper} emit --workflow skf-verify-stack --run-dir "{run_dir}" --result-dir "{forge_data_folder}" < "{run_dir}/result-context.json"
144
+ ```
120
145
 
121
- Display: "**[R] Review full report** | **[X] Exit verification**"
146
+ It writes `{forge_data_folder}/verify-stack-result-{timestamp}.json`, named after the run's own `{timestamp}` (the one the timestamped report carries), and its `verify-stack-result-latest.json` copy, and prints the `SKF_VERIFY_STACK_RESULT_JSON:` line on stdout. When `{headless_mode}` is true, display the line verbatim before chaining to step 7. 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, correct `result-context.json` from the message on its stderr and run it once more; if it fails again, HALT (exit code 4, `halt_reason: "write-failed"`) at phase `report:result-contract`, adding `"report_latest_path": "{outputFileLatest}"` to the halt payload: the run's result contract could not be written.
122
147
 
123
- #### Menu Handling Logic:
148
+ ### 5. Finish
124
149
 
125
- - **IF R:** Walk through the report section by section, presenting each section's content from {outputFile} in a readable format. After completing the walkthrough, redisplay the menu. (Note: the R walkthrough loop terminates only when the user selects X.)
126
- - **IF X:** "**Feasibility report saved to:** `{outputFile}`
150
+ "**Feasibility report saved to:** `{outputFile}` (a copy at `{outputFileLatest}`). Ask me to walk through any section of it.
127
151
 
128
152
  Re-run **[VS] Verify Stack** anytime after making changes to your skills or architecture document.
129
153
 
130
154
  **Verification workflow complete.**"
131
155
 
132
- If `{workflow.on_complete}` is non-empty, execute it now (e.g. route the verdict onward or trigger a downstream step); in headless, log the action. Then load, read the full file, and execute `{nextStepFile}` — the health-check step is the true terminal step of this workflow.
133
-
134
- #### EXECUTION RULES:
135
-
136
- - **GATE [default: X]** — If `{headless_mode}`: auto-proceed with [X] Exit verification, log: "headless: auto-exit past report menu"
137
- - R may be selected multiple times — always walk through the full report
138
-
139
-
156
+ If `{workflow.on_complete}` is non-empty, execute it now (e.g. route the verdict onward or trigger a downstream step); in headless, log the action. Then delete the run folder, whose inventory, summaries and payloads the run no longer needs: `rm -rf "{run_dir}"`. Then load, read the full file, and execute `{nextStepFile}`: the health-check step is the true terminal step of this workflow.