bmad-module-skill-forge 2.2.0 → 4.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 (437) 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 +143 -18
  18. package/docs/verifying-a-skill.md +87 -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 +3 -3
  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 +31 -59
  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 +233 -64
  64. package/src/shared/scripts/skf-build-change-manifest.py +2753 -28
  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 +772 -0
  69. package/src/shared/scripts/skf-comention-pairs.py +1333 -123
  70. package/src/shared/scripts/skf-compare-file-hashes.py +267 -105
  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 +21 -3
  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 +197 -55
  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 +5247 -96
  86. package/src/shared/scripts/skf-extraction-inventory.py +1280 -0
  87. package/src/shared/scripts/skf-extraction-snapshot.py +664 -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 +469 -205
  92. package/src/shared/scripts/skf-github-fetch.py +365 -0
  93. package/src/shared/scripts/skf-github-probe.py +700 -0
  94. package/src/shared/scripts/skf-hash-content.py +180 -20
  95. package/src/shared/scripts/skf-language-corpora.py +1 -1
  96. package/src/shared/scripts/skf-load-provenance.py +161 -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 +143 -20
  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 +176 -28
  105. package/src/shared/scripts/skf-promote-staged.py +430 -0
  106. package/src/shared/scripts/skf-provenance-gap-dispatch.py +64 -8
  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 +155 -14
  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 +787 -121
  127. package/src/shared/scripts/skf-tessl-review.py +706 -0
  128. package/src/shared/scripts/skf-update-active-symlink.py +120 -67
  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 +23 -2
  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 +3945 -152
  138. package/src/shared/scripts/skf-write-skill-brief.py +406 -25
  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 +28 -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/health-check.md +2 -0
  168. package/src/skf-audit-skill/references/init.md +149 -210
  169. package/src/skf-audit-skill/references/re-index.md +103 -110
  170. package/src/skf-audit-skill/references/report.md +96 -33
  171. package/src/skf-audit-skill/references/semantic-diff.md +34 -25
  172. package/src/skf-audit-skill/references/severity-classify.md +79 -65
  173. package/src/skf-audit-skill/references/severity-rules.md +15 -6
  174. package/src/skf-audit-skill/references/structural-diff.md +80 -90
  175. package/src/skf-audit-skill/references/upstream-checkout.md +77 -0
  176. package/src/skf-audit-skill/scripts/render-drift-tables.py +712 -0
  177. package/src/skf-brief-skill/SKILL.md +37 -26
  178. package/src/skf-brief-skill/assets/description-voice-examples.md +1 -1
  179. package/src/skf-brief-skill/assets/scope-templates.md +18 -25
  180. package/src/skf-brief-skill/assets/skill-brief-schema.md +30 -23
  181. package/src/skf-brief-skill/customize.toml +48 -20
  182. package/src/skf-brief-skill/references/analyze-target.md +144 -127
  183. package/src/skf-brief-skill/references/confirm-brief.md +11 -9
  184. package/src/skf-brief-skill/references/draft-checkpoint.md +36 -17
  185. package/src/skf-brief-skill/references/gather-intent-ratify.md +68 -0
  186. package/src/skf-brief-skill/references/gather-intent.md +87 -182
  187. package/src/skf-brief-skill/references/headless-args.md +84 -16
  188. package/src/skf-brief-skill/references/health-check.md +1 -1
  189. package/src/skf-brief-skill/references/invocation-contract.md +18 -13
  190. package/src/skf-brief-skill/references/portfolio-similarity-check.md +1 -1
  191. package/src/skf-brief-skill/references/qmd-collection-registration.md +7 -10
  192. package/src/skf-brief-skill/references/scope-definition.md +123 -47
  193. package/src/skf-brief-skill/references/step-auto-brief.md +26 -100
  194. package/src/skf-brief-skill/references/step-auto-validate.md +20 -121
  195. package/src/skf-brief-skill/references/version-resolution.md +7 -10
  196. package/src/skf-brief-skill/references/write-brief.md +66 -57
  197. package/src/skf-campaign/SKILL.md +31 -34
  198. package/src/skf-campaign/assets/campaign-state-schema.json +25 -4
  199. package/src/skf-campaign/customize.toml +47 -16
  200. package/src/skf-campaign/references/campaign-contracts.md +39 -29
  201. package/src/skf-campaign/references/campaign-directive-spec.md +4 -2
  202. package/src/skf-campaign/references/health-check.md +7 -16
  203. package/src/skf-campaign/references/step-01-setup.md +46 -84
  204. package/src/skf-campaign/references/step-02-strategy.md +31 -30
  205. package/src/skf-campaign/references/step-03-pins.md +26 -18
  206. package/src/skf-campaign/references/step-04-provenance.md +24 -23
  207. package/src/skf-campaign/references/step-05-skill-loop.md +67 -48
  208. package/src/skf-campaign/references/step-06-batch.md +41 -34
  209. package/src/skf-campaign/references/step-07-capstone.md +40 -25
  210. package/src/skf-campaign/references/step-08-verify.md +28 -29
  211. package/src/skf-campaign/references/step-09-refine.md +29 -30
  212. package/src/skf-campaign/references/step-10-export.md +48 -36
  213. package/src/skf-campaign/references/step-11-maintenance.md +31 -34
  214. package/src/skf-campaign/references/step-resume.md +37 -68
  215. package/src/skf-campaign/scripts/campaign-deps.py +57 -18
  216. package/src/skf-campaign/scripts/campaign-parse-manifest.py +361 -54
  217. package/src/skf-campaign/scripts/campaign-provenance.py +96 -53
  218. package/src/skf-campaign/scripts/campaign-quality-gate.py +592 -0
  219. package/src/skf-campaign/scripts/campaign-render-batch.py +257 -49
  220. package/src/skf-campaign/scripts/campaign-render-kickoff.py +343 -50
  221. package/src/skf-campaign/scripts/campaign-report.py +204 -37
  222. package/src/skf-campaign/scripts/campaign-state.py +1128 -0
  223. package/src/skf-campaign/scripts/campaign-status.py +10 -74
  224. package/src/skf-campaign/scripts/campaign-validate-pins.py +30 -3
  225. package/src/skf-campaign/scripts/campaign-validate-state.py +34 -4
  226. package/src/skf-campaign/templates/campaign-brief-template.yaml +4 -5
  227. package/src/skf-campaign/templates/campaign-report-template.md +5 -1
  228. package/src/skf-campaign/templates/kickoff-template.md +0 -14
  229. package/src/skf-create-skill/SKILL.md +27 -20
  230. package/src/skf-create-skill/assets/compile-assembly-rules.md +11 -8
  231. package/src/skf-create-skill/assets/skill-sections.md +21 -11
  232. package/src/skf-create-skill/customize.toml +20 -8
  233. package/src/skf-create-skill/references/authoritative-files-protocol.md +36 -58
  234. package/src/skf-create-skill/references/batch-mode.md +81 -0
  235. package/src/skf-create-skill/references/ccc-index-check.md +27 -0
  236. package/src/skf-create-skill/references/compile.md +119 -70
  237. package/src/skf-create-skill/references/component-extraction.md +113 -91
  238. package/src/skf-create-skill/references/enrich.md +41 -23
  239. package/src/skf-create-skill/references/entry-points-by-hand.md +37 -0
  240. package/src/skf-create-skill/references/extract.md +204 -162
  241. package/src/skf-create-skill/references/extraction-patterns-by-hand.md +141 -0
  242. package/src/skf-create-skill/references/extraction-patterns-tracing.md +11 -11
  243. package/src/skf-create-skill/references/extraction-patterns.md +588 -201
  244. package/src/skf-create-skill/references/generate-artifacts.md +145 -93
  245. package/src/skf-create-skill/references/health-check.md +1 -1
  246. package/src/skf-create-skill/references/load-brief.md +53 -36
  247. package/src/skf-create-skill/references/relabel-rule.md +12 -0
  248. package/src/skf-create-skill/references/report.md +37 -57
  249. package/src/skf-create-skill/references/source-resolution-protocols.md +58 -169
  250. package/src/skf-create-skill/references/step-auto-shard.md +20 -93
  251. package/src/skf-create-skill/references/step-doc-rot.md +44 -60
  252. package/src/skf-create-skill/references/step-doc-sources.md +28 -19
  253. package/src/skf-create-skill/references/sub/ccc-discover.md +18 -7
  254. package/src/skf-create-skill/references/sub/fetch-docs.md +106 -59
  255. package/src/skf-create-skill/references/sub/fetch-temporal.md +53 -166
  256. package/src/skf-create-skill/references/tier-degradation-rules.md +18 -9
  257. package/src/skf-create-skill/references/validate.md +173 -99
  258. package/src/skf-create-skill/scripts/scan-doc-rot.py +232 -99
  259. package/src/skf-create-stack-skill/SKILL.md +29 -56
  260. package/src/skf-create-stack-skill/assets/metadata-contract.md +51 -0
  261. package/src/skf-create-stack-skill/assets/provenance-map-schema.md +15 -15
  262. package/src/skf-create-stack-skill/assets/stack-skill-template.md +23 -57
  263. package/src/skf-create-stack-skill/customize.toml +23 -12
  264. package/src/skf-create-stack-skill/references/compile-stack.md +57 -66
  265. package/src/skf-create-stack-skill/references/compose-mode-rules.md +24 -44
  266. package/src/skf-create-stack-skill/references/detect-integrations.md +92 -95
  267. package/src/skf-create-stack-skill/references/detect-manifests.md +46 -71
  268. package/src/skf-create-stack-skill/references/generate-output.md +138 -128
  269. package/src/skf-create-stack-skill/references/init.md +90 -32
  270. package/src/skf-create-stack-skill/references/integration-patterns.md +1 -17
  271. package/src/skf-create-stack-skill/references/invocation-contract.md +34 -0
  272. package/src/skf-create-stack-skill/references/manifest-patterns.md +32 -20
  273. package/src/skf-create-stack-skill/references/parallel-extract.md +112 -38
  274. package/src/skf-create-stack-skill/references/rank-and-confirm.md +57 -75
  275. package/src/skf-create-stack-skill/references/report.md +39 -33
  276. package/src/skf-create-stack-skill/references/validate.md +20 -39
  277. package/src/skf-drop-skill/SKILL.md +28 -51
  278. package/src/skf-drop-skill/customize.toml +44 -30
  279. package/src/skf-drop-skill/references/execute.md +83 -146
  280. package/src/skf-drop-skill/references/health-check.md +2 -0
  281. package/src/skf-drop-skill/references/invocation-contract.md +64 -0
  282. package/src/skf-drop-skill/references/report.md +46 -30
  283. package/src/skf-drop-skill/references/select.md +122 -124
  284. package/src/skf-drop-skill/scripts/dir-sizes.py +54 -26
  285. package/src/skf-drop-skill/scripts/drop-roster.py +322 -0
  286. package/src/skf-export-skill/SKILL.md +40 -62
  287. package/src/skf-export-skill/assets/managed-section-format.md +14 -50
  288. package/src/skf-export-skill/assets/snippet-format.md +3 -1
  289. package/src/skf-export-skill/customize.toml +42 -13
  290. package/src/skf-export-skill/references/generate-snippet.md +54 -46
  291. package/src/skf-export-skill/references/health-check.md +2 -0
  292. package/src/skf-export-skill/references/invocation-contract.md +15 -0
  293. package/src/skf-export-skill/references/load-skill.md +88 -62
  294. package/src/skf-export-skill/references/manifest-rebuild.md +9 -10
  295. package/src/skf-export-skill/references/multi-skill-mode.md +4 -4
  296. package/src/skf-export-skill/references/orphan-context-detection.md +13 -5
  297. package/src/skf-export-skill/references/orphan-row-detection.md +31 -22
  298. package/src/skf-export-skill/references/package.md +15 -73
  299. package/src/skf-export-skill/references/preflight-snippet-root-probe.md +51 -70
  300. package/src/skf-export-skill/references/result-envelope.md +31 -16
  301. package/src/skf-export-skill/references/summary.md +41 -17
  302. package/src/skf-export-skill/references/token-report.md +4 -12
  303. package/src/skf-export-skill/references/update-context.md +118 -237
  304. package/src/skf-forger/SKILL.md +61 -37
  305. package/src/skf-forger/bmad-skill-manifest.yaml +4 -1
  306. package/src/skf-forger/customize.toml +43 -0
  307. package/src/skf-forger/references/pipeline-mode.md +73 -18
  308. package/src/skf-forger/scripts/forge-status.py +299 -0
  309. package/src/skf-forger/scripts/parse-pipeline.py +322 -54
  310. package/src/skf-forger/scripts/pipeline-gate.py +428 -0
  311. package/src/skf-forger/scripts/pipeline-journal.py +1052 -0
  312. package/src/skf-quick-skill/SKILL.md +54 -53
  313. package/src/skf-quick-skill/assets/skill-template.md +4 -2
  314. package/src/skf-quick-skill/customize.toml +51 -20
  315. package/src/skf-quick-skill/references/batch-mode.md +74 -21
  316. package/src/skf-quick-skill/references/compile.md +30 -31
  317. package/src/skf-quick-skill/references/ecosystem-check.md +7 -57
  318. package/src/skf-quick-skill/references/finalize.md +69 -18
  319. package/src/skf-quick-skill/references/halt-contract.md +41 -29
  320. package/src/skf-quick-skill/references/health-check.md +5 -3
  321. package/src/skf-quick-skill/references/quick-extract.md +114 -45
  322. package/src/skf-quick-skill/references/registry-resolution.md +9 -64
  323. package/src/skf-quick-skill/references/resolve-target.md +116 -66
  324. package/src/skf-quick-skill/references/write-and-validate.md +79 -40
  325. package/src/skf-refine-architecture/SKILL.md +43 -53
  326. package/src/skf-refine-architecture/customize.toml +49 -20
  327. package/src/skf-refine-architecture/references/compile.md +97 -54
  328. package/src/skf-refine-architecture/references/exit-codes.md +30 -0
  329. package/src/skf-refine-architecture/references/finding-storage.md +21 -0
  330. package/src/skf-refine-architecture/references/gap-analysis.md +101 -38
  331. package/src/skf-refine-architecture/references/improvements.md +14 -20
  332. package/src/skf-refine-architecture/references/init.md +98 -57
  333. package/src/skf-refine-architecture/references/issue-detection.md +32 -39
  334. package/src/skf-refine-architecture/references/refinement-rules.md +37 -48
  335. package/src/skf-refine-architecture/references/report.md +65 -54
  336. package/src/skf-refine-architecture/scripts/skf-check-preservation.py +1619 -0
  337. package/src/skf-rename-skill/SKILL.md +19 -54
  338. package/src/skf-rename-skill/customize.toml +32 -26
  339. package/src/skf-rename-skill/references/execute.md +230 -184
  340. package/src/skf-rename-skill/references/exit-codes.md +7 -7
  341. package/src/skf-rename-skill/references/health-check.md +1 -7
  342. package/src/skf-rename-skill/references/invocation-contract.md +25 -0
  343. package/src/skf-rename-skill/references/report.md +63 -52
  344. package/src/skf-rename-skill/references/select.md +197 -115
  345. package/src/skf-rename-skill/scripts/skf-validate-rename-name.py +161 -21
  346. package/src/skf-setup/SKILL.md +26 -26
  347. package/src/skf-setup/customize.toml +14 -10
  348. package/src/skf-setup/references/auto-index.md +50 -63
  349. package/src/skf-setup/references/ccc-index.md +29 -90
  350. package/src/skf-setup/references/detect-and-tier.md +58 -67
  351. package/src/skf-setup/references/health-check.md +2 -0
  352. package/src/skf-setup/references/invocation-contract.md +14 -0
  353. package/src/skf-setup/references/report.md +43 -166
  354. package/src/skf-setup/references/tier-rules.md +5 -5
  355. package/src/skf-setup/references/write-config.md +34 -57
  356. package/src/skf-test-skill/SKILL.md +17 -57
  357. package/src/skf-test-skill/assets/output-section-formats.md +33 -34
  358. package/src/skf-test-skill/customize.toml +27 -13
  359. package/src/skf-test-skill/references/coherence-check.md +134 -62
  360. package/src/skf-test-skill/references/coverage-check-tiers.md +35 -0
  361. package/src/skf-test-skill/references/coverage-check.md +209 -264
  362. package/src/skf-test-skill/references/detect-mode.md +5 -5
  363. package/src/skf-test-skill/references/external-validators.md +94 -82
  364. package/src/skf-test-skill/references/health-check.md +6 -7
  365. package/src/skf-test-skill/references/init.md +164 -91
  366. package/src/skf-test-skill/references/invocation-contract.md +66 -0
  367. package/src/skf-test-skill/references/migration-section-rules.md +5 -2
  368. package/src/skf-test-skill/references/report.md +164 -142
  369. package/src/skf-test-skill/references/score.md +80 -107
  370. package/src/skf-test-skill/references/scoring-rules.md +42 -155
  371. package/src/skf-test-skill/references/source-access-protocol.md +18 -94
  372. package/src/skf-test-skill/references/step-hard-gate.md +51 -33
  373. package/src/skf-test-skill/scripts/aggregate-coherence.py +218 -30
  374. package/src/skf-test-skill/scripts/build-result-context.py +380 -0
  375. package/src/skf-test-skill/scripts/check-metadata-coherence.py +37 -4
  376. package/src/skf-test-skill/scripts/combine-external-scores.py +23 -6
  377. package/src/skf-test-skill/scripts/compute-score.py +223 -45
  378. package/src/skf-test-skill/scripts/gap-ledger.py +1666 -0
  379. package/src/skf-test-skill/scripts/hard-gate.py +203 -0
  380. package/src/skf-test-skill/scripts/load-coverage-inputs.py +1198 -0
  381. package/src/skf-test-skill/scripts/locate-export-segments.py +835 -0
  382. package/src/skf-test-skill/scripts/reconcile-coverage.py +547 -79
  383. package/src/skf-test-skill/scripts/score-signatures.py +479 -0
  384. package/src/skf-test-skill/scripts/stage-helper-payload.py +148 -0
  385. package/src/skf-test-skill/scripts/validate-inventory.py +311 -16
  386. package/src/skf-test-skill/scripts/verify-declared-numerator.py +133 -56
  387. package/src/skf-test-skill/templates/test-report-template.md +21 -15
  388. package/src/skf-update-skill/SKILL.md +38 -25
  389. package/src/skf-update-skill/customize.toml +27 -12
  390. package/src/skf-update-skill/references/detect-changes.md +253 -223
  391. package/src/skf-update-skill/references/gap-driven.md +336 -0
  392. package/src/skf-update-skill/references/health-check.md +31 -5
  393. package/src/skf-update-skill/references/init.md +254 -84
  394. package/src/skf-update-skill/references/invocation-contract.md +12 -0
  395. package/src/skf-update-skill/references/manual-section-rules.md +6 -23
  396. package/src/skf-update-skill/references/merge.md +182 -49
  397. package/src/skf-update-skill/references/re-extract.md +53 -262
  398. package/src/skf-update-skill/references/report.md +102 -35
  399. package/src/skf-update-skill/references/write.md +357 -155
  400. package/src/skf-update-skill/scripts/skf-new-file-diff.py +183 -46
  401. package/src/skf-verify-stack/SKILL.md +23 -42
  402. package/src/skf-verify-stack/assets/feasibility-report-template.md +11 -5
  403. package/src/skf-verify-stack/customize.toml +55 -22
  404. package/src/skf-verify-stack/references/coverage-patterns.md +17 -8
  405. package/src/skf-verify-stack/references/coverage.md +67 -64
  406. package/src/skf-verify-stack/references/exit-codes.md +21 -8
  407. package/src/skf-verify-stack/references/init.md +107 -62
  408. package/src/skf-verify-stack/references/integration-verification-rules.md +12 -13
  409. package/src/skf-verify-stack/references/integrations.md +106 -65
  410. package/src/skf-verify-stack/references/report.md +59 -42
  411. package/src/skf-verify-stack/references/requirements.md +32 -9
  412. package/src/skf-verify-stack/references/synthesize.md +53 -39
  413. package/src/skf-verify-stack/scripts/skf-coverage-tally.py +398 -52
  414. package/src/skf-verify-stack/scripts/skf-previous-report.py +330 -0
  415. package/src/skf-verify-stack/scripts/skf-report-delta.py +453 -49
  416. package/src/skf-verify-stack/scripts/skf-verdict-rollup.py +240 -27
  417. package/tools/cli/commands/install.js +11 -4
  418. package/tools/cli/commands/status.js +15 -3
  419. package/tools/cli/commands/update.js +11 -4
  420. package/tools/cli/lib/tool-check.js +320 -0
  421. package/tools/cli/lib/version-check.js +22 -9
  422. package/tools/cli/skf-cli.js +4 -1
  423. package/.gitattributes +0 -16
  424. package/.nvmrc +0 -1
  425. package/docs/_internal/RELEASING.md +0 -679
  426. package/release-audits/v1.0.0-launch-audit.md +0 -728
  427. package/src/skf-audit-skill/references/step-doc-drift.md +0 -177
  428. package/src/skf-brief-skill/references/headless-source-authority-detection.md +0 -26
  429. package/src/skf-campaign/manifest.yaml +0 -15
  430. package/src/skf-create-skill/assets/tessl-dismissal-rules.md +0 -106
  431. package/src/skf-create-skill/references/ecosystem-check.md +0 -74
  432. package/src/skf-drop-skill/references/headless-contract.md +0 -18
  433. package/src/skf-update-skill/references/merge-conflict-rules.md +0 -15
  434. package/src/skf-update-skill/references/remote-source-resolution.md +0 -98
  435. package/src/skf-update-skill/references/validate.md +0 -124
  436. package/tools/validate-docs-drift.js +0 -233
  437. package/tools/validate-docs-links.js +0 -665
