bmad-module-skill-forge 2.1.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (435) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/README.md +51 -49
  3. package/docs/404.md +10 -8
  4. package/docs/_data/pinned.yaml +22 -13
  5. package/docs/_internal/STABILITY.md +58 -35
  6. package/docs/agents.md +39 -53
  7. package/docs/architecture.md +65 -51
  8. package/docs/bmad-synergy.md +53 -51
  9. package/docs/campaign.md +127 -75
  10. package/docs/concepts.md +34 -28
  11. package/docs/examples.md +70 -68
  12. package/docs/forge-auto.md +34 -31
  13. package/docs/getting-started.md +118 -57
  14. package/docs/how-it-works.md +25 -21
  15. package/docs/index.md +15 -15
  16. package/docs/skill-model.md +70 -59
  17. package/docs/troubleshooting.md +135 -18
  18. package/docs/verifying-a-skill.md +83 -57
  19. package/docs/why-skf.md +24 -22
  20. package/docs/workflows.md +274 -110
  21. package/package.json +18 -10
  22. package/src/forger/preferences.yaml +8 -1
  23. package/src/knowledge/agentskills-spec.md +2 -0
  24. package/src/knowledge/ccc-bridge.md +40 -24
  25. package/src/knowledge/confidence-tiers.md +9 -5
  26. package/src/knowledge/overview.md +3 -3
  27. package/src/knowledge/progressive-capability.md +8 -8
  28. package/src/knowledge/provenance-tracking.md +9 -5
  29. package/src/knowledge/qmd-registry.md +2 -2
  30. package/src/knowledge/skf-knowledge-index.csv +2 -2
  31. package/src/knowledge/skill-lifecycle.md +18 -11
  32. package/src/knowledge/split-body-strategy.md +0 -3
  33. package/src/knowledge/tool-resolution.md +4 -2
  34. package/src/knowledge/version-paths.md +101 -15
  35. package/src/module-help.csv +3 -3
  36. package/src/module.yaml +10 -0
  37. package/src/shared/data/ast-grep-recipes.yaml +608 -0
  38. package/src/shared/data/ide-context-files.json +30 -0
  39. package/src/shared/health-check.md +32 -12
  40. package/src/shared/references/description-guard-protocol.md +14 -9
  41. package/src/shared/references/feasibility-report-schema.md +19 -13
  42. package/src/shared/references/headless-gate-convention.md +55 -3
  43. package/src/shared/references/output-contract-schema.md +19 -8
  44. package/src/shared/references/pipeline-contracts.md +94 -29
  45. package/src/shared/references/tessl-review.md +77 -0
  46. package/src/shared/scripts/schemas/skf-analyze-result-envelope.v1.json +194 -0
  47. package/src/shared/scripts/schemas/skf-audit-result-envelope.v1.json +192 -0
  48. package/src/shared/scripts/schemas/skf-brief-result-envelope.v1.json +32 -4
  49. package/src/shared/scripts/schemas/skf-campaign-result-envelope.v1.json +174 -0
  50. package/src/shared/scripts/schemas/skf-create-skill-result-envelope.v1.json +284 -0
  51. package/src/shared/scripts/schemas/skf-drop-skill-result-envelope.v1.json +164 -0
  52. package/src/shared/scripts/schemas/skf-export-result-envelope.v1.json +160 -0
  53. package/src/shared/scripts/schemas/skf-quick-skill-result-envelope.v1.json +261 -0
  54. package/src/shared/scripts/schemas/skf-refine-architecture-result-envelope.v1.json +192 -0
  55. package/src/shared/scripts/schemas/skf-rename-skill-result-envelope.v1.json +179 -0
  56. package/src/shared/scripts/schemas/skf-setup-result-envelope.v1.json +27 -11
  57. package/src/shared/scripts/schemas/skf-stack-result-envelope.v1.json +176 -0
  58. package/src/shared/scripts/schemas/skf-test-result-envelope.v1.json +173 -0
  59. package/src/shared/scripts/schemas/skf-update-result-envelope.v1.json +19 -5
  60. package/src/shared/scripts/schemas/skf-verify-stack-result-envelope.v1.json +180 -0
  61. package/src/shared/scripts/schemas/skill-brief.v1.json +34 -0
  62. package/src/shared/scripts/schemas/workspace-detection.v1.json +1 -1
  63. package/src/shared/scripts/skf-atomic-write.py +30 -14
  64. package/src/shared/scripts/skf-build-change-manifest.py +2203 -24
  65. package/src/shared/scripts/skf-ccc-git-hygiene.py +532 -0
  66. package/src/shared/scripts/skf-check-unit-records.py +184 -0
  67. package/src/shared/scripts/skf-check-workspace-drift.py +538 -9
  68. package/src/shared/scripts/skf-classify-changed-files.py +694 -0
  69. package/src/shared/scripts/skf-comention-pairs.py +1333 -123
  70. package/src/shared/scripts/skf-compare-file-hashes.py +1 -1
  71. package/src/shared/scripts/skf-count-imports.py +1867 -0
  72. package/src/shared/scripts/skf-count-tokens.py +1 -1
  73. package/src/shared/scripts/skf-derive-assembly-shape.py +3 -2
  74. package/src/shared/scripts/skf-description-guard.py +117 -9
  75. package/src/shared/scripts/skf-detect-docs.py +892 -4
  76. package/src/shared/scripts/skf-detect-language.py +486 -107
  77. package/src/shared/scripts/skf-detect-registry.py +887 -0
  78. package/src/shared/scripts/skf-detect-scripts-assets.py +1 -1
  79. package/src/shared/scripts/skf-detect-tools.py +215 -27
  80. package/src/shared/scripts/skf-detect-workspaces.py +506 -30
  81. package/src/shared/scripts/skf-disqualify-candidates.py +821 -182
  82. package/src/shared/scripts/skf-emit-brief-result-envelope.py +69 -191
  83. package/src/shared/scripts/skf-emit-result-envelope.py +1604 -106
  84. package/src/shared/scripts/skf-enumerate-stack-skills.py +986 -117
  85. package/src/shared/scripts/skf-extract-public-api.py +4084 -85
  86. package/src/shared/scripts/skf-extraction-inventory.py +746 -0
  87. package/src/shared/scripts/skf-extraction-snapshot.py +539 -0
  88. package/src/shared/scripts/skf-fetch-temporal.py +674 -0
  89. package/src/shared/scripts/skf-find-cycles.py +97 -29
  90. package/src/shared/scripts/skf-find-test-report.py +476 -0
  91. package/src/shared/scripts/skf-forge-tier-rw.py +444 -203
  92. package/src/shared/scripts/skf-github-fetch.py +365 -0
  93. package/src/shared/scripts/skf-github-probe.py +661 -0
  94. package/src/shared/scripts/skf-hash-content.py +166 -12
  95. package/src/shared/scripts/skf-language-corpora.py +1 -1
  96. package/src/shared/scripts/skf-load-provenance.py +159 -27
  97. package/src/shared/scripts/skf-manifest-ops.py +1 -1
  98. package/src/shared/scripts/skf-merge-ccc-exclusions.py +2307 -223
  99. package/src/shared/scripts/skf-merge-doc-urls.py +1 -1
  100. package/src/shared/scripts/skf-names-present.py +221 -0
  101. package/src/shared/scripts/skf-pair-intersect.py +119 -28
  102. package/src/shared/scripts/skf-parse-gaps.py +1384 -0
  103. package/src/shared/scripts/skf-preapply.py +1 -1
  104. package/src/shared/scripts/skf-preflight.py +161 -27
  105. package/src/shared/scripts/skf-promote-staged.py +430 -0
  106. package/src/shared/scripts/skf-provenance-gap-dispatch.py +39 -7
  107. package/src/shared/scripts/skf-qmd-classify-collections.py +229 -45
  108. package/src/shared/scripts/skf-quick-batch.py +774 -0
  109. package/src/shared/scripts/skf-rebuild-managed-sections.py +972 -88
  110. package/src/shared/scripts/skf-recommend-scope-type.py +323 -156
  111. package/src/shared/scripts/skf-render-metadata-stats.py +156 -12
  112. package/src/shared/scripts/skf-render-quick-metadata.py +132 -28
  113. package/src/shared/scripts/skf-render-stack-metadata.py +976 -0
  114. package/src/shared/scripts/skf-resolve-authoritative-files.py +128 -13
  115. package/src/shared/scripts/skf-resolve-package.py +523 -106
  116. package/src/shared/scripts/skf-rewrite-skill-name.py +433 -47
  117. package/src/shared/scripts/skf-run-lock.py +577 -0
  118. package/src/shared/scripts/skf-scan-manifests.py +998 -57
  119. package/src/shared/scripts/skf-scan-skill-md-structure.py +1341 -37
  120. package/src/shared/scripts/skf-severity-classify.py +712 -108
  121. package/src/shared/scripts/skf-shape-detect.py +298 -204
  122. package/src/shared/scripts/skf-shard-body.py +9 -8
  123. package/src/shared/scripts/skf-skill-inventory.py +2412 -89
  124. package/src/shared/scripts/skf-skills-module.py +472 -0
  125. package/src/shared/scripts/skf-source-tree.py +1796 -0
  126. package/src/shared/scripts/skf-structural-diff.py +670 -119
  127. package/src/shared/scripts/skf-tessl-review.py +706 -0
  128. package/src/shared/scripts/skf-update-active-symlink.py +5 -5
  129. package/src/shared/scripts/skf-update-run-state.py +624 -0
  130. package/src/shared/scripts/skf-validate-brief-inputs.py +92 -29
  131. package/src/shared/scripts/skf-validate-brief-schema.py +4 -1
  132. package/src/shared/scripts/skf-validate-feasibility-report.py +577 -66
  133. package/src/shared/scripts/skf-validate-frontmatter.py +103 -26
  134. package/src/shared/scripts/skf-validate-output.py +712 -64
  135. package/src/shared/scripts/skf-validate-pins.py +1 -1
  136. package/src/shared/scripts/skf-verify-no-trace.py +116 -10
  137. package/src/shared/scripts/skf-verify-provenance-completeness.py +2919 -54
  138. package/src/shared/scripts/skf-write-skill-brief.py +367 -19
  139. package/src/shared/tool-requirements.yaml +201 -0
  140. package/src/skf-analyze-source/SKILL.md +41 -36
  141. package/src/skf-analyze-source/assets/skill-brief-schema.md +7 -8
  142. package/src/skf-analyze-source/customize.toml +36 -24
  143. package/src/skf-analyze-source/references/auto-docs-only.md +58 -20
  144. package/src/skf-analyze-source/references/continue.md +2 -13
  145. package/src/skf-analyze-source/references/discover-additional-source.md +147 -0
  146. package/src/skf-analyze-source/references/generate-briefs.md +121 -55
  147. package/src/skf-analyze-source/references/headless-contract.md +42 -15
  148. package/src/skf-analyze-source/references/identify-units.md +96 -110
  149. package/src/skf-analyze-source/references/init.md +73 -71
  150. package/src/skf-analyze-source/references/map-and-detect.md +123 -105
  151. package/src/skf-analyze-source/references/map-unit-exports.md +68 -0
  152. package/src/skf-analyze-source/references/recommend.md +51 -70
  153. package/src/skf-analyze-source/references/scan-project.md +60 -84
  154. package/src/skf-analyze-source/references/scan-root.md +39 -0
  155. package/src/skf-analyze-source/references/step-auto-scope-coexistence.md +47 -0
  156. package/src/skf-analyze-source/references/step-auto-scope-corpora.md +53 -0
  157. package/src/skf-analyze-source/references/step-auto-scope-split.md +91 -0
  158. package/src/skf-analyze-source/references/step-auto-scope.md +208 -293
  159. package/src/skf-analyze-source/references/step-shape-detect.md +14 -12
  160. package/src/skf-analyze-source/references/unit-detection-heuristics.md +37 -42
  161. package/src/skf-audit-skill/SKILL.md +43 -51
  162. package/src/skf-audit-skill/assets/drift-report-template.md +27 -3
  163. package/src/skf-audit-skill/customize.toml +41 -20
  164. package/src/skf-audit-skill/references/constituent-freshness.md +91 -0
  165. package/src/skf-audit-skill/references/doc-drift.md +141 -0
  166. package/src/skf-audit-skill/references/headless-contract.md +29 -0
  167. package/src/skf-audit-skill/references/init.md +148 -210
  168. package/src/skf-audit-skill/references/re-index.md +96 -108
  169. package/src/skf-audit-skill/references/report.md +96 -33
  170. package/src/skf-audit-skill/references/semantic-diff.md +27 -18
  171. package/src/skf-audit-skill/references/severity-classify.md +79 -65
  172. package/src/skf-audit-skill/references/severity-rules.md +15 -6
  173. package/src/skf-audit-skill/references/structural-diff.md +75 -90
  174. package/src/skf-audit-skill/references/upstream-checkout.md +77 -0
  175. package/src/skf-audit-skill/scripts/render-drift-tables.py +685 -0
  176. package/src/skf-brief-skill/SKILL.md +36 -25
  177. package/src/skf-brief-skill/assets/description-voice-examples.md +1 -1
  178. package/src/skf-brief-skill/assets/scope-templates.md +17 -24
  179. package/src/skf-brief-skill/assets/skill-brief-schema.md +29 -15
  180. package/src/skf-brief-skill/customize.toml +48 -20
  181. package/src/skf-brief-skill/references/analyze-target.md +142 -125
  182. package/src/skf-brief-skill/references/confirm-brief.md +10 -8
  183. package/src/skf-brief-skill/references/draft-checkpoint.md +36 -17
  184. package/src/skf-brief-skill/references/gather-intent-ratify.md +68 -0
  185. package/src/skf-brief-skill/references/gather-intent.md +87 -182
  186. package/src/skf-brief-skill/references/headless-args.md +84 -16
  187. package/src/skf-brief-skill/references/health-check.md +1 -1
  188. package/src/skf-brief-skill/references/invocation-contract.md +18 -13
  189. package/src/skf-brief-skill/references/portfolio-similarity-check.md +1 -1
  190. package/src/skf-brief-skill/references/qmd-collection-registration.md +7 -10
  191. package/src/skf-brief-skill/references/scope-definition.md +123 -47
  192. package/src/skf-brief-skill/references/step-auto-brief.md +24 -80
  193. package/src/skf-brief-skill/references/step-auto-validate.md +20 -121
  194. package/src/skf-brief-skill/references/version-resolution.md +3 -2
  195. package/src/skf-brief-skill/references/write-brief.md +66 -57
  196. package/src/skf-campaign/SKILL.md +31 -34
  197. package/src/skf-campaign/assets/campaign-state-schema.json +25 -4
  198. package/src/skf-campaign/customize.toml +47 -16
  199. package/src/skf-campaign/references/campaign-contracts.md +39 -29
  200. package/src/skf-campaign/references/campaign-directive-spec.md +4 -2
  201. package/src/skf-campaign/references/health-check.md +7 -16
  202. package/src/skf-campaign/references/step-01-setup.md +46 -84
  203. package/src/skf-campaign/references/step-02-strategy.md +31 -30
  204. package/src/skf-campaign/references/step-03-pins.md +26 -18
  205. package/src/skf-campaign/references/step-04-provenance.md +24 -23
  206. package/src/skf-campaign/references/step-05-skill-loop.md +67 -48
  207. package/src/skf-campaign/references/step-06-batch.md +41 -34
  208. package/src/skf-campaign/references/step-07-capstone.md +40 -25
  209. package/src/skf-campaign/references/step-08-verify.md +28 -29
  210. package/src/skf-campaign/references/step-09-refine.md +29 -30
  211. package/src/skf-campaign/references/step-10-export.md +48 -36
  212. package/src/skf-campaign/references/step-11-maintenance.md +31 -34
  213. package/src/skf-campaign/references/step-resume.md +37 -68
  214. package/src/skf-campaign/scripts/campaign-deps.py +57 -18
  215. package/src/skf-campaign/scripts/campaign-parse-manifest.py +361 -54
  216. package/src/skf-campaign/scripts/campaign-provenance.py +96 -53
  217. package/src/skf-campaign/scripts/campaign-quality-gate.py +592 -0
  218. package/src/skf-campaign/scripts/campaign-render-batch.py +257 -49
  219. package/src/skf-campaign/scripts/campaign-render-kickoff.py +343 -50
  220. package/src/skf-campaign/scripts/campaign-report.py +204 -37
  221. package/src/skf-campaign/scripts/campaign-state.py +1128 -0
  222. package/src/skf-campaign/scripts/campaign-status.py +10 -74
  223. package/src/skf-campaign/scripts/campaign-validate-pins.py +30 -3
  224. package/src/skf-campaign/scripts/campaign-validate-state.py +34 -4
  225. package/src/skf-campaign/templates/campaign-brief-template.yaml +4 -5
  226. package/src/skf-campaign/templates/campaign-report-template.md +5 -1
  227. package/src/skf-campaign/templates/kickoff-template.md +0 -14
  228. package/src/skf-create-skill/SKILL.md +27 -20
  229. package/src/skf-create-skill/assets/compile-assembly-rules.md +6 -5
  230. package/src/skf-create-skill/assets/skill-sections.md +17 -6
  231. package/src/skf-create-skill/customize.toml +20 -8
  232. package/src/skf-create-skill/references/authoritative-files-protocol.md +41 -42
  233. package/src/skf-create-skill/references/batch-mode.md +81 -0
  234. package/src/skf-create-skill/references/ccc-index-check.md +27 -0
  235. package/src/skf-create-skill/references/compile.md +107 -29
  236. package/src/skf-create-skill/references/component-extraction.md +113 -91
  237. package/src/skf-create-skill/references/enrich.md +41 -23
  238. package/src/skf-create-skill/references/entry-points-by-hand.md +20 -0
  239. package/src/skf-create-skill/references/extract.md +200 -161
  240. package/src/skf-create-skill/references/extraction-patterns-by-hand.md +141 -0
  241. package/src/skf-create-skill/references/extraction-patterns-tracing.md +2 -2
  242. package/src/skf-create-skill/references/extraction-patterns.md +584 -196
  243. package/src/skf-create-skill/references/generate-artifacts.md +145 -93
  244. package/src/skf-create-skill/references/health-check.md +1 -1
  245. package/src/skf-create-skill/references/load-brief.md +53 -36
  246. package/src/skf-create-skill/references/relabel-rule.md +12 -0
  247. package/src/skf-create-skill/references/report.md +28 -59
  248. package/src/skf-create-skill/references/source-resolution-protocols.md +49 -155
  249. package/src/skf-create-skill/references/step-auto-shard.md +20 -93
  250. package/src/skf-create-skill/references/step-doc-rot.md +44 -60
  251. package/src/skf-create-skill/references/step-doc-sources.md +55 -18
  252. package/src/skf-create-skill/references/sub/ccc-discover.md +18 -7
  253. package/src/skf-create-skill/references/sub/fetch-docs.md +106 -57
  254. package/src/skf-create-skill/references/sub/fetch-temporal.md +53 -166
  255. package/src/skf-create-skill/references/tier-degradation-rules.md +18 -9
  256. package/src/skf-create-skill/references/validate.md +173 -99
  257. package/src/skf-create-skill/scripts/scan-doc-rot.py +232 -99
  258. package/src/skf-create-stack-skill/SKILL.md +29 -56
  259. package/src/skf-create-stack-skill/assets/metadata-contract.md +51 -0
  260. package/src/skf-create-stack-skill/assets/provenance-map-schema.md +15 -15
  261. package/src/skf-create-stack-skill/assets/stack-skill-template.md +23 -57
  262. package/src/skf-create-stack-skill/customize.toml +23 -12
  263. package/src/skf-create-stack-skill/references/compile-stack.md +57 -66
  264. package/src/skf-create-stack-skill/references/compose-mode-rules.md +24 -44
  265. package/src/skf-create-stack-skill/references/detect-integrations.md +92 -95
  266. package/src/skf-create-stack-skill/references/detect-manifests.md +46 -71
  267. package/src/skf-create-stack-skill/references/generate-output.md +138 -128
  268. package/src/skf-create-stack-skill/references/init.md +90 -32
  269. package/src/skf-create-stack-skill/references/integration-patterns.md +1 -17
  270. package/src/skf-create-stack-skill/references/invocation-contract.md +34 -0
  271. package/src/skf-create-stack-skill/references/manifest-patterns.md +32 -20
  272. package/src/skf-create-stack-skill/references/parallel-extract.md +112 -38
  273. package/src/skf-create-stack-skill/references/rank-and-confirm.md +57 -75
  274. package/src/skf-create-stack-skill/references/report.md +39 -33
  275. package/src/skf-create-stack-skill/references/validate.md +20 -39
  276. package/src/skf-drop-skill/SKILL.md +28 -51
  277. package/src/skf-drop-skill/customize.toml +44 -30
  278. package/src/skf-drop-skill/references/execute.md +79 -146
  279. package/src/skf-drop-skill/references/invocation-contract.md +64 -0
  280. package/src/skf-drop-skill/references/report.md +46 -30
  281. package/src/skf-drop-skill/references/select.md +118 -124
  282. package/src/skf-drop-skill/scripts/dir-sizes.py +54 -26
  283. package/src/skf-drop-skill/scripts/drop-roster.py +322 -0
  284. package/src/skf-export-skill/SKILL.md +40 -62
  285. package/src/skf-export-skill/assets/managed-section-format.md +14 -50
  286. package/src/skf-export-skill/assets/snippet-format.md +3 -1
  287. package/src/skf-export-skill/customize.toml +42 -13
  288. package/src/skf-export-skill/references/generate-snippet.md +54 -46
  289. package/src/skf-export-skill/references/health-check.md +2 -0
  290. package/src/skf-export-skill/references/invocation-contract.md +15 -0
  291. package/src/skf-export-skill/references/load-skill.md +88 -62
  292. package/src/skf-export-skill/references/manifest-rebuild.md +9 -10
  293. package/src/skf-export-skill/references/multi-skill-mode.md +4 -4
  294. package/src/skf-export-skill/references/orphan-context-detection.md +13 -5
  295. package/src/skf-export-skill/references/orphan-row-detection.md +31 -22
  296. package/src/skf-export-skill/references/package.md +15 -73
  297. package/src/skf-export-skill/references/preflight-snippet-root-probe.md +51 -70
  298. package/src/skf-export-skill/references/result-envelope.md +31 -16
  299. package/src/skf-export-skill/references/summary.md +41 -17
  300. package/src/skf-export-skill/references/token-report.md +4 -12
  301. package/src/skf-export-skill/references/update-context.md +118 -237
  302. package/src/skf-forger/SKILL.md +61 -37
  303. package/src/skf-forger/bmad-skill-manifest.yaml +4 -1
  304. package/src/skf-forger/customize.toml +43 -0
  305. package/src/skf-forger/references/pipeline-mode.md +73 -18
  306. package/src/skf-forger/scripts/forge-status.py +299 -0
  307. package/src/skf-forger/scripts/parse-pipeline.py +322 -54
  308. package/src/skf-forger/scripts/pipeline-gate.py +428 -0
  309. package/src/skf-forger/scripts/pipeline-journal.py +1052 -0
  310. package/src/skf-quick-skill/SKILL.md +54 -53
  311. package/src/skf-quick-skill/assets/skill-template.md +4 -2
  312. package/src/skf-quick-skill/customize.toml +51 -20
  313. package/src/skf-quick-skill/references/batch-mode.md +74 -21
  314. package/src/skf-quick-skill/references/compile.md +30 -31
  315. package/src/skf-quick-skill/references/ecosystem-check.md +7 -57
  316. package/src/skf-quick-skill/references/finalize.md +69 -18
  317. package/src/skf-quick-skill/references/halt-contract.md +41 -29
  318. package/src/skf-quick-skill/references/health-check.md +5 -3
  319. package/src/skf-quick-skill/references/quick-extract.md +114 -45
  320. package/src/skf-quick-skill/references/registry-resolution.md +9 -64
  321. package/src/skf-quick-skill/references/resolve-target.md +116 -66
  322. package/src/skf-quick-skill/references/write-and-validate.md +79 -40
  323. package/src/skf-refine-architecture/SKILL.md +43 -53
  324. package/src/skf-refine-architecture/customize.toml +49 -20
  325. package/src/skf-refine-architecture/references/compile.md +97 -54
  326. package/src/skf-refine-architecture/references/exit-codes.md +30 -0
  327. package/src/skf-refine-architecture/references/finding-storage.md +21 -0
  328. package/src/skf-refine-architecture/references/gap-analysis.md +101 -38
  329. package/src/skf-refine-architecture/references/improvements.md +14 -20
  330. package/src/skf-refine-architecture/references/init.md +98 -57
  331. package/src/skf-refine-architecture/references/issue-detection.md +32 -39
  332. package/src/skf-refine-architecture/references/refinement-rules.md +37 -48
  333. package/src/skf-refine-architecture/references/report.md +65 -54
  334. package/src/skf-refine-architecture/scripts/skf-check-preservation.py +1619 -0
  335. package/src/skf-rename-skill/SKILL.md +19 -54
  336. package/src/skf-rename-skill/customize.toml +32 -26
  337. package/src/skf-rename-skill/references/execute.md +230 -184
  338. package/src/skf-rename-skill/references/exit-codes.md +7 -7
  339. package/src/skf-rename-skill/references/health-check.md +1 -7
  340. package/src/skf-rename-skill/references/invocation-contract.md +25 -0
  341. package/src/skf-rename-skill/references/report.md +63 -52
  342. package/src/skf-rename-skill/references/select.md +197 -115
  343. package/src/skf-rename-skill/scripts/skf-validate-rename-name.py +161 -21
  344. package/src/skf-setup/SKILL.md +26 -26
  345. package/src/skf-setup/customize.toml +14 -10
  346. package/src/skf-setup/references/auto-index.md +50 -63
  347. package/src/skf-setup/references/ccc-index.md +29 -89
  348. package/src/skf-setup/references/detect-and-tier.md +58 -66
  349. package/src/skf-setup/references/health-check.md +2 -0
  350. package/src/skf-setup/references/invocation-contract.md +14 -0
  351. package/src/skf-setup/references/report.md +43 -166
  352. package/src/skf-setup/references/tier-rules.md +5 -5
  353. package/src/skf-setup/references/write-config.md +34 -57
  354. package/src/skf-test-skill/SKILL.md +17 -57
  355. package/src/skf-test-skill/assets/output-section-formats.md +33 -34
  356. package/src/skf-test-skill/customize.toml +27 -13
  357. package/src/skf-test-skill/references/coherence-check.md +134 -62
  358. package/src/skf-test-skill/references/coverage-check-tiers.md +35 -0
  359. package/src/skf-test-skill/references/coverage-check.md +217 -254
  360. package/src/skf-test-skill/references/detect-mode.md +5 -5
  361. package/src/skf-test-skill/references/external-validators.md +94 -82
  362. package/src/skf-test-skill/references/health-check.md +6 -7
  363. package/src/skf-test-skill/references/init.md +163 -88
  364. package/src/skf-test-skill/references/invocation-contract.md +66 -0
  365. package/src/skf-test-skill/references/migration-section-rules.md +5 -2
  366. package/src/skf-test-skill/references/report.md +162 -142
  367. package/src/skf-test-skill/references/score.md +80 -107
  368. package/src/skf-test-skill/references/scoring-rules.md +41 -155
  369. package/src/skf-test-skill/references/source-access-protocol.md +19 -92
  370. package/src/skf-test-skill/references/step-hard-gate.md +51 -33
  371. package/src/skf-test-skill/scripts/aggregate-coherence.py +218 -30
  372. package/src/skf-test-skill/scripts/build-result-context.py +287 -0
  373. package/src/skf-test-skill/scripts/check-metadata-coherence.py +37 -4
  374. package/src/skf-test-skill/scripts/combine-external-scores.py +23 -6
  375. package/src/skf-test-skill/scripts/compute-score.py +223 -45
  376. package/src/skf-test-skill/scripts/gap-ledger.py +1381 -0
  377. package/src/skf-test-skill/scripts/hard-gate.py +203 -0
  378. package/src/skf-test-skill/scripts/load-coverage-inputs.py +760 -0
  379. package/src/skf-test-skill/scripts/locate-export-segments.py +835 -0
  380. package/src/skf-test-skill/scripts/reconcile-coverage.py +273 -79
  381. package/src/skf-test-skill/scripts/score-signatures.py +459 -0
  382. package/src/skf-test-skill/scripts/stage-helper-payload.py +148 -0
  383. package/src/skf-test-skill/scripts/validate-inventory.py +311 -16
  384. package/src/skf-test-skill/scripts/verify-declared-numerator.py +127 -52
  385. package/src/skf-test-skill/templates/test-report-template.md +21 -15
  386. package/src/skf-update-skill/SKILL.md +38 -25
  387. package/src/skf-update-skill/customize.toml +27 -12
  388. package/src/skf-update-skill/references/detect-changes.md +233 -222
  389. package/src/skf-update-skill/references/gap-driven.md +336 -0
  390. package/src/skf-update-skill/references/health-check.md +31 -5
  391. package/src/skf-update-skill/references/init.md +250 -84
  392. package/src/skf-update-skill/references/invocation-contract.md +12 -0
  393. package/src/skf-update-skill/references/manual-section-rules.md +6 -23
  394. package/src/skf-update-skill/references/merge.md +180 -47
  395. package/src/skf-update-skill/references/re-extract.md +53 -262
  396. package/src/skf-update-skill/references/report.md +100 -35
  397. package/src/skf-update-skill/references/write.md +331 -149
  398. package/src/skf-update-skill/scripts/skf-new-file-diff.py +29 -7
  399. package/src/skf-verify-stack/SKILL.md +23 -42
  400. package/src/skf-verify-stack/assets/feasibility-report-template.md +11 -5
  401. package/src/skf-verify-stack/customize.toml +55 -22
  402. package/src/skf-verify-stack/references/coverage-patterns.md +17 -8
  403. package/src/skf-verify-stack/references/coverage.md +67 -64
  404. package/src/skf-verify-stack/references/exit-codes.md +21 -8
  405. package/src/skf-verify-stack/references/init.md +107 -62
  406. package/src/skf-verify-stack/references/integration-verification-rules.md +12 -13
  407. package/src/skf-verify-stack/references/integrations.md +106 -65
  408. package/src/skf-verify-stack/references/report.md +59 -42
  409. package/src/skf-verify-stack/references/requirements.md +32 -9
  410. package/src/skf-verify-stack/references/synthesize.md +53 -39
  411. package/src/skf-verify-stack/scripts/skf-coverage-tally.py +398 -52
  412. package/src/skf-verify-stack/scripts/skf-previous-report.py +330 -0
  413. package/src/skf-verify-stack/scripts/skf-report-delta.py +453 -49
  414. package/src/skf-verify-stack/scripts/skf-verdict-rollup.py +240 -27
  415. package/tools/cli/commands/install.js +11 -4
  416. package/tools/cli/commands/status.js +15 -3
  417. package/tools/cli/commands/update.js +11 -4
  418. package/tools/cli/lib/tool-check.js +320 -0
  419. package/tools/cli/lib/version-check.js +22 -9
  420. package/tools/cli/skf-cli.js +4 -1
  421. package/.gitattributes +0 -16
  422. package/.nvmrc +0 -1
  423. package/docs/_internal/RELEASING.md +0 -645
  424. package/release-audits/v1.0.0-launch-audit.md +0 -728
  425. package/src/skf-audit-skill/references/step-doc-drift.md +0 -177
  426. package/src/skf-brief-skill/references/headless-source-authority-detection.md +0 -26
  427. package/src/skf-campaign/manifest.yaml +0 -15
  428. package/src/skf-create-skill/assets/tessl-dismissal-rules.md +0 -106
  429. package/src/skf-create-skill/references/ecosystem-check.md +0 -74
  430. package/src/skf-drop-skill/references/headless-contract.md +0 -18
  431. package/src/skf-update-skill/references/merge-conflict-rules.md +0 -15
  432. package/src/skf-update-skill/references/remote-source-resolution.md +0 -98
  433. package/src/skf-update-skill/references/validate.md +0 -124
  434. package/tools/validate-docs-drift.js +0 -233
  435. package/tools/validate-docs-links.js +0 -665
