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
@@ -7,11 +7,12 @@ description: Drift detection between skill and current source code. Use when the
7
7
 
8
8
  ## Overview
9
9
 
10
- Detects drift between an existing skill and its current source code, producing a severity-graded drift report with AST-backed findings and actionable remediation suggestions. Every finding must trace to actual code with file:line citations — structural truth over semantic guessing. Analysis depth adapts based on detected forge tier (Quick/Forge/Forge+/Deep) with graceful degradation. Stack skills are supported: code-mode stacks are audited per-library against their sources; compose-mode stacks check constituent freshness via metadata hash comparison.
10
+ Detects drift between an existing skill and its current source code, producing a severity-graded drift report with AST-backed findings and actionable remediation suggestions. Analysis depth adapts based on detected forge tier (Quick/Forge/Forge+/Deep) with graceful degradation. Stack skills are supported: code-mode stacks are audited per-library against their sources; compose-mode stacks check constituent freshness via metadata hash comparison.
11
11
 
12
12
  ## Conventions
13
13
 
14
14
  - Bare paths (e.g. `references/<name>.md`) resolve from the skill root.
15
+ - **Module-level path exception:** bare paths beginning with `knowledge/` or `shared/` resolve from the SKF module root (`{project-root}/_bmad/skf/` installed, `src/` in dev), not the skill root — stage files reference `knowledge/version-paths.md` and `knowledge/tool-resolution.md`, and the terminal step chains to `shared/health-check.md`.
15
16
  - `references/` holds prompt content carved out of SKILL.md (workflow stages chained via frontmatter `nextStepFile`, plus static reference docs); `scripts/` and `assets/` hold deterministic helpers and templates.
16
17
  - `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives, if present).
17
18
  - `{project-root}`-prefixed paths resolve from the project working directory.
@@ -19,7 +20,7 @@ Detects drift between an existing skill and its current source code, producing a
19
20
 
20
21
  ## Role
21
22
 
22
- You are a skill auditor operating in Ferris Audit mode. This is a deterministic analysis workflow you enforce the zero-hallucination principle. You bring AST analysis expertise and drift detection methodology, while the source code provides the ground truth.
23
+ You are a skill auditor in Ferris Audit mode: a deterministic drift-detection workflow where the source code is the ground truth and every finding traces back to it.
23
24
 
24
25
  ## Workflow Rules
25
26
 
@@ -56,7 +57,7 @@ These rules apply to every step in this workflow:
56
57
 
57
58
  ## Exit Codes
58
59
 
59
- Every HARD HALT in this workflow exits with a stable code so headless automators can branch on the failure class without grepping message text:
60
+ Every hard halt in this workflow exits with a stable code so headless automators can branch on the failure class without grepping message text:
60
61
 
61
62
  | Code | Meaning | Raised by |
62
63
  | ---- | -------------------- | ------------------------------------------------------------------------------------------------------------------ |
@@ -68,13 +69,13 @@ Every HARD HALT in this workflow exits with a stable code so headless automators
68
69
 
69
70
  ## Result Contract (Headless)
70
71
 
71
- When `{headless_mode}` is true, step 6 emits a single-line JSON envelope on **stdout** before chaining to step 7, and every HARD HALT emits the same envelope shape on **stderr** with `status: "error"`:
72
+ When `{headless_mode}` is true, step 6 emits a single-line JSON envelope on **stdout** before chaining to step 7, and every hard halt emits the same envelope shape on **stderr** with `status: "error"`:
72
73
 
73
74
  ```
74
75
  SKF_AUDIT_RESULT_JSON: {"status":"success|error","skill_name":"…","drift_score":"CLEAN|MINOR|SIGNIFICANT|CRITICAL|null","report_path":"…|null","next_workflow":"update-skill|null","audit_ref":"…|null","exit_code":0,"halt_reason":null}
