bmad-module-skill-forge 1.4.1 → 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 (230) 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 +34 -4
  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/{steps-c/step-01-init.md → references/init.md} +57 -19
  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 -17
  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} +11 -11
  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} +11 -11
  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} +11 -49
  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} +20 -8
  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} +109 -113
  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} +16 -31
  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-refine-architecture/steps-c/step-01-init.md +0 -136
  226. package/src/skf-rename-skill/steps-c/step-04-health-check.md +0 -22
  227. package/src/skf-test-skill/steps-c/step-07-health-check.md +0 -25
  228. package/src/skf-update-skill/steps-c/step-07-report.md +0 -148
  229. package/src/skf-update-skill/steps-c/step-08-health-check.md +0 -22
  230. package/src/skf-verify-stack/steps-c/step-01-init.md +0 -178
@@ -1,9 +1,12 @@
1
1
  ---
2
- nextStepFile: './step-03-identify-units.md'
2
+ nextStepFile: 'identify-units.md'
3
3
  outputFile: '{forge_data_folder}/analyze-source-report-{project_name}.md'
4
4
  heuristicsFile: 'references/unit-detection-heuristics.md'
5
+ scanManifestsScript: '{project-root}/src/shared/scripts/skf-scan-manifests.py'
5
6
  ---
6
7
 
8
+ <!-- Config: communicate in {communication_language}. -->
9
+
7
10
  # Step 2: Scan Project
8
11
 
9
12
  ## STEP GOAL:
@@ -14,13 +17,11 @@ To map the complete project structure by scanning directory trees, detecting ser
14
17
 
15
18
  - Focus only on structural scanning — do not classify units or map exports yet
16
19
  - Do not read source file contents beyond manifest files and entry points
17
- - Use subprocess Pattern 1 for scanning across many files
20
+ - Delegate per-file scanning to subagents in parallel when many files are involved (main-thread fallback is fine)
18
21
  - Tier-aware scanning depth: Quick (file structure), Forge (+ manifest parsing), Deep (+ config analysis)
19
22
 
20
23
  ## MANDATORY SEQUENCE
21
24
 
22
- **CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise unless user explicitly requests a change.
23
-
24
25
  ### 1. Load Context
25
26
 
26
27
  Read {outputFile} frontmatter to obtain:
@@ -36,9 +37,9 @@ Load {heuristicsFile} for reference on detection signals.
36
37
 
37
38
  1. Map the top-level directory tree (2-3 levels deep)
38
39
  2. Identify workspace configuration files (pnpm-workspace.yaml, lerna.json, Cargo.toml [workspace], go.work, etc.)
39
- 3. Find all package manifests (package.json, Cargo.toml, go.mod, requirements.txt, pyproject.toml, build.gradle, pom.xml)
40
+ 3. Enumerate package manifests deterministically — invoke `uv run {scanManifestsScript} scan {path}` and parse the JSON envelope. The script returns `{manifests[], total_unique, monorepo, warnings?}` covering npm/python/rust/go/maven/gradle/ruby/composer/swift; record each `{path, ecosystem}` for the manifests catalog in §4 and capture `monorepo` for the boundary-signal pass in §3
40
41
  4. Locate entry point files (index.ts, main.ts, app.ts, main.go, main.rs, __init__.py, etc.)
41
- 5. Detect service configuration (Dockerfile, docker-compose.yml, kubernetes manifests, serverless.yml)
42
+ 5. Detect service configuration (Dockerfile, docker-compose.yml, kubernetes manifests, serverless.yml) — keep this step LLM-driven; file glob + presence check is sufficient, no parsing required
42
43
  6. Return structured findings — file paths and types only, not contents
43
44
 
44
45
  **If subprocess unavailable:** Perform directory scanning in main thread using file I/O tools.
@@ -120,7 +121,7 @@ Wait for user feedback. If user identifies gaps, rescan as directed.
120
121
 
121
122
  Append the complete "## Project Scan" section to {outputFile}:
122
123
 
123
- Replace the placeholder `[Appended by step-02-scan-project]` with the full scan results including:
124
+ Replace the placeholder `[Appended by scan-project]` with the full scan results including:
124
125
  - Structure overview
125
126
  - Detected boundaries table
126
127
  - Manifests catalog
@@ -130,17 +131,18 @@ Replace the placeholder `[Appended by step-02-scan-project]` with the full scan
130
131
 
131
132
  Update {outputFile} frontmatter:
132
133
  ```yaml
133
- stepsCompleted: [append 'step-02-scan-project' to existing array]
134
- lastStep: 'step-02-scan-project'
134
+ stepsCompleted: [append 'scan-project' to existing array]
135
+ lastStep: 'scan-project'
135
136
  ```
136
137
 
137
138
  ### 7. Present MENU OPTIONS
138
139
 
139
- Display: "**Select:** [C] Continue to Unit Identification"
140
+ Display: "**Select:** [C] Continue to Unit Identification | [X] Cancel and exit"
140
141
 