@@ -1,16 +1,45 @@
1
1
  # /// script
2
- # requires-python = ">=3.9"
2
+ # requires-python = ">=3.11"
3
3
  # dependencies = ["pyyaml"]
4
4
  # ///
5
- """Campaign Report — generate a markdown report from campaign state + template.
5
+ """Campaign Report: generate a markdown report from campaign state + template.
6
6
 
7
7
  CLI:
8
8
  uv run campaign-report.py \
9
- --state-file <path> --template-file <path> --output-file <path>
9
+ --state-file <path> --template-file <path> --output-file <path> \
10
+ [--context-file <path> [--decision-log <path>]]
10
11
 
11
12
  Output (JSON on stdout):
12
13
  {"status":"success","report_path":"...","skills_completed":N,"skills_failed":N,
13
- "quality_scores":{"skill":score,...},"duration":"..."}
14
+ "quality_scores":{"skill":score,...},"duration":"...",
15
+ "export_verdicts":{"skill":"pass|fallback|fail",...},"skills_excluded":["skill",...],
16
+ "skills_exported":["skill",...],
17
+ "export_failures":[{"skill","halt_reason","exit_code"},...]}
18
+
19
+ `export_verdicts` holds each completed skill's quality-gate verdict at Export
20
+ and `skills_excluded` the completed skills the gate kept from export, both
21
+ from campaign-quality-gate.py classify (the rule step-10 applies, the state's
22
+ directive included), so a headless caller sees which completed skills were
23
+ not exported. Both are null when the gate cannot be applied (an invalid gate
24
+ or an unreadable directive), and the report says so.
25
+
26
+ `skills_exported` and `export_failures` are what Export did: the `export`
27
+ outcome campaign-state.py recorded for each skill after its skf-export-skill
28
+ call, an exported skill by name and a failed one with that call's
29
+ halt_reason and exit code. Both are null when the Export stage did not run
30
+ (`campaign.current_stage` below 9). The report's Export Gate table shows the
31
+ same outcome per skill in its Export column.
32
+
33
+ --context-file also writes the payload skf-emit-result-envelope.py turns into
34
+ the campaign's SKF_CAMPAIGN_RESULT_JSON line (schemas/
35
+ skf-campaign-result-envelope.v1.json): the result above, with the report as
36
+ `campaign_report_path` and --decision-log as `decision_log`. When the report
37
+ cannot be written it still writes one, the degraded finish: `status` error,
38
+ `halt_reason` report-failure, no report path, and the counts and scores the
39
+ state gives (none when it cannot be read). So step 11 stages nothing by hand
40
+ on either path. It first removes the payload an earlier run left, so a
41
+ payload that cannot be written leaves no file and step 11 takes its fallback
42
+ instead of an earlier run's envelope.
14
43
 