75
76
  ```
76
77
 
77
- `status` is `"success"` on the terminal happy path, `"error"` on any HALT. `drift_score` is `null` when the workflow halted before severity classification ran. `next_workflow` is `"update-skill"` when CRITICAL or HIGH findings exist, otherwise `null`. `halt_reason` is one of: `null` (success), `"input-missing"`, `"skill-not-found"`, `"forge-tier-missing"`, `"source-dir-missing"`, `"write-failed"`, `"user-cancelled"`. `exit_code` matches the table above.
78
+ `status` is `"success"` on the terminal happy path, `"error"` on any halt. `drift_score` is `null` when the workflow halted before severity classification ran. `next_workflow` is `"update-skill"` when CRITICAL or HIGH findings exist, otherwise `null`. `halt_reason` is one of: `null` (success), `"input-missing"`, `"skill-not-found"`, `"forge-tier-missing"`, `"source-dir-missing"`, `"write-failed"`, `"user-cancelled"`. `exit_code` matches the table above.
78
79
 
79
80
  ## On Activation
80
81
 
@@ -106,6 +107,8 @@ SKF_AUDIT_RESULT_JSON: {"status":"success|error","skill_name":"…","drift_score
106
107
  - `{severityRulesPath}` ← `workflow.severity_rules_path` if non-empty, else `references/severity-rules.md`
107
108
  - `{onCompleteCommand}` ← `workflow.on_complete` if non-empty, else empty (no-op — report.md skips the hook invocation entirely)
108
109
 
109
- Stash all three as workflow-context variables. Stage files reference `{driftReportTemplatePath}` / `{severityRulesPath}` / `{onCompleteCommand}` directly — no conditional at the usage site. Empty-string overrides cleanly fall through to the bundled default; non-empty values let orgs swap in house-style copies (custom drift-report layout, stricter severity thresholds) or wire in post-audit hooks (Slack notifier, ticket-tracker integration) without forking the skill.
110
+ Stash all three as workflow-context variables. Stage files reference `{driftReportTemplatePath}` / `{severityRulesPath}` / `{onCompleteCommand}` directly.
111
+
112
+ Also apply the array surfaces (not silent no-ops): run `workflow.activation_steps_prepend` now, treat `workflow.persistent_facts` as standing context for the run (`file:`-prefixed entries load their file/glob contents as facts — the bundled default globs any `project-context.md`), then run `workflow.activation_steps_append` after activation.
110
113
 
111
114
  4. Load, read the full file, and then execute `references/init.md` to begin the workflow.
@@ -1,6 +1,8 @@
1
1
  # DO NOT EDIT -- overwritten on every update.
2
2
  #
3
3
  # Workflow customization surface for skf-audit-skill.
4
+ # Team overrides: _bmad/custom/skf-audit-skill.toml (under {project-root})
5
+ # Personal overrides: _bmad/custom/skf-audit-skill.user.toml (under {project-root})
4
6
 
5
7
  [workflow]
6
8
 
@@ -1,13 +1,16 @@
1
1
  ---
2
2
  nextStepFile: 're-index.md'
3
3
  outputFile: '{forge_version}/drift-report-{timestamp}.md'
4
- templateFile: 'assets/drift-report-template.md'
4
+ templateFile: '{driftReportTemplatePath}'
5
5
  loadProvenanceProbeOrder:
6
6
  - '{project-root}/_bmad/skf/shared/scripts/skf-load-provenance.py'
7
7
  - '{project-root}/src/shared/scripts/skf-load-provenance.py'
8
8
  compareFileHashesProbeOrder:
9
9
  - '{project-root}/_bmad/skf/shared/scripts/skf-compare-file-hashes.py'
10
10
  - '{project-root}/src/shared/scripts/skf-compare-file-hashes.py'
11
+ compareConstituentHashesProbeOrder:
12
+ - '{project-root}/_bmad/skf/shared/scripts/skf-hash-content.py'
13
+ - '{project-root}/src/shared/scripts/skf-hash-content.py'
11
14
  ---
12
15
 
13
16
  <!-- Config: communicate in {communication_language}. -->
@@ -52,9 +55,9 @@ Which skill would you like to audit? Please provide the skill name or path."
52
55
 
53
56
  - **[N] Audit symlink target ({symlink_target})** — recommended. The drift report describes the version the skill currently resolves to.
54
57
  - **[M] Audit manifest version ({active_version})** — only useful when investigating the older version specifically.
55
- - **[X] Abort** — halt without producing a report. Run `[EX] Export Skill` to reconcile the manifest before re-running audit-skill."
58
+ - **[X] Abort** — halt without producing a report (exit 6, `halt_reason: "user-cancelled"`). Run `[EX] Export Skill` to reconcile the manifest before re-running audit-skill."
56
59
 
57
- Default is **[N]**. Headless mode auto-selects **[N]** with a loud log line: `"headless: manifest active_version ({active_version}) is older than symlink target ({symlink_target}); auditing symlink target. Run export-skill to reconcile."` This mirrors §5b's upstream-drift handling — when the manifest and the working tree disagree, the working tree is the more honest signal under automation.
60
+ Default is **[N]**. Headless mode auto-selects **[N]** with a loud log line: `"headless: manifest active_version ({active_version}) is older than symlink target ({symlink_target}); auditing symlink target. Run export-skill to reconcile."` When the manifest and on-disk state disagree, the working tree is the more honest signal under automation.
58
61
 
59
62
  - When the symlink target's provenance is **older** than (or equal to) the manifest's `last_exported`, the symlink predates the export — this is the normal post-export shape, no gate needed. Resolve to the manifest's `active_version`.
60
63
  - When only one of the two versions has a provenance map, resolve to the version that has one (the other is inert — auditing it would degrade to text-diff). Log the choice.
@@ -70,13 +73,17 @@ Which skill would you like to audit? Please provide the skill name or path."
70
73
  - If missing → "Skill not found at `{resolved_skill_package}`. Check the path and try again."
71
74
  - If found → Continue
72
75
 
76
+ **Headless default** (when `{headless_mode}`): the interactive prompt and its "check the path and try again" re-prompt cannot be answered under automation, so §1 halts deterministically instead of looping. This is the origin site for the exit-2 / exit-3 rows the Exit Codes table attributes to step 1 §1 — emit the `SKF_AUDIT_RESULT_JSON` error envelope on **stderr** (shape per SKILL.md → Result Contract; `status: "error"`, `drift_score: null`, `report_path: null`, `next_workflow: null`, `audit_ref: null`) at each halt:
77
+ - **No `skill_name` supplied** (neither name nor path given): HALT with **exit 2**, `halt_reason: "input-missing"`, `skill_name: null`. Log: `"headless: no skill_name supplied; cannot resolve interactively. Re-run with skill_name set."`
78
+ - **`SKILL.md` missing at `{resolved_skill_package}`**: HALT with **exit 3**, `halt_reason: "skill-not-found"`, `skill_name: {skill_name}`. Log: `"headless: skill not found at {resolved_skill_package}; no interactive retry. Check the exported skill name/path."`
79
+
73
80
  ### 2. Load Forge Tier
74
81
 
75
82
  Load `{sidecar_path}/forge-tier.yaml` to detect available tools.
76
83
 
77
84
  **If file missing:**
78
85
  - "Setup-forge has not been run. Cannot determine tool availability. Run `[SF] Setup Forge` first."
79
- - HALT workflow
86
+ - HALT with **exit 3**, `halt_reason: "forge-tier-missing"`. When `{headless_mode}`, emit the error envelope on **stderr** (shape per SKILL.md → Result Contract) and log: `"headless: forge-tier.yaml missing at {sidecar_path}; run setup-forge. Aborting."`
80
87
 
81
88
  **If found:**
82
89
  - Extract tier level: Quick / Forge / Forge+ / Deep
@@ -118,24 +125,50 @@ Search for provenance map at `{forge_data_folder}/{skill_name}/{active_version}/
118
125
  - `{source_root}`, `{baseline_commit}`, `{baseline_ref}` — used by §5 Resolve Source Path and §5b Detect Upstream Drift.