141
142
  #### Menu Handling Logic:
142
143
 
143
144
  - IF C: Save scan results to {outputFile}, update frontmatter, then load, read entire file, then execute {nextStepFile}
145
+ - IF X: HARD HALT with exit code 6 (`user-cancelled`). Emit the `SKF_ANALYZE_RESULT_JSON` envelope on stderr with `status: "error"`, `halt_reason: "user-cancelled"`, and counts/paths reflecting state at cancellation
144
146
  - IF Any other: help user, then [Redisplay Menu Options](#7-present-menu-options)
145
147
 
146
148
  #### EXECUTION RULES:
@@ -1,3 +1,5 @@
1
+ <!-- Config: communicate in {communication_language}. -->
2
+
1
3
  # Unit Detection Heuristics
2
4
 
3
5
  ## Purpose
@@ -18,24 +18,24 @@ nextWorkflow: ''
18
18
 
19
19
  ## Project Scan
20
20
 
21
- [Appended by step-02-scan-project]
21
+ [Appended by scan-project]
22
22
 
23
23
  ## Identified Units
24
24
 
25
- [Appended by step-03-identify-units]
25
+ [Appended by identify-units]
26
26
 
27
27
  ## Export Map
28
28
 
29
- [Appended by step-04-map-and-detect]
29
+ [Appended by map-and-detect]
30
30
 
31
31
  ## Integration Points
32
32
 
33
- [Appended by step-04-map-and-detect]
33
+ [Appended by map-and-detect]
34
34
 
35
35
  ## Recommendations
36
36
 
37
- [Appended by step-05-recommend]
37
+ [Appended by recommend]
38
38
 
39
39
  ## Generation Results
40
40
 
41
- [Appended by step-06-generate-briefs]
41
+ [Appended by generate-briefs]
@@ -9,6 +9,14 @@ description: Drift detection between skill and current source code. Use when the
9
9
 
10
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.
11
11
 
12
+ ## Conventions
13
+
14
+ - Bare paths (e.g. `references/<name>.md`) resolve from the skill root.
15
+ - `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
+ - `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives, if present).
17
+ - `{project-root}`-prefixed paths resolve from the project working directory.
18
+ - `{skill-name}` resolves to the skill directory's basename.
19
+
12
20
  ## Role
13
21
 
14
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.
@@ -18,11 +26,8 @@ You are a skill auditor operating in Ferris Audit mode. This is a deterministic
18
26
  These rules apply to every step in this workflow:
19
27
 
20
28
  - Never fabricate findings — all data must trace to source code with file:line citations
21
- - Read each step file completely before taking any action
22
- - Follow the mandatory sequence in each step exactly — do not skip, reorder, or optimize
23
29
  - Only load one step file at a time — never preload future steps
24
30
  - Update `stepsCompleted` in output file frontmatter before loading next step
25
- - If any instruction references a subprocess or tool you lack, achieve the outcome in your main context thread
26
31
  - Always communicate in `{communication_language}`
27
32
  - If `{headless_mode}` is true, auto-proceed through confirmation gates with their default action and log each auto-decision
28
33
 
@@ -30,22 +35,45 @@ These rules apply to every step in this workflow:
30
35
 
31
36
  | # | Step | File | Auto-proceed |
32
37
  |---|------|------|--------------|
33
- | 1 | Initialize & Baseline | steps-c/step-01-init.md | No (confirm) |
34
- | 2 | Re-Index Source | steps-c/step-02-re-index.md | Yes |
35
- | 3 | Structural Diff | steps-c/step-03-structural-diff.md | Yes |
36
- | 4 | Semantic Diff | steps-c/step-04-semantic-diff.md | Yes (skip at non-Deep) |
37
- | 5 | Severity Classification | steps-c/step-05-severity-classify.md | Yes |
38
- | 6 | Report | steps-c/step-06-report.md | Yes |
39
- | 7 | Workflow Health Check | steps-c/step-07-health-check.md | Yes |
38
+ | 1 | Initialize & Baseline | references/init.md | No (confirm) |
39
+ | 2 | Re-Index Source | references/re-index.md | Yes |
40
+ | 3 | Structural Diff | references/structural-diff.md | Yes |
41
+ | 4 | Semantic Diff | references/semantic-diff.md | Yes (skip at non-Deep) |
42
+ | 5 | Severity Classification | references/severity-classify.md | Yes |
43
+ | 6 | Report | references/report.md | Yes |
44
+ | 7 | Workflow Health Check | references/health-check.md | Yes |
40
45
 
41
46
  ## Invocation Contract
42
47
 
43
48
  | Aspect | Detail |
44
49
  |--------|--------|