15
44
  Exit codes:
16
45
  0 success
@@ -20,6 +49,8 @@ Exit codes:
20
49
  from __future__ import annotations
21
50
 
22
51
  import argparse
52
+ import contextlib
53
+ import importlib.util
23
54
  import json
24
55
  import os
25
56
  import sys
@@ -29,6 +60,8 @@ from typing import Any, Dict, List, Optional
29
60
 
30
61
  import yaml
31
62
 
63
+ GATE_SCRIPT = Path(__file__).resolve().with_name("campaign-quality-gate.py")
64
+
32
65
 
33
66
  def _emit_error(message: str, code: str) -> None:
34
67
  json.dump({"error": message, "code": code}, sys.stderr)
@@ -65,7 +98,81 @@ def _format_duration(start: Optional[datetime], end: Optional[datetime]) -> str:
65
98
  return f"{seconds}s"
66
99
 
67
100
 
68
- def _compute_aggregates(state: Dict[str, Any]) -> Dict[str, Any]:
101
+ def _export_classification(state: Dict[str, Any]) -> Optional[Dict[str, Any]]:
102
+ """campaign-quality-gate.py classify for the state, or None when the gate cannot be applied."""
103
+ spec = importlib.util.spec_from_file_location("campaign_quality_gate", GATE_SCRIPT)
104
+ gate = importlib.util.module_from_spec(spec)
105
+ spec.loader.exec_module(gate)
106
+ campaign = state.get("campaign") or {}
107
+ try:
108
+ return gate.classify(state, gate.read_directive(campaign.get("directive_path")))
109
+ except (gate.GateError, KeyError, TypeError, AttributeError):
110
+ return None
111
+
112
+
113
+ def _export_record(skill: Any) -> Optional[Dict[str, Any]]:
114
+ """The `export` outcome campaign-state.py recorded for a skill, or None."""
115
+ record = skill.get("export") if isinstance(skill, dict) else None
116
+ return record if isinstance(record, dict) and record.get("status") in ("exported", "failed") else None
117
+
118
+
119
+ def _export_cell(record: Optional[Dict[str, Any]], verdict: str) -> str:
120
+ if record is None:
121
+ return "not exported" if verdict == "fail" else "N/A"
122
+ if record["status"] == "exported":
123
+ return "exported"
124
+ why = record.get("halt_reason") or (
125
+ f"exit {record['exit_code']}" if record.get("exit_code") is not None else "no exit code")
126
+ return f"failed ({why})"
127
+
128
+
129
+ def _export_outcomes(state: Any) -> Dict[str, Any]:
130
+ """What Export did, from each skill's recorded `export`; both null before stage 9 ran."""
131
+ campaign = state.get("campaign") if isinstance(state, dict) else None
132
+ stage = campaign.get("current_stage") if isinstance(campaign, dict) else None
133
+ if not isinstance(stage, int) or isinstance(stage, bool) or stage < 9:
134
+ return {"skills_exported": None, "export_failures": None}
135
+ skills = state.get("skills")
136
+ exported, failures = [], []
137
+ for skill in skills if isinstance(skills, list) else []:
138
+ record = _export_record(skill)
139
+ if record is None or not skill.get("name"):
140
+ continue
141
+ if record["status"] == "exported":
142
+ exported.append(skill["name"])
143
+ else:
144
+ failures.append({"skill": skill["name"], "halt_reason": record.get("halt_reason"),
145
+ "exit_code": record.get("exit_code")})
146
+ return {"skills_exported": exported, "export_failures": failures}
147
+
148
+
149
+ def _export_gate_section(
150
+ classification: Optional[Dict[str, Any]], state: Optional[Dict[str, Any]] = None
151
+ ) -> str:
152
+ if classification is None:
153
+ return "The quality gate could not be applied to the completed skills (see the decision log)."
154
+ rows = classification["skills"]
155
+ if not rows:
156
+ return "No completed skills."
157
+ records = {s.get("name"): _export_record(s) for s in (state or {}).get("skills") or [] if isinstance(s, dict)}
158
+ lines = ["| Skill | Quality Score | Gate | Export |", "|-------|---------------|------|--------|"]
159
+ for row in rows:
160
+ score = row["quality_score"] if row["quality_score"] is not None else "N/A"
161
+ export = _export_cell(records.get(row["name"]), row["verdict"])
162
+ lines.append(f"| {row['name']} | {score} | {row['verdict']} | {export} |")
163
+ excluded = classification["excluded"]
164
+ if excluded:
165
+ listed = ", ".join(
166
+ f"{e['name']} ({e['quality_score'] if e['quality_score'] is not None else 'N/A'}: {e['reason']})"
167
+ for e in excluded
168
+ )
169
+ lines += ["", f"**Not exported (below the quality gate):** {listed}"]
170
+ return "\n".join(lines)
171
+
172
+
173
+ def _compute_aggregates(
174
+ state: Dict[str, Any], classification: Optional[Dict[str, Any]] = None
175
+ ) -> Dict[str, Any]:
69
176
  campaign = state.get("campaign", {})
