bmad-module-skill-forge 2.0.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 (235) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.nvmrc +1 -1
  3. package/docs/_data/pinned.yaml +1 -1
  4. package/package.json +2 -2
  5. package/src/knowledge/skill-lifecycle.md +1 -1
  6. package/src/module-help.csv +2 -2
  7. package/src/shared/scripts/skf-comention-pairs.py +350 -0
  8. package/src/shared/scripts/skf-count-tokens.py +222 -0
  9. package/src/shared/scripts/skf-detect-docs.py +232 -1
  10. package/src/shared/scripts/skf-detect-language.py +77 -0
  11. package/src/shared/scripts/skf-detect-tools.py +105 -2
  12. package/src/shared/scripts/skf-enumerate-stack-skills.py +111 -2
  13. package/src/shared/scripts/skf-find-cycles.py +246 -0
  14. package/src/shared/scripts/skf-hash-content.py +487 -2
  15. package/src/shared/scripts/skf-manifest-ops.py +67 -1
  16. package/src/shared/scripts/skf-rebuild-managed-sections.py +180 -0
  17. package/src/shared/scripts/skf-recommend-scope-type.py +1 -2
  18. package/src/shared/scripts/skf-render-metadata-stats.py +499 -0
  19. package/src/shared/scripts/skf-rewrite-skill-name.py +308 -0
  20. package/src/shared/scripts/skf-shard-body.py +461 -0
  21. package/src/shared/scripts/skf-skill-inventory.py +139 -3
  22. package/src/shared/scripts/skf-structural-diff.py +307 -67
  23. package/src/shared/scripts/skf-validate-brief-schema.py +39 -1
  24. package/src/shared/scripts/skf-validate-feasibility-report.py +234 -0
  25. package/src/shared/scripts/skf-validate-frontmatter.py +17 -12
  26. package/src/shared/scripts/skf-validate-output.py +443 -10
  27. package/src/shared/scripts/skf-validate-pins.py +1 -1
  28. package/src/shared/scripts/skf-verify-no-trace.py +214 -0
  29. package/src/shared/scripts/skf-verify-provenance-completeness.py +439 -0
  30. package/src/skf-analyze-source/SKILL.md +17 -32
  31. package/src/skf-analyze-source/customize.toml +2 -0
  32. package/src/skf-analyze-source/references/auto-docs-only.md +116 -0
  33. package/src/skf-analyze-source/references/continue.md +8 -13
  34. package/src/skf-analyze-source/references/generate-briefs.md +28 -12
  35. package/src/skf-analyze-source/references/headless-contract.md +33 -0
  36. package/src/skf-analyze-source/references/health-check.md +1 -2
  37. package/src/skf-analyze-source/references/identify-units.md +25 -36
  38. package/src/skf-analyze-source/references/init.md +12 -25
  39. package/src/skf-analyze-source/references/map-and-detect.md +8 -20
  40. package/src/skf-analyze-source/references/recommend.md +4 -14
  41. package/src/skf-analyze-source/references/scan-project.md +3 -11
  42. package/src/skf-analyze-source/references/step-auto-scope.md +42 -180
  43. package/src/skf-analyze-source/references/unit-detection-heuristics.md +2 -2
  44. package/src/skf-audit-skill/SKILL.md +9 -6
  45. package/src/skf-audit-skill/customize.toml +2 -0
  46. package/src/skf-audit-skill/references/init.md +58 -32
  47. package/src/skf-audit-skill/references/re-index.md +15 -34
  48. package/src/skf-audit-skill/references/report.md +11 -58
  49. package/src/skf-audit-skill/references/semantic-diff.md +4 -22
  50. package/src/skf-audit-skill/references/severity-classify.md +53 -87
  51. package/src/skf-audit-skill/references/step-doc-drift.md +49 -19
  52. package/src/skf-audit-skill/references/structural-diff.md +43 -68
  53. package/src/skf-brief-skill/SKILL.md +7 -36
  54. package/src/skf-brief-skill/assets/scope-templates.md +1 -1
  55. package/src/skf-brief-skill/customize.toml +14 -0
  56. package/src/skf-brief-skill/references/analyze-target.md +6 -14
  57. package/src/skf-brief-skill/references/confirm-brief.md +2 -14
  58. package/src/skf-brief-skill/references/draft-checkpoint.md +8 -8
  59. package/src/skf-brief-skill/references/gather-intent.md +19 -22
  60. package/src/skf-brief-skill/references/headless-args.md +1 -1
  61. package/src/skf-brief-skill/references/health-check.md +1 -22
  62. package/src/skf-brief-skill/references/invocation-contract.md +37 -0
  63. package/src/skf-brief-skill/references/scope-definition.md +4 -14
  64. package/src/skf-brief-skill/references/step-auto-brief.md +1 -5
  65. package/src/skf-brief-skill/references/step-auto-validate.md +1 -5
  66. package/src/skf-brief-skill/references/version-resolution.md +1 -1
  67. package/src/skf-brief-skill/references/write-brief.md +17 -10
  68. package/src/skf-campaign/SKILL.md +15 -84
  69. package/src/skf-campaign/customize.toml +2 -0
  70. package/src/skf-campaign/manifest.yaml +4 -0
  71. package/src/skf-campaign/references/campaign-contracts.md +67 -0
  72. package/src/skf-campaign/references/campaign-directive-spec.md +14 -103
  73. package/src/skf-campaign/references/step-01-setup.md +4 -5
  74. package/src/skf-campaign/references/step-02-strategy.md +8 -3
  75. package/src/skf-campaign/references/step-03-pins.md +1 -1
  76. package/src/skf-campaign/references/step-04-provenance.md +1 -1
  77. package/src/skf-campaign/references/step-05-skill-loop.md +1 -1
  78. package/src/skf-campaign/references/step-06-batch.md +7 -6
  79. package/src/skf-campaign/references/step-11-maintenance.md +2 -2
  80. package/src/skf-campaign/references/step-resume.md +9 -8
  81. package/src/skf-campaign/scripts/campaign-deps.py +10 -1
  82. package/src/skf-campaign/scripts/campaign-render-batch.py +199 -0
  83. package/src/skf-campaign/scripts/campaign-status.py +162 -0
  84. package/src/skf-campaign/templates/campaign-brief-template.yaml +1 -1
  85. package/src/skf-create-skill/SKILL.md +14 -3
  86. package/src/skf-create-skill/assets/compile-assembly-rules.md +17 -38
  87. package/src/skf-create-skill/assets/skill-sections.md +9 -100
  88. package/src/skf-create-skill/assets/tessl-dismissal-rules.md +4 -13
  89. package/src/skf-create-skill/customize.toml +13 -0
  90. package/src/skf-create-skill/references/authoritative-files-protocol.md +7 -7
  91. package/src/skf-create-skill/references/compile.md +34 -47
  92. package/src/skf-create-skill/references/component-extraction.md +8 -35
  93. package/src/skf-create-skill/references/ecosystem-check.md +9 -25
  94. package/src/skf-create-skill/references/enrich.md +4 -17
  95. package/src/skf-create-skill/references/extract.md +14 -29
  96. package/src/skf-create-skill/references/extraction-patterns-tracing.md +1 -1
  97. package/src/skf-create-skill/references/extraction-patterns.md +7 -7
  98. package/src/skf-create-skill/references/generate-artifacts.md +9 -23
  99. package/src/skf-create-skill/references/health-check.md +1 -1
  100. package/src/skf-create-skill/references/load-brief.md +16 -18
  101. package/src/skf-create-skill/references/report.md +12 -15
  102. package/src/skf-create-skill/references/source-resolution-protocols.md +3 -3
  103. package/src/skf-create-skill/references/step-auto-shard.md +52 -25
  104. package/src/skf-create-skill/references/step-doc-rot.md +30 -12
  105. package/src/skf-create-skill/references/step-doc-sources.md +2 -2
  106. package/src/skf-create-skill/references/sub/ccc-discover.md +2 -13
  107. package/src/skf-create-skill/references/sub/fetch-docs.md +8 -50
  108. package/src/skf-create-skill/references/sub/fetch-temporal.md +5 -20
  109. package/src/skf-create-skill/references/tier-degradation-rules.md +6 -8
  110. package/src/skf-create-skill/references/validate.md +59 -28
  111. package/src/skf-create-skill/scripts/scan-doc-rot.py +245 -0
  112. package/src/skf-create-stack-skill/SKILL.md +15 -9
  113. package/src/skf-create-stack-skill/assets/provenance-map-schema.md +1 -1
  114. package/src/skf-create-stack-skill/customize.toml +10 -0
  115. package/src/skf-create-stack-skill/references/compile-stack.md +7 -8
  116. package/src/skf-create-stack-skill/references/compose-mode-rules.md +2 -13
  117. package/src/skf-create-stack-skill/references/detect-integrations.md +49 -54
  118. package/src/skf-create-stack-skill/references/detect-manifests.md +37 -30
  119. package/src/skf-create-stack-skill/references/generate-output.md +24 -75
  120. package/src/skf-create-stack-skill/references/init.md +9 -81
  121. package/src/skf-create-stack-skill/references/manifest-patterns.md +5 -35
  122. package/src/skf-create-stack-skill/references/parallel-extract.md +12 -27
  123. package/src/skf-create-stack-skill/references/rank-and-confirm.md +6 -6
  124. package/src/skf-create-stack-skill/references/report.md +27 -62
  125. package/src/skf-create-stack-skill/references/validate.md +35 -31
  126. package/src/skf-drop-skill/SKILL.md +20 -23
  127. package/src/skf-drop-skill/customize.toml +10 -0
  128. package/src/skf-drop-skill/references/execute.md +51 -31
  129. package/src/skf-drop-skill/references/headless-contract.md +18 -0
  130. package/src/skf-drop-skill/references/health-check.md +1 -13
  131. package/src/skf-drop-skill/references/report.md +42 -10
  132. package/src/skf-drop-skill/references/select.md +88 -48
  133. package/src/skf-drop-skill/scripts/dir-sizes.py +116 -0
  134. package/src/skf-export-skill/SKILL.md +17 -14
  135. package/src/skf-export-skill/assets/managed-section-format.md +2 -5
  136. package/src/skf-export-skill/customize.toml +10 -6
  137. package/src/skf-export-skill/references/generate-snippet.md +21 -35
  138. package/src/skf-export-skill/references/load-skill.md +44 -42
  139. package/src/skf-export-skill/references/multi-skill-mode.md +1 -1
  140. package/src/skf-export-skill/references/orphan-context-detection.md +11 -3
  141. package/src/skf-export-skill/references/package.md +27 -33
  142. package/src/skf-export-skill/references/preflight-snippet-root-probe.md +24 -5
  143. package/src/skf-export-skill/references/result-envelope.md +28 -0
  144. package/src/skf-export-skill/references/summary.md +11 -5
  145. package/src/skf-export-skill/references/token-report.md +42 -24
  146. package/src/skf-export-skill/references/update-context.md +32 -33
  147. package/src/skf-forger/SKILL.md +27 -39
  148. package/src/skf-forger/references/pipeline-mode.md +34 -0
  149. package/src/skf-forger/scripts/parse-pipeline.py +270 -0
  150. package/src/skf-quick-skill/SKILL.md +10 -60
  151. package/src/skf-quick-skill/customize.toml +9 -0
  152. package/src/skf-quick-skill/references/batch-mode.md +6 -4
  153. package/src/skf-quick-skill/references/compile.md +15 -52
  154. package/src/skf-quick-skill/references/ecosystem-check.md +5 -20
  155. package/src/skf-quick-skill/references/finalize.md +12 -6
  156. package/src/skf-quick-skill/references/halt-contract.md +54 -0
  157. package/src/skf-quick-skill/references/health-check.md +3 -4
  158. package/src/skf-quick-skill/references/quick-extract.md +7 -18
  159. package/src/skf-quick-skill/references/registry-resolution.md +1 -23
  160. package/src/skf-quick-skill/references/resolve-target.md +27 -34
  161. package/src/skf-quick-skill/references/write-and-validate.md +10 -25
  162. package/src/skf-refine-architecture/SKILL.md +14 -7
  163. package/src/skf-refine-architecture/customize.toml +9 -0
  164. package/src/skf-refine-architecture/references/compile.md +9 -7
  165. package/src/skf-refine-architecture/references/gap-analysis.md +21 -50
  166. package/src/skf-refine-architecture/references/health-check.md +1 -1
  167. package/src/skf-refine-architecture/references/improvements.md +9 -25
  168. package/src/skf-refine-architecture/references/init.md +9 -16
  169. package/src/skf-refine-architecture/references/issue-detection.md +10 -25
  170. package/src/skf-refine-architecture/references/refinement-rules.md +4 -16
  171. package/src/skf-refine-architecture/references/report.md +13 -10
  172. package/src/skf-rename-skill/SKILL.md +11 -21
  173. package/src/skf-rename-skill/customize.toml +10 -0
  174. package/src/skf-rename-skill/references/execute.md +107 -78
  175. package/src/skf-rename-skill/references/exit-codes.md +12 -0
  176. package/src/skf-rename-skill/references/report.md +16 -8
  177. package/src/skf-rename-skill/references/select.md +69 -42
  178. package/src/skf-rename-skill/scripts/skf-validate-rename-name.py +161 -0
  179. package/src/skf-setup/SKILL.md +20 -12
  180. package/src/skf-setup/customize.toml +10 -0
  181. package/src/skf-setup/references/auto-index.md +9 -10
  182. package/src/skf-setup/references/ccc-index.md +14 -15
  183. package/src/skf-setup/references/detect-and-tier.md +6 -8
  184. package/src/skf-setup/references/report.md +22 -31
  185. package/src/skf-setup/references/tier-rules.md +2 -32
  186. package/src/skf-setup/references/write-config.md +9 -10
  187. package/src/skf-test-skill/SKILL.md +10 -8
  188. package/src/skf-test-skill/customize.toml +2 -0
  189. package/src/skf-test-skill/references/coherence-check.md +19 -31
  190. package/src/skf-test-skill/references/coverage-check.md +109 -75
  191. package/src/skf-test-skill/references/detect-mode.md +10 -41
  192. package/src/skf-test-skill/references/external-validators.md +11 -19
  193. package/src/skf-test-skill/references/init.md +38 -20
  194. package/src/skf-test-skill/references/migration-section-rules.md +4 -4
  195. package/src/skf-test-skill/references/report.md +60 -40
  196. package/src/skf-test-skill/references/score.md +32 -64
  197. package/src/skf-test-skill/references/scoring-rules.md +6 -62
  198. package/src/skf-test-skill/references/source-access-protocol.md +6 -6
  199. package/src/skf-test-skill/references/step-hard-gate.md +1 -3
  200. package/src/skf-test-skill/scripts/aggregate-coherence.py +276 -0
  201. package/src/skf-test-skill/scripts/check-metadata-coherence.py +359 -0
  202. package/src/skf-test-skill/scripts/combine-external-scores.py +190 -0
  203. package/src/skf-test-skill/scripts/compute-score.py +131 -1
  204. package/src/skf-test-skill/scripts/reconcile-coverage.py +327 -0
  205. package/src/skf-test-skill/scripts/validate-inventory.py +251 -0
  206. package/src/skf-test-skill/scripts/verify-declared-numerator.py +192 -0
  207. package/src/skf-update-skill/SKILL.md +17 -5
  208. package/src/skf-update-skill/customize.toml +14 -0
  209. package/src/skf-update-skill/references/detect-changes.md +19 -37
  210. package/src/skf-update-skill/references/health-check.md +3 -9
  211. package/src/skf-update-skill/references/init.md +39 -32
  212. package/src/skf-update-skill/references/manual-section-rules.md +1 -2
  213. package/src/skf-update-skill/references/merge-conflict-rules.md +1 -52
  214. package/src/skf-update-skill/references/merge.md +13 -57
  215. package/src/skf-update-skill/references/re-extract.md +12 -24
  216. package/src/skf-update-skill/references/report.md +14 -7
  217. package/src/skf-update-skill/references/validate.md +32 -30
  218. package/src/skf-update-skill/references/write.md +86 -51
  219. package/src/skf-update-skill/scripts/skf-new-file-diff.py +167 -0
  220. package/src/skf-verify-stack/SKILL.md +11 -21
  221. package/src/skf-verify-stack/customize.toml +12 -3
  222. package/src/skf-verify-stack/references/coverage-patterns.md +1 -29
  223. package/src/skf-verify-stack/references/coverage.md +21 -10
  224. package/src/skf-verify-stack/references/exit-codes.md +14 -0
  225. package/src/skf-verify-stack/references/health-check.md +1 -1
  226. package/src/skf-verify-stack/references/init.md +20 -25
  227. package/src/skf-verify-stack/references/integration-verification-rules.md +10 -19
  228. package/src/skf-verify-stack/references/integrations.md +44 -49
  229. package/src/skf-verify-stack/references/report.md +28 -34
  230. package/src/skf-verify-stack/references/requirements.md +3 -3
  231. package/src/skf-verify-stack/references/synthesize.md +36 -39
  232. package/src/skf-verify-stack/scripts/skf-coverage-tally.py +196 -0
  233. package/src/skf-verify-stack/scripts/skf-report-delta.py +256 -0
  234. package/src/skf-verify-stack/scripts/skf-verdict-rollup.py +258 -0
  235. package/src/skf-rename-skill/references/rebuild-context.md +0 -110
