bmad-module-skill-forge 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/README.md +0 -8
  3. package/docs/_data/pinned.yaml +1 -1
  4. package/docs/_internal/STABILITY.md +1 -1
  5. package/docs/architecture.md +2 -2
  6. package/docs/examples.md +1 -1
  7. package/docs/workflows.md +5 -5
  8. package/package.json +2 -2
  9. package/src/README.md +1 -1
  10. package/src/knowledge/ccc-bridge.md +12 -12
  11. package/src/knowledge/qmd-registry.md +5 -5
  12. package/src/shared/health-check.md +5 -5
  13. package/src/shared/references/description-guard-protocol.md +100 -0
  14. package/src/shared/references/output-contract-schema.md +1 -1
  15. package/src/shared/scripts/schemas/skf-brief-result-envelope.v1.json +6 -6
  16. package/src/shared/scripts/schemas/skf-setup-result-envelope.v1.json +9 -3
  17. package/src/shared/scripts/schemas/skf-update-result-envelope.v1.json +149 -0
  18. package/src/shared/scripts/schemas/skill-brief.v1.json +22 -2
  19. package/src/shared/scripts/skf-build-change-manifest.py +420 -0
  20. package/src/shared/scripts/skf-check-workspace-drift.py +321 -0
  21. package/src/shared/scripts/skf-compare-file-hashes.py +357 -0
  22. package/src/shared/scripts/skf-description-guard.py +359 -0
  23. package/src/shared/scripts/skf-detect-language.py +2 -2
  24. package/src/shared/scripts/skf-detect-scripts-assets.py +613 -0
  25. package/src/shared/scripts/skf-detect-tools.py +97 -8
  26. package/src/shared/scripts/skf-detect-workspaces.py +1 -1
  27. package/src/shared/scripts/skf-disqualify-candidates.py +576 -0
  28. package/src/shared/scripts/skf-emit-brief-result-envelope.py +3 -3
  29. package/src/shared/scripts/skf-emit-result-envelope.py +93 -9
  30. package/src/shared/scripts/skf-enumerate-stack-skills.py +514 -0
  31. package/src/shared/scripts/skf-forge-tier-rw.py +11 -11
  32. package/src/shared/scripts/skf-hash-content.py +284 -0
  33. package/src/shared/scripts/skf-load-provenance.py +295 -0
  34. package/src/shared/scripts/skf-merge-ccc-exclusions.py +45 -1
  35. package/src/shared/scripts/skf-pair-intersect.py +250 -0
  36. package/src/shared/scripts/skf-provenance-gap-dispatch.py +433 -0
  37. package/src/shared/scripts/skf-qmd-classify-collections.py +42 -8
  38. package/src/shared/scripts/skf-recommend-scope-type.py +2 -2
  39. package/src/shared/scripts/skf-render-quick-metadata.py +2 -2
  40. package/src/shared/scripts/skf-resolve-authoritative-files.py +504 -0
  41. package/src/shared/scripts/skf-scan-manifests.py +738 -0
  42. package/src/shared/scripts/skf-scan-skill-md-structure.py +375 -0
  43. package/src/shared/scripts/skf-update-active-symlink.py +315 -0
  44. package/src/shared/scripts/skf-validate-brief-inputs.py +5 -5
  45. package/src/shared/scripts/skf-validate-brief-schema.py +348 -0
  46. package/src/shared/scripts/skf-write-skill-brief.py +61 -5
  47. package/src/skf-analyze-source/SKILL.md +69 -16
  48. package/src/skf-analyze-source/assets/skill-brief-schema.md +1 -1
  49. package/src/skf-analyze-source/customize.toml +55 -0
  50. package/src/skf-analyze-source/{steps-c/step-01b-continue.md → references/continue.md} +12 -12
  51. package/src/skf-analyze-source/{steps-c/step-06-generate-briefs.md → references/generate-briefs.md} +29 -10
  52. package/src/skf-analyze-source/{steps-c/step-07-health-check.md → references/health-check.md} +5 -3
  53. package/src/skf-analyze-source/{steps-c/step-03-identify-units.md → references/identify-units.md} +44 -14
  54. package/src/skf-analyze-source/{steps-c/step-01-init.md → references/init.md} +27 -6
  55. package/src/skf-analyze-source/{steps-c/step-04-map-and-detect.md → references/map-and-detect.md} +52 -25
  56. package/src/skf-analyze-source/{steps-c/step-05-recommend.md → references/recommend.md} +15 -8
  57. package/src/skf-analyze-source/{steps-c/step-02-scan-project.md → references/scan-project.md} +12 -10
  58. package/src/skf-analyze-source/references/unit-detection-heuristics.md +2 -0
  59. package/src/skf-analyze-source/templates/analysis-report-template.md +6 -6
  60. package/src/skf-audit-skill/SKILL.md +66 -15
  61. package/src/skf-audit-skill/assets/drift-report-template.md +6 -5
  62. package/src/skf-audit-skill/customize.toml +49 -0
  63. package/src/skf-audit-skill/{steps-c/step-07-health-check.md → references/health-check.md} +5 -3
  64. package/src/skf-audit-skill/references/init.md +305 -0
  65. package/src/skf-audit-skill/{steps-c/step-02-re-index.md → references/re-index.md} +11 -11
  66. package/src/skf-audit-skill/{steps-c/step-06-report.md → references/report.md} +25 -7
  67. package/src/skf-audit-skill/{steps-c/step-04-semantic-diff.md → references/semantic-diff.md} +6 -6
  68. package/src/skf-audit-skill/{steps-c/step-05-severity-classify.md → references/severity-classify.md} +5 -5
  69. package/src/skf-audit-skill/references/severity-rules.md +2 -0
  70. package/src/skf-audit-skill/{steps-c/step-03-structural-diff.md → references/structural-diff.md} +29 -16
  71. package/src/skf-brief-skill/SKILL.md +48 -18
  72. package/src/skf-brief-skill/assets/description-voice-examples.md +1 -1
  73. package/src/skf-brief-skill/assets/skill-brief-schema.md +32 -2
  74. package/src/skf-brief-skill/customize.toml +44 -0
  75. package/src/skf-brief-skill/{steps-c/step-02-analyze-target.md → references/analyze-target.md} +5 -5
  76. package/src/skf-brief-skill/{steps-c/step-04-confirm-brief.md → references/confirm-brief.md} +13 -10
  77. package/src/skf-brief-skill/references/draft-checkpoint.md +4 -4
  78. package/src/skf-brief-skill/{steps-c/step-01-gather-intent.md → references/gather-intent.md} +24 -24
  79. package/src/skf-brief-skill/references/headless-args.md +9 -9
  80. package/src/skf-brief-skill/references/headless-source-authority-detection.md +1 -1
  81. package/src/skf-brief-skill/{steps-c/step-06-health-check.md → references/health-check.md} +4 -2
  82. package/src/skf-brief-skill/references/portfolio-similarity-check.md +2 -2
  83. package/src/skf-brief-skill/references/qmd-collection-registration.md +1 -1
  84. package/src/skf-brief-skill/{steps-c/step-03-scope-definition.md → references/scope-definition.md} +19 -16
  85. package/src/skf-brief-skill/references/version-resolution.md +2 -2
  86. package/src/skf-brief-skill/{steps-c/step-05-write-brief.md → references/write-brief.md} +11 -10
  87. package/src/skf-create-skill/SKILL.md +25 -19
  88. package/src/skf-create-skill/assets/compile-assembly-rules.md +3 -3
  89. package/src/skf-create-skill/assets/skill-sections.md +5 -5
  90. package/src/skf-create-skill/assets/tessl-dismissal-rules.md +11 -11
  91. package/src/skf-create-skill/customize.toml +35 -0
  92. package/src/skf-create-skill/references/authoritative-files-protocol.md +142 -0
  93. package/src/skf-create-skill/{steps-c/step-05-compile.md → references/compile.md} +16 -16
  94. package/src/skf-create-skill/{steps-c/step-03d-component-extraction.md → references/component-extraction.md} +16 -16
  95. package/src/skf-create-skill/{steps-c/step-02-ecosystem-check.md → references/ecosystem-check.md} +4 -4
  96. package/src/skf-create-skill/{steps-c/step-04-enrich.md → references/enrich.md} +3 -3
  97. package/src/skf-create-skill/{steps-c/step-03-extract.md → references/extract.md} +52 -120
  98. package/src/skf-create-skill/references/extraction-patterns.md +8 -8
  99. package/src/skf-create-skill/{steps-c/step-07-generate-artifacts.md → references/generate-artifacts.md} +17 -9
  100. package/src/skf-create-skill/{steps-c/step-09-health-check.md → references/health-check.md} +4 -2
  101. package/src/skf-create-skill/{steps-c/step-01-load-brief.md → references/load-brief.md} +40 -32
  102. package/src/skf-create-skill/{steps-c/step-08-report.md → references/report.md} +8 -8
  103. package/src/skf-create-skill/references/source-resolution-protocols.md +6 -6
  104. package/src/skf-create-skill/{steps-c/sub/step-02b-ccc-discover.md → references/sub/ccc-discover.md} +5 -5
  105. package/src/skf-create-skill/{steps-c/sub/step-03c-fetch-docs.md → references/sub/fetch-docs.md} +28 -12
  106. package/src/skf-create-skill/{steps-c/sub/step-03b-fetch-temporal.md → references/sub/fetch-temporal.md} +81 -50
  107. package/src/skf-create-skill/{steps-c/step-06-validate.md → references/validate.md} +46 -26
  108. package/src/skf-create-stack-skill/SKILL.md +76 -17
  109. package/src/skf-create-stack-skill/assets/provenance-map-schema.md +102 -0
  110. package/src/skf-create-stack-skill/assets/stack-skill-template.md +1 -1
  111. package/src/skf-create-stack-skill/customize.toml +46 -0
  112. package/src/skf-create-stack-skill/{steps-c/step-06-compile-stack.md → references/compile-stack.md} +6 -5
  113. package/src/skf-create-stack-skill/references/compose-mode-rules.md +3 -1
  114. package/src/skf-create-stack-skill/{steps-c/step-05-detect-integrations.md → references/detect-integrations.md} +32 -11
  115. package/src/skf-create-stack-skill/{steps-c/step-02-detect-manifests.md → references/detect-manifests.md} +28 -28
  116. package/src/skf-create-stack-skill/{steps-c/step-07-generate-output.md → references/generate-output.md} +11 -85
  117. package/src/skf-create-stack-skill/{steps-c/step-10-health-check.md → references/health-check.md} +4 -2
  118. package/src/skf-create-stack-skill/{steps-c/step-01-init.md → references/init.md} +70 -4
  119. package/src/skf-create-stack-skill/references/integration-patterns.md +2 -0
  120. package/src/skf-create-stack-skill/references/manifest-patterns.md +2 -0
  121. package/src/skf-create-stack-skill/{steps-c/step-04-parallel-extract.md → references/parallel-extract.md} +40 -17
  122. package/src/skf-create-stack-skill/{steps-c/step-03-rank-and-confirm.md → references/rank-and-confirm.md} +5 -4
  123. package/src/skf-create-stack-skill/{steps-c/step-09-report.md → references/report.md} +3 -3
  124. package/src/skf-create-stack-skill/{steps-c/step-08-validate.md → references/validate.md} +6 -6
  125. package/src/skf-drop-skill/SKILL.md +84 -12
  126. package/src/skf-drop-skill/customize.toml +57 -0
  127. package/src/skf-drop-skill/{steps-c/step-02-execute.md → references/execute.md} +49 -34
  128. package/src/skf-drop-skill/{steps-c/step-04-health-check.md → references/health-check.md} +6 -4
  129. package/src/skf-drop-skill/{steps-c/step-03-report.md → references/report.md} +13 -5
  130. package/src/skf-drop-skill/{steps-c/step-01-select.md → references/select.md} +63 -15
  131. package/src/skf-export-skill/SKILL.md +85 -16
  132. package/src/skf-export-skill/assets/managed-section-format.md +3 -3
  133. package/src/skf-export-skill/assets/snippet-format.md +2 -2
  134. package/src/skf-export-skill/customize.toml +49 -0
  135. package/src/skf-export-skill/{steps-c/step-03-generate-snippet.md → references/generate-snippet.md} +18 -12
  136. package/src/skf-export-skill/{steps-c/step-07-health-check.md → references/health-check.md} +6 -4
  137. package/src/skf-export-skill/{steps-c/step-01-load-skill.md → references/load-skill.md} +21 -51
  138. package/src/skf-export-skill/references/manifest-rebuild.md +68 -0
  139. package/src/skf-export-skill/references/multi-skill-mode.md +38 -0
  140. package/src/skf-export-skill/references/orphan-context-detection.md +75 -0
  141. package/src/skf-export-skill/references/orphan-row-detection.md +102 -0
  142. package/src/skf-export-skill/{steps-c/step-02-package.md → references/package.md} +7 -7
  143. package/src/skf-export-skill/references/preflight-snippet-root-probe.md +74 -0
  144. package/src/skf-export-skill/{steps-c/step-06-summary.md → references/summary.md} +30 -6
  145. package/src/skf-export-skill/{steps-c/step-05-token-report.md → references/token-report.md} +5 -5
  146. package/src/skf-export-skill/{steps-c/step-04-update-context.md → references/update-context.md} +116 -91
  147. package/src/skf-quick-skill/SKILL.md +63 -123
  148. package/src/skf-quick-skill/customize.toml +44 -0
  149. package/src/skf-quick-skill/references/batch-mode.md +102 -0
  150. package/src/skf-quick-skill/{steps-c/step-04-compile.md → references/compile.md} +10 -10
  151. package/src/skf-quick-skill/{steps-c/step-02-ecosystem-check.md → references/ecosystem-check.md} +5 -5
  152. package/src/skf-quick-skill/{steps-c/step-06-finalize.md → references/finalize.md} +7 -7
  153. package/src/skf-quick-skill/{steps-c/step-07-health-check.md → references/health-check.md} +3 -3
  154. package/src/skf-quick-skill/{steps-c/step-03-quick-extract.md → references/quick-extract.md} +5 -5
  155. package/src/skf-quick-skill/references/registry-resolution.md +2 -0
  156. package/src/skf-quick-skill/{steps-c/step-01-resolve-target.md → references/resolve-target.md} +14 -10
  157. package/src/skf-quick-skill/{steps-c/step-05-write-and-validate.md → references/write-and-validate.md} +4 -4
  158. package/src/skf-refine-architecture/SKILL.md +86 -16
  159. package/src/skf-refine-architecture/customize.toml +49 -0
  160. package/src/skf-refine-architecture/{steps-c/step-05-compile.md → references/compile.md} +4 -4
  161. package/src/skf-refine-architecture/{steps-c/step-02-gap-analysis.md → references/gap-analysis.md} +5 -5
  162. package/src/skf-refine-architecture/{steps-c/step-07-health-check.md → references/health-check.md} +6 -4
  163. package/src/skf-refine-architecture/{steps-c/step-04-improvements.md → references/improvements.md} +5 -5
  164. package/src/skf-refine-architecture/references/init.md +144 -0
  165. package/src/skf-refine-architecture/{steps-c/step-03-issue-detection.md → references/issue-detection.md} +5 -5
  166. package/src/skf-refine-architecture/references/refinement-rules.md +2 -0
  167. package/src/skf-refine-architecture/{steps-c/step-06-report.md → references/report.md} +14 -5
  168. package/src/skf-rename-skill/SKILL.md +82 -12
  169. package/src/skf-rename-skill/customize.toml +52 -0
  170. package/src/skf-rename-skill/{steps-c/step-02-execute.md → references/execute.md} +94 -99
  171. package/src/skf-rename-skill/references/health-check.md +30 -0
  172. package/src/skf-rename-skill/references/rebuild-context.md +110 -0
  173. package/src/skf-rename-skill/{steps-c/step-03-report.md → references/report.md} +13 -5
  174. package/src/skf-rename-skill/{steps-c/step-01-select.md → references/select.md} +59 -20
  175. package/src/skf-setup/SKILL.md +35 -35
  176. package/src/skf-setup/customize.toml +33 -0
  177. package/src/skf-setup/{steps-c/step-03-auto-index.md → references/auto-index.md} +10 -18
  178. package/src/skf-setup/{steps-c/step-01b-ccc-index.md → references/ccc-index.md} +14 -22
  179. package/src/skf-setup/{steps-c/step-01-detect-and-tier.md → references/detect-and-tier.md} +23 -10
  180. package/src/skf-setup/{steps-c/step-05-health-check.md → references/health-check.md} +1 -1
  181. package/src/skf-setup/{steps-c/step-04-report.md → references/report.md} +21 -19
  182. package/src/skf-setup/references/tier-rules.md +1 -1
  183. package/src/skf-setup/{steps-c/step-02-write-config.md → references/write-config.md} +14 -13
  184. package/src/skf-test-skill/SKILL.md +77 -15
  185. package/src/skf-test-skill/customize.toml +54 -0
  186. package/src/skf-test-skill/{steps-c/step-04-coherence-check.md → references/coherence-check.md} +28 -71
  187. package/src/skf-test-skill/{steps-c/step-03-coverage-check.md → references/coverage-check.md} +16 -39
  188. package/src/skf-test-skill/{steps-c/step-02-detect-mode.md → references/detect-mode.md} +4 -26
  189. package/src/skf-test-skill/{steps-c/step-04b-external-validators.md → references/external-validators.md} +6 -28
  190. package/src/skf-test-skill/references/health-check.md +14 -0
  191. package/src/skf-test-skill/{steps-c/step-01-init.md → references/init.md} +21 -37
  192. package/src/skf-test-skill/references/migration-section-rules.md +4 -2
  193. package/src/skf-test-skill/{steps-c/step-06-report.md → references/report.md} +41 -51
  194. package/src/skf-test-skill/{steps-c/step-05-score.md → references/score.md} +26 -43
  195. package/src/skf-test-skill/references/scoring-rules.md +8 -6
  196. package/src/skf-test-skill/references/source-access-protocol.md +7 -5
  197. package/src/skf-test-skill/scripts/compute-score.py +88 -17
  198. package/src/skf-test-skill/templates/test-report-template.md +13 -13
  199. package/src/skf-update-skill/SKILL.md +23 -14
  200. package/src/skf-update-skill/customize.toml +44 -0
  201. package/src/skf-update-skill/{steps-c/step-02-detect-changes.md → references/detect-changes.md} +176 -68
  202. package/src/skf-update-skill/references/health-check.md +32 -0
  203. package/src/skf-update-skill/{steps-c/step-01-init.md → references/init.md} +56 -8
  204. package/src/skf-update-skill/references/manual-section-rules.md +4 -0
  205. package/src/skf-update-skill/references/merge-conflict-rules.md +4 -0
  206. package/src/skf-update-skill/{steps-c/step-04-merge.md → references/merge.md} +8 -8
  207. package/src/skf-update-skill/{steps-c/step-03-re-extract.md → references/re-extract.md} +53 -44
  208. package/src/skf-update-skill/references/remote-source-resolution.md +5 -1
  209. package/src/skf-update-skill/references/report.md +214 -0
  210. package/src/skf-update-skill/{steps-c/step-05-validate.md → references/validate.md} +5 -5
  211. package/src/skf-update-skill/{steps-c/step-06-write.md → references/write.md} +73 -51
  212. package/src/skf-verify-stack/SKILL.md +89 -17
  213. package/src/skf-verify-stack/assets/feasibility-report-template.md +4 -4
  214. package/src/skf-verify-stack/customize.toml +50 -0
  215. package/src/skf-verify-stack/references/coverage-patterns.md +2 -2
  216. package/src/skf-verify-stack/{steps-c/step-02-coverage.md → references/coverage.md} +7 -7
  217. package/src/skf-verify-stack/{steps-c/step-07-health-check.md → references/health-check.md} +7 -5
  218. package/src/skf-verify-stack/references/init.md +166 -0
  219. package/src/skf-verify-stack/references/integration-verification-rules.md +1 -1
  220. package/src/skf-verify-stack/{steps-c/step-03-integrations.md → references/integrations.md} +12 -12
  221. package/src/skf-verify-stack/{steps-c/step-06-report.md → references/report.md} +22 -41
  222. package/src/skf-verify-stack/{steps-c/step-04-requirements.md → references/requirements.md} +7 -7
  223. package/src/skf-verify-stack/{steps-c/step-05-synthesize.md → references/synthesize.md} +8 -8
  224. package/tools/validate-docs-drift.js +1 -1
  225. package/src/skf-audit-skill/steps-c/step-01-init.md +0 -221
  226. package/src/skf-refine-architecture/steps-c/step-01-init.md +0 -136
  227. package/src/skf-rename-skill/steps-c/step-04-health-check.md +0 -22
  228. package/src/skf-test-skill/steps-c/step-07-health-check.md +0 -25
  229. package/src/skf-update-skill/steps-c/step-07-report.md +0 -148
  230. package/src/skf-update-skill/steps-c/step-08-health-check.md +0 -22
  231. package/src/skf-verify-stack/steps-c/step-01-init.md +0 -178
