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
@@ -25,6 +25,21 @@ buildChangeManifestProbeOrder:
25
25
  provenanceGapDispatchProbeOrder:
26
26
  - '{project-root}/_bmad/skf/shared/scripts/skf-provenance-gap-dispatch.py'
27
27
  - '{project-root}/src/shared/scripts/skf-provenance-gap-dispatch.py'
28
+ # Resolve `{detectScriptsAssetsHelper}` to the first existing path; HALT if
29
+ # neither candidate exists. §Category D uses `detect` to walk the current
30
+ # source tree for scripts/assets (directory conventions, shebang signals,
31
+ # `package.json` `bin` entry-points, asset filename patterns) so NEW_FILE
32
+ # detection mirrors create-skill §4c exactly. Falling back to prose-driven
33
+ # file walking would let the LLM drift on the heuristic list and miss new
34
+ # scripts/assets at deeper directory depths — and on installed modules
35
+ # (no `src/` tree) the LLM would otherwise guess a non-existent path.
36
+ detectScriptsAssetsProbeOrder:
37
+ - '{project-root}/_bmad/skf/shared/scripts/skf-detect-scripts-assets.py'
38
+ - '{project-root}/src/shared/scripts/skf-detect-scripts-assets.py'
39
+ # `{newFileDiffHelper}` derives NEW_FILE (inventory source_files not in the
40
+ # provenance map, minus [MANUAL] paths) — the set-difference §Category D would
41
+ # otherwise ask the model to compute by hand. Per-skill helper, always bundled.
42
+ newFileDiffHelper: 'scripts/skf-new-file-diff.py'
28
43
  ---
29
44
 
30
45
  <!-- Config: communicate in {communication_language}. -->
@@ -40,7 +55,7 @@ Compare current source code state against the provenance map to produce a comple
40
55
  - Focus only on detecting and classifying changes — do not extract or merge
41
56
  - Use subprocess Pattern 4 (parallel) when available; if unavailable, compare sequentially
42
57
 
43
- ## MANDATORY SEQUENCE
58
+ ## Steps
44
59
 
45
60
  ### 0. Check for Test Report Input (Gap-Driven Mode)
46
61
 
@@ -94,7 +109,7 @@ Read the source directory at `{source_root}` and build a current file inventory:
94
109
 
95
110
  ### 1b. Discovered Authoritative Files Protocol (Mirror)
96
111
 
97
- **Purpose:** mirror `skf-create-skill` §2a into update-skill. `skf-create-skill` §2a catches authoritative AI documentation files (`llms.txt`, `AGENTS.md`, `.cursorrules`, etc.) during **creation**. But a project may add these files *after* the skill was created — for example, an upstream project adopts an `llms.txt` convention six months into development. Without this mirror, update-skill would either miss the new file entirely (if it doesn't match the provenance map's file patterns) or classify it as a generic ADDED file in §2 Category A with no authoritative-file treatment. The mirror surfaces the discovery with the same P/S/U prompt create-skill uses, honoring any prior amendments.
112
+ **Purpose:** mirror `skf-create-skill` §2a into update-skill. `skf-create-skill` §2a catches authoritative AI documentation files (`llms.txt`, `AGENTS.md`, `.cursorrules`, etc.) during **creation**, but a project may add these files *after* the skill was created. Without this mirror, update-skill would either miss the new file entirely (if it doesn't match the provenance map's file patterns) or classify it as a generic ADDED file in §2 Category A with no authoritative-file treatment. The mirror surfaces the discovery with the same P/S/U prompt create-skill uses, honoring any prior amendments.
98
113
 
99
114
  **Skip this section entirely if:**
100
115
 
@@ -166,11 +181,11 @@ Read the source directory at `{source_root}` and build a current file inventory:
166
181
 
167
182
  **Record for evidence report:** the update-skill evidence report appends `authoritative_files_mirror: {candidates: N, promoted: P, skipped: S, pre_decided: A, already_tracked: T, decisions: [{path, action, heuristic, reason}]}`.
168
183
 
169
- **Interaction with §2 change detection:** promoted docs live in `promoted_docs_new[]`, NOT in the change manifest. But §2 Category A ("files in source but not in provenance map → ADDED") would still find the promoted doc files on disk and classify them as ADDED if nothing prevents it. The coordination mechanism is an explicit pre-filter exclusion set built in §2.0 (below) that every Category A subprocess worker receives as an input before it starts scanning. See §2.0 for the exact contract. The exclusion set is the only mechanism guaranteeing that parallel subprocesses cannot double-count `promoted_docs_new[]` paths — prose-level "skip any path" instructions cannot cross subprocess boundaries.
184
+ **Interaction with §2 change detection:** promoted docs live in `promoted_docs_new[]`, not in the change manifest. §2.0's `change_detection_excludes` set (built below) is what stops §2 Category A from re-classifying them as ADDED it is the only coordination that survives across the parallel Category A subprocesses.
170
185
 
171
186
  ### 1c. Major-Version Scope Reconciliation (Pre-Detection)
172
187
 
173
- **Purpose:** When upstream undergoes a paradigm shift (rebrand, package restructure, major-version rewrite), the brief's `scope.include` no longer reflects the real public API. §1b handles new authoritative-doc files; §1c handles new **code globs** that fall outside the original scope. Without it, update-skill silently misses the new surface and pays the gap cost on every future update — the cocoindex `0.3.37 → 1.0.0` and cognee `0.5.8 → 1.0.0` runs are existence proofs that this case is real and recurring.
188
+ **Purpose:** §1b handles new authoritative-doc files; §1c handles new **code globs** that fall outside the original scope when upstream restructures (rebrand, package restructure, major-version rewrite) so the brief's `scope.include` no longer reflects the real public API. Without it, update-skill silently misses the new public surface and pays the gap cost on every future update.
174
189
 