@@ -10,9 +10,15 @@ detectWorkspacesProbeOrder:
10
10
  detectLanguageProbeOrder:
11
11
  - '{project-root}/_bmad/skf/shared/scripts/skf-detect-language.py'
12
12
  - '{project-root}/src/shared/scripts/skf-detect-language.py'
13
- emitBriefEnvelopeProbeOrder:
14
- - '{project-root}/_bmad/skf/shared/scripts/skf-emit-brief-result-envelope.py'
15
- - '{project-root}/src/shared/scripts/skf-emit-brief-result-envelope.py'
13
+ githubProbeProbeOrder:
14
+ - '{project-root}/_bmad/skf/shared/scripts/skf-github-probe.py'
15
+ - '{project-root}/src/shared/scripts/skf-github-probe.py'
16
+ githubFetchProbeOrder:
17
+ - '{project-root}/_bmad/skf/shared/scripts/skf-github-fetch.py'
18
+ - '{project-root}/src/shared/scripts/skf-github-fetch.py'
19
+ validatePinsProbeOrder:
20
+ - '{project-root}/_bmad/skf/shared/scripts/skf-validate-pins.py'
21
+ - '{project-root}/src/shared/scripts/skf-validate-pins.py'
16
22
  ---
17
23
 
18
24
  <!-- Config: communicate in {communication_language}. -->
