bmad-module-skill-forge 2.0.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 (235) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.nvmrc +1 -1
  3. package/docs/_data/pinned.yaml +1 -1
  4. package/package.json +2 -2
  5. package/src/knowledge/skill-lifecycle.md +1 -1
  6. package/src/module-help.csv +2 -2
  7. package/src/shared/scripts/skf-comention-pairs.py +350 -0
  8. package/src/shared/scripts/skf-count-tokens.py +222 -0
  9. package/src/shared/scripts/skf-detect-docs.py +232 -1
  10. package/src/shared/scripts/skf-detect-language.py +77 -0
  11. package/src/shared/scripts/skf-detect-tools.py +105 -2
  12. package/src/shared/scripts/skf-enumerate-stack-skills.py +111 -2
  13. package/src/shared/scripts/skf-find-cycles.py +246 -0
  14. package/src/shared/scripts/skf-hash-content.py +487 -2
  15. package/src/shared/scripts/skf-manifest-ops.py +67 -1
  16. package/src/shared/scripts/skf-rebuild-managed-sections.py +180 -0
  17. package/src/shared/scripts/skf-recommend-scope-type.py +1 -2
  18. package/src/shared/scripts/skf-render-metadata-stats.py +499 -0
  19. package/src/shared/scripts/skf-rewrite-skill-name.py +308 -0
  20. package/src/shared/scripts/skf-shard-body.py +461 -0
  21. package/src/shared/scripts/skf-skill-inventory.py +139 -3
  22. package/src/shared/scripts/skf-structural-diff.py +307 -67
  23. package/src/shared/scripts/skf-validate-brief-schema.py +39 -1
  24. package/src/shared/scripts/skf-validate-feasibility-report.py +234 -0
  25. package/src/shared/scripts/skf-validate-frontmatter.py +17 -12
  26. package/src/shared/scripts/skf-validate-output.py +443 -10
  27. package/src/shared/scripts/skf-validate-pins.py +1 -1
  28. package/src/shared/scripts/skf-verify-no-trace.py +214 -0
  29. package/src/shared/scripts/skf-verify-provenance-completeness.py +439 -0
  30. package/src/skf-analyze-source/SKILL.md +17 -32
  31. package/src/skf-analyze-source/customize.toml +2 -0
  32. package/src/skf-analyze-source/references/auto-docs-only.md +116 -0
  33. package/src/skf-analyze-source/references/continue.md +8 -13
  34. package/src/skf-analyze-source/references/generate-briefs.md +28 -12
  35. package/src/skf-analyze-source/references/headless-contract.md +33 -0
  36. package/src/skf-analyze-source/references/health-check.md +1 -2
  37. package/src/skf-analyze-source/references/identify-units.md +25 -36
  38. package/src/skf-analyze-source/references/init.md +12 -25
  39. package/src/skf-analyze-source/references/map-and-detect.md +8 -20
  40. package/src/skf-analyze-source/references/recommend.md +4 -14
  41. package/src/skf-analyze-source/references/scan-project.md +3 -11
  42. package/src/skf-analyze-source/references/step-auto-scope.md +42 -180
  43. package/src/skf-analyze-source/references/unit-detection-heuristics.md +2 -2
  44. package/src/skf-audit-skill/SKILL.md +9 -6
  45. package/src/skf-audit-skill/customize.toml +2 -0
  46. package/src/skf-audit-skill/references/init.md +58 -32
  47. package/src/skf-audit-skill/references/re-index.md +15 -34
  48. package/src/skf-audit-skill/references/report.md +11 -58
  49. package/src/skf-audit-skill/references/semantic-diff.md +4 -22
  50. package/src/skf-audit-skill/references/severity-classify.md +53 -87
  51. package/src/skf-audit-skill/references/step-doc-drift.md +49 -19
  52. package/src/skf-audit-skill/references/structural-diff.md +43 -68
  53. package/src/skf-brief-skill/SKILL.md +7 -36
  54. package/src/skf-brief-skill/assets/scope-templates.md +1 -1
  55. package/src/skf-brief-skill/customize.toml +14 -0
  56. package/src/skf-brief-skill/references/analyze-target.md +6 -14
  57. package/src/skf-brief-skill/references/confirm-brief.md +2 -14
  58. package/src/skf-brief-skill/references/draft-checkpoint.md +8 -8
  59. package/src/skf-brief-skill/references/gather-intent.md +19 -22
  60. package/src/skf-brief-skill/references/headless-args.md +1 -1
  61. package/src/skf-brief-skill/references/health-check.md +1 -22
  62. package/src/skf-brief-skill/references/invocation-contract.md +37 -0
  63. package/src/skf-brief-skill/references/scope-definition.md +4 -14
  64. package/src/skf-brief-skill/references/step-auto-brief.md +1 -5
  65. package/src/skf-brief-skill/references/step-auto-validate.md +1 -5
  66. package/src/skf-brief-skill/references/version-resolution.md +1 -1
  67. package/src/skf-brief-skill/references/write-brief.md +17 -10
  68. package/src/skf-campaign/SKILL.md +15 -84
  69. package/src/skf-campaign/customize.toml +2 -0
  70. package/src/skf-campaign/manifest.yaml +4 -0
  71. package/src/skf-campaign/references/campaign-contracts.md +67 -0
  72. package/src/skf-campaign/references/campaign-directive-spec.md +14 -103
  73. package/src/skf-campaign/references/step-01-setup.md +4 -5
  74. package/src/skf-campaign/references/step-02-strategy.md +8 -3
  75. package/src/skf-campaign/references/step-03-pins.md +1 -1
  76. package/src/skf-campaign/references/step-04-provenance.md +1 -1
  77. package/src/skf-campaign/references/step-05-skill-loop.md +1 -1
  78. package/src/skf-campaign/references/step-06-batch.md +7 -6
  79. package/src/skf-campaign/references/step-11-maintenance.md +2 -2
  80. package/src/skf-campaign/references/step-resume.md +9 -8
  81. package/src/skf-campaign/scripts/campaign-deps.py +10 -1
  82. package/src/skf-campaign/scripts/campaign-render-batch.py +199 -0
  83. package/src/skf-campaign/scripts/campaign-status.py +162 -0
  84. package/src/skf-campaign/templates/campaign-brief-template.yaml +1 -1
  85. package/src/skf-create-skill/SKILL.md +14 -3
  86. package/src/skf-create-skill/assets/compile-assembly-rules.md +17 -38
  87. package/src/skf-create-skill/assets/skill-sections.md +9 -100
  88. package/src/skf-create-skill/assets/tessl-dismissal-rules.md +4 -13
  89. package/src/skf-create-skill/customize.toml +13 -0
  90. package/src/skf-create-skill/references/authoritative-files-protocol.md +7 -7
  91. package/src/skf-create-skill/references/compile.md +34 -47
  92. package/src/skf-create-skill/references/component-extraction.md +8 -35
  93. package/src/skf-create-skill/references/ecosystem-check.md +9 -25
  94. package/src/skf-create-skill/references/enrich.md +4 -17
  95. package/src/skf-create-skill/references/extract.md +14 -29
  96. package/src/skf-create-skill/references/extraction-patterns-tracing.md +1 -1
  97. package/src/skf-create-skill/references/extraction-patterns.md +7 -7
  98. package/src/skf-create-skill/references/generate-artifacts.md +9 -23
  99. package/src/skf-create-skill/references/health-check.md +1 -1
  100. package/src/skf-create-skill/references/load-brief.md +16 -18
  101. package/src/skf-create-skill/references/report.md +12 -15
  102. package/src/skf-create-skill/references/source-resolution-protocols.md +3 -3
  103. package/src/skf-create-skill/references/step-auto-shard.md +52 -25
  104. package/src/skf-create-skill/references/step-doc-rot.md +30 -12
  105. package/src/skf-create-skill/references/step-doc-sources.md +2 -2
  106. package/src/skf-create-skill/references/sub/ccc-discover.md +2 -13
  107. package/src/skf-create-skill/references/sub/fetch-docs.md +8 -50
  108. package/src/skf-create-skill/references/sub/fetch-temporal.md +5 -20
  109. package/src/skf-create-skill/references/tier-degradation-rules.md +6 -8
  110. package/src/skf-create-skill/references/validate.md +59 -28
  111. package/src/skf-create-skill/scripts/scan-doc-rot.py +245 -0
  112. package/src/skf-create-stack-skill/SKILL.md +15 -9
  113. package/src/skf-create-stack-skill/assets/provenance-map-schema.md +1 -1
  114. package/src/skf-create-stack-skill/customize.toml +10 -0
  115. package/src/skf-create-stack-skill/references/compile-stack.md +7 -8
  116. package/src/skf-create-stack-skill/references/compose-mode-rules.md +2 -13
  117. package/src/skf-create-stack-skill/references/detect-integrations.md +49 -54
  118. package/src/skf-create-stack-skill/references/detect-manifests.md +37 -30
  119. package/src/skf-create-stack-skill/references/generate-output.md +24 -75
  120. package/src/skf-create-stack-skill/references/init.md +9 -81
  121. package/src/skf-create-stack-skill/references/manifest-patterns.md +5 -35
  122. package/src/skf-create-stack-skill/references/parallel-extract.md +12 -27
  123. package/src/skf-create-stack-skill/references/rank-and-confirm.md +6 -6
  124. package/src/skf-create-stack-skill/references/report.md +27 -62
  125. package/src/skf-create-stack-skill/references/validate.md +35 -31
  126. package/src/skf-drop-skill/SKILL.md +20 -23
  127. package/src/skf-drop-skill/customize.toml +10 -0
  128. package/src/skf-drop-skill/references/execute.md +51 -31
  129. package/src/skf-drop-skill/references/headless-contract.md +18 -0
  130. package/src/skf-drop-skill/references/health-check.md +1 -13
  131. package/src/skf-drop-skill/references/report.md +42 -10
  132. package/src/skf-drop-skill/references/select.md +88 -48
  133. package/src/skf-drop-skill/scripts/dir-sizes.py +116 -0
  134. package/src/skf-export-skill/SKILL.md +17 -14
  135. package/src/skf-export-skill/assets/managed-section-format.md +2 -5
  136. package/src/skf-export-skill/customize.toml +10 -6
  137. package/src/skf-export-skill/references/generate-snippet.md +21 -35
  138. package/src/skf-export-skill/references/load-skill.md +44 -42
  139. package/src/skf-export-skill/references/multi-skill-mode.md +1 -1
  140. package/src/skf-export-skill/references/orphan-context-detection.md +11 -3
  141. package/src/skf-export-skill/references/package.md +27 -33
  142. package/src/skf-export-skill/references/preflight-snippet-root-probe.md +24 -5
  143. package/src/skf-export-skill/references/result-envelope.md +28 -0
  144. package/src/skf-export-skill/references/summary.md +11 -5
  145. package/src/skf-export-skill/references/token-report.md +42 -24
  146. package/src/skf-export-skill/references/update-context.md +32 -33
  147. package/src/skf-forger/SKILL.md +27 -39
  148. package/src/skf-forger/references/pipeline-mode.md +34 -0
  149. package/src/skf-forger/scripts/parse-pipeline.py +270 -0
  150. package/src/skf-quick-skill/SKILL.md +10 -60
  151. package/src/skf-quick-skill/customize.toml +9 -0
  152. package/src/skf-quick-skill/references/batch-mode.md +6 -4
  153. package/src/skf-quick-skill/references/compile.md +15 -52
  154. package/src/skf-quick-skill/references/ecosystem-check.md +5 -20
  155. package/src/skf-quick-skill/references/finalize.md +12 -6
  156. package/src/skf-quick-skill/references/halt-contract.md +54 -0
  157. package/src/skf-quick-skill/references/health-check.md +3 -4
  158. package/src/skf-quick-skill/references/quick-extract.md +7 -18
  159. package/src/skf-quick-skill/references/registry-resolution.md +1 -23
  160. package/src/skf-quick-skill/references/resolve-target.md +27 -34
  161. package/src/skf-quick-skill/references/write-and-validate.md +10 -25
  162. package/src/skf-refine-architecture/SKILL.md +14 -7
  163. package/src/skf-refine-architecture/customize.toml +9 -0
  164. package/src/skf-refine-architecture/references/compile.md +9 -7
  165. package/src/skf-refine-architecture/references/gap-analysis.md +21 -50
  166. package/src/skf-refine-architecture/references/health-check.md +1 -1
  167. package/src/skf-refine-architecture/references/improvements.md +9 -25
  168. package/src/skf-refine-architecture/references/init.md +9 -16
  169. package/src/skf-refine-architecture/references/issue-detection.md +10 -25
  170. package/src/skf-refine-architecture/references/refinement-rules.md +4 -16
  171. package/src/skf-refine-architecture/references/report.md +13 -10
  172. package/src/skf-rename-skill/SKILL.md +11 -21
  173. package/src/skf-rename-skill/customize.toml +10 -0
  174. package/src/skf-rename-skill/references/execute.md +107 -78
  175. package/src/skf-rename-skill/references/exit-codes.md +12 -0
  176. package/src/skf-rename-skill/references/report.md +16 -8
  177. package/src/skf-rename-skill/references/select.md +69 -42
  178. package/src/skf-rename-skill/scripts/skf-validate-rename-name.py +161 -0
  179. package/src/skf-setup/SKILL.md +20 -12
  180. package/src/skf-setup/customize.toml +10 -0
  181. package/src/skf-setup/references/auto-index.md +9 -10
  182. package/src/skf-setup/references/ccc-index.md +14 -15
  183. package/src/skf-setup/references/detect-and-tier.md +6 -8
  184. package/src/skf-setup/references/report.md +22 -31
  185. package/src/skf-setup/references/tier-rules.md +2 -32
  186. package/src/skf-setup/references/write-config.md +9 -10
  187. package/src/skf-test-skill/SKILL.md +10 -8
  188. package/src/skf-test-skill/customize.toml +2 -0
  189. package/src/skf-test-skill/references/coherence-check.md +19 -31
  190. package/src/skf-test-skill/references/coverage-check.md +109 -75
  191. package/src/skf-test-skill/references/detect-mode.md +10 -41
  192. package/src/skf-test-skill/references/external-validators.md +11 -19
  193. package/src/skf-test-skill/references/init.md +38 -20
  194. package/src/skf-test-skill/references/migration-section-rules.md +4 -4
  195. package/src/skf-test-skill/references/report.md +60 -40
  196. package/src/skf-test-skill/references/score.md +32 -64
  197. package/src/skf-test-skill/references/scoring-rules.md +6 -62
  198. package/src/skf-test-skill/references/source-access-protocol.md +6 -6
  199. package/src/skf-test-skill/references/step-hard-gate.md +1 -3
  200. package/src/skf-test-skill/scripts/aggregate-coherence.py +276 -0
  201. package/src/skf-test-skill/scripts/check-metadata-coherence.py +359 -0
  202. package/src/skf-test-skill/scripts/combine-external-scores.py +190 -0
  203. package/src/skf-test-skill/scripts/compute-score.py +131 -1
  204. package/src/skf-test-skill/scripts/reconcile-coverage.py +327 -0
  205. package/src/skf-test-skill/scripts/validate-inventory.py +251 -0
  206. package/src/skf-test-skill/scripts/verify-declared-numerator.py +192 -0
  207. package/src/skf-update-skill/SKILL.md +17 -5
  208. package/src/skf-update-skill/customize.toml +14 -0
  209. package/src/skf-update-skill/references/detect-changes.md +19 -37
  210. package/src/skf-update-skill/references/health-check.md +3 -9
  211. package/src/skf-update-skill/references/init.md +39 -32
  212. package/src/skf-update-skill/references/manual-section-rules.md +1 -2
  213. package/src/skf-update-skill/references/merge-conflict-rules.md +1 -52
  214. package/src/skf-update-skill/references/merge.md +13 -57
  215. package/src/skf-update-skill/references/re-extract.md +12 -24
  216. package/src/skf-update-skill/references/report.md +14 -7
  217. package/src/skf-update-skill/references/validate.md +32 -30
  218. package/src/skf-update-skill/references/write.md +86 -51
  219. package/src/skf-update-skill/scripts/skf-new-file-diff.py +167 -0
  220. package/src/skf-verify-stack/SKILL.md +11 -21
  221. package/src/skf-verify-stack/customize.toml +12 -3
  222. package/src/skf-verify-stack/references/coverage-patterns.md +1 -29
  223. package/src/skf-verify-stack/references/coverage.md +21 -10
  224. package/src/skf-verify-stack/references/exit-codes.md +14 -0
  225. package/src/skf-verify-stack/references/health-check.md +1 -1
  226. package/src/skf-verify-stack/references/init.md +20 -25
  227. package/src/skf-verify-stack/references/integration-verification-rules.md +10 -19
  228. package/src/skf-verify-stack/references/integrations.md +44 -49
  229. package/src/skf-verify-stack/references/report.md +28 -34
  230. package/src/skf-verify-stack/references/requirements.md +3 -3
  231. package/src/skf-verify-stack/references/synthesize.md +36 -39
  232. package/src/skf-verify-stack/scripts/skf-coverage-tally.py +196 -0
  233. package/src/skf-verify-stack/scripts/skf-report-delta.py +256 -0
  234. package/src/skf-verify-stack/scripts/skf-verdict-rollup.py +258 -0
  235. package/src/skf-rename-skill/references/rebuild-context.md +0 -110
