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.10"
2
+ # requires-python = ">=3.11"
3
3
  # dependencies = ["pyyaml"]
4
4
  # ///
5
5
  """SKF Resolve Authoritative Files — §2a deterministic pre-prompt pipeline.
@@ -27,7 +27,7 @@ drift-prone parts. The helper consolidates them into one `resolve` call.
27
27
 
28
28
  Subcommand:
29
29
  resolve --source-root <path> --brief <brief.yaml-path>
30
- [--preview-lines 20]
30
+ [--preview-lines 20] [--provenance-map <provenance-map.json>]
31
31
 
32
32
  Output JSON (stdout):
33
33
 
@@ -35,10 +35,14 @@ Output JSON (stdout):
35
35
  "status": "no-candidates" | "candidates-found",
36
36
  "summary": {
37
37
  "candidates_total": N,
38
+ "already_tracked_count": N,
38
39
  "already_in_scope_count": N,
39
40
  "pre_decided_count": N,
40
41
  "unresolved_count": N
41
42
  },
43
+ "already_tracked": [
44
+ {"path": "...", "heuristic": "llms.txt"}
45
+ ],
42
46
  "already_in_scope": [
43
47
  {"path": "...", "heuristic": "llms.txt", "size_bytes": N,
44
48
  "line_count": N, "content_hash": "sha256:..."}
@@ -53,13 +57,21 @@ Output JSON (stdout):
53
57
  {"path": "...", "heuristic": "...", "size_bytes": N,
54
58
  "line_count": N, "content_hash": "sha256:...",
55
59
  "preview": "<first N lines as a string>",
56
- "excluded_by_pattern": "<glob>" | "not matched by any scope.include"}
60
+ "excluded_by_pattern": "<glob>" | "not matched by any scope.include",
61
+ "prior_action": null | "deferred-headless"}
57
62
  ]
58
63
  }
59
64
 
60
65
  Paths are emitted relative to `source-root`, forward-slash form
61
66
  (cross-platform JSON convention — same as skf-detect-scripts-assets.py).
62
67
 
68
+ `already_tracked` semantics (update-skill's mirror of this protocol):
69
+ with `--provenance-map`, a candidate the map already names, in
70
+ `entries[].source_file` or `file_entries[].source_file`, is tracked:
71
+ change detection handles it, so it is listed here, with no hash, and in
72
+ no other bucket. Without `--provenance-map` the list is empty.
73
+ `candidates_total` counts every candidate, tracked ones included.
74
+
63
75
  `pre_decided` semantics:
64
76
  - `prior_action="promoted"` AND `should_add_to_promoted_docs=true` →
65
77
  the path is in scope but the caller still needs to add it to
@@ -68,9 +80,18 @@ Paths are emitted relative to `source-root`, forward-slash form
68
80
  - `prior_action="skipped"` → the user previously declined; caller
69
81
  does nothing. Hash/size/lines are null (no need to read the file).
70
82
 
83
+ `unresolved` semantics: nobody has decided the path yet, so an
84
+ interactive run asks. `prior_action="deferred-headless"` means a headless
85
+ run already met the path and left the decision to the next interactive
86
+ run (an amendment with `action: "deferred-headless"`); a headless run
87
+ does not record it again. A `skipped` amendment whose reason is the
88
+ headless default, "headless: no user to prompt", was written that way by
89
+ a headless run before `deferred-headless` existed: no person declined
90
+ the file, so it counts as `deferred-headless` too.
91
+
71
92
  Exit codes:
72
- 0 — operation succeeded (any status)
73
- 1 — user error (paths invalid, brief unparseable)
93
+ 0 operation succeeded (any status)
94
+ 1 user error (paths invalid, brief or provenance map unparseable)
74
95
  """
75
96
 
76
97
  from __future__ import annotations
@@ -86,6 +107,21 @@ from typing import Iterable
86
107
  import yaml
87
108
 
88
109
 