@@ -23,61 +29,100 @@ emitBriefEnvelopeProbeOrder:
23
29
 
24
30
  - Do not make scoping decisions or recommendations
25
31
  - Do not hallucinate or guess about repository contents
32
+ - **One display.** The §5 summary is this step's one display of the analysis. Before it, §2 to §4.3 show one progress line each, besides any warning, the truncation choice (§1), the monorepo pick (§1b) and §4.4's semantic signals; the values they compute stay in context for §5.
33
+ - **Staged inputs.** The helpers of this step read the repository from files in the run folder `{run_dir}` that step 1 §1 created, never from a list or a file's text typed into a command: `{run_dir}/tree.json` (the file list, §1), `{run_dir}/files/` (manifests and entry points fetched at `{analysis_ref}`, laid out like the repository), `{run_dir}/snapshot.json` (the tree's counts and module candidates, §2) and `{run_dir}/extract.json` (the exports, §4). Step 3 reads the same files.
34
+ - **Ratify run (`ratify_mode: true`):** this step runs only from step 4 `[R] Revise Scope`, to give step 3 an analysis of the brief's repository, and never replaces the hydrated `name`, `version` or `language`. §1 treats the hydrated `target_ref` and `target_version` as set in step 01, and a hydrated `version` without either as an implicit `target_version`: §1 resolves it to a tag the same way, and with no match analyzes `HEAD` without the zero-match warning. §1b selects, without asking, the workspace whose path begins the hydrated `scope.include` globs (the repo root when none does). §3 runs only to choose §4's path: the brief keeps the hydrated `language`, which the §5 summary shows with the hydrated `version`. Skip §4b. At §5, set `ratify_analyzed: true` in workflow context, so a later `[R]` goes straight to step 3.
26
35
 
27
36
  ## Sequence
28
37
 
38
+ ### 0. Docs-Only Target
39
+
40
+ **If `source_type` is `docs-only`:** there is no repository to read, so skip §1 to §5 (no tree, manifests, extraction or version detection). Set `{language}` to the `language_hint` argument when one was supplied, else `documentation` (the language skf-analyze-source writes for a docs-only brief). Leave `detected_version` unset: the brief's version is `target_version` when step 1 collected one, else the `1.0.0` default (step 5's writer applies that precedence). Display:
41
+
42
+ "**Docs-only target: no repository to analyze.**
43
+ **Language:** {language}
44
+ **Version:** {target_version, or 1.0.0 (default)}"
45
+
46
+ Then load, read entire file, then execute {nextStepFile}.
47
+
48
+ **If `source_type` is `source`:** continue to §1.
49
+
29
50
  ### 1. Resolve Target Location
30
51
 
52
+ Display: "**Resolving target...**"
53
+
31
54
  **For GitHub URLs:**
32
55
 
33
- **Resolve the analysis ref first.** `{analysis_ref}` is the git ref every GitHub-API fetch in this step (tree, manifests, contents) reads from — resolve it before fetching anything so the analyzed structure matches the version being skilled:
34
- - If neither `target_ref` nor `target_version` was set in step 01: `{analysis_ref}` = `HEAD` (default branch). This is the common case — skip straight to the probes below with no extra call.
35
- - If `target_ref` is set (an explicit ref the user stated verbatim, highest priority): use it directly as `{analysis_ref}` — no tag lookup.
36
- - If `target_version` is set: resolve it to a tag via `gh api repos/{owner}/{repo}/git/refs/tags` (paginate if the repo has many tags), matching in priority order — exact `{target_version}`, then `v{target_version}`. This mirrors the clone-path tag matching in `skf-create-skill/references/source-resolution-protocols.md` (see that file for the full monorepo-tag priority if the simple forms miss). On a single match, set `{analysis_ref}` to that tag. On **multiple matches**, present them and ask which to use (headless: take the exact match, else the `v`-prefixed one). On **zero matches**, warn `"No git tag matches version {target_version}; analyzing the default branch (HEAD) instead — structure and exports may not match the pinned version."`, set `{analysis_ref}` = `HEAD`, and record the fallback in the §5 analysis summary.
56
+ **Resolve the analysis ref first.** `{analysis_ref}` is the git ref every GitHub-API fetch in this step (tree, manifests, contents) reads from: resolve it before fetching anything so the analyzed structure matches the version being skilled.
57
+ - If neither `target_ref` nor `target_version` was set in step 01: `{analysis_ref}` = `HEAD` (default branch). This is the common case: skip straight to the listing below with no extra call.
58
+ - If `target_ref` is set (an explicit ref the user stated verbatim, highest priority): use it directly as `{analysis_ref}`, with no tag lookup.
59
+ - If `target_version` is set: resolve it to a tag with `{validatePinsHelper}` (resolve it from `{validatePinsProbeOrder}`; first existing path wins), which tries every form a tag writes a version in and prints one JSON line:
60
+
61
+ ```bash
62
+ uv run {validatePinsHelper} --repo-url "https://github.com/{owner}/{repo}" --pin "{target_version}" --format tag
63
+ ```
37
64
 
