bmad-module-skill-forge 1.9.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (281) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.nvmrc +1 -1
  3. package/README.md +10 -5
  4. package/docs/_data/pinned.yaml +2 -2
  5. package/docs/agents.md +11 -2
  6. package/docs/architecture.md +5 -4
  7. package/docs/bmad-synergy.md +30 -7
  8. package/docs/campaign.md +172 -0
  9. package/docs/examples.md +7 -3
  10. package/docs/forge-auto.md +90 -0
  11. package/docs/getting-started.md +9 -0
  12. package/docs/how-it-works.md +6 -4
  13. package/docs/index.md +4 -3
  14. package/docs/skill-model.md +1 -1
  15. package/docs/troubleshooting.md +17 -1
  16. package/docs/verifying-a-skill.md +2 -2
  17. package/docs/why-skf.md +1 -1
  18. package/docs/workflows.md +64 -24
  19. package/package.json +2 -2
  20. package/src/knowledge/skill-lifecycle.md +1 -1
  21. package/src/module-help.csv +4 -3
  22. package/src/shared/data/language-corpora.json +32 -0
  23. package/src/shared/references/pipeline-contracts.md +6 -3
  24. package/src/shared/scripts/schemas/skill-brief.v1.json +6 -1
  25. package/src/shared/scripts/skf-comention-pairs.py +350 -0
  26. package/src/shared/scripts/skf-count-tokens.py +222 -0
  27. package/src/shared/scripts/skf-derive-assembly-shape.py +107 -0
  28. package/src/shared/scripts/skf-detect-docs.py +240 -4
  29. package/src/shared/scripts/skf-detect-language.py +82 -3
  30. package/src/shared/scripts/skf-detect-tools.py +105 -2
  31. package/src/shared/scripts/skf-emit-result-envelope.py +17 -0
  32. package/src/shared/scripts/skf-enumerate-stack-skills.py +111 -2
  33. package/src/shared/scripts/skf-extract-public-api.py +53 -0
  34. package/src/shared/scripts/skf-find-cycles.py +246 -0
  35. package/src/shared/scripts/skf-hash-content.py +487 -2
  36. package/src/shared/scripts/skf-language-corpora.py +100 -0
  37. package/src/shared/scripts/skf-manifest-ops.py +67 -1
  38. package/src/shared/scripts/skf-merge-doc-urls.py +244 -0
  39. package/src/shared/scripts/skf-preapply.py +1 -1
  40. package/src/shared/scripts/skf-rebuild-managed-sections.py +180 -0
  41. package/src/shared/scripts/skf-recommend-scope-type.py +1 -2
  42. package/src/shared/scripts/skf-render-metadata-stats.py +499 -0
  43. package/src/shared/scripts/skf-rewrite-skill-name.py +308 -0
  44. package/src/shared/scripts/skf-shape-detect.py +576 -25
  45. package/src/shared/scripts/skf-shard-body.py +461 -0
  46. package/src/shared/scripts/skf-skill-inventory.py +139 -3
  47. package/src/shared/scripts/skf-structural-diff.py +307 -67
  48. package/src/shared/scripts/skf-validate-brief-schema.py +41 -6
  49. package/src/shared/scripts/skf-validate-feasibility-report.py +234 -0
  50. package/src/shared/scripts/skf-validate-frontmatter.py +17 -12
  51. package/src/shared/scripts/skf-validate-output.py +443 -10
  52. package/src/shared/scripts/skf-validate-pins.py +3 -3
  53. package/src/shared/scripts/skf-verify-no-trace.py +214 -0
  54. package/src/shared/scripts/skf-verify-provenance-completeness.py +439 -0
  55. package/src/shared/scripts/skf-write-skill-brief.py +21 -5
  56. package/src/skf-analyze-source/SKILL.md +17 -32
  57. package/src/skf-analyze-source/assets/skill-brief-schema.md +1 -1
  58. package/src/skf-analyze-source/customize.toml +2 -0
  59. package/src/skf-analyze-source/references/auto-docs-only.md +116 -0
  60. package/src/skf-analyze-source/references/continue.md +8 -13
  61. package/src/skf-analyze-source/references/generate-briefs.md +28 -12
  62. package/src/skf-analyze-source/references/headless-contract.md +33 -0
  63. package/src/skf-analyze-source/references/health-check.md +1 -2
  64. package/src/skf-analyze-source/references/identify-units.md +25 -36
  65. package/src/skf-analyze-source/references/init.md +12 -25
  66. package/src/skf-analyze-source/references/map-and-detect.md +8 -20
  67. package/src/skf-analyze-source/references/recommend.md +4 -14
  68. package/src/skf-analyze-source/references/scan-project.md +3 -11
  69. package/src/skf-analyze-source/references/step-auto-scope.md +211 -197
  70. package/src/skf-analyze-source/references/step-shape-detect.md +20 -13
  71. package/src/skf-analyze-source/references/unit-detection-heuristics.md +2 -2
  72. package/src/skf-audit-skill/SKILL.md +9 -6
  73. package/src/skf-audit-skill/customize.toml +2 -0
  74. package/src/skf-audit-skill/references/init.md +58 -32
  75. package/src/skf-audit-skill/references/re-index.md +15 -34
  76. package/src/skf-audit-skill/references/report.md +11 -58
  77. package/src/skf-audit-skill/references/semantic-diff.md +4 -22
  78. package/src/skf-audit-skill/references/severity-classify.md +53 -87
  79. package/src/skf-audit-skill/references/step-doc-drift.md +49 -19
  80. package/src/skf-audit-skill/references/structural-diff.md +43 -68
  81. package/src/skf-brief-skill/SKILL.md +7 -36
  82. package/src/skf-brief-skill/assets/scope-templates.md +1 -1
  83. package/src/skf-brief-skill/assets/skill-brief-schema.md +1 -1
  84. package/src/skf-brief-skill/customize.toml +14 -0
  85. package/src/skf-brief-skill/references/analyze-target.md +13 -18
  86. package/src/skf-brief-skill/references/confirm-brief.md +2 -15
  87. package/src/skf-brief-skill/references/draft-checkpoint.md +8 -8
  88. package/src/skf-brief-skill/references/gather-intent.md +27 -24
  89. package/src/skf-brief-skill/references/headless-args.md +1 -1
  90. package/src/skf-brief-skill/references/health-check.md +1 -22
  91. package/src/skf-brief-skill/references/invocation-contract.md +37 -0
  92. package/src/skf-brief-skill/references/scope-definition.md +6 -15
  93. package/src/skf-brief-skill/references/step-auto-brief.md +22 -9
  94. package/src/skf-brief-skill/references/step-auto-validate.md +3 -7
  95. package/src/skf-brief-skill/references/version-resolution.md +1 -1
  96. package/src/skf-brief-skill/references/write-brief.md +19 -13
  97. package/src/skf-campaign/SKILL.md +121 -0
  98. package/src/skf-campaign/assets/campaign-state-schema.json +191 -0
  99. package/src/skf-campaign/customize.toml +75 -0
  100. package/src/skf-campaign/manifest.yaml +15 -0
  101. package/src/skf-campaign/references/campaign-contracts.md +67 -0
  102. package/src/skf-campaign/references/campaign-directive-spec.md +32 -0
  103. package/src/skf-campaign/references/health-check.md +35 -0
  104. package/src/skf-campaign/references/step-01-setup.md +121 -0
  105. package/src/skf-campaign/references/step-02-strategy.md +102 -0
  106. package/src/skf-campaign/references/step-03-pins.md +56 -0
  107. package/src/skf-campaign/references/step-04-provenance.md +63 -0
  108. package/src/skf-campaign/references/step-05-skill-loop.md +103 -0
  109. package/src/skf-campaign/references/step-06-batch.md +88 -0
  110. package/src/skf-campaign/references/step-07-capstone.md +63 -0
  111. package/src/skf-campaign/references/step-08-verify.md +75 -0
  112. package/src/skf-campaign/references/step-09-refine.md +83 -0
  113. package/src/skf-campaign/references/step-10-export.md +106 -0
  114. package/src/skf-campaign/references/step-11-maintenance.md +84 -0
  115. package/src/skf-campaign/references/step-resume.md +115 -0
  116. package/src/skf-campaign/scripts/.gitkeep +0 -0
  117. package/src/skf-campaign/scripts/campaign-deps.py +244 -0
  118. package/src/skf-campaign/scripts/campaign-parse-manifest.py +119 -0
  119. package/src/skf-campaign/scripts/campaign-provenance.py +247 -0
  120. package/src/skf-campaign/scripts/campaign-render-batch.py +199 -0
  121. package/src/skf-campaign/scripts/campaign-render-kickoff.py +158 -0
  122. package/src/skf-campaign/scripts/campaign-report.py +249 -0
  123. package/src/skf-campaign/scripts/campaign-status.py +162 -0
  124. package/src/skf-campaign/scripts/campaign-validate-pins.py +174 -0
  125. package/src/skf-campaign/scripts/campaign-validate-state.py +207 -0
  126. package/src/skf-campaign/templates/campaign-brief-template.yaml +34 -0
  127. package/src/skf-campaign/templates/campaign-report-template.md +54 -0
  128. package/src/skf-campaign/templates/kickoff-template.md +48 -0
  129. package/src/skf-create-skill/SKILL.md +15 -4
  130. package/src/skf-create-skill/assets/compile-assembly-rules.md +35 -34
  131. package/src/skf-create-skill/assets/skill-sections.md +9 -100
  132. package/src/skf-create-skill/assets/tessl-dismissal-rules.md +4 -13
  133. package/src/skf-create-skill/customize.toml +13 -0
  134. package/src/skf-create-skill/references/authoritative-files-protocol.md +7 -7
  135. package/src/skf-create-skill/references/compile.md +37 -47
  136. package/src/skf-create-skill/references/component-extraction.md +8 -35
  137. package/src/skf-create-skill/references/ecosystem-check.md +9 -25
  138. package/src/skf-create-skill/references/enrich.md +4 -17
  139. package/src/skf-create-skill/references/extract.md +20 -27
  140. package/src/skf-create-skill/references/extraction-patterns-tracing.md +1 -1
  141. package/src/skf-create-skill/references/extraction-patterns.md +10 -8
  142. package/src/skf-create-skill/references/generate-artifacts.md +20 -25
  143. package/src/skf-create-skill/references/health-check.md +2 -2
  144. package/src/skf-create-skill/references/load-brief.md +16 -18
  145. package/src/skf-create-skill/references/report.md +27 -14
  146. package/src/skf-create-skill/references/source-resolution-protocols.md +4 -4
  147. package/src/skf-create-skill/references/step-auto-shard.md +52 -25
  148. package/src/skf-create-skill/references/step-doc-rot.md +33 -15
  149. package/src/skf-create-skill/references/step-doc-sources.md +13 -4
  150. package/src/skf-create-skill/references/sub/ccc-discover.md +2 -13
  151. package/src/skf-create-skill/references/sub/fetch-docs.md +33 -46
  152. package/src/skf-create-skill/references/sub/fetch-temporal.md +5 -20
  153. package/src/skf-create-skill/references/tier-degradation-rules.md +6 -8
  154. package/src/skf-create-skill/references/validate.md +69 -29
  155. package/src/skf-create-skill/scripts/scan-doc-rot.py +245 -0
  156. package/src/skf-create-stack-skill/SKILL.md +15 -9
  157. package/src/skf-create-stack-skill/assets/provenance-map-schema.md +1 -1
  158. package/src/skf-create-stack-skill/customize.toml +10 -0
  159. package/src/skf-create-stack-skill/references/compile-stack.md +7 -8
  160. package/src/skf-create-stack-skill/references/compose-mode-rules.md +2 -13
  161. package/src/skf-create-stack-skill/references/detect-integrations.md +49 -54
  162. package/src/skf-create-stack-skill/references/detect-manifests.md +37 -30
  163. package/src/skf-create-stack-skill/references/generate-output.md +24 -75
  164. package/src/skf-create-stack-skill/references/init.md +9 -81
  165. package/src/skf-create-stack-skill/references/manifest-patterns.md +5 -35
  166. package/src/skf-create-stack-skill/references/parallel-extract.md +12 -27
  167. package/src/skf-create-stack-skill/references/rank-and-confirm.md +6 -6
  168. package/src/skf-create-stack-skill/references/report.md +27 -62
  169. package/src/skf-create-stack-skill/references/validate.md +35 -31
  170. package/src/skf-drop-skill/SKILL.md +20 -23
  171. package/src/skf-drop-skill/customize.toml +10 -0
  172. package/src/skf-drop-skill/references/execute.md +67 -36
  173. package/src/skf-drop-skill/references/headless-contract.md +18 -0
  174. package/src/skf-drop-skill/references/health-check.md +1 -13
  175. package/src/skf-drop-skill/references/report.md +44 -10
  176. package/src/skf-drop-skill/references/select.md +93 -48
  177. package/src/skf-drop-skill/scripts/dir-sizes.py +116 -0
  178. package/src/skf-export-skill/SKILL.md +17 -14
  179. package/src/skf-export-skill/assets/managed-section-format.md +2 -5
  180. package/src/skf-export-skill/customize.toml +10 -6
  181. package/src/skf-export-skill/references/generate-snippet.md +21 -35
  182. package/src/skf-export-skill/references/load-skill.md +44 -42
  183. package/src/skf-export-skill/references/multi-skill-mode.md +1 -1
  184. package/src/skf-export-skill/references/orphan-context-detection.md +11 -3
  185. package/src/skf-export-skill/references/package.md +27 -33
  186. package/src/skf-export-skill/references/preflight-snippet-root-probe.md +24 -5
  187. package/src/skf-export-skill/references/result-envelope.md +28 -0
  188. package/src/skf-export-skill/references/summary.md +11 -5
  189. package/src/skf-export-skill/references/token-report.md +42 -24
  190. package/src/skf-export-skill/references/update-context.md +32 -33
  191. package/src/skf-forger/SKILL.md +32 -39
  192. package/src/skf-forger/references/pipeline-mode.md +34 -0
  193. package/src/skf-forger/scripts/parse-pipeline.py +270 -0
  194. package/src/skf-quick-skill/SKILL.md +10 -60
  195. package/src/skf-quick-skill/customize.toml +9 -0
  196. package/src/skf-quick-skill/references/batch-mode.md +6 -4
  197. package/src/skf-quick-skill/references/compile.md +15 -52
  198. package/src/skf-quick-skill/references/ecosystem-check.md +5 -20
  199. package/src/skf-quick-skill/references/finalize.md +12 -6
  200. package/src/skf-quick-skill/references/halt-contract.md +54 -0
  201. package/src/skf-quick-skill/references/health-check.md +3 -4
  202. package/src/skf-quick-skill/references/quick-extract.md +7 -18
  203. package/src/skf-quick-skill/references/registry-resolution.md +1 -23
  204. package/src/skf-quick-skill/references/resolve-target.md +27 -34
  205. package/src/skf-quick-skill/references/write-and-validate.md +10 -25
  206. package/src/skf-refine-architecture/SKILL.md +16 -8
  207. package/src/skf-refine-architecture/customize.toml +9 -0
  208. package/src/skf-refine-architecture/references/compile.md +10 -8
  209. package/src/skf-refine-architecture/references/gap-analysis.md +21 -50
  210. package/src/skf-refine-architecture/references/health-check.md +1 -1
  211. package/src/skf-refine-architecture/references/improvements.md +9 -25
  212. package/src/skf-refine-architecture/references/init.md +9 -16
  213. package/src/skf-refine-architecture/references/issue-detection.md +10 -25
  214. package/src/skf-refine-architecture/references/refinement-rules.md +4 -16
  215. package/src/skf-refine-architecture/references/report.md +14 -11
  216. package/src/skf-rename-skill/SKILL.md +11 -21
  217. package/src/skf-rename-skill/customize.toml +10 -0
  218. package/src/skf-rename-skill/references/execute.md +112 -82
  219. package/src/skf-rename-skill/references/exit-codes.md +12 -0
  220. package/src/skf-rename-skill/references/report.md +16 -8
  221. package/src/skf-rename-skill/references/select.md +69 -42
  222. package/src/skf-rename-skill/scripts/skf-validate-rename-name.py +161 -0
  223. package/src/skf-setup/SKILL.md +21 -13
  224. package/src/skf-setup/customize.toml +10 -0
  225. package/src/skf-setup/references/auto-index.md +11 -10
  226. package/src/skf-setup/references/ccc-index.md +14 -15
  227. package/src/skf-setup/references/detect-and-tier.md +10 -8
  228. package/src/skf-setup/references/report.md +26 -32
  229. package/src/skf-setup/references/tier-rules.md +2 -32
  230. package/src/skf-setup/references/write-config.md +9 -10
  231. package/src/skf-test-skill/SKILL.md +10 -8
  232. package/src/skf-test-skill/customize.toml +2 -0
  233. package/src/skf-test-skill/references/coherence-check.md +19 -31
  234. package/src/skf-test-skill/references/coverage-check.md +111 -67
  235. package/src/skf-test-skill/references/detect-mode.md +10 -41
  236. package/src/skf-test-skill/references/external-validators.md +11 -19
  237. package/src/skf-test-skill/references/init.md +39 -21
  238. package/src/skf-test-skill/references/migration-section-rules.md +4 -4
  239. package/src/skf-test-skill/references/report.md +60 -40
  240. package/src/skf-test-skill/references/score.md +32 -64
  241. package/src/skf-test-skill/references/scoring-rules.md +6 -62
  242. package/src/skf-test-skill/references/source-access-protocol.md +15 -5
  243. package/src/skf-test-skill/references/step-hard-gate.md +1 -3
  244. package/src/skf-test-skill/scripts/aggregate-coherence.py +276 -0
  245. package/src/skf-test-skill/scripts/check-metadata-coherence.py +359 -0
  246. package/src/skf-test-skill/scripts/combine-external-scores.py +190 -0
  247. package/src/skf-test-skill/scripts/compute-score.py +135 -4
  248. package/src/skf-test-skill/scripts/reconcile-coverage.py +327 -0
  249. package/src/skf-test-skill/scripts/validate-inventory.py +251 -0
  250. package/src/skf-test-skill/scripts/verify-declared-numerator.py +192 -0
  251. package/src/skf-update-skill/SKILL.md +17 -5
  252. package/src/skf-update-skill/customize.toml +11 -6
  253. package/src/skf-update-skill/references/detect-changes.md +48 -36
  254. package/src/skf-update-skill/references/health-check.md +5 -11
  255. package/src/skf-update-skill/references/init.md +40 -32
  256. package/src/skf-update-skill/references/manual-section-rules.md +1 -2
  257. package/src/skf-update-skill/references/merge-conflict-rules.md +1 -52
  258. package/src/skf-update-skill/references/merge.md +13 -57
  259. package/src/skf-update-skill/references/re-extract.md +27 -25
  260. package/src/skf-update-skill/references/report.md +14 -7
  261. package/src/skf-update-skill/references/validate.md +32 -30
  262. package/src/skf-update-skill/references/write.md +86 -51
  263. package/src/skf-update-skill/scripts/skf-new-file-diff.py +167 -0
  264. package/src/skf-verify-stack/SKILL.md +11 -21
  265. package/src/skf-verify-stack/customize.toml +12 -3
  266. package/src/skf-verify-stack/references/coverage-patterns.md +1 -29
  267. package/src/skf-verify-stack/references/coverage.md +21 -10
  268. package/src/skf-verify-stack/references/exit-codes.md +14 -0
  269. package/src/skf-verify-stack/references/health-check.md +1 -1
  270. package/src/skf-verify-stack/references/init.md +20 -25
  271. package/src/skf-verify-stack/references/integration-verification-rules.md +10 -19
  272. package/src/skf-verify-stack/references/integrations.md +44 -49
  273. package/src/skf-verify-stack/references/report.md +28 -34
  274. package/src/skf-verify-stack/references/requirements.md +3 -3
  275. package/src/skf-verify-stack/references/synthesize.md +36 -39
  276. package/src/skf-verify-stack/scripts/skf-coverage-tally.py +196 -0
  277. package/src/skf-verify-stack/scripts/skf-report-delta.py +256 -0
  278. package/src/skf-verify-stack/scripts/skf-verdict-rollup.py +258 -0
  279. package/tools/cli/lib/ui.js +3 -2
  280. package/docs/deepwiki.md +0 -89
  281. package/src/skf-rename-skill/references/rebuild-context.md +0 -110