119
126
  - `{reexport_map}` — `{<internal>: <public>}` mapping consumed by `structural-diff.md` §1 to collapse public-API renames before diffing.
120
127
 
121
- If the script exits non-zero, surface the stderr as a HARD HALT — the map is structurally invalid and downstream steps cannot proceed.
128
+ If the script exits non-zero, surface the stderr as a hard halt — the map is structurally invalid and downstream steps cannot proceed.
122
129
 
123
130
  **If missing at both paths:**
124
131
  - "No provenance map found for `{skill_name}`. This skill may not have been created by create-skill."
125
132
  - "**Degraded mode available:** I can perform text-based comparison without provenance data. Findings will have T1-low confidence."
126
133
  - "**[D]egraded mode** — proceed with text-diff only"
127
134
  - "**[X]** — abort audit"
128
- - Wait for user selection. If D, set `degraded_mode: true` and `confidence_mode = "degraded — all findings T1-low"`, then skip the normalize call above (no map to normalize). If X, halt workflow.
135
+ - Wait for user selection. If D, set `degraded_mode: true` and `confidence_mode = "degraded — all findings T1-low"`, then skip the normalize call above (no map to normalize). If X, halt workflow (exit 6, `halt_reason: "user-cancelled"`).
136
+
137
+ **Headless default** (when `{headless_mode}`): consume the pre-supplied `degraded` input from the Invocation Contract. If `degraded=true`, auto-select **[D]** (set `degraded_mode: true`, `confidence_mode = "degraded — all findings T1-low"`, skip the normalize call) and log: `"headless: no provenance map for {skill_name}; proceeding in degraded mode (text-diff, T1-low) per pre-supplied degraded=true."` If `degraded` is unset or false, auto-select **[X] abort** (exit 6, `halt_reason: "user-cancelled"`) and log: `"headless: no provenance map for {skill_name} and degraded not pre-supplied; aborting. Re-run with degraded=true for text-diff."` Never silently emit a low-confidence report under automation without explicit opt-in — same stance as the [A]-abort default at §5b's dirty-worktree sub-gate.
129
138
 
130
139
  ### Stack Skill Detection
131
140
 
132
141
  `{is_stack_skill}` and `{legacy_stack_provenance}` are already resolved by the normalize call in §4 — no additional walk needed. Apply the post-detection logic:
133
142
 
134
143
  If `{is_stack_skill}` is true and `constituents` array is present (compose-mode stack):
135
- - For each constituent, compute the current metadata hash: read `{constituent.skill_path}/active/{constituent.skill_name}/metadata.json` and compute SHA-256
136
- - Compare against `constituent.metadata_hash`
137
- - Flag any mismatches as **constituent drift** with severity HIGH
138
- - Record constituent freshness results for the report
144
+
145
+ Re-hashing each constituent's live `metadata.json` and comparing against the compile-time snapshot is deterministic work — and the model cannot compute a `sha256:{hexdigest}` natively (it must shell out on every run). Delegate the whole read/hash/compare pass to the shared helper, which hashes byte-symmetrically with how `constituents[].metadata_hash` was written at compose time (the `sha256:`-prefixed digest of the raw `metadata.json` bytes). This mirrors the two sibling drift checks — `structural-diff.md` §4b (`skf-compare-file-hashes.py`) and `step-doc-drift.md` §2 (`skf-detect-docs.py compare-hashes`).
146
+
147
+ **Resolve `{compareConstituentHashesHelper}`** from `{compareConstituentHashesProbeOrder}`; first existing path wins.
148
+
149
+ Run one deterministic comparison subprocess over the provenance map's `constituents[]`. Relative constituent `skill_path` values (e.g. `skills/{skill-dir}/`) are project-root-relative, so resolve them against `{project-root}`:
150
+
151
+ ```bash
152
+ uv run {compareConstituentHashesHelper} compare-constituent-hashes {provenanceMap} --skills-root {project-root}
153
+ ```
154
+
155
+ Parse the emitted JSON:
156
+
157
+ ```json
158
+ {
159
+ "drifted": [{"skill_name": "...", "skill_path": "...", "stored_hash": "sha256:...", "current_hash": "sha256:..."}],
160
+ "fresh": [{"skill_name": "..."}],
161
+ "missing": [{"skill_name": "...", "skill_path": "...", "stored_hash": "sha256:...", "reason": "metadata-not-found|incomplete-record"}],
162
+ "skipped_null_hash": [{"skill_name": "..."}],
163
+ "stats": {"total": N, "drifted": N, "fresh": N, "missing": N, "skipped_null_hash": N}
164
+ }
165
+ ```
166
+
167
+ - **Flag every entry in `drifted[]` as constituent drift with severity HIGH** — its live `metadata.json` differs from the compile-time snapshot recorded in the provenance map.
168
+ - `fresh[]` are unchanged constituents. `missing[]` (each carrying a `reason`) are constituents whose `metadata.json` could not be located (`metadata-not-found`) or whose provenance record lacked `skill_name`/`skill_path` (`incomplete-record`) — surface these as a lower-severity note, not HIGH drift. `skipped_null_hash[]` had no compile-time baseline hash (recorded from a references/ cascade) — never reported as drift.
169
+ - Record the constituent freshness results (the four buckets + `stats`) for the report — read the counts straight from `stats`, no manual recount.
170
+
171
+ **If `uv`/the helper cannot execute** (e.g. claude.ai web): fall back to hashing by hand — for each constituent, read its `metadata.json` at `{constituent.skill_path}/active/{constituent.skill_name}/metadata.json` (resolve `skill_path` against `{project-root}` when relative, use as-is when absolute), SHA-256 the raw bytes, and compare against `constituent.metadata_hash` (a stored bare-hex form still matches after stripping any `sha256:` prefix from both sides). Flag mismatches as HIGH constituent drift.
139
172
 