175
190
  **Skip this section entirely if:**
176
191
 
@@ -222,7 +237,7 @@ Read the source directory at `{source_root}` and build a current file inventory:
222
237
  - `status: "pre-decided-demoted"` → record as `pre_decided`; do not re-prompt (`prior_action` ∈ `demoted-include`, `demoted-exclude`).
223
238
  - `status: "unresolved"` → continue to step 4 (user prompt).
224
239
 
225
- **Note:** the Out-of-Scope section is an optional audit-skill output. `skf-audit-skill` does not currently discover new files (per `src/skf-audit-skill/references/re-index.md` — new-file detection is the responsibility of update-skill). The section is a forward-looking integration point: manual additions or a future audit-skill enhancement populate it.
240
+ **Note:** the Out-of-Scope section is an optional audit-skill output and is often absent or empty — new-file detection is update-skill's job (§1b/§2.2), not audit-skill's so the `no-report` / `no-candidates` paths above are the common case.
226
241
 
227
242
  3. **Prompt for each unresolved candidate.** Present the same menu shape as §1b:
228
243
 
@@ -305,7 +320,20 @@ Launch subprocesses in parallel that compare source state against provenance map
305
320
 
306
321
  **Category C — Rename detection:**
307
322
  - Cross-reference deleted files/exports with added files/exports
308
- - If content similarity > 80%: classify as RENAMED instead of deleted+added. **Similarity mechanism by tier:** Quick: compare file size ratio (within 20%) and export name overlap (>70% of exports match by name). Forge and above: use ast-grep to compare export signatures between the deleted and added files. Forge+/Deep: use CCC semantic similarity when available
323
+ - If content similarity > 80% (fixed bundled threshold — not configurable): classify as RENAMED instead of deleted+added. **Similarity mechanism by tier:** Quick: compare file size ratio (within 20%) and export name overlap (>70% of exports match by name). Forge and above: use ast-grep to compare export signatures between the deleted and added files. Forge+/Deep: use CCC semantic similarity when available
324
+
325
+ **Subprocess return contract.** Hand each Category worker its exact output slice so it returns parse-ready JSON, not prose the parent must re-read. Each worker returns ONLY its own object — no prose, no commentary, no markdown fences (parent strips wrapping fences before parsing). The slice each worker fills is exactly the key §3's `build` helper consumes (the `category_a/b/c` shape below; Category D is helper-driven, not a worker):
326
+
327
+ ```json
328
+ // Category A worker returns ONLY:
329
+ {"category_a": {"modified": [...], "added": [...], "deleted": [...]}}
330
+ // Category B worker returns ONLY:
331
+ {"category_b": {"modified_exports": [...], "new_exports": [...], "deleted_exports": [...], "moved_exports": [...]}}
332
+ // Category C worker returns ONLY:
333
+ {"category_c": {"renamed_files": [...], "renamed_exports": [...]}}
334
+ ```
335
+
336
+ The parent merges the three slices (plus Category D and the `degraded_mode`/`update_mode` flags) into the single category-JSON object §3 pipes to the `build` helper.
309
337
 
310
338
  **Category D — Script/asset file changes:**
311
339
 
@@ -334,9 +362,14 @@ Translate the helper's output into the change manifest:
334
362
  - `DELETED_FILE` rows → add to manifest as DELETED_FILE
335
363
  - `UNCHANGED` rows → omit from the manifest (no action needed)
336
364
 
337
- The helper does NOT detect NEW_FILE its job is provenance comparison only. Detect new files via `skf-detect-scripts-assets.py` from create-skill step 3 §4c against the current source tree, then subtract the paths already present in `provenance.file_entries[].source_file`. Remaining files matching detection patterns (`scripts/`, `bin/`, `assets/`, `templates/`) and NOT under `scripts/[MANUAL]/` or `assets/[MANUAL]/` are NEW_FILE.
365
+ The compare helper reports only tracked files; NEW_FILE detection (a file present in source but absent from the provenance map) is a set-difference, so it runs through a script rather than the prompt. Pipe the same deterministic detector create-skill step 3 §4c uses (resolved via `detectScriptsAssetsProbeOrder`) into `{newFileDiffHelper}`, which subtracts the provenance map's `file_entries[].source_file` and sets aside user-authored `[MANUAL]` paths:
338
366
 
339
- Files in `scripts/[MANUAL]/` or `assets/[MANUAL]/` → SKIP (user-authored, preserved).
367
+ ```bash
368
+ uv run {detectScriptsAssetsHelper} detect <source-root> \
369
+ | uv run {newFileDiffHelper} {forge_version}/provenance-map.json
370
+ ```
371
+
372
+ It emits `{"new_files":[{source_file, kind}], "skipped_manual":[...], "already_tracked":[...], "stats":{...}}`. Add each `new_files[]` entry to the manifest as NEW_FILE — `kind` (`script`/`asset`) selects the target array. `skipped_manual[]` are user-authored files under `scripts/[MANUAL]/` or `assets/[MANUAL]/`, preserved and not touched; `already_tracked[]` were handled by the compare above.
340
373
 
341
374
  Aggregate all subprocess results into a unified change manifest.
342
375
 
@@ -356,7 +389,7 @@ echo "{category JSON}" | uv run {buildChangeManifestHelper} deletion-ratio \
356
389
  --provenance-map {forge_version}/provenance-map.json