38
- - Issue both probes in **one message with two parallel Bash calls** — they are independent:
39
- - `gh api repos/{owner}/{repo}` (verify repo exists)
40
- - `gh api repos/{owner}/{repo}/git/trees/{analysis_ref}?recursive=1` (fetch file tree at the resolved ref)
41
- - If the repo-existence probe fails, fall through to the failure-class triage below; the tree response from the parallel call is discarded in that case.
65
+ - Exit 0: set `{analysis_ref}` to its `resolved_ref`.
66
+ - Exit 1 (`status: "invalid"`) with tags in `suggestions`: no tag matches. Warn `"No git tag matches version {target_version}; analyzing the default branch (HEAD) instead: structure and exports may not match the pinned version."`, naming those nearest tags.
67
+ - Exit 1 with an empty `suggestions`: the repository has no tag, or its tags could not be listed. Warn `"Could not find or list the tags of {owner}/{repo}; analyzing the default branch (HEAD) instead: structure and exports may not match the pinned version."`
68
+ - Exit 2 (`gh` missing, or a URL it does not accept), or no candidate path: warn `"Could not check the tags of {owner}/{repo} ({the error it printed}); analyzing the default branch (HEAD) instead: structure and exports may not match the pinned version."`
69
+ - On any of these warnings, add it to `workflow_warnings[]`, set `{analysis_ref}` = `HEAD`, and record the fallback in the §5 analysis summary.
42
70
 
43
- **Truncation detection:** After receiving the tree response, check the `truncated` field in the JSON output. If `truncated: true`:
44
- - Display: "Note: GitHub API returned a truncated tree response ({count} items). Full analysis may require a local clone."
45
- - Record in analysis summary: "Tree listing is partial — some files may not appear in the analysis."
46
- - For very large repos (>1000 files in tree response): offer a recovery path instead of just warning. Interactive — present:
71
+ **List the repository.** Resolve `{githubProbeHelper}` from `{githubProbeProbeOrder}`; first existing path wins. Write its listing to the run folder in one call:
72
+
73
+ ```bash
74
+ uv run {githubProbeHelper} tree --repo "{owner}/{repo}" --ref "{analysis_ref}" --out "{run_dir}/tree.json"
75
+ ```
76
+
77
+ `--out` writes the listing to `{run_dir}/tree.json`, where the helpers read it, and the call prints the rest as one JSON line: `status`, `cause`, `message`, `gh`, `count` and `truncated`. Branch on that line. Every branch below that halts emits its halt envelope first, per the SKILL.md Halt Contract:
78
+
79
+ - **`status: "unavailable"`** (exit 3): the repository or the ref cannot be read, and `message` names the cause and the fix.
80
+ - `cause` `gh-missing` or `gh-unauthenticated`: emit the halt envelope first, `uv run {emitBriefEnvelopeHelper} emit --target stderr` with `halt_reason: "gh-auth-failed"`, then HALT (exit code 3): "**Error:** {message}"
81
+ - `cause` `repo-not-found`, `no-access` or `ref-not-found` (or `unreachable`, `invalid-repo`): emit the halt envelope first, `uv run {emitBriefEnvelopeHelper} emit --target stderr` with `halt_reason: "target-inaccessible"`, then HALT (exit code 3): "**Error:** {message}"
82
+ - **No candidate path, or no JSON** (the helper exits 1 or 2): emit the halt envelope first, `uv run {emitBriefEnvelopeHelper} emit --target stderr` with `halt_reason: "target-inaccessible"`, then HALT (exit code 3): "**Error:** Cannot list `{url}`: {the first line of its stderr, or `skf-github-probe.py not found`}."
83
+
84
+ **Fetching files.** Every file this step and step 3 read from a GitHub source is fetched into `{run_dir}/files` at `{analysis_ref}`, laid out like the repository, by `{githubFetchHelper}` (resolve it from `{githubFetchProbeOrder}`; first existing path wins; HALT if no candidate exists), which §4.1's `--follow` runs too. It reads each file from `raw.githubusercontent.com`, which needs no `gh`, and through `gh` only when that fails (a private repository). A path the listing does not hold costs no request and is reported in `unmatched`, so each call names every candidate. On exit 3, its `failed` names each file it could not read: go on without them, and add `files not fetched: <their paths>` to `workflow_warnings[]`.
85
+
86
+ **Truncation.** When `truncated` is true, GitHub cut the listing short:
87
+ - Display: "Note: GitHub returned a truncated tree ({count} files). Full analysis may require a local clone." and add `tree listing truncated by GitHub ({count} files listed)` to `workflow_warnings[]`.
88
+ - Interactive: present
47
89
  ```
48
90
  Tree is truncated. How would you like to proceed?
49
91
  [L] Clone locally and re-analyze (slower but complete)
50
92
  [P] Proceed with the partial tree (faster, may miss exports under deeper paths)
51
93
  ```
52
- On `[L]`: shallow-clone (`git clone --depth 1 {url} {tmp_dir}`), restart this section against the local path, and remove `{tmp_dir}` after the analysis summary in §5. On `[P]` (or under headless): record `tree_truncated: true` in the analysis summary and continue without HALT.
94
+ On `[L]`: shallow-clone the repository into the run folder at `{analysis_ref}`:
53
95
 
54
- **On API failure (non-200 from `gh api`):**
96
+ ```bash
97
+ git clone --depth 1 --branch "{analysis_ref}" "https://github.com/{owner}/{repo}.git" "{run_dir}/clone"
98
+ ```
55
99
 
56
- Distinguish the failure class before reporting. In headless mode, every branch below emits the error envelope per **step 5 §4b** with its stated `halt_reason` before the HALT (pass the resolved `{skill_name}`, or the `"unknown"` placeholder documented in §4b if it is not yet set):
57
- - Auto-run `gh auth status` and capture its output. If it reports an unauthenticated state or expired token: emit the error envelope per **step 5 §4b** with `halt_reason: "gh-auth-failed"`, then HALT (exit code 3, `halt_reason: "gh-auth-failed"`) — "**Error:** GitHub CLI is not authenticated. `gh auth status` says: `{captured output}`. Run `gh auth login` and retry."
58
- - If `gh auth status` reports authenticated but the call still failed (404/403): emit the error envelope per **step 5 §4b** with `halt_reason: "target-inaccessible"`, then HALT (exit code 3, `halt_reason: "target-inaccessible"`) — "**Error:** Cannot access repository at `{url}`. The CLI is authenticated but the API returned `{status}`. Check the URL and that the account has access to private repositories if applicable."
59
- - If `gh auth status` itself fails to run (binary missing): emit the error envelope per **step 5 §4b** with `halt_reason: "gh-auth-failed"`, then HALT (exit code 3, `halt_reason: "gh-auth-failed"`) — "**Error:** `gh` CLI not found on PATH. Install it from <https://cli.github.com> and re-run."
100
+ Leave `--branch` out when `{analysis_ref}` is `HEAD`. A commit SHA is no `--branch` value: clone it with `git clone --filter=blob:none --no-checkout "https://github.com/{owner}/{repo}.git" "{run_dir}/clone"`, then `git -C "{run_dir}/clone" checkout --quiet "{analysis_ref}"`. Set `{source_path}` ← `{run_dir}/clone` and restart this section for that local path: its listing replaces `{run_dir}/tree.json`, and every later `{source_path}`, in this step and in step 3, is the clone. Before any later HALT, remove the clone (`rm -rf "{run_dir}/clone"`): a halt keeps the files the run staged, never a copy of the repository. If a clone or checkout command fails, remove what it left (`rm -rf "{run_dir}/clone"`), warn `"Could not clone {owner}/{repo} at {analysis_ref} ({the first line of its stderr}); proceeding with the partial tree."`, add the warning to `workflow_warnings[]` and continue as `[P]`.
101
+ **GATE [default: P]**: on `[P]`, and under headless: record `tree_truncated: true` in the analysis summary and continue without HALT.
60
102
 
