bmad-module-skill-forge 2.2.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (435) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/README.md +49 -49
  3. package/docs/404.md +10 -8
  4. package/docs/_data/pinned.yaml +22 -13
  5. package/docs/_internal/STABILITY.md +58 -35
  6. package/docs/agents.md +39 -53
  7. package/docs/architecture.md +65 -51
  8. package/docs/bmad-synergy.md +53 -51
  9. package/docs/campaign.md +127 -75
  10. package/docs/concepts.md +34 -28
  11. package/docs/examples.md +70 -68
  12. package/docs/forge-auto.md +34 -31
  13. package/docs/getting-started.md +118 -57
  14. package/docs/how-it-works.md +25 -21
  15. package/docs/index.md +15 -15
  16. package/docs/skill-model.md +70 -59
  17. package/docs/troubleshooting.md +135 -18
  18. package/docs/verifying-a-skill.md +83 -57
  19. package/docs/why-skf.md +24 -22
  20. package/docs/workflows.md +274 -110
  21. package/package.json +18 -10
  22. package/src/forger/preferences.yaml +8 -1
  23. package/src/knowledge/agentskills-spec.md +2 -0
  24. package/src/knowledge/ccc-bridge.md +40 -24
  25. package/src/knowledge/confidence-tiers.md +9 -5
  26. package/src/knowledge/overview.md +3 -3
  27. package/src/knowledge/progressive-capability.md +8 -8
  28. package/src/knowledge/provenance-tracking.md +9 -5
  29. package/src/knowledge/qmd-registry.md +2 -2
  30. package/src/knowledge/skf-knowledge-index.csv +2 -2
  31. package/src/knowledge/skill-lifecycle.md +18 -11
  32. package/src/knowledge/split-body-strategy.md +0 -3
  33. package/src/knowledge/tool-resolution.md +4 -2
  34. package/src/knowledge/version-paths.md +101 -15
  35. package/src/module-help.csv +3 -3
  36. package/src/module.yaml +10 -0
  37. package/src/shared/data/ast-grep-recipes.yaml +608 -0
  38. package/src/shared/data/ide-context-files.json +30 -0
  39. package/src/shared/health-check.md +32 -12
  40. package/src/shared/references/description-guard-protocol.md +12 -9
  41. package/src/shared/references/feasibility-report-schema.md +19 -13
  42. package/src/shared/references/headless-gate-convention.md +55 -3
  43. package/src/shared/references/output-contract-schema.md +19 -8
  44. package/src/shared/references/pipeline-contracts.md +94 -29
  45. package/src/shared/references/tessl-review.md +77 -0
  46. package/src/shared/scripts/schemas/skf-analyze-result-envelope.v1.json +194 -0
  47. package/src/shared/scripts/schemas/skf-audit-result-envelope.v1.json +192 -0
  48. package/src/shared/scripts/schemas/skf-brief-result-envelope.v1.json +32 -4
  49. package/src/shared/scripts/schemas/skf-campaign-result-envelope.v1.json +174 -0
  50. package/src/shared/scripts/schemas/skf-create-skill-result-envelope.v1.json +284 -0
  51. package/src/shared/scripts/schemas/skf-drop-skill-result-envelope.v1.json +164 -0
  52. package/src/shared/scripts/schemas/skf-export-result-envelope.v1.json +160 -0
  53. package/src/shared/scripts/schemas/skf-quick-skill-result-envelope.v1.json +261 -0
  54. package/src/shared/scripts/schemas/skf-refine-architecture-result-envelope.v1.json +192 -0
  55. package/src/shared/scripts/schemas/skf-rename-skill-result-envelope.v1.json +179 -0
  56. package/src/shared/scripts/schemas/skf-setup-result-envelope.v1.json +27 -11
  57. package/src/shared/scripts/schemas/skf-stack-result-envelope.v1.json +176 -0
  58. package/src/shared/scripts/schemas/skf-test-result-envelope.v1.json +173 -0
  59. package/src/shared/scripts/schemas/skf-update-result-envelope.v1.json +19 -5
  60. package/src/shared/scripts/schemas/skf-verify-stack-result-envelope.v1.json +180 -0
  61. package/src/shared/scripts/schemas/skill-brief.v1.json +34 -0
  62. package/src/shared/scripts/schemas/workspace-detection.v1.json +1 -1
  63. package/src/shared/scripts/skf-atomic-write.py +30 -14
  64. package/src/shared/scripts/skf-build-change-manifest.py +2203 -24
  65. package/src/shared/scripts/skf-ccc-git-hygiene.py +532 -0
  66. package/src/shared/scripts/skf-check-unit-records.py +184 -0
  67. package/src/shared/scripts/skf-check-workspace-drift.py +538 -9
  68. package/src/shared/scripts/skf-classify-changed-files.py +694 -0
  69. package/src/shared/scripts/skf-comention-pairs.py +1333 -123
  70. package/src/shared/scripts/skf-compare-file-hashes.py +1 -1
  71. package/src/shared/scripts/skf-count-imports.py +1867 -0
  72. package/src/shared/scripts/skf-count-tokens.py +1 -1
  73. package/src/shared/scripts/skf-derive-assembly-shape.py +3 -2
  74. package/src/shared/scripts/skf-description-guard.py +99 -11
  75. package/src/shared/scripts/skf-detect-docs.py +694 -2
  76. package/src/shared/scripts/skf-detect-language.py +486 -107
  77. package/src/shared/scripts/skf-detect-registry.py +887 -0
  78. package/src/shared/scripts/skf-detect-scripts-assets.py +1 -1
  79. package/src/shared/scripts/skf-detect-tools.py +209 -27
  80. package/src/shared/scripts/skf-detect-workspaces.py +506 -30
  81. package/src/shared/scripts/skf-disqualify-candidates.py +821 -182
  82. package/src/shared/scripts/skf-emit-brief-result-envelope.py +69 -191
  83. package/src/shared/scripts/skf-emit-result-envelope.py +1604 -106
  84. package/src/shared/scripts/skf-enumerate-stack-skills.py +986 -117
  85. package/src/shared/scripts/skf-extract-public-api.py +4084 -85
  86. package/src/shared/scripts/skf-extraction-inventory.py +746 -0
  87. package/src/shared/scripts/skf-extraction-snapshot.py +539 -0
  88. package/src/shared/scripts/skf-fetch-temporal.py +674 -0
  89. package/src/shared/scripts/skf-find-cycles.py +97 -29
  90. package/src/shared/scripts/skf-find-test-report.py +476 -0
  91. package/src/shared/scripts/skf-forge-tier-rw.py +444 -203
  92. package/src/shared/scripts/skf-github-fetch.py +365 -0
  93. package/src/shared/scripts/skf-github-probe.py +661 -0
  94. package/src/shared/scripts/skf-hash-content.py +166 -12
  95. package/src/shared/scripts/skf-language-corpora.py +1 -1
  96. package/src/shared/scripts/skf-load-provenance.py +159 -27
  97. package/src/shared/scripts/skf-manifest-ops.py +1 -1
  98. package/src/shared/scripts/skf-merge-ccc-exclusions.py +2307 -223
  99. package/src/shared/scripts/skf-merge-doc-urls.py +1 -1
  100. package/src/shared/scripts/skf-names-present.py +221 -0
  101. package/src/shared/scripts/skf-pair-intersect.py +119 -28
  102. package/src/shared/scripts/skf-parse-gaps.py +1384 -0
  103. package/src/shared/scripts/skf-preapply.py +1 -1
  104. package/src/shared/scripts/skf-preflight.py +161 -27
  105. package/src/shared/scripts/skf-promote-staged.py +430 -0
  106. package/src/shared/scripts/skf-provenance-gap-dispatch.py +39 -7
  107. package/src/shared/scripts/skf-qmd-classify-collections.py +229 -45
  108. package/src/shared/scripts/skf-quick-batch.py +774 -0
  109. package/src/shared/scripts/skf-rebuild-managed-sections.py +972 -88
  110. package/src/shared/scripts/skf-recommend-scope-type.py +323 -156
  111. package/src/shared/scripts/skf-render-metadata-stats.py +156 -12
  112. package/src/shared/scripts/skf-render-quick-metadata.py +132 -28
  113. package/src/shared/scripts/skf-render-stack-metadata.py +976 -0
  114. package/src/shared/scripts/skf-resolve-authoritative-files.py +128 -13
  115. package/src/shared/scripts/skf-resolve-package.py +523 -106
  116. package/src/shared/scripts/skf-rewrite-skill-name.py +433 -47
  117. package/src/shared/scripts/skf-run-lock.py +577 -0
  118. package/src/shared/scripts/skf-scan-manifests.py +998 -57
  119. package/src/shared/scripts/skf-scan-skill-md-structure.py +1341 -37
  120. package/src/shared/scripts/skf-severity-classify.py +712 -108
  121. package/src/shared/scripts/skf-shape-detect.py +298 -204
  122. package/src/shared/scripts/skf-shard-body.py +9 -8
  123. package/src/shared/scripts/skf-skill-inventory.py +2412 -89
  124. package/src/shared/scripts/skf-skills-module.py +472 -0
  125. package/src/shared/scripts/skf-source-tree.py +1796 -0
  126. package/src/shared/scripts/skf-structural-diff.py +670 -119
  127. package/src/shared/scripts/skf-tessl-review.py +706 -0
  128. package/src/shared/scripts/skf-update-active-symlink.py +5 -5
  129. package/src/shared/scripts/skf-update-run-state.py +624 -0
  130. package/src/shared/scripts/skf-validate-brief-inputs.py +92 -29
  131. package/src/shared/scripts/skf-validate-brief-schema.py +4 -1
  132. package/src/shared/scripts/skf-validate-feasibility-report.py +577 -66
  133. package/src/shared/scripts/skf-validate-frontmatter.py +103 -26
  134. package/src/shared/scripts/skf-validate-output.py +712 -64
  135. package/src/shared/scripts/skf-validate-pins.py +1 -1
  136. package/src/shared/scripts/skf-verify-no-trace.py +116 -10
  137. package/src/shared/scripts/skf-verify-provenance-completeness.py +2919 -54
  138. package/src/shared/scripts/skf-write-skill-brief.py +367 -19
  139. package/src/shared/tool-requirements.yaml +201 -0
  140. package/src/skf-analyze-source/SKILL.md +41 -36
  141. package/src/skf-analyze-source/assets/skill-brief-schema.md +7 -8
  142. package/src/skf-analyze-source/customize.toml +36 -24
  143. package/src/skf-analyze-source/references/auto-docs-only.md +58 -20
  144. package/src/skf-analyze-source/references/continue.md +2 -13
  145. package/src/skf-analyze-source/references/discover-additional-source.md +147 -0
  146. package/src/skf-analyze-source/references/generate-briefs.md +121 -55
  147. package/src/skf-analyze-source/references/headless-contract.md +42 -15
  148. package/src/skf-analyze-source/references/identify-units.md +96 -110
  149. package/src/skf-analyze-source/references/init.md +73 -71
  150. package/src/skf-analyze-source/references/map-and-detect.md +123 -105
  151. package/src/skf-analyze-source/references/map-unit-exports.md +68 -0
  152. package/src/skf-analyze-source/references/recommend.md +51 -70
  153. package/src/skf-analyze-source/references/scan-project.md +60 -84
  154. package/src/skf-analyze-source/references/scan-root.md +39 -0
  155. package/src/skf-analyze-source/references/step-auto-scope-coexistence.md +47 -0
  156. package/src/skf-analyze-source/references/step-auto-scope-corpora.md +53 -0
  157. package/src/skf-analyze-source/references/step-auto-scope-split.md +91 -0
  158. package/src/skf-analyze-source/references/step-auto-scope.md +208 -293
  159. package/src/skf-analyze-source/references/step-shape-detect.md +14 -12
  160. package/src/skf-analyze-source/references/unit-detection-heuristics.md +37 -42
  161. package/src/skf-audit-skill/SKILL.md +43 -51
  162. package/src/skf-audit-skill/assets/drift-report-template.md +27 -3
  163. package/src/skf-audit-skill/customize.toml +41 -20
  164. package/src/skf-audit-skill/references/constituent-freshness.md +91 -0
  165. package/src/skf-audit-skill/references/doc-drift.md +141 -0
  166. package/src/skf-audit-skill/references/headless-contract.md +29 -0
  167. package/src/skf-audit-skill/references/init.md +148 -210
  168. package/src/skf-audit-skill/references/re-index.md +96 -108
  169. package/src/skf-audit-skill/references/report.md +96 -33
  170. package/src/skf-audit-skill/references/semantic-diff.md +27 -18
  171. package/src/skf-audit-skill/references/severity-classify.md +79 -65
  172. package/src/skf-audit-skill/references/severity-rules.md +15 -6
  173. package/src/skf-audit-skill/references/structural-diff.md +75 -90
  174. package/src/skf-audit-skill/references/upstream-checkout.md +77 -0
  175. package/src/skf-audit-skill/scripts/render-drift-tables.py +685 -0
  176. package/src/skf-brief-skill/SKILL.md +36 -25
  177. package/src/skf-brief-skill/assets/description-voice-examples.md +1 -1
  178. package/src/skf-brief-skill/assets/scope-templates.md +17 -24
  179. package/src/skf-brief-skill/assets/skill-brief-schema.md +29 -15
  180. package/src/skf-brief-skill/customize.toml +48 -20
  181. package/src/skf-brief-skill/references/analyze-target.md +142 -125
  182. package/src/skf-brief-skill/references/confirm-brief.md +10 -8
  183. package/src/skf-brief-skill/references/draft-checkpoint.md +36 -17
  184. package/src/skf-brief-skill/references/gather-intent-ratify.md +68 -0
  185. package/src/skf-brief-skill/references/gather-intent.md +87 -182
  186. package/src/skf-brief-skill/references/headless-args.md +84 -16
  187. package/src/skf-brief-skill/references/health-check.md +1 -1
  188. package/src/skf-brief-skill/references/invocation-contract.md +18 -13
  189. package/src/skf-brief-skill/references/portfolio-similarity-check.md +1 -1
  190. package/src/skf-brief-skill/references/qmd-collection-registration.md +7 -10
  191. package/src/skf-brief-skill/references/scope-definition.md +123 -47
  192. package/src/skf-brief-skill/references/step-auto-brief.md +24 -80
  193. package/src/skf-brief-skill/references/step-auto-validate.md +20 -121
  194. package/src/skf-brief-skill/references/version-resolution.md +3 -2
  195. package/src/skf-brief-skill/references/write-brief.md +66 -57
  196. package/src/skf-campaign/SKILL.md +31 -34
  197. package/src/skf-campaign/assets/campaign-state-schema.json +25 -4
  198. package/src/skf-campaign/customize.toml +47 -16
  199. package/src/skf-campaign/references/campaign-contracts.md +39 -29
  200. package/src/skf-campaign/references/campaign-directive-spec.md +4 -2
  201. package/src/skf-campaign/references/health-check.md +7 -16
  202. package/src/skf-campaign/references/step-01-setup.md +46 -84
  203. package/src/skf-campaign/references/step-02-strategy.md +31 -30
  204. package/src/skf-campaign/references/step-03-pins.md +26 -18
  205. package/src/skf-campaign/references/step-04-provenance.md +24 -23
  206. package/src/skf-campaign/references/step-05-skill-loop.md +67 -48
  207. package/src/skf-campaign/references/step-06-batch.md +41 -34
  208. package/src/skf-campaign/references/step-07-capstone.md +40 -25
  209. package/src/skf-campaign/references/step-08-verify.md +28 -29
  210. package/src/skf-campaign/references/step-09-refine.md +29 -30
  211. package/src/skf-campaign/references/step-10-export.md +48 -36
  212. package/src/skf-campaign/references/step-11-maintenance.md +31 -34
  213. package/src/skf-campaign/references/step-resume.md +37 -68
  214. package/src/skf-campaign/scripts/campaign-deps.py +57 -18
  215. package/src/skf-campaign/scripts/campaign-parse-manifest.py +361 -54
  216. package/src/skf-campaign/scripts/campaign-provenance.py +96 -53
  217. package/src/skf-campaign/scripts/campaign-quality-gate.py +592 -0
  218. package/src/skf-campaign/scripts/campaign-render-batch.py +257 -49
  219. package/src/skf-campaign/scripts/campaign-render-kickoff.py +343 -50
  220. package/src/skf-campaign/scripts/campaign-report.py +204 -37
  221. package/src/skf-campaign/scripts/campaign-state.py +1128 -0
  222. package/src/skf-campaign/scripts/campaign-status.py +10 -74
  223. package/src/skf-campaign/scripts/campaign-validate-pins.py +30 -3
  224. package/src/skf-campaign/scripts/campaign-validate-state.py +34 -4
  225. package/src/skf-campaign/templates/campaign-brief-template.yaml +4 -5
  226. package/src/skf-campaign/templates/campaign-report-template.md +5 -1
  227. package/src/skf-campaign/templates/kickoff-template.md +0 -14
  228. package/src/skf-create-skill/SKILL.md +27 -20
  229. package/src/skf-create-skill/assets/compile-assembly-rules.md +6 -5
  230. package/src/skf-create-skill/assets/skill-sections.md +15 -5
  231. package/src/skf-create-skill/customize.toml +20 -8
  232. package/src/skf-create-skill/references/authoritative-files-protocol.md +41 -42
  233. package/src/skf-create-skill/references/batch-mode.md +81 -0
  234. package/src/skf-create-skill/references/ccc-index-check.md +27 -0
  235. package/src/skf-create-skill/references/compile.md +107 -29
  236. package/src/skf-create-skill/references/component-extraction.md +113 -91
  237. package/src/skf-create-skill/references/enrich.md +41 -23
  238. package/src/skf-create-skill/references/entry-points-by-hand.md +20 -0
  239. package/src/skf-create-skill/references/extract.md +200 -161
  240. package/src/skf-create-skill/references/extraction-patterns-by-hand.md +141 -0
  241. package/src/skf-create-skill/references/extraction-patterns-tracing.md +2 -2
  242. package/src/skf-create-skill/references/extraction-patterns.md +584 -196
  243. package/src/skf-create-skill/references/generate-artifacts.md +145 -93
  244. package/src/skf-create-skill/references/health-check.md +1 -1
  245. package/src/skf-create-skill/references/load-brief.md +53 -36
  246. package/src/skf-create-skill/references/relabel-rule.md +12 -0
  247. package/src/skf-create-skill/references/report.md +28 -59
  248. package/src/skf-create-skill/references/source-resolution-protocols.md +49 -155
  249. package/src/skf-create-skill/references/step-auto-shard.md +20 -93
  250. package/src/skf-create-skill/references/step-doc-rot.md +44 -60
  251. package/src/skf-create-skill/references/step-doc-sources.md +28 -19
  252. package/src/skf-create-skill/references/sub/ccc-discover.md +18 -7
  253. package/src/skf-create-skill/references/sub/fetch-docs.md +106 -59
  254. package/src/skf-create-skill/references/sub/fetch-temporal.md +53 -166
  255. package/src/skf-create-skill/references/tier-degradation-rules.md +18 -9
  256. package/src/skf-create-skill/references/validate.md +173 -99
  257. package/src/skf-create-skill/scripts/scan-doc-rot.py +232 -99
  258. package/src/skf-create-stack-skill/SKILL.md +29 -56
  259. package/src/skf-create-stack-skill/assets/metadata-contract.md +51 -0
  260. package/src/skf-create-stack-skill/assets/provenance-map-schema.md +15 -15
  261. package/src/skf-create-stack-skill/assets/stack-skill-template.md +23 -57
  262. package/src/skf-create-stack-skill/customize.toml +23 -12
  263. package/src/skf-create-stack-skill/references/compile-stack.md +57 -66
  264. package/src/skf-create-stack-skill/references/compose-mode-rules.md +24 -44
  265. package/src/skf-create-stack-skill/references/detect-integrations.md +92 -95
  266. package/src/skf-create-stack-skill/references/detect-manifests.md +46 -71
  267. package/src/skf-create-stack-skill/references/generate-output.md +138 -128
  268. package/src/skf-create-stack-skill/references/init.md +90 -32
  269. package/src/skf-create-stack-skill/references/integration-patterns.md +1 -17
  270. package/src/skf-create-stack-skill/references/invocation-contract.md +34 -0
  271. package/src/skf-create-stack-skill/references/manifest-patterns.md +32 -20
  272. package/src/skf-create-stack-skill/references/parallel-extract.md +112 -38
  273. package/src/skf-create-stack-skill/references/rank-and-confirm.md +57 -75
  274. package/src/skf-create-stack-skill/references/report.md +39 -33
  275. package/src/skf-create-stack-skill/references/validate.md +20 -39
  276. package/src/skf-drop-skill/SKILL.md +28 -51
  277. package/src/skf-drop-skill/customize.toml +44 -30
  278. package/src/skf-drop-skill/references/execute.md +79 -146
  279. package/src/skf-drop-skill/references/invocation-contract.md +64 -0
  280. package/src/skf-drop-skill/references/report.md +46 -30
  281. package/src/skf-drop-skill/references/select.md +118 -124
  282. package/src/skf-drop-skill/scripts/dir-sizes.py +54 -26
  283. package/src/skf-drop-skill/scripts/drop-roster.py +322 -0
  284. package/src/skf-export-skill/SKILL.md +40 -62
  285. package/src/skf-export-skill/assets/managed-section-format.md +14 -50
  286. package/src/skf-export-skill/assets/snippet-format.md +3 -1
  287. package/src/skf-export-skill/customize.toml +42 -13
  288. package/src/skf-export-skill/references/generate-snippet.md +54 -46
  289. package/src/skf-export-skill/references/health-check.md +2 -0
  290. package/src/skf-export-skill/references/invocation-contract.md +15 -0
  291. package/src/skf-export-skill/references/load-skill.md +88 -62
  292. package/src/skf-export-skill/references/manifest-rebuild.md +9 -10
  293. package/src/skf-export-skill/references/multi-skill-mode.md +4 -4
  294. package/src/skf-export-skill/references/orphan-context-detection.md +13 -5
  295. package/src/skf-export-skill/references/orphan-row-detection.md +31 -22
  296. package/src/skf-export-skill/references/package.md +15 -73
  297. package/src/skf-export-skill/references/preflight-snippet-root-probe.md +51 -70
  298. package/src/skf-export-skill/references/result-envelope.md +31 -16
  299. package/src/skf-export-skill/references/summary.md +41 -17
  300. package/src/skf-export-skill/references/token-report.md +4 -12
  301. package/src/skf-export-skill/references/update-context.md +118 -237
  302. package/src/skf-forger/SKILL.md +61 -37
  303. package/src/skf-forger/bmad-skill-manifest.yaml +4 -1
  304. package/src/skf-forger/customize.toml +43 -0
  305. package/src/skf-forger/references/pipeline-mode.md +73 -18
  306. package/src/skf-forger/scripts/forge-status.py +299 -0
  307. package/src/skf-forger/scripts/parse-pipeline.py +322 -54
  308. package/src/skf-forger/scripts/pipeline-gate.py +428 -0
  309. package/src/skf-forger/scripts/pipeline-journal.py +1052 -0
  310. package/src/skf-quick-skill/SKILL.md +54 -53
  311. package/src/skf-quick-skill/assets/skill-template.md +4 -2
  312. package/src/skf-quick-skill/customize.toml +51 -20
  313. package/src/skf-quick-skill/references/batch-mode.md +74 -21
  314. package/src/skf-quick-skill/references/compile.md +30 -31
  315. package/src/skf-quick-skill/references/ecosystem-check.md +7 -57
  316. package/src/skf-quick-skill/references/finalize.md +69 -18
  317. package/src/skf-quick-skill/references/halt-contract.md +41 -29
  318. package/src/skf-quick-skill/references/health-check.md +5 -3
  319. package/src/skf-quick-skill/references/quick-extract.md +114 -45
  320. package/src/skf-quick-skill/references/registry-resolution.md +9 -64
  321. package/src/skf-quick-skill/references/resolve-target.md +116 -66
  322. package/src/skf-quick-skill/references/write-and-validate.md +79 -40
  323. package/src/skf-refine-architecture/SKILL.md +43 -53
  324. package/src/skf-refine-architecture/customize.toml +49 -20
  325. package/src/skf-refine-architecture/references/compile.md +97 -54
  326. package/src/skf-refine-architecture/references/exit-codes.md +30 -0
  327. package/src/skf-refine-architecture/references/finding-storage.md +21 -0
  328. package/src/skf-refine-architecture/references/gap-analysis.md +101 -38
  329. package/src/skf-refine-architecture/references/improvements.md +14 -20
  330. package/src/skf-refine-architecture/references/init.md +98 -57
  331. package/src/skf-refine-architecture/references/issue-detection.md +32 -39
  332. package/src/skf-refine-architecture/references/refinement-rules.md +37 -48
  333. package/src/skf-refine-architecture/references/report.md +65 -54
  334. package/src/skf-refine-architecture/scripts/skf-check-preservation.py +1619 -0
  335. package/src/skf-rename-skill/SKILL.md +19 -54
  336. package/src/skf-rename-skill/customize.toml +32 -26
  337. package/src/skf-rename-skill/references/execute.md +230 -184
  338. package/src/skf-rename-skill/references/exit-codes.md +7 -7
  339. package/src/skf-rename-skill/references/health-check.md +1 -7
  340. package/src/skf-rename-skill/references/invocation-contract.md +25 -0
  341. package/src/skf-rename-skill/references/report.md +63 -52
  342. package/src/skf-rename-skill/references/select.md +197 -115
  343. package/src/skf-rename-skill/scripts/skf-validate-rename-name.py +161 -21
  344. package/src/skf-setup/SKILL.md +26 -26
  345. package/src/skf-setup/customize.toml +14 -10
  346. package/src/skf-setup/references/auto-index.md +50 -63
  347. package/src/skf-setup/references/ccc-index.md +29 -90
  348. package/src/skf-setup/references/detect-and-tier.md +58 -67
  349. package/src/skf-setup/references/health-check.md +2 -0
  350. package/src/skf-setup/references/invocation-contract.md +14 -0
  351. package/src/skf-setup/references/report.md +43 -166
  352. package/src/skf-setup/references/tier-rules.md +5 -5
  353. package/src/skf-setup/references/write-config.md +34 -57
  354. package/src/skf-test-skill/SKILL.md +17 -57
  355. package/src/skf-test-skill/assets/output-section-formats.md +33 -34
  356. package/src/skf-test-skill/customize.toml +27 -13
  357. package/src/skf-test-skill/references/coherence-check.md +134 -62
  358. package/src/skf-test-skill/references/coverage-check-tiers.md +35 -0
  359. package/src/skf-test-skill/references/coverage-check.md +217 -254
  360. package/src/skf-test-skill/references/detect-mode.md +5 -5
  361. package/src/skf-test-skill/references/external-validators.md +94 -82
  362. package/src/skf-test-skill/references/health-check.md +6 -7
  363. package/src/skf-test-skill/references/init.md +163 -88
  364. package/src/skf-test-skill/references/invocation-contract.md +66 -0
  365. package/src/skf-test-skill/references/migration-section-rules.md +5 -2
  366. package/src/skf-test-skill/references/report.md +162 -142
  367. package/src/skf-test-skill/references/score.md +80 -107
  368. package/src/skf-test-skill/references/scoring-rules.md +41 -155
  369. package/src/skf-test-skill/references/source-access-protocol.md +19 -92
  370. package/src/skf-test-skill/references/step-hard-gate.md +51 -33
  371. package/src/skf-test-skill/scripts/aggregate-coherence.py +218 -30
  372. package/src/skf-test-skill/scripts/build-result-context.py +287 -0
  373. package/src/skf-test-skill/scripts/check-metadata-coherence.py +37 -4
  374. package/src/skf-test-skill/scripts/combine-external-scores.py +23 -6
  375. package/src/skf-test-skill/scripts/compute-score.py +223 -45
  376. package/src/skf-test-skill/scripts/gap-ledger.py +1381 -0
  377. package/src/skf-test-skill/scripts/hard-gate.py +203 -0
  378. package/src/skf-test-skill/scripts/load-coverage-inputs.py +760 -0
  379. package/src/skf-test-skill/scripts/locate-export-segments.py +835 -0
  380. package/src/skf-test-skill/scripts/reconcile-coverage.py +273 -79
  381. package/src/skf-test-skill/scripts/score-signatures.py +459 -0
  382. package/src/skf-test-skill/scripts/stage-helper-payload.py +148 -0
  383. package/src/skf-test-skill/scripts/validate-inventory.py +311 -16
  384. package/src/skf-test-skill/scripts/verify-declared-numerator.py +127 -52
  385. package/src/skf-test-skill/templates/test-report-template.md +21 -15
  386. package/src/skf-update-skill/SKILL.md +38 -25
  387. package/src/skf-update-skill/customize.toml +27 -12
  388. package/src/skf-update-skill/references/detect-changes.md +233 -222
  389. package/src/skf-update-skill/references/gap-driven.md +336 -0
  390. package/src/skf-update-skill/references/health-check.md +31 -5
  391. package/src/skf-update-skill/references/init.md +250 -84
  392. package/src/skf-update-skill/references/invocation-contract.md +12 -0
  393. package/src/skf-update-skill/references/manual-section-rules.md +6 -23
  394. package/src/skf-update-skill/references/merge.md +180 -47
  395. package/src/skf-update-skill/references/re-extract.md +53 -262
  396. package/src/skf-update-skill/references/report.md +100 -35
  397. package/src/skf-update-skill/references/write.md +331 -149
  398. package/src/skf-update-skill/scripts/skf-new-file-diff.py +29 -7
  399. package/src/skf-verify-stack/SKILL.md +23 -42
  400. package/src/skf-verify-stack/assets/feasibility-report-template.md +11 -5
  401. package/src/skf-verify-stack/customize.toml +55 -22
  402. package/src/skf-verify-stack/references/coverage-patterns.md +17 -8
  403. package/src/skf-verify-stack/references/coverage.md +67 -64
  404. package/src/skf-verify-stack/references/exit-codes.md +21 -8
  405. package/src/skf-verify-stack/references/init.md +107 -62
  406. package/src/skf-verify-stack/references/integration-verification-rules.md +12 -13
  407. package/src/skf-verify-stack/references/integrations.md +106 -65
  408. package/src/skf-verify-stack/references/report.md +59 -42
  409. package/src/skf-verify-stack/references/requirements.md +32 -9
  410. package/src/skf-verify-stack/references/synthesize.md +53 -39
  411. package/src/skf-verify-stack/scripts/skf-coverage-tally.py +398 -52
  412. package/src/skf-verify-stack/scripts/skf-previous-report.py +330 -0
  413. package/src/skf-verify-stack/scripts/skf-report-delta.py +453 -49
  414. package/src/skf-verify-stack/scripts/skf-verdict-rollup.py +240 -27
  415. package/tools/cli/commands/install.js +11 -4
  416. package/tools/cli/commands/status.js +15 -3
  417. package/tools/cli/commands/update.js +11 -4
  418. package/tools/cli/lib/tool-check.js +320 -0
  419. package/tools/cli/lib/version-check.js +22 -9
  420. package/tools/cli/skf-cli.js +4 -1
  421. package/.gitattributes +0 -16
  422. package/.nvmrc +0 -1
  423. package/docs/_internal/RELEASING.md +0 -679
  424. package/release-audits/v1.0.0-launch-audit.md +0 -728
  425. package/src/skf-audit-skill/references/step-doc-drift.md +0 -177
  426. package/src/skf-brief-skill/references/headless-source-authority-detection.md +0 -26
  427. package/src/skf-campaign/manifest.yaml +0 -15
  428. package/src/skf-create-skill/assets/tessl-dismissal-rules.md +0 -106
  429. package/src/skf-create-skill/references/ecosystem-check.md +0 -74
  430. package/src/skf-drop-skill/references/headless-contract.md +0 -18
  431. package/src/skf-update-skill/references/merge-conflict-rules.md +0 -15
  432. package/src/skf-update-skill/references/remote-source-resolution.md +0 -98
  433. package/src/skf-update-skill/references/validate.md +0 -124
  434. package/tools/validate-docs-drift.js +0 -233
  435. package/tools/validate-docs-links.js +0 -665