@@ -1,10 +1,14 @@
1
1
  ---
2
2
  nextStepFile: 'compile-stack.md'
3
- integrationPatterns: 'references/integration-patterns.md'
4
- composeModeRules: 'references/compose-mode-rules.md'
5
3
  pairIntersectProbeOrder:
6
4
  - '{project-root}/_bmad/skf/shared/scripts/skf-pair-intersect.py'
7
5
  - '{project-root}/src/shared/scripts/skf-pair-intersect.py'
6
+ comentionProbeOrder:
7
+ - '{project-root}/_bmad/skf/shared/scripts/skf-comention-pairs.py'
8
+ - '{project-root}/src/shared/scripts/skf-comention-pairs.py'
9
+ validateFeasibilityReportProbeOrder:
10
+ - '{project-root}/_bmad/skf/shared/scripts/skf-validate-feasibility-report.py'
11
+ - '{project-root}/src/shared/scripts/skf-validate-feasibility-report.py'
8
12
  ---
9
13
 
10
14
  <!-- Config: communicate in {communication_language}. -->
@@ -19,7 +23,6 @@ Analyze co-import patterns between confirmed libraries to identify integration p
19
23
 
20
24
  - Focus on detecting cross-library patterns using subprocess Pattern 1 (grep/search)
21
25
  - Do not compile SKILL.md (Step 06)