61
- **For local paths:**
62
- - Verify the directory exists
63
- - List the directory tree
64
- - If the path does not exist: HALT (exit code 3, `halt_reason: "target-inaccessible"`) — "**Error:** Directory not found at {path}. Verify the path is correct." In headless mode, emit the error envelope per **step 5 §4b** with `halt_reason: "target-inaccessible"` before the HALT (pass the resolved `{skill_name}`, or the `"unknown"` placeholder documented in §4b if it is not yet set), matching the GitHub-target failure branches above so a missing local path surfaces the same `SKF_BRIEF_RESULT_JSON` failure class.
103
+ **For local paths:** `{source_path}` is the path.
104
+ - If the directory does not exist (`test -d "{source_path}"` fails): emit the halt envelope first, `uv run {emitBriefEnvelopeHelper} emit --target stderr` with `halt_reason: "target-inaccessible"` (the failure class of a GitHub target the CLI cannot read), then HALT (exit code 3): "**Error:** Directory not found at {path}. Verify the path is correct."
105
+ - List its files into the run folder, the files git tracks and the untracked ones it does not ignore:
65
106
 
66
- Display: "**Resolving target...**"
107
+ ```bash
108
+ git -C "{source_path}" -c core.quotePath=false ls-files --cached --others --exclude-standard -- . ':(exclude,glob)**/.skf-run/**' > "{run_dir}/tree.json"
109
+ ```
110
+
111
+ Outside a git work tree (the command fails): `(cd "{source_path}" && find . -type f -not -path './.git/*' -not -path '*/node_modules/*' -not -path '*/.skf-run/*') > "{run_dir}/tree.json"`. Both leave out SKF's run folders (`.skf-run`), which a listing of the project root would otherwise hold.
67
112
 
68
113
  ### 1b. Detect Monorepo / Workspace Layout
69
114
 
70
115
  **Resolve `{detectWorkspacesHelper}`** from `{detectWorkspacesProbeOrder}`; first existing path wins. HALT if no candidate exists.
71
116
 
72
- Delegate workspace detection to `{detectWorkspacesHelper}` instead of reasoning through manifest rules in prose. Build a payload from the tree fetched in §1 plus the small set of root manifests the detector needs, then invoke the script:
117
+ Delegate workspace detection to `{detectWorkspacesHelper}`: it reads the file list from `{run_dir}/tree.json` and the root manifests from a folder laid out like the repository. For a GitHub source, `--manifest-files` lists the root manifests the detectors read that the listing holds (`rush.json` among them; Nx needs only the tree), the fetch writes them into `{run_dir}/files`, and the last line runs the detection:
73
118
 
74
119
  ```bash
75
- echo '{"tree": [<flat list of repo-relative file paths>], "manifests": {"package.json": "<raw text>", "Cargo.toml": "<raw text>", "pnpm-workspace.yaml": "<raw text>", "lerna.json": "<raw text>"}}' | \
76
- uv run {detectWorkspacesHelper}
120
+ uv run {detectWorkspacesHelper} --tree-file "{run_dir}/tree.json" --manifest-files > "{run_dir}/manifests.txt"
121
+ uv run {githubFetchHelper} --repo "{owner}/{repo}" --ref "{analysis_ref}" --tree-file "{run_dir}/tree.json" --dest "{run_dir}/files" --patterns-file "{run_dir}/manifests.txt"
122
+ uv run {detectWorkspacesHelper} --tree-file "{run_dir}/tree.json" --manifest-dir "{run_dir}/files"
77
123
  ```
78
124
 
79
- - **`tree`** — pass the flat list of repo-relative file paths already fetched in §1 (for GitHub: the `path` values from the `gh api .../git/trees/{analysis_ref}?recursive=1` response; for local: the equivalent listing).
80
- - **`manifests`** — only the root manifests need contents; child-workspace manifests are looked up from the tree by the script. Include any of `package.json`, `Cargo.toml`, `pnpm-workspace.yaml`, `lerna.json` that appears at the repo root. Fetch them in **one message with N parallel Bash calls** (`gh api .../contents/{path}?ref={analysis_ref}` for GitHub, file reads for local), then base64-decode together. Per-workspace manifest contents (e.g. `packages/foo/package.json`) are optional — including them populates the workspace `name` field with the manifest's declared package name; omitting them falls back to the directory basename.
125
+ For a local source (or the `[L]` clone), drop the first two lines and pass the folder itself: `--manifest-dir "{source_path}"`. The manifest folder of this section is the one §2 and §4 pass again.
81
126
 
82
127
  The script returns a JSON envelope: `{is_monorepo, manifest_kind, workspaces[], warnings[]}`. Apply the result deterministically — see `src/shared/scripts/schemas/workspace-detection.v1.json` for the full contract.
83
128
 
@@ -95,47 +140,39 @@ Which one should the skill cover? Pick a number, or type 'all' to scope at the r
95
140
 
96
141
  Interactive: wait for the user choice. On a numbered choice, store `monorepo_workspace: {path}` and rebase §2-§4b against that path. On `'all'`, leave `monorepo_workspace` unset and proceed at the repo root with a note in the analysis summary that scope is unfiltered.
97
142
 
98
- Headless: if the input contract supplied an `include` glob that begins with one of the workspace paths, auto-select that workspace (log `"headless: auto-selected workspace {name} from include glob"`). Otherwise default to repo root and log `"warn: monorepo detected ({manifest_kind}) but no workspace pre-selected — analyzing at repo root"`.
143
+ **GATE [default: the workspace an `include` glob names, else the repo root]**: headless, if the input contract supplied an `include` glob that begins with one of the workspace paths, auto-select that workspace (log `"headless: auto-selected workspace {name} from include glob"`). Otherwise default to repo root and log `"warn: monorepo detected ({manifest_kind}) but no workspace pre-selected; analyzing at repo root"`.
99
144
 
100
- Surface any non-empty `warnings[]` from the script to the operator log so a malformed root manifest is debuggable; the workflow does not HALT — falling back to repo-root analysis is always safe.
145
+ Log each non-empty `warnings[]` entry from the script and add it to `workflow_warnings[]`, so a malformed or unfetched root manifest is debuggable; the workflow does not HALT, because falling back to repo-root analysis is always safe.
101
146
 
102
147
  **`cross-ecosystem workspace ignored` warning:** when a root workspace manifest from a different language ecosystem co-exists with the surfaced one (e.g. a root `Cargo.toml [workspace]` alongside a pnpm workspace), the script surfaces only the higher-priority kind and emits this warning naming the ignored kind and its member count. The ignored ecosystem's workspaces are **not** in `workspaces[]`, so the numbered menu above will not list them. When this warning is present, tell the operator both ecosystems exist and ask which the skill should cover; if they pick the ignored ecosystem, scope §2-§4b at its root (or the relevant member) rather than the surfaced workspace, and carry the ignored kind into §3 (see the `workspace_signal` note there).
103
148
 
104
149
  ### 2. Read Repository Structure
105
150
 
106
- List the top-level directory structure:
151
+ Display `Reading the repository structure...`, then take the structure from the tree snapshot `{detectWorkspacesHelper}` computes, never from a count of the listing by hand. Add `--root "{monorepo_workspace}"` when §1b picked a workspace:
107
152
 
108
- "**Repository Structure:**
109
- ```
110
- {repo-name}/
111
- ├── {top-level files}
112
- ├── {top-level directories}/
113
- │ └── ...
114
- └── ...
153
+ ```bash
154
+ uv run {detectWorkspacesHelper} --tree-file "{run_dir}/tree.json" --manifest-dir "<§1b's manifest folder>" --snapshot > "{run_dir}/snapshot.json"
115
155
  ```
116
- **Total:** {file count} files, {directory count} directories"
156
+
157
+ It holds `file_count`, `source_file_count`, `dir_count`, `top_level_files`, `top_level_dirs`, `truncated` (the counts are then lower bounds), the `workspaces` detection found, and the module candidates §4.3 picks from.
117
158
 
118
159
  ### 3. Detect Primary Language
119
160
 
120
- **Resolve `{detectLanguageHelper}`** from `{detectLanguageProbeOrder}`; first existing path wins. HALT if no candidate exists.
161
+ Display `Detecting the language...`. **Resolve `{detectLanguageHelper}`** from `{detectLanguageProbeOrder}`; first existing path wins. HALT if no candidate exists.
121
162
 
122
163
  Delegate the rule walk to `{detectLanguageHelper}` instead of evaluating manifest presence and extension frequency in prose:
123
164
 
124
165
  ```bash