@@ -1,7 +1,31 @@
1
1
  ---
2
2
  nextStepFile: 'recommend.md'
3
3
  outputFile: '{forge_data_folder}/analyze-source-report-{project_name}.md'
4
- heuristicsFile: '{unitDetectionHeuristicsPath}'
4
+ heuristicsFile: 'references/unit-detection-heuristics.md'
5
+ discoverFile: 'references/discover-additional-source.md'
6
+ unitExportsFile: 'references/map-unit-exports.md'
7
+ scanRootFile: 'references/scan-root.md'
8
+ extractPublicApiProbeOrder:
9
+ - '{project-root}/_bmad/skf/shared/scripts/skf-extract-public-api.py'
10
+ - '{project-root}/src/shared/scripts/skf-extract-public-api.py'
11
+ scanManifestsProbeOrder:
12
+ - '{project-root}/_bmad/skf/shared/scripts/skf-scan-manifests.py'
13
+ - '{project-root}/src/shared/scripts/skf-scan-manifests.py'
14
+ countImportsProbeOrder:
15
+ - '{project-root}/_bmad/skf/shared/scripts/skf-count-imports.py'
16
+ - '{project-root}/src/shared/scripts/skf-count-imports.py'
17
+ findCyclesProbeOrder:
18
+ - '{project-root}/_bmad/skf/shared/scripts/skf-find-cycles.py'
19
+ - '{project-root}/src/shared/scripts/skf-find-cycles.py'
20
+ pairIntersectProbeOrder:
21
+ - '{project-root}/_bmad/skf/shared/scripts/skf-pair-intersect.py'
22
+ - '{project-root}/src/shared/scripts/skf-pair-intersect.py'
23
+ skillInventoryProbeOrder:
24
+ - '{project-root}/_bmad/skf/shared/scripts/skf-skill-inventory.py'
25
+ - '{project-root}/src/shared/scripts/skf-skill-inventory.py'
26
+ checkUnitRecordsProbeOrder:
27
+ - '{project-root}/_bmad/skf/shared/scripts/skf-check-unit-records.py'
28
+ - '{project-root}/src/shared/scripts/skf-check-unit-records.py'
5
29
  ---