70
177
  skills: List[Dict[str, Any]] = state.get("skills", [])
71
178
 
@@ -141,6 +248,8 @@ def _compute_aggregates(state: Dict[str, Any]) -> Dict[str, Any]:
141
248
  failed_skipped_lines.append("No skills in campaign.")
142
249
 
143
250
  quality_gate = campaign.get("quality_gate", {})
251
+ if classification is None:
252
+ classification = _export_classification(state)
144
253
 
145
254
  return {
146
255
  "campaign_name": campaign.get("name", ""),
@@ -163,72 +272,125 @@ def _compute_aggregates(state: Dict[str, Any]) -> Dict[str, Any]:
163
272
  "workarounds_list": "\n".join(workarounds_list_items),
164
273
  "duration_table": "\n".join(duration_table_rows),
165
274
  "failed_skipped_section": "\n".join(failed_skipped_lines),
275
+ "export_gate_section": _export_gate_section(classification, state),
166
276
  }
167
277
 
168
278
 
169
- def run(state_file: str, template_file: str, output_file: str) -> int:
279
+ def _counts(state: Any) -> Dict[str, Any]:
280
+ """The completed and failed counts and the completed skills' scores."""
281
+ skills = state.get("skills", []) if isinstance(state, dict) else []
282
+ skills = [s for s in skills if isinstance(s, dict)] if isinstance(skills, list) else []
283
+ return {
284
+ "skills_completed": sum(1 for s in skills if s.get("status") == "completed"),
285
+ "skills_failed": sum(1 for s in skills if s.get("status") == "failed"),
286
+ "quality_scores": {
287
+ s["name"]: s["quality_score"]
288
+ for s in skills
289
+ if s.get("status") == "completed" and s.get("quality_score") is not None and s.get("name")
290
+ },
291
+ }
292
+
293
+
294
+ def _write_context(path: Optional[str], payload: Dict[str, Any]) -> None:
295
+ """Write the emitter payload; a failed write leaves step 11 its fallback."""
296
+ if not path:
297
+ return
298
+ try:
299
+ Path(path).parent.mkdir(parents=True, exist_ok=True)
300
+ Path(path).write_text(json.dumps(payload, indent=2) + "\n", encoding="utf-8")
301
+ except OSError as exc:
302
+ _emit_error(f"Failed to write the envelope context: {exc}", "CONTEXT_WRITE_ERROR")
303
+
304
+
305
+ def run(
306
+ state_file: str,
307
+ template_file: str,
308
+ output_file: str,
309
+ context_file: Optional[str] = None,
310
+ decision_log: Optional[str] = None,
311
+ ) -> int:
170
312
  state_path = Path(state_file)