125
- echo '{"tree": [<flat list of repo-relative file paths from §1>], "workspace_signal": "<§1b manifest_kind, or omit when null>"}' | uv run {detectLanguageHelper}
166
+ uv run {detectLanguageHelper} --tree-file "{run_dir}/tree.json" [--workspace-signal "<§1b manifest_kind>"]
126
167
  ```
127
168
 
128
- Pass the §1b `manifest_kind` as `workspace_signal` (omit the key when it is `null` / not a monorepo). This gives the workspace root precedence: for a `cargo-workspace` or `python-multi-package` root, the script returns the root language (rust/python) instead of being misled into `typescript` by a nested `package.json` + `tsconfig.json` in a non-workspace subdirectory (e.g. a `docs/` or `website/` site). JS-family workspace kinds (`npm-workspaces`/`pnpm-workspaces`/`lerna`) carry no override — their root `package.json` resolves js/ts normally.
129
-
130
- **When §1b surfaced a `cross-ecosystem workspace ignored` warning and the operator chose the ignored ecosystem:** pass that ignored kind as `workspace_signal` (not the surfaced kind), so a co-located `cargo-workspace`/`python-multi-package` root resolves to rust/python instead of being pinned to the surfaced ecosystem's language by the workspace that won detection priority.
169
+ Pass the §1b `manifest_kind` as `--workspace-signal` (leave the flag out when it is `null` / not a monorepo). This gives the workspace root precedence: for a `cargo-workspace` or `python-multi-package` root, the script returns the root language (rust/python) instead of being misled into `typescript` by a nested `package.json` + `tsconfig.json` in a non-workspace subdirectory (e.g. a `docs/` or `website/` site). JS-family workspace kinds (`npm-workspaces`/`pnpm-workspaces`/`lerna`/`rush`/`nx`) carry no override: their root `package.json` resolves js/ts normally.
131
170
 
132
- The script returns `{language, confidence, detection_source, fallback_to_extension_frequency}` after walking the documented rule table (the `workspace_signal` precedence above first, then manifest presence — package.json with tsconfig.json disambiguation, Cargo.toml, pyproject.toml/setup.py/setup.cfg, go.mod, pom.xml, build.gradle.kts, build.gradle Groovy with Java/Kotlin disambiguation, *.csproj/*.sln, Gemfile — then extension-frequency fallback over recognized source extensions). Use the returned values directly:
171
+ **When §1b surfaced a `cross-ecosystem workspace ignored` warning and the operator chose the ignored ecosystem:** pass that ignored kind as `--workspace-signal` (not the surfaced kind), so a co-located `cargo-workspace`/`python-multi-package` root resolves to rust/python instead of being pinned to the surfaced ecosystem's language by the workspace that won detection priority.
133
172
 
134
- "**Detected language:** {language}
135
- **Confidence:** {confidence}
136
- **Detection source:** {detection_source}"
173
+ The script returns `{language, confidence, detection_source, fallback_to_extension_frequency, source_language, detected_languages}` after walking the documented rule table: the `workspace_signal` precedence above first, then the manifests nearest the tree's root, by folder depth and then rule order (package.json with tsconfig.json disambiguation, Cargo.toml, pyproject.toml/setup.py/setup.cfg, go.mod, pom.xml, build.gradle.kts, Package.swift, Gemfile, build.gradle Groovy with Java/Kotlin disambiguation, *.csproj/*.sln), where a manifest in a docs, examples, tests or other non-core folder, or in a hidden one, decides only when no other exists, then extension-frequency fallback. With no manifest at the root, the nearest one decides at `medium` confidence and `source_language` names the language most source files are in. Use the returned values directly: §5 shows them.
137
174
 
138
- **Headless language override.** If `language_hint` was supplied as a headless argument, use it as the confirmed `{language}` (overriding the detected value) and carry it forward to §4 and step 03. The detector still runs so the "Detected language" line reflects what the source signals, but the explicit hint wins and the step 03 §4 low-confidence override does not fire. When `language_hint` is absent, carry the detected `{language}` forward.
175
+ **Headless language override.** If `language_hint` was supplied as a headless argument, use it as the confirmed `{language}` (overriding the detected value) and carry it forward to §4 and step 03. The detector still runs so §5's Detected-language line reflects what the source signals, but the explicit hint wins and the step 03 §4 low-confidence override does not fire. When `language_hint` is absent, carry the detected `{language}` forward.
139
176
 
140
177
  If `confidence` is `low` (or `unknown` is returned for `language`) and no `language_hint` was supplied: flag for user override in step 03 §4.
141
178
 
@@ -143,61 +180,52 @@ If `confidence` is `low` (or `unknown` is returned for `language`) and no `langu
143
180
 
144
181
  **Resolve `{extractPublicApiHelper}`** from `{extractPublicApiProbeOrder}`; first existing path wins. HALT if no candidate exists.
145
182
 
146
- Identify the public API surface. **Delegate the parsing to `{extractPublicApiHelper}` whenever the detected language is supported** — the script is the single source of truth for manifest parsing, export discovery, and version detection across the whole SKF pipeline. Hand-rolling these in prose creates drift seams the LLM cannot fully close.
183
+ Identify the public API surface. **Delegate the parsing to `{extractPublicApiHelper}` whenever the detected language is supported:** it finds the entry files, parses the manifest, reads the exports and finds the version, so none of them is derived in prose.
147
184
 
148
185
  **Script-supported languages** (use the script): `js`, `ts`, `javascript`, `typescript`, `python`, `rust`, `go`, `java`, `kotlin`.
149
186
 
150
- This section runs exactly one of §4.1 (script path) or §4.2 (fallback path) based on the detected language, then always emits §4.3 (output format) and conditionally §4.4 (semantic signals).
187
+ Display `Listing the exports...`. This section runs exactly one of §4.1 (script path) or §4.2 (fallback path) based on the detected language, then always §4.3 (the modules and exports §5 shows) and conditionally §4.4 (semantic signals).
151
188
 
152
189
  #### 4.1 Procedure — script-supported languages
153
190
 
154
- 1. Read the relevant files into memory (no parsing yet — just collect content). For GitHub sources, issue **all N `gh api repos/{owner}/{repo}/contents/{file}?ref={analysis_ref}` calls in a single message with N parallel Bash calls** (one per manifest + each entry point), then base64-decode the responses together — these are 2-4 independent fetches per typical run. Carrying `{analysis_ref}` through here is what keeps the analyzed exports/version aligned with the pinned tag rather than HEAD. For local sources read directly (also parallelisable, but local reads are fast enough that serial Read tool calls are acceptable).
155
-
156
- | Language | Manifest | Entry points (mode=quick) |
157
- |----------|----------|--------------------------|
158
- | js / ts / javascript / typescript | `package.json` (root, or primary workspace package per `references/version-resolution.md`) | `index.{ts,js}` and/or `src/index.{ts,js}` if present |
159
- | python | `pyproject.toml` (or `setup.py` / `setup.cfg` if no `pyproject.toml`) | top-level `__init__.py` of the package, plus `_version.py` if present |
160
- | rust | `Cargo.toml` (`[package]` — workspace root if `version = { workspace = true }`) | `src/lib.rs` |
161
- | go | `go.mod` | top-level `*.go` exporting the package surface |
162
- | java | `pom.xml` | (manifest alone is sufficient for the modules listing) |
163
- | kotlin | `build.gradle` / `build.gradle.kts` | (manifest alone) |
164
-
165
- 2. Build a JSON payload matching the script contract:
166
-
167
- ```json
168
- {
169
- "language": "<one of the supported values>",
170
- "manifest": {"path": "<relative path>", "content": "<file contents>"},
171
- "entries": [{"path": "<relative path>", "content": "<file contents>"}, ...],
172
- "mode": "quick"
173
- }
191
+ `<source root>` is `{run_dir}/files` for a GitHub source. For a local source, or the `[L]` clone, it is `{source_path}`, whose files need no fetch: leave the `{githubFetchHelper}` lines and step 2's `--repo` and `--ref` out. When §1b picked a workspace, prefix each manifest candidate with `{monorepo_workspace}/` and pass `--scope "{monorepo_workspace}"`.
192
+
193
+ 1. **Find the entry files.** Fetch the manifest candidates (the listing decides which exist), let the extractor find the entry files in the listing by full mode's rules, and fetch the files it lists:
194
+
195
+ ```bash
196
+ uv run {githubFetchHelper} --repo "{owner}/{repo}" --ref "{analysis_ref}" --tree-file "{run_dir}/tree.json" --dest "{run_dir}/files" package.json pyproject.toml setup.py setup.cfg Cargo.toml go.mod pom.xml build.gradle.kts build.gradle
197
+ uv run {extractPublicApiHelper} --mode entries --language "<language>" --tree-file "{run_dir}/tree.json" --source-root "<source root>" [--scope "{monorepo_workspace}"] --fetch-list "{run_dir}/entries.txt" > "{run_dir}/entries.json"
198
+ uv run {githubFetchHelper} --repo "{owner}/{repo}" --ref "{analysis_ref}" --tree-file "{run_dir}/tree.json" --dest "{run_dir}/files" --patterns-file "{run_dir}/entries.txt"
174
199
  ```
175
200
 
176
- 3. Invoke the script and parse its JSON stdout:
201
+ `{run_dir}/entries.json` names the `manifest` the extractor read and its `entry_files`: never pick an entry file yourself. Its `unresolved` and `warnings` join the extraction warnings §5 shows. When the entries call exits non-zero, or it names neither a manifest nor an entry file, there is nothing to parse: skip the rest of §4.1 and take §4.2.
202
+
203
+ 2. **Parse them and follow their re-exports** by path: the `manifest` (no `--manifest-file` when it is null) and one `--entry-file` per entry file (for a GitHub source, each one the fetch `fetched`):
177
204
 
178
205
  ```bash