@@ -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
 
@@ -54,6 +64,8 @@ If a report is located, set `test_report_path` in context to the resolved absolu
54
64
 
55
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.
56
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
+
57
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").
58
70
 
59
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.
@@ -81,8 +93,8 @@ if [ -f "$LOCK" ]; then
81
93
  # (LLM emits SKF_UPDATE_RESULT_JSON status=halted-for-concurrent-run, see below)
82
94
  exit 1
83
95
  fi
84
- # Stale lock (PID is dead) log + overwrite
85
- 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)"
86
98
  fi
87
99
 
88
100
  # Acquire: write our PID + start timestamp (one per line)
@@ -96,9 +108,9 @@ printf '%s\n%s\n' "$$" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" > "$LOCK"
96
108
 
97
109
  **Release contract:**
98
110
 
99
- - The terminal health-check step (step 8) deletes the lock file as its final action.
100
- - **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.
101
- - 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.
102
114
 
103
115
  ### 2. Validate Required Artifacts
104
116
 
@@ -113,7 +125,7 @@ printf '%s\n%s\n' "$$" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" > "$LOCK"
113
125
 
114
126
  **Detect skill type from metadata:**
115
127
  - If `skill_type == "single"` or absent: flag as single skill
116
- - 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
117
129
 
118
130
  ### Stack Skill Guard