110
+ # skf-classify-changed-files.py loads this file for load_brief,
111
+ # extract_scope, glob_match, scope_match, normalize_rel_path and
112
+ # EXCLUDED_DIR_NAMES (its load_scope, the brief-scope test that
113
+ # skf-new-file-diff.py, skf-detect-scripts-assets.py --brief and
114
+ # skf-compare-file-hashes.py --brief load from it, reads the brief through
115
+ # them), skf-detect-registry.py for glob_match, load_brief
116
+ # and extract_scope, skf-extract-public-api.py for glob_match and
117
+ # parse_brief_yaml, and every other script that reads a skill brief
118
+ # (skf-validate-brief-schema.py, skf-provenance-gap-dispatch.py,
119
+ # skf-derive-assembly-shape.py, skf-write-skill-brief.py and skf-test-skill's
120
+ # load-coverage-inputs.py) for parse_brief_yaml, load-coverage-inputs.py
121
+ # also for _amendment_action: keep those names and what they take and
122
+ # return.
123
+
124
+
89
125
  # --------------------------------------------------------------------------
90
126
  # Heuristic list — case-insensitive basename match
91
127
  # --------------------------------------------------------------------------
@@ -243,13 +279,30 @@ def scope_match(
243
279
  # --------------------------------------------------------------------------
244
280
 
245
281
 
282
+ def parse_brief_yaml(text: str):
283
+ """The one document a skill brief's YAML text holds, or None when it holds none.
284
+
285
+ SKF 1.x closed every brief with a trailing `---`, which YAML reads as a
286
+ second, empty document, so `yaml.safe_load` refuses such a brief. A
287
+ document that holds no value (empty, or an explicit null such as `~`) is
288
+ skipped wherever it stands; more than one document that holds a value is
289
+ refused with yaml.YAMLError, as is text that is not YAML.
290
+ """
291
+ documents = [doc for doc in yaml.safe_load_all(text) if doc is not None]
292
+ if len(documents) > 1:
293
+ raise yaml.YAMLError(
294
+ f"a skill brief is a single document; this text holds {len(documents)}"
295
+ )
296
+ return documents[0] if documents else None
297
+
298
+
246
299
  def load_brief(brief_path: Path) -> dict:
247
300
  try:
248
301
  text = brief_path.read_text(encoding="utf-8")
249
302
  except OSError as exc:
250
303
  raise ValueError(f"cannot read brief at {brief_path}: {exc}") from exc
251
304
  try:
252
- brief = yaml.safe_load(text)
305
+ brief = parse_brief_yaml(text)
253
306
  except yaml.YAMLError as exc:
254
307
  raise ValueError(
255
308
  f"brief at {brief_path} is not valid YAML: {exc}"
@@ -267,7 +320,8 @@ def extract_scope(brief: dict) -> tuple[list[str], list[str], dict[str, list[str
267
320
 
268
321
  amendments_by_path maps each path to a list of actions seen, in the
269
322
  order they appear in the brief (so reconcile() can pick most-recent
270
- by iterating in reverse).
323
+ by iterating in reverse). A legacy headless skip is listed as
324
+ 'deferred-headless' (see _amendment_action).
271
325
  """
272
326
  scope = brief.get("scope") if isinstance(brief.get("scope"), dict) else {}
273
327
  includes = scope.get("include") if isinstance(scope.get("include"), list) else []
@@ -279,8 +333,8 @@ def extract_scope(brief: dict) -> tuple[list[str], list[str], dict[str, list[str
279
333
  if not isinstance(amend, dict):
280
334
  continue
281
335
  path = amend.get("path")
282
- action = amend.get("action")
283
- if isinstance(path, str) and isinstance(action, str):
336
+ action = _amendment_action(amend)
337
+ if isinstance(path, str) and action is not None:
284
338
  by_path.setdefault(path, []).append(action)
285
339
 
286
340
  # filter to strings only — schema requires strings but defensively guard
@@ -289,6 +343,48 @@ def extract_scope(brief: dict) -> tuple[list[str], list[str], dict[str, list[str
289
343
  return includes, excludes, by_path
290
344
 
291
345
 
346
+ # --------------------------------------------------------------------------
347
+ # Provenance map: the files it already tracks
348
+ # --------------------------------------------------------------------------
349
+
350
+
351
+ def normalize_rel_path(path: str) -> str:
352
+ """A provenance or brief path in the form this helper emits: forward
353
+ slashes, no leading `./`."""
354
+ path = path.strip().replace("\\", "/")
355
+ while path.startswith("./"):
356
+ path = path[2:]
357
+ return path
358
+
359
+
360
+ def load_tracked_files(provenance_path: Path) -> set[str]:
361
+ """Every `entries[].source_file` and `file_entries[].source_file` of a
362
+ provenance map. Raises ValueError when the map cannot be read."""
363
+ try:
364
+ data = json.loads(provenance_path.read_text(encoding="utf-8"))
365
+ except OSError as exc:
366
+ raise ValueError(f"cannot read provenance map at {provenance_path}: {exc}") from exc
367
+ except ValueError as exc:
368
+ raise ValueError(
369
+ f"provenance map at {provenance_path} is not valid JSON: {exc}"
370
+ ) from exc
371
+ if not isinstance(data, dict):
372
+ raise ValueError(
373
+ f"provenance map at {provenance_path} must be a JSON object; got "
374
+ f"{type(data).__name__}"
375
+ )
376
+ tracked: set[str] = set()
377
+ for key in ("entries", "file_entries"):
378
+ rows = data.get(key)
379
+ if not isinstance(rows, list):
380
+ continue
381
+ for row in rows:
382
+ source = row.get("source_file") if isinstance(row, dict) else None
383
+ if isinstance(source, str) and source.strip():
384
+ tracked.add(normalize_rel_path(source))
385
+ return tracked
386
+
387
+
292
388
  # --------------------------------------------------------------------------
293
389
  # File metadata: hash + size + lines + preview
294
390
  # --------------------------------------------------------------------------
@@ -338,13 +434,28 @@ def load_preview(path: Path, *, max_lines: int) -> str:
338
434
 
339
435
  _PROMOTED = "promoted"
340
436
  _SKIPPED = "skipped"
437
+ _DEFERRED = "deferred-headless"
438
+ # The reason a headless run gave its automatic skip before deferred-headless
439
+ # existed. Such a skip was never a person's decision.
440
+ _LEGACY_HEADLESS_REASON = "headless: no user to prompt"
441
+
442
+
443
+ def _amendment_action(amend: dict) -> str | None:
444
+ """The action an amendment records, reading a legacy headless skip as a deferral."""
445
+ action = amend.get("action")
446
+ if not isinstance(action, str):
447
+ return None
448
+ reason = amend.get("reason")
449
+ if action == _SKIPPED and isinstance(reason, str) and reason.strip() == _LEGACY_HEADLESS_REASON:
450
+ return _DEFERRED
451
+ return action
341
452
 
342
453
 
343
454
  def _latest_action(actions: list[str]) -> str | None:
344
455
  """Most-recent matching amendment wins. Returns 'promoted', 'skipped',
345
- or None if no recognized action was seen."""
456
+ 'deferred-headless', or None if no recognized action was seen."""
346
457
  for action in reversed(actions):
347
- if action in (_PROMOTED, _SKIPPED):
458
+ if action in (_PROMOTED, _SKIPPED, _DEFERRED):
348
459
  return action
349
460
  return None
350
461
 
@@ -354,17 +465,25 @@ def resolve(
354
465
  brief_path: Path,
355
466
  *,
356
467
  preview_lines: int = 20,
468
+ provenance_map: Path | None = None,
357
469
  ) -> dict:
358
470
  """Run the §2a deterministic pipeline. See module docstring for output shape."""
359
471
  brief = load_brief(brief_path)
360
472
  includes, excludes, amendments_by_path = extract_scope(brief)
473
+ tracked = load_tracked_files(provenance_map) if provenance_map is not None else set()
361
474
 
475
+ already_tracked: list[dict] = []
362
476
  already_in_scope: list[dict] = []
363
477
  pre_decided: list[dict] = []
364
478
  unresolved: list[dict] = []
365
479
 
366
480
  for file_path, heuristic in iter_auth_doc_files(source_root):
367
481
  rel = file_path.relative_to(source_root).as_posix()
482
+ if rel in tracked:
483
+ # The provenance map already names it: change detection handles
484
+ # it, and no decision is asked for.
485
+ already_tracked.append({"path": rel, "heuristic": heuristic})
486
+ continue
368
487
  in_scope, excluded_by = scope_match(rel, includes, excludes)
369
488
  prior_action = _latest_action(amendments_by_path.get(rel, []))
370
489
 
@@ -398,6 +517,7 @@ def resolve(
398
517
  continue
399
518
 
400
519
  if prior_action == _SKIPPED:
520
+ # A person declined the file; a headless deferral never lands here.
401
521
  pre_decided.append({
402
522
  "path": rel,
403
523
  "heuristic": heuristic,
@@ -409,7 +529,8 @@ def resolve(
409
529
  })
410
530
  continue
411
531
 
412
- # No prior amendment and out of scope → unresolved
532
+ # Out of scope and undecided (no amendment, or a headless deferral
533
+ # that waits for the next interactive run) → unresolved
413
534
  unresolved.append({
414
535
  "path": rel,
415
536
  "heuristic": heuristic,
@@ -418,24 +539,28 @@ def resolve(
418
539
  "content_hash": sha256_of_file(file_path),
419
540
  "preview": load_preview(file_path, max_lines=preview_lines),
420
541
  "excluded_by_pattern": excluded_by,
542
+ "prior_action": prior_action,
421
543
  })
422
544
 
423
545
  # Deterministic ordering for stable diffs / cache keys
546
+ already_tracked.sort(key=lambda r: r["path"])
424
547
  already_in_scope.sort(key=lambda r: r["path"])
425
548
  pre_decided.sort(key=lambda r: r["path"])
426
549
  unresolved.sort(key=lambda r: r["path"])
427
550
 
428
551
  candidates_total = (
429
- len(already_in_scope) + len(pre_decided) + len(unresolved)
552
+ len(already_tracked) + len(already_in_scope) + len(pre_decided) + len(unresolved)
430
553
  )
431
554
  return {
432
555
  "status": "candidates-found" if candidates_total > 0 else "no-candidates",
433
556
  "summary": {
434
557
  "candidates_total": candidates_total,
558
+ "already_tracked_count": len(already_tracked),
435
559
  "already_in_scope_count": len(already_in_scope),
436
560
  "pre_decided_count": len(pre_decided),
437
561
  "unresolved_count": len(unresolved),
438
562
  },
563
+ "already_tracked": already_tracked,
439
564
  "already_in_scope": already_in_scope,
440
565
  "pre_decided": pre_decided,
441
566
  "unresolved": unresolved,
@@ -461,8 +586,17 @@ def _cmd_resolve(args: argparse.Namespace) -> int:
461
586
  if args.preview_lines < 1:
462
587
  print("error: --preview-lines must be >= 1", file=sys.stderr)
463
588
  return 1
589
+ provenance_map = Path(args.provenance_map) if args.provenance_map else None
590
+ if provenance_map is not None and not provenance_map.is_file():
591
+ print(f"error: provenance map not found: {provenance_map}", file=sys.stderr)
592
+ return 1
464
593
  try:
465
- result = resolve(source_root, brief_path, preview_lines=args.preview_lines)
594
+ result = resolve(
595
+ source_root,
596
+ brief_path,
597
+ preview_lines=args.preview_lines,
598
+ provenance_map=provenance_map,
599
+ )
466
600
  except ValueError as exc:
467
601
  print(f"error: {exc}", file=sys.stderr)
468
602
  return 1
@@ -490,6 +624,13 @@ def _build_parser() -> argparse.ArgumentParser:
490
624
  default=20,
491
625
  help="number of lines to capture for the prompt preview (default: 20)",
492
626
  )
627
+ p.add_argument(
628
+ "--provenance-map",
629
+ help=(
630
+ "path to provenance-map.json: candidates it already tracks are "
631
+ "listed in already_tracked and in no other bucket"
632
+ ),
633
+ )
493
634
  p.set_defaults(func=_cmd_resolve)
494
635
  return parser
495
636