22
- - Integration detection is the core differentiator of stack skills vs individual skills
23
26
 
24
27
  ## MANDATORY SEQUENCE
25
28
 
@@ -54,7 +57,7 @@ From `confirmed_dependencies`, conceptually you have N*(N-1)/2 unordered pairs.
54
57
  `pairs[]` is sorted by `intersection_count` DESC, then `(a, b)` ASC for stable ordering. Default Top-K cap is **20** (matches S7 below); pass `--top-k N` to override.
55
58
  3. **Parse the JSON result** and use `pairs[]` as the qualifying-pair set for §2 onward. The `intersection_count` is the candidate file count for the §2 2-file threshold pre-grep; `files[]` is the grep-scope for that pair.
56
59
 
57
- **Top-K cap (S7, 20):** If the script's response has `truncated: true`, more pairs than the cap had non-empty intersections. Surface a user-visible warning composed as: `"non-empty-intersection pair count {total_pairs} exceeds cap — analyzing top 20 by intersection size; {total_pairs - 20} pairs skipped"`. Record this cap in the evidence report. (Tie-break by intersection size is what the script sorts on; if you need to override the cap intentionally, pass `--top-k N` and document the rationale.) The legacy 50-dependency threshold that formerly gated a separate Top-K pass is retired — the file-intersection prune does the bulk of the work and the cap is now a second-order safety limit, not a primary strategy.
60
+ **Top-K cap (S7, 20):** If the script's response has `truncated: true`, more pairs than the cap had non-empty intersections. Surface a user-visible warning composed as: `"non-empty-intersection pair count {total_pairs} exceeds cap — analyzing top 20 by intersection size; {total_pairs - 20} pairs skipped"`. Record this cap in the evidence report. (Tie-break by intersection size is what the script sorts on; if you need to override the cap intentionally, pass `--top-k N` and document the rationale.) The cap is a second-order safety limit, not a primary strategy — the file-intersection prune does the bulk of the work.
58
61
 
