bmad-module-skill-forge 1.9.0 → 2.0.1

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 (281) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.nvmrc +1 -1
  3. package/README.md +10 -5
  4. package/docs/_data/pinned.yaml +2 -2
  5. package/docs/agents.md +11 -2
  6. package/docs/architecture.md +5 -4
  7. package/docs/bmad-synergy.md +30 -7
  8. package/docs/campaign.md +172 -0
  9. package/docs/examples.md +7 -3
  10. package/docs/forge-auto.md +90 -0
  11. package/docs/getting-started.md +9 -0
  12. package/docs/how-it-works.md +6 -4
  13. package/docs/index.md +4 -3
  14. package/docs/skill-model.md +1 -1
  15. package/docs/troubleshooting.md +17 -1
  16. package/docs/verifying-a-skill.md +2 -2
  17. package/docs/why-skf.md +1 -1
  18. package/docs/workflows.md +64 -24
  19. package/package.json +2 -2
  20. package/src/knowledge/skill-lifecycle.md +1 -1
  21. package/src/module-help.csv +4 -3
  22. package/src/shared/data/language-corpora.json +32 -0
  23. package/src/shared/references/pipeline-contracts.md +6 -3
  24. package/src/shared/scripts/schemas/skill-brief.v1.json +6 -1
  25. package/src/shared/scripts/skf-comention-pairs.py +350 -0
  26. package/src/shared/scripts/skf-count-tokens.py +222 -0
  27. package/src/shared/scripts/skf-derive-assembly-shape.py +107 -0
  28. package/src/shared/scripts/skf-detect-docs.py +240 -4
  29. package/src/shared/scripts/skf-detect-language.py +82 -3
  30. package/src/shared/scripts/skf-detect-tools.py +105 -2
  31. package/src/shared/scripts/skf-emit-result-envelope.py +17 -0
  32. package/src/shared/scripts/skf-enumerate-stack-skills.py +111 -2
  33. package/src/shared/scripts/skf-extract-public-api.py +53 -0
  34. package/src/shared/scripts/skf-find-cycles.py +246 -0
  35. package/src/shared/scripts/skf-hash-content.py +487 -2
  36. package/src/shared/scripts/skf-language-corpora.py +100 -0
  37. package/src/shared/scripts/skf-manifest-ops.py +67 -1
  38. package/src/shared/scripts/skf-merge-doc-urls.py +244 -0
  39. package/src/shared/scripts/skf-preapply.py +1 -1
  40. package/src/shared/scripts/skf-rebuild-managed-sections.py +180 -0
  41. package/src/shared/scripts/skf-recommend-scope-type.py +1 -2
  42. package/src/shared/scripts/skf-render-metadata-stats.py +499 -0
  43. package/src/shared/scripts/skf-rewrite-skill-name.py +308 -0
  44. package/src/shared/scripts/skf-shape-detect.py +576 -25
  45. package/src/shared/scripts/skf-shard-body.py +461 -0
  46. package/src/shared/scripts/skf-skill-inventory.py +139 -3
  47. package/src/shared/scripts/skf-structural-diff.py +307 -67
  48. package/src/shared/scripts/skf-validate-brief-schema.py +41 -6
  49. package/src/shared/scripts/skf-validate-feasibility-report.py +234 -0
  50. package/src/shared/scripts/skf-validate-frontmatter.py +17 -12
  51. package/src/shared/scripts/skf-validate-output.py +443 -10
  52. package/src/shared/scripts/skf-validate-pins.py +3 -3
  53. package/src/shared/scripts/skf-verify-no-trace.py +214 -0
  54. package/src/shared/scripts/skf-verify-provenance-completeness.py +439 -0
  55. package/src/shared/scripts/skf-write-skill-brief.py +21 -5
  56. package/src/skf-analyze-source/SKILL.md +17 -32
  57. package/src/skf-analyze-source/assets/skill-brief-schema.md +1 -1
  58. package/src/skf-analyze-source/customize.toml +2 -0
  59. package/src/skf-analyze-source/references/auto-docs-only.md +116 -0
  60. package/src/skf-analyze-source/references/continue.md +8 -13
  61. package/src/skf-analyze-source/references/generate-briefs.md +28 -12
  62. package/src/skf-analyze-source/references/headless-contract.md +33 -0
  63. package/src/skf-analyze-source/references/health-check.md +1 -2
  64. package/src/skf-analyze-source/references/identify-units.md +25 -36
  65. package/src/skf-analyze-source/references/init.md +12 -25
  66. package/src/skf-analyze-source/references/map-and-detect.md +8 -20
  67. package/src/skf-analyze-source/references/recommend.md +4 -14
  68. package/src/skf-analyze-source/references/scan-project.md +3 -11
  69. package/src/skf-analyze-source/references/step-auto-scope.md +211 -197
  70. package/src/skf-analyze-source/references/step-shape-detect.md +20 -13
  71. package/src/skf-analyze-source/references/unit-detection-heuristics.md +2 -2
  72. package/src/skf-audit-skill/SKILL.md +9 -6
  73. package/src/skf-audit-skill/customize.toml +2 -0
  74. package/src/skf-audit-skill/references/init.md +58 -32
  75. package/src/skf-audit-skill/references/re-index.md +15 -34
  76. package/src/skf-audit-skill/references/report.md +11 -58
  77. package/src/skf-audit-skill/references/semantic-diff.md +4 -22
  78. package/src/skf-audit-skill/references/severity-classify.md +53 -87
  79. package/src/skf-audit-skill/references/step-doc-drift.md +49 -19
  80. package/src/skf-audit-skill/references/structural-diff.md +43 -68
  81. package/src/skf-brief-skill/SKILL.md +7 -36
  82. package/src/skf-brief-skill/assets/scope-templates.md +1 -1
  83. package/src/skf-brief-skill/assets/skill-brief-schema.md +1 -1
  84. package/src/skf-brief-skill/customize.toml +14 -0
  85. package/src/skf-brief-skill/references/analyze-target.md +13 -18
  86. package/src/skf-brief-skill/references/confirm-brief.md +2 -15
  87. package/src/skf-brief-skill/references/draft-checkpoint.md +8 -8
  88. package/src/skf-brief-skill/references/gather-intent.md +27 -24
  89. package/src/skf-brief-skill/references/headless-args.md +1 -1
  90. package/src/skf-brief-skill/references/health-check.md +1 -22
  91. package/src/skf-brief-skill/references/invocation-contract.md +37 -0
  92. package/src/skf-brief-skill/references/scope-definition.md +6 -15
  93. package/src/skf-brief-skill/references/step-auto-brief.md +22 -9
  94. package/src/skf-brief-skill/references/step-auto-validate.md +3 -7
  95. package/src/skf-brief-skill/references/version-resolution.md +1 -1
  96. package/src/skf-brief-skill/references/write-brief.md +19 -13
  97. package/src/skf-campaign/SKILL.md +121 -0
  98. package/src/skf-campaign/assets/campaign-state-schema.json +191 -0
  99. package/src/skf-campaign/customize.toml +75 -0
  100. package/src/skf-campaign/manifest.yaml +15 -0
  101. package/src/skf-campaign/references/campaign-contracts.md +67 -0
  102. package/src/skf-campaign/references/campaign-directive-spec.md +32 -0
  103. package/src/skf-campaign/references/health-check.md +35 -0
  104. package/src/skf-campaign/references/step-01-setup.md +121 -0
  105. package/src/skf-campaign/references/step-02-strategy.md +102 -0
  106. package/src/skf-campaign/references/step-03-pins.md +56 -0
  107. package/src/skf-campaign/references/step-04-provenance.md +63 -0
  108. package/src/skf-campaign/references/step-05-skill-loop.md +103 -0
  109. package/src/skf-campaign/references/step-06-batch.md +88 -0
  110. package/src/skf-campaign/references/step-07-capstone.md +63 -0
  111. package/src/skf-campaign/references/step-08-verify.md +75 -0
  112. package/src/skf-campaign/references/step-09-refine.md +83 -0
  113. package/src/skf-campaign/references/step-10-export.md +106 -0
  114. package/src/skf-campaign/references/step-11-maintenance.md +84 -0
  115. package/src/skf-campaign/references/step-resume.md +115 -0
  116. package/src/skf-campaign/scripts/.gitkeep +0 -0
  117. package/src/skf-campaign/scripts/campaign-deps.py +244 -0
  118. package/src/skf-campaign/scripts/campaign-parse-manifest.py +119 -0
  119. package/src/skf-campaign/scripts/campaign-provenance.py +247 -0
  120. package/src/skf-campaign/scripts/campaign-render-batch.py +199 -0
  121. package/src/skf-campaign/scripts/campaign-render-kickoff.py +158 -0
  122. package/src/skf-campaign/scripts/campaign-report.py +249 -0
  123. package/src/skf-campaign/scripts/campaign-status.py +162 -0
  124. package/src/skf-campaign/scripts/campaign-validate-pins.py +174 -0
  125. package/src/skf-campaign/scripts/campaign-validate-state.py +207 -0
  126. package/src/skf-campaign/templates/campaign-brief-template.yaml +34 -0
  127. package/src/skf-campaign/templates/campaign-report-template.md +54 -0
  128. package/src/skf-campaign/templates/kickoff-template.md +48 -0
  129. package/src/skf-create-skill/SKILL.md +15 -4
  130. package/src/skf-create-skill/assets/compile-assembly-rules.md +35 -34
  131. package/src/skf-create-skill/assets/skill-sections.md +9 -100
  132. package/src/skf-create-skill/assets/tessl-dismissal-rules.md +4 -13
  133. package/src/skf-create-skill/customize.toml +13 -0
  134. package/src/skf-create-skill/references/authoritative-files-protocol.md +7 -7
  135. package/src/skf-create-skill/references/compile.md +37 -47
  136. package/src/skf-create-skill/references/component-extraction.md +8 -35
  137. package/src/skf-create-skill/references/ecosystem-check.md +9 -25
  138. package/src/skf-create-skill/references/enrich.md +4 -17
  139. package/src/skf-create-skill/references/extract.md +20 -27
  140. package/src/skf-create-skill/references/extraction-patterns-tracing.md +1 -1
  141. package/src/skf-create-skill/references/extraction-patterns.md +10 -8
  142. package/src/skf-create-skill/references/generate-artifacts.md +20 -25
  143. package/src/skf-create-skill/references/health-check.md +2 -2
  144. package/src/skf-create-skill/references/load-brief.md +16 -18
  145. package/src/skf-create-skill/references/report.md +27 -14
  146. package/src/skf-create-skill/references/source-resolution-protocols.md +4 -4
  147. package/src/skf-create-skill/references/step-auto-shard.md +52 -25
  148. package/src/skf-create-skill/references/step-doc-rot.md +33 -15
  149. package/src/skf-create-skill/references/step-doc-sources.md +13 -4
  150. package/src/skf-create-skill/references/sub/ccc-discover.md +2 -13
  151. package/src/skf-create-skill/references/sub/fetch-docs.md +33 -46
  152. package/src/skf-create-skill/references/sub/fetch-temporal.md +5 -20
  153. package/src/skf-create-skill/references/tier-degradation-rules.md +6 -8
  154. package/src/skf-create-skill/references/validate.md +69 -29
  155. package/src/skf-create-skill/scripts/scan-doc-rot.py +245 -0
  156. package/src/skf-create-stack-skill/SKILL.md +15 -9
  157. package/src/skf-create-stack-skill/assets/provenance-map-schema.md +1 -1
  158. package/src/skf-create-stack-skill/customize.toml +10 -0
  159. package/src/skf-create-stack-skill/references/compile-stack.md +7 -8
  160. package/src/skf-create-stack-skill/references/compose-mode-rules.md +2 -13
  161. package/src/skf-create-stack-skill/references/detect-integrations.md +49 -54
  162. package/src/skf-create-stack-skill/references/detect-manifests.md +37 -30
  163. package/src/skf-create-stack-skill/references/generate-output.md +24 -75
  164. package/src/skf-create-stack-skill/references/init.md +9 -81
  165. package/src/skf-create-stack-skill/references/manifest-patterns.md +5 -35
  166. package/src/skf-create-stack-skill/references/parallel-extract.md +12 -27
  167. package/src/skf-create-stack-skill/references/rank-and-confirm.md +6 -6
  168. package/src/skf-create-stack-skill/references/report.md +27 -62
  169. package/src/skf-create-stack-skill/references/validate.md +35 -31
  170. package/src/skf-drop-skill/SKILL.md +20 -23
  171. package/src/skf-drop-skill/customize.toml +10 -0
  172. package/src/skf-drop-skill/references/execute.md +67 -36
  173. package/src/skf-drop-skill/references/headless-contract.md +18 -0
  174. package/src/skf-drop-skill/references/health-check.md +1 -13
  175. package/src/skf-drop-skill/references/report.md +44 -10
  176. package/src/skf-drop-skill/references/select.md +93 -48
  177. package/src/skf-drop-skill/scripts/dir-sizes.py +116 -0
  178. package/src/skf-export-skill/SKILL.md +17 -14
  179. package/src/skf-export-skill/assets/managed-section-format.md +2 -5
  180. package/src/skf-export-skill/customize.toml +10 -6
  181. package/src/skf-export-skill/references/generate-snippet.md +21 -35
  182. package/src/skf-export-skill/references/load-skill.md +44 -42
  183. package/src/skf-export-skill/references/multi-skill-mode.md +1 -1
  184. package/src/skf-export-skill/references/orphan-context-detection.md +11 -3
  185. package/src/skf-export-skill/references/package.md +27 -33
  186. package/src/skf-export-skill/references/preflight-snippet-root-probe.md +24 -5
  187. package/src/skf-export-skill/references/result-envelope.md +28 -0
  188. package/src/skf-export-skill/references/summary.md +11 -5
  189. package/src/skf-export-skill/references/token-report.md +42 -24
  190. package/src/skf-export-skill/references/update-context.md +32 -33
  191. package/src/skf-forger/SKILL.md +32 -39
  192. package/src/skf-forger/references/pipeline-mode.md +34 -0
  193. package/src/skf-forger/scripts/parse-pipeline.py +270 -0
  194. package/src/skf-quick-skill/SKILL.md +10 -60
  195. package/src/skf-quick-skill/customize.toml +9 -0
  196. package/src/skf-quick-skill/references/batch-mode.md +6 -4
  197. package/src/skf-quick-skill/references/compile.md +15 -52
  198. package/src/skf-quick-skill/references/ecosystem-check.md +5 -20
  199. package/src/skf-quick-skill/references/finalize.md +12 -6
  200. package/src/skf-quick-skill/references/halt-contract.md +54 -0
  201. package/src/skf-quick-skill/references/health-check.md +3 -4
  202. package/src/skf-quick-skill/references/quick-extract.md +7 -18
  203. package/src/skf-quick-skill/references/registry-resolution.md +1 -23
  204. package/src/skf-quick-skill/references/resolve-target.md +27 -34
  205. package/src/skf-quick-skill/references/write-and-validate.md +10 -25
  206. package/src/skf-refine-architecture/SKILL.md +16 -8
  207. package/src/skf-refine-architecture/customize.toml +9 -0
  208. package/src/skf-refine-architecture/references/compile.md +10 -8
  209. package/src/skf-refine-architecture/references/gap-analysis.md +21 -50
  210. package/src/skf-refine-architecture/references/health-check.md +1 -1
  211. package/src/skf-refine-architecture/references/improvements.md +9 -25
  212. package/src/skf-refine-architecture/references/init.md +9 -16
  213. package/src/skf-refine-architecture/references/issue-detection.md +10 -25
  214. package/src/skf-refine-architecture/references/refinement-rules.md +4 -16
  215. package/src/skf-refine-architecture/references/report.md +14 -11
  216. package/src/skf-rename-skill/SKILL.md +11 -21
  217. package/src/skf-rename-skill/customize.toml +10 -0
  218. package/src/skf-rename-skill/references/execute.md +112 -82
  219. package/src/skf-rename-skill/references/exit-codes.md +12 -0
  220. package/src/skf-rename-skill/references/report.md +16 -8
  221. package/src/skf-rename-skill/references/select.md +69 -42
  222. package/src/skf-rename-skill/scripts/skf-validate-rename-name.py +161 -0
  223. package/src/skf-setup/SKILL.md +21 -13
  224. package/src/skf-setup/customize.toml +10 -0
  225. package/src/skf-setup/references/auto-index.md +11 -10
  226. package/src/skf-setup/references/ccc-index.md +14 -15
  227. package/src/skf-setup/references/detect-and-tier.md +10 -8
  228. package/src/skf-setup/references/report.md +26 -32
  229. package/src/skf-setup/references/tier-rules.md +2 -32
  230. package/src/skf-setup/references/write-config.md +9 -10
  231. package/src/skf-test-skill/SKILL.md +10 -8
  232. package/src/skf-test-skill/customize.toml +2 -0
  233. package/src/skf-test-skill/references/coherence-check.md +19 -31
  234. package/src/skf-test-skill/references/coverage-check.md +111 -67
  235. package/src/skf-test-skill/references/detect-mode.md +10 -41
  236. package/src/skf-test-skill/references/external-validators.md +11 -19
  237. package/src/skf-test-skill/references/init.md +39 -21
  238. package/src/skf-test-skill/references/migration-section-rules.md +4 -4
  239. package/src/skf-test-skill/references/report.md +60 -40
  240. package/src/skf-test-skill/references/score.md +32 -64
  241. package/src/skf-test-skill/references/scoring-rules.md +6 -62
  242. package/src/skf-test-skill/references/source-access-protocol.md +15 -5
  243. package/src/skf-test-skill/references/step-hard-gate.md +1 -3
  244. package/src/skf-test-skill/scripts/aggregate-coherence.py +276 -0
  245. package/src/skf-test-skill/scripts/check-metadata-coherence.py +359 -0
  246. package/src/skf-test-skill/scripts/combine-external-scores.py +190 -0
  247. package/src/skf-test-skill/scripts/compute-score.py +135 -4
  248. package/src/skf-test-skill/scripts/reconcile-coverage.py +327 -0
  249. package/src/skf-test-skill/scripts/validate-inventory.py +251 -0
  250. package/src/skf-test-skill/scripts/verify-declared-numerator.py +192 -0
  251. package/src/skf-update-skill/SKILL.md +17 -5
  252. package/src/skf-update-skill/customize.toml +11 -6
  253. package/src/skf-update-skill/references/detect-changes.md +48 -36
  254. package/src/skf-update-skill/references/health-check.md +5 -11
  255. package/src/skf-update-skill/references/init.md +40 -32
  256. package/src/skf-update-skill/references/manual-section-rules.md +1 -2
  257. package/src/skf-update-skill/references/merge-conflict-rules.md +1 -52
  258. package/src/skf-update-skill/references/merge.md +13 -57
  259. package/src/skf-update-skill/references/re-extract.md +27 -25
  260. package/src/skf-update-skill/references/report.md +14 -7
  261. package/src/skf-update-skill/references/validate.md +32 -30
  262. package/src/skf-update-skill/references/write.md +86 -51
  263. package/src/skf-update-skill/scripts/skf-new-file-diff.py +167 -0
  264. package/src/skf-verify-stack/SKILL.md +11 -21
  265. package/src/skf-verify-stack/customize.toml +12 -3
  266. package/src/skf-verify-stack/references/coverage-patterns.md +1 -29
  267. package/src/skf-verify-stack/references/coverage.md +21 -10
  268. package/src/skf-verify-stack/references/exit-codes.md +14 -0
  269. package/src/skf-verify-stack/references/health-check.md +1 -1
  270. package/src/skf-verify-stack/references/init.md +20 -25
  271. package/src/skf-verify-stack/references/integration-verification-rules.md +10 -19
  272. package/src/skf-verify-stack/references/integrations.md +44 -49
  273. package/src/skf-verify-stack/references/report.md +28 -34
  274. package/src/skf-verify-stack/references/requirements.md +3 -3
  275. package/src/skf-verify-stack/references/synthesize.md +36 -39
  276. package/src/skf-verify-stack/scripts/skf-coverage-tally.py +196 -0
  277. package/src/skf-verify-stack/scripts/skf-report-delta.py +256 -0
  278. package/src/skf-verify-stack/scripts/skf-verdict-rollup.py +258 -0
  279. package/tools/cli/lib/ui.js +3 -2
  280. package/docs/deepwiki.md +0 -89
  281. package/src/skf-rename-skill/references/rebuild-context.md +0 -110