140
173
  If `{legacy_stack_provenance}` is true: log a note that this stack uses v1 provenance format with reduced audit depth (library-level only, no per-export verification).
141
174
 
@@ -150,7 +183,7 @@ If `{legacy_stack_provenance}` is true: log a note that this stack uses v1 prove
150
183
  - Ask user: "Please provide the path to the current source code."
151
184
  - `baseline_commit` and `baseline_ref` are unavailable — §5b will short-circuit
152
185
 
153
- **Validate:** Confirm source directory exists and contains expected files.
186
+ **Validate:** Confirm the source directory exists and is accessible. If it is missing or unreadable → HALT with **exit 3**, `halt_reason: "source-dir-missing"`. When `{headless_mode}`, emit the error envelope on **stderr** (shape per SKILL.md → Result Contract) and log: `"headless: source directory {source_root} from the provenance map no longer exists; aborting."`
154
187
 
155
188
  ### 5b. Detect Upstream Drift
156
189
 
@@ -221,7 +254,10 @@ When skipping, log the reason, then set the audit-ref context variables to basel
221
254
  - **[F]:** Run `git -C {source_root} checkout --force {chosen_ref}` instead of the plain checkout. Record `pre_checkout_force_discard: true` in workflow context for step 6 to surface as a loud warning. Skip the stash path.
222
255
  - **Other input:** help user, redisplay the sub-gate.
223
256
 
224
- **Headless default** (when `{headless_mode}`): auto-select **[A] Abort** rather than silently mutating the working tree. Emit a loud log line: `"headless: dirty worktree detected at {source_root}; refusing to checkout {chosen_ref} or stash. Re-run interactively to choose [T]/[A]/[F]."` Stashing under automation could lose work if the operator never returns to pop; force-checkout under automation could destroy uncommitted work outright. Abort is the only safe non-interactive default.
257
+ **Headless default** (when `{headless_mode}`): consume the pre-supplied `dirty_worktree_choice` from the Invocation Contract the operator's explicit answer is the consent that a silent working-tree mutation would otherwise lack.
258
+ - **`dirty_worktree_choice=T`**: run the `[T]` transient-stash path. Log: `"headless: dirty worktree at {source_root}; stashing before checkout per pre-supplied dirty_worktree_choice=T."`
259
+ - **`dirty_worktree_choice=F` with `force=true`**: run the `[F]` force-checkout path — `force=true` is the required consent to discard uncommitted changes irrecoverably. Log: `"headless: dirty worktree at {source_root}; force-discarding uncommitted changes per pre-supplied dirty_worktree_choice=F force=true."`
260
+ - **`dirty_worktree_choice=A`, unset, or `=F` without `force=true`**: auto-select **[A] Abort** (exit 6, `halt_reason: "user-cancelled"`). Abort is the safe default, and a force-discard without `force=true` consent is refused rather than executed. Log: `"headless: dirty worktree detected at {source_root}; refusing to checkout {chosen_ref} (dirty_worktree_choice={value or 'unset'}). Pass dirty_worktree_choice=T, or =F with force=true, to proceed non-interactively."` Stashing that is never popped could lose work; force-checkout without consent could destroy uncommitted work outright — so both require an explicit pre-supplied choice.
225
261
 
226
262
  If `git status --porcelain` is empty, skip the sub-gate and proceed directly to the checkout.
227
263
 
@@ -230,7 +266,10 @@ When skipping, log the reason, then set the audit-ref context variables to basel
230
266
  - **[X]:** HALT workflow — do not create drift report.
231
267
  - **Other input:** help user, redisplay gate.
232
268
 
233
- **Headless default** (when `{headless_mode}`): auto-select **[S]** and emit a loud log line: `"headless: upstream drift detected ({baseline_ref} → {latest_tag or remote_head}); staying on baseline. Re-run interactively to audit against latest."` Do not check out in headless mode — silent ref changes under automation would mutate the user's working tree without consent.
269
+ **Headless default** (when `{headless_mode}`): consume the pre-supplied `upstream_drift_choice` from the Invocation Contract.
270
+ - **`upstream_drift_choice=S`, or unset**: auto-select **[S] Stay-on-baseline** (default). Set `audit_ref = baseline_ref`, `audit_ref_source = "baseline"`, `audit_commit = baseline_commit`. Log: `"headless: upstream drift detected ({baseline_ref} → {latest_tag or remote_head}); staying on baseline per upstream_drift_choice={value or 'default S'}. Pass upstream_drift_choice=C to audit against latest."` Defaulting to a checkout would mutate the working tree without consent, so `[S]` remains the default when no choice is supplied.
271
+ - **`upstream_drift_choice=C`**: run the `[C] Checkout-and-audit-against-latest` path above — the operator's pre-supplied choice is the explicit consent that a silent ref change would otherwise lack. The dirty-worktree sub-gate still applies and consults its own pre-supplied `dirty_worktree_choice`. Log: `"headless: upstream drift detected; checking out {latest_tag or remote_head} per pre-supplied upstream_drift_choice=C."`
272
+ - **`upstream_drift_choice=X`**: HALT the workflow (exit 6, `halt_reason: "user-cancelled"`) — do not create a drift report. Log: `"headless: upstream drift detected; aborting per pre-supplied upstream_drift_choice=X."`
234
273
 