45
- | **Inputs** | skill_name [required] |
46
- | **Gates** | step-01: Confirm Gate [C] |
47
- | **Outputs** | drift-report-{timestamp}.md with drift_score and nextWorkflow |
48
- | **Headless** | All gates auto-resolve with default action when `{headless_mode}` is true |
50
+ | **Inputs** | `skill_name` [required], `skill_path` [optional override — full path to skill directory; bypasses manifest/symlink resolution], `tier_override` [optional: Quick / Forge / Forge+ / Deep — overrides detected tier], `degraded` [optional bool — pre-confirm degraded-mode opt-in when no provenance map exists], `upstream_drift_choice` [optional: C / S / X — pre-supplied answer for the upstream-drift gate at init.md §5b], `dirty_worktree_choice` [optional: T / A / F — pre-supplied answer for the dirty-worktree sub-gate at init.md §5b], `force` [optional bool — when paired with `dirty_worktree_choice=F` or used for any future destructive-action gate, signals consent to skip the confirmation] |
51
+ | **Gates** | step 1: Manifest-vs-Symlink Gate [N] · Upstream-Drift Gate [C/S/X] · Dirty-Worktree Sub-Gate [T/A/F] · Degraded-Mode Gate [D/X] · Baseline Confirm Gate [C] |
52
+ | **Outputs** | `drift-report-{timestamp}.md` at `{forge_version}/` with `drift_score` and `nextWorkflow` frontmatter; per-run result contract at `{forge_version}/audit-skill-result-{timestamp}.json` plus `-latest.json` copy; final `SKF_AUDIT_RESULT_JSON` line on stdout when `{headless_mode}` is true |
53
+ | **Headless** | All gates auto-resolve with default action when `{headless_mode}` is true; pre-supplied inputs (`upstream_drift_choice`, `dirty_worktree_choice`, `degraded`, `tier_override`) consumed at the gates that would otherwise prompt |
54
+ | **Exit codes** | See "Exit Codes" below |
55
+
56
+ ## Exit Codes
57
+
58
+ Every HARD HALT in this workflow exits with a stable code so headless automators can branch on the failure class without grepping message text:
59
+
60
+ | Code | Meaning | Raised by |
61
+ | ---- | -------------------- | ------------------------------------------------------------------------------------------------------------------ |
62
+ | 0 | success | step 7 (terminal health-check) |
63
+ | 2 | input-missing | step 1 §1 — no `skill_name` supplied in headless mode (interactive prompt cannot resolve) |
64
+ | 3 | resolution-failure | step 1 §1 (skill not found at resolved path: missing `SKILL.md`); step 1 §2 (`forge-tier.yaml` missing — setup-forge not run); step 1 §5 (source directory from provenance map no longer exists / inaccessible) |
65
+ | 4 | write-failure | step 1 §6 / step 6 §3 (drift report write failed: read-only mount, disk full, permissions denied) |
66
+ | 6 | user-cancelled | step 1 §1 manifest-vs-symlink gate `[X]` · step 1 §4 degraded-mode gate `[X]` · step 1 §5b upstream-drift gate `[X]` · step 1 §5b dirty-worktree sub-gate `[A]` (and `[A]` headless default) |
67
+
68
+ ## Result Contract (Headless)
69
+
70
+ 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"`:
71
+
72
+ ```
73
+ 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}
74
+ ```
75
+
76
+ `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.
49
77
 
50
78
  ## On Activation
51
79
 
@@ -56,4 +84,27 @@ These rules apply to every step in this workflow:
56
84
 
57
85
  2. **Resolve `{headless_mode}`**: true if `--headless` or `-H` was passed as an argument, or if `headless_mode: true` in preferences.yaml. Default: false.
58
86
 
59
- 3. Load, read the full file, and then execute `./steps-c/step-01-init.md` to begin the workflow.
87
+ 3. **Resolve workflow customization.** Run:
88
+
89
+ ```bash
90
+ python3 {project-root}/_bmad/scripts/resolve_customization.py \
91
+ --skill {skill-root} --key workflow
92
+ ```
93
+
94
+ The script merges the three customization layers per `bmad-customize`'s structural merge rules (scalars override, arrays append):
95
+
96
+ - `{skill-root}/customize.toml` — bundled defaults
97
+ - `_bmad/custom/<skill-name>.toml` under `{project-root}` — team overrides (committed)
98
+ - `_bmad/custom/<skill-name>.user.toml` under `{project-root}` — personal overrides (gitignored)
99
+
100
+ If the script fails or is missing, fall back to reading `{skill-root}/customize.toml` directly — the bundled defaults are an empty string for each path scalar.
101
+
102
+ Apply the path-scalar fallback now so stage files don't have to repeat the conditional logic. For each of the scalars, if the merged value is empty or absent, use the bundled default:
103
+
104
+ - `{driftReportTemplatePath}` ← `workflow.drift_report_template_path` if non-empty, else `assets/drift-report-template.md`
105
+ - `{severityRulesPath}` ← `workflow.severity_rules_path` if non-empty, else `references/severity-rules.md`
106
+ - `{onCompleteCommand}` ← `workflow.on_complete` if non-empty, else empty (no-op — report.md skips the hook invocation entirely)
107
+
108
+ 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.
109
+
110
+ 4. Load, read the full file, and then execute `references/init.md` to begin the workflow.
@@ -17,6 +17,7 @@ previousWorkflow: 'create-skill'
17
17
 
18
18
  ## Audit Summary
19
19
 
20
+ **Confidence Mode:** {confidence_mode}
20
21
  **Skill:** {skill_name}
21
22
  **Source:** {source_path}
22
23
  **Tier:** {forge_tier}
@@ -35,28 +36,28 @@ previousWorkflow: 'create-skill'
35
36
 
36
37
  ## Structural Drift
37
38
 
38
- <!-- Appended by step-03-structural-diff -->
39
+ <!-- Appended by structural-diff -->
39
40
 
40
41
  ---
41
42
 
42
43
  ## Semantic Drift
43
44
 
44
- <!-- Appended by step-04-semantic-diff (Deep tier only) -->
45
+ <!-- Appended by semantic-diff (Deep tier only) -->
45
46
 
46
47
  ---
47
48
 
48
49
  ## Severity Classification
49
50
 
50
- <!-- Appended by step-05-severity-classify -->
51
+ <!-- Appended by severity-classify -->
51
52
 
52
53
  ---
53
54
 
54
55
  ## Remediation Suggestions
55
56
 
56
- <!-- Appended by step-06-report -->
57
+ <!-- Appended by report -->
57
58
 
58
59
  ---
59
60
 
60
61
  ## Provenance
61
62
 
62
- <!-- Appended by step-06-report -->
63
+ <!-- Appended by report -->
@@ -0,0 +1,49 @@
1
+ # DO NOT EDIT -- overwritten on every update.
2
+ #
3
+ # Workflow customization surface for skf-audit-skill.
4
+
5
+ [workflow]
6
+
7
+ # --- Configurable below. Overrides merge per BMad structural rules: ---
8
+ # scalars: override wins • arrays (persistent_facts, activation_steps_*): append
9
+ # arrays-of-tables with `code`/`id`: replace matching items, append new ones.
10
+
11
+ # Steps to run before the standard activation (uv probe, config load).
12
+ # Overrides append. Use for org-wide pre-flight checks (auth, network,
13
+ # compliance) that must precede any audit work.
14
+
15
+ activation_steps_prepend = []
16
+
17
+ # Steps to run after activation but before the first stage executes.
18
+ # Overrides append. Use for context loads or banner customization that
19
+ # should run once activation completes successfully.
20
+
21
+ activation_steps_append = []
22
+
23
+ # Persistent facts the workflow keeps in mind for the whole run
24
+ # (house style, severity-threshold policies, audit guardrails).
25
+ # Overrides append.
26
+ #
27
+ # Each entry is either:
28
+ # - a literal sentence, e.g. "Critical drift requires CODEOWNERS notification."
29
+ # - a file reference prefixed with `file:`, e.g.
30
+ # "file:{project-root}/docs/audit-policy.md" (globs supported; file
31
+ # contents are loaded and treated as facts).
32
+
33
+ persistent_facts = [
34
+ "file:{project-root}/**/project-context.md",
35
+ ]
36
+
37
+ # --- Optional asset overrides ---
38
+ #
39
+ # Lift the canonical asset paths so orgs can substitute house-style copies
40
+ # without forking the skill. Empty string = use the bundled default.
41
+
42
+ drift_report_template_path = ""
43
+ severity_rules_path = ""
44
+
45
+ # Optional post-audit hook. When non-empty, invoked with
46
+ # `--result-path=<path>` after the drift report and result JSON are finalized.
47
+ # Failures are logged to workflow_warnings[] but never fail the workflow.
48
+
49
+ on_complete = ""
@@ -1,10 +1,12 @@
1
1
  ---
2
2
  # `shared/health-check.md` resolves relative to the SKF module root
3
- # (`_bmad/skf/` when installed, `src/` during development), NOT relative
4
- # to this step file.
3
+ # (`{project-root}/_bmad/skf/` when installed, `{project-root}/src/` during
4
+ # development), NOT relative to this step file.
5
5
  nextStepFile: 'shared/health-check.md'
6
6
  ---
7
7
 
8
+ <!-- Config: communicate in {communication_language}. -->
9
+
8
10
  # Step 7: Workflow Health Check
9
11
 
10
12
  ## STEP GOAL:
@@ -13,7 +15,7 @@ Chain to the shared workflow self-improvement health check at `{nextStepFile}`.
13
15
 
14
16
  ## Rules
15
17
 
16
- - No user-facing reports, file writes, or result contracts in this step — those belong in step-06
18
+ - No user-facing reports, file writes, or result contracts in this step — those belong in step 6
17
19
  - Delegate directly to `{nextStepFile}` with no additional commentary
18
20
  - Do not attempt any other action between loading this step and executing `{nextStepFile}`
19
21
 
@@ -1,9 +1,13 @@
1
1
  ---
2
- nextStepFile: './step-02-re-index.md'
2
+ nextStepFile: 're-index.md'
3
3
  outputFile: '{forge_version}/drift-report-{timestamp}.md'
4
4
  templateFile: 'assets/drift-report-template.md'
5
+ loadProvenanceScript: '{project-root}/src/shared/scripts/skf-load-provenance.py'
6
+ compareFileHashesScript: '{project-root}/src/shared/scripts/skf-compare-file-hashes.py'
5
7
  ---
6
8
 
9
+ <!-- Config: communicate in {communication_language}. -->
10
+
7
11
  # Step 1: Initialize Audit
8
12
 
9
13
  ## STEP GOAL:
@@ -19,7 +23,7 @@ Load the existing skill artifacts, provenance map, and forge tier configuration
19
23
 
20
24
  ## MANDATORY SEQUENCE
21
25
 
22
- **CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise unless user explicitly requests a change.
26
+ **Initialize workflow context defaults.** Before entering §1, set `confidence_mode = "normal"` as the default. §4 may upgrade this to `"degraded — all findings T1-low"` if the operator opts into degraded mode. Downstream steps (report.md, drift-report-template.md) consume this variable directly no conditional at the usage site.
23
27
 
24
28
  ### 1. Get Skill Path
25
29
 
@@ -53,7 +57,7 @@ Which skill would you like to audit? Please provide the skill name or path."
53
57
 
54
58
  3. If not in manifest: check for `active` symlink at `{skills_output_folder}/{skill_name}/active` — resolve to `{skill_group}/active/{skill_name}/`
55
59
  4. If neither: fall back to flat path `{skills_output_folder}/{skill_name}/`. If SKILL.md exists at the flat path, auto-migrate per `knowledge/version-paths.md` migration rules
56
- 5. Store the resolved path as `{resolved_skill_package}`. Also store `audit_target_version` = the version that was actually selected (manifest, symlink, or flat) for step-06 Provenance to surface. When the gate above fired, also record the rejected version under `manifest_symlink_drift = {manifest: {active_version}, symlink: {symlink_target}, audited: {audit_target_version}, reason: {fresher-provenance|operator-choice|headless-default}}` so reviewers can audit the choice.
60
+ 5. Store the resolved path as `{resolved_skill_package}`. Also store `audit_target_version` = the version that was actually selected (manifest, symlink, or flat) for step 6 Provenance to surface. When the gate above fired, also record the rejected version under `manifest_symlink_drift = {manifest: {active_version}, symlink: {symlink_target}, audited: {audit_target_version}, reason: {fresher-provenance|operator-choice|headless-default}}` so reviewers can audit the choice.
57
61
 
58
62
  **If user provides full path:**
59
63
  - Use as provided
@@ -88,29 +92,38 @@ Load the following from the skill directory:
88
92
  - `name`, `version`, `generation_date`, `confidence_tier` used during creation
89
93
  - `source_root` — Resolved source code path used during extraction
90
94
 
91
- **Detect split-body state:** If a `references/` directory exists and SKILL.md's `## Full` headings are absent or stubs, this is a split-body skill. Flag `split_body: true` in the baseline so downstream steps (especially semantic diff in step-04) know to also read `references/*.md` for complete content comparison.
95
+ **Detect split-body state:** If a `references/` directory exists and SKILL.md's `## Full` headings are absent or stubs, this is a split-body skill. Flag `split_body: true` in the baseline so downstream steps (especially semantic diff in step 4) know to also read `references/*.md` for complete content comparison.
92
96
 