171
313
  template_path = Path(template_file)
172
314
  output_path = Path(output_file)
173
-
174
- if not state_path.is_file():
175
- _emit_error(f"State file not found: {state_file}", "STATE_NOT_FOUND")
315
+ state: Any = None
316
+ if context_file:
317
+ with contextlib.suppress(OSError):
318
+ Path(context_file).unlink(missing_ok=True)
319
+
320
+ def fail(message: str, code: str) -> int:
321
+ _emit_error(message, code)
322
+ _write_context(context_file, {
323
+ "status": "error",
324
+ "halt_reason": "report-failure",
325
+ **_counts(state),
326
+ **_export_outcomes(state),
327
+ "campaign_report_path": None,
328
+ "decision_log": decision_log,
329
+ })
176
330
  return 2
177
331
 
178
- if not template_path.is_file():
179
- _emit_error(f"Template file not found: {template_file}", "TEMPLATE_NOT_FOUND")
180
- return 2
332
+ if not state_path.is_file():
333
+ return fail(f"State file not found: {state_file}", "STATE_NOT_FOUND")
181
334
 
182
335
  try:
183
336
  state = _load_yaml(state_path)
184
337
  except Exception as exc:
185
- _emit_error(f"Failed to parse state file: {exc}", "STATE_PARSE_ERROR")
186
- return 2
338
+ return fail(f"Failed to parse state file: {exc}", "STATE_PARSE_ERROR")
187
339
 