6
30
 
7
31
  <!-- Config: communicate in {communication_language}. -->
@@ -10,22 +34,31 @@ heuristicsFile: '{unitDetectionHeuristicsPath}'
10
34
 
11
35
  ## STEP GOAL:
12
36
 
13
- To analyze each qualifying unit's export surface and import graph, detect cross-unit integration points, and flag potential stack skill candidates — completing the analysis foundation needed for recommendations.
37
+ To analyze each qualifying unit's export surface and import graph, detect cross-unit integration points, propose composite merges and flag potential stack skill candidates, completing the analysis foundation needed for recommendations.
14
38
 
15
39
  ## Rules
16
40
 
17
41
  - Delegate per-unit deep analysis to a subagent when available (parallelizes across units; main-thread fallback is fine)
18
42
  - For each qualifying unit, perform thorough export surface analysis — do not shortcut
19
43
  - Do not make recommendations (Step 05)
20
- - Tier-aware depth: Quick (file-level), Forge (AST), Deep (AST + semantic)
21
44
 
22
45
  ## MANDATORY SEQUENCE
23
46
 
47
+ Every HARD HALT in this step names its exit code, `halt_reason` and phase. When `{headless_mode}` is true it first prints its envelope on stderr through the shared emitter (`{emitEnvelopeHelper}` and `{run_dir}` come from SKILL.md On Activation): stage `{run_dir}/halt.json` as `{"phase": "<phase>", "reason": "<the halt message>", "halt_reason": "<halt_reason>", "mode": "interactive", "report_path": "{outputFile as an absolute path}"}`, plus `"path"` when the halt names one, then run
48
+
49
+ ```bash
50
+ uv run {emitEnvelopeHelper} emit-halt --workflow skf-analyze-source --run-dir "{run_dir}" --target stderr < "{run_dir}/halt.json"
51
+ ```
52
+
53
+ and display the line it prints verbatim. Write the payload as valid JSON: in the halt message and `path`, replace each backslash with / and each double quote with a backtick. If the emitter exits non-zero or prints no line, display the halt message alone. An interactive HALT displays its message and emits nothing.
54
+
24
55
  ### 1. Load Context
