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
@@ -1,5 +1,5 @@
1
1
  # /// script
2
- # requires-python = ">=3.9"
2
+ # requires-python = ">=3.11"
3
3
  # dependencies = ["pyyaml"]
4
4
  # ///
5
5
  """SKF Pre-Apply — apply known workarounds before pipeline iteration.
@@ -1,11 +1,13 @@
1
1
  # /// script
2
- # requires-python = ">=3.10"
2
+ # requires-python = ">=3.11"
3
3
  # dependencies = ["pyyaml"]
4
4
  # ///
5
5
  """SKF Preflight — Config and sidecar loader for all SKF skills.
6
6
 
7
7
  Loads config.yaml, validates sidecar_path, loads preferences.yaml and
8
8
  forge-tier.yaml, and outputs a unified JSON blob for step consumption.
9
+ Ferris (skf-forger) runs it at activation and again for WS, with
10
+ --allow-missing-sidecar.
9
11
 
10
12
  CLI — invoke via `uv run` so the PEP 723 PyYAML dependency declared
11
13
  above is auto-resolved on first call and cached. `docs/getting-started.md`
@@ -16,14 +18,41 @@ on stdout — that fallback is the safety net, not the canonical path:
16
18
 
17
19
  uv run skf-preflight.py <project-root>
18
20
  uv run skf-preflight.py <project-root> --config-path <alt-config>
21
+ uv run skf-preflight.py <project-root> --allow-missing-sidecar
22
+
23
+ --allow-missing-sidecar: a sidecar folder that does not exist yet (a first
24
+ run, before skf-setup writes it) is not a halt. The run goes on with empty
25
+ preferences and forge tier, and `sidecar.missing` is true.
26
+
27
+ Folder values: the BMAD Method installer writes each folder in config.yaml
28
+ as `{project-root}/<value>`, and the standalone installer writes it relative
29
+ to the project root. `config` keeps each raw value and adds its absolute
30
+ path: `output_folder_resolved`, `skills_output_folder_resolved`,
31
+ `forge_data_folder_resolved` ("" for an empty value) and
32
+ `sidecar_path_resolved`. A sidecar_path that still holds a placeholder once
33
+ `{project-root}` is expanded, such as `{sidecar_path}` or the `{value}` of
34
+ `{project-root}/{value}`, halts with SIDECAR_UNDEFINED, flag or not.
19
35
 
20
36
  Output: JSON to stdout with all resolved config variables and sidecar state.