188
340
  if not isinstance(state, dict):
189
- _emit_error("State file root is not a mapping", "INVALID_STATE")
190
- return 2
341
+ return fail("State file root is not a mapping", "INVALID_STATE")
342
+
343
+ # Read after the state, so a degraded payload still carries its counts.
344
+ if not template_path.is_file():
345
+ return fail(f"Template file not found: {template_file}", "TEMPLATE_NOT_FOUND")
191
346
 
192
347
  try:
193
348
  template = template_path.read_text(encoding="utf-8")
194
349
  except Exception as exc:
195
- _emit_error(f"Failed to read template file: {exc}", "TEMPLATE_READ_ERROR")
196
- return 2
350
+ return fail(f"Failed to read template file: {exc}", "TEMPLATE_READ_ERROR")
197
351
 
198
352
  try:
199
- aggregates = _compute_aggregates(state)
353
+ classification = _export_classification(state)
354
+ aggregates = _compute_aggregates(state, classification)
200
355
  except Exception as exc:
201
- _emit_error(f"Failed to compute report aggregates: {exc}", "AGGREGATE_ERROR")
202
- return 2
356
+ return fail(f"Failed to compute report aggregates: {exc}", "AGGREGATE_ERROR")
203
357
 
204
358
  report = template
205
359
  for key, value in aggregates.items():