@@ -1,9 +1,11 @@
1
1
  ---
2
2
  nextStepFile: 'rank-and-confirm.md'
3
- manifestPatterns: 'references/manifest-patterns.md'
4
3
  scanManifestsProbeOrder:
5
4
  - '{project-root}/_bmad/skf/shared/scripts/skf-scan-manifests.py'
6
5
  - '{project-root}/src/shared/scripts/skf-scan-manifests.py'
6
+ enumerateStackSkillsProbeOrder:
7
+ - '{project-root}/_bmad/skf/shared/scripts/skf-enumerate-stack-skills.py'
8
+ - '{project-root}/src/shared/scripts/skf-enumerate-stack-skills.py'
7
9
  ---
8
10
 
9
11
  <!-- Config: communicate in {communication_language}. -->
@@ -26,7 +28,7 @@ Scan the project root for dependency manifest files, parse each to extract depen
26
28
 
27
29
  **If `compose_mode` is true AND `explicit_deps` was provided in step 01:**
28
30
 
29
- Use the explicit dependency list directly. Store the explicit list as `raw_dependencies` with `source: "explicit"` and skip to [Auto-Proceed to Next Step](#5-auto-proceed-to-next-step).
31
+ Use the explicit dependency list directly. Store the explicit list as `raw_dependencies` with `source: "explicit"` and skip to [Auto-Proceed to Next Step](#4-auto-proceed-to-next-step).
30
32
 
31
33
  **If `compose_mode` is true AND `explicit_deps` was NOT provided:**
32
34
 
@@ -39,7 +41,11 @@ Discover skills in `{skills_output_folder}` using version-aware resolution — s
39
41
  **Stale manifest fallback (H6):** If a manifest entry resolves to a path that does not exist (broken `active_version`, deleted version dir, missing `SKILL.md` / `metadata.json`), do NOT HALT for that single entry. Instead:
40
42
  a. Fall back to the symlink scan (rule 2) **for that one skill only**: probe `{skills_output_folder}/{skill-name}/active/{skill-name}/SKILL.md`.
41
43
  b. If the symlink-based path resolves, use it and log a warning: `"export-manifest entry '{skill-name}' is stale — resolved via active symlink instead"`.
42
- c. If BOTH the manifest path AND the symlink path fail, only then HALT with a manifest-corruption diagnostic naming the affected skill and pointing the user at `[SKF-update-skill]` to repair.
44
+ c. If BOTH the manifest path AND the symlink path fail, only then HALT with a manifest-corruption diagnostic naming the affected skill and pointing the user at `[SKF-update-skill]` to repair. Emit the result envelope on stderr per the Result Contract in SKILL.md, then STOP:
45
+
46
+ ```
47
+ SKF_STACK_RESULT_JSON: {"status":"error","skill_package":null,"skill_name":"{project_name}-stack","stack_libraries":[],"mode":"compose","exit_code":3,"halt_reason":"resolution-failure"}
48
+ ```
43
49
 
44
50
  **Manifest JSON parse guard (B3):** Wrap the `.export-manifest.json` parse in try/except. If JSON parsing fails for any reason, fall through entirely to the `active` symlink scan (rule 2) across all skills; log a warning and validate each symlink target exists before including it.
45
51
 
@@ -53,26 +59,33 @@ Discover skills in `{skills_output_folder}` using version-aware resolution — s
53
59
 
54
60
  Maintain a **visited set keyed by `skill_dir`** (the top-level dir under `{skills_output_folder}`) while resolving. If a skill would be revisited via a circular reference (e.g., a constituent that claims another stack as dependency), skip the duplicate and log a warning `"cycle detected at {skill_dir} — skipping"`. Stack skills must not be loaded as source dependencies to avoid self-referencing loops.
55
61
 
56
- **If zero skills remain after filtering:** HALT with: "**Cannot proceed in compose-mode.** No individual skills found in `{skills_output_folder}` (after filtering stack skills). Run [CS] Create Skill or [QS] Quick Skill to generate individual skills first, then re-run [SS]."
62
+ **If zero skills remain after filtering:** HALT with: "**Cannot proceed in compose-mode.** No individual skills found in `{skills_output_folder}` (after filtering stack skills). Run [CS] Create Skill or [QS] Quick Skill to generate individual skills first, then re-run [SS]." Then emit the result envelope on stderr per the Result Contract in SKILL.md, and STOP:
63
+
64
+ ```
65
+ SKF_STACK_RESULT_JSON: {"status":"error","skill_package":null,"skill_name":"{project_name}-stack","stack_libraries":[],"mode":"compose","exit_code":3,"halt_reason":"resolution-failure"}
66
+ ```
67
+
68
+ **Deterministic metadata hashing (S13) — script-driven:** Do NOT compute `sha256` in-prompt (a model cannot reproduce a digest, so a hand-computed hash would false-diverge against step 4's script-computed hash). Invoke the same enumeration helper step 4 §0 uses to obtain every constituent's `metadata_hash` in one deterministic call:
69
+
70
+ **Resolve `{enumerateStackSkillsHelper}`** from `{enumerateStackSkillsProbeOrder}`; first existing path wins. HALT if no candidate exists.
71
+
72
+ ```bash
73
+ uv run {enumerateStackSkillsHelper} enumerate {skills_output_folder}
74
+ ```
75
+
76
+ Key the emitted `skills[].metadata_hash` (a `sha256:`-prefixed digest of the raw `metadata.json`, or `null` when no metadata.json is present) by `skills[].name` for use in rule 5 below. The script's `name` is the top-level subdirectory under `{skills_output_folder}` — i.e. the `skill_dir` captured in rule 3, not the metadata `name` — so join on `skill_dir`.
57
77
 
58
78
  For each skill found:
59
79
  1. Read `metadata.json` from the resolved version-aware path (`{skill_package}` or `{active_skill}`). **Skill-type gate (S1):** the sibling `metadata.json` MUST be present AND parseable AND contain a `skill_type` field whose value is one of the known set (`skill`, `stack`, or any future values explicitly recognised by this workflow). Directories lacking a qualifying `metadata.json`/`skill_type` are NOT treated as skills — log `"{dir_name}: not a skill (no valid metadata.json/skill_type) — excluding"` and skip.
60
80
  2. Extract: name, language, confidence_tier, source_repo, exports count, version
61
81
  3. Store the skill group directory name as `skill_dir` (the top-level name under `{skills_output_folder}`, distinct from `name` — the directory may differ from the metadata name)
62
82
  4. Store the resolved package path as `skill_package_path` for use in later steps
63
- 5. **Hash the constituent metadata at read-time (S13):** compute `sha256` of the raw `metadata.json` bytes just read, and store it in workflow state as `metadata_hash` alongside `skill_package_path`. Step-07 uses this stored hash (not a re-read) for `constituents[].metadata_hash` in `provenance-map.json`, so drift between step 2 read and step 7 write is captured.
83
+ 5. **Record the constituent metadata_hash (S13):** take this skill's `metadata_hash` from the enumerate-script inventory above (matched on `skill_dir`) and store it in workflow state alongside `skill_package_path`. The script is the single source of this hash — never hand-compute — so the step-4 drift check compares script-hash to script-hash and never false-positives on a model recomputation. Step-07 uses this stored hash (not a re-read) for `constituents[].metadata_hash` in `provenance-map.json`, so drift between step 2 read and step 7 write is captured.
64
84
  6. Store as `raw_dependencies` with source: "existing_skill"
65
85
 
66
- Display:
67
- "**Loaded {N} existing skills as dependencies.**
68
-
69
- | Skill | Language | Tier | Exports | Source |
70
- |-------|----------|------|---------|--------|
71
- | {name} | {lang} | {tier} | {count} | {repo} |
72
-
73
- **Proceeding to scope confirmation...**"
86
+ Report the `{N}` loaded skills — for each: name, language, confidence tier, export count, and source.
74
87
 
75
- Skip to [Auto-Proceed to Next Step](#5-auto-proceed-to-next-step) — the skills table above serves as the detection summary.
88
+ Skip to [Auto-Proceed to Next Step](#4-auto-proceed-to-next-step) — this loaded-skills summary serves as the detection summary.
76
89
 
77
90
  **If not compose_mode:** Continue with section 1 (existing flow).
78
91
 
@@ -84,7 +97,7 @@ Skip to [Auto-Proceed to Next Step](#5-auto-proceed-to-next-step) — the skills
84
97
 
85
98
  **Dependencies:** {explicit_deps_count} libraries provided"
86
99
 
87
- Store the explicit list as `raw_dependencies` and skip to [Display Detection Summary](#4-display-detection-summary).
100
+ Store the explicit list as `raw_dependencies` and skip to [Display Detection Summary](#3-display-detection-summary).
88
101
 
89
102
  **If no explicit list:** Continue to section 2.
90
103
 
@@ -98,7 +111,7 @@ Invoke the deterministic manifest scanner — it walks the project root, parses
98
111
  uv run {scanManifestsHelper} scan {scan_root}
99
112
  ```
100
113
 
101
- Where `{scan_root}` is the project root path. Load `{manifestPatterns}` for the ecosystem reference table that documents supported filenames, dependency keys, and normalisation rules; the script implements exactly that table (npm/pnpm/yarn, python pip/poetry/pdm, rust cargo, go modules, java/kotlin maven + gradle, ruby bundler, composer, swift package manager). Exclusion patterns (`node_modules/`, `.venv/`, `vendor/`, `dist/`, `build/`, `target/`, `.git/`, hidden dirs) are applied internally.
114
+ Where `{scan_root}` is the project root path. Load `{manifestPatternsPath}` for the ecosystem reference table that documents supported filenames, dependency keys, and normalisation rules; the script implements exactly that table (npm/pnpm/yarn, python pip/poetry/pdm, rust cargo, go modules, java/kotlin maven + gradle, ruby bundler, composer, swift package manager). Exclusion patterns (`node_modules/`, `.venv/`, `vendor/`, `dist/`, `build/`, `target/`, `.git/`, hidden dirs) are applied internally.
102
115
 
103
116
  Parse the JSON output — shape:
104
117
 
@@ -116,7 +129,11 @@ Parse the JSON output — shape:
116
129
 
117
130
  If `manifests` is empty:
118
131
 
119
- **Headless auto-cancel (S2):** If `{headless_mode}` is true, do NOT wait for user input. Emit a structured error contract `{"status":"error","skill":"skf-create-stack-skill","stage":"step 2","reason":"no manifests found, headless cannot prompt"}` on stderr and exit non-zero. Headless mode cannot proceed without an explicit dependency list.
132
+ **Headless auto-cancel (S2):** If `{headless_mode}` is true, do NOT wait for user input. Emit the result envelope on stderr per the Result Contract in SKILL.md and exit `2`. Headless mode cannot proceed without an explicit dependency list.
133
+
134
+ ```
135
+ SKF_STACK_RESULT_JSON: {"status":"error","skill_package":null,"skill_name":"{project_name}-stack","stack_libraries":[],"mode":"code","exit_code":2,"halt_reason":"no-manifests"}
136
+ ```
120
137
 
121
138
  **Interactive mode:**
122
139
 
@@ -135,21 +152,11 @@ STOP — wait for user response.
135
152
 
136
153
  Otherwise, store the parsed `manifests[]` and `total_unique` as `raw_dependencies` (dedup is already applied by the scanner), surface any `warnings[]` to the user as parse-quality notes, and inspect the `monorepo` flag: if `true`, mention the monorepo layout in the detection summary so the user can decide whether to scope the ranking to a specific package or proceed across all manifests.
137
154
 
138
- ### 4. Display Detection Summary
139
-
140
- "**Manifest detection complete.**
141
-
142
- **Manifests found:** {count}
143
- {For each manifest:}
144
- - `{file_path}` ({ecosystem}) — {dep_count} dependencies
145
-
146
- **Total unique dependencies:** {total_count}
147
- - Runtime: {runtime_count}
148
- - Dev-only: {dev_count}
155
+ ### 3. Display Detection Summary
149
156
 
150
- **Proceeding to dependency ranking...**"
157
+ Report the detected manifests (for each: path, ecosystem, dependency count) and the total unique dependency count split into runtime vs dev-only.
151
158
 
152
- ### 5. Auto-Proceed to Next Step
159
+ ### 4. Auto-Proceed to Next Step
153
160
 
154
161
  Load, read the full file and then execute `{nextStepFile}`.
155
162
 
@@ -1,7 +1,5 @@
1
1
  ---
2
2
  nextStepFile: 'validate.md'
3
- stackSkillTemplate: 'assets/stack-skill-template.md'
4
- provenanceMapSchemaPath: 'assets/provenance-map-schema.md'
5
3
  # Resolve `{atomicWriteHelper}` by probing `{atomicWriteProbeOrder}` in order
6
4
  # (installed SKF module path first, src/ dev-checkout fallback); first existing
7
5
  # path wins. HALT if neither resolves — stage/commit/flip-link/write below
@@ -49,7 +47,7 @@ Resolve `{version}` per S11 below — the primary library version in code-mode,
49
47
 
50
48
  Where the skill name is `{project_name}-stack` and `{version}` is the semver version (with build metadata stripped per `knowledge/version-paths.md`).
51
49
 
52
- **Primary library definition (S11):** In code-mode, the primary library is the dependency with the highest import count from step 3; its `version` (from the manifest) becomes `{primary_library_version}`, falling back to `1.0.0` if unavailable. In compose-mode, the stack carries its own release identity: default `{version}` to `1.0.0` (a stack-local scheme) do NOT borrow the highest constituent semver. Constituent versions are preserved in `dependencies[]`, so no information is lost, and the package no longer reads as tracking whichever constituent happened to have the highest version. The `1.0.0` default applies only to a **genuinely new** stack — see the re-composition rule below.
50
+ **Primary library definition (S11):** In code-mode, the primary library is the dependency with the highest import count from step 3; its `version` (from the manifest) becomes `{primary_library_version}`, falling back to `1.0.0` if unavailable. In compose-mode, the stack carries its own release identity: default `{version}` to `1.0.0` (a stack-local scheme) rather than borrowing the highest constituent semver. Constituent versions are preserved in `dependencies[]`, so no information is lost, and the stack's version does not track whichever constituent happens to have the highest version. The `1.0.0` default applies only to a **genuinely new** stack — see the re-composition rule below.
53
51
 
54
52
  **Re-composition versioning (S11, compose-mode):** When the S3 pre-flight resolves a `{prior_stack_version}` (re-composing a stack that already has a release line), continue that line instead of resetting — defaulting to `1.0.0` would publish a version *below* the existing release (e.g. `1.0.0` shadowing a prior `3.0.5`, a backward jump). Bump `{prior_stack_version}`:
55
53
 
@@ -62,7 +60,11 @@ Never emit a `{version}` ≤ `{prior_stack_version}`. Narrate the resolved versi
62
60
 
63
61
  "**Cannot proceed.** `{skills_output_folder}/{project_name}-stack/` exists but is not a stack skill (`skill_type={found_type}`). Rename the existing directory or choose a different `project_name` to avoid collision."
64
62
 
65
- Do NOT proceed to staging or commit.
63
+ Do NOT proceed to staging or commit. Emit the result envelope on stderr per the Result Contract in SKILL.md and exit `4` (`stack_libraries` carries the confirmed library names; nothing was committed, so `skill_package` is `null`):
64
+
65
+ ```
66
+ SKF_STACK_RESULT_JSON: {"status":"error","skill_package":null,"skill_name":"{project_name}-stack","stack_libraries":["<confirmed-lib>", "..."],"mode":"{code|compose}","exit_code":4,"halt_reason":"write-failure"}
67
+ ```
66
68
 
67
69
  If that metadata exists and `skill_type == "stack"`, this run is a **re-composition**: capture its `version` as `{prior_stack_version}` and its `libraries` array as `{prior_libraries}` for the S11 re-composition rule above. If the group dir is absent — or exists but has no resolvable `active` stack metadata — treat this as a new stack and leave `{prior_stack_version}` unset.
68
70
 
@@ -92,7 +94,11 @@ mkdir -p {forge_version}
92
94
  python3 {atomicWriteHelper} commit-dir --rollback --target {skill_package}
93
95
  ```
94
96
 
95
- Then abort with a structured error contract (see B7): purge any `{forge_version}/*-tmp` staging artifacts, emit `{"status":"error","skill":"skf-create-stack-skill","stage":"step 7","reason":"<message>"}` on stderr, and halt the workflow.
97
+ Then abort (see B7): purge any `{forge_version}/*-tmp` staging artifacts, emit the result envelope on stderr per the Result Contract in SKILL.md, and halt the workflow. This is the single rollback exit shared by §7 (workspace-write failure) and §9 (commit-dir failure):
98
+
99
+ ```
100
+ SKF_STACK_RESULT_JSON: {"status":"error","skill_package":null,"skill_name":"{project_name}-stack","stack_libraries":["<confirmed-lib>", "..."],"mode":"{code|compose}","exit_code":4,"halt_reason":"write-failure"}
101
+ ```
96
102
 
97
103
  ### 2. Stage SKILL.md
98
104
 
@@ -102,20 +108,20 @@ Write the approved `skill_content` from step 06 to `{skill_staging}/SKILL.md` (r
102
108
 
103
109
  For each confirmed library, write `{skill_staging}/references/{library_name}.md`:
104
110
 
105
- Load structure from `{stackSkillTemplate}` references section:
111
+ Load structure from `{stackSkillTemplatePath}` references section:
106
112
  - Library name, version from manifest (**in compose-mode**: version from source skill `metadata.json`)
107
113
  - Import count and file count (**in compose-mode**: export count from source skill metadata)
108
114
  - Key exports with signatures
109
115
  - Usage patterns with file:line citations (**in compose-mode**: usage patterns from source skill SKILL.md)
110
116
  - Confidence tier label
111
117
 
112
- **If the catalog was extracted** (large stack — step 06 §4 placed the `Library Reference Index` + `Per-Library Summaries` out of SKILL.md), also write `{skill_staging}/references/stack-catalog.md` using the structure in `{stackSkillTemplate}`, and confirm SKILL.md carries the inline pointer instead of the two sections. Small stacks keep the catalog inline and write no `stack-catalog.md`.
118
+ **If the catalog was extracted** (large stack — step 06 §4 placed the `Library Reference Index` + `Per-Library Summaries` out of SKILL.md), also write `{skill_staging}/references/stack-catalog.md` using the structure in `{stackSkillTemplatePath}`, and confirm SKILL.md carries the inline pointer instead of the two sections. Small stacks keep the catalog inline and write no `stack-catalog.md`.
113
119
 
114
120
  ### 4. Stage Integration Pair Reference Files
115
121
 
116
122
  For each detected integration pair, write `{skill_staging}/references/integrations/{libraryA}-{libraryB}.md`:
117
123
 
118
- Load structure from `{stackSkillTemplate}` integrations section:
124
+ Load structure from `{stackSkillTemplatePath}` integrations section:
119
125
  - Library pair and integration type
120
126
  - Co-import file count
121
127
  - Integration pattern description with file:line citations
@@ -131,7 +137,7 @@ Write `{skill_staging}/context-snippet.md`:
131
137
  Use the Vercel-aligned indexed format targeting **~80-120 tokens** (M2). Token estimation is heuristic — use `ceil(char_count / 4)` as the working approximation (the standard rule-of-thumb for English text in BPE-style tokenizers; precise counts differ per model). Compute against the rendered snippet body (excluding trailing newline).
132
138
 
133
139
  ```
134
- [{project_name}-stack v{version — per S11: code-mode primary_library_version or 1.0.0; compose-mode stack-local scheme — 1.0.0 for a new stack, or the bumped {prior_stack_version} on re-composition}]|root: skills/{project_name}-stack/
140
+ [{project_name}-stack v{version — resolved in §1}]|root: skills/{project_name}-stack/
135
141
  |IMPORTANT: {project_name}-stack — read SKILL.md before writing integration code. Do NOT rely on training data.
136
142
  |stack: {dep-1}@{v1}, {dep-2}@{v2}, {dep-3}@{v3}
137
143
  |integrations: {pattern-1}, {pattern-2}
@@ -151,52 +157,12 @@ If the snippet is still over budget after step 4, log a warning to workflow_warn
151
157
 
152
158
  ### 6. Stage metadata.json
153
159
 
154
- Write `{skill_staging}/metadata.json`:
155
-
156
- Populate all fields from the metadata.json schema defined in `{stackSkillTemplate}`.
160
+ Write `{skill_staging}/metadata.json`, populating every field from the metadata.json schema in `{stackSkillTemplatePath}` (loaded in §3) — that template is the single schema source; do not re-transcribe it here. Resolve the field values whose template placeholders don't spell out the rule:
157
161
 
158
- **Tier fields:**
162
+ - `version` — the `{version}` resolved in §1 (not the template's literal `1.0.0`, which is only the new-stack default).
159
163
  - `forge_tier` — the run tier (Quick/Forge/Forge+/Deep) resolved in step 1.
160
164
  - `confidence_tier` — the dominant T-code from `confidence_distribution`. Pick the tier with the highest count; resolve ties toward the weaker tier (T1-low > T1, T2 > T1-low, T3 > T2) so the reported value never overstates confidence. When `confidence_distribution` is empty (no libraries extracted), emit `"T1-low"` as the conservative default.
161
-
162
- ```json
163
- {
164
- "skill_type": "stack",
165
- "name": "{project_name}-stack",
166
- "version": "{version — resolved per S11: code-mode primary_library_version or 1.0.0; compose-mode 1.0.0 (new stack) or bumped {prior_stack_version} (re-composition)}",
167
- "generation_date": "{current_date}",
168
- "forge_tier": "{Quick|Forge|Forge+|Deep — the tier under which this run executed}",
169
- "confidence_tier": "{T1|T1-low|T2|T3 — dominant T-code from confidence_distribution below}",
170
- "spec_version": "1.3",
171
- "source_authority": "{official|community|internal — use the lowest authority among constituent skills}",
172
- "generated_by": "create-stack-skill",
173
- "exports": [],
174
- "library_count": N,
175
- "integration_count": N,
176
- "libraries": ["lib1", "lib2"],
177
- "integration_pairs": [["lib1", "lib2"]],
178
- "language": "{primary language or list of languages from constituent skills}",
179
- "ast_node_count": "{number or omit if no AST extraction performed}",
180
- "confidence_distribution": {"t1": N, "t1_low": N, "t2": N, "t3": N},
181
- "tool_versions": {
182
- "ast_grep": "{version or null}",
183
- "qmd": "{version or null}",
184
- "skf": "{skf_version}"
185
- },
186
- "stats": {
187
- "exports_documented": N,
188
- "exports_public_api": N,
189
- "exports_internal": N,
190
- "exports_total": N,
191
- "public_api_coverage": 0.0,
192
- "total_coverage": 0.0,
193
- "scripts_count": N,
194
- "assets_count": N
195
- },
196
- "dependencies": [],
197
- "compatibility": "{semver-range}"
198
- }
199
- ```
165
+ - `source_authority` — the lowest authority among constituent skills (official > community > internal).
200
166
 
201
167
  ### 7. Write Forge Data Artifacts (Workspace)
202
168
 
@@ -216,7 +182,7 @@ Use the schema from `{provenanceMapSchemaPath}` — see that asset for the canon
216
182
  - **In code-mode:** use the code-mode variant (`source_repo` / `source_commit` populated; `extraction_method` ∈ `ast_bridge|source_reading|qmd_bridge`; `detection_method = "co-import grep"`).
217
183
  - **In compose-mode:** use the compose-mode variant (source-anchor fields `null`; `extraction_method = "compose-from-skill"`; `detection_method ∈ "architecture_co_mention|constituent_documented_contract|inferred_from_shared_domain"`; includes the additional `constituents[]` array for drift detection).
218
184
 
219
- **Use the `metadata_hash` value already stored in workflow state during step 2 (S13) do NOT re-read and re-hash at step 7 time. The stored hash captures the state as it was at manifest-detection time, which is the correct provenance anchor.**
185
+ Populate compose-mode `constituents[].metadata_hash` from the value stored in workflow state at step 2 (S13), not a fresh re-hash at step-7 time `{provenanceMapSchemaPath}` carries the rationale for why the manifest-detection-time hash is the correct provenance anchor.
220
186
 
221
187
  **evidence-report.md:**
222
188
  - Extraction summary per library
@@ -226,9 +192,9 @@ Use the schema from `{provenanceMapSchemaPath}` — see that asset for the canon
226
192
 
227
193
  ### 8. Pre-Commit Frontmatter & Body-Size Gate
228
194
 
229
- The full schema/frontmatter validation runs in step 8 (`validate.md`) — but that runs *after* commit-dir and flip-link have already published the package. The most common non-auto-fixable `skill-check` hard rejects — a `description` over the 1024-char limit (which `skill-check --fix` cannot trim for you), a SKILL.md body over the `body.max_lines` limit (default **500**), and a body exceeding the `body.max_tokens` limit (default **5000**) — would therefore only surface on an already-committed, symlink-active artifact, forcing edits to the live `SKILL.md`. Additive re-composition of an already-large stack grows the body monotonically, so body overflow (lines or tokens) is the likeliest trigger. Catch all three here, while the package is still in `.skf-tmp`.
195
+ The full schema/frontmatter validation runs in step 8 (`validate.md`) — but that runs *after* commit-dir and flip-link have already published the package. The most common non-auto-fixable `skill-check` hard rejects — a `description` over the 1024-char limit (which `skill-check --fix` cannot trim for you) and a SKILL.md body over the `body.max_lines` limit (default **500**) — would therefore only surface on an already-committed, symlink-active artifact, forcing edits to the live `SKILL.md`. `skill-check` also *warns* (non-blocking) when the body exceeds `body.max_tokens` (default **5000**). Additive re-composition of an already-large stack grows the body monotonically, so body overflow is the likeliest trigger. Catch these here, while the package is still in `.skf-tmp`.
230
196
 
231
- Resolve `{frontmatterValidator}` from `{frontmatterValidatorProbeOrder}` (first existing path wins). Run it against the **staged** `SKILL.md`, passing the real skill name so the directory-match check is not fooled by the `.skf-tmp` staging suffix, `--max-body-lines 500` to assert the skill-check body-line limit, and `--max-body-tokens 5000` to assert the skill-check body-token limit pre-commit:
197
+ Resolve `{frontmatterValidator}` from `{frontmatterValidatorProbeOrder}` (first existing path wins). Run it against the **staged** `SKILL.md`, passing the real skill name so the directory-match check is not fooled by the `.skf-tmp` staging suffix, `--max-body-lines 500` to assert the skill-check body-line limit, and `--max-body-tokens 5000` to surface the skill-check body-token *warning* pre-commit (advisory — see disposition below):
232
198
 
233
199
  ```bash
234
200
  uv run {frontmatterValidator} {skill_staging}/SKILL.md --skill-dir-name {project_name}-stack --max-body-lines 500 --max-body-tokens 5000
@@ -238,10 +204,10 @@ The validator emits JSON: `status` (`pass`/`warn`/`fail`), `issues[]` (each with
238
204
 
239
205
  - **`status` is `fail`, OR any `issues[]` entry has `severity` `high` or `medium`** — a hard violation that `npx skill-check` (step 8) would reject and `--fix` cannot auto-correct. HALT-to-fix **in staging**, then re-run the validator until it clears. Remediate by `field`:
240
206
  - `description` / `name` / `compatibility` — trim/correct `{skill_staging}/SKILL.md` (e.g. shorten `description` to ≤ 1024 chars).
241
- - `body` (`body lines N exceeds max 500` or `body token estimate N exceeds max 5000`) — reduce the staged body: prefer a **selective split** of the largest Tier-2 section(s) into `{skill_staging}/references/`, keeping Tier-1 content inline (mirrors `validate.md` §3); or trim redundant content. Re-run the gate until both `body_lines ≤ 500` and `body_tokens 5000`.
207
+ - `body` (`body lines N exceeds max 500`) — reduce the staged body: prefer a **selective split** of the largest Tier-2 section(s) into `{skill_staging}/references/`, keeping Tier-1 content inline (mirrors `validate.md` §3); or trim redundant content. Re-run the gate until `body_lines ≤ 500`. (An over-`body_tokens` estimate is advisory, not a hard stop — see the low-severity note below.)
242
208
 
243
209
  Do NOT proceed to §9 commit-dir with an unresolved high/medium issue. Note: an over-long `description` is rated `medium` and exits `0`, so key the HALT on the issue severities above — not on the exit code.
244
- - **Only `low`-severity issues (e.g. an unexpected field)** — record each as a WARNING in the evidence report and proceed; these do not block the commit.
210
+ - **Only `low`-severity issues (e.g. an unexpected field, or a `body token estimate N exceeds max 5000` advisory)** — record each as a WARNING in the evidence report and proceed; these do not block the commit. The body-token estimate is a char/4 heuristic that runs higher than `skill-check`'s own whitespace-split count, and `skill-check` treats `body.max_tokens` as a non-blocking warning — so an over-token estimate is advisory here, not a HALT (the `body.max_lines` gate above remains the hard body pre-check).
245
211
 
246
212
  **If `{frontmatterValidator}` does not resolve** (neither probe path exists) **or the invocation cannot run**, emit a WARNING ("pre-commit frontmatter + body-size gate skipped — validator unavailable") and proceed. Step 8 (`validate.md`) remains the post-commit backstop (including the `body.max_lines` split path in its §3); this gate is a best-effort early catch, never a new hard dependency.
247
213
 
@@ -269,24 +235,7 @@ If `flip-link` fails, emit a warning (the committed package is still valid), not
269
235
 
270
236
  ### 11. Display Write Summary
271
237
 
272
- "**Output files written.**
273
-
274
- **Deliverables** ({skill_package}):
275
- - SKILL.md ({line_count} lines)
276
- - context-snippet.md ({token_estimate} tokens)
277
- - metadata.json
278
- - references/ -- {lib_count} library files
279
- - references/integrations/ -- {pair_count} integration files
280
-
281
- **Workspace** ({forge_version}):
282
- - provenance-map.json
283
- - evidence-report.md
284
-
285
- **Symlink:** {skill_group}/active -> {version}
286
-
287
- **Total files written:** {total_count}
288
-
289
- **Proceeding to validation...**"
238
+ Report the files written: the `{skill_package}` deliverables (SKILL.md with `{line_count}` lines, context-snippet.md with `{token_estimate}` tokens, metadata.json, `references/` `{lib_count}` library files, `references/integrations/` `{pair_count}` integration files), the `{forge_version}` workspace (provenance-map.json, evidence-report.md), the `{skill_group}/active -> {version}` symlink, and the `{total_count}` total.
290
239
 
291
240
  ### 12. Auto-Proceed to Next Step
292
241
 
@@ -27,74 +27,12 @@ Before anything else, load `{project-root}/_bmad/skf/config.yaml`. If the file i
27
27
 
28
28
  **Halting workflow.**"
29
29
 
30
- STOP — do not proceed.
30
+ Then emit the result envelope on stderr per the Result Contract in SKILL.md (`project_name` is unresolved here, so `skill_name` is `null`), and STOP — do not proceed:
31
31
 
32
- ### 0b. Resume Check
33
-
34
- Before any further init work, check for an interrupted prior run.
35
-
36
- **Probe path.** Resolve `{resume_skill_name}` as `{project_name}-stack` (the same skill name used at step 7) and probe `{forge_data_folder}/{resume_skill_name}/in-progress.json`. (The file lives at the version-agnostic skill root so it can be found before `{version}` resolution.)
37
-
38
- **If no in-progress.json exists:** Continue to §1.
39
-
40
- **If in-progress.json exists:** Load and parse it. Read `last_completed_step` and `started_at` (ISO-8601 timestamp). Surface a soft gate:
41
-
42
- "**Resume previous run?**
43
-
44
- Found a previous in-progress run at `{forge_data_folder}/{resume_skill_name}/in-progress.json` from {started_at}, last completed at step {last_completed_step}.
45
-
46
- - **[C] Continue** (recommended) — resume from the next step after {last_completed_step}, restoring saved workflow state.
47
- - **[F] Fresh** — archive the existing in-progress.json (rename to `in-progress.{timestamp}.json`) and start over from step 1.
48
- - **[X] Cancel and exit** — leave the in-progress.json untouched and halt.
49
-
50
- Select [C/F/X]:"
51
-
52
- **Headless default:** `[C]` Continue.
53
-
54
- **On [C] Continue:**
55
- 1. Restore workflow context from in-progress.json fields: `last_completed_step`, `workflow_state` (mode, tier, scope), and any accumulator fields (partial extractions, ranked libraries, integration pairs, compile-stack output) that the writing step persisted.
56
- 2. Determine the resume target: the step file that runs immediately after `last_completed_step`.
57
- 3. Jump directly to that step file by loading and executing it (skip the remaining §0b–§5 init substeps for this run).
58
-
59
- **On [F] Fresh:**
60
- 1. Compute `{archive_timestamp}` as the current UTC time in `YYYYMMDDTHHMMSSZ` form.
61
- 2. Rename `{forge_data_folder}/{resume_skill_name}/in-progress.json` → `{forge_data_folder}/{resume_skill_name}/in-progress.{archive_timestamp}.json`.
62
- 3. Continue with §1 of this file as if no prior run existed.
63
-
64
- **On [X] Cancel and exit:** HARD HALT with exit code 6 (user-cancelled). Do NOT modify the in-progress.json. Emit the result envelope on stderr per the Result Contract in SKILL.md:
65
-
66
- ```
67
- SKF_STACK_RESULT_JSON: {"status":"error","skill_package":null,"skill_name":"{resume_skill_name}","stack_libraries":[],"mode":null,"exit_code":6,"halt_reason":"user-cancelled"}
68
32
  ```
69
-
70
- **in-progress.json schema (read side).** This PR wires only the READ side of the resume protocol. The WRITE side — each stage step persisting an updated in-progress.json after it completes — is deferred to a follow-up PR. When write-side wiring lands, each step writes the file via `skf-atomic-write.py write` at the end of its mandatory sequence with this shape:
71
-
72
- ```json
73
- {
74
- "schema_version": "1.0",
75
- "skill_name": "{project_name}-stack",
76
- "started_at": "{ISO-8601 of step 1 start}",
77
- "updated_at": "{ISO-8601 of most recent step completion}",
78
- "last_completed_step": "step-NN",
79
- "workflow_state": {
80
- "mode": "code|compose",
81
- "forge_tier": "Quick|Forge|Forge+|Deep",
82
- "headless_mode": false,
83
- "scope": {"explicit_deps": [], "scope_overrides": {}, "architecture_doc_path": null}
84
- },
85
- "accumulators": {
86
- "manifests": [],
87
- "ranked_libraries": [],
88
- "extractions": {},
89
- "integration_pairs": [],
90
- "compiled_stack": null,
91
- "workflow_warnings": []
92
- }
93
- }
33
+ SKF_STACK_RESULT_JSON: {"status":"error","skill_package":null,"skill_name":null,"stack_libraries":[],"mode":null,"exit_code":2,"halt_reason":"config-missing"}
94
34
  ```
95
35
 
96
- Until the write side is wired, in-progress.json will not naturally appear and §0b will fall through to §1 on every run. The resume gate is a no-op until that follow-up lands.
97
-
98
36
  ### 1. Load Forge Tier Configuration
99
37
 
100
38
  Load `{forgeTierFile}` from the Ferris sidecar.
@@ -107,7 +45,11 @@ Load `{forgeTierFile}` from the Ferris sidecar.
107
45
 
108
46
  **Halting workflow.**"
109
47
 
110
- STOP — do not proceed.
48
+ Then emit the result envelope on stderr per the Result Contract in SKILL.md (config loaded, so `skill_name` is known; `mode` is not yet resolved), and STOP — do not proceed:
49
+
50
+ ```
51
+ SKF_STACK_RESULT_JSON: {"status":"error","skill_package":null,"skill_name":"{project_name}-stack","stack_libraries":[],"mode":null,"exit_code":3,"halt_reason":"forge-tier-missing"}
52
+ ```
111
53
 
112
54
  **If forge-tier.yaml exists:**
113
55
 
@@ -156,6 +98,7 @@ Skills use version-nested directories — see `knowledge/version-paths.md` for t
156
98
  - If user provides an architecture document path for composition or explicitly requests compose mode → set `compose_mode: true` and store `architecture_doc_path`
157
99
  - If no manifest files exist in project root AND at least one skill is discoverable in `{skills_output_folder}` → suggest compose mode to the user and ask for optional architecture document path
158
100
  - **Skill discovery (version-aware):** First, read `{skills_output_folder}/.export-manifest.json` — each entry in `exports` names a skill with an `active_version`, which resolves to `{skills_output_folder}/{skill-name}/{active_version}/{skill-name}/` containing `SKILL.md` and `metadata.json`. If the export manifest does not exist or is empty, fall back to scanning for `active` symlinks: check `{skills_output_folder}/*/active/*/SKILL.md` — each match indicates a skill whose package lives at `{skills_output_folder}/{skill-name}/active/{skill-name}/` (the `{active_skill}` template).
101
+ - **Headless default (B8):** If `{headless_mode}` is true, do NOT prompt — auto-accept the suggestion: set `compose_mode: true` and `architecture_doc_path: null` (unless an architecture doc path was supplied via the optional inputs above). This is the constructive default: with no manifests present, code-mode would only halt at step 2 (`no-manifests`), so compose is the sole path that produces output. Log the auto-decision by appending to `workflow_warnings[]`: `{step: "step-01", severity: "info", code: "headless-compose-autodetect", message: "no manifests + {N} discoverable skills — auto-selected compose mode", context: {discoverable_skills: {N}}}`.
159
102
  - If user accepts → set `compose_mode: true` and store `architecture_doc_path` (may be `null` if user chose not to provide one)
160
103
  - If user declines → `compose_mode` remains `false`, continue with code-mode
161
104
 
@@ -166,22 +109,7 @@ If no optional inputs provided, auto-detection will be used.
166
109
 
167
110
  ### 4. Display Initialization Summary
168
111
 
169
- "**Stack Skill Forge initialized.**
170
-
171
- **Project:** {project_name}
172
- **Forge Tier:** {forge_tier} — {tier_description}
173
-
174
- Where tier_description follows positive capability framing:
175
- - Quick: "Source reading and import counting"
176
- - Forge: "AST-backed structural analysis"
177
- - Forge+: "AST structural + CCC semantic co-import augmentation"
178
- - Deep: "Full intelligence — structural + contextual + temporal"
179
-
180
- **Available Tools:** {tool_list}
181
- **Input Mode:** {auto-detect | explicit dependency list | compose mode}
182
-
183
- **If compose mode:** Proceeding to skill loading...
184
- **If code mode:** Proceeding to manifest detection..."
112
+ Report that the Stack Skill Forge is initialized, naming: the project (`{project_name}`); the forge tier (`{forge_tier}`) with its positive-capability framing (Quick = source reading and import counting; Forge = AST-backed structural analysis; Forge+ = AST structural + CCC semantic co-import augmentation; Deep = full intelligence — structural + contextual + temporal); the available tools (`{tool_list}`); and the resolved input mode (auto-detect, explicit dependency list, or compose mode).
185
113
 
186
114
  ### 5. Auto-Proceed to Next Step
187
115
 
@@ -15,41 +15,11 @@
15
15
  | PHP | composer.json | require, require-dev | `use ...`, `require_once` |
16
16
  | .NET | *.csproj | PackageReference | `using ...` |
17
17
 
18
- ## Detection Priority
19
-
20
- 1. Search project root for manifest files (depth 0-1)
21
- 2. Parse each found manifest to extract dependency names
22
- 3. Normalize names across ecosystems (e.g., `@scope/package` `package`)
23
- 4. Deduplicate across multiple manifests
24
-
25
- ## Scan Exclusion Patterns
26
-
27
- When scanning for manifest files, ALWAYS exclude these directories from glob results:
28
-
29
- **Dependency/Vendor Directories:**
30
- - `node_modules/`
31
- - `.venv/` / `venv/` / `.env/`
32
- - `vendor/` (PHP Composer, Go modules)
33
- - `Pods/` (iOS CocoaPods)
34
-
35
- **Build Output Directories:**
36
- - `dist/` / `build/` / `out/`
37
- - `target/` (Rust, Java/Maven)
38
- - `__pycache__/`
39
- - `.next/` / `.nuxt/` / `.output/`
40
-
41
- **Hidden and VCS Directories:**
42
- - `.git/`
43
- - Any directory starting with `.` (except project root hidden config files like `.csproj`)
44
-
45
- **Monorepo Note:** For monorepo structures (e.g., `packages/*/package.json`), the depth 0-1 scan rule already limits scope. If monorepo manifest detection is needed at deeper levels, these exclusions become critical to prevent scanning dependency trees within each package.
46
-
47
- ## Filtering Rules
48
-
49
- - Exclude dev-only dependencies unless they appear in production imports
50
- - Exclude build tools (webpack, babel, eslint, etc.) unless significantly imported
51
- - Include all runtime dependencies by default
52
- - Flag transitive dependencies that appear in direct imports
18
+ <!-- Manifest scanning, name normalization, dedup, exclusion-dir filtering, and
19
+ dev/build-tool filtering are performed by `skf-scan-manifests.py` (invoked in
20
+ detect-manifests.md §2), which implements exactly the ecosystem table above.
21
+ This file is loaded only for that reference table and the import-counting
22
+ exclusions below see the script's `--help` for the operative scan contract. -->
53
23
 
54
24
  ## Import Counting
55
25
 
@@ -60,7 +60,11 @@ The script emits JSON of the form:
60
60
  }
61
61
  ```
62
62
 
63
- Cache this result as `stack_skill_inventory` in workflow state — the per-skill subagent fan-out at §1+ MUST read from this cache rather than re-reading each skill's `SKILL.md` / `metadata.json` / `references/` to determine exports. Append every entry in `warnings[]` to workflow state for the evidence report (the script already labels them per-skill, e.g. `"<skill-name>: no exports found via any resolution path"`). For every entry in `cycles[]`, halt with a structured-error contract on stderra composes-cycle makes the stack unbuildable.
63
+ Cache this result as `stack_skill_inventory` in workflow state — the per-skill subagent fan-out at §1+ MUST read from this cache rather than re-reading each skill's `SKILL.md` / `metadata.json` / `references/` to determine exports. Append every entry in `warnings[]` to workflow state for the evidence report (the script already labels them per-skill, e.g. `"<skill-name>: no exports found via any resolution path"`). If `cycles[]` is non-empty, a composes-cycle makes the stack unbuildable emit the result envelope on stderr per the Result Contract in SKILL.md and exit `3`:
64
+
65
+ ```
66
+ SKF_STACK_RESULT_JSON: {"status":"error","skill_package":null,"skill_name":"{project_name}-stack","stack_libraries":[],"mode":"compose","exit_code":3,"halt_reason":"resolution-failure"}
67
+ ```
64
68
 
65
69
  Build a `per_library_extractions[]` entry for each skill by reading from the cached inventory:
66
70
  - `library`: `inventory.skills[i].name`
@@ -70,15 +74,7 @@ Build a `per_library_extractions[]` entry for each skill by reading from the cac
70
74
  - `metadata_hash`: `inventory.skills[i].metadata_hash` — record for step 7 provenance (null when exports came from references/ or SKILL.md prose).
71
75
  - `usage_patterns`: populated by the §1+ per-skill subagent fan-out, NOT by this script. The script provides the inventory + exports; the subagent does the per-skill usage analysis. They're complementary.
72
76
 
73
- Display an extraction summary:
74
-
75
- "**Loaded {N} skill extractions from existing skills.**
76
-
77
- | Skill | Exports | Confidence | Status |
78
- |-------|---------|------------|--------|
79
- | {name} | {count} | {tier} | Loaded |"
80
-
81
- Auto-proceed to next step.
77
+ Report the loaded extractions — for each skill: export count, confidence tier, and load status. Then auto-proceed to the next step.
82
78
 
83
79
  **If not compose_mode:** Continue with section 1 (existing flow).
84
80
 
@@ -177,26 +173,15 @@ For each library extraction:
177
173
  **If ALL extractions fail:** HALT — cannot produce meaningful stack skill. Before halting (B7):
178
174
 
179
175
  1. Purge any in-flight staging artifacts under the forge workspace: remove `{forge_data_folder}/{project_name}-stack/{version}/*-tmp` and any `{forge_data_folder}/{project_name}-stack/{version}/*.skf-tmp` directories so partial state does not linger.
180
- 2. Emit a structured error contract on stderr: `{"status":"error","skill":"skf-create-stack-skill","stage":"step 4","reason":"all extractions failed","libraries":[...]}`.
181
- 3. Exit with a non-zero status so headless pipelines detect the failure.
182
-
183
- ### 4. Display Extraction Summary
176
+ 2. Emit the result envelope on stderr per the Result Contract in SKILL.md (`stack_libraries` carries the confirmed library names that failed extraction), and exit `2`:
184
177
 
185
- "**Library extraction complete.**
178
+ ```
179
+ SKF_STACK_RESULT_JSON: {"status":"error","skill_package":null,"skill_name":"{project_name}-stack","stack_libraries":["<confirmed-lib>", "..."],"mode":"{code|compose}","exit_code":2,"halt_reason":"all-extractions-failed"}
180
+ ```
186
181
 
187
- | Library | Exports | Patterns | Confidence | Status |
188
- |---------|---------|----------|------------|--------|
189
- | {name} | {count} | {count} | {tier} | ✓ |
190
- | {name} | {count} | {count} | {tier} | ✓ |
191
- | {name} | — | — | — | ⚠ partial |
192
-
193
- **Results:** {success_count}/{total_count} libraries extracted
194
- **Confidence distribution:** T1: {count}, T1-low: {count}, T2: {count}
195
- {If Deep tier:} **T2 enrichment:** {enriched_count}/{total_count} libraries had temporal collections available
196
- {If libraries without temporal > 0:} **Tip:** Run [CS] Create Skill at Deep tier for individual libraries to generate temporal collections, then re-run [SS] for full T2 enrichment.
197
- {If warnings:} **Warnings:** {warning_count} issues noted
182
+ ### 4. Display Extraction Summary
198
183
 
199
- **Proceeding to integration detection...**"
184
+ Report the extraction results: per library the export count, pattern count, confidence tier, and success/partial status; the overall `{success_count}/{total_count}` extracted; and the T1 / T1-low / T2 confidence distribution. At Deep tier, add the T2-enrichment count (`{enriched_count}/{total_count}` libraries with temporal collections available); and if any library lacked a temporal collection, add the tip: run **[CS] Create Skill** at Deep tier for those libraries to generate temporal collections, then re-run **[SS]** for full T2 enrichment. Note any warning count.
200
185
 
201
186
  ### 5. Auto-Proceed to Next Step
202
187
 
@@ -56,7 +56,7 @@ Use ecosystem-appropriate import patterns:
56
56
  - Python: `import library`, `from library import`
57
57
  - Rust: `use library::`, `extern crate library`
58
58
  - Go: `"library"` in import blocks
59
- - (Match patterns from manifest-patterns.md)
59
+ - (Match patterns from `{manifestPatternsPath}`)
60
60
 
61
61
  **Subprocess returns:** `{library_name: import_count, files: [file_paths]}` for each dependency.
62
62
 
@@ -112,13 +112,13 @@ Apply additions/exclusions, display updated list, and ask for final confirmation
112
112
  **If custom list provided:**
113
113
  Use the custom list as `confirmed_dependencies`.
114
114
 
115
- Display final confirmation:
115
+ Display the resolved scope:
116
116
 
117
117
  "**Scope confirmed:** {count} libraries selected for stack skill extraction.
118
118
 
119
- {List confirmed libraries}
119
+ {List confirmed libraries}"
120
120
 
121
- **Proceeding to parallel extraction...**"
121
+ The extraction itself begins only once the user clears the gate below.
122
122
 
123
123
  ### 5. Present MENU OPTIONS
124
124
 
@@ -126,9 +126,9 @@ Display: **Select:** [C] Continue to Extraction | [X] Cancel and exit
126
126
 
127
127
  #### EXECUTION RULES:
128
128
 
129
- - ALWAYS halt and wait for user input after presenting scope
129
+ - This is a confirmation gate — advancing without the user's `C` would extract and ship a stack scope they never approved. Halt and wait for input after presenting scope.
130
130
  - **GATE [default: C]** — If `{headless_mode}`: auto-proceed with [C] Continue (accept all ranked libraries), log: "headless: auto-confirm library scope"
131
- - ONLY proceed to next step when user confirms scope and selects 'C'
131
+ - Proceed to the next step only once the user confirms scope by selecting `C`.
132
132
 
133
133
  #### Menu Handling Logic:
134
134