25
56
 
26
57
  Read {outputFile} to obtain:
27
- - Qualifying units from Identified Units section (names, paths, scope types, languages)
28
- - `forge_tier` from frontmatter
58
+ - Qualifying units from the Identified Units section: names, project paths, paths, scope types, languages, file counts, statuses and each unit's own manifest (path, name and ecosystem). A unit whose status is `deferred` (outside the goal the user stated) stays in the report and is not analyzed here
59
+ - `forge_tier`, `scan_roots` (each project path's scan root) and `refs` from frontmatter
60
+
61
+ **A scan root that is gone.** A session that resumed this report runs in a new run folder, and the folder of the session that made a copy may be gone. When a recorded scan root no longer exists, make it again by {scanRootFile} into this run's `{run_dir}/source-{i}` and update `scan_roots` in {outputFile}'s frontmatter. If a command there fails, HARD HALT (exit code 3, `halt_reason: "resolution-failure"`, phase `map-and-detect:1`, path `{path}`): "{path} could not be fetched: {the first stderr line}."
29
62
 
30
63
  Load {heuristicsFile} for stack skill candidate detection rules.
31
64
 
@@ -33,91 +66,65 @@ Load {heuristicsFile} for stack skill candidate detection rules.
33
66
 
34
67
  For each qualifying unit, delegate deep analysis to a subagent so per-unit work runs in parallel and the parent's context stays clean.
35
68
 
69
+ **Resolve `{extractPublicApiHelper}`** from `{extractPublicApiProbeOrder}` and **`{checkUnitRecordsHelper}`** from `{checkUnitRecordsProbeOrder}`; first existing path wins for each. If one has no candidate, HARD HALT (exit code 3, `halt_reason: "resolution-failure"`, phase `map-and-detect:2`): "`{the missing script}` is missing. Re-install SKF."
70
+
36
71
  **Subagent fan-out protocol:**
37
72
 
38
- 1. **Build the qualifying-unit list.** Read the unit list produced upstream (Step §3 / §4 outputs already in workflow context — names, paths, scope types, languages, file counts). Do not re-scan the project here.
39
-
40
- 2. **Delegate per-unit deep analysis to a subagent.** For each qualifying unit, launch a subagent task with these explicit constraints:
41
- - The subagent reads only that unit's directory tree
42
- - The subagent analyzes exports / usage / CCC signals / scripts+assets for that one unit
43
- - **The parent does not read the unit's source files before delegating** (avoid the implicit-read trap — the whole point of fan-out is to keep large source bodies out of the parent's context)
44
-
45
- 3. **Per-unit analysis the subagent performs (scaled by size-aware strategy):**
46
-
47
- **Size-aware strategy selection:**
48
- - **< 50 files:** Full export scan — analyze every file for exports
49
- - **50-200 files:** Targeted scan — entry points (`__init__.py`, `index.ts`, `lib.rs`) + public modules + barrel exports only
50
- - **200+ files:** Entry-point strategy — analyze top-level entry point for public API surface, list submodule entry points, analyze each submodule entry point only. Report coverage confidence based on percentage of files analyzed.
51
-
52
- **Tier-aware depth:**
53
- - **Quick tier:** Count files by type, identify index/barrel files, list directory structure
54
- - **Forge tier:** Parse export statements, identify public API surface, count exported functions/classes/types
55
- - **Forge+ tier:** All Forge analysis plus:
56
- - If `tools.ccc` is true: run `ccc_bridge.search("{unit_name} exports public API", top_k=15)` to discover semantically relevant files beyond directory scan. Tool resolution: prefer the `/ccc` skill search (Claude Code) or ccc MCP server (Cursor); fall back to the `ccc search` CLI if neither is available; if no ccc tool resolves, skip CCC discovery and record `ccc: unavailable` in per-unit findings.
57
- - Merge CCC-discovered files with scoped file list — files from CCC that are within the unit's directory are added to the analysis queue
58
- - Record CCC signals in per-unit findings: top 3 CCC-ranked file names (or "—" if no ccc results)
59
- - **Deep tier:** All Forge analysis plus:
60
- - ast-grep structural export extraction: `ast-grep -p 'export $$$' --lang typescript` or equivalent per language to build a verified export inventory
61
- - ast-grep type/interface mapping: `ast-grep -p 'interface $NAME' --lang typescript` or `ast-grep -p 'class $NAME($$$)' --lang python`
62
- - If QMD available: query for temporal evolution of identified exports (deprecation signals, recent additions, refactoring patterns)
63
- - Record semantic relationships between exports (which exports reference/depend on each other)
64
-
65
- **Subagent must also record:**
66
- - Script/asset presence: check for `scripts/`, `bin/`, `assets/`, `templates/` directories and files matching detection signals in `{heuristicsFile}`
67
- - Analysis strategy used and coverage confidence
68
-
69
- 4. **Subagent return contract.** Each subagent returns only this JSON object — no prose, no commentary, no markdown fences:
70
-
71
- ```json
72
- {
73
- "unit_name": "...",
74
- "files_count": N,
75
- "exports_count": N,
76
- "export_pattern": "...",
77
- "api_surface": ["..."],
78
- "scripts_assets": {"scripts": [], "assets": []},
79
- "ccc_signals": {"top_files": [], "available": <bool>},
80
- "strategy_used": "ast-grep|regex|main-thread",
81
- "confidence": "T1|T2|T1-low"
82
- }
83
- ```
84
-
85
- 5. **Parent post-processing.** Strip any wrapping markdown fences (subagents sometimes wrap JSON in ` ```json … ``` ` despite the contract) before parsing. Validate each payload against the contract; if a key is missing, log a warning to `workflow_warnings[]` and continue with that unit's degraded record.
86
-
87
- 6. **Aggregate.** Collect all per-unit JSON payloads into `per_unit_findings[]` in workflow context for use by §3 (import graph), §4 (integration points), §5 (stack candidates), §6 (findings presentation), and downstream stages (recommend.md, generate-briefs.md).
73
+ 1. **Build the qualifying-unit list.** Read the unit list produced upstream (names, project paths, paths, scope types, languages, file counts), leaving out the deferred units. Do not re-scan the project here.
88
74
 