206
360
  report = report.replace("{{" + key + "}}", value)
207
361
 
208
- output_path.parent.mkdir(parents=True, exist_ok=True)
209
362
  try:
363
+ output_path.parent.mkdir(parents=True, exist_ok=True)
210
364
  output_path.write_text(report, encoding="utf-8")
211
365
  except Exception as exc:
212
- _emit_error(f"Failed to write report: {exc}", "WRITE_ERROR")
213
- return 2
214
-
215
- skills = state.get("skills", [])
216
- completed_count = sum(1 for s in skills if s.get("status") == "completed")
217
- failed_count = sum(1 for s in skills if s.get("status") == "failed")
218
- quality_scores = {
219
- s["name"]: s["quality_score"]
220
- for s in skills
221
- if s.get("status") == "completed" and s.get("quality_score") is not None
222
- }
366
+ return fail(f"Failed to write report: {exc}", "WRITE_ERROR")
223
367
 
224
368
  result = {
225
369
  "status": "success",
226
370
  "report_path": output_path.as_posix(),
227
- "skills_completed": completed_count,
228
- "skills_failed": failed_count,
229
- "quality_scores": quality_scores,
371
+ **_counts(state),
230
372
  "duration": aggregates["duration"],
373
+ "export_verdicts": (
374
+ None if classification is None else {r["name"]: r["verdict"] for r in classification["skills"]}
375
+ ),
376
+ "skills_excluded": (
377
+ None if classification is None else [e["name"] for e in classification["excluded"]]
378
+ ),
379
+ **_export_outcomes(state),
231
380
  }