@@ -4,10 +4,17 @@ forgeTierConfig: '{sidecar_path}/forge-tier.yaml'
4
4
  # Resolve `{atomicWriteHelper}` by probing `{atomicWriteProbeOrder}` in order
5
5
  # (installed SKF module path first, src/ dev-checkout fallback); first existing
6
6
  # path wins. HALT if neither resolves — the active-symlink flip and registry
7
- # writes below MUST go through the atomic helper for concurrency safety.
7
+ # writes below go through the atomic helper for concurrency safety.
8
8
  atomicWriteProbeOrder:
9
9
  - '{project-root}/_bmad/skf/shared/scripts/skf-atomic-write.py'
10
10
  - '{project-root}/src/shared/scripts/skf-atomic-write.py'
11
+ # Resolve `{forgeTierRwHelper}` by probing `{forgeTierRwProbeOrder}` in order
12
+ # (installed SKF module path first, src/ dev-checkout fallback); first existing
13
+ # path wins. HALT if neither resolves — §6b's ccc-index registry round-trip is
14
+ # comment-preserving and has no prose fallback.
15
+ forgeTierRwProbeOrder:
16
+ - '{project-root}/_bmad/skf/shared/scripts/skf-forge-tier-rw.py'
17
+ - '{project-root}/src/shared/scripts/skf-forge-tier-rw.py'
11
18
  ---