235
274
  5. **Record for report:** store `audit_ref`, `audit_ref_source`, `audit_commit`, `latest_tag`, `remote_head`, and `baseline_commit` in context. Step-06 surfaces them in the Provenance section so readers can tell which comparison actually ran.
236
275
 
@@ -252,7 +291,7 @@ When skipping, log the reason, then set the audit-ref context variables to basel
252
291
  - **[D]:** Read the prior report's findings_list (parse the Structural/Semantic/Severity sections, or the appended findings tables) and stash as `prior_findings` in workflow context. Run the new audit normally. In step 6 (report.md), after the Remediation Suggestions section, emit a `## Diff Against Prior Report` subsection summarizing added / removed / changed findings vs `prior_findings`.
253
292
  - **[R]:** Load the prior report's frontmatter (`stepsCompleted`, `drift_score`, any intermediate state). Set `{outputFile}` to the prior report path (do NOT create a new one). Determine the next un-completed step from `stepsCompleted` and skip forward to it; downstream steps append to the existing report.
254
293
 
255
- > **Note (resumability):** the existing template frontmatter captures `stepsCompleted` and `drift_score` but does not currently persist intermediate findings_list between stages. If [R] is selected and stepsCompleted indicates the prior run halted after structural-diff or semantic-diff, the appended sections in the report body (`## Structural Drift`, `## Semantic Drift`, `## Severity Classification`) serve as the implicit intermediate state — re-parse them on resume rather than re-running completed stages. **Design note:** explicit mid-stage resume state is intentionally not persisted today — if resumability proves unreliable in practice, a future enhancement is to extend the report frontmatter to carry an explicit `intermediate_findings` block.
294
+ > **Note (resumability):** the template frontmatter captures `stepsCompleted` and `drift_score` but does not persist an intermediate findings_list between stages. If [R] is selected and stepsCompleted indicates the prior run halted after structural-diff or semantic-diff, the appended report-body sections (`## Structural Drift`, `## Semantic Drift`, `## Severity Classification`) serve as the implicit intermediate state — re-parse them on resume rather than re-running completed stages.
256
295
 
257
296
  - **Other input:** help user, redisplay the gate.
258
297
 
@@ -268,7 +307,9 @@ Create `{outputFile}` from `{templateFile}`:
268
307
  - Set `stepsCompleted: ['init']`
269
308
  - Fill Audit Summary skeleton with loaded baseline data
270
309
 
271
- ### 7. Present Baseline Summary (User Gate)
310
+ If the write fails (read-only mount, disk full, permissions denied) → HALT with **exit 4**, `halt_reason: "write-failed"`. When `{headless_mode}`, emit the error envelope on **stderr** (shape per SKILL.md → Result Contract).
311
+
312
+ ### 7. Present Baseline Summary and Confirm (User Gate)
272
313
 
273
314
  "**Audit Baseline Loaded**
274
315
 
@@ -290,22 +331,7 @@ Create `{outputFile}` from `{templateFile}`:
290
331
 
291
332
  **Ready to begin drift analysis?**"
292
333
 