357
390
  ```
358
391
 
359
- The helper handles the three skip conditions internally — when the input has `update_mode: "gap-driven"`, `degraded_mode: true`, or the provenance has zero entries, it returns `skip_reason` set and `should_trigger: false`. The output envelope:
392
+ The helper handles the three skip conditions internally — when the input has `update_mode: "gap-driven"`, `degraded_mode: true`, or the provenance has zero entries, it returns `skip_reason` set and `should_trigger: false`. `should_trigger` fires when the deletion ratio reaches the fixed bundled threshold of 50% (`ratio >= 0.50`, baked into the helper — not configurable). The output envelope:
360
393
 
361
394
  ```json
362
395
  {
@@ -399,8 +432,6 @@ The upstream surface appears to have been substantially replaced. The brief's
399
432
  - **[B] Brief:** halt with status `halted-for-brief-refinement`. Display: `"Halting update-skill. Re-run skf-brief-skill to refine scope for {skill_name}, then re-run skf-update-skill."` Change manifest discarded — no partial writes.
400
433
  - **[A] Audit:** halt with status `halted-for-audit`. Display: `"Halting update-skill. Run skf-audit-skill against {skill_name} to map the new surface — its drift report will feed §1c on the next update-skill run."` Change manifest discarded.
401
434
 
402
- **Why both §1c and §2.2:** §1c is precise (per-path P/S/U) but requires upstream signal from audit-skill. §2.2 is coarse (single halt/continue) but self-contained — it fires even when the user runs update-skill directly without audit. Together they cover the major-version case across the two real workflows.
403
-
404
435
  ### 3. Build Change Manifest
405
436
 
406
437
  Hand the assembled Category A/B/C/D JSON to the helper:
@@ -460,7 +491,7 @@ The skill `{skill_name}` is current — no update needed.
460
491
 
461
492
  → Skip steps 03-06, immediately load {noChangeReportFile} with "no changes" status.
462
493
 
463
- ### 5. Display Change Summary and Auto-Proceed
494
+ ### 5. Display Change Summary and Route
464
495
 
465
496
  "**Change Detection Complete:**
466
497
 
@@ -470,30 +501,11 @@ The skill `{skill_name}` is current — no update needed.
470
501
  | Files added | {count} |
471
502
  | Files deleted | {count} |
472
503
  | Files moved/renamed | {count} |
473
- | Exports affected | {total_export_changes} |
474
-
475
- **Proceeding to re-extraction of {affected_file_count if normal mode, or gap_count if gap-driven mode} changes...**"
476
-
477
- ### 6. Present MENU OPTIONS
478
-
479
- Display: "**Proceeding to re-extraction...**"
480
-
481
- #### Menu Handling Logic:
482
-
483
- - **If `detect_only_mode` is true:** display "**Detect-only mode — skipping re-extract/merge/validate/write.** Loading report..." and load `{noChangeReportFile}` (report.md). The report handles the detect-only envelope. Do NOT load `{nextStepFile}`.
484
- - Else, after change manifest is built, immediately load, read entire file, then execute `{nextStepFile}`.
485
- - **EXCEPTION:** If no changes detected (section 4), load `{noChangeReportFile}` instead.
486
-
487
- #### EXECUTION RULES:
488
-
489
- - This is an auto-proceed step with no user choices
490
- - Proceed directly to next step after change detection completes (or to report when `detect_only_mode` is true)
491
-
492
- ## CRITICAL STEP COMPLETION NOTE
504
+ | Exports affected | {total_export_changes} |"
493
505
 
494
- ONLY WHEN the change manifest is fully built will you load the next file:
506
+ This step auto-proceeds — no user choices. Once the change manifest is fully built, load and fully read the next file, then execute it, per the branch that applies:
495
507
 
496
- - `detect_only_mode == true` → load `{noChangeReportFile}` (report.md). Report emits status `detect-only`.
497
- - No changes detected → load `{noChangeReportFile}` (report.md). Report emits status `no-changes`.
498
- - Otherwise → load `{nextStepFile}` (re-extract.md) to begin re-extraction.
508
+ - **`detect_only_mode == true`**display "**Detect-only mode — skipping re-extract/merge/validate/write.** Loading report..." and load `{noChangeReportFile}` (report.md), which emits status `detect-only`. Do not load `{nextStepFile}`.
509
+ - **No changes detected** (section 4) → load `{noChangeReportFile}` (report.md), which emits status `no-changes`.
510
+ - **Otherwise**display "**Proceeding to re-extraction of {affected_file_count if normal mode, or gap_count if gap-driven mode} changes...**" and load `{nextStepFile}` (re-extract.md) to begin re-extraction.
499
511
 
@@ -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
 
@@ -11,15 +11,9 @@ nextStepFile: 'shared/health-check.md'
11
11
 
12
12
  ## STEP GOAL:
13
13
 
14
- Chain to the shared workflow self-improvement health check at `{nextStepFile}`. This is the terminal step of update-skill — after the shared health check completes, the workflow is fully done.
14
+ Chain to the shared workflow self-improvement health check at `{nextStepFile}`. This is the terminal step of update-skill — after the shared health check completes, the workflow is fully done. This step only releases the concurrency lock and delegates: no user-facing reports, file writes, or result contracts here (those belong in step 7).
15
15
 
16
- ## Rules
17
-
18
- - No user-facing reports, file writes, or result contracts in this step — those belong in step 7
19
- - Delegate directly to `{nextStepFile}` with no additional commentary
20
- - Do not attempt any other action between loading this step and executing `{nextStepFile}` (other than the lock release below)
21
-
22
- ## MANDATORY SEQUENCE
16
+ ## Steps
23
17
 
24
18
  1. **Release the concurrency lock** acquired by init.md §1b (skip when `detect_only_mode` or `dry_run_mode` is true — those modes never acquired one):
25
19
 
@@ -27,6 +21,6 @@ Chain to the shared workflow self-improvement health check at `{nextStepFile}`.
27
21
  rm -f "{forge_data_folder}/{skill_name}/.skf-update.lock"
28
22
  ```
29
23
 
30
- The lock release MUST run before delegating to the shared health-check, since the health-check is the terminal step once it returns, the workflow is done and any held lock becomes orphaned for the next run to clean up. Releasing here keeps the lock lifecycle tight against the workflow's actual span.
24
+ Release the lock before delegating to the shared health-check: the health-check is the terminal step, so once it returns the workflow is done and any still-held lock is orphaned until the next run clears it. Releasing here keeps the lock lifecycle tight against the workflow's actual span.
31
25
 
32
26
  2. Load `{nextStepFile}`, read it fully, then execute it.
@@ -1,6 +1,15 @@
1
1
  ---
2
2
  nextStepFile: 'detect-changes.md'
3
3
  manualSectionRulesFile: 'references/manual-section-rules.md'
4
+ # Resolve `{hashContentHelper}` to the first existing path; HALT if neither
5
+ # candidate exists. §5 uses its `manual-inventory` subcommand to capture the
6
+ # exact pre-write [MANUAL] inventory (per-block byte-exact interior hashes),
7
+ # which write.md §1 (HALT gate) and validate.md Check B later verify against.
8
+ # An LLM marker-count would miss an interior truncation that leaves the marker
9
+ # count unchanged.
10
+ hashContentProbeOrder:
11
+ - '{project-root}/_bmad/skf/shared/scripts/skf-hash-content.py'
12
+ - '{project-root}/src/shared/scripts/skf-hash-content.py'
4
13
  ---
5
14
 
6
15
  <!-- Config: communicate in {communication_language}. -->
@@ -16,7 +25,7 @@ Load the existing skill and all its provenance data, detect whether this is an i
16
25
  - Focus only on loading existing artifacts and establishing the baseline — read-only operations
17
26
  - Do not begin change detection (Step 02)
18
27
 
19
- ## MANDATORY SEQUENCE
28
+ ## Steps
20
29
 
21
30
  ### 1. Request Skill Path
22
31
 
@@ -27,6 +36,7 @@ Provide either:
27
36
  - A full path to the skill folder
28
37
  - A skill name with `--from-test-report` to use the test report's gap findings instead of source drift detection
29
38
  - `--allow-workspace-drift` (gap-driven mode only) to intentionally bypass the step 3 §0.a guard that halts when the local workspace HEAD does not match `metadata.source_commit`. Only use this if you know the spot-checks should read the current workspace instead of the pinned tree — step 6 will NOT automatically re-pin
39
+ - `--allow-degraded` (headless mode only) to pre-authorize the lossy degraded full re-extraction if §4 finds no provenance map — without it, a headless run halts `blocked` there rather than silently rebuilding
30
40
  - `--detect-only` to run detect-changes only and exit; emits the change manifest with no further work and no writes
31
41
  - `--dry-run` to run detect-changes + re-extract and exit before merge/write; emits what WOULD change without modifying any artifact
32
42
 
@@ -38,6 +48,7 @@ Provide either:
38
48
  3. If not in manifest: check for `active` symlink at `{skills_output_folder}/{skill-name}/active` — resolve to `{skill_group}/active/{skill-name}/`
39
49
  4. If neither: fall back to flat path `{skills_output_folder}/{skill-name}/`. If SKILL.md exists at the flat path, auto-migrate per `knowledge/version-paths.md` migration rules
40
50
  5. Store the resolved path as `{resolved_skill_package}` for all subsequent artifact loading
51
+ 6. Bind `{baseline_version}` to the pre-update version — for an update this is the version being updated, i.e. the `{active_version}` resolved in step 1 above (the flat-path fallback in step 4 has no version, so use the package version read from metadata.json in §2). Step 2 §1c passes `{baseline_version}` to `skf-provenance-gap-dispatch.py` as a required argument; leaving it unbound makes the helper search a wrong/empty directory and silently return `no-report`, dropping the major-version off-ramp.
41
52
 
42
53
  Resolve the path to an absolute skill folder location.
43
54
 
@@ -53,6 +64,8 @@ If a report is located, set `test_report_path` in context to the resolved absolu
53
64
 
54
65
  **If `--allow-workspace-drift` was provided:** set `allow_workspace_drift: true` in workflow context. This flag is consumed by step 3 §0.a's pre-flight drift guard (gap-driven mode only) and has no effect in normal source-drift mode.
55
66
 
67
+ **If `--allow-degraded` was provided:** set `allow_degraded: true` in workflow context. This flag is consumed by §4 below when no provenance map is found under `{headless_mode}`; it has no effect interactively (the [D]/[X] prompt is shown) or when a provenance map is present.
68
+
56
69
  **If `--detect-only` was provided:** set `detect_only_mode: true` in workflow context. After step 2 (detect-changes) completes, jump directly to step 7 (report) — skip re-extract, merge, validate, and write. The report emits the change manifest and a `SKF_UPDATE_RESULT_JSON` envelope with `status: "detect-only"`. **Compatibility:** `--detect-only` short-circuits before §0.a runs, so `--allow-workspace-drift` is silently ignored in detect-only mode (warn the user once at flag-parse time: "`--allow-workspace-drift` has no effect with `--detect-only` — workspace drift guard runs in step 3 §0.a, which is skipped").
57
70
 
58
71
  **If `--dry-run` was provided:** set `dry_run_mode: true` in workflow context. After step 3 (re-extract) completes, jump directly to step 7 (report) — skip merge, validate, and write. The report emits what would change with `status: "dry-run"` in the envelope. No artifact on disk is modified — `--dry-run` is the "show me what an update would do without committing" mode.
@@ -80,8 +93,8 @@ if [ -f "$LOCK" ]; then
80
93
  # (LLM emits SKF_UPDATE_RESULT_JSON status=halted-for-concurrent-run, see below)
81
94
  exit 1
82
95
  fi
83
- # Stale lock (PID is dead) log + overwrite
84
- echo "skf-update-skill: clearing stale lock from pid=$HELD_PID"
96
+ # Dead PID — lock left by a prior halted or crashed run; clear + overwrite
97
+ echo "skf-update-skill: clearing lock from a prior halted/crashed run (pid=$HELD_PID)"
85
98
  fi
86
99
 
87
100
  # Acquire: write our PID + start timestamp (one per line)
@@ -95,9 +108,9 @@ printf '%s\n%s\n' "$$" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" > "$LOCK"
95
108
 
96
109
  **Release contract:**
97
110
 
98
- - The terminal health-check step (step 8) deletes the lock file as its final action.
99
- - **Every halted-for-\* path in this workflow must delete the lock before exiting** otherwise the next attempt would see a stale lock from this run. The lock-release is a single `rm -f "$LOCK"` per halt site; do not skip it.
100
- - The lock is best-effort: a crash mid-workflow (process kill, host reboot) leaves a stale lock that the next run will clear via the live-PID check above. No manual cleanup needed in the common case.
111
+ - The terminal health-check step (step 8) deletes the lock as its final action — the normal end of every non-inspection run. The two init-stage headless halts below (§4 no-provenance-map, §6 invalid-source-path) also delete it explicitly, since they fire right after acquisition, before the terminal step runs.
112
+ - Mid-workflow halts (detect-changes, re-extract, merge, write) do **not** delete the lock themselvesthey rely on the self-heal below. This is deliberate: several of those halt sites are also reachable under `--detect-only`/`--dry-run`, which never acquired this lock, so a blind `rm -f` there could clobber a concurrent real update's lock.
113
+ - The lock is best-effort and self-healing: whatever a halt or crash (process kill, host reboot) leaves behind is cleared by the next run's live-PID check above, since the stored PID is a short-lived bash PID that is already dead. No manual cleanup needed in the common case.
101
114
 
102
115
  ### 2. Validate Required Artifacts
103
116
 
@@ -112,7 +125,7 @@ printf '%s\n%s\n' "$$" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" > "$LOCK"
112
125
 
113
126
  **Detect skill type from metadata:**
114
127
  - If `skill_type == "single"` or absent: flag as single skill
115
- - If `skill_type == "stack"`: flag as stack skill (multi-file update mode)
128
+ - If `skill_type == "stack"`: flag as stack skill the guard below redirects it
116
129
 
117
130
  ### Stack Skill Guard
118
131
 
@@ -125,6 +138,8 @@ After loading metadata.json, check `skill_type`:
125
138
  If you came here from an audit report, the drift report identifies which constituent libraries changed — use that to decide whether re-composition is needed."
126
139
  - Exit the workflow (do not proceed to step 2)
127
140
 
141
+ **This guard is the single gate for stack skills** — every stack is redirected to `skf-create-stack-skill` here, before step 2, and no flag (`--detect-only`, `--dry-run`, `--from-test-report`, `--allow-workspace-drift`) bypasses it. Every later stage therefore runs against a single skill only and carries no stack-merge branch.
142
+
128
143
  ### 3. Load Forge Tier Configuration
129
144
 
130
145
  **Load `{sidecar_path}/forge-tier.yaml`:**
@@ -159,18 +174,22 @@ Select: [D] Degraded / [X] Abort"
159
174
  - If D: set `degraded_mode = true`, proceed with full extraction scope
160
175
  - If X: **ABORT**
161
176
 
177
+ **In `{headless_mode}` without `--allow-degraded` (default):** do not auto-select [D]. Degraded mode is a full, lossy T1-low re-extraction — choosing it unattended would silently swap surgical update for a create-skill-equivalent rebuild, a policy call that belongs to an operator. Halt instead: release the lock (`rm -f "$LOCK"`), emit `SKF_UPDATE_RESULT_JSON` with `status: "blocked"`, `error: {phase: "init:load-provenance-map", path: "{forge_version}/provenance-map.json", reason: "no provenance map at versioned or flat path; degraded full re-extraction needs a human decision"}`, and exit. No `headless_decisions[]` entry — this is a hard halt, not an auto-resolved gate.
178
+
179
+ **In `{headless_mode}` with `--allow-degraded` (`allow_degraded: true`):** the operator pre-authorized the lossy rebuild for this run, so treat it as an auto-resolved [D] rather than a halt. Set `degraded_mode = true`, proceed with full extraction scope, and append to in-context `headless_decisions[]`: `{gate: "init.degraded-rebuild", default_action: "X", taken_action: "D", reason: "headless: --allow-degraded pre-authorized degraded full re-extraction", evidence: "no provenance map at {forge_version}/provenance-map.json or flat fallback"}`. Continue to step 2.
180
+
162
181
  ### 5. Load [MANUAL] Section Inventory
163
182
 
164
- Load {manualSectionRulesFile} to understand [MANUAL] detection patterns.
183
+ Load {manualSectionRulesFile} to understand [MANUAL] detection patterns (the human-readable rules for markers, parent-section mapping, and orphan/nesting handling).
165
184
 
166
- **Scan SKILL.md for [MANUAL] sections:**
167
- - Count all `<!-- [MANUAL:*] -->` markers
168
- - Map each [MANUAL] block to its parent section (by heading hierarchy)
169
- - Record section names and approximate line positions
185
+ **Capture the [MANUAL] inventory deterministically.** The workflow's headline rule is "[MANUAL] sections survive regeneration with zero content loss" — the pre-write inventory captured here is the exact baseline that write.md §1 and validate.md Check B verify against, so it must be a per-block byte-exact hash, not an eyeballed marker count. Run the `manual-inventory` subcommand of `{hashContentHelper}` and persist its JSON:
186
+
187
+ ```bash
188
+ uv run {hashContentHelper} manual-inventory {resolved_skill_package}/SKILL.md \
189
+ > {forge_version}/.manual-inventory.json
190
+ ```
170
191
 
171
- **For stack skills, also scan:**
172
- - All `references/*.md` files for [MANUAL] markers
173
- - All `references/integrations/*.md` files for [MANUAL] markers
192
+ The emitted JSON is `{"blocks":[{name, content_hash, byte_offset, parent_heading}...], "count":N}` — each `content_hash` covers the block's byte-exact interior, so a later interior truncation that leaves the marker count unchanged is still caught. Bind the persisted path as `{manual_inventory}` in context; write.md §1 and validate.md Check B pass it to `manual-verify`. Surface the block `count` in the baseline summary (§7 `{manual_count}`).
174
193
 
175
194
  ### 6. Resolve Source Code Path
176
195
 
@@ -185,6 +204,8 @@ Load {manualSectionRulesFile} to understand [MANUAL] detection patterns.
185
204
  Provide the current source code path:
186
205
  **Path:** {user provides path}"
187
206
 
207
+ **In `{headless_mode}`:** there is no operator to supply a path. Halt: release the lock (`rm -f "$LOCK"`), emit `SKF_UPDATE_RESULT_JSON` with `status: "blocked"`, `error: {phase: "init:resolve-source-path", path: "{source_root}", reason: "source_root from provenance map is invalid or inaccessible and no interactive path can be supplied"}`, and exit. No `headless_decisions[]` entry — this is a hard halt, not an auto-resolved gate.
208
+
188
209
  ### 7. Present Baseline Summary
189
210
 
190
211
  "**Update Skill Baseline:**
@@ -192,7 +213,7 @@ Provide the current source code path:
192
213
  | Property | Value |
193
214
  |----------|-------|
194
215
  | **Skill** | {skill_name} |
195
- | **Type** | {single/stack} |
216
+ | **Type** | single |
196
217
  | **Version** | {version} |
197
218
  | **Created** | {created date} |
198
219
  | **Source** | {source_root} |
@@ -209,22 +230,9 @@ Provide the current source code path:
209
230
 
210
231
  **Ready to detect changes and update this skill?**"
211
232
 
212
- ### 8. Present MENU OPTIONS
213
-
214
- Display: "**Select:** [C] Continue to Change Detection"
215
-
216
- #### Menu Handling Logic:
217
-
218
- - IF C: Load, read entire file, then execute {nextStepFile}
219
- - IF Any other: help user respond, then [Redisplay Menu Options](#8-present-menu-options)
220
-
221
- #### EXECUTION RULES:
222
-
223
- - ALWAYS halt and wait for user input after presenting menu
224
- - **GATE [default: C]** — If `{headless_mode}`: auto-proceed with [C] Continue, log: "headless: auto-continue past update confirmation". **Also append to in-context `headless_decisions[]`** (step 7 surfaces this list in `SKF_UPDATE_RESULT_JSON`): `{gate: "init.update-confirmation", default_action: "C", taken_action: "C", reason: "headless: no user to prompt"}`. The headless_decisions[] array is the structured audit trail for non-interactive runs — see `src/shared/scripts/schemas/skf-update-result-envelope.v1.json` for the entry shape.
225
- - ONLY proceed to next step when user selects 'C'
233
+ ### 8. Confirmation Gate
226
234
 
227
- ## CRITICAL STEP COMPLETION NOTE
235
+ Present "**Select:** [C] Continue to Change Detection" and wait for the user to confirm; on [C], load, read the full file, then execute {nextStepFile}.
228
236
 
229
- ONLY WHEN [C] is selected and baseline has been established with all required artifacts loaded, will you then load and read fully `{nextStepFile}` to execute change detection.
237
+ **Headless (`{headless_mode}` true):** auto-continue and append to in-context `headless_decisions[]` (step 7 surfaces it in `SKF_UPDATE_RESULT_JSON`): `{gate: "init.update-confirmation", default_action: "C", taken_action: "C", reason: "headless: no user to prompt"}`. Entry shape: `src/shared/scripts/schemas/skf-update-result-envelope.v1.json`.
230
238
 
@@ -26,8 +26,7 @@ It must be preserved during any update operation.
26
26
  2. **Preserve marker positions** — if the surrounding generated content moves, the [MANUAL] block moves with its logical parent section
27
27
  3. **Orphan detection** — if the parent section is deleted (export removed), flag as WARNING and present to user
28
28
  4. **Multiple [MANUAL] blocks** — a single SKILL.md may have multiple [MANUAL] sections; preserve all
29
- 5. **Stack skill [MANUAL] blocks** — [MANUAL] markers can appear in any output file (SKILL.md, references/*.md, integrations/*.md); preserve across all files
30
- 6. **Nested [MANUAL] forbidden** — [MANUAL] blocks cannot be nested; if detected, flag as ERROR
29
+ 5. **Nested [MANUAL] forbidden** — [MANUAL] blocks cannot be nested; if detected, flag as ERROR
31
30
 
32
31
  ### Conflict Types
33
32
 
@@ -4,58 +4,7 @@ type: static-reference
4
4
 
5
5
  # Merge Conflict Rules
6
6
 
7
- ## Change Categories
8
-
9
- ### Category 1: Modified Exports (signature/type change)
10
-
11
- - **Action:** Re-extract affected export with fresh AST analysis
12
- - **Merge:** Replace generated content for that export; preserve adjacent [MANUAL] blocks
13
- - **Confidence:** Same tier as original (T1/T1-low/T2)
14
-
15
- ### Category 2: New Exports (added since last generation)
16
-
17
- - **Action:** Extract new export with full AST analysis
18
- - **Merge:** Append to appropriate section based on export type (function, type, class, constant)
19
- - **Confidence:** Label with extraction tier confidence
20
- - **[MANUAL] impact:** None — new content, no existing [MANUAL] blocks
21
-
22
- ### Category 3: Deleted Exports (removed from source)
23
-
24
- - **Action:** Remove generated content for that export
25
- - **Merge:** Check for attached [MANUAL] blocks before deletion
26
- - **If [MANUAL] attached:** Flag as orphan, present to user for decision
27
- - **If no [MANUAL]:** Auto-remove generated content
28
-
29
- ### Category 4: Moved Exports (file relocated)
30
-
31
- - **Action:** Update provenance map file references
32
- - **Merge:** Update file:line citations in generated content
33
- - **Confidence:** Retain original tier if AST structure unchanged; downgrade to T1-low if structure changed
34
- - **[MANUAL] impact:** Preserve — content unchanged, only provenance metadata updates
35
-
36
- ### Category 5: Renamed Exports (identifier changed)
37
-
38
- - **Action:** Re-extract with new identifier
39
- - **Merge:** Replace old identifier references in generated content
40
- - **[MANUAL] impact:** Flag if [MANUAL] blocks reference old identifier name
41
-
42
- ## Merge Priority Order
43
-
44
- 1. Process deleted exports first (remove generated content, flag [MANUAL] orphans)
45
- 2. Process moved exports second (update references only)
46
- 3. Process renamed exports third (update identifiers)
47
- 4. Process modified exports fourth (re-extract and replace)
48
- 5. Process new exports last (append to sections)
49
-
50
- ## Stack Skill Merge Rules
51
-
52
- For stack skills with multi-file outputs:
53
-
54
- 1. **SKILL.md:** Apply standard merge rules above
55
- 2. **references/{library}.md:** Merge per-library, preserving [MANUAL] blocks within each
56
- 3. **references/integrations/{pair}.md:** Merge per-integration-pair
57
- 4. **metadata.json:** Regenerate completely (no [MANUAL] support in JSON)
58
- 5. **context-snippet.md:** Regenerate completely (no [MANUAL] support — too concise)
7
+ > Change-category actions and the merge priority order (deleted → moved → renamed → modified → new, plus the gap-driven priorities) are specified authoritatively in `merge.md` §3. This reference carries only the one thing §3 does not: the conflict-resolution strategy table below.
59
8
 
60
9
  ## Conflict Resolution Strategies
61
10
 
@@ -10,21 +10,21 @@ mergeConflictRulesFile: 'references/merge-conflict-rules.md'
10
10
 
11
11
  ## STEP GOAL:
12
12
 
13
- Merge freshly extracted export data into the existing SKILL.md content while preserving all [MANUAL] sections. Detect and resolve conflicts where regenerated content overlaps developer-authored content. For stack skills, merge across all output files.
13
+ Merge freshly extracted export data into the existing SKILL.md content while preserving all [MANUAL] sections. Detect and resolve conflicts where regenerated content overlaps developer-authored content.
14
14
 
15
15
  ## Rules
16
16
 
17
17
  - Focus only on merging extractions into existing skill content
18
18
  - Never delete or modify [MANUAL] section content
19
- - Write merged SKILL.md (and stack reference files) directly to disk at section 6b — Claude Code's Edit/Write tools commit on call, so there is no held-in-memory "edit plan" primitive; subsequent steps validate and verify against the on-disk files
19
+ - Write merged SKILL.md directly to disk at section 6b — Claude Code's Edit/Write tools commit on call, so there is no held-in-memory "edit plan" primitive; subsequent steps validate and verify against the on-disk files
20
20
  - If [MANUAL] conflicts detected: halt and present to user. If clean merge: auto-proceed
21
21
 
22
- ## MANDATORY SEQUENCE
22
+ ## Steps
23
23
 
24
24
  ### 1. Load Merge Rules
25
25
 
26
26
  Load {manualSectionRulesFile} for [MANUAL] detection and preservation patterns.
27
- Load {mergeConflictRulesFile} for change category merge strategies and priority order.
27
+ Load {mergeConflictRulesFile} for the conflict-resolution strategy table (the change-category actions and priority order live in §3 below).
28
28
 
29
29
  ### 2. Extract [MANUAL] Blocks
30
30
 
@@ -35,7 +35,7 @@ From the [MANUAL] inventory captured in step 01:
35
35
 
36
36
  ### 3. Apply Merge by Priority Order
37
37
 
38
- Follow the merge priority order from {mergeConflictRulesFile}:
38
+ Apply merge in the following priority order:
39
39
 
40
40
  **Priority 1 — Process DELETED exports:**
41
41
  - Remove generated content for deleted exports
@@ -146,20 +146,6 @@ Select: [K] Keep / [R] Remove / [E] Edit"
146
146
 
147
147
  Process each conflict with user's decision.
148
148
 
149
- ### 5. Stack Skill Merge (Conditional)
150
-
151
- **ONLY if skill_type == "stack":**
152
-
153
- Apply the same merge process to each stack output file:
154
- - `references/{library}.md` — merge per-library changes, preserve [MANUAL] blocks
155
- - `references/integrations/{pair}.md` — merge per-integration-pair
156
- - `metadata.json` — regenerate completely (no [MANUAL] support)
157
- - `context-snippet.md` — regenerate completely (no [MANUAL] support)
158
-
159
- Report stack file merge status for each file.
160
-
161
- **If skill_type != "stack":** Skip with notice: "Individual skill — single file merge."
162
-
163
149
  ### 6. Compile Merge Results
164
150
 
165
151
  Build merge result summary:
@@ -176,30 +162,22 @@ Merge Results:
176
162
  manual_conflicts_resolved: [count]
177
163
  manual_orphans_kept: [count]
178
164
  manual_orphans_removed: [count]
179
-
180
- stack_files_merged: [count] (if stack skill)
181
165
  ```
182
166
 
183
167
  ### 6b. Write Merged Files to Disk
184
168
 
185
- Write the merged content produced by sections 3–5 directly to disk now. Later steps read from these files for validation and verification. The write must happen exactly once, here.
169
+ Write the merged content produced by sections 3–4 directly to disk now. Later steps read from these files for validation and verification. The write must happen exactly once, here.
186
170
 
187
171
  **Write SKILL.md:**
188
172
  - Use the `Edit` or `Write` tool to write merged SKILL.md content to `{skill_package}/SKILL.md`
189
173
  - Preserve UTF-8 encoding
190
174
  - If the source version detected during step 3 differs from the previous metadata version, create the new `{skill_package}` directory (`{skill_group}/{new_version}/`) first and write there — the previous version's directory is preserved on disk. Update `{skill_package}` in context to point at the new path.
191
175
 
192
- **Write stack reference files (if `skill_type == "stack"`):**
193
- - For each affected file from section 5, use `Edit` or `Write` to write:
194
- - `references/{library}.md` with merged per-library content
195
- - `references/integrations/{pair}.md` with merged per-integration content
196
- - Preserve [MANUAL] blocks exactly as captured in section 2.
197
-
198
176
  **Do NOT write here:**
199
177
  - `metadata.json`, `provenance-map.json`, `evidence-report.md` — derived from merge + validation output, written by step 6 sections 2–4
200
178
  - `context-snippet.md` — regenerated from the on-disk SKILL.md + metadata.json by step 6 section 5
201
179
 
202
- **Halt-on-tool-failure:** If any `Edit`/`Write` call errors (permission denied, disk full, path invalid, etc.), halt and report the failure — do not proceed to step 5 validation. The skill package may be in a partial state and will need manual recovery before re-running update-skill.
180
+ **Halt-on-tool-failure:** If any `Edit`/`Write` call errors (permission denied, disk full, path invalid, etc.), halt with status `halted-for-write-failure` and report the failure — do not proceed to step 5 validation. The skill package may be in a partial state and will need manual recovery before re-running update-skill. In `{headless_mode}`, emit the halt envelope per SKILL.md §Headless (`error: {phase: "merge:write-skill-md", path: "{skill_package}/SKILL.md", reason: "..."}`).
203
181
 
204
182
  ### 7. Display Merge Summary
205
183
 
@@ -213,36 +191,14 @@ Write the merged content produced by sections 3–5 directly to disk now. Later
213
191
  | [MANUAL] sections preserved | {count} |
214
192
  | Conflicts resolved | {count} |"
215
193
 
216
- ### 8. Present MENU OPTIONS
217
-
218
- **If conflicts were resolved (user interaction occurred):**
219
-
220
- Display: "**Merge complete with conflict resolution. Select:** [C] Continue to Validation"
221
-
222
- #### Menu Handling Logic:
223
-
224
- - IF C: Load, read entire file, then execute {nextStepFile}
225
- - IF Any other: help user respond, then [Redisplay Menu Options](#8-present-menu-options)
226
-
227
- #### EXECUTION RULES:
228
-
229
- - ALWAYS halt and wait for user input after conflict resolution
230
- - **GATE [default: C if clean merge]** — If `{headless_mode}` and merge is clean (no [MANUAL] conflicts): auto-proceed with [C] Continue, log: "headless: clean merge, auto-continue". **Also append to in-context `headless_decisions[]`** (surfaced via `SKF_UPDATE_RESULT_JSON` by step 7): `{gate: "merge.clean-merge-gate", default_action: "C", taken_action: "C", reason: "headless: clean merge, no conflicts to resolve"}`. If conflicts exist, HALT even in headless mode — conflicts require human judgment, and the headless_decisions[] array does NOT get a continue-on-conflict entry (the workflow status becomes `halted-for-manual-mismatch` instead).
231
- - ONLY proceed when user selects 'C'
232
-
233
- **If clean merge (no conflicts):**
234
-
235
- Display: "**Clean merge — proceeding to validation...**"
236
-
237
- #### Clean Merge Menu Handling Logic:
238
-
239
- - Immediately load, read entire file, then execute {nextStepFile}
194
+ ### 8. Gate to Validation
240
195
 
241
- #### Clean Merge EXECUTION RULES:
196
+ **Clean merge (no conflicts):** display "**Clean merge proceeding to validation...**", then load, read the full file, and execute {nextStepFile} (auto-proceed).
242
197
 
243
- - This is an auto-proceed path when no conflicts exist
198
+ **Conflicts were resolved (user interaction occurred):** present "**Merge complete with conflict resolution. Select:** [C] Continue to Validation" and wait for the user to confirm before loading {nextStepFile}.
244
199
 
245
- ## CRITICAL STEP COMPLETION NOTE
200
+ **Headless (`{headless_mode}` true):**
246
201
 
247
- ONLY WHEN all merge operations are complete and any [MANUAL] conflicts have been resolved by the user will you load {nextStepFile} to begin validation.
202
+ - Clean merge auto-continue and append to in-context `headless_decisions[]` (surfaced via `SKF_UPDATE_RESULT_JSON` by step 7): `{gate: "merge.clean-merge-gate", default_action: "C", taken_action: "C", reason: "headless: clean merge, no conflicts to resolve"}`.
203
+ - Conflicts present → halt even in headless mode (conflicts require human judgment): status `halted-for-manual-mismatch`, emitting the halt envelope per SKILL.md §Headless (`error: {phase: "merge:conflict-resolution", reason: "..."}`); no `headless_decisions[]` entry is added.
248
204