12
19
 
13
20
  <!-- Config: communicate in {communication_language}. -->
@@ -73,7 +80,7 @@ Write these 4 files from the compiled content:
73
80
 
74
81
  **Note on `file_type: "doc"` entries** (promoted authoritative docs from step 3 §2a):
75
82
 
76
- Promoted docs are tracked in `file_entries[]` with `file_type: "doc"` for drift detection but are **NOT** copied into the skill package. The source file remains at its original location outside `{skill_package}`. Step-07 must skip any `file_entries[]` row where `file_type == "doc"` when iterating for file copy — these entries exist only for provenance tracking, not bundling. Step-07 verification (§5) also does not check for doc files in the skill package.
83
+ Promoted docs are tracked in `file_entries[]` with `file_type: "doc"` for drift detection but are **not** copied into the skill package. The source file remains at its original location outside `{skill_package}`. Step-07 must skip any `file_entries[]` row where `file_type == "doc"` when iterating for file copy — these entries exist only for provenance tracking, not bundling. Step-07 verification (§5) also does not check for doc files in the skill package.
77
84
 
78
85
  ### 3. Write Workspace Artifacts to {forge_version}
79
86
 
@@ -101,7 +108,7 @@ python3 {atomicWriteHelper} flip-link \
101
108
 
102
109
  The helper returns non-zero (exit 2) if `{skill_group}/active` already exists as a real directory or file rather than a symlink — in that case, halt with: "Refusing to flip `{skill_group}/active` — existing path is not a symlink. Investigate manually; expected a symlink pointing at a version directory."
103
110
 
104
- **Never `rm` + `ln -s` the active link manually.** The bare-rm pattern has two failure modes: (1) a concurrent reader sees a missing `active` mid-flip, and (2) a bug or typo that replaces `{skill_group}/active` with a plain directory turns the next manual `rm -rf {skill_group}/active` into data loss. The helper encapsulates both guards.
111
+ Do not `rm` + `ln -s` the active link by hand. The bare-rm pattern has two failure modes: (1) a concurrent reader sees a missing `active` mid-flip, and (2) a bug or typo that replaces `{skill_group}/active` with a plain directory turns the next manual `rm -rf {skill_group}/active` into data loss. The helper encapsulates both guards.
105
112
 
106
113
  ### 5. Verify Write Completion
107
114
 
@@ -174,10 +181,10 @@ If an entry with `name: "{name}-extraction"` already exists, replace it. Otherwi
174
181
  Write the updated forge-tier.yaml.
175
182
 
176
183
  **Error handling:**
177
- - If QMD collection creation fails: log the error, note that indexing can be retried via [SF] setup. Do NOT fail the workflow.
184
+ - If QMD collection creation fails: log the error, note that indexing can be retried via [SF] setup. Do not fail the workflow.
178
185
  - If forge-tier.yaml update fails: log the error, continue. The collection exists in QMD even if the registry entry failed.
179
186
 
180
- **IF forge tier is NOT Deep:** Skip this section silently. No messaging.
187
+ **IF forge tier is not Deep:** Skip this section silently. No messaging.
181
188
 
182
189
  ### 6b. CCC Index Registry Registration (Forge+ and Deep with ccc)
183
190
 
@@ -195,34 +202,22 @@ Ensure the source path used for extraction is indexed by ccc and registered in t
195
202
 
196
203
  **Registry update:**
197
204
 