89
- **Per-unit export summary (built from `per_unit_findings[]`):**
75
+ 2. **Map each unit's exports.** Load, read the entire file, then execute {unitExportsFile} for the qualifying units: it delegates each one to a subagent with `{unit_root}` its path under the scan root of its project path and its file count from Identified Units, has the subagent write the unit's record to `{run_dir}/unit-records/{unit_name}.json`, checks the records and returns them.
90
76
 
91
- | Unit | Files | Exports | Export Pattern | API Surface | Scripts/Assets | CCC Signals |
92
- |------|-------|---------|----------------|-------------|----------------|-------------|
93
- | {name} | {count} | {count} | {pattern} | {small/medium/large} | {N scripts, M assets or --} | {CCC signals or --} |
77
+ 3. **Aggregate.** Collect the checked `records` into `per_unit_findings[]` in workflow context for use by §3 (import graph), §4 (integration points), §5 (composites and stack candidates), §6 (findings presentation), and downstream stages (recommend.md, generate-briefs.md).
94
78
 
95
- **Graceful degradation.** If subagents are unavailable in the current runtime, the parent performs the per-unit analysis sequentially in the main thread using the same size-aware strategy and tier-aware depth as above. Each main-thread analysis still produces the same JSON record shape so downstream stages remain agnostic to the execution mode. Record `strategy_used: "main-thread"` for every unit processed this way.
79
+ **Per-unit export summary (built from `per_unit_findings[]`):**
80
+
81
+ | Unit | Files | Exports | Export Pattern | API Surface | CCC Signals |
82
+ |------|-------|---------|----------------|-------------|-------------|
83
+ | {name} | {count} | {count} | {pattern} | {small/medium/large} | {CCC signals or --} |
96
84
 
97
85
  ### 3. Map Import Graph
98
86
 
99
- For each qualifying unit, analyze inbound and outbound imports:
87
+ Which unit imports which, how many files import each unit, which units are imported together and which import each other in a cycle each have one right answer per tree, so the helpers compute them and this section reads their output.
88
+
89
+ **Resolve `{scanManifestsHelper}`, `{countImportsHelper}`, `{findCyclesHelper}` and `{pairIntersectHelper}`** from their probe orders; first existing path wins for each. If one has no candidate, HARD HALT (exit code 3, `halt_reason: "resolution-failure"`, phase `map-and-detect:3`): "`{the missing script}` is missing. Re-install SKF."
90
+
91
+ **Units JSON.** One entry per qualifying unit, from its Identified Units row: `{"name": "<unit name>", "path": "<its path, relative to the source root>", "manifest_name": "<its own manifest's name>", "ecosystem": "<its own manifest's ecosystem>"}`, with `manifest_name` and `ecosystem` left out for a unit without a manifest. The import helper works out the names other code imports each unit by from what the unit declares. Add `"modules"` only for a folder without a manifest that code imports by name: a Python package folder (`["acme"]`) or a Go package inside a module (`["example.com/svc/internal/auth"]`).
92
+
93
+ Run this once per project path, the `{i}`-th entry of `project_paths[]`, with `{source_root}` its scan root, over the units under it. `{run_dir}/manifests-{i}.json` is the manifest scan scan-project wrote; when it is missing, as in a session that resumed the report, run `uv run {scanManifestsHelper} scan "{source_root}" > "{run_dir}/manifests-{i}.json"` first.
94
+
95
+ ```bash
96
+ cat > "{run_dir}/units-{i}.json" <<'SKF_UNITS'
97
+ {"units": [<one entry per qualifying unit under {source_root}>]}
98
+ SKF_UNITS
99
+ uv run {countImportsHelper} count "{source_root}" --units "{run_dir}/units-{i}.json" --deps "{run_dir}/manifests-{i}.json" > "{run_dir}/imports-{i}.json"
100
+ uv run {countImportsHelper} summary "{run_dir}/imports-{i}.json" --manifests "{run_dir}/manifests-{i}.json"
101
+ uv run {findCyclesHelper} find --edges "{run_dir}/imports-{i}.json"
102
+ uv run {countImportsHelper} count "{source_root}" --units "{run_dir}/units-{i}.json" --format libraries > "{run_dir}/importers-{i}.json"
103
+ uv run {pairIntersectHelper} intersect --libraries "{run_dir}/importers-{i}.json"
104
+ ```
100
105
 
101
- **Outbound imports (this unit imports from):**
102
- - Which other qualifying units does it depend on?
103
- - Which external dependencies does it use?
106
+ A helper that exits non-zero names the problem on stderr (a unit name or path given twice, a malformed entry): fix the units JSON and run the block again.
104
107
 
105
- **Inbound imports (other units import from this):**
106
- - Which other qualifying units consume this unit's exports?
107
- - How many import sites exist?
108
+ Read the output. The `summary` line prints the graph without the file lists, which stay in `{run_dir}/imports-{i}.json`:
109
+
110
+ - **Imports From / Imported By:** each summary `units[]` entry's `imports_from` and `imported_by`. Its `file_count` is the number of import sites (files outside the unit that import it).
111
+ - **External Deps:** each summary `units[]` entry's `external_dep_count`, the number of manifest dependencies its files import.
112
+ - **Mutual dependencies:** each `cycles[]` entry (`["a", "b", "a"]` is two units that import each other).
113
+ - **Co-imported units:** each `pairs[]` entry: `intersection_count` files import both units, listed in `files`. When `truncated` is true, run that last call again with `--top-k` set to its `total_pairs`, so no pair is left out.
114
+ - **Cohesion evidence:** the summary's `umbrella_candidates[]` and `manifests[]` (each manifest's `name`, `private` and `internal_deps`), which §5 reads.
108
115
 
109
116
  **Build cross-reference matrix:**
110
117
 
111
- | Unit | Imports From | Imported By | External Deps |
112
- |------|-------------|-------------|---------------|
113
- | {name} | {list units} | {list units} | {count} |
118
+ | Unit | Imports From | Imported By | Import Sites | External Deps |
119
+ |------|-------------|-------------|--------------|---------------|
120
+ | {name} | {imports_from} | {imported_by} | {file_count} | {external_dep_count, or --} |
114
121
 