93
97
  ### 4. Load Provenance Map
94
98
 
95
99
  Search for provenance map at `{forge_data_folder}/{skill_name}/{active_version}/provenance-map.json` (i.e., `{forge_version}/provenance-map.json`). If not found at the versioned path, fall back to `{forge_data_folder}/{skill_name}/provenance-map.json`:
96
100
 
97
101
  **If found:**
98
- - Load and extract: export list, file mappings, extraction timestamps, confidence tiers
99
- - Record provenance map age (days since last extraction)
102
+ - Record provenance map age (days since last extraction) from file mtime
103
+ - Normalize the map's deterministic projections in one subprocess call:
104
+
105
+ ```bash
106
+ uv run {loadProvenanceScript} normalize {provenanceMap}
107
+ ```
108
+
109
+ Parse the emitted JSON and stash these fields in workflow context (downstream steps read them directly — no re-walk):
110
+ - `{bounded_scan_files}` — sorted POSIX list, union of `entries[].source_file` and `file_entries[].source_file`. Step 2 `re-index.md` consumes this as the bounded scan list.
111
+ - `{is_stack_skill}`, `{legacy_stack_provenance}` — stack-skill flags (see Stack Skill Detection below for downstream branching).
112
+ - `{source_root}`, `{baseline_commit}`, `{baseline_ref}` — used by §5 Resolve Source Path and §5b Detect Upstream Drift.
113
+ - `{reexport_map}` — `{<internal>: <public>}` mapping consumed by `structural-diff.md` §1 to collapse public-API renames before diffing.
114
+
115
+ If the script exits non-zero, surface the stderr as a HARD HALT — the map is structurally invalid and downstream steps cannot proceed.
100
116
 