179
- echo '<payload-json>' | uv run {extractPublicApiHelper} --mode quick
206
+ uv run {extractPublicApiHelper} --mode quick --language "<language>" --source-root "<source root>" --tree-file "{run_dir}/tree.json" --manifest-file "<manifest path>" --entry-file "<entry path>" --follow --resolve-version [--repo "{owner}/{repo}" --ref "{analysis_ref}"] > "{run_dir}/extract.json"
180
207
  ```
181
208
 
182
- On a non-zero exit (codes 1 or 2 per the script's docstring), capture stderr, log it, and fall through to §4.2 (the prose-fallback path) — never HALT just because the script choked on an unusual manifest.
209
+ `--follow` reads each module an `export *` or a star import passes names on from, round after round, so a chain is read to its end, and lists them in `followed`; for a GitHub source, `--repo` and `--ref` fetch each into `{run_dir}/files` first. A module it could not read stays in `unlisted[]`, and a warning names it. `--resolve-version` looks up a version the manifest does not state.
183
210
 
184
- 4. Render the returned `package_name`, `exports` (each entry's `name`/`type`/`source_file`), `dependencies`, and any `warnings` to the user. The script also returns `version` — feed that into §4b instead of re-deriving.
211
+ 3. On a non-zero exit of the extractor (codes 1 or 2 per its docstring), log its stderr and fall through to §4.2 (the prose-fallback path), which writes over `{run_dir}/extract.json`: never HALT just because the script choked on an unusual manifest.
185
212
 
186
- 5. The script does not enumerate directories under `src/`. The LLM still lists those as "Top-Level Modules/Directories" so the user sees structural context (Maven and Gradle are the exception — for those, the script returns a `modules` array which IS the list).
213
+ 4. Keep `{run_dir}/extract.json`'s `package_name`, `exports` (each entry's `name`/`type`/`source_file`), `dependencies` and `warnings` for §5, which shows the package, its dependency count, the exports and the warnings. Its `version` feeds §4b, and step 3 counts its exports.
187
214
 
188
215
  #### 4.2 Procedure — fallback (not script-supported)
189
216
 
190
217
  Languages outside the script coverage (Ruby / C# / Swift / etc.) take this path. The §4.1 fall-through on script error also lands here.
191
218
 
192
- Fall back to ad-hoc inspection — `Gemfile` / `*.csproj` / `*.sln` / `Package.swift` / file extension frequency. List top-level source directories as potential modules and note any obvious entry points. Flag the limitation in the analysis summary so the user knows scoping is on coarser signals.
219
+ Fall back to ad-hoc inspection of `Gemfile` / `*.csproj` / `*.sln` / `Package.swift` / file extension frequency. Read the files you inspect from `{run_dir}/files` (fetched with §4.1's fetch line, naming them) or the local folder. Note any obvious entry points, and flag the limitation in the analysis summary so the user knows scoping is on coarser signals. Then stage an extraction with no export, so step 3 reads `{run_dir}/extract.json` on either path: `printf '{"exports": []}' > "{run_dir}/extract.json"`.
193
220
 
194
221
  #### 4.3 Output format (both paths)
195
222
 
196
- "**Top-Level Modules/Directories:**
197
- {numbered list of modules with brief description of each}
223
+ Display `Picking the top-level modules...`. The snapshot lists candidates and names no module on purpose: a folder-name rule misreads `LICENSES`, `ci`, `web` or lodash's `lib/`. **Pick the Top-Level Modules from `{run_dir}/snapshot.json`** (Maven and Gradle aside: there the §4.1 script's `modules` array is the list):
224
+ - The snapshot's `workspaces`, when it lists some.
225
+ - Else the `module_candidates` that hold the library's own code: not a folder with no source file (`source_file_count` 0), nor one of tests, docs, examples, scripts, build tooling or CI.
226
+ - When one candidate holds most of the source files, it is the package itself (`pandas/` at the root of pandas): run the snapshot again for that folder, `uv run {detectWorkspacesHelper} --tree-file "{run_dir}/tree.json" --snapshot --root "<that folder>" > "{run_dir}/package-snapshot.json"`, and pick among its candidates.
198
227
 
199
- **Detected Exports/Entry Points:**
200
- {numbered list of public-facing items found — from script output when available, ad-hoc inspection otherwise}"
228
+ The number of modules picked is `module_count`, which step 3 §2c passes the scope-type recommender (0 when none qualifies). Give each picked module a one-line description. The exports are the §4.1 script's `exports`, or the entry points §4.2 found.
201
229
 
202
230
  #### 4.4 Semantic Signals (Forge+/Deep with ccc only)
203
231
 
@@ -217,56 +245,60 @@ If results are returned, display:
217
245
  "**Semantic Signals (ccc):**
218
246
  {numbered list of file:snippet pairs from CCC results — top 5 most relevant}"
219
247
 
220
- This supplements — never replaces — the explicit module list above. CCC may surface non-obvious entry points (dynamically constructed exports, re-export chains) that static directory analysis misses.
248
+ This supplements, and never replaces, the module list §4.3 picked. CCC may surface non-obvious entry points (dynamically constructed exports, re-export chains) that static directory analysis misses.
221
249
 
222
250
  If CCC is unavailable or returns no results: skip this subsection silently.
223
251
 
224
252
  ### 4b. Detect Source Version
225
253
 
226
- **When the language was script-supported (§4 took the script path):** the `version` field returned by `{extractPublicApiHelper}` IS the detected version — do not re-derive it and do not load `{versionResolutionFile}`. The script already implements the language-specific lookups documented in that reference, so loading the reference here only burns context.
227
-
228
- **When the language was not script-supported:** load `{versionResolutionFile}` and follow the prose Detection Algorithm directly (Ruby / C# / Swift / etc. fall outside the script's coverage).
229
-
230
- Surface the result regardless of which path produced it:
231
-
232
- **If `target_version` was provided in step 01:**
233
- - Display: "**Target version:** {target_version} (user-specified)"
254
+ **When §4.1 ran:** `{run_dir}/extract.json`'s `version` is the detected version, null when the extractor found none. Do not derive it again or load `{versionResolutionFile}`.
234
255
 
235
- Display: "**Detected version:** {version or 'Not detected — will default to 1.0.0'}"
256
+ **When §4.2 ran:** load `{versionResolutionFile}` and run its Detection Algorithm.
236
257
 
237
- {If target_version was provided AND auto-detected version differs:}
238
- "**Note:** Detected version ({detected_version}) differs from your target version ({target_version}). Using target version (per `references/version-resolution.md` precedence rules)."
239
-
240
- If detection fails or returns a non-semver value: note that version will default to `"1.0.0"` and the user can override in step 04. The actual write happens in step 05.
258
+ Whichever path produced it, keep the detected version for §5, which shows it beside `target_version`. The actual write happens in step 05.
241
259
 
242
260
  ### 5. Report Analysis Summary
243
261
 
244
- Present the complete analysis:
262
+ Present the complete analysis, the counts and notable files read from `{run_dir}/snapshot.json`:
245
263
 
246
264
  "**Analysis Complete**
247
265
 
248
266
  ---
249
267
 
250
268
  **Target:** {repo URL or path}
251
- **Language:** {detected language} ({confidence})
252
- **Structure:** {file count} files across {directory count} directories
269
+ {If §4.1 returned a `package_name`:}
270
+ **Package:** {package_name} ({the number of its `dependencies`} dependencies)
271
+ **Detected language:** {the detector's language} ({confidence}, {detection_source})
272
+ {If a `language_hint` or a ratified brief set the language:}
273
+ **Language:** {language} (kept over the detected one)
274
+ **Structure:** {file_count} files ({source_file_count} source files) across {dir_count} directories
253
275
 
254
- **Key Modules ({count}):**
255
- {bulleted list of modules}
276
+ **Key Modules ({module_count}):**
277
+ {bulleted list of the §4.3 modules, each with its one-line description}
256
278
 
257
279
  **Public Exports/Entry Points ({count}):**
258
- {bulleted list of exports}
280
+ {bulleted list of the §4.3 exports}
281
+
282
+ **Version:** {on a ratify run, the hydrated `version`; otherwise:}
283
+ - Detected version: {the §4b version, or `not detected: defaulting to 1.0.0, which you can change when you confirm the brief` when detection failed or returned a non-semver value}
284
+ {If `target_version` was provided in step 01:}
285
+ - Target version: {target_version} (user-specified)
286
+ {If `target_version` was provided AND the detected version differs:}
287
+ - Note: the detected version ({detected_version}) differs from your target version ({target_version}). Using target version (per `references/version-resolution.md` precedence rules).
288
+
289
+ {If §4.1 returned `warnings`:}
290
+ **Extraction warnings:**
291
+ {one bullet per warning}
259
292
 
260
293
  **Notable Files:**
261
- - README: {found/not found}
262
- - Tests: {found/not found — location}
263
- - Docs: {found/not found — location}
264
- - Config: {list of config files found}
265
- - Version: {detected version or "Not detected — defaulting to 1.0.0"}
294
+ - README: {a README file in `top_level_files`, or not found}
295
+ - Tests: {a tests folder in `top_level_dirs` (`test`, `tests`, `__tests__`, `spec`), or not found}
296
+ - Docs: {a docs folder in `top_level_dirs` (`docs`, `doc`, `documentation`), or not found}
297
+ - Config: {the configuration files in `top_level_files`}
266
298
  {If the target was a GitHub URL:}
267
299
  - Analysis ref: {analysis_ref} {append " (resolved from target_version {target_version})" when a tag was matched, or " (no tag matched {target_version} — analyzed default branch)" on the zero-match fallback}
268
300
 
269
- Store `{analysis_ref}` in workflow context — step 03 (`scope-definition.md`) reuses it for any further `contents/` fetches so scope analysis reads the same ref as this step.
301
+ Store `{analysis_ref}` and `module_count` in workflow context: step 03 (`scope-definition.md`) reuses them, with `{run_dir}/tree.json`, the fetched files and `{run_dir}/extract.json`, so scope analysis reads the same ref as this step.
270
302
 
271
303
  ---
272
304
 
@@ -275,21 +307,6 @@ Store `{analysis_ref}` in workflow context — step 03 (`scope-definition.md`) r
275
307
 
276
308
  Moving to scope definition where you'll choose what to include and exclude."
277
309
 
278
- ### 6. Auto-Proceed to Scope Definition
279
-
280
- Display: "**Proceeding to scope definition...**
281
-
282
- Review the analysis above. If anything looks wrong, let me know now — otherwise I'll proceed to scope definition."
283
-
284
- Pause briefly for user input. If the user provides corrections or asks questions, address them and re-present any updated analysis findings. Then proceed.
285
-
286
- #### Menu Handling Logic:
287
-
288
- - After analysis report is presented to user and any corrections addressed, load, read entire file, then execute {nextStepFile}
289
-
290
- #### Execution rules:
291
-
292
- - This is a soft auto-proceed step — present the pause prompt, wait briefly for user input
293
- - If user provides corrections: address them, then proceed
294
- - If no user input after a brief pause: proceed directly to step 03
310
+ ### 6. Proceed to Scope Definition
295
311
 
312
+ In the same turn as the §5 summary, load, read entire file, then execute {nextStepFile}: step 3 §1 asks whether anything in this analysis is wrong, and applies a correction before a scope decision relies on it.
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  nextStepFile: 'write-brief.md'
3
3
  reviseStepFile: 'scope-definition.md'
4
+ analyzeStepFile: 'analyze-target.md'
4
5
  advancedElicitationSkill: '/bmad-advanced-elicitation'
5
6
  partyModeSkill: '/bmad-party-mode'
6
7
  ---
@@ -17,9 +18,11 @@ partyModeSkill: '/bmad-party-mode'
17
18
 
18
19
  ### 1. Assemble Complete Brief
19
20
 
20
- Use the values already accepted in steps 01-03 directly — do not re-load `{briefSchemaPath}` here. The 18 fields below are all in conversation; the schema is only consulted in §4 if an inline adjustment needs a specific field's validation rule cited.
21
+ Use the values already accepted in steps 01-03 directly: do not load `assets/skill-brief-schema.md` here. The 18 fields below are all in conversation; the schema is only consulted in §4 if an inline adjustment needs a specific field's validation rule cited.
21
22
 
22
- **Ratify run (`ratify_mode: true`):** steps 2-3 were skipped (interactive `[R]` at gather-intent §3.1a, or the headless §8 GATE `from_brief` route), so there is no fresh steps 01-03 output to compile. Use the brief context variables **hydrated from the parsed brief** at step 1 in place of that output — the hydrated variable names match the field references below one-for-one. `detected_version` is absent on this path; rely on the hydrated `version` (step 5 pins it via `version_resolved`).
23
+ **Ratify run (`ratify_mode: true`):** steps 2-3 were skipped (step 1 ratified a brief through `references/gather-intent-ratify.md`: a brief path at the first prompt, or a headless `from_brief`), so there is no fresh steps 01-03 output to compile. Use the brief context variables **hydrated from the parsed brief** at step 1 in place of that output: the hydrated variable names match the field references below one-for-one. `detected_version` is absent on this path; rely on the hydrated `version` (step 5 writes from the ratified file, which keeps it).
24
+
25
+ After a `[R]` pass on a ratify run, take `scope.*`, `scripts_intent`, `assets_intent` and `doc_urls` from step 3, except `scope.amendments`, which step 3 never writes; every other field, `scope.amendments` included, stays hydrated.
23
26
 
24
27
  Compile all gathered data from steps 01-03 into the complete brief:
25
28
 
@@ -57,6 +60,7 @@ Skill Brief: {name}
57
60
  ====================
58
61
 
59
62
  Target: {source_repo}
63
+ Target ref: {target_ref; omit this line entirely when target_ref is unset}
60
64
  Language: {language}
61
65
  Forge Tier: {forge_tier} — {tier_gloss}
62
66
  Description: {description}
@@ -104,7 +108,7 @@ Glosses (substitute the matching one-liner for `{tier_gloss}`, `{scripts_gloss}`
104
108
  - `Deep`: full pipeline — AST + ccc + qmd portfolio search + LLM re-ranking
105
109
 
106
110
  - **`scripts_intent` / `assets_intent` glosses** —
107
- - `detect`: SKF will scan source for the standard `scripts/`/`bin/`/`tools/`/`cli/` (or `assets/`/`templates/`/`schemas/`/`configs/`) directories during create-skill and decide automatically
111
+ - `detect`: SKF will scan source for the standard `scripts/`/`bin/`/`tools/`/`cli/` (or `assets/`/`templates/`/`schemas/`/`configs/`) directories during create-skill and decide automatically (when one of the four script folders is a Python package, holding `__init__.py`, only its `__main__.py` and the modules with a shebang or a `__main__` block count as scripts)
108
112
  - `none`: no script/asset packaging — create-skill will skip the detection pass
109
113
  - free-text (anything else): a description of what to package; create-skill treats it as the user's spec
110
114
 
@@ -117,7 +121,7 @@ Flag any fields that may need review:
117
121
  {If language was overridden or low confidence:}
118
122
  "**Note:** Language was {auto-detected / manually overridden}."
119
123
 
120
- "**Description:** synthesized and confirmed in step 1 §7b. This is the text agents read when deciding whether to route to your skill — refine here if you want to tighten it now that the full brief is visible."
124
+ "**Description:** synthesized in step 1 and accepted there. This is the text agents read when deciding whether to route to your skill: refine it here if you want to tighten it now that the full brief is visible."
121
125
 
122
126
  {If forge tier was defaulted:}
123
127
  "**Note:** Forge tier defaulted to Quick (no forge-tier.yaml found)."
@@ -138,7 +142,7 @@ You can:
138
142
  ### 4. Handle Inline Adjustments
139
143
 
140
144
  If the user requests changes to specific fields (name, description, version, etc.):
141
- - If the adjustment requires explaining a field's validation rule or allowed values, load `{briefSchemaPath}` now (otherwise skip the read — the common path does not need it)
145
+ - If the adjustment requires explaining a field's validation rule or allowed values, load `assets/skill-brief-schema.md` now (otherwise skip the read: the common path does not need it)
142
146
  - Make the adjustment
143
147
  - Re-present the updated brief
144
148
  - Return to the menu
@@ -149,16 +153,14 @@ Display: **Select an Option:** [R] Revise Scope [A] Advanced Elicitation [P] Par
149
153
 
150
154
  #### Menu Handling Logic:
151
155
 
152
- - IF R: Load, read entire file, then execute {reviseStepFile} to re-enter scope definition
156
+ - IF R: When `ratify_mode` is true, `source_type` is not `docs-only` and `ratify_analyzed` is not set, load, read entire file, then execute {analyzeStepFile}, which chains to scope definition. Otherwise load, read entire file, then execute {reviseStepFile} to re-enter scope definition
153
157
  - IF A: Invoke {advancedElicitationSkill}, and when finished redisplay the menu
154
158
  - IF P: Invoke {partyModeSkill}, and when finished redisplay the menu
155
159
  - IF C: Load, read entire file, then execute {nextStepFile}
156
- - IF X: Treat as user-cancellation. Display `"Cancelled — no brief was written."` and HALT (exit code 6, `halt_reason: "user-cancelled"`). Cancellation here is non-destructive — step 5 has not run, no skill-brief.yaml file exists yet. `[X]` is interactive-only; the headless GATE never reaches this branch.
160
+ - IF X: Treat as user-cancellation. Remove the run folder (`case "{run_dir}" in "{project-root}/_bmad-output/.skf-run/skf-brief-skill-"*) rm -rf "{run_dir}" ;; esac`), display `"Cancelled: no brief was written."` and HALT (exit code 6, `halt_reason: "user-cancelled"`). Step 5 has not run, so no brief was written; a saved draft stays for a later resume. `[X]` is interactive-only; the headless GATE never reaches this branch.
157
161
  - IF Any other comments or queries: help user respond, apply any field adjustments, re-present brief if changed, then [Redisplay Menu Options](#5-present-menu-options)
158
162
 
159
163
  #### Execution rules:
160
164
 
161
165
  - **GATE [default: C]** — If `{headless_mode}`: auto-proceed with [C] Confirm, log: "headless: auto-confirm brief"
162
- - After other menu items execution, return to this menu
163
- - User can chat, request field changes, or ask questions — always respond and then redisplay menu
164
166