381
+ _write_context(context_file, {
382
+ "status": "success",
383
+ "skills_completed": result["skills_completed"],
384
+ "skills_failed": result["skills_failed"],
385
+ "quality_scores": result["quality_scores"],
386
+ "export_verdicts": result["export_verdicts"],
387
+ "skills_excluded": result["skills_excluded"],
388
+ "skills_exported": result["skills_exported"],
389
+ "export_failures": result["export_failures"],
390
+ "campaign_report_path": result["report_path"],
391
+ "decision_log": decision_log,
392
+ "duration": result["duration"],
393
+ })
232
394
  json.dump(result, sys.stdout, separators=(",", ":"))
233
395
  sys.stdout.write("\n")
234
396
  return 0
@@ -241,8 +403,13 @@ def main() -> int:
241
403
  parser.add_argument("--state-file", required=True, help="Path to _campaign-state.yaml")
242
404
  parser.add_argument("--template-file", required=True, help="Path to campaign-report-template.md")
243
405
  parser.add_argument("--output-file", required=True, help="Path to write the generated report")
406
+ parser.add_argument(
407
+ "--context-file",
408
+ help="Also write the SKF_CAMPAIGN_RESULT_JSON payload for skf-emit-result-envelope.py here",
409
+ )
410
+ parser.add_argument("--decision-log", help="Path to _campaign-decision-log.md, for the payload")
244
411
  args = parser.parse_args()
245
- return run(args.state_file, args.template_file, args.output_file)
412
+ return run(args.state_file, args.template_file, args.output_file, args.context_file, args.decision_log)
246
413
 
247
414
 
248
415
  if __name__ == "__main__":