59
62
  Report: "**Analyzing {pair_count} library pairs for integration patterns** (pruned from {N*(N-1)/2} via file-list intersection; {capped_count} after Top-K if applicable)**...**"
60
63
 
@@ -64,29 +67,54 @@ Report: "**Analyzing {pair_count} library pairs for integration patterns** (prun
64
67
 
65
68
  Instead of co-import grep, detect integrations from architecture document:
66
69
 
67
- 1. Load `{composeModeRules}` for integration evidence format rules
70
+ 1. Load `{composeModeRulesPath}` for integration evidence format rules
68
71
  2. **If `{architecture_doc_path}` is null or not available:** Skip directly to the "If no architecture document available" fallback below
69
- 3. Load the architecture document from `{architecture_doc_path}`
70
- 4. **Prose-based co-mention analysis with precision guards (H2):**
71
- - Use **word-boundary matching** when searching for skill names in the architecture document: `\b{skill_name}\b` (case-insensitive). This prevents substring false positives (e.g., `react` matching inside `reactive`).
72
- - **Exclude non-body sections.** Detect H1 and H2 markdown headers (`^# ` and `^## `) and skip any paragraphs under headers that normalise to `introduction`, `overview`, `glossary`, `table of contents`, `references`, `appendix`, or `index`. Co-mentions inside headings themselves also do not qualify.
73
- - **Require ≥2 qualifying paragraphs.** A pair `(A, B)` qualifies only when at least two distinct body paragraphs each contain word-boundary matches for both `A` and `B`. A single co-mention paragraph is insufficient evidence.
74
- - Risks and rationale are documented in `{composeModeRules}` under "Compose-mode co-mention precision".
75
- 5. For each detected integration pair:
72
+ 3. **Compute qualifying co-mention pairs deterministically via the shared script.** The precision guards (word-boundary matching `\b{skill_name}\b` case-insensitive to reject substrings like `react` inside `reactive`; H1/H2 section exclusion for headers that normalise to `introduction`, `overview`, `glossary`, `table of contents`, `references`, `appendix`, or `index`, with heading text itself never a co-mention source; and the ≥2-distinct-body-paragraph gate) are a scan-and-count with one correct answer per `(architecture_doc, skill-name-set)` — do not perform them in-prompt. Risks and rationale stay documented in `{composeModeRulesPath}` under "Compose-mode co-mention precision".
73
+
74
+ **Resolve `{comentionHelper}`** from `{comentionProbeOrder}`; first existing path wins.
75
+
76
+ ```bash
77
+ uv run {comentionHelper} comention --doc {architecture_doc_path} --skills -
78
+ ```
79
+ piping the loaded skill names — the `confirmed_dependencies` names — as a JSON array on stdin (e.g. `["react", "express"]`; use a temp file under `{forge_data_folder}/` if stdin piping is unavailable). The script emits:
80
+ ```json
81
+ {
82
+ "pairs": [
83
+ {"a": "<skill>", "b": "<skill>", "paragraph_count": N,
84
+ "evidence": [{"header": "<governing-header-or-null>", "excerpt": "<text>"}, ...]},
85
+ ...
86
+ ],
87
+ "excluded_section_count": M
88
+ }
89
+ ```
90
+ `pairs[]` contains only qualifying pairs (≥2 distinct body paragraphs), sorted by `paragraph_count` DESC then `(a, b)` ASC. Use `pairs[]` as the detected-integration-pair set for step 4 onward; each pair's `evidence[]` supplies the governing header and paragraph excerpts to quote as architecture-reference evidence.
91
+
92
+ **Graceful degradation:** if no `{comentionProbeOrder}` candidate exists (e.g. `uv` unavailable on claude.ai web), perform the equivalent scan directly per the guards above and the script's `--help` contract, then proceed with the same qualifying-pair set.
93
+ 4. For each detected integration pair (from `pairs[]`):
76
94
  - Load both skills' export lists and API signatures