101
117
  **If missing at both paths:**
102
118
  - "No provenance map found for `{skill_name}`. This skill may not have been created by create-skill."
103
119
  - "**Degraded mode available:** I can perform text-based comparison without provenance data. Findings will have T1-low confidence."
104
120
  - "**[D]egraded mode** — proceed with text-diff only"
105
121
  - "**[X]** — abort audit"
106
- - Wait for user selection. If D, set `degraded_mode: true`. If X, halt workflow.
122
+ - 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.
107
123
 
108
124
  ### Stack Skill Detection
109
125
 
110
- After loading provenance-map.json, detect skill type:
111
- - If `provenance_version` is `"2.0"` and `skill_type` is `"stack"`: set `{is_stack_skill}` = true
112
- - If provenance-map has top-level `libraries` key (v1 stack format): set `{is_stack_skill}` = true, `{legacy_stack_provenance}` = true
113
- - Otherwise: `{is_stack_skill}` = false
126
+ `{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:
114
127
 
115
128
  If `{is_stack_skill}` is true and `constituents` array is present (compose-mode stack):
116
129
  - For each constituent, compute the current metadata hash: read `{constituent.skill_path}/active/{constituent.skill_name}/metadata.json` and compute SHA-256
@@ -123,10 +136,9 @@ If `{legacy_stack_provenance}` is true: log a note that this stack uses v1 prove
123
136
  ### 5. Resolve Source Path
124
137
 
125
138
  **If provenance map loaded:**
126
- - Use `source_root` from provenance map as source code path
139
+ - Use `{source_root}` (already extracted by §4 normalize) as source code path
127
140
  - Verify source path still exists and is accessible
128
- - Extract `baseline_commit` = `provenance-map.source_commit` (fall back to `metadata.source_commit` if absent from the provenance map)
129
- - Extract `baseline_ref` = `metadata.source_ref` (may be a tag, branch, `HEAD`, or `"local"`)
141
+ - `{baseline_commit}` and `{baseline_ref}` are already populated by §4. If `{baseline_commit}` is null in the projection, fall back to `metadata.source_commit`. `{baseline_ref}` may be a tag, branch, `HEAD`, or `"local"`.
130
142
 
131
143
  **If degraded mode:**
132
144
  - Ask user: "Please provide the path to the current source code."
@@ -144,7 +156,7 @@ Upstream drift detection is the primary use case of this workflow. If the local
144
156
  - `baseline_commit` is unavailable
145
157
  - Degraded mode is active (no provenance map)
146
158
 
147
- When skipping, log the reason, then set the audit-ref context variables to baseline values so step-06 renders a coherent Provenance row: `audit_ref = baseline_ref or "(unknown)"`, `audit_ref_source = "baseline"` (or `"unavailable"` if both `baseline_ref` and `baseline_commit` are unset), `audit_commit = baseline_commit or "(unknown)"`, `latest_tag = null`, `remote_head = null`. Continue to §6.
159
+ When skipping, log the reason, then set the audit-ref context variables to baseline values so step 6 renders a coherent Provenance row: `audit_ref = baseline_ref or "(unknown)"`, `audit_ref_source = "baseline"` (or `"unavailable"` if both `baseline_ref` and `baseline_commit` are unset), `audit_commit = baseline_commit or "(unknown)"`, `latest_tag = null`, `remote_head = null`. Continue to §6.
148
160
 
149
161
  **Otherwise:**
150
162
 
@@ -198,16 +210,16 @@ When skipping, log the reason, then set the audit-ref context variables to basel
198
210
  - **[F] Force checkout** — `git checkout --force` discards uncommitted changes irrecoverably. Only choose this after confirming the changes are safe to lose."
199
211
 
200
212
  **Gate handling:**
201
- - **[T]:** Run `git -C {source_root} stash push -m 'skf-audit-skill: pre-checkout {chosen_ref}' --include-untracked`. Capture the stash ref from the command output (e.g. `stash@{0}`) and store as `pre_checkout_stash_ref` in workflow context for step-06 Provenance to surface. Proceed to the checkout. (After audit completes, the operator restores the stash with `git stash pop` — step-06 puts the literal command in the report as a workflow-level convention rather than per-author ad-hoc prose.)
213
+ - **[T]:** Run `git -C {source_root} stash push -m 'skf-audit-skill: pre-checkout {chosen_ref}' --include-untracked`. Capture the stash ref from the command output (e.g. `stash@{0}`) and store as `pre_checkout_stash_ref` in workflow context for step 6 Provenance to surface. Proceed to the checkout. (After audit completes, the operator restores the stash with `git stash pop` — step 6 puts the literal command in the report as a workflow-level convention rather than per-author ad-hoc prose.)
202
214
  - **[A]:** HALT the workflow. Do not write a drift report — the audit was never started.
203
- - **[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-06 to surface as a loud warning. Skip the stash path.
215
+ - **[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.
204
216
  - **Other input:** help user, redisplay the sub-gate.
205
217
 
206
218
  **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.
207
219
 
208
220
  If `git status --porcelain` is empty, skip the sub-gate and proceed directly to the checkout.
209
221
 
210
- Then `git -C {source_root} checkout {chosen_ref}` (prefer `latest_tag` when present, else `remote_head`). Set `audit_ref = {chosen_ref}`, `audit_ref_source = "checkout-latest"`, `audit_commit = git rev-parse HEAD`. Hold the lock through step-02 re-extraction and release only after the extraction snapshot is complete.
222
+ Then `git -C {source_root} checkout {chosen_ref}` (prefer `latest_tag` when present, else `remote_head`). Set `audit_ref = {chosen_ref}`, `audit_ref_source = "checkout-latest"`, `audit_commit = git rev-parse HEAD`. Hold the lock through step 2 re-extraction and release only after the extraction snapshot is complete.
211
223
  - **[S]:** Keep baseline. Set `audit_ref = baseline_ref`, `audit_ref_source = "baseline"`, `audit_commit = baseline_commit`.
212
224
  - **[X]:** HALT workflow — do not create drift report.
213
225
  - **Other input:** help user, redisplay gate.
@@ -218,10 +230,36 @@ When skipping, log the reason, then set the audit-ref context variables to basel
218
230
 
219
231
  ### 6. Create Drift Report
220
232
 
233
+ **Re-audit detection (before creating a fresh report).** Glob `{forge_version}/drift-report-*.md`. If one or more matches exist, identify the most recent one by file mtime (or by the `{timestamp}` segment in the filename when mtime is unreliable on the filesystem). If that report's age is `< 7 days` and its frontmatter `audit_ref` matches the current `{audit_ref}` (resolved in §5b), surface a soft gate before creating a fresh report:
234
+
235
+ "**Recent audit found:** `{prior_report_path}` (created {prior_timestamp}, audit_ref=`{audit_ref}`).
236
+
237
+ Options:
238
+ - **[F] Fresh audit** (recommended; default in headless) — start a new drift report at `{outputFile}` and ignore the prior run.
239
+ - **[D] Diff against prior report** — compute findings delta vs the prior report and emit a `## Diff Against Prior Report` subsection in step 6 (report.md).
240
+ - **[R] Resume the prior report** — load the prior report's frontmatter (`stepsCompleted`, `drift_score`, intermediate findings) and jump to the next un-completed step instead of starting over.
241
+
242
+ **Select:** [F] / [D] / [R]"
243
+
244
+ **Gate handling:**
245
+ - **[F]:** Default. Proceed with the fresh-report creation below — ignore the prior report.
246
+ - **[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`.
247
+ - **[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.
248
+
249
+ > **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. **TODO:** if resumability proves unreliable in practice, extend the report frontmatter to carry an explicit `intermediate_findings` block (out of scope for this PR).
250
+
251
+ - **Other input:** help user, redisplay the gate.
252
+
253
+ **Headless default** (when `{headless_mode}`): auto-select **[F]** and emit a loud log line: `"headless: recent audit found at {prior_report_path}; defaulting to fresh audit. Re-run interactively to choose [D]/[R]."`
254
+
255
+ **Skip this gate** if no prior report matches the `< 7 days + same audit_ref` filter — proceed directly to creating the fresh report.
256
+
257
+ **Create the fresh report** (when [F] is selected, headless default fires, or no prior report exists):
258
+
221
259
  Create `{outputFile}` from `{templateFile}`:
222
260
 
223
261
  - Populate frontmatter: skill_name, skill_path, source_path, forge_tier, date, user_name
224
- - Set `stepsCompleted: ['step-01-init']`
262
+ - Set `stepsCompleted: ['init']`
225
263
  - Fill Audit Summary skeleton with loaded baseline data
226
264
 
227
265
  ### 7. Present Baseline Summary (User Gate)
@@ -1,8 +1,10 @@
1
1
  ---
2
- nextStepFile: './step-03-structural-diff.md'
2
+ nextStepFile: 'structural-diff.md'
3
3
  outputFile: '{forge_version}/drift-report-{timestamp}.md'
4
4
  ---
5
5
 
6
+ <!-- Config: communicate in {communication_language}. -->
7
+
6
8
  # Step 2: Re-Index Source
7
9
 
8
10
  ## STEP GOAL:
@@ -17,8 +19,6 @@ Re-scan the source code using the current forge tier tools to build a fresh extr
17
19
 
18
20
  ## MANDATORY SEQUENCE
19
21
 
20
- **CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise unless user explicitly requests a change.
21
-
22
22
  ### 1. Determine Extraction Strategy
23
23
 
24
24
  Based on forge tier detected in Step 01:
@@ -47,23 +47,23 @@ Based on forge tier detected in Step 01:
47
47
 
48
48
  ### 2. Build Bounded Scan List
49
49
 
50
- Audit-skill detects drift on files that were in scope during create-skill. The authoritative record of "what was in scope" is the provenance map loaded in step-01. Scan only those files — **audit-skill does NOT discover new files**. New-file detection is the responsibility of `skf-update-skill`, which maintains its own change manifest. To audit a project that has grown new files since creation, run update-skill first, then audit-skill.
50
+ Audit-skill detects drift on files that were in scope during create-skill. The authoritative record of "what was in scope" is the provenance map loaded in step 1. Scan only those files — **audit-skill does NOT discover new files**. New-file detection is the responsibility of `skf-update-skill`, which maintains its own change manifest. To audit a project that has grown new files since creation, run update-skill first, then audit-skill.
51
51
 
52
- **Why bounded:** without this constraint, files that were deliberately excluded by the original brief's scope patterns (test fixtures, vendored code, generated artifacts, demo code, unrelated modules) get scanned on every audit and their exports are flagged by step-03 structural diff as "added" — false-positive drift that obscures real structural changes.
52
+ **Why bounded:** without this constraint, files that were deliberately excluded by the original brief's scope patterns (test fixtures, vendored code, generated artifacts, demo code, unrelated modules) get scanned on every audit and their exports are flagged by step 3 structural diff as "added" — false-positive drift that obscures real structural changes.
53
53
 
54
- **If a provenance map was loaded in step-01** (normal mode):
54
+ **If a provenance map was loaded in step 1** (normal mode):
55
55
 
56
56
  1. Extract the unique set of file paths from the provenance map:
57
57
  - `entries[].source_file` (one path per extracted export)
58
58
  - `file_entries[].source_file` (one path per tracked script/asset, when present)
59
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-03 can classify them as DELETED. Handling missing files is step-03's job, not step-02's.
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
61
  4. Record `bounded_scan: true` and `bounded_scan_source: "provenance-map"` in context for the evidence report.
62
62
  5. Report:
63
63
 
64
64
  "**Bounded scan:** {count} files from provenance map ({provenance_date})."
65
65
 
66
- **If degraded mode** (no provenance map was loaded — user confirmed `[D]egraded mode` at step-01 §4):
66
+ **If degraded mode** (no provenance map was loaded — user confirmed `[D]egraded mode` at step 1 §4):
67
67
 
68
68
  1. Fall back to a source-tree scan: list all source files under `{source_root}` matching the project's primary language extensions (derive from `metadata.json.language` — e.g., `*.ts` / `*.tsx` for typescript, `*.py` for python, `*.rs` for rust, `*.go` for go).
69
69
  2. Apply generic exclusions: `**/tests/**`, `**/test/**`, `**/__tests__/**`, `*.test.*`, `*.spec.*`, `node_modules/**`, `dist/**`, `build/**`, `target/**`, `__pycache__/**`, `.venv/**`, `vendor/**`.
@@ -82,7 +82,7 @@ Audit-skill detects drift on files that were in scope during create-skill. The a
82
82
  3. Records: export name, type, signature, file path, line number, confidence tier
83
83
  4. Returns structured findings to parent
84
84
 
85
- **If a file from the bounded scan list is missing on disk:** record `{file, exports: [], status: "missing"}` and continue — step-03 structural diff will classify exports previously at this path as DELETED.
85
+ **If a file from the bounded scan list is missing on disk:** record `{file, exports: [], status: "missing"}` and continue — step 3 structural diff will classify exports previously at this path as DELETED.
86
86
 
87
87
  **If subprocess unavailable:** Perform extraction in main thread, processing each file sequentially.
88
88
 
@@ -116,7 +116,7 @@ Read the `qmd_collections` registry from `{sidecar_path}/forge-tier.yaml`.
116
116
 
117
117
  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
118
 
119
- Three collection states must be handled distinctly (same branching as step-04 §2 — keep them in sync):
119
+ Three collection states must be handled distinctly (same branching as step 4 §2 — keep them in sync):
120
120
 
121
121
  **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
122
  Query qmd_bridge against the `{skill_name}-extraction` collection for temporal context on each extracted export:
@@ -175,7 +175,7 @@ CCC failures: skip rename detection silently, proceed with standard structural d
175
175
  ### 6. Update Report and Auto-Proceed
176
176
 
177
177
  Update {outputFile} frontmatter:
178
- - Append `'step-02-re-index'` to `stepsCompleted`
178
+ - Append `'re-index'` to `stepsCompleted`
179
179
 
180
180
  ### 7. Present MENU OPTIONS
181
181