293
- ### 8. Present MENU OPTIONS
294
-
295
- Display: "**Select:** [C] Continue to Analysis"
296
-
297
- #### Menu Handling Logic:
298
-
299
- - IF C: Save baseline to {outputFile}, update frontmatter stepsCompleted, then load, read entire file, then execute {nextStepFile}
300
- - IF Any other: help user, then [Redisplay Menu Options](#8-present-menu-options)
301
-
302
- #### EXECUTION RULES:
303
-
304
- - ALWAYS halt and wait for user input after presenting menu
305
- - **GATE [default: C]** — If `{headless_mode}`: auto-proceed with [C] Continue, log: "headless: auto-continue past baseline confirmation"
306
- - ONLY proceed to next step when user selects 'C'
307
-
308
- ## CRITICAL STEP COMPLETION NOTE
334
+ Halt and wait for the user's go-ahead. Only proceed once the drift report has been created with baseline data populated. On confirmation, save the baseline to `{outputFile}`, append `'init'` to the frontmatter `stepsCompleted`, then load, read the entire file, and execute `{nextStepFile}`. On any other input, help the user, then re-ask.
309
335
 
310
- ONLY WHEN C is selected and the drift report has been created with baseline data populated, will you then load and read fully `{nextStepFile}` to execute and begin source re-indexing.
336
+ **GATE [default: proceed]** if `{headless_mode}`, auto-proceed and log: "headless: auto-continue past baseline confirmation".
311
337
 
@@ -14,7 +14,7 @@ Re-scan the source code using the current forge tier tools to build a fresh extr
14
14
  ## Rules
15
15
 
16
16
  - Focus only on extracting current source state — do not compare yet (that's Step 03)
17
- - Do not skip files or take shortcuts in extraction
17
+ - Extract every file in the bounded scan list — a file skipped here makes step 3 flag its exports as false "removed" drift
18
18
  - Use subprocess Pattern 2 (per-file deep analysis) when available for AST extraction; if unavailable, extract in main thread file by file
19
19
 
20
20
  ## MANDATORY SEQUENCE
@@ -53,13 +53,10 @@ Audit-skill detects drift on files that were in scope during create-skill. The a
53
53
 
54
54
  **If a provenance map was loaded in step 1** (normal mode):
55
55
 
56
- 1. Extract the unique set of file paths from the provenance map:
57
- - `entries[].source_file` (one path per extracted export)
58
- - `file_entries[].source_file` (one path per tracked script/asset, when present)
59
- 2. Deduplicate the combined list. This is the **bounded scan list**.
60
- 3. Verify each path under `{source_root}`. Files that existed at creation time but are now missing are **not** errors at this stage — keep them in the list so step 3 can classify them as DELETED. Handling missing files is step 3's job, not step 2's.
61
- 4. Record `bounded_scan: true` and `bounded_scan_source: "provenance-map"` in context for the evidence report.
62
- 5. Report:
56
+ 1. The **bounded scan list** is `{bounded_scan_files}` — the union of `entries[].source_file` and `file_entries[].source_file`, deduplicated, sorted, and forward-slash normalized by init.md §4's `skf-load-provenance.py normalize` call. Consume it directly; do **not** re-walk the provenance map to rebuild it. The union/dedup/sort has one correct answer per map and is already scripted — re-deriving it in-prompt risks diverging from step 3, which diffs against the same normalized projection.
57
+ 2. Verify each path under `{source_root}`. Files that existed at creation time but are now missing are **not** errors at this stage — keep them in the list so step 3 can classify them as DELETED. Handling missing files is step 3's job, not step 2's.
58
+ 3. Record `bounded_scan: true` and `bounded_scan_source: "provenance-map"` in context for the evidence report.
59
+ 4. Report:
63
60
 
64
61
  "**Bounded scan:** {count} files from provenance map ({provenance_date})."
65
62
 
@@ -76,7 +73,7 @@ Audit-skill detects drift on files that were in scope during create-skill. The a
76
73
 
77
74
  ### 3. Extract Current Exports
78
75
 
79
- **DO NOT BE LAZY — For EACH file in the bounded scan list from §2, launch a subprocess that:**
76
+ **For each file in the bounded scan list from §2, launch a subprocess that:**
80
77
  1. Loads the source file
81
78
  2. Extracts all public exports using tier-appropriate method
82
79
  3. Records: export name, type, signature, file path, line number, confidence tier
@@ -86,7 +83,7 @@ Audit-skill detects drift on files that were in scope during create-skill. The a
86
83
 
87
84
  **If subprocess unavailable:** Perform extraction in main thread, processing each file sequentially.
88
85
 
89
- **Build extraction snapshot:**
86
+ **Build extraction snapshot and persist it to `{forge_version}/extraction-snapshot.json`** — step 3 (`structural-diff.md`) reads this file directly, so it must be written to disk, not merely held in context:
90
87
  ```
91
88
  {
92
89
  "extraction_date": "{timestamp}",
@@ -108,15 +105,17 @@ Audit-skill detects drift on files that were in scope during create-skill. The a
108
105
  }
109
106
  ```
110
107
 
108
+ Record the written path as `{extractionSnapshot}` in workflow context — step 3 passes it to the deterministic structural-diff helper.
109
+
111
110
  ### 4. Deep Tier Enhancement (Deep Only)
112
111
 
113
- **IF forge tier is Deep:**
112
+ **If forge tier is Deep:**
114
113
 
115
114
  Read the `qmd_collections` registry from `{sidecar_path}/forge-tier.yaml`.
116
115
 
117
116
  Find the collection entry matching the current skill: look for an entry where `skill_name` matches the current skill being audited AND `type` is `"extraction"`.
118
117
 
119
- Three collection states must be handled distinctly (same branching as step 4 §2 keep them in sync):
118
+ Three collection states must be handled distinctly semantic-diff.md §2 branches the same way:
120
119
 
121
120
  **If a matching extraction collection is found and populated** (pre-query probe via `qmd ls {collection_name}` or equivalent returns one or more files):
122
121
  Query qmd_bridge against the `{skill_name}-extraction` collection for temporal context on each extracted export:
@@ -135,12 +134,12 @@ Continue without T2 enrichment — the unpopulated collection is a setup gap, no
135
134
  Log: "No QMD extraction collection found for {skill_name}. Temporal enrichment skipped. Re-run [CS] Create Skill to generate the collection."
136
135
  Continue without T2 enrichment — this is not an error.
137
136
 
138
- **IF forge tier is Quick, Forge, or Forge+:**
137
+ **If forge tier is Quick, Forge, or Forge+:**
139
138
  Skip this section. Temporal context requires Deep tier.
140
139
 
141
140
  ### 4b. CCC Rename Detection (Forge+ and Deep with ccc)
142
141
 
143
- **IF `tools.ccc` is true in forge-tier.yaml:**
142
+ **If `tools.ccc` is true in forge-tier.yaml:**
144
143
 
145
144
  For each export in the skill baseline that was NOT found at its recorded file path during re-extraction (potential "deleted" export):
146
145
 
@@ -153,7 +152,7 @@ For each export in the skill baseline that was NOT found at its recorded file pa
153
152
 
154
153
  CCC failures: skip rename detection silently, proceed with standard structural diff.
155
154
 
156
- **IF `tools.ccc` is false:** Skip this section silently.
155
+ **If `tools.ccc` is false:** Skip this section silently.
157
156
 
158
157
  ### 5. Validate Extraction Completeness
159
158
 
@@ -174,23 +173,5 @@ CCC failures: skip rename detection silently, proceed with standard structural d
174
173
 
175
174
  ### 6. Update Report and Auto-Proceed
176
175
 
177
- Update {outputFile} frontmatter:
178
- - Append `'re-index'` to `stepsCompleted`
179
-
180
- ### 7. Present MENU OPTIONS
181
-
182
- Display: "**Proceeding to structural diff...**"
183
-
184
- #### Menu Handling Logic:
185
-
186
- - After extraction is complete and frontmatter updated, immediately load, read entire file, then execute {nextStepFile}
187
-
188
- #### EXECUTION RULES:
189
-
190
- - This is an auto-proceed analysis step with no user choices
191
- - Proceed directly to next step after extraction
192
-
193
- ## CRITICAL STEP COMPLETION NOTE
194
-
195
- ONLY WHEN the extraction snapshot is complete with all source files processed will you then load and read fully `{nextStepFile}` to execute and begin structural comparison.
176
+ Update {outputFile} frontmatter — append `'re-index'` to `stepsCompleted`. Once the extraction snapshot is complete with all source files processed, load, read fully, and execute `{nextStepFile}` (structural diff).
196
177
 
@@ -34,24 +34,7 @@ Update the ## Audit Summary section at the top of {outputFile} with final calcul
34
34
 
35
35
  ### 2. Generate Remediation Suggestions
36
36
 
37
- For EACH classified drift finding, generate a specific remediation suggestion:
38
-
39
- **CRITICAL findings remediation:**
40
- - Removed export → "Remove reference to `{export_name}` from SKILL.md section {section}. Export no longer exists at `{file}:{line}`."
41
- - Changed signature → "Update `{export_name}` signature in SKILL.md from `{old_signature}` to `{new_signature}`. See `{file}:{line}`."
42
- - Renamed export → "Replace `{old_name}` with `{new_name}` throughout SKILL.md. Renamed at `{file}:{line}`."
43
-
44
- **HIGH findings remediation:**
45
- - New public API (>3) → "Add documentation for {count} new exports to SKILL.md: {export_list}. Consider running update-skill workflow."
46
- - Deprecated API → "Mark `{export_name}` as deprecated in SKILL.md. Current replacement: `{replacement}` at `{file}:{line}`."
47
-
48
- **MEDIUM findings remediation:**
49
- - Moved function → "Update file reference for `{export_name}` from `{old_file}` to `{new_file}:{line}`."
50
- - New exports (1-3) → "Consider adding `{export_names}` to SKILL.md for completeness."
51
- - Changed convention → "Review convention documentation in SKILL.md for currency."
52
-
53
- **LOW findings remediation:**
54
- - Style changes → "Optional: Update style references in SKILL.md to reflect current conventions."
37
+ For each classified drift finding, write one concrete remediation derived from the finding itself: **what** to change in the audited **SKILL.md** (or its `references/`) — not the source code — **where** (the section plus the source `{file}:{line}` the finding cites), and **why**. Set effort (`low`/`medium`/`high`) by how much of the skill doc the change touches. A reviewer should be able to act on each row without re-deriving the finding.
55
38
 
56
39
  Append to {outputFile}:
57
40
 
@@ -125,50 +108,20 @@ Append to {outputFile}:
125
108
 
126
109
  Update {outputFile} frontmatter:
127
110
  - Append `'report'` to `stepsCompleted`
128
- - Set `drift_score` to final calculated score
111
+ - Set `drift_score` to the score from step 5's classification helper
129
112
  - Set `nextWorkflow` to `'update-skill'` if CRITICAL or HIGH findings, otherwise leave empty
130
113
 
131
- ### 5. Present Final Report Summary
132
-
133
- "**Audit Complete: {skill_name}**
134
-
135
- ---
136
-
137
- **Overall Drift Score: {CLEAN / MINOR / SIGNIFICANT / CRITICAL}**
138
-
139
- | Severity | Count |
140
- |----------|-------|
141
- | CRITICAL | {count} |
142
- | HIGH | {count} |
143
- | MEDIUM | {count} |
144
- | LOW | {count} |
145
- | **Total** | {total} |
114
+ If finalizing the report or writing the result JSON below fails (read-only mount, disk full, permissions denied) → HALT with **exit 4**, `halt_reason: "write-failed"`. When `{headless_mode}`, emit the error envelope on **stderr** (shape per SKILL.md Result Contract) with `report_path: null`.
146
115
 
147
- **Report saved to:** `{outputFile}`
148
-
149
- {IF CRITICAL/HIGH findings:}
150
- **Action Required:** {count} priority items need remediation. Recommend running `[US] Update Skill` workflow.
151
-
152
- {IF MEDIUM/LOW only:}
153
- **Minor Drift:** Skill is functional but could benefit from updates. See report for details.
154
-
155
- {IF CLEAN:}
156
- **All Clear:** No drift detected. Skill accurately reflects current source code.
157
-
158
- ---
116
+ ### 5. Present Final Report Summary
159
117
 
160
- **Next Steps:**
161
- {IF findings exist:}
162
- 1. **[US] Update Skill** — Automatically apply remediations from this drift report
163
- 2. **Review report** — Manual review at `{outputFile}`
118
+ Present a concise completion summary to the user conveying: the skill name, the **overall drift score** (CLEAN / MINOR / SIGNIFICANT / CRITICAL), the severity-count table (CRITICAL / HIGH / MEDIUM / LOW / Total), and the saved report path (`{outputFile}`). Close with the next-action recommendation matching the drift level:
164
119
 
165
- {IF CLEAN:}
166
- 1. **No action needed** Skill is current
167
- 2. **[EX] Export Skill** Skill is ready for distribution
168
-
169
- ---
120
+ - **CRITICAL or HIGH findings** → action required: recommend running the `[US] Update Skill` workflow to apply the priority remediations; manual review at `{outputFile}` is the alternative.
121
+ - **MEDIUM or LOW only** minor drift: manual updates suffice, or run `[US] Update Skill` for automated remediation.
122
+ - **CLEAN** no action needed; the skill is current and ready for `[EX] Export Skill`.
170
123
 
171
- **Audit workflow complete.**"
124
+ This summary reads as final but is **not** the terminal step — proceed to §6.
172
125
 
173
126
  ### Result Contract
174
127
 
@@ -182,7 +135,7 @@ SKF_AUDIT_RESULT_JSON: {"status":"success","skill_name":"{skill_name}","drift_sc
182
135
 
183
136
  Field rules: `next_workflow` is `"update-skill"` when CRITICAL or HIGH findings exist (matches the frontmatter `nextWorkflow` set in §4), otherwise `null`. `audit_ref` carries the resolved value from step 1 §5b (`baseline_ref` when no upstream drift was detected, `latest_tag` or `remote_head` when the operator chose `[C] Checkout-and-audit-against-latest`).
184
137
 
185
- **HALT envelope mirror (headless only).** For every HARD HALT raised in this workflow (skill-not-found at init.md §1, forge-tier missing at §2, source-dir missing at §5, write-failed at §6, user-cancelled at any `[X]` selection), emit the same envelope shape on **stderr** with `status: "error"`, `drift_score: null` (or last known value if classification ran), `report_path: null` if the report write failed, `exit_code` matching the Exit Codes table, and `halt_reason` set to the failure class from the table (`"skill-not-found"`, `"forge-tier-missing"`, `"source-dir-missing"`, `"write-failed"`, `"user-cancelled"`). This is the only signal a wrapping pipeline receives on failure log it before exiting.
138
+ **Hard-halt envelope (headless only).** Every hard halt emits this same envelope shape on **stderr** with `status: "error"` and the `exit_code` / `halt_reason` for its failure class (per SKILL.md Exit Codes and Result Contract), produced at the halting site before exit it is the only failure signal a wrapping pipeline receives, so log it before exiting. `drift_score` carries its last known value (`null` if classification never ran); `report_path` is `null` when the report write failed.
186
139
 
187
140
  **Post-audit hook (optional).** If `{onCompleteCommand}` is non-empty (resolved at SKILL.md On Activation §3 from `workflow.on_complete`), invoke it as:
188
141
 
@@ -194,5 +147,5 @@ where `{result_json_path}` is the per-run record path written above (`{forge_ver
194
147
 
195
148
  ### 6. Chain to Health Check
196
149
 
197
- ONLY WHEN the report has been written, presented, and the 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 user-facing summary reads as final.
150
+ Only when the report has been written, presented, and the result contract saved do 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 user-facing summary reads as final.
198
151
 
@@ -13,7 +13,7 @@ Compare QMD knowledge context between the original skill creation and current st
13
13
 
14
14
  ## Rules
15
15
 
16
- - CONDITIONAL: Skip entire analysis at Quick/Forge/Forge+ tier — append skip notice only
16
+ - At Quick/Forge/Forge+ tier, skip the entire analysis — append the skip notice only
17
17
  - Focus only on semantic/meaning-level changes via QMD context — do not repeat structural findings from Step 03
18
18
  - Do not classify severity (Step 05)
19
19
  - Use subprocess Pattern 3 when available for QMD queries; if unavailable, query in main thread
@@ -22,7 +22,7 @@ Compare QMD knowledge context between the original skill creation and current st
22
22
 
23
23
  ### 1. Check Forge Tier
24
24
 
25
- **IF forge tier is Quick, Forge, or Forge+:**
25
+ **If forge tier is Quick, Forge, or Forge+:**
26
26
 
27
27
  Append to {outputFile}:
28
28
 
@@ -40,7 +40,7 @@ Update frontmatter: append `'semantic-diff'` to `stepsCompleted`
40
40
 
41
41
  → Auto-proceed to {nextStepFile}
42
42
 
43
- **IF forge tier is Deep:**
43
+ **If forge tier is Deep:**
44
44
 
45
45
  Continue to section 2.
46
46
 
@@ -127,23 +127,5 @@ Append to {outputFile}:
127
127
 
128
128
  ### 5. Update Report and Auto-Proceed
129
129
 
130
- Update {outputFile} frontmatter:
131
- - Append `'semantic-diff'` to `stepsCompleted`
132
-
133
- ### 6. Present MENU OPTIONS
134
-
135
- Display: "**Semantic diff complete. {total} semantic drift items found. Proceeding to severity classification...**"
136
-
137
- #### Menu Handling Logic:
138
-
139
- - After semantic diff section is appended and frontmatter updated, immediately load, read entire file, then execute {nextStepFile}
140
-
141
- #### EXECUTION RULES:
142
-
143
- - This is an auto-proceed analysis step with no user choices
144
- - Proceed directly to next step after completion
145
-
146
- ## CRITICAL STEP COMPLETION NOTE
147
-
148
- ONLY WHEN the ## Semantic Drift section (or skip notice) has been appended to {outputFile} will you then load and read fully `{nextStepFile}` to execute and begin severity classification.
130
+ Update {outputFile} frontmatter — append `'semantic-diff'` to `stepsCompleted`. Once the ## Semantic Drift section (or skip notice) has been appended, load, read fully, and execute `{nextStepFile}` (severity classification).
149
131