77
- - Compose an integration section following the format from `{composeModeRules}`
95
+ - Compose an integration section following the format from `{composeModeRulesPath}`
78
96
  - Include VS feasibility verdict if a feasibility report matching the filename pattern defined in `src/shared/references/feasibility-report-schema.md` exists under `{forge_data_folder}/` (timestamped `feasibility-report-{project_slug}-{YYYYMMDD-HHmmss}.md` or the stable `feasibility-report-{project_slug}-latest.md` copy). Schema version `"1.0"` is required; see the schema for the full contract.
79
97
  - Cite evidence from both skills: `[from skill: {skill_name}]`
80
98
 
81
- All integration evidence inherits confidence tiers from the source skills. Load and apply the full **Confidence Tier Inheritance** matrix from `{composeModeRules}` to compute the correct tier for each pair (covers T1+T1, T1+T1-low, T1-low+T1-low, T1+T2, T1-low+T2, T2+T2 cases). Apply the `[composed]` suffix to all confidence labels — e.g., `T1 [composed]`, `T1-low [composed, +T2 annotations]`.
99
+ All integration evidence inherits confidence tiers from the source skills. Load and apply the full **Confidence Tier Inheritance** matrix from `{composeModeRulesPath}` to compute the correct tier for each pair (covers T1+T1, T1+T1-low, T1-low+T1-low, T1+T2, T1-low+T2, T2+T2 cases). Apply the `[composed]` suffix to all confidence labels — e.g., `T1 [composed]`, `T1-low [composed, +T2 annotations]`.
82
100
 