21
- Exit 0 on success, exit 1 on hard-halt conditions (missing config, bad sidecar).
37
+ `sidecar.preferences` and `sidecar.forge_tier` are {} for a file that is
38
+ not there yet, and `sidecar.preferences_error` or
39
+ `sidecar.forge_tier_error` appears only for a file that is there but did not
40
+ load. `derived` holds what a greeting needs: `tier`, `tier_source`,
41
+ `compact_greeting`, `headless_mode` (true only for `headless_mode: true` in
42
+ preferences.yaml) and `is_first_run`.
43
+ Exit 0 on success, exit 1 on a hard halt, whose `code` is CONFIG_MISSING
44
+ (no config.yaml: SKF is not installed, so the error names the installer),
45
+ CONFIG_MALFORMED (config.yaml is there but cannot be read or is not a YAML
46
+ mapping), SIDECAR_UNDEFINED or, without --allow-missing-sidecar,
47
+ SIDECAR_MISSING.
22
48
  """
23
49
 
24
50
  from __future__ import annotations
25
51
 
52
+ import datetime
26
53
  import json
54
+ import re
55
+ import stat
27
56
  import sys
28
57
  from pathlib import Path
29
58
 
@@ -39,20 +68,111 @@ except ImportError:
39
68
  sys.exit(1)
40
69
 
41
70
 
71
+ # skf-setup halts on a missing config.yaml and never writes one: only the
72
+ # installer does. Ferris's config guard and skf-setup's
73
+ # on-activation:config-missing reason name the same two commands.
74
+ INSTALL_REMEDY = (
75
+ "From the project root, run npx bmad-module-skill-forge install "
76
+ "(or npx bmad-method install and add SKF), then run the skf-setup skill."
77
+ )
78
+
79
+ # The BMAD Method installer writes folder values as `{project-root}/<value>`
80
+ # (module.yaml's `result`). Only a whole leading segment is the placeholder.
81
+ PROJECT_ROOT_RE = re.compile(r"\A\{project-root\}(?:[/\\]+|\Z)")
82
+ PLACEHOLDER_RE = re.compile(r"\{[^{}]*\}")
83
+ FOLDER_KEYS = ("output_folder", "skills_output_folder", "forge_data_folder")
84
+
85
+
86
+ def _json_default(value):
87
+ """Print a date or time as ISO 8601.
88
+
89
+ YAML reads an unquoted timestamp as a date or datetime object. SKF 1.x
90
+ wrote ``tier_detected_at`` and ``ccc_index.last_indexed`` in
91
+ forge-tier.yaml unquoted, so a sidecar from before 2.0.0 holds them; any
92
+ other value json cannot print is still an error.
93
+ """
94
+ if isinstance(value, (datetime.date, datetime.time)):
95
+ return value.isoformat()
96
+ raise TypeError(f"Object of type {type(value).__name__} is not JSON serializable")
97
+
98
+
42
99
  def load_yaml_file(path):
43
- """Load a YAML file, returning (data, None) or (None, error_string)."""
100
+ """Load a YAML mapping, returning (data, None) or (None, error_string).
101
+
102
+ An empty file reads as an empty mapping. A file that is not there raises
103
+ FileNotFoundError, which each caller reads its own way: CONFIG_MISSING
104
+ for config.yaml, empty defaults for a sidecar file. Every file this
105
+ script loads is a mapping of keys, so a file that is there but cannot be
106
+ read, or whose top level is a list or a scalar, is an error instead of a
107
+ crash.
108
+ """
44
109
  try:
45
110
  with open(path, encoding="utf-8") as f:
46
111
  data = yaml.safe_load(f)
47
- return data or {}, None
48
112
  except FileNotFoundError:
49
- return None, f"File not found: {path}"
113
+ raise
50
114
  except yaml.YAMLError as e:
51
115
  return None, f"YAML parse error in {path}: {e}"
116
+ except (OSError, ValueError) as e:
117
+ # A folder named like the file, a parent folder that cannot be
118
+ # searched, no read permission, or bytes that are not UTF-8.
119
+ return None, f"Cannot read {path}: {e}"
120
+ if data is None:
121
+ return {}, None
122
+ if not isinstance(data, dict):
123
+ return None, f"Not a YAML mapping: {path} holds a {type(data).__name__}"
124
+ return data, None
52
125
 
53
126
 
54
- def run_preflight(project_root, config_path=None):
55
- """Run preflight checks and return a result dict."""
127
+ def load_sidecar_file(path):
128
+ """Load a sidecar file. One that is not there yet reads as {}."""
129
+ try:
130
+ return load_yaml_file(path)
131
+ except FileNotFoundError:
132
+ return {}, None
133
+
134
+
135
+ def resolve_folder(value, project_root):
136
+ """Return (absolute path, placeholder) for a folder value from config.yaml.
137
+
138
+ A leading `{project-root}` segment becomes the project root, and a
139
+ relative path is joined to it. `placeholder` is the first `{...}` token
140
+ left after that, or None. An empty value gives ("", None).
141
+ """
142
+ if not value:
143
+ return "", None
144
+ value = str(value)
145
+ anchored = PROJECT_ROOT_RE.match(value)
146
+ rest = value[anchored.end():] if anchored else value
147
+ placeholder = PLACEHOLDER_RE.search(rest)
148
+ path = Path(rest)
149
+ if not path.is_absolute():
150
+ path = project_root / path
151
+ return str(path), placeholder.group(0) if placeholder else None
152
+
153
+
154
+ def folder_missing(path):
155
+ """True when no folder is at `path`.
156
+
157
+ A folder that cannot be checked, such as one under a parent folder that
158
+ cannot be searched, counts as there, so the reads that follow report why
159
+ its files did not load. Path.is_dir() raises for that on Python 3.12 and
160
+ returns False on 3.14.
161
+ """
162
+ try:
163
+ return not stat.S_ISDIR(path.stat().st_mode)
164
+ except (FileNotFoundError, NotADirectoryError):
165
+ return True
166
+ except (OSError, ValueError):
167
+ return False
168
+
169
+
170
+ def run_preflight(project_root, config_path=None, allow_missing_sidecar=False):
171
+ """Run preflight checks and return a result dict.
172
+
173
+ `allow_missing_sidecar` turns a missing sidecar folder into empty
174
+ defaults instead of the SIDECAR_MISSING halt.
175
+ """
56
176
  project_root = Path(project_root).resolve()
57
177
 
58
178
  # 1. Load config.yaml
@@ -61,13 +181,25 @@ def run_preflight(project_root, config_path=None):
61
181
  else:
62
182
  cfg_path = project_root / "_bmad" / "skf" / "config.yaml"
63
183
 
64
- config, err = load_yaml_file(cfg_path)
65
- if err:
184
+ try:
185
+ config, err = load_yaml_file(cfg_path)
186
+ except FileNotFoundError:
66
187
  return {
67
188
  "status": "hard-halt",
68
- "error": f"Cannot initialize. SKF config not found at {cfg_path}. Run the skf-setup skill to initialize your forge environment.",
189
+ "error": f"Cannot initialize. SKF is not installed in this project ({cfg_path} not found). {INSTALL_REMEDY}",
69
190
  "code": "CONFIG_MISSING",
70
191
  }
192
+ if err:
193
+ # An update install restores an existing config.yaml as it is, so
194
+ # this error names the file to repair instead of the installer.
195
+ return {
196
+ "status": "hard-halt",
197
+ "error": (
198
+ f"Cannot initialize. {' '.join(err.split())}. "
199
+ "Repair the file, or restore it from version control, and retry."
200
+ ),
201
+ "code": "CONFIG_MALFORMED",
202
+ }
71
203
 
72
204
  # 2. Resolve config variables
73
205
  resolved = {
@@ -82,26 +214,30 @@ def run_preflight(project_root, config_path=None):
82
214
  "skills_output_folder": config.get("skills_output_folder", ""),
83
215
  "forge_data_folder": config.get("forge_data_folder", ""),
84
216
  }
217
+ for key in FOLDER_KEYS:
218
+ resolved[f"{key}_resolved"] = resolve_folder(resolved[key], project_root)[0]
85
219
 
86
- # 3. Validate sidecar_path
87
- sidecar_path = resolved["sidecar_path"]
88
- if not sidecar_path or sidecar_path == "{sidecar_path}":
220
+ # 3. Validate sidecar_path, before the folder check, so that
221
+ # --allow-missing-sidecar never reads an unresolved path as a first run.
222
+ # The advice is the standalone installer's relative value: unquoted, a
223
+ # value that starts with {project-root} would be a YAML flow mapping.
224
+ sidecar_path, placeholder = resolve_folder(resolved["sidecar_path"], project_root)
225
+ if not sidecar_path or placeholder:
226
+ found = f"holds the placeholder {placeholder}" if placeholder else "is not defined"
89
227
  return {
90
228
  "status": "hard-halt",
91
229
  "error": (
92
- "Cannot initialize. sidecar_path is not defined in your installed config.yaml. "
93
- f"Add sidecar_path: {project_root}/_bmad/_memory/forger-sidecar to your project "
94
- "config.yaml and retry. This is a known installer issue with prompt: false config variables."
230
+ f"Cannot initialize. sidecar_path {found} in {cfg_path}. "
231
+ "Set sidecar_path to _bmad/_memory/forger-sidecar, a path from the project root, and retry. "
232
+ "This is a known installer issue with prompt: false config variables."
95
233
  ),
96
234
  "code": "SIDECAR_UNDEFINED",
97
235
  "config": resolved,
98
236
  }
99
237
 
100
238
  sidecar_dir = Path(sidecar_path)
101
- if not sidecar_dir.is_absolute():
102
- sidecar_dir = project_root / sidecar_path
103
-
104
- if not sidecar_dir.is_dir():
239
+ sidecar_missing = folder_missing(sidecar_dir)
240
+ if sidecar_missing and not allow_missing_sidecar:
105
241
  return {
106
242
  "status": "hard-halt",
107
243
  "error": f"Sidecar directory not found: {sidecar_dir}. Run skf-setup to initialize.",
@@ -111,11 +247,15 @@ def run_preflight(project_root, config_path=None):
111
247
 
112
248
  resolved["sidecar_path_resolved"] = str(sidecar_dir)
113
249
 
114
- # 4. Load sidecar files
115
- sidecar = {}
250
+ # 4. Load sidecar files. A missing folder (allowed above) or a file not
251
+ # written yet reads as empty defaults with no error: the installer writes
252
+ # preferences.yaml, and skf-setup creates the folder and forge-tier.yaml
253
+ # on its first run. An `*_error` field is left for a file that is there
254
+ # but did not load.
255
+ sidecar = {"missing": sidecar_missing}
116
256
 
117
257
  prefs_path = sidecar_dir / "preferences.yaml"
118
- prefs, prefs_err = load_yaml_file(prefs_path)
258
+ prefs, prefs_err = ({}, None) if sidecar_missing else load_sidecar_file(prefs_path)
119
259
  if prefs_err:
120
260
  sidecar["preferences"] = None
121
261
  sidecar["preferences_error"] = prefs_err
@@ -123,7 +263,7 @@ def run_preflight(project_root, config_path=None):
123
263
  sidecar["preferences"] = prefs
124
264
 
125
265
  tier_path = sidecar_dir / "forge-tier.yaml"
126
- tier, tier_err = load_yaml_file(tier_path)
266
+ tier, tier_err = ({}, None) if sidecar_missing else load_sidecar_file(tier_path)
127
267
  if tier_err:
128
268
  sidecar["forge_tier"] = None
129
269
  sidecar["forge_tier_error"] = tier_err
@@ -139,6 +279,10 @@ def run_preflight(project_root, config_path=None):
139
279
  if prefs:
140
280
  compact_greeting = prefs.get("compact_greeting", False) is True
141
281
 
282
+ headless_mode = False
283
+ if prefs:
284
+ headless_mode = prefs.get("headless_mode", False) is True
285
+
142
286
  tier_override = None
143
287
  if prefs:
144
288
  tier_override = prefs.get("tier_override")
@@ -151,14 +295,18 @@ def run_preflight(project_root, config_path=None):
151
295
  "tier": tier_override or tier_value,
152
296
  "tier_source": "override" if tier_override else ("detected" if tier_value else None),
153
297
  "compact_greeting": compact_greeting,
298
+ "headless_mode": headless_mode,
154
299
  "is_first_run": tier_value is None,
155
300
  },
156
301
  }
157
302
 
158
303
 
304
+ USAGE = "Usage: uv run skf-preflight.py <project-root> [--config-path <path>] [--allow-missing-sidecar]"
305
+
306
+
159
307
  if __name__ == "__main__":
160
- if len(sys.argv) < 2:
161
- print("Usage: uv run skf-preflight.py <project-root> [--config-path <path>]", file=sys.stderr)
308
+ if len(sys.argv) < 2 or sys.argv[1].startswith("--"):
309
+ print(USAGE, file=sys.stderr)
162
310
  sys.exit(1)
163
311
 
164
312
  proj_root = sys.argv[1]
@@ -169,6 +317,6 @@ if __name__ == "__main__":
169
317
  if idx + 1 < len(sys.argv):
170
318
  cfg_path = sys.argv[idx + 1]
171
319
 
172
- result = run_preflight(proj_root, cfg_path)
173
- print(json.dumps(result, indent=2))
320
+ result = run_preflight(proj_root, cfg_path, allow_missing_sidecar="--allow-missing-sidecar" in sys.argv)
321
+ print(json.dumps(result, indent=2, default=_json_default))
174
322
  sys.exit(1 if result["status"] == "hard-halt" else 0)