119
131
 
@@ -126,6 +138,8 @@ After loading metadata.json, check `skill_type`:
126
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."
127
139
  - Exit the workflow (do not proceed to step 2)
128
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
+
129
143
  ### 3. Load Forge Tier Configuration
130
144
 
131
145
  **Load `{sidecar_path}/forge-tier.yaml`:**
@@ -160,18 +174,22 @@ Select: [D] Degraded / [X] Abort"
160
174
  - If D: set `degraded_mode = true`, proceed with full extraction scope
161
175
  - If X: **ABORT**
162
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
+
163
181
  ### 5. Load [MANUAL] Section Inventory
164
182
 
165
- 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).
166
184
 
167
- **Scan SKILL.md for [MANUAL] sections:**
168
- - Count all `<!-- [MANUAL:*] -->` markers
169
- - Map each [MANUAL] block to its parent section (by heading hierarchy)
170
- - 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
+ ```
171
191
 
172
- **For stack skills, also scan:**
173
- - All `references/*.md` files for [MANUAL] markers
174
- - 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}`).
175
193
 
176
194
  ### 6. Resolve Source Code Path
177
195
 
@@ -186,6 +204,8 @@ Load {manualSectionRulesFile} to understand [MANUAL] detection patterns.
186
204
  Provide the current source code path:
187
205
  **Path:** {user provides path}"
188
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
+
189
209
  ### 7. Present Baseline Summary
190
210
 
191
211
  "**Update Skill Baseline:**
@@ -193,7 +213,7 @@ Provide the current source code path:
193
213
  | Property | Value |
194
214
  |----------|-------|
195
215
  | **Skill** | {skill_name} |
196
- | **Type** | {single/stack} |
216
+ | **Type** | single |
197
217
  | **Version** | {version} |
198
218
  | **Created** | {created date} |
199
219
  | **Source** | {source_root} |
@@ -210,22 +230,9 @@ Provide the current source code path:
210
230
 
211
231
  **Ready to detect changes and update this skill?**"
212
232
 
213
- ### 8. Present MENU OPTIONS
214
-
215
- Display: "**Select:** [C] Continue to Change Detection"
216
-
217
- #### Menu Handling Logic:
218
-
219
- - IF C: Load, read entire file, then execute {nextStepFile}
220
- - IF Any other: help user respond, then [Redisplay Menu Options](#8-present-menu-options)
221
-
222
- #### EXECUTION RULES:
223
-
224
- - ALWAYS halt and wait for user input after presenting menu
225
- - **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.
226
- - ONLY proceed to next step when user selects 'C'
233
+ ### 8. Confirmation Gate
227
234
 
228
- ## 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}.
229
236
 
230
- 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`.
231
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
 
@@ -28,7 +28,7 @@ Perform tier-aware extraction on only the changed files identified in step 02, p
28
28
  - Only extract files in the change manifest — do not touch unchanged files. **Exception (gap-driven mode):** §0a's Targeted Re-Extraction Branch also scans files listed in each manifest entry's `remediation_paths[]` to resolve citation-less Critical/High gaps.
29
29
  - For each changed file, launch a subprocess for deep AST analysis (Pattern 2); if unavailable, extract sequentially
30
30
 
31
- ## MANDATORY SEQUENCE
31
+ ## Steps
32
32
 
33
33
  ### 0. Check for Gap-Driven Mode
34
34
 
@@ -45,7 +45,7 @@ uv run {checkWorkspaceDriftHelper} <source-root> \
45
45
  [--allow-drift]
46
46
  ```
47
47
 
48
- Pass `--allow-drift` only when the user provided `--allow-workspace-drift` to update-skill. The helper accepts `""` and `"local"` as the "no pinned commit" sentinels; it also auto-skips when `source_root` is not a git working tree (bare checkout, tarball extract, etc.). **For per-repo pinned-commit maps (stack skills with no single commit):** the caller must skip the helper entirely — pass nothing and log `workspace_drift_check: skipped (no pinned commit)` directly.
48
+ Pass `--allow-drift` only when the user provided `--allow-workspace-drift` to update-skill. The helper accepts `""` and `"local"` as the "no pinned commit" sentinels; it also auto-skips when `source_root` is not a git working tree (bare checkout, tarball extract, etc.).
49
49
 
50
50
  The helper emits a result envelope:
51
51
 
@@ -63,7 +63,7 @@ The helper emits a result envelope:
63
63
 
64
64
  - **`ok` or `skipped`** (helper exit 0): log `log_message` and continue to bullet 1.
65
65
  - **`overridden`** (helper exit 0): log `log_message`, surface a visible warning in the final report ("**Workspace drift accepted via --allow-workspace-drift** — spot-checks read HEAD {head_short_sha}, not pinned {pinned_commit}"), and continue to bullet 1. The override does not automatically re-pin `metadata.source_commit`; re-pinning is explicit user work (run the normal-mode update-skill flow against the same HEAD, or re-create the skill).
66
- - **`mismatch`** (helper exit 2): HALT immediately with exit status `halted-for-workspace-drift`. Display the helper's `halt_message` verbatim — it already substitutes `{pinned_commit}`, `{source_ref or "unset"}`, `{source_root}`, `{head_sha}`, and the suggested `git checkout` command. Do not proceed to bullet 1. Step-04 merge has not run; no partial writes.
66
+ - **`mismatch`** (helper exit 2): HALT immediately with status `halted-for-workspace-drift`. Display the helper's `halt_message` verbatim — it already substitutes `{pinned_commit}`, `{source_ref or "unset"}`, `{source_root}`, `{head_sha}`, and the suggested `git checkout` command. Do not proceed to bullet 1. Step-04 merge has not run; no partial writes. In `{headless_mode}`, emit the halt envelope per SKILL.md §Headless (`error: {phase: "re-extract:workspace-drift", path: "{source_root}", reason: "..."}`).
67
67
 
68
68
  1. Use the provenance map already loaded in step 1 (at `{forge_version}/provenance-map.json`) — do not re-read
69
69
  2. **Partition by change category, then iterate the export-bearing entries.** Entries that do not name an export skip the per-export verification below — they have no symbol to resolve against source:
@@ -173,7 +173,7 @@ The helper emits a result envelope:
173
173
  c) Downgrade the gap(s) to Medium/Low/Info (accepts the degraded documentation outcome).
174
174
  ```
175
175
 
176
- Exit with status `halted-for-remediation-path`. Step-04 merge has not run; no partial writes.
176
+ Exit with status `halted-for-remediation-path`. Step-04 merge has not run; no partial writes. In `{headless_mode}`, emit the halt envelope per SKILL.md §Headless (`error: {phase: "re-extract:targeted-reextraction", reason: "..."}`).
177
177
 
178
178
  6. **Success summary** — record `targeted_reextraction: {resolved_count, files_scanned, exports_matched, tier}` in workflow context. The evidence report (step 6 §4) surfaces this alongside the verified / moved / missing tally.
179
179
 
@@ -223,7 +223,7 @@ The helper emits a result envelope:
223
223
 
224
224
  **Forge tier (AST structural extraction):**
225
225
 
226
- ⚠️ **CRITICAL:** Load and follow the **AST Extraction Protocol** from `{extractionPatternsData}`. Use the decision tree based on the number of changed files: prefer MCP `find_code()` for small sets, `find_code_by_rule()` with scoped YAML rules for medium sets, and CLI `--json=stream` with line-by-line streaming for large sets. Never use `ast-grep --json` (without `=stream`) — it loads the entire result set into memory and will fail on large codebases.
226
+ Load and follow the **AST Extraction Protocol** from `{extractionPatternsData}`. Use the decision tree based on the number of changed files: prefer MCP `find_code()` for small sets, `find_code_by_rule()` with scoped YAML rules for medium sets, and CLI `--json=stream` with line-by-line streaming for large sets. Never use `ast-grep --json` (without `=stream`) — it loads the entire result set into memory and will fail on large codebases.
227
227
 
228
228
  - Extract: function signatures, type definitions, class members, exported constants
229
229
  - Extract: parameter types, return types, JSDoc/docstring comments
@@ -243,17 +243,11 @@ The helper emits a result envelope:
243
243
 
244
244
  **Skip authoritative doc paths.** Before iterating the change manifest, build a skip set from `promoted_docs_new[]` (populated by step 2 §1b) and any existing `file_entries[]` entries with `file_type: "doc"` from the provenance map. These are documentation files tracked for drift detection only — they must not reach AST extraction, which would produce ghost entries on non-code content. If a change manifest entry matches the skip set, skip it silently and continue; doc-type drift is handled by step 2 Category D and step 4 Priority 6/7.
245
245
 
246
- DO NOT BE LAZY — For EACH remaining file in the change manifest with status MODIFIED, ADDED, or RENAMED, launch a subprocess that:
246
+ For each remaining file in the change manifest with status MODIFIED, ADDED, or RENAMED, launch a subprocess that:
247
247
 
248
248
  1. Loads the source file
249
249
  2. Performs tier-appropriate extraction (Quick/Forge/Forge+/Deep)
250
- 3. For each export found:
251
- - Record: export name, type (function/class/type/constant), signature
252
- - Record: file path, start line, end line
253
- - Record: parameters with types (if function/method)
254
- - Record: return type (if function/method)
255
- - Record: JSDoc/docstring summary (if present)
256
- - Label: confidence tier (T1/T1-low/T2)
250
+ 3. Extract each export into the per-file return contract shown in bullet 4.
257
251
  4. **Return contract.** Each extraction worker returns ONLY this per-file block — no prose, no commentary, no markdown fences (the parent strips wrapping fences before parsing). The shape is exactly the per-file record §4 aggregates (the `Per-file extractions` block, lines below), so the parent appends it verbatim rather than re-parsing free text:
258
252
 
259
253
  ```json
@@ -291,7 +285,7 @@ This helps the merge step (section 4) prioritize which changes are most likely t
291
285
 
292
286
  CCC failures: skip ranking silently, all changes treated equally.
293
287
 
294
- **Note on remote sources:** If `source_root` is a workspace clone, the CCC index may already exist from a prior forge and can be reused via `ccc search --refresh`. If the source is an ephemeral fallback clone, the clone path is not indexed by CCC — the search will return empty results and semantic ranking will be skipped. Deferred CCC indexing is implemented in create-skill step 3 but not in update-skill. All changes are treated equally for ephemeral remote sources.
288
+ **Note on remote sources:** If `source_root` is a workspace clone, the CCC index may already exist from a prior forge and can be reused via `ccc search --refresh`. If the source is an ephemeral fallback clone, the clone path is not indexed by CCC — the search returns empty results, so semantic ranking is skipped and all changes are treated equally.
295
289
 
296
290
  **IF `tools.ccc` is false:** Skip this section silently.
297
291
 
@@ -356,16 +350,10 @@ Extraction Results:
356
350
 
357
351
  **Proceeding to merge with existing skill...**"
358
352
 
359
- ### 6. Present MENU OPTIONS
353
+ ### 6. Route to Next Step
360
354
 
361
- - **If `dry_run_mode` is true:** display "**Dry-run mode skipping merge/validate/write.** Loading report..." and load `report.md` (NOT `{nextStepFile}`). The report emits the dry-run envelope describing what merge+write WOULD have done.
362
- - Else, display "**Proceeding to merge...**" and after extraction results are compiled, immediately load, read entire file, then execute `{nextStepFile}`.
363
- - This is an auto-proceed step with no user choices.
355
+ This step auto-proceeds no user choices. Once all changed files are extracted and results compiled, load and fully read the next file, then execute it, per the branch that applies:
364
356
 
365
- ## CRITICAL STEP COMPLETION NOTE
366
-
367
- ONLY WHEN all changed files have been extracted and results compiled will you load the next file:
368
-
369
- - `dry_run_mode == true` → load `report.md`. Report emits status `dry-run`. No artifact is modified on disk by this run.
370
- - Otherwise → load `{nextStepFile}` (merge.md) to begin the merge operation.
357
+ - **`dry_run_mode == true`** → display "**Dry-run mode — skipping merge/validate/write.** Loading report..." and load `report.md` (NOT `{nextStepFile}`); it emits status `dry-run` describing what merge+write would have done. No artifact is modified on disk by this run.
358
+ - **Otherwise** → display "**Proceeding to merge...**" and load `{nextStepFile}` (merge.md) to begin the merge operation.
371
359
 
@@ -16,7 +16,7 @@ Present a comprehensive change summary showing what was updated, [MANUAL] sectio
16
16
  - Present clear, actionable summary with next step recommendations
17
17
  - Chains to the local health-check step via `{nextStepFile}` after completion — the user-facing summary is NOT the terminal step
18
18
 
19
- ## MANDATORY SEQUENCE
19
+ ## Steps
20
20
 
21
21
  ### 1. Handle No-Change Shortcut
22
22
 
@@ -89,7 +89,7 @@ The headless envelope carries `status: "dry-run"`, `files_written: []`, the `hea
89
89
 
90
90
  | Metric | Value |
91
91
  |--------|-------|
92
- | **Skill** | {skill_name} ({single/stack}) |
92
+ | **Skill** | {skill_name} |
93
93
  | **Forge Tier** | {tier} |
94
94
  | **Mode** | {update_mode}{mode_fallback_note} |
95
95
  | **Duration** | {step count} steps |
@@ -169,7 +169,6 @@ These signals also appear in `warnings[]` on the headless envelope; the Mode row
169
169
  | `{resolved_skill_package}/metadata.json` | Updated |
170
170
  | `{forge_version}/provenance-map.json` | Updated |
171
171
  | `{forge_version}/evidence-report.md` | Appended |
172
- | {stack reference files if applicable} | Updated |
173
172
 
174
173
  Where `{resolved_skill_package}` = `{skills_output_folder}/{skill_name}/{version}/{skill_name}/` and `{forge_version}` = `{forge_data_folder}/{skill_name}/{version}/` — see `knowledge/version-paths.md`."
175
174
 
@@ -199,16 +198,24 @@ Write the result contract per `shared/references/output-contract-schema.md`: the
199
198
  **Headless envelope (`SKF_UPDATE_RESULT_JSON`):** when `{headless_mode}` is true, ALSO emit a single-line JSON envelope to stdout prefixed with the literal `SKF_UPDATE_RESULT_JSON: `. Schema: `src/shared/scripts/schemas/skf-update-result-envelope.v1.json`. Construct the envelope from in-context state:
200
199
 
201
200
  ```json
202
- SKF_UPDATE_RESULT_JSON: {"skf_update":{"status":"success|no-changes|halted-for-*|blocked","skill_name":"<name>","version":"<v>","previous_version":"<v>","update_mode":"normal|gap-driven|degraded","files_written":[...],"headless_decisions":[...],"warnings":[...],"error":null|{...}}}
201
+ SKF_UPDATE_RESULT_JSON: {"skf_update":{"status":"success|no-changes|detect-only|dry-run|halted-for-*|blocked","skill_name":"<name>","version":"<v>","previous_version":"<v>","update_mode":"normal|gap-driven|degraded","files_written":[...],"headless_decisions":[...],"warnings":[...],"error":null|{...}}}
203
202
  ```
204
203
 
205
- - `headless_decisions[]` — verbatim from the in-context array populated by gates (init.md §confirmation, detect-changes.md §1b/§1c/§2.2, merge.md §gate). Each entry `{gate, default_action, taken_action, reason, evidence?}`. Empty when no gates auto-resolved (e.g. no-changes path skipped detect-changes' gates).
206
- - `status` — single-field outcome for pipeline branching. `"success"` when the run wrote artifacts and produced no halts; `"no-changes"` when §1 short-circuited; one of the documented `halted-for-*` codes when a halt fired; `"blocked"` as the catch-all.
204
+ - `headless_decisions[]` — verbatim from the in-context array populated by gates (init.md §confirmation and §4 degraded-rebuild, detect-changes.md §1b/§1c/§2.2, merge.md §gate). Each entry `{gate, default_action, taken_action, reason, evidence?}`. Empty when no gates auto-resolved (e.g. no-changes path skipped detect-changes' gates).
205
+ - `status` — single-field outcome for pipeline branching. `"success"` when the run wrote artifacts and produced no halts; `"no-changes"` when §1 short-circuited; `"detect-only"` / `"dry-run"` for the §1a/§1b read-only exits; one of the documented `halted-for-*` codes when a halt fired; `"blocked"` as the catch-all. The full enum lives in the schema (this step emits the value already resolved in context).
207
206
  - `error` — null on success or no-changes. Object `{phase, path?, reason}` describing the failure when a halt or write error fired. Pipelines branch on `error !== null` for non-zero exit semantics.
208
207
 
209
208
  The headless envelope is the structured channel; the per-run JSON written above is the audit trail. Both coexist — the envelope is one line on stdout for grep-friendly consumption, the per-run JSON is the full record on disk.
210
209
 
210
+ **Post-finalization hook.** If `{onCompleteCommand}` (resolved in SKILL.md On Activation §3 from `workflow.on_complete`) is non-empty, invoke it after both result-JSON writes complete:
211
+
212
+ ```bash
213
+ {onCompleteCommand} --result-path={forge_version}/update-skill-result-latest.json
214
+ ```
215
+
216
+ Run it with a bounded timeout (default 60s). On success, log an Info note and continue; on non-zero exit, timeout, or any failure, append the reason to `warnings[]` (surfaced on the headless envelope) and continue. The hook must never fail the workflow — it is integration glue (notify a CI router, chain audit/export/test) orthogonal to the update outcome. Empty `{onCompleteCommand}` = no-op, no log entry.
217
+
211
218
  ### 6. Chain to Health Check
212
219
 
213
- ONLY WHEN the change summary has been presented, files-written list displayed, and result contract saved 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.
220
+ Once the change summary has been presented, the files-written list displayed, and the result contract saved, load, read the full file, and execute `{nextStepFile}`. The health-check step is the true terminal step — do not stop at the report even though it reads as final.
214
221