198
- Register the indexed source path via `register-ccc-index` (comment-preserving round-trip, same pattern as §6's `register-qmd-collection`). Acquire an exclusive `flock` on `{sidecar_path}/forge-tier.yaml.lock`, then:
205
+ **Resolve `{forgeTierRwHelper}`** from `{forgeTierRwProbeOrder}`; first existing path wins. HALT if no candidate exists.
206
+
207
+ Register the indexed source path via `register-ccc-index` — a comment-preserving round-trip on `forge-tier.yaml`. This differs from §6, which mutates the registry with an inline read→modify→atomic-write under `flock`; here the helper owns the read→modify→write internally so the `ccc_index_registry` deduplication logic stays in the script. Acquire an exclusive `flock` on `{sidecar_path}/forge-tier.yaml.lock`, then:
199
208
 
200
209
  ```bash
201
210
  echo '{"source_repo":"{brief.source_repo}","path":"{source_root}","skill_name":"{name}","indexed_at":"{current ISO date}","source_workflow":"create-skill"}' \
202
- | uv run {forgeTierRw} register-ccc-index --target {forgeTierConfig}
211
+ | uv run {forgeTierRwHelper} register-ccc-index --target {forgeTierConfig}
203
212
  ```
204
213
 
205
- Deduplicates by `source_repo` + `skill_name` (NOT local `path`, which may be ephemeral). Release the lock after the command completes. If `flock` is unavailable, fall back to read-CAS-by-mtime.
214
+ Deduplicates by `source_repo` + `skill_name` (not local `path`, which may be ephemeral). Release the lock after the command completes. If `flock` is unavailable, fall back to read-CAS-by-mtime.
206
215
 
207
- **Error handling:** If ccc indexing or registry update fails, log and continue — do NOT fail the workflow.
216
+ **Error handling:** If ccc indexing or registry update fails, log and continue — do not fail the workflow.
208
217
 
209
218
  **IF `tools.ccc` is false:** Skip this section silently.
210
219
 
211
- ### 7. Menu Handling Logic
212
-
213
- **Auto-proceed step — no user interaction.**
214
-
215
- After all artifacts are written, verified, and optionally indexed into QMD, immediately load, read entire file, then execute `{nextStepFile}`.
216
-
217
- #### EXECUTION RULES:
218
-
219
- - This is an auto-proceed file writing step with no user choices
220
- - All 7 files must be written before proceeding
221
- - QMD indexing failure does NOT block proceeding
222
- - File write failures are real errors — halt, do not proceed with partial output
223
- - Proceed directly to next step after successful generation
224
-
225
- ## CRITICAL STEP COMPLETION NOTE
220
+ ### 7. Auto-Proceed
226
221
 
227
- ONLY WHEN all 7 artifact files are written, the active symlink is created, and verification is complete will you proceed to load `{nextStepFile}` for the compilation report.
222
+ No user interaction. Once all 7 files are written and verified (and optionally indexed into QMD), load `{nextStepFile}`, read it fully, then execute it. A QMD-indexing failure does not block; a file-write failure halts (§5) rather than proceeding with partial output.
228
223
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  # `shared/health-check.md` resolves relative to the SKF module root
3
- # (`_bmad/skf/` when installed, `src/` during development), NOT relative
4
- # to this step file.
3
+ # (`{project-root}/_bmad/skf/` when installed, `{project-root}/src/` during
4
+ # development), not relative to this step file.
5
5
  nextStepFile: 'shared/health-check.md'
6
6
  ---
7
7
 
@@ -40,14 +40,14 @@ Extract and report:
40
40
  - `tools`: which tools are available (gh, ast-grep, ccc, qmd)
41
41
  - `ccc_index`: ccc index state (status, indexed_path, last_indexed) — needed by step 2b
42
42
 
43
- **Apply tier override:** Read `{preferencesFile}`. If `tier_override` is set and is one of the exact valid tier values (`Quick`, `Forge`, `Forge+`, `Deep`), use it instead of the detected tier. **If `tier_override` is set but is NOT one of those four values:** log a warning — "Unknown tier_override `{value}` in preferences.yaml; falling back to detected tier `{detected_tier}`. Valid values: Quick, Forge, Forge+, Deep." — and use the detected tier. Never silently apply an unknown override value, and never map it heuristically to a tier.
43
+ **Apply tier override:** Read `{preferencesFile}`. If `tier_override` is set and is one of the exact valid tier values (`Quick`, `Forge`, `Forge+`, `Deep`), use it instead of the detected tier. **If `tier_override` is set but is not one of those four values:** log a warning — "Unknown tier_override `{value}` in preferences.yaml; falling back to detected tier `{detected_tier}`. Valid values: Quick, Forge, Forge+, Deep." — and use the detected tier. Never silently apply an unknown override value, and never map it heuristically to a tier.
44
44
 
45
45
  **Record the decision:** append an entry to the in-context `headless_decisions[]` buffer (initialize to `[]` at the start of this step if absent) whenever a non-interactive choice is made automatically — both the valid-override path AND the rejected-override path:
46
46
 
47
47
  - Valid override applied: `{step: "load-brief", gate: "tier-override", decision: "apply", value: "{tier_override}", rationale: "explicit preferences.yaml tier_override", timestamp: {ISO}}`
48
48
  - Invalid override rejected: `{step: "load-brief", gate: "tier-override", decision: "reject-invalid", value: "{tier_override}", fallback: "{detected_tier}", rationale: "tier_override not in {Quick,Forge,Forge+,Deep}", timestamp: {ISO}}`
49
49
 
50
- Step-05 §7 reads `headless_decisions[]` and emits an "Auto-Decisions" section into `evidence-report.md` so reviewers can audit every silent choice the workflow made.
50
+ These entries stay in the in-context buffer until §3 establishes the on-disk auto-decision sink and seeds it with the buffer-so-far; from then on every later gate's decision is appended to the sink as it lands (per the headless Workflow Rule). Step 5 §7 renders the sink into the evidence-report `## Auto-Decisions` table and step 6 §8 reconciles it, so reviewers can audit every silent choice even on a run long enough to compact the in-context buffer before step 5.
51
51
 
52
52
  ### 2. Discover Skill Brief
53
53
 
@@ -58,7 +58,7 @@ Step-05 §7 reads `headless_decisions[]` and emits an "Auto-Decisions" section i
58
58
 
59
59
  **If user invoked with --batch flag:**
60
60
  - Check `{sidecar_path}/batch-state.yaml` for an active batch checkpoint:
61
- - If `batch_active: true`: validate the checkpoint before trusting it. Both conditions below MUST hold:
61
+ - If `batch_active: true`: validate the checkpoint before trusting it both conditions below must hold:
62
62
  1. `0 <= current_index < len(brief_list)` — the index points inside the recorded list.
63
63
  2. `os.path.exists(brief_list[current_index])` — the brief file is still on disk.
64
64
  If both hold, load the brief at `brief_list[current_index]` (resuming a batch loop from step 8). If **either** check fails, the checkpoint is stale (briefs renamed, moved, or deleted between runs; index off the end after a partial failure). Log a warning — "Stale batch checkpoint — current_index={i}, brief_list length={n}, brief_exists={bool}. Resetting and re-discovering." — then set `batch_active: false` in `batch-state.yaml` and fall through to the no-checkpoint branch below.
@@ -95,9 +95,19 @@ The helper emits:
95
95
 
96
96
  **If `valid` is true:** continue with `brief` (the parsed object) for downstream sections. Surface any `warnings[]` to the user but do not halt.
97
97
 
98
+ **Establish the auto-decision sink (durable headless audit).** The brief is now confirmed, so create the on-disk audit sink at `{sidecar_path}/auto-decisions.jsonl` — one compact JSON object per line — and seed it with whatever is already in the in-context `headless_decisions[]` buffer (the §1 tier-override row, or nothing if none fired). This truncates any stale sink a prior brief left behind:
99
+
100
+ ```bash
101
+ : > {sidecar_path}/auto-decisions.jsonl # truncate / create empty
102
+ # then, for each entry already in headless_decisions[], append its compact JSON:
103
+ printf '%s\n' '{decision-json}' >> {sidecar_path}/auto-decisions.jsonl
104
+ ```
105
+
106
+ From here on, **every time a later gate appends an auto-decision to `headless_decisions[]`, append that same object as a line to this sink the moment it lands** (the on-landing append the headless Workflow Rule mandates). The array is tiny, so the append costs nothing and keeps a complete on-disk copy across the token-heavy step 3→5 extraction window — the point where a long component-library run can compact the in-context buffer. Step 5 §7 renders this sink into the evidence-report `## Auto-Decisions` table and step 6 §8 reconciles it, so the audit table and `auto_decision_count` stay complete even when the buffer is lost.
107
+
98
108
  **Field reference (for human readers):**
99
109
 
100
- The complete contract — required fields, optional fields, types, and rules — lives in `src/shared/scripts/schemas/skill-brief.v1.json` and the prose mirror at `src/skf-brief-skill/assets/skill-brief-schema.md`. Read those if you need to explain a specific field; do NOT restate the rules here.
110
+ The complete contract — required fields, optional fields, types, and rules — lives in `src/shared/scripts/schemas/skill-brief.v1.json` and the prose mirror at `src/skf-brief-skill/assets/skill-brief-schema.md`. Read those if you need to explain a specific field; do not restate the rules here.
101
111
 
102
112
  ### 4. Resolve Source Code Location
103
113
 
@@ -137,19 +147,7 @@ Where tier_description follows positive capability framing:
137
147
  - Forge+: "Semantic-guided precision — ccc pre-ranks files before AST extraction"
138
148
  - Deep: "Full intelligence — structural + contextual + QMD knowledge synthesis"
139
149
 
140
- ### 6. Menu Handling Logic
141
-
142
- **Auto-proceed step — no user interaction.**
143
-
144
- After initialization is complete and all data is loaded (including `target_version` if present in the brief), immediately load, read entire file, then execute `{nextStepFile}`.
145
-
146
- #### EXECUTION RULES:
147
-
148
- - This is an auto-proceed initialization step with no user choices
149
- - Proceed directly to next step after successful initialization
150
- - If any prerequisite check fails, HALT with actionable error — do NOT proceed
151
-
152
- ## CRITICAL STEP COMPLETION NOTE
150
+ ### 6. Auto-Proceed
153
151
 
154
- ONLY WHEN forge-tier.yaml is loaded, skill-brief.yaml is validated, and source code location is resolved will you proceed to load `{nextStepFile}` for ecosystem check.
152
+ No user interaction. After initialization completes and all data is loaded (including `target_version` if present), load `{nextStepFile}`, read it fully, then execute it. A failed prerequisite check above has already halted with an actionable error rather than reaching here.
155
153
 
@@ -20,7 +20,7 @@ To display the final compilation summary — skill name, version, source, export
20
20
 
21
21
  - Focus only on reporting compilation results — do not modify any files
22
22
  - Deliver structured report with confidence breakdown
23
- - Chains to the local health-check step via `{nextStepFile}` after completion (non-batch mode, or after the final batch brief) — the user-facing report is NOT the terminal step
23
+ - Chains to the local health-check step via `{nextStepFile}` after completion (non-batch mode, or after the final batch brief) — the user-facing report is not the terminal step
24
24
 
25
25
  ## MANDATORY SEQUENCE
26
26
 
@@ -72,11 +72,6 @@ If there were warnings from extraction, validation, or enrichment, display them:
72
72
 
73
73
  If no warnings, omit this section entirely.
74
74
 
75
- **Next steps:** After reviewing the report, recommend the next workflow:
76
- - **TS** (test skill) — verify completeness before export
77
- - **EX** (export) — publish to your IDE's context system
78
- - If issues were flagged, suggest **reviewing the SKILL.md** and re-running compilation
79
-
80
75
  ### 4. Suggest Next Steps
81
76
 
82
77
  "**Recommended next steps:**
@@ -125,21 +120,39 @@ End workflow. No further steps.
125
120
 
126
121
  **Resolve the schema reference:** before writing, verify that `{project-root}/src/shared/references/output-contract-schema.md` exists and is readable. Try in order: `{project-root}/src/shared/references/output-contract-schema.md`, then `{project-root}/_bmad/skf/shared/references/output-contract-schema.md` (installed-forge path).
127
122
 
128
- - **If resolved:** write the result contract per the schema — the per-run record at `{forge_version}/create-skill-result-{YYYYMMDD-HHmmss}.json` (UTC timestamp, resolution to seconds) and a copy at `{forge_version}/create-skill-result-latest.json` (stable path for pipeline consumers — copy, not symlink). Include `SKILL.md`, `context-snippet.md`, and `metadata.json` paths in `outputs` and confidence distribution in `summary`. Use `python3 {atomicWriteHelper} write --target {forge_version}/create-skill-result-{YYYYMMDD-HHmmss}.json` (stdin-piped JSON) for the per-run record, then the same helper for the `-latest.json` copy.
123
+ - **If resolved:** write the result contract per the schema — the per-run record at `{forge_version}/create-skill-result-{YYYYMMDD-HHmmss}.json` (UTC timestamp, resolution to seconds) and a copy at `{forge_version}/create-skill-result-latest.json` (stable path for pipeline consumers — copy, not symlink). Include `SKILL.md`, `context-snippet.md`, `metadata.json`, **and `{forge_version}/evidence-report.md`** paths in `outputs` (the evidence report carries the `## Auto-Decisions` audit table where every silent auto-decision is recorded — pipeline consumers follow this path to audit the run) and confidence distribution in `summary`. Also set `summary.auto_decision_count` to the number of decision rows in the reconciled evidence-report `## Auto-Decisions` table (0 when the run was interactive and the section holds only the no-auto-decisions line) so a consumer can tell from the result JSON alone whether any gate auto-resolved. Count the persisted rows — the durable audit record step 6 §8 reconciled from disk — rather than the in-context `headless_decisions[]` length, so the count matches the table even if a long headless run compacted the buffer. Use `python3 {atomicWriteHelper} write --target {forge_version}/create-skill-result-{YYYYMMDD-HHmmss}.json` (stdin-piped JSON) for the per-run record, then the same helper for the `-latest.json` copy.
129
124
 
130
125
  - **If neither candidate path resolves:** skip the result-contract write entirely. Append a warning to `evidence-report.md`: "Result contract skipped — `shared/references/output-contract-schema.md` could not be resolved at either candidate path." Then set `validation_status: 'schema-unavailable'` in `metadata.json` (and re-write metadata.json via `skf-atomic-write.py write`). Pipeline consumers will observe the missing `-latest.json` and the metadata flag.
131
126
 
132
- ### 6. Chain to Health Check
127
+ **Post-completion hook (optional).** After the result JSON and `metadata.json` are finalized, if `{onCompleteCommand}` is non-empty (resolved at SKILL.md On Activation §3 from `workflow.on_complete`), invoke it:
133
128
 
134
- **If not batch mode (or all batch briefs complete):**
129
+ ```bash
130
+ {onCompleteCommand} --result-path={forge_version}/create-skill-result-latest.json
131
+ ```
135
132
 
136
- ONLY WHEN the compilation report, warnings (if any), recommended next steps, and result contract have been handled will you then load, read the full file, and execute `{nextStepFile}`. The health-check step is the true terminal step do not stop here even though the report reads as final.
133
+ Log success or failure to `workflow_warnings[]` but never fail the workflow on a hook error the skill is already written and the result contract is final. The hook runs last so a git-add, registry registration, notifier, or downstream-skill chain sees a complete package. When `{onCompleteCommand}` is empty (bundled default), skip the invocation entirely.
137
134
 
138
- **If batch mode with remaining briefs:** Skip the health-check chain — load and execute `references/load-brief.md` for the next brief instead. The health check runs only after the final brief in the batch.
135
+ ### Result Contract on HARD HALT
139
136
 
140
- ## CRITICAL STEP COMPLETION NOTE
137
+ The success-variant contract above is only reached at step 8. The ~10 HARD HALT conditions in steps 1–7 (forge-config missing, no brief, brief invalid, source not found, prerequisite failure in load-brief; atomic/detect/auth helper unresolved and the Tier-1 split-count drop in extract/validate; the non-symlink active-link refusal in generate-artifacts) otherwise print a human string and exit with **no machine-readable outcome** — a pipeline polling `create-skill-result-latest.json` cannot distinguish "halted at brief-invalid" from "still running" from "crashed". Mirror skf-quick-skill: **whenever `{headless_mode}` is true, every HARD HALT must surface an error-variant result before exiting.**
138
+
139
+ **For every HARD HALT under `{headless_mode}` (regardless of phase)** — emit a single line on **stderr** (one line, no pretty-print; matches the prefix-and-envelope convention used by `skf-emit-result-envelope.py`):
140
+
141
+ ```
142
+ SKF_CREATE_SKILL_RESULT_JSON: {"status":"failed","phase":"<step-slug>","outputs":{},"summary":{"halt_reason":"<short class>","evidence_report":"<path-or-null>"},"skill_package":"<path-or-null>"}
143
+ ```
141
144
 
142
- This step chains to the local health-check step (`{nextStepFile}`), which in turn delegates to `shared/health-check.md` (unless batch mode loops back to step 1). After the health check completes, the create-skill workflow is fully done.
145
+ Use `status: "partial"` instead of `"failed"` when artifacts were already staged or promoted before the HALT (i.e. the HALT fired at step 7 generate-artifacts after some files were written); use `"failed"` for HALTs before any artifact exists on disk (steps 1–6).
143
146
 
144
- For batch mode: load and execute `references/load-brief.md` for remaining briefs via sidecar checkpoint. Health check runs only after the last brief.
147
+ **Additionally, when `{forge_version}` is resolved** (HALT at step 7 onward, where the staging tree has been promoted) — write the same JSON object (without the `SKF_CREATE_SKILL_RESULT_JSON: ` prefix) to disk at `{forge_version}/create-skill-result-{YYYYMMDD-HHmmss}.json` and a copy at `{forge_version}/create-skill-result-latest.json` (copy, not symlink) via `python3 {atomicWriteHelper} write`, so consumers that hardcode the `-latest.json` path see a deterministic file even on failed runs. Set `summary.evidence_report` to `{forge_version}/evidence-report.md` whenever that file exists, so the consumer can still reach the `## Auto-Decisions` audit on a failed run. HALTs before step 7 cannot write to disk because `{forge_version}` is only created at step 7 §1; for those, the stderr envelope is the contract and `summary.evidence_report` is `null`.
148
+
149
+ When `{headless_mode}` is false, HARD HALTs display their human message only — no envelope is emitted.
150
+
151
+ ### 6. Chain to Health Check
152
+
153
+ **If not batch mode (or all batch briefs complete):**
154
+
155
+ Only after the compilation report, warnings (if any), recommended next steps, and result contract have been handled do you load `{nextStepFile}`, read it fully, and execute it. The health-check step is the true terminal step — do not stop here even though the report reads as final.
156
+
157
+ **If batch mode with remaining briefs:** Skip the health-check chain — load and execute `references/load-brief.md` for the next brief instead. The health check runs only after the final brief in the batch.
145
158
 
@@ -123,7 +123,7 @@ If `source_repo` is a remote URL (GitHub URL or owner/repo format) AND tier is F
123
123
 
124
124
  If fetch or checkout fails, proceed to the **ephemeral fallback** (step 5).
125
125
 
126
- **If `{workspace_repo_path}/.git/` does NOT exist (workspace miss):**
126
+ **If `{workspace_repo_path}/.git/` does not exist (workspace miss):**
127
127
 
128
128
  Clone the repository into the workspace for persistent reuse. Create the parent directory first (`{workspace_root}/repos/{host}/{owner}/`):
129
129
 
@@ -131,7 +131,7 @@ If `source_repo` is a remote URL (GitHub URL or owner/repo format) AND tier is F
131
131
  mkdir -p "{workspace_root}/repos/{host}/{owner}/"
132
132
  ```
133
133
 
134
- Clone with the appropriate branch flag — `--branch` is only valid for real branch/tag names, not for `HEAD`. **Do NOT pass `--single-branch`** here: workspace clones are persistent and re-used for future forges with different `source_ref` values (a later run may target a different tag or branch). A single-branch workspace clone would force every re-forge with a new ref to fall through to ephemeral cloning, defeating the workspace cache:
134
+ Clone with the appropriate branch flag — `--branch` is only valid for real branch/tag names, not for `HEAD`. **Do not pass `--single-branch`** here: workspace clones are persistent and re-used for future forges with different `source_ref` values (a later run may target a different tag or branch). A single-branch workspace clone would force every re-forge with a new ref to fall through to ephemeral cloning, defeating the workspace cache:
135
135
 
136
136
  ```
137
137
  # If source_ref is a real branch or tag (not HEAD/null):
@@ -154,7 +154,7 @@ If `source_repo` is a remote URL (GitHub URL or owner/repo format) AND tier is F
154
154
  - `remote_clone_path = {workspace_repo_path}`
155
155
  - `remote_clone_type = "workspace"`
156
156
 
157
- **Scope filtering:** Since the workspace uses a full checkout (no sparse-checkout), apply `include_patterns` and `exclude_patterns` from the brief as **file-level filters** when building the extraction file list. Always-included root files (`pyproject.toml`, `package.json`, `Cargo.toml`, `go.mod`, `setup.py`, `setup.cfg`, `VERSION`) are exempt from pattern filtering.
157
+ **Scope filtering:** Since the workspace uses a full checkout (no sparse-checkout), apply `include_patterns` and `exclude_patterns` from the brief as **file-level filters** when building the extraction file list. Always-included root files (`pyproject.toml`, `package.json`, `Cargo.toml`, `go.mod`, `pom.xml`, `build.gradle`, `build.gradle.kts`, `Package.swift`, `setup.py`, `setup.cfg`, `VERSION`) are exempt from pattern filtering.
158
158
 
159
159
  5. **Ephemeral fallback (on any workspace failure):**
160
160
 
@@ -216,7 +216,7 @@ Also store `source_ref` in context (from tag resolution above, or `HEAD` if no t
216
216
 
217
217
  ## Version Reconciliation (all tiers, source mode only)
218
218
 
219
- **Target version override:** If `brief.target_version` is present, use it as the authoritative version for the skill. Do NOT warn about a brief-vs-source version mismatch — the user intentionally specified this version. Set the working version to `brief.target_version` and skip the rest of this reconciliation section. The `target_version` field indicates deliberate user intent (e.g., targeting an older version, or providing the version for a docs-only skill).
219
+ **Target version override:** If `brief.target_version` is present, use it as the authoritative version for the skill. Do not warn about a brief-vs-source version mismatch — the user intentionally specified this version. Set the working version to `brief.target_version` and skip the rest of this reconciliation section. The `target_version` field indicates deliberate user intent (e.g., targeting an older version, or providing the version for a docs-only skill).
220
220
 
221
221
  **If `source_type: "docs-only"`:** skip this section — no source files exist to reconcile.
222
222
 
@@ -1,5 +1,12 @@
1
1
  ---
2
2
  nextStepFile: 'step-doc-rot.md'
3
+ # Resolve `{shardBodyHelper}` by probing `{shardBodyProbeOrder}` in order
4
+ # (installed SKF module path first, src/ dev-checkout fallback); first existing
5
+ # path wins. HALT if neither resolves — hand line-counting is the least reliable
6
+ # deterministic op and would silently ship an over-budget body or wrongly HALT.
7
+ shardBodyProbeOrder:
8
+ - '{project-root}/_bmad/skf/shared/scripts/skf-shard-body.py'
9
+ - '{project-root}/src/shared/scripts/skf-shard-body.py'
3
10
  ---
4
11
 
5
12
  <!-- Config: communicate in {communication_language}. -->
@@ -15,42 +22,66 @@ Proactively reduce oversized SKILL.md bodies to under 400 lines by extracting Ti
15
22
  - Auto-proceed step — no user interaction required
16
23
  - Graceful skip — if body is under threshold, proceed without modification
17
24
  - Only extract Tier 2 sections (identified by `## Full` heading prefix)
18
- - Tier 1 sections must NEVER be moved to references/
25
+ - Tier 1 sections stay inline moving one to references/ would break the standalone SKILL.md the two-tier design guarantees
19
26
  - Do not modify frontmatter — only body content and references/ directory
20
27
  - Do not invoke `npx skill-check split-body` — this step uses direct extraction
21
28
  - Do not invoke the Description Guard Protocol — frontmatter is untouched
22
29
 
23
30
  ## MANDATORY SEQUENCE
24
31
 
32
+ ### §0. Run the Shard Script (primary path)
33
+
34
+ The counting, boundary detection, size-sort, file writes, and blockquote replacement described in §1–§5 are fully deterministic and run every invocation — so a script owns them, not the model. Do not count body lines or extract sections by hand when the script ran.
35
+
36
+ **Resolve `{shardBodyHelper}`** from `{shardBodyProbeOrder}`; first existing path wins. HALT if no candidate exists.
37
+
38
+ Run:
39
+
40
+ ```bash
41
+ uv run {shardBodyHelper} <staging-skill-dir>/SKILL.md --budget 400
42
+ ```
43
+
44
+ The script performs everything §1–§5 document — it counts the body between the frontmatter close and EOF, enumerates the `## Full` Tier 2 sections, extracts the largest first to `references/` until the body fits, writes the extracted files and the trimmed SKILL.md through the atomic-write helper, rewrites each section as a cross-reference blockquote, and checks Tier 1 preservation and cross-reference integrity. Read its JSON and set context directly:
45
+
46
+ - **`action: "skip"`** → the body was already within budget. Log `"auto-shard: skipped (body {body_lines_before} lines)"`, set `auto_shard_triggered: false`, `sections_extracted: []`, `body_lines_before`/`body_lines_after` from the report, then skip to §6.
47
+ - **`action: "shard"`** → set `auto_shard_triggered: true` and copy `sections_extracted`, `body_lines_before`, `body_lines_after` straight from the report.
48
+ - **HALT** if `tier1_preserved` is false: `"Auto-shard removed Tier 1 section(s) {tier1_missing}. Aborting."`
49
+ - **HALT** if `xref_ok` is false: `"Auto-shard cross-references did not resolve. Aborting."`
50
+ - If `under_budget` is false, selective Tier 2 extraction alone could not bring the body under budget (rare — Tier 1 itself exceeds ~300 lines). Apply the §4 editing-judgment trim, then continue.
51
+
52
+ Log: `"auto-shard: {N} sections extracted, body reduced from {body_lines_before} to {body_lines_after} lines"`, then proceed to §6.
53
+
54
+ **Manual fallback (only when `uv`/Python is unavailable):** perform §1–§5 by hand as documented below — they describe exactly what the script does.
55
+
25
56
  ### §1. Count Body Lines
26
57
 
27
- Count all lines in the staging SKILL.md between the frontmatter closing `---` and EOF. Exclude trailing blank lines from the count. Store as `body_line_count`.
58
+ The script counts all lines in the staging SKILL.md between the frontmatter closing `---` and EOF, excluding trailing blank lines, and reports the total as `body_lines_before`.
28
59
 
29
60
  ```
30
61
  body_lines_before = body_line_count
31
62
  ```
32
63
 
33
- **IF `body_line_count` <= 400:**
64
+ **IF `body_line_count` <= 400:** the script emits `action: "skip"` and writes nothing —
34
65
  - Log: `"auto-shard: skipped (body {body_line_count} lines)"`
35
66
  - Set context: `auto_shard_triggered: false`, `sections_extracted: []`, `body_lines_before: {body_line_count}`, `body_lines_after: {body_line_count}`
36
67
  - Skip to §6 (Auto-Proceed)
37
68
 
38
- **ELSE:** Proceed to §2.
69
+ **ELSE:** the script proceeds to §2.
39
70
 
40
71
  ### §2. Selective Shard — Tier 2 Extraction
41
72
 
42
- Identify Tier 2 sections by their `## Full` heading prefix:
73
+ The script identifies Tier 2 sections by their `## Full` heading prefix:
43
74
  - `## Full API Reference` → `references/full-api-reference.md`
44
75
  - `## Full Type Definitions` → `references/full-type-definitions.md`
45
76
  - `## Full Integration Patterns` → `references/full-integration-patterns.md`
46
77
 
47
- Sort identified sections by line count descending (extract largest first).
78
+ Sections are sorted by line count descending (largest first).
48
79
 
49
80
  **FOR EACH Tier 2 section (largest first):**
50
81
 
51
82
  1. Extract the full section content (from `## Full` heading to the next `##` heading or EOF)
52
83
  2. Derive the reference filename from the heading: kebab-case (as shown above)
53
- 3. Write the extracted content (preserving the `##` heading) to `<staging-skill-dir>/references/{filename}`
84
+ 3. Write the extracted content (preserving the `##` heading) to `<staging-skill-dir>/references/{filename}` via the atomic-write helper
54
85
  4. Replace the extracted section in SKILL.md with a cross-reference blockquote:
55
86
  ```markdown
56
87
  > See [Full API Reference](references/full-api-reference.md)
@@ -58,44 +89,40 @@ Sort identified sections by line count descending (extract largest first).
58
89
  5. Re-count body lines
59
90
  6. **IF `body_line_count` <= 400:** stop extracting, proceed to §3
60
91
 
61
- Track: `sections_extracted: [{heading names}]`
92
+ The report's `sections_extracted: [{heading, file, lines}]` records exactly which sections were pulled.
62
93
 
63
94
  ### §3. Tier 1 Preservation Check
64
95
 
65
- Verify ALL Tier 1 sections remain inline in SKILL.md after extraction. Check for these headings:
96
+ The script verifies ALL Tier 1 sections that were inline before extraction remain inline in SKILL.md afterward. These headings:
66
97
 
67
98
  - `## Overview`
68
99
  - `## Quick Start`
69
100
  - `## Common Workflows`
70
101
  - `## Key API Summary` (or `## Component Catalog` for component-library scope)
71
- - `## Migration & Deprecation Warnings` (conditional — only check if it was present before extraction)
102
+ - `## Migration & Deprecation Warnings` (conditional — only checked if it was present before extraction)
72
103
  - `## Key Types`
73
104
  - `## Architecture at a Glance`
74
- - `## CLI` (conditional — only check if present before extraction)
75
- - `## Scripts & Assets` (conditional — only check if present before extraction)
76
- - `## Manual Sections` (conditional — only check if present before extraction)
105
+ - `## CLI` (conditional — only checked if present before extraction)
106
+ - `## Scripts & Assets` (conditional — only checked if present before extraction)
107
+ - `## Manual Sections` (conditional — only checked if present before extraction)
108
+
109
+ The result surfaces as `tier1_preserved` (with any pulled headings in `tier1_missing`).
77
110
 
78
- **IF any Tier 1 section is missing after extraction:**
111
+ **IF `tier1_preserved` is false:**
79
112
  HALT: `"Auto-shard removed Tier 1 section {name}. Aborting."`
80
113
 
81
114
  ### §4. Post-Shard Validation
82
115
 
83
- Re-count body lines after all Tier 2 sections have been extracted.
84
-
85
- ```
86
- body_lines_after = body_line_count
87
- ```
116
+ The report's `body_lines_after` is the recount after all extraction. `under_budget` is true when the body now fits.
88
117
 
89
- **IF `body_line_count` > 400 after all Tier 2 sections extracted:**
118
+ **IF `under_budget` is false** (body still > 400 after all Tier 2 sections extracted — this is the one genuine editing-judgment step):
90
119
  - Trim oversized Tier 1 sections: reduce `## Key API Summary` and `## Architecture at a Glance` content to fit within the 400-line budget
91
- - Do NOT move any Tier 1 section to references/
92
- - Re-count and update `body_lines_after`
120
+ - Do not move any Tier 1 section to references/
121
+ - Re-run `{shardBodyHelper}` (or re-count) and update `body_lines_after`
93
122
 
94
123
  ### §5. Cross-Reference Integrity
95
124
 
96
- **FOR EACH extracted reference file:**
97
- 1. Verify the file exists at `<staging-skill-dir>/references/{filename}`
98
- 2. Verify the cross-reference blockquote in SKILL.md contains a link resolving to the file
125
+ The script verifies, for each extracted reference file, that the file exists at `<staging-skill-dir>/references/{filename}` and that the cross-reference blockquote in SKILL.md links to it — reported as `xref_ok`. HALT if `xref_ok` is false.
99
126
 
100
127
  Log: `"auto-shard: {N} sections extracted, body reduced from {body_lines_before} to {body_lines_after} lines"`
101
128
 
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  nextStepFile: 'validate.md'
3
+ scanDocRotHelper: 'scripts/scan-doc-rot.py'
3
4
  ---
4
5
 
5
6
  <!-- Config: communicate in {communication_language}. -->
@@ -8,7 +9,7 @@ nextStepFile: 'validate.md'
8
9
 
9
10
  ## STEP GOAL:
10
11
 
11
- Scan feeder artifacts for doc-rot correction indicators and annotate the compiled SKILL.md with `## CORRECTION` blocks. Matching is grep-based and deterministic — no AI judgment is used for detection.
12
+ Scan feeder artifacts for doc-rot correction indicators and annotate the compiled SKILL.md with `## CORRECTION` blocks. Matching is a deterministic substring grep performed by `{scanDocRotHelper}` (`scripts/scan-doc-rot.py`) — no AI judgment is used for detection. The prompt keeps only the genuine judgment the script cannot make: enriching each match's `affected` symbol (§2) and choosing where each `## CORRECTION` block goes (§3).
12
13
 
13
14
  ## Rules
14
15
 
@@ -23,12 +24,12 @@ Scan feeder artifacts for doc-rot correction indicators and annotate the compile
23
24
 
24
25
  ### §1. Locate Feeder Artifacts
25
26
 
26
- Identify the feeder artifacts in the staging directory for the current skill:
27
+ Identify the feeder artifacts in the **staging directory** for the current skill. This step (5c) runs **before** step 7 promotes the staging tree to `{forge_data_folder}/{skill-name}/{version}/`, so the feeder artifacts only exist under the staging path compile (step 5 §1a) wrote — reading the not-yet-promoted `{forge_data_folder}` path would make every match a no-op:
27
28
 
28
- 1. **Evidence report:** `{forge_data_folder}/{skill-name}/{version}/evidence-report.md`
29
- 2. **Provenance map:** `{forge_data_folder}/{skill-name}/{version}/provenance-map.json` — focus on T2/T3 entries with temporal annotations
29
+ 1. **Evidence report:** `_bmad-output/{skill-name}/evidence-report.md`
30
+ 2. **Provenance map:** `_bmad-output/{skill-name}/provenance-map.json` — focus on T2/T3 entries with temporal annotations
30
31
  3. **Temporal context:** changelogs, migration guides, and issue/PR data fetched by step 3b and enriched by step 4 (available in workflow context)
31
- 4. **Compiled SKILL.md:** the staged SKILL.md itself — check for `[QMD:...]` or `[DOC:...]` annotations referencing corrections
32
+ 4. **Compiled SKILL.md:** the staged `_bmad-output/{skill-name}/SKILL.md` itself — check for `[QMD:...]` or `[DOC:...]` annotations referencing corrections. **Do not treat its own `## Migration & Deprecation Warnings` section (§4b) as a correction source:** compile (step 5 §4b) already authored that section from the same T2-future annotations, so its bullets are already-surfaced corrections — §2 discards matches that land inside it.
32
33
 
33
34
  For each artifact, attempt to load its content. If an artifact does not exist or is empty, skip it — this is not an error.
34
35
 
@@ -36,7 +37,31 @@ Store: `feeder_artifacts_scanned: [{list of artifacts that were loaded}]`
36
37
 
37
38
  ### §2. Grep for Correction Indicators
38
39
 
39
- Scan each loaded feeder artifact for the following correction patterns. All matches are **case-insensitive substring matches** no regex interpretation, no semantic analysis.
40
+ The scan is deterministic plumbing — a fixed-table substring grep with one correct answer per input — so it runs in `{scanDocRotHelper}`, **not** in-prompt. Do not hand-grep the feeder artifacts: identical feeders must yield identical `correction_matches`, and only the script guarantees that across multi-KB inputs. Pass the `## Migration & Deprecation Warnings`-bearing compiled SKILL.md (feeder #4) as `--skill-md` and every other loaded feeder as a positional argument:
41
+
42
+ ```bash
43
+ uv run {scanDocRotHelper} \
44
+ --skill-md _bmad-output/{skill-name}/SKILL.md \
45
+ _bmad-output/{skill-name}/evidence-report.md \
46
+ _bmad-output/{skill-name}/provenance-map.json \
47
+ _bmad-output/{skill-name}-temporal/*.md
48
+ ```
49
+
50
+ (Pass whichever of the §1 feeder paths actually exist — the script skips any that are missing or empty, and reports the loaded set in `scanned`.)
51
+
52
+ The script emits `{scanned: [...], matches: [...], match_count, excluded_count}` on stdout. Each entry in `matches` is a match record with the deterministic fields the script owns:
53
+
54
+ - `source`: the feeder artifact path where the match was found
55
+ - `pattern`: the specific pattern string that matched
56
+ - `category`: the category label
57
+ - `context_line`: the line containing the match
58
+ - `line_number`: the 1-indexed line the match sits on
59
+
60
+ Read `matches` into `correction_matches: [{match records}]`. Then add the one judgment field the script cannot infer:
61
+
62
+ - `affected`: the function name, API, or section the correction relates to — enrich each record from surrounding context (use the `[QMD:...]`/`[DOC:...]` annotations and nearby symbols); if not identifiable, set to `"unknown"`.
63
+
64
+ **What the script does (the contract it implements — keep this table and the script's `PATTERN_TABLE` in lockstep):** it matches every feeder line against the following correction patterns. All matches are **case-insensitive substring matches** — no regex interpretation, no semantic analysis.
40
65
 
41
66
  | Pattern | Category |
42
67
  |---------|----------|
@@ -54,16 +79,9 @@ Scan each loaded feeder artifact for the following correction patterns. All matc
54
79
  | `migration required` | Migration |
55
80
  | `signature changed` | Signature change |
56
81
 
57
- For each match, record:
58
- - `source`: the feeder artifact path or citation where the match was found
59
- - `pattern`: the specific pattern string that matched
60
- - `category`: the category from the table above
61
- - `context_line`: the line or excerpt containing the match
62
- - `affected`: the function name, API, or section the correction relates to (extract from surrounding context if identifiable; otherwise set to `"unknown"`)
63
-
64
- Store all matches as `correction_matches: [{match records}]`
82
+ **Exclusion drop already-surfaced §4b corrections (deterministic, no AI judgment, applied inside the script before it emits):** the script discards any match whose `source` is the compiled SKILL.md (feeder #4) **and** whose `context_line` sits inside that file's own `## Migration & Deprecation Warnings` section — i.e. on a line at or after the `## Migration & Deprecation Warnings` heading and before the next `##` heading (`excluded_count` reports how many it dropped). Compile (step 5 §4b) authored that section from the same T2-future annotations, so re-emitting its bullets as `## CORRECTION` blocks in §3 would duplicate already-surfaced content verbatim. This is a positional heading-boundary check on text already loaded, not a semantic assessment. Set `feeder_artifacts_scanned` from the script's `scanned` list.
65
83
 
66
- **IF `correction_matches` is empty:**
84
+ **IF `correction_matches` is empty** (the script returned `match_count: 0`, or the run had no feeder files to pass)**:**
67
85
  - Log: `"doc-rot: skipped (no correction indicators found in feeder artifacts)"`
68
86
  - Set context: `doc_rot_triggered: false`, `corrections_added: 0`
69
87
  - Skip to §5 (Auto-Proceed)
@@ -1,5 +1,12 @@
1
1
  ---
2
2
  nextStepFile: 'step-auto-shard.md'
3
+ # Resolve `{detectDocsHelper}` by probing `{detectDocsProbeOrder}` in order
4
+ # (installed SKF module path first, src/ dev-checkout fallback); first existing
5
+ # path wins. HALT if neither resolves — §2 has no prose fallback for doc-source
6
+ # detection (Pages-API walk, docs/ folder scan, content hashing).
7
+ detectDocsProbeOrder:
8
+ - '{project-root}/_bmad/skf/shared/scripts/skf-detect-docs.py'
9
+ - '{project-root}/src/shared/scripts/skf-detect-docs.py'
3
10
  ---
4
11
 
5
12
  <!-- Config: communicate in {communication_language}. -->
@@ -21,7 +28,7 @@ Record detected documentation pages and README with content hashes in metadata.j
21
28
 
22
29
  ### 1. Check for Upstream Doc Detection Results
23
30
 
24
- Check if `doc_detection_results` is already populated in the workflow context (set by BS auto-brief in the deepwiki pipeline).
31
+ Check if `doc_detection_results` is already populated in the workflow context (set by BS auto-brief in the forge-auto pipeline).
25
32
 
26
33
  - **If upstream results exist:** use them directly, skip to step 3.
27
34
  - **If no upstream results:** continue to step 2.
@@ -37,10 +44,12 @@ Check that `{source_repo}` is available from the skill brief.
37
44
 
38
45
  **If `{source_repo}` is available:**
39
46
 
47
+ **Resolve `{detectDocsHelper}`** from `{detectDocsProbeOrder}`; first existing path wins. HALT if no candidate exists.
48
+
40
49
  Invoke the detect-docs script:
41
50
 
42
51
  ```bash
43
- uv run python src/shared/scripts/skf-detect-docs.py \
52
+ uv run {detectDocsHelper} \
44
53
  --repo-url {source_repo} \
45
54
  [--local-path {source_path}] \
46
55
  [--skip-pages-api]
@@ -85,10 +94,10 @@ Map each detection result to the `doc_sources` schema:
85
94
  Field mapping from `skf-detect-docs.py` output:
86
95
  - `url` ← `url` (direct copy)
87
96
  - `detected_via` ← `detected_via` (direct copy; or `"readme_always"` for the mandatory README entry)
88
- - `content_hash` ← `content_hash` (direct copy, already in `sha256:{hexdigest}` format from story 1.2)
97
+ - `content_hash` ← `content_hash` (direct copy, already in `sha256:{hexdigest}` format)
89
98
  - `recorded_at` ← generated at step execution time (ISO-8601 with timezone)
90
99
 
91
- Note: `content_type` from detect-docs output is NOT carried into `doc_sources`.
100
+ Note: `content_type` from detect-docs output is not carried into `doc_sources`.
92
101
 
93
102
  ### 5. Update metadata.json
94
103
 
@@ -82,7 +82,7 @@ Set `{ccc_discovery: []}` in context.
82
82
 
83
83
  Display: "CCC discovery unavailable — proceeding with standard extraction."
84
84
 
85
- Do NOT halt. This is not an error.
85
+ Do not halt. This is not an error.
86
86
 
87
87
  **If search returns empty results:**
88
88
 
@@ -92,16 +92,5 @@ No message needed — empty results are normal for small or highly focused libra
92
92
 
93
93
  ### 5. Auto-Proceed
94
94
 
95
- Immediately load, read entire file, then execute `{nextStepFile}`.
96
-
97
- #### EXECUTION RULES:
98
-
99
- - This is an auto-proceed step with no user choices
100
- - Quick/Forge tiers skip directly with no output
101
- - Forge+/Deep with ccc displays brief discovery summary then auto-proceeds
102
- - CCC failures do not halt — degrade and proceed
103
-
104
- ## CRITICAL STEP COMPLETION NOTE
105
-
106
- ONLY WHEN discovery is complete (Forge+/Deep with ccc) or the step is skipped (Quick/Forge or ccc unavailable) will you proceed to load `{nextStepFile}` for AST extraction.
95
+ No user interaction. Load `{nextStepFile}`, read it fully, then execute it. CCC failures degrade and proceed — they never halt.
107
96