83
101
  **VS verdict parsing (if feasibility report exists):** The feasibility report format is defined by the shared schema at `src/shared/references/feasibility-report-schema.md` (single source of truth; skf-verify-stack is the producer, this skill is the consumer). Follow the schema strictly:
84
102
 
85
103
  - Locate the report via the filename pattern in the schema: `{forge_data_folder}/feasibility-report-{project_slug}-{YYYYMMDD-HHmmss}.md` (or the stable `feasibility-report-{project_slug}-latest.md` copy next to it).
86
- - **Schema version guard:** Parse the report's YAML frontmatter and verify `schemaVersion == "1.0"`. If the field is missing or mismatched, HALT with an explicit error: `"feasibility-report schemaVersion mismatch: expected '1.0', got '{value}' refusing to proceed"`. Do NOT attempt to interpret unknown versions.
104
+ - **Schema version guard (deterministic gate):** Resolve `{validateFeasibilityReportHelper}` from `{validateFeasibilityReportProbeOrder}` (first existing path wins) and run it against the located report:
105
+
106
+ ```bash
107
+ python3 {validateFeasibilityReportHelper} <located-report-path>
108
+ ```
109
+
110
+ Consume `schemaVersionOk` / `schemaVersionFound` from its JSON. If `schemaVersionOk` is false, HALT with `"feasibility-report schemaVersion mismatch: expected '1.0', got '{schemaVersionFound}' — refusing to proceed"`, then emit the result envelope on stderr per the Result Contract in SKILL.md and exit `2`. The script's structural findings (`headingsOk` / `orderViolations`) are advisory for this consumer — it gates only on schemaVersion. **If the helper does not resolve or cannot run,** parse the report's YAML frontmatter directly and compare `schemaVersion` to the literal `1.0`, applying the same HALT (a missing or mismatched version halts identically). Unknown versions are never interpreted.
111
+
112
+ ```
113
+ SKF_STACK_RESULT_JSON: {"status":"error","skill_package":null,"skill_name":"{project_name}-stack","stack_libraries":[],"mode":"compose","exit_code":2,"halt_reason":"schema-version-mismatch"}
114
+ ```
87
115
  - Read `overallVerdict` from frontmatter (exactly one of `FEASIBLE|CONDITIONALLY_FEASIBLE|NOT_FEASIBLE`).