@@ -1,7 +1,9 @@
1
1
  ---
2
- nextStepFile: './step-03-generate-snippet.md'
2
+ nextStepFile: 'generate-snippet.md'
3
3
  ---
4
4
 
5
+ <!-- Config: communicate in {communication_language}. Validate package contents in {document_output_language}. -->
6
+
5
7
  # Step 2: Package
6
8
 
7
9
  ## STEP GOAL:
@@ -12,21 +14,19 @@ To assemble and validate an agentskills.io-compliant package structure from the
12
14
 
13
15
  - Focus only on package structure assembly and validation — do not modify SKILL.md content
14
16
  - Auto-proceed when complete
15
- - **Multi-skill mode:** when step-01 loaded more than one skill (`len(skill_batch) > 1`), iterate sections 1–4 below per skill using each skill's `{resolved_skill_package}`. Collect per-skill status; report the aggregate in §4 as one row per skill. Halt the batch if any skill is NOT READY. See step-01 §1c.
17
+ - **Multi-skill mode:** when step 1 loaded more than one skill (`len(skill_batch) > 1`), iterate sections 1–4 below per skill using each skill's `{resolved_skill_package}`. Collect per-skill status; report the aggregate in §4 as one row per skill. Halt the batch if any skill is NOT READY. See step 1 §1c.
16
18
 