115
122
  ### 4. Detect Integration Points
116
123
 
117
124
  Identify cross-unit integration patterns:
118
125
 
119
126
  **Direct integrations:**
120
- - Unit A imports from Unit B → document the interface boundary
127
+ - Each §3 summary `edge_files[]` entry (unit `from` imports from unit `to` in `file_count` files, the first of them listed in `files` with the line of their first import) → document the interface boundary. When the boundary needs every file, read that entry in `{run_dir}/imports-{i}.json`
121
128
  - Shared type definitions across units
122
129
  - Cross-unit function calls
123
130
 
@@ -127,70 +134,81 @@ Identify cross-unit integration patterns:
127
134
  - Files involved (with paths)
128
135
  - Coupling strength (tight / loose / indirect)
129
136
 
130
- ### 5. Flag Stack Skill Candidates
137
+ ### 5. Decide Composites and Stack Skill Candidates
138
+
139
+ Decide both here, in one pass over §3's graph and §4's integration map, so each group of units is judged once: a **composite** when its units only deliver value together, a **stack skill candidate** when each is useful on its own and they are also used together. A group is never both.
131
140
 
132
- Check each of the four stack-skill indicators defined in {heuristicsFile}'s Stack Skill Candidate Detection section — co-import frequency, integration adapter, shared state, orchestration layer — against the units.
141
+ **Resolve `{skillInventoryHelper}`** from `{skillInventoryProbeOrder}`; first existing path wins. If no candidate exists, HARD HALT (exit code 3, `halt_reason: "resolution-failure"`, phase `map-and-detect:5`): "`skf-skill-inventory.py` is missing. Re-install SKF."
133
142
 