88
116
  - Parse the `## Integration Verdicts` markdown table for per-pair verdicts (exactly one of `Verified|Plausible|Risky|Blocked`). Any unknown verdict token is a hard error per the schema — do not silently drop or map.
89
- - For each architecture-detected pair, include `VS overall: {overallVerdict}` and `VS pair: {verdict}` in the integration evidence per the format in `{composeModeRules}`. VS verdicts do not apply to inferred integrations since the VS report operates on architecture-described interactions only. Additionally, flag any pairs where VS reported `Risky` or `Blocked` by appending a `[VS: Risky]` or `[VS: Blocked]` warning annotation to the integration entry.
117
+ - For each architecture-detected pair, include `VS overall: {overallVerdict}` and `VS pair: {verdict}` in the integration evidence per the format in `{composeModeRulesPath}`. VS verdicts do not apply to inferred integrations since the VS report operates on architecture-described interactions only. Additionally, flag any pairs where VS reported `Risky` or `Blocked` by appending a `[VS: Risky]` or `[VS: Blocked]` warning annotation to the integration entry.
90
118
 
91
119
  If no architecture document available:
92
120
  - Infer potential integrations from skills sharing the same `language` field or sharing domain keywords in their SKILL.md descriptions (use the `usage_patterns` and `exports` fields from `per_library_extractions[]` built in step 4, or reload SKILL.md from the version-aware path: use `skill_package_path` from step 2, or resolve via `{skills_output_folder}/{skill_dir}/active/{skill_dir}/SKILL.md` — see `knowledge/version-paths.md`)
@@ -115,7 +143,7 @@ If `tools.ccc` is true AND `ccc_index.status` is `"fresh"` or `"stale"` in forge
115
143
 
116
144
  For each library pair with **0 or 1 co-import files** (below the 2-file threshold — S9, symmetric to give the 0-hit case the same chance as the 1-hit case), run `ccc_bridge.search("{libA} {libB}", source_root, top_k=10)` to find files where the two libraries interact semantically — even without explicit import co-location. If CCC returns additional files where both libraries appear, add them to the pair's co-import candidate list and re-evaluate against the 2-file threshold.
117
145
 
118
- **CCC precision guard for 1-file pairs (H3):** When a CCC hit would elevate a 1-file pair to qualifying status, run a post-hoc verification on that file: re-grep the file and confirm it contains explicit import statements for **both** libraries (per the ecosystem import patterns from `references/manifest-patterns.md`). If either import is missing (e.g., one library is only name-dropped in a comment or string), drop the CCC-added file from the candidate list. Only pairs with ≥2 files that each contain explicit imports for both libraries qualify. Log rejected CCC candidates in workflow state for the evidence report.
146
+ **CCC precision guard for 1-file pairs (H3):** When a CCC hit would elevate a 1-file pair to qualifying status, run a post-hoc verification on that file: re-grep the file and confirm it contains explicit import statements for **both** libraries (per the ecosystem import patterns from `{manifestPatternsPath}`). If either import is missing (e.g., one library is only name-dropped in a comment or string), drop the CCC-added file from the candidate list. Only pairs with ≥2 files that each contain explicit imports for both libraries qualify. Log rejected CCC candidates in workflow state for the evidence report.
119
147
 
120
148
  **Tool resolution for ccc_bridge.search:** Use `/ccc` skill search (Claude Code), ccc MCP server (Cursor), or `ccc search "{libA} {libB}" --path {source_root} --top 10` (CLI). See `knowledge/tool-resolution.md`.
121
149
 
@@ -125,16 +153,9 @@ CCC failures: skip augmentation silently, proceed with grep-only results.
125
153
 
126
154
  ### 3. Classify Integration Types
127
155
 
128
- Load `{integrationPatterns}` for classification rules.
156
+ Load `{integrationPatternsPath}` for classification rules.
129
157
 