17
19
  ## MANDATORY SEQUENCE
18
20
 
19
- **CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise unless user explicitly requests a change.
20
-
21
21
  ### 1. Validate Package Structure
22
22
 
23
- Verify the skill package at `{resolved_skill_package}` (resolved in step-01 via manifest or `active` symlink — see `knowledge/version-paths.md`) contains the expected agentskills.io package layout:
23
+ Verify the skill package at `{resolved_skill_package}` (resolved in step 1 via manifest or `active` symlink — see `knowledge/version-paths.md`) contains the expected agentskills.io package layout:
24
24
 
25
25
  ```
26
26
  {skill_package} = {skills_output_folder}/{skill-name}/{version}/{skill-name}/
27
27
  ├── SKILL.md ← Required: Active skill document
28
28
  ├── metadata.json ← Required: Machine-readable metadata
29
- ├── context-snippet.md ← Will be generated/updated in step-03
29
+ ├── context-snippet.md ← Will be generated/updated in step 3
30
30
  ├── references/ ← Optional: Progressive disclosure
31
31
  │ ├── {function-a}.md
32
32
  │ └── {function-b}.md
@@ -66,7 +66,7 @@ Determine package status:
66
66
 
67
67
  **READY:** All required files present, all required metadata fields valid
68
68
  **WARNINGS:** Ready but with missing recommended fields or empty references/
69
- **NOT READY:** Missing required files or required metadata fields (should not reach here — step-01 would have halted)
69
+ **NOT READY:** Missing required files or required metadata fields (should not reach here — step 1 would have halted)
70
70
 
71
71
  ### 4. Report Package Status
72
72
 
@@ -0,0 +1,74 @@
1
+ ---
2
+ # Static reference loaded by load-skill.md §1b only when
3
+ # `snippet_skill_root_override` is UNSET in config.yaml. When the
4
+ # override is set, every existing snippet's on-disk prefix is ground
5
+ # truth by contract — no probe needed and the entire authoring-repo
6
+ # escape hatch is already configured. Loaded once per export run, not
7
+ # per skill.
8
+ ---
9
+
10
+ <!-- Config: communicate in {communication_language}. Render the warning and gate prompt in {document_output_language}. -->
11
+
12
+ # Snippet Root Prefix Mismatch — Pre-flight Probe
13
+
14
+ ## Purpose
15
+
16
+ Catch the authoring-repo case before step 4 silently rewrites root paths. In an authoring repo, skills typically live under a single shared directory (`skills/`) that does not match any per-IDE `skill_root` (`.claude/skills/`, `.cursor/skills/`, etc.). Without this probe, step 4's root-rewrite algorithm would replace the on-disk prefix with an IDE-mapped one that the snippet files do not actually reside under.
17
+
18
+ Loaded by `load-skill.md` §1b after `target_context_files` is resolved and `snippet_skill_root_override` is confirmed unset.
19
+
20
+ ## Inputs
21
+
22
+ - `target_context_files[0].skill_root` — the reference IDE-mapped skill root (used because step 3 §2.7 picks this same entry for snippet generation when no override is set)
23
+ - `{skills_output_folder}` — for manifest-driven candidate enumeration
24
+ - Current skill's snippet path (resolved via manifest / `active` symlink / flat path per `knowledge/version-paths.md`)
25
+ - `{headless_mode}` — boolean flag from workflow context
26
+
27
+ ## Probe Algorithm
28
+
29
+ 1. Collect candidate snippet paths:
30
+ - Read `{skills_output_folder}/.export-manifest.json` if it exists. For each skill in `exports` with a resolvable `active_version`, add `{skills_output_folder}/{skill-name}/{active_version}/{skill-name}/context-snippet.md`.
31
+ - Also include the current skill's snippet if present.
32
+ 2. For each snippet that exists on disk, read the first line and parse the `root:` value. Strip the trailing `{skill-name}/` to extract the prefix (e.g. `skills/`, `.claude/skills/`).
33
+ 3. Collect unique prefixes into `observed_prefixes`.
34
+ 4. Compare against `target_context_files[0].skill_root` (the reference).
35
+
36
+ ## Mismatch Gate
37
+
38
+ **If `observed_prefixes` contains any value that does not match the reference `skill_root`:**
39
+
40
+ Emit a single warning (once, not per snippet) and present resolution options before continuing to §2:
41
+
42
+ > **Snippet root prefix mismatch detected.**
43
+ > Existing snippets use: `{observed_prefixes}`
44
+ > IDE-mapped skill_root: `{target_context_files[0].skill_root}`
45
+ >
46
+ > This usually means you are in an authoring repo where skills live under a single shared directory. Options:
47
+ >
48
+ > - **(a) Set override** — add `snippet_skill_root_override: {observed_prefix}` to `config.yaml`. Snippets keep their on-disk prefix; the managed section references the real location.
49
+ > - **(b) Proceed with IDE mapping** — step 4 will rewrite every snippet's root path to the IDE's skill_root. Use this only if the IDE's skill directory actually contains the skill files.
50
+ > - **(c) Cancel** — abort export and investigate.
51
+ >
52
+ > If multiple distinct prefixes were observed, the snippets disagree with each other — investigate before choosing (a).
53
+
54
+ Wait for user choice.
55
+
56
+ **Headless default:** when `{headless_mode}`, default to **(b) Proceed with IDE mapping** and log the observed prefix(es) so the mismatch is visible in run logs (not silent).
57
+
58
+ ## Choice handling
59
+
60
+ ### (a) Set override
61
+
62
+ Halt and instruct the user to update `config.yaml` with `snippet_skill_root_override: {observed_prefix}`, then re-run export. Exit code 6, `halt_reason: "user-cancelled"` (configuration change is out-of-band — workflow does not edit config.yaml on the user's behalf).
63
+
64
+ ### (b) Proceed with IDE mapping
65
+
66
+ Continue to §2. Step 4's root-rewrite algorithm will rewrite every snippet's prefix to the reference `skill_root`. The user is accepting that the IDE's skill directory contains the actual files; if it does not, the resulting managed section will reference paths that don't resolve.
67
+
68
+ ### (c) Cancel
69
+
70
+ HALT. Exit code 6, `halt_reason: "user-cancelled"`. No files written.
71
+
72
+ ## No-mismatch fast path
73
+
74
+ **If all observed prefixes match the reference `skill_root` (or no existing snippets were found):** no warning, no gate. Return control to §1b and proceed silently to §2.
@@ -1,7 +1,9 @@
1
1
  ---
2
- nextStepFile: './step-07-health-check.md'
2
+ nextStepFile: 'health-check.md'
3
3
  ---
4
4
 
5
+ <!-- Config: communicate in {communication_language}. Render the user-facing summary in {document_output_language}. -->
6
+
5
7
  # Step 6: Summary
6
8
 
7
9
  ## STEP GOAL:
@@ -12,12 +14,10 @@ To present a complete export summary showing all files written, token counts, an
12
14
 
13
15
  - Focus only on summarizing what was done and providing next steps — no additional file writes
14
16
  - Chains to the local health-check step via `{nextStepFile}` after completion — the user-facing summary is NOT the terminal step
15
- - **Multi-skill mode:** emit ONE consolidated summary and ONE result contract for the whole batch. The files-written table lists every skill in `skill_batch` (one row per skill's `context-snippet.md` + one row per target managed-section file, shared across the batch). The result contract's `outputs` enumerates every context-snippet file plus every target context file. Distribution instructions (§2) key off `source_authority` per skill — present one block per distinct authority value observed in the batch, listing the skills it applies to. See step-01 §1c.
17
+ - **Multi-skill mode:** emit ONE consolidated summary and ONE result contract for the whole batch. The files-written table lists every skill in `skill_batch` (one row per skill's `context-snippet.md` + one row per target managed-section file, shared across the batch). The result contract's `outputs` enumerates every context-snippet file plus every target context file. Distribution instructions (§2) key off `source_authority` per skill — present one block per distinct authority value observed in the batch, listing the skills it applies to. See step 1 §1c.
16
18
 
17
19
  ## MANDATORY SEQUENCE
18
20
 
19
- **CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise unless user explicitly requests a change.
20
-
21
21
  ### 1. Compile Export Summary
22
22
 
23
23
  "**Export Complete{if dry-run: ' (Dry Run)'}**
@@ -99,7 +99,7 @@ To install this skill into the current project right now:
99
99
  npx skills add {resolved_skill_package}
100
100
  ```