134
- **For each candidate, document:**
143
+ 1. **Composite merge proposals.** Apply the Composite Boundary triggers in {heuristicsFile} (mutual hard dependency, shared integration surface, and the Cohesion Triggers: umbrella facade, shared runtime contract, internal building blocks) to the qualifying units. The evidence comes from the helpers: `cycles[]` for a mutual dependency, `edge_files[]` and §4's shared types for a shared integration surface, and the §3 summary's `umbrella_candidates[]` and each manifest's `internal_deps` and `private` for the cohesion triggers. For each group that meets a trigger, propose one composite:
144
+ - **Constituents:** the unit names and paths merged
145
+ - **Heuristic and evidence:** the trigger and what showed it (the cycle, the umbrella candidate and the members its `internal_deps` cover, the `private` flags, the shared types and their files)
146
+ - **Name:** name every proposal in one call to the helper that names every unit and brief ({heuristicsFile}'s Unit Names), one entry each: `target` is its constituents' project path, `manifest_name` the facade's manifest name when an umbrella facade triggered the merge (else null), and `members` the constituents' manifest names:
147
+ ```bash
148
+ uv run {skillInventoryHelper} derive-name --from - <<'SKF_COMPOSITE_NAMES'
149
+ [{"target": "<project path>", "manifest_name": "<facade name or null>", "members": ["<constituent manifest name>", ...]}, ...]
150
+ SKF_COMPOSITE_NAMES
151
+ ```
152
+ Each `names[].name` is that proposal's name; give the entries `unnamed` and `duplicates` list a name of your own, from their constituents.
153
+ 2. **Stack skill candidates.** Check the four stack-skill indicators defined in {heuristicsFile}'s Stack Skill Candidate Detection section against the units no composite proposal groups: co-import frequency is a §3 `pairs[]` entry with an `intersection_count` of 3 or more, and integration adapter, shared state and orchestration layer come from §4. When the user rejects a composite in §6, check its constituents here too.
154
+
155
+ **For each stack skill candidate, document:**
135
156
  - Units involved
136
157
  - Detection signal
137
158
  - Recommended stack skill grouping
138
159
  - Evidence (specific files/lines)
139
160
 
140
- ### 6. Present Findings
161
+ ### 6. Present the Findings and Confirm
141
162
 
142
- "**Export Mapping and Integration Detection Complete**
163
+ Show the user the per-unit export summary, the cross-reference matrix, each integration point (source to target, type, coupling), the composite merge proposals, the stack skill candidates (units involved and detection signal), and the observations (key architectural patterns, tightly and loosely coupled areas). Present the proposals as a table:
143
164
 
144
- **Export Map Summary:**
145
- {Per-unit export summary table}
165
+ | # | Composite Name | Constituents | Heuristic | Evidence |
166
+ |---|----------------|--------------|-----------|----------|
167
+ | 1 | {name} | {constituent unit names and paths} | {mutual hard dependency / shared integration surface / umbrella facade / shared runtime contract / internal building blocks} | {evidence} |
146
168
 
147
- **Cross-Reference Matrix:**
148
- {Import graph matrix}
169
+ Then display:
149
170
 
150
- **Integration Points:** {count}
151
- {List each integration with source → target, type, coupling}
171
+ "Accept or reject each composite merge proposal (every one is accepted unless you reject it), or name an integration pattern to investigate further. **Select:** [C] Continue to Recommendations | [D] Discover Additional Source | [X] Cancel and exit"
152
172
 
153
- **Stack Skill Candidates:** {count}
154
- {List each candidate with units involved and detection signal}
173
+ An approved composite replaces its constituents as one unit: `Boundary Type: Composite`, its constituents' paths as its Path, the project path they share, the scope type and language of its dominant constituent (the one with the most exports), and confidence from the strength of its trigger. A rejected one leaves its constituents as separate units.
155
174
 
156
- **Observations:**
157
- - {Key architectural patterns observed}
158
- - {Tightly coupled areas}
159
- - {Loosely coupled areas ideal for independent skills}
175
+ #### Menu Handling Logic:
160
176
 
161
- Does this analysis look complete? Any integration patterns I should investigate further?"
177
+ - IF C: go to §7
178
+ - IF D: load, read the entire file, then execute {discoverFile} with the project path the user gives. It adds the new path's units to Identified Units and returns their export records, import graph, composite proposals and stack skill candidates, which join the findings here, so §7 writes the Export Map and Integration Points with them: redisplay §6 with them included.
179
+ - IF X: HARD HALT (exit code 6, `halt_reason: "user-cancelled"`, phase `map-and-detect:6`): "Cancelled at the export mapping."
180
+ - IF Any other: apply the composite decisions, investigate what the user named, show what changed, then [Redisplay Menu Options](#6-present-the-findings-and-confirm)
181
+
182
+ **GATE [default: C]**: present the menu and wait for the user's choice. If `{headless_mode}`: accept every composite merge proposal and continue with [C], and record that decision the moment it is taken: stage `{run_dir}/decision.json` as `{"gate": "map-and-detect.findings", "default_action": "C", "taken_action": "C", "reason": "headless: auto-accept {count} composite merges and continue past the integration analysis", "evidence": {"composites": [<the name of each accepted composite>], "stack_skill_candidates": <the candidate count>}}`, then run
183
+
184
+ ```bash
185
+ uv run {emitEnvelopeHelper} record --workflow skf-analyze-source --run-dir "{run_dir}" --decision < "{run_dir}/decision.json"
186
+ ```
162
187
 
163
- Wait for user feedback. Adjust analysis based on user input.
188
+ If the command fails, go on: only that entry is lost.
164
189
 
165
- ### 7. Append to Report
190
+ ### 7. Append to Report and Continue
166
191
 
167
- Append the complete "## Export Map" section to {outputFile}:
168
- Replace `[Appended by map-and-detect]` under Export Map with:
192
+ Replace `[Appended by map-and-detect]` under Export Map in {outputFile} with:
169
193
  - Per-unit export summary table
170
194
  - Export pattern analysis
171
195
 
172
- Append the complete "## Integration Points" section to {outputFile}:
173
196
  Replace `[Appended by map-and-detect]` under Integration Points with:
174
197
  - Cross-reference matrix
175
198
  - Integration point details
199
+ - Composite merge proposals and decisions: name, constituents with their paths, heuristic, evidence
176
200
  - Stack skill candidate flags
177
201
 
202
+ In the Identified Units classification table, replace the constituent rows of each approved composite with the composite's one row (its Path the constituents' paths), so recommend builds one card for it.
203
+
178
204
  Update {outputFile} frontmatter:
179
205
  ```yaml
180
206
  stepsCompleted: [append 'map-and-detect' to existing array]
181
207
  lastStep: 'map-and-detect'
208
+ confirmed_composites: [{list of approved composites: {name, constituents: [{name, path}], heuristic}}]
182
209
  stack_skill_candidates: [{list flagged candidate groupings}]
183
210
  ```
184
211
 
185
- ### 8. Present MENU OPTIONS
186
-
187
- Display: "**Select:** [C] Continue to Recommendations | [D] Discover Additional Source"
188
-
189
- #### Menu Handling Logic:
190
-
191
- - IF C: Save findings to {outputFile}, update frontmatter, then load, read entire file, then execute {nextStepFile}
192
- - IF D: Accept a new repo path/URL from the user. Run a lightweight scan (directory structure + manifest detection from step 02) and classify (unit identification from step 03) for the new source only. Merge results into the existing report — append new units to the unit list, update `project_paths[]` in frontmatter. Then redisplay this step's export mapping for the new units before returning to the menu.
193
- - IF Any other: help user, then [Redisplay Menu Options](#8-present-menu-options)
194
-
195
- **GATE [default: C]** — present the menu and wait for the user's choice. If `{headless_mode}`: auto-proceed with [C] Continue past export/integration findings, log: "headless: auto-continue past integration analysis".
212
+ (`confirmed_composites` is an empty array when no composite was proposed or all were rejected. generate-briefs puts every constituent's path in the composite brief's `scope.include`.)
196
213
 
214
+ Then load, read the entire file, then execute {nextStepFile}.
@@ -0,0 +1,68 @@
1
+ <!-- Config: communicate in {communication_language}. -->
2
+
3
+ # Map Each Unit's Exports
4
+
5
+ The per-unit export analysis, stated once for the two files that run it: map-and-detect section 2, for every qualifying unit, and discover-additional-source section 4, for the units it adds. The file that loads this one has resolved `{extractPublicApiHelper}` and `{checkUnitRecordsHelper}` and gives each unit its name, its scope type (`{unit_scope_type}`), its language, its folder (`{unit_root}`: its path under the scan root of its project path) and its file count (the `files_count` of its disqualification record, which the Files column of Identified Units shows); `{forge_tier}` is the report's. This file returns to it with the checked records.
6
+
7
+ ## 1. Delegate Each Unit to a Subagent
8
+
9
+ For each unit, launch a subagent task with these explicit constraints:
10
+
11
+ - The subagent reads only that unit's directory tree
12
+ - The subagent analyzes exports / usage / CCC signals for that one unit
13
+ - **The parent does not read the unit's source files before delegating** (avoid the implicit-read trap: the whole point of fan-out is to keep large source bodies out of the parent's context)
14
+ - The subagent writes its record (§3) to a file of the run folder and returns only that file's path, so the parent never copies a record: pass it `{run_dir}` and the resolved `{extractPublicApiHelper}`
15
+
16
+ **Graceful degradation.** If subagents are unavailable in the current runtime, the parent performs the per-unit analysis sequentially in the main thread with the same export-surface call and tier-aware extras. Each main-thread analysis still writes the same JSON record, so the later steps do not depend on the execution mode.
17
+
18
+ ## 2. Analyze One Unit
19
+
20
+ **Export surface (every tier):** run the recipe runner on the unit's own folder. For the languages it has ast-grep recipes for (Python, JavaScript and TypeScript, Rust, Go, Vue) it lists the files, runs the recipes, follows the entry points and counts the public API, so the subagent neither greps nor counts those exports by hand:
21
+
22
+ ```bash
23
+ uv run {extractPublicApiHelper} --mode full --source-root "{unit_root}" --scope-type {unit_scope_type} --tier {forge_tier}
24
+ ```
25
+
26
+ **No recipe for the unit's language:** when `files_in_scope` is 0, or `files_without_recipes` lists the extension of the unit's language (Java, Kotlin, Swift, C#, PHP, Ruby and C or C++ have no recipe), the run counted none of its exports, whatever its exit code. Read the public declarations of the unit's source files by eye, as on exit 3: `exports_count`, `api_surface` and `export_pattern` from what you read (for example "public classes: 14, interfaces: 3"), `strategy_used: "source-read"`, `confidence: "T1-low"`.
27
+
28
+ Otherwise read the JSON by the exit code:
29
+
30
+ - **0 or 1:** `exports_count` ← `counts.exports_public_api`, `api_surface` ← the names in `entry_point_diff.public[]`, `export_pattern` ← `entry_points.status` with `aggregates.by_type` (for example "barrel: 12 functions, 5 classes", marked "capped" when `truncated` is true), `strategy_used: "ast-grep"`, `confidence: "T1"`. Then read by eye what the recipes could not, and name each one in `warnings`: every `entry_point_diff.extraction_gaps[]` name (public, but no recipe found its definition: read it at its `file` and `line`) and every `file_issues[]` file (one the parser could not fully read: add the exports it shows to `api_surface`). Exit 1 (`status: "incomplete"`) means an ast-grep run failed on some files: keep what it returned and put its `errors[]` in `warnings`.
31
+ - **3** (no ast-grep the runner can run): the JSON still lists `entry_points.files`. Read the exports from those entry-point files by eye (from the unit's source files when it lists none), with `strategy_used: "source-read"` and `confidence: "T1-low"`.
32
+ - **2:** an input error, named on stderr (a wrong path or flag): fix the call and run it again.
33
+
34
+ **Tier-aware extras:** when `tools.ccc` is true (Forge+, or Deep with ccc installed), search `"{unit_name} exports public API"` (top 15) with the ccc tool the runtime offers (the `/ccc` skill, a ccc MCP server or the `ccc search` CLI) and record the top 3 files in `ccc_signals.top_files`, with `available: true`; with no ccc tool, record `available: false`.
35
+
36
+ The subagent also records the export-surface call's `strategy_used`, `confidence` and `warnings`.
37
+
38
+ ## 3. Record Contract
39
+
40
+ Each subagent writes only this JSON object, with no prose, no commentary and no markdown fence, to `{run_dir}/unit-records/{unit_name}.json` (creating the folder), and returns that path:
41
+
42
+ ```json
43
+ {
44
+ "unit_name": "...",
45
+ "files_count": N,
46
+ "exports_count": N,
47
+ "export_pattern": "...",
48
+ "api_surface": ["..."],
49
+ "ccc_signals": {"top_files": [], "available": <bool>},
50
+ "strategy_used": "ast-grep|source-read",
51
+ "confidence": "T1|T1-low",
52
+ "warnings": []
53
+ }
54
+ ```
55
+
56
+ `files_count` is the unit's file count the loading file gave (the `files_count` of its disqualification record), not the runner's `files_in_scope`, which leaves out every file no recipe reads.
57
+
58
+ ## 4. Check the Records
59
+
60
+ Once every subagent has returned its path (a main-thread analysis writes its record the same way), check all the records in one call:
61
+
62
+ ```bash
63
+ uv run {checkUnitRecordsHelper} --dir "{run_dir}/unit-records"
64
+ ```
65
+
66
+ The script drops a wrapping markdown fence (a subagent sometimes writes one despite the contract), checks each record against the contract above and fills a missing or wrong-typed key with its empty value, so a degraded record still goes on. Its `records` are the per-unit payloads. Record each `problems` entry as the warning `{unit_name}: {problem}` and each `warnings` entry as it is, so they reach the envelope's `warnings`: one `uv run {emitEnvelopeHelper} record --run-dir "{run_dir}" --warning '<the warning>'` per entry, a single quote in it written as a backtick. A unit with no file in the folder, or a file the script lists in `unreadable` (it held no JSON object), is analyzed again in the main thread (graceful degradation, §1), and the check runs once more. Record only the entries of the units this pass analyzed: a record an earlier pass checked was recorded then.
67
+
68
+ Return to the file that loaded this one with the checked `records` of these units.
@@ -1,7 +1,8 @@
1
1
  ---
2
2
  nextStepFile: 'generate-briefs.md'
3
3
  outputFile: '{forge_data_folder}/analyze-source-report-{project_name}.md'
4
- schemaFile: '{briefSchemaPath}'
4
+ schemaFile: 'assets/skill-brief-schema.md'
5
+ discoverFile: 'references/discover-additional-source.md'
5
6
  advancedElicitationSkill: '/bmad-advanced-elicitation'
6
7
  partyModeSkill: '/bmad-party-mode'
7
8
  ---
@@ -16,21 +17,29 @@ To present each qualifying unit as a recommendation with evidence-based rational
16
17
 
17
18
  ## Rules
18
19
 
19
- - This is the primary user decision point — do not rush through it
20
- - Do not proceed without explicit confirmation for each unit
20
+ - This is the primary user decision point: every unit gets a decision before the run moves on, which a headless run takes by the §7 GATE default
21
21
  - Present evidence for each recommendation, invite questions and pushback
22
22
 
23
23
  ## MANDATORY SEQUENCE
24
24
 
25
+ Every HARD HALT in this step names its exit code, `halt_reason` and phase. When `{headless_mode}` is true it first prints its envelope on stderr through the shared emitter (`{emitEnvelopeHelper}` and `{run_dir}` come from SKILL.md On Activation): stage `{run_dir}/halt.json` as `{"phase": "<phase>", "reason": "<the halt message>", "halt_reason": "<halt_reason>", "mode": "interactive", "report_path": "{outputFile as an absolute path}"}`, plus `"path"` when the halt names one, then run
26
+
27
+ ```bash
28
+ uv run {emitEnvelopeHelper} emit-halt --workflow skf-analyze-source --run-dir "{run_dir}" --target stderr < "{run_dir}/halt.json"
29
+ ```
30
+
31
+ and display the line it prints verbatim. Write the payload as valid JSON: in the halt message and `path`, replace each backslash with / and each double quote with a backtick. If the emitter exits non-zero or prints no line, display the halt message alone. An interactive HALT displays its message and emits nothing.
32
+
25
33
  ### 1. Load Context
26
34
 
27
35
  Read {outputFile} completely to obtain:
28
- - Qualifying units from Identified Units
36
+ - Qualifying units from Identified Units, each with its project path (the deferred ones are listed in the summary, not given a card)
29
37
  - Export map data per unit
30
38
  - Integration points and coupling analysis
31
39
  - Stack skill candidates from frontmatter
32
40
  - Existing skills from frontmatter
33
- - `intent_hint` from frontmatter (captured in init.md §3 — user's stated goal for the analysis; empty string if skipped)
41
+ - `intent_hint` from frontmatter (the goal the user stated at init; empty when none)
42
+ - `refs` from frontmatter: a unit's ref is its project path's entry there (none without one)
34
43
 
35
44
  Load {schemaFile} for reference on what skill-brief.yaml requires (so recommendations are actionable).
36
45
 
@@ -42,6 +51,7 @@ For each qualifying unit, prepare a recommendation card:
42
51
 
43
52
  ```
44
53
  **Unit: {name}**
54
+ - Source: {its project path}{, at {its ref} when it has one}
45
55
  - Path: {path}
46
56
  - Language: {language}
47
57
  - Boundary: {type} | Scope: {scope_type}
@@ -51,12 +61,12 @@ For each qualifying unit, prepare a recommendation card:
51
61
  - Coupling: {tight/loose/indirect}
52
62
  - Confidence: {high/medium/low}
53
63
  - Stack Skill: {yes — grouped with {units} / no}
54
- - Status: {new / already-skilled → recommend update-skill}
64
+ - Status: {new / briefed: a brief from an earlier analysis at {its path}, rewritten if you confirm the unit / already-skilled → recommend update-skill}
55
65
 
56
66
  **Rationale:** {2-3 sentences explaining WHY this should be a skill, citing specific detection signals and file paths}
57
67
 
58
68
  **Proposed Brief Fields:**
59
- - name: {suggested kebab-case name}
69
+ - name: {the unit's name, as identify-units or map-and-detect derived it}
60
70
  - scope.type: {full-library / specific-modules / public-api / component-library / reference-app / docs-only}
61
71
  - scope.include: {suggested glob patterns}
62
72
  - description: {suggested 1-3 sentence description, containing a literal `Use when` clause}
@@ -64,6 +74,8 @@ For each qualifying unit, prepare a recommendation card:
64
74
 
65
75
  ### 3. Present Recommendations
66
76
 
77
+ **Headless** (`{headless_mode}` true): no one answers the questions below. Take the §7 GATE default now (confirm every card as proposed and flag every stack skill candidate for create-stack-skill), record it as that GATE says, then continue at §6. No question of §3 to §5 is asked.
78
+
67
79
  "**Recommendations for {project_name}**
68
80
 
69
81
  I've analyzed {count} qualifying units. Here are my recommendations for skill creation:
@@ -78,97 +90,66 @@ Present each recommendation card, then after ALL cards:
78
90
  - **Recommended for new skills:** {count}
79
91
  - **Already-skilled (recommend update-skill):** {count}
80
92
  - **Stack skill candidates:** {count}
93
+ - **Deferred (outside the stated goal, not analyzed):** {count, with their names}
81
94
 
82
95
  **For each unit above, please indicate:**
83
- - **Y** — Confirm: generate skill-brief.yaml
84
- - **N** — Reject: skip this unit
85
- - **M** — Modify: adjust name, scope, or description before confirming
96
+ - **Y**: Confirm: generate skill-brief.yaml
97
+ - **N**: Reject: skip this unit
98
+ - **M**: Modify: adjust name, scope, or description before confirming
86
99
 
87
100
  **Bulk shortcuts:**
88
- - `all-Y` — confirm every recommendation as-is
89
- - `all-N` — skip every recommendation
90
- - Individual response list (e.g., `1:Y, 2:N, 3:M, ...`) — explicit per-unit decisions (use this when you want to mix Y/N/M or modify any unit)
101
+ - `all-Y`: confirm every recommendation as-is
102
+ - `all-N`: skip every recommendation
103
+ - Individual response list (e.g., `1:Y, 2:N, 3:M, ...`): explicit per-unit decisions (use this when you want to mix Y/N/M or modify any unit)
91
104
 
92
105
  **Questions?** Ask 'why?' about any recommendation and I'll explain my reasoning with specific evidence."
93
106
 
94
107
  ### 4. Process User Decisions
95
108
 
96
- For each unit:
97
-
98
- **IF Y (Confirm):**
99
- - Add to confirmed_units list with proposed brief fields
100
-
101
- **IF N (Reject):**
102
- - Document rejection with user's reason (if provided)
103
- - Remove from confirmed list
104
-
105
- **IF M (Modify):**
106
- - Ask what to modify (name, scope, description, scope.include patterns)
107
- - Update the recommendation with user changes
108
- - Confirm the modified version
109
-
110
- **Continue until ALL units have a decision (Y/N/M).**
109
+ Record a decision for every unit before moving on: Y adds it to `confirmed_units` with its proposed brief fields; N records the user's reason; M asks what to change (name, scope type, include patterns, description), applies it and confirms the result.
111
110
 
112
111
  ### 5. Confirm Stack Skill Candidates
113
112
 
114
- If stack skill candidates were flagged:
115
-
116
- "**Stack Skill Candidates:**
117
-
118
- The following unit groupings show strong co-integration patterns and may benefit from a consolidated stack skill via create-stack-skill:
119
-
120
- {For each candidate: list units, detection signal, evidence}
121
-
122
- Would you like to flag these for create-stack-skill? (Y/N per candidate)"
123
-
124
- Document decisions.
113
+ If stack skill candidates were flagged, list them (units, detection signal, evidence): their units show strong co-integration patterns and may benefit from a consolidated stack skill via create-stack-skill. Ask "Flag these for create-stack-skill? (Y/N per candidate)" and record each decision.
125
114
 
126
- ### 6. Present Final Confirmation
115
+ ### 6. Append to Report
127
116
 
128
- "**Confirmed Units for Brief Generation:** {count}
129
-
130
- {List each confirmed unit with final name, scope type, and description}
131
-
132
- **Rejected Units:** {count}
133
- {List with reasons}
134
-
135
- **Stack Skill Flags:** {count}
136
- {List groupings flagged for create-stack-skill}
137
-
138
- **This is your final confirmation before I generate skill-brief.yaml files.** All confirmed?"
139
-
140
- Wait for explicit final confirmation.
141
-
142
- ### 7. Append to Report
143
-
144
- Append the complete "## Recommendations" section to {outputFile}:
145
-
146
- Replace `[Appended by recommend]` with:
117
+ Replace `[Appended by recommend]` in {outputFile} with:
147
118
  - All recommendation cards (including rationale)
148
119
  - User decisions per unit (confirmed/rejected/modified)
149
120
  - Stack skill candidate decisions
150
- - Final confirmation status
151
121
 
152
122
  Update {outputFile} frontmatter:
153
123
  ```yaml
154
- stepsCompleted: [append 'recommend' to existing array]
155
- lastStep: 'recommend'
156
124
  confirmed_units: [{list of confirmed unit names}]
157
125
  stack_skill_candidates: [{updated list with user decisions}]
158
126
  ```
159
127
 
160
- ### 8. Present MENU OPTIONS
128
+ A later pass through this section (after [A], [P] or [D], or in a session that resumed this step) replaces what the earlier one wrote. The step is marked complete only when [C] leaves it, so a run cancelled at the §7 menu resumes at these recommendations.
129
+
130
+ ### 7. Present MENU OPTIONS
131
+
132
+ Lead with the decisions, so the menu is chosen against the final list:
133
+
134
+ "**Confirmed for brief generation:** {count}: {each confirmed unit with its final name, scope type and description}
135
+ **Rejected:** {count}: {each with its reason}
136
+ **Flagged for create-stack-skill:** {count}: {each grouping}"
161
137
 
162
138
  Display: "**Select an Option:** [A] Advanced Elicitation [P] Party Mode [D] Discover Additional Source [C] Continue to Brief Generation [X] Cancel and exit"
163
139
 
164
140
  #### Menu Handling Logic:
165
141
 
166
- - IF A: Invoke {advancedElicitationSkill}, and when finished redisplay the menu
167
- - IF P: Invoke {partyModeSkill}, and when finished redisplay the menu
168
- - IF D: Accept a new repo path/URL from the user. Run a lightweight scan + classify (subset of steps 02-03) for the new source only. Merge new units into the existing report and update `project_paths[]` in frontmatter. Run export mapping for the new units (same logic as step 04 section 2). Generate recommendation cards for the new units and present them for confirmation. Then redisplay this menu.
169
- - IF C: Save recommendations to {outputFile}, update frontmatter, then load, read entire file, then execute {nextStepFile}
170
- - IF X: HARD HALT with exit code 6 (`user-cancelled`). Emit the error envelope on stderr with `halt_reason: "user-cancelled"` and counts/paths reflecting state at cancellation (shape in `references/headless-contract.md`)
171
- - IF Any other comments or queries: help user respond then [Redisplay Menu Options](#8-present-menu-options)
142
+ - IF A: Invoke {advancedElicitationSkill}. For each unit what it surfaced changes, take the decision again as §4 says, redo §6, then redisplay this menu
143
+ - IF P: Invoke {partyModeSkill}, then handle what it surfaced as [A] does
144
+ - IF D: load, read the entire file, then execute {discoverFile} with the project path the user gives. It returns the new path's units with their export records and composite proposals. Present each proposal (accepted unless the user rejects it; an accepted one replaces its constituents as one unit and joins `confirmed_composites` in the frontmatter), build the cards of the new units (§2), take their decisions (§3 to §5), redo §6, then redisplay this menu
145
+ - IF C: update {outputFile} frontmatter (`stepsCompleted`: append `recommend`; `lastStep: 'recommend'`), then load, read the entire file, then execute {nextStepFile}
146
+ - IF X: HARD HALT (exit code 6, `halt_reason: "user-cancelled"`, phase `recommend:7`, with `unit_counts` reflecting the decisions made so far in its payload): "Cancelled at the recommendations."
147
+ - IF Any other comments or queries: help user respond then [Redisplay Menu Options](#7-present-menu-options)
148
+
149
+ **GATE [default: C]**: present the menu and wait for the user's choice. The default also answers every question of §3 to §5: confirm every card as proposed and flag every stack skill candidate. If `{headless_mode}`, §3 takes that default before any question and records it the moment it does: stage `{run_dir}/decision.json` as `{"gate": "recommend.recommendations", "default_action": "C", "taken_action": "C", "reason": "headless: auto-accept all recommendations and flag every stack skill candidate", "evidence": {"confirmed": [<each confirmed unit name>], "stack_skill_candidates": <the flagged candidate count>}}`, then run
172
150
 
173
- **GATE [default: C]** — present the menu and wait for the user's choice. If `{headless_mode}`: accept all recommendations and auto-proceed, log: "headless: auto-accept all recommendations".
151
+ ```bash
152
+ uv run {emitEnvelopeHelper} record --workflow skf-analyze-source --run-dir "{run_dir}" --decision < "{run_dir}/decision.json"
153
+ ```
174
154
 
155
+ If the command fails, go on: only that entry is lost. At this menu a headless run continues with [C].