130
- For each qualifying pair, analyze to classify the integration type (**in compose-mode**: all architecture-document-detected pairs qualify automatically — the 2+ co-import file threshold applies only in code-mode; **in code-mode**: pair must have 2+ co-import files):
131
-
132
- - **Type 1: Middleware Chain** — Sequential function calls piping output between libraries
133
- - **Type 2: Shared Types** — Type definitions exchanged between libraries
134
- - **Type 3: Configuration Bridge** — One library configuring or initializing another
135
- - **Type 4: Event Handler** — Event patterns crossing library boundaries
136
- - **Type 5: Adapter/Wrapper** — Thin wrapper connecting library interfaces
137
- - **Type 6: State Sharing** — Shared state stores or context providers
158
+ For each qualifying pair, analyze to classify the integration type against those pattern types (**in compose-mode**: all architecture-document-detected pairs qualify automatically — the 2+ co-import file threshold applies only in code-mode; **in code-mode**: pair must have 2+ co-import files):
138
159
 
139
160
  For each detected integration:
140
161
  - Identify the top 3 files demonstrating the pattern
@@ -145,7 +166,7 @@ For each detected integration:
145
166
  - `architecture-co-mention` — compose-mode pair qualified via word-boundary co-mention in the architecture document (per §2 H2 guards). Maps to `detection_method: architecture_co_mention` in `provenance-map.json`.
146
167
  - `constituent-documented-contract` — compose-mode pair whose cross-library contract is documented in a constituent skill's integration docs (cited, e.g. a grep-verified upstream seam) but not co-mentioned in the architecture document. Maps to `detection_method: constituent_documented_contract` in `provenance-map.json`.
147
168
  - `inferred-shared-domain` — compose-mode pair without an architecture document, inferred from shared `language` or domain keywords (no cited contract). Maps to `detection_method: inferred_from_shared_domain` in `provenance-map.json`.
148
- - Render as `{tier} ({qualifier})` — e.g., `T1-low (grep-co-import)`, `T1 (ccc-augmented)`, `T1-low (architecture-co-mention) [composed]`. The `[composed]`/`[inferred from shared domain]` suffix from `compose-mode-rules.md` is appended after the qualifier in compose-mode.
169
+ - Render as `{tier} ({qualifier})` — e.g., `T1-low (grep-co-import)`, `T1 (ccc-augmented)`, `T1-low (architecture-co-mention) [composed]`. The `[composed]`/`[inferred from shared domain]` suffix from `{composeModeRulesPath}` is appended after the qualifier in compose-mode.
149
170
 
150
171
  **Provenance ↔ SKILL.md tier parity:** The tier derived above is the single value for this edge — write the *same* tier to both the SKILL.md integration label and `provenance-map.json` `integrations[].confidence`. The detection-method qualifier (and the `provenance-map.json` `detection_method` it maps to) records *how* the edge was found and is orthogonal to confidence; it never forces the tier into a fixed band.
151
172
 
@@ -159,33 +180,7 @@ Assemble the integration graph:
159
180
 
160
181
  ### 5. Display Integration Summary
161
182
 
162
- **If integrations detected:**
163
-
164
- "**Integration detection complete.**
165
-
166
- **Integration graph:** {lib_count} libraries, {pair_count} integration pairs
167
-
168
- **Hub libraries** (connected to 3+ others):
169
- {For each hub:} - **{library}** — integrates with {partner_list}
170
-
171
- **Detected integrations:**
172
- | Library A | Library B | Type | Co-import Files | Confidence |
173
- |-----------|-----------|------|-----------------|------------|
174
- | {name} | {name} | {type} | {count} | {tier} |
175
-
176
- {If cross-cutting patterns:}
177
- **Cross-cutting patterns:**
178
- - {description spanning 3+ libraries}
179
-
180
- **Proceeding to stack compilation...**"
181
-
182
- **If no integrations detected:**
183
-
184
- "**No co-import integration patterns detected** between confirmed libraries.
185
-
186
- The libraries in this project appear to operate independently. The stack skill will contain library summaries without an integration layer.
187
-
188
- **Proceeding to stack compilation...**"
183
+ If integrations were detected, report the integration graph (`{lib_count}` libraries, `{pair_count}` pairs): the hub libraries (connected to 3+ others) with their partners, each detected pair (library A, library B, type, co-import file count, confidence tier), and any cross-cutting patterns spanning 3+ libraries. If none were detected, report that no co-import integration patterns were found — the libraries appear to operate independently, so the stack skill will carry library summaries without an integration layer.
189
184
 
190
185
  ### 6. Auto-Proceed to Next Step
191
186
 
@@ -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