101
101
 
102
- Replace `{resolved_skill_package}` with the absolute path to the package folder shown above (from step-02), e.g. `{skills_output_folder}/{skill-name}/{version}/{skill-name}/`.
102
+ Replace `{resolved_skill_package}` with the absolute path to the package folder shown above (from step 2), e.g. `{skills_output_folder}/{skill-name}/{version}/{skill-name}/`.
103
103
 
104
104
  For other source formats (registry name, git URL, tarball, etc.), see the **Installation → Source Formats** section at <https://www.npmjs.com/package/skills>.
105
105
 
@@ -130,7 +130,31 @@ No files were written. To run the export for real:
130
130
 
131
131
  ### 6. Result Contract
132
132
 
133
- Write the result contract per `shared/references/output-contract-schema.md`: the per-run record at `{skills_output_folder}/export-skill-result-{YYYYMMDD-HHmmss}.json` (UTC timestamp, resolution to seconds) and a copy at `{skills_output_folder}/export-skill-result-latest.json` (stable path for pipeline consumers — copy, not symlink). Include all context files and target managed-section files in `outputs`; include total always-on and on-trigger token counts in `summary`.
133
+ Write the result contract per `shared/references/output-contract-schema.md`: the per-run record at `{skills_output_folder}/export-skill-result-{timestamp}.json` (reuse the activation-stored `{timestamp}`, resolution to seconds) and a copy at `{skills_output_folder}/export-skill-result-latest.json` (stable path for pipeline consumers — copy, not symlink). Include all context files and target managed-section files in `outputs`; include total always-on and on-trigger token counts in `summary`.
134
+
135
+ When `{headless_mode}` is true, also emit the single-line envelope on **stdout** before chaining to step 7 (matches the SKILL.md "Result Contract (Headless)" shape):
136
+
137
+ ```
138
+ SKF_EXPORT_RESULT_JSON: {"status":"success","skills":{skill_batch_names},"context_files_updated":{context_files_updated},"manifest_path":"{skills_output_folder}/.export-manifest.json","headless_decisions":{headless_decisions},"exit_code":0,"halt_reason":null}
139
+ ```
140
+
141
+ Substitute `{skill_batch_names}`, `{context_files_updated}`, and `{headless_decisions}` as JSON arrays. When `--dry-run` was set, emit `"status":"dry-run"` instead and report what *would* have been written without performing the writes.
142
+
143
+ **`deviations[]` field (export-skill-specific extension):** when step 4 §4c.1 detected manifest-orphan managed rows and the operator (or `{headless_mode}`) chose **(b) Preserve verbatim**, also include a `deviations[]` array in the contract. Each entry has the shape:
144
+
145
+ ```json
146
+ {
147
+ "kind": "preserve_external_skills",
148
+ "skills": [
149
+ {"name": "skill-name", "version": "1.0.0", "source_files": ["CLAUDE.md", ".cursorrules"]}
150
+ ],
151
+ "rationale": "managed-section row exists but no manifest entry / no source draft"
152
+ }
153
+ ```
154
+
155
+ `source_files` per skill records the prior context files the orphan was found in (the §4c.1 multi-file scan deduplicates by `(skill, version)` and tracks which target context files originally carried the row — useful when an operator later debugs which IDE's managed section first introduced the external skill).
156
+
157
+ Other workflow choices that diverge from the strict spec path may add their own entries with a distinct `kind` value — auditors then have one place to look for "what did this run choose to do differently from the canonical flow." Omit the field when there are no deviations rather than writing an empty array, so the absence is readable as "ran the canonical path."
134
158
 
135
159
  ### 7. Chain to Health Check
136
160
 
@@ -1,7 +1,9 @@
1
1
  ---
2
- nextStepFile: './step-06-summary.md'
2
+ nextStepFile: 'summary.md'
3
3
  ---
4
4
 
5
+ <!-- Config: communicate in {communication_language}. Render the token report in {document_output_language}. -->
6
+
5
7
  # Step 5: Token Report
6
8
 
7
9
  ## STEP GOAL:
@@ -12,15 +14,13 @@ To calculate approximate token counts for all exported artifacts and present a c
12
14
 
13
15
  - Focus only on token counting and reporting — read-only measurement
14
16
  - Auto-proceed when complete
15
- - **Multi-skill mode:** when step-01 loaded more than one skill (`len(skill_batch) > 1`), compute token counts per skill, then present one aggregate table with one row per skill (context-snippet.md, SKILL.md, metadata.json, references/, package total). Measure the managed section once for the run — it is shared across the batch. See step-01 §1c.
17
+ - **Multi-skill mode:** when step 1 loaded more than one skill (`len(skill_batch) > 1`), compute token counts per skill, then present one aggregate table with one row per skill (context-snippet.md, SKILL.md, metadata.json, references/, package total). Measure the managed section once for the run — it is shared across the batch. See step 1 §1c.
16
18
 
17
19
  ## MANDATORY SEQUENCE
18
20
 
19
- **CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise unless user explicitly requests a change.
20
-
21
21
  ### 1. Calculate Token Counts
22
22
 
23
- For each artifact, estimate tokens using the heuristic: **words * 1.3** (approximate for GPT/Claude tokenizers). This same heuristic is used in step-03 for snippet token estimation.
23
+ For each artifact, estimate tokens using the heuristic: **words * 1.3** (approximate for GPT/Claude tokenizers). This same heuristic is used in step 3 for snippet token estimation.
24
24
 
25
25
  **Artifacts to measure:**
26
26
 
@@ -1,8 +1,32 @@
1
1
  ---
2
- nextStepFile: './step-05-token-report.md'
3
- managedSectionData: 'assets/managed-section-format.md'
2
+ nextStepFile: 'token-report.md'
3
+ managedSectionData: '{managedSectionFormatPath}'
4
+ # Resolve `{rebuildManagedSectionsHelper}` by probing
5
+ # `{rebuildManagedSectionsProbeOrder}` in order (installed SKF module path
6
+ # first, src/ dev-checkout fallback); first existing path wins. §9 uses
7
+ # the `replace` action for the surgical between-marker swap with
8
+ # atomic temp-file + rename, marker preservation, and post-write verify.
9
+ # HALT if no candidate exists — the in-prompt prose path silently regresses
10
+ # the Case 4 (malformed markers) HARD HALT guarantee.
11
+ rebuildManagedSectionsProbeOrder:
12
+ - '{project-root}/_bmad/skf/shared/scripts/skf-rebuild-managed-sections.py'
13
+ - '{project-root}/src/shared/scripts/skf-rebuild-managed-sections.py'
14
+ # Resolve `{manifestOpsHelper}` similarly. §9b uses `read` / `set` for
15
+ # atomic v2-schema-aware manifest mutation (handles v1→v2 migration and
16
+ # `platforms`→`ides` rename internally).
17
+ manifestOpsProbeOrder:
18
+ - '{project-root}/_bmad/skf/shared/scripts/skf-manifest-ops.py'
19
+ - '{project-root}/src/shared/scripts/skf-manifest-ops.py'
20
+ # Resolve `{atomicWriteHelper}` similarly. §6 Case 1 (Create) and §6
21
+ # Case 2 (Append) use it via `write` for safe artifact emission — the
22
+ # in-prompt write would risk half-written files on process kill.
23
+ atomicWriteProbeOrder:
24
+ - '{project-root}/_bmad/skf/shared/scripts/skf-atomic-write.py'
25
+ - '{project-root}/src/shared/scripts/skf-atomic-write.py'
4
26
  ---
5
27
 
28
+ <!-- Config: communicate in {communication_language}. Render the change preview and managed section in {document_output_language}. -->
29
+
6
30
  # Step 4: Update Context
7
31
 
8
32
  ## STEP GOAL:
@@ -14,16 +38,14 @@ To update the managed `<!-- SKF:BEGIN/END -->` section in the platform-appropria
14
38
  - Focus only on the managed section update in the target context file
15
39
  - Do not modify any content outside `<!-- SKF:BEGIN -->` and `<!-- SKF:END -->` markers
16
40
  - Do not write without user confirmation — this modifies shared project files
17
- - If `passive_context: false` was detected in step-01, skip this step entirely
18
- - **Multi-skill mode:** this step executes ONCE for the whole batch, not once per skill. §4b already builds the exported skill set from the manifest (plus current export targets), so a multi-skill run naturally appears as a single rebuild. The only batch adjustment is in §9b: update the manifest entry for every skill in `skill_batch` (not just one), and include all of them when computing `ides_written`. See step-01 §1c.
41
+ - If `passive_context: false` was detected in step 1, skip this step entirely
42
+ - **Multi-skill mode:** this step executes ONCE for the whole batch, not once per skill. §4b already builds the exported skill set from the manifest (plus current export targets), so a multi-skill run naturally appears as a single rebuild. The only batch adjustment is in §9b: update the manifest entry for every skill in `skill_batch` (not just one), and include all of them when computing `ides_written`. See step 1 §1c.
19
43
 
20
44
  ## MANDATORY SEQUENCE
21
45
 
22
- **CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise unless user explicitly requests a change.
23
-
24
46
  ### 1. Check Passive Context Setting
25
47
 
26
- **If `passive_context: false` was detected in step-01:**
48
+ **If `passive_context: false` was detected in step 1:**
27
49
 
28
50
  "**Passive context disabled in preferences.yaml. Skipping context update.**"
29
51
 
@@ -37,7 +59,7 @@ Load {managedSectionData} and read the complete format template and four-case lo
37
59
 
38
60
  ### 3. Determine Target File(s)
39
61
 
40
- Using the `target_context_files` list resolved in step-01, determine all target files. Each entry has `{context_file, skill_root}` — the context file to write and the IDE's skill directory for root path resolution.
62
+ Using the `target_context_files` list resolved in step 1, determine all target files. Each entry has `{context_file, skill_root}` — the context file to write and the IDE's skill directory for root path resolution.
41
63
 
42
64
  For each entry in `target_context_files`, resolve target file path: `{context_file}`
43
65
 
@@ -49,87 +71,29 @@ For each entry in `target_context_files`, resolve target file path: `{context_fi
49
71
 
50
72
  A context file becomes orphaned when its IDE is removed from `config.yaml` after a prior export. The file still contains an SKF managed section pointing to stale skill versions, but no future export will rewrite it.
51
73
 
52
- Build `orphaned_context_files` — the set of context files that exist on disk with an `<!-- SKF:BEGIN -->` marker but whose context file is NOT in the current `target_context_files` list:
53
-
54
- 1. For each known context file in `{CLAUDE.md, .cursorrules, AGENTS.md}`:
55
- - If the context file is in `target_context_files`, skip (it will be rewritten in the main loop)
56
- - Otherwise, check whether the file exists at `{context_file}`
57
- - If the file exists, read it and check for the `<!-- SKF:BEGIN -->` marker
58
- - If the marker is present, add the file path to `orphaned_context_files` along with the context file name
59
-
60
- 2. If `orphaned_context_files` is non-empty, emit a warning:
61
-
62
- "**Orphaned context files detected.** The following files contain SKF managed sections but no configured IDEs target them:
63
- {list: context file → file path}
64
-
65
- The managed sections in these files are stale. Options:
66
- - **(a) clear** — remove the SKF managed section from each orphaned file (surgical marker replacement, leaves user content intact)
67
- - **(b) keep** — leave them untouched (they will remain stale until you re-add an IDE that targets this file or delete the file)
68
- - **(c) rewrite** — also rewrite the orphaned files with the current skill index (use this if the IDE was removed by mistake)"
69
-
70
- 3. Wait for user choice. In non-interactive mode (dry-run or unattended), default to **(b) keep** and print the warning only.
71
-
72
- 4. If the user chose **(a) clear**: for each orphaned file, replace everything between `<!-- SKF:BEGIN` and `<!-- SKF:END -->` (inclusive) with an empty string, preserving surrounding content byte-exactly. Record the cleared files in `orphans_cleared`.
73
-
74
- 5. If the user chose **(c) rewrite**: add each orphaned context file to a separate `rewrite_context_files` list (kept distinct from `target_context_files` so the user's intent to only export to configured IDEs is preserved in the manifest). Use `.agents/skills/` as the default skill root for rewritten orphans. Sections 4–9a will loop over `target_context_files + rewrite_context_files` for this run only. Record the rewritten files in `orphans_rewritten`.
74
+ **Cheap pre-check (always run, ~3 file existence checks):** build `orphaned_context_files` — for each known context file in `{CLAUDE.md, .cursorrules, AGENTS.md}` that is NOT in `target_context_files`, check whether it exists on disk and contains the `<!-- SKF:BEGIN -->` marker. If yes, add `{context_file, file_path}` to `orphaned_context_files`.
75
75
 
76
- 6. If the user chose **(b) keep**: record nothing and proceed.
76
+ **If `orphaned_context_files` is non-empty:** load `references/orphan-context-detection.md` and follow its (a) clear / (b) keep / (c) rewrite gate protocol. The reference handles user prompting, headless default (keep), and downstream-state recording (`orphans_cleared`, `orphans_rewritten`, `rewrite_context_files`). When the user chooses (c), the §4–§9a loop iterates over `target_context_files + rewrite_context_files`.
77
77
 
78
- This cleanup only runs during interactive export. Drop-skill and rename-skill operate on the manifest's declared context files and are not responsible for orphan detection.
78
+ **If `orphaned_context_files` is empty:** proceed to §4.
79
79
 
80
80
  ### 4. Rebuild Complete Skill Index
81
81
 
82
82
  #### 4a. Read Export Manifest (v2 — version-aware)
83
83
 
84
- Read `{skills_output_folder}/.export-manifest.json` see `knowledge/version-paths.md` for the full v2 schema:
85
-
86
- **If the file exists:** Parse JSON. Check for `schema_version` field:
87
-
88
- **v2 manifest** (`schema_version: "2"`):
89
- ```json
90
- {
91
- "schema_version": "2",
92
- "exports": {
93
- "skill-name": {
94
- "active_version": "0.6.0",
95
- "versions": {
96
- "0.1.0": {
97
- "ides": ["claude-code"],
98
- "last_exported": "2026-01-15",
99
- "status": "deprecated"
100
- },
101
- "0.5.0": {
102
- "ides": ["claude-code"],
103
- "last_exported": "2026-03-15",
104
- "status": "archived"
105
- },
106
- "0.6.0": {
107
- "ides": ["claude-code", "github-copilot"],
108
- "last_exported": "2026-04-04",
109
- "status": "active"
110
- }
111
- }
112
- }
113
- }
114
- }
84
+ Read the manifest via `{manifestOpsHelper}` (resolved at §9 from `{manifestOpsProbeOrder}` see frontmatter):
85
+
86
+ ```bash
87
+ python3 {manifestOpsHelper} {skills_output_folder} read
115
88
  ```
116
89
 
117
- **Status values:**
118
- - `"active"` — currently exported; snippet appears in managed sections
119
- - `"archived"` — previously exported, not active; files retained for rollback
120
- - `"deprecated"` — dropped via drop-skill workflow; excluded from all exports (files may or may not exist on disk)
121
- - `"draft"` — created but never exported
90
+ The helper handles v2-schema enforcement, v1→v2 migration, and the `platforms`→`ides` rename internally. The returned JSON is always in canonical v2 shape regardless of on-disk state.
122
91
 
123
- **Legacy `platforms` `ides` rename:** Pre-rename v2 manifests used a `platforms` array at the version level. If a version entry contains `platforms` instead of (or in addition to) `ides`, treat `platforms` as `ides` and rewrite it to `ides` on the next manifest write. This is a silent in-place upgrade no user prompt, no v3 bump.
92
+ **Schema reference:** `references/manifest-rebuild.md` documents the v2 shape, the status enum (`active`/`archived`/`deprecated`/`draft`), the v1 migration path, and the `active_version` integrity invariant. Load that file only when an inline schema reminder is needed the helper enforces the shape so the in-prompt prose is not load-bearing.
124
93
 
125
- **v1 manifest** (no `schema_version` field migrate in-place to v2):
126
- 1. For each entry in `exports`, read its `last_exported` (v1 had no per-version IDE list)
127
- 2. Resolve the skill's current version from `{resolved_skill_package}/metadata.json`
128
- 3. Wrap in v2 structure: set `active_version` to the resolved version, create a single entry in `versions` with `status: "active"`, `ides: []` (unknown — will be filled on next successful export), and `last_exported`
129
- 4. Set `schema_version: "2"` at root
130
- 5. Hold the migrated structure in context (it will be written in section 9b)
94
+ **Integrity guard:** if the helper returns an entry where `active_version` does not resolve to a key in `versions`, the manifest is inconsistent. Skip the affected skill and log: "**Manifest integrity warning:** `{skill-name}.active_version = v{active_version}` has no matching entry under `versions`. Skipping. Re-run `[EX] Export Skill` on `{skill-name}` to repair the manifest entry."
131
95
 
132
- **If the file does not exist** (first export or migration): Treat as empty only the current export target will appear in the rebuilt index.
96
+ **If the manifest does not exist** (first export or fresh forge): the helper returns `{"schema_version": "2", "exports": {}}`. Only the current export target will appear in the rebuilt index.
133
97
 
134
98
  #### 4b. Build Exported Skill Set (version-aware)
135
99
 
@@ -156,6 +120,26 @@ Instead of globbing `{skills_output_folder}/*/context-snippet.md`, resolve snipp
156
120
 
157
121
  **If no snippets pass the filter:** Generate managed section with zero skills — header only, no skill entries.
158
122
 
123
+ #### 4c.1 Detect Orphaned Managed-Section Rows (manifest-absent skills)
124
+
125
+ A managed-section row becomes orphaned when a `[skill-name v...]` entry already exists in the prior managed section but the skill is not in the exported skill set built in 4b — typically an externally-installed skill authored in a different repo and dropped into `{skills_output_folder}` without going through export-skill. Strict ADR-K would silently drop such rows, but the user's managed section is load-bearing — silent removal is a regression.
126
+
127
+ **Cheap pre-check (always run before §5 assembly).** Scan **every** target context file (not just the first), deduplicate by `(skill_name, version)`, and present one consolidated gate. Asymmetric orphans — a row present in `.cursorrules` but absent from `CLAUDE.md`, or vice versa — must be detected; otherwise the §4 rebuild loop silently overwrites the orphan-bearing file's content (ADR-J violation: silent loss of user content).
128
+
129
+ 1. Initialize `orphan_managed_rows = []` (a list of `{skill_name, version, snippet_text, source_files: []}` entries — `source_files` carries provenance for the gate display and the audit `deviations[]` entry).
130
+ 2. **Iterate every entry in `target_context_files`:**
131
+ a. Read the prior managed section from `{entry.context_file}`. If the file does not exist or has no `<!-- SKF:BEGIN -->` marker, skip this entry — it has no orphans by definition.
132
+ b. Parse the `[skill-name v...]` rows between `<!-- SKF:BEGIN -->` and `<!-- SKF:END -->` into `file_rows` — a list of `{skill_name, version, snippet_text}` triples (capture the original snippet line(s) verbatim so they can be re-emitted unchanged if (b) is chosen).
133
+ c. For each `row` in `file_rows`:
134
+ - If `row.skill_name` is in the exported skill set built in 4b (manifest entries plus current-export targets), skip — not an orphan.
135
+ - Otherwise look up `(row.skill_name, row.version)` in `orphan_managed_rows`:
136
+ - If already present, append `entry.context_file` to that row's `source_files` list (deduplicated). Keep the first-encountered `snippet_text` — divergent snippets across files for the same `(skill, version)` are themselves a user-content asymmetry but the `(b) Preserve verbatim` semantic writes one canonical row to every target file, so picking the first is deterministic and avoids silently choosing.
137
+ - If new, append `{skill_name: row.skill_name, version: row.version, snippet_text: row.snippet_text, source_files: [entry.context_file]}`.
138
+
139
+ **If `orphan_managed_rows` is non-empty:** load `references/orphan-row-detection.md` and follow its (a) Drop / (b) Preserve verbatim / (c) Cancel gate protocol. The reference handles user prompting (with per-orphan `source_files` provenance), headless default (Preserve verbatim), `deviations[]` recording (including `source_files` per orphan for audit), and §6 result-contract integration.
140
+
141
+ **If `orphan_managed_rows` is empty:** proceed to §4d.
142
+
159
143
  #### 4d. Rewrite Root Paths for Target Context File
160
144
 
161
145
  The context-snippet.md files on disk contain root paths for the IDE they were originally exported to. When assembling the managed section for the current target context file, rewrite root paths if they differ from the target's `skill_root`.
@@ -217,8 +201,9 @@ Assemble the complete managed section:
217
201
  - Preserved: ALL content before `<!-- SKF:BEGIN` and after `<!-- SKF:END -->`
218
202
 
219
203
  **Case 4: Malformed markers (file contains `<!-- SKF:BEGIN` but no `<!-- SKF:END -->`)**
220
- - Action: HALT with warning: "Malformed SKF markers detected in `{target-file}` — `<!-- SKF:BEGIN` found but `<!-- SKF:END -->` is missing. Please restore the end marker manually before running export."
221
- - Do NOT attempt to write or append — the file is in an inconsistent state
204
+ - Action: HALT (exit code 5, `halt_reason: "malformed-markers"`) with warning: "Malformed SKF markers detected in `{target-file}` — `<!-- SKF:BEGIN` found but `<!-- SKF:END -->` is missing. Please restore the end marker manually before running export."
205
+ - Do NOT attempt to write or append — the file is in an inconsistent state.
206
+ - In headless mode, emit the error envelope per SKILL.md "Result Contract (Headless)" with `manifest_path: null`, `context_files_updated: []`.
222
207
 
223
208
  ### 7. Present Change Preview
224
209
 
@@ -251,18 +236,19 @@ Auto-proceed to {nextStepFile}.
251
236
 
252
237
  **If NOT dry-run:**
253
238
 
254
- Display: "**Select:** [C] Continue — write changes to {target-file}"
239
+ Display: "**Select:** [C] Continue — write changes to {target-file} | [X] Cancel and exit (or type `cancel` / `exit` / `:q`)"
255
240
 
256
241
  **Multi-target behavior:** When processing multiple context files, present all previews together before asking for a single confirmation. After confirmation, write all target files sequentially, verifying each one.
257
242
 
258
243
  "**Targets:** {list all context-file → target-file pairs}
259
244
  **Ready to write changes to all targets?**"
260
245
 
261
- Display: "**Select:** [C] Continue — write changes to all targets"
246
+ Display: "**Select:** [C] Continue — write changes to all targets | [X] Cancel and exit"
262
247
 
263
248
  #### Menu Handling Logic:
264
249
 
265
250
  - IF C: Write the changes to all target files (or single target), verify each write succeeded, then load, read entire file, then execute {nextStepFile}
251
+ - IF X (or `cancel` / `exit` / `:q`): Display "Cancelled — no context files were written." and HALT (exit code 6, `halt_reason: "user-cancelled"`). In headless, emit the error envelope per SKILL.md "Result Contract (Headless)" with the resolved `skills`, `context_files_updated: []`, and `manifest_path: null`.
266
252
  - IF Any other: help user respond, then [Redisplay Menu Options](#8-present-menu-options)
267
253
 
268
254
  #### EXECUTION RULES:
@@ -274,16 +260,49 @@ Display: "**Select:** [C] Continue — write changes to all targets"
274
260
 
275
261
  ### 9. Write and Verify (Non-Dry-Run Only)
276
262
 
277
- After user confirms with 'C':
263
+ After user confirms with 'C', resolve the helpers in parallel — these are independent file-existence checks that batch into one tool-call message:
264
+
265
+ - `{rebuildManagedSectionsHelper}` ← first existing path in `{rebuildManagedSectionsProbeOrder}` (used for Cases 2 and 3)
266
+ - `{atomicWriteHelper}` ← first existing path in `{atomicWriteProbeOrder}` (used for Case 1)
267
+ - `{manifestOpsHelper}` ← first existing path in `{manifestOpsProbeOrder}` (used in §9b)
268
+
269
+ If any helper has no existing candidate, HALT (exit code 4, `halt_reason: "context-rebuild-failed"`) and emit the error envelope per SKILL.md "Result Contract (Headless)" — the rewrite's safety guarantees depend on these helpers and a fall-through to LLM-driven writes would silently regress atomicity, marker preservation, and the Case 4 malformed-marker HARD HALT contract.
278
270
 
279
- 1. Write the file using the appropriate case logic
280
- 2. Re-read the written file
281
- 3. Verify `<!-- SKF:BEGIN` and `<!-- SKF:END -->` markers are present
282
- 4. Verify content outside markers is unchanged (for Cases 2 and 3)
283
- 5. Report: "**{target-file} updated successfully.** Verified: markers present, external content preserved."
271
+ For each target context file, dispatch by case:
284
272
 
285
- **If verification fails:**
286
- "**WARNING: Write verification failed.** {describe issue}. File may need manual review."
273
+ **Case 1 (Create — file does not exist):**
274
+
275
+ ```bash
276
+ echo "{new_managed_section_text}" | python3 {atomicWriteHelper} write "{target-file}"
277
+ ```
278
+
279
+ The helper stages the content into `<target>.skf-tmp`, fsyncs, and atomically renames into place.
280
+
281
+ **Case 2 (Append — file exists, no `<!-- SKF:BEGIN` marker):**
282
+
283
+ ```bash
284
+ python3 {rebuildManagedSectionsHelper} {target-file} insert --content "{new_managed_section_text}"
285
+ ```
286
+
287
+ The helper appends the managed section to the end of the file via the same atomic temp-file + rename pattern.
288
+
289
+ **Case 3 (Regenerate — file contains `<!-- SKF:BEGIN` and `<!-- SKF:END -->`):**
290
+
291
+ ```bash
292
+ python3 {rebuildManagedSectionsHelper} {target-file} replace --content "{new_managed_section_text}"
293
+ ```
294
+
295
+ The helper performs the surgical between-marker swap with post-write verification (markers present, content outside markers byte-identical).
296
+
297
+ **Case 4 (malformed markers — already HALTed in §6):** never reaches here.
298
+
299
+ **Verification (deferred to helpers):** the `replace`/`insert`/`write` actions above each perform their own verification. Treat any non-zero exit as a write failure:
300
+
301
+ - HALT (exit code 4, `halt_reason: "context-rebuild-failed"`) and report `{target-file}: {captured stderr}`.
302
+ - In headless mode, emit the error envelope.
303
+ - Continue to the next target file only on success — partial-batch writes are acceptable in single-skill mode but the overall envelope reports per-target outcomes.
304
+
305
+ On success per file, report: "**{target-file} updated successfully.** Verified by `{rebuildManagedSectionsHelper}` (or `{atomicWriteHelper}` for Case 1)."
287
306
 
288
307
  ### 9b. Update Export Manifest (Non-Dry-Run Only)
289
308
 
@@ -313,11 +332,17 @@ After user confirms with 'C':
313
332
  - If the version already exists in `versions`, union its existing `ides` with `ides_written` (deduplicate, keep sorted), refresh `last_exported`, and set `status: "active"`
314
333
  - If this is a new version, add it to `versions` with `status: "active"` and set any previously-active version's status to `"archived"`
315
334
  - Preserve all other version entries in `versions` (do not delete archived versions)
316
- 5. Write the updated manifest once to `{skills_output_folder}/.export-manifest.json` after all skills in the batch have been applied
335
+ 5. Write the updated manifest atomically via `{manifestOpsHelper}` after all skills in the batch have been applied. For each skill / version pair, invoke:
336
+
337
+ ```bash
338
+ python3 {manifestOpsHelper} {skills_output_folder} set {skill-name} {version}
339
+ ```
340
+
341
+ The helper handles v2-schema validation, v1→v2 migration, and `platforms`→`ides` rename internally — no in-prompt JSON manipulation needed. Each `set` invocation merges the per-version `ides` and `last_exported` fields into the existing entry. After all skills have been set, re-read the manifest via `{manifestOpsHelper} {skills_output_folder} read` to confirm the final state matches expectations.
317
342
 
318
343
  **Dry-run mode:** Do NOT update the manifest. Display: "**[DRY RUN] Export manifest would be updated for {skill-name-list} — ides: {ides_written}.**" (list every skill in `skill_batch`)
319
344
 
320
- **Error handling:** If manifest write fails, warn but do not fail the workflow the managed section was already written successfully.
345
+ **Error handling:** If `{manifestOpsHelper}` exits non-zero, HALT (exit code 4, `halt_reason: "manifest-write-failed"`) with the captured `stderr`. The managed section was already written successfully; the operator's recovery path is to manually reconcile the on-disk managed section with the manifest, then re-run `[EX] Export Skill --all` to refresh the manifest. In headless mode, emit the error envelope per SKILL.md "Result Contract (Headless)" with `manifest_path: null` and the partial `context_files_updated` list.
321
346
 
322
347
  ## CRITICAL STEP COMPLETION NOTE
323
348