bmad-module-skill-forge 1.9.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (281) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.nvmrc +1 -1
  3. package/README.md +10 -5
  4. package/docs/_data/pinned.yaml +2 -2
  5. package/docs/agents.md +11 -2
  6. package/docs/architecture.md +5 -4
  7. package/docs/bmad-synergy.md +30 -7
  8. package/docs/campaign.md +172 -0
  9. package/docs/examples.md +7 -3
  10. package/docs/forge-auto.md +90 -0
  11. package/docs/getting-started.md +9 -0
  12. package/docs/how-it-works.md +6 -4
  13. package/docs/index.md +4 -3
  14. package/docs/skill-model.md +1 -1
  15. package/docs/troubleshooting.md +17 -1
  16. package/docs/verifying-a-skill.md +2 -2
  17. package/docs/why-skf.md +1 -1
  18. package/docs/workflows.md +64 -24
  19. package/package.json +2 -2
  20. package/src/knowledge/skill-lifecycle.md +1 -1
  21. package/src/module-help.csv +4 -3
  22. package/src/shared/data/language-corpora.json +32 -0
  23. package/src/shared/references/pipeline-contracts.md +6 -3
  24. package/src/shared/scripts/schemas/skill-brief.v1.json +6 -1
  25. package/src/shared/scripts/skf-comention-pairs.py +350 -0
  26. package/src/shared/scripts/skf-count-tokens.py +222 -0
  27. package/src/shared/scripts/skf-derive-assembly-shape.py +107 -0
  28. package/src/shared/scripts/skf-detect-docs.py +240 -4
  29. package/src/shared/scripts/skf-detect-language.py +82 -3
  30. package/src/shared/scripts/skf-detect-tools.py +105 -2
  31. package/src/shared/scripts/skf-emit-result-envelope.py +17 -0
  32. package/src/shared/scripts/skf-enumerate-stack-skills.py +111 -2
  33. package/src/shared/scripts/skf-extract-public-api.py +53 -0
  34. package/src/shared/scripts/skf-find-cycles.py +246 -0
  35. package/src/shared/scripts/skf-hash-content.py +487 -2
  36. package/src/shared/scripts/skf-language-corpora.py +100 -0
  37. package/src/shared/scripts/skf-manifest-ops.py +67 -1
  38. package/src/shared/scripts/skf-merge-doc-urls.py +244 -0
  39. package/src/shared/scripts/skf-preapply.py +1 -1
  40. package/src/shared/scripts/skf-rebuild-managed-sections.py +180 -0
  41. package/src/shared/scripts/skf-recommend-scope-type.py +1 -2
  42. package/src/shared/scripts/skf-render-metadata-stats.py +499 -0
  43. package/src/shared/scripts/skf-rewrite-skill-name.py +308 -0
  44. package/src/shared/scripts/skf-shape-detect.py +576 -25
  45. package/src/shared/scripts/skf-shard-body.py +461 -0
  46. package/src/shared/scripts/skf-skill-inventory.py +139 -3
  47. package/src/shared/scripts/skf-structural-diff.py +307 -67
  48. package/src/shared/scripts/skf-validate-brief-schema.py +41 -6
  49. package/src/shared/scripts/skf-validate-feasibility-report.py +234 -0
  50. package/src/shared/scripts/skf-validate-frontmatter.py +17 -12
  51. package/src/shared/scripts/skf-validate-output.py +443 -10
  52. package/src/shared/scripts/skf-validate-pins.py +3 -3
  53. package/src/shared/scripts/skf-verify-no-trace.py +214 -0
  54. package/src/shared/scripts/skf-verify-provenance-completeness.py +439 -0
  55. package/src/shared/scripts/skf-write-skill-brief.py +21 -5
  56. package/src/skf-analyze-source/SKILL.md +17 -32
  57. package/src/skf-analyze-source/assets/skill-brief-schema.md +1 -1
  58. package/src/skf-analyze-source/customize.toml +2 -0
  59. package/src/skf-analyze-source/references/auto-docs-only.md +116 -0
  60. package/src/skf-analyze-source/references/continue.md +8 -13
  61. package/src/skf-analyze-source/references/generate-briefs.md +28 -12
  62. package/src/skf-analyze-source/references/headless-contract.md +33 -0
  63. package/src/skf-analyze-source/references/health-check.md +1 -2
  64. package/src/skf-analyze-source/references/identify-units.md +25 -36
  65. package/src/skf-analyze-source/references/init.md +12 -25
  66. package/src/skf-analyze-source/references/map-and-detect.md +8 -20
  67. package/src/skf-analyze-source/references/recommend.md +4 -14
  68. package/src/skf-analyze-source/references/scan-project.md +3 -11
  69. package/src/skf-analyze-source/references/step-auto-scope.md +211 -197
  70. package/src/skf-analyze-source/references/step-shape-detect.md +20 -13
  71. package/src/skf-analyze-source/references/unit-detection-heuristics.md +2 -2
  72. package/src/skf-audit-skill/SKILL.md +9 -6
  73. package/src/skf-audit-skill/customize.toml +2 -0
  74. package/src/skf-audit-skill/references/init.md +58 -32
  75. package/src/skf-audit-skill/references/re-index.md +15 -34
  76. package/src/skf-audit-skill/references/report.md +11 -58
  77. package/src/skf-audit-skill/references/semantic-diff.md +4 -22
  78. package/src/skf-audit-skill/references/severity-classify.md +53 -87
  79. package/src/skf-audit-skill/references/step-doc-drift.md +49 -19
  80. package/src/skf-audit-skill/references/structural-diff.md +43 -68
  81. package/src/skf-brief-skill/SKILL.md +7 -36
  82. package/src/skf-brief-skill/assets/scope-templates.md +1 -1
  83. package/src/skf-brief-skill/assets/skill-brief-schema.md +1 -1
  84. package/src/skf-brief-skill/customize.toml +14 -0
  85. package/src/skf-brief-skill/references/analyze-target.md +13 -18
  86. package/src/skf-brief-skill/references/confirm-brief.md +2 -15
  87. package/src/skf-brief-skill/references/draft-checkpoint.md +8 -8
  88. package/src/skf-brief-skill/references/gather-intent.md +27 -24
  89. package/src/skf-brief-skill/references/headless-args.md +1 -1
  90. package/src/skf-brief-skill/references/health-check.md +1 -22
  91. package/src/skf-brief-skill/references/invocation-contract.md +37 -0
  92. package/src/skf-brief-skill/references/scope-definition.md +6 -15
  93. package/src/skf-brief-skill/references/step-auto-brief.md +22 -9
  94. package/src/skf-brief-skill/references/step-auto-validate.md +3 -7
  95. package/src/skf-brief-skill/references/version-resolution.md +1 -1
  96. package/src/skf-brief-skill/references/write-brief.md +19 -13
  97. package/src/skf-campaign/SKILL.md +121 -0
  98. package/src/skf-campaign/assets/campaign-state-schema.json +191 -0
  99. package/src/skf-campaign/customize.toml +75 -0
  100. package/src/skf-campaign/manifest.yaml +15 -0
  101. package/src/skf-campaign/references/campaign-contracts.md +67 -0
  102. package/src/skf-campaign/references/campaign-directive-spec.md +32 -0
  103. package/src/skf-campaign/references/health-check.md +35 -0
  104. package/src/skf-campaign/references/step-01-setup.md +121 -0
  105. package/src/skf-campaign/references/step-02-strategy.md +102 -0
  106. package/src/skf-campaign/references/step-03-pins.md +56 -0
  107. package/src/skf-campaign/references/step-04-provenance.md +63 -0
  108. package/src/skf-campaign/references/step-05-skill-loop.md +103 -0
  109. package/src/skf-campaign/references/step-06-batch.md +88 -0
  110. package/src/skf-campaign/references/step-07-capstone.md +63 -0
  111. package/src/skf-campaign/references/step-08-verify.md +75 -0
  112. package/src/skf-campaign/references/step-09-refine.md +83 -0
  113. package/src/skf-campaign/references/step-10-export.md +106 -0
  114. package/src/skf-campaign/references/step-11-maintenance.md +84 -0
  115. package/src/skf-campaign/references/step-resume.md +115 -0
  116. package/src/skf-campaign/scripts/.gitkeep +0 -0
  117. package/src/skf-campaign/scripts/campaign-deps.py +244 -0
  118. package/src/skf-campaign/scripts/campaign-parse-manifest.py +119 -0
  119. package/src/skf-campaign/scripts/campaign-provenance.py +247 -0
  120. package/src/skf-campaign/scripts/campaign-render-batch.py +199 -0
  121. package/src/skf-campaign/scripts/campaign-render-kickoff.py +158 -0
  122. package/src/skf-campaign/scripts/campaign-report.py +249 -0
  123. package/src/skf-campaign/scripts/campaign-status.py +162 -0
  124. package/src/skf-campaign/scripts/campaign-validate-pins.py +174 -0
  125. package/src/skf-campaign/scripts/campaign-validate-state.py +207 -0
  126. package/src/skf-campaign/templates/campaign-brief-template.yaml +34 -0
  127. package/src/skf-campaign/templates/campaign-report-template.md +54 -0
  128. package/src/skf-campaign/templates/kickoff-template.md +48 -0
  129. package/src/skf-create-skill/SKILL.md +15 -4
  130. package/src/skf-create-skill/assets/compile-assembly-rules.md +35 -34
  131. package/src/skf-create-skill/assets/skill-sections.md +9 -100
  132. package/src/skf-create-skill/assets/tessl-dismissal-rules.md +4 -13
  133. package/src/skf-create-skill/customize.toml +13 -0
  134. package/src/skf-create-skill/references/authoritative-files-protocol.md +7 -7
  135. package/src/skf-create-skill/references/compile.md +37 -47
  136. package/src/skf-create-skill/references/component-extraction.md +8 -35
  137. package/src/skf-create-skill/references/ecosystem-check.md +9 -25
  138. package/src/skf-create-skill/references/enrich.md +4 -17
  139. package/src/skf-create-skill/references/extract.md +20 -27
  140. package/src/skf-create-skill/references/extraction-patterns-tracing.md +1 -1
  141. package/src/skf-create-skill/references/extraction-patterns.md +10 -8
  142. package/src/skf-create-skill/references/generate-artifacts.md +20 -25
  143. package/src/skf-create-skill/references/health-check.md +2 -2
  144. package/src/skf-create-skill/references/load-brief.md +16 -18
  145. package/src/skf-create-skill/references/report.md +27 -14
  146. package/src/skf-create-skill/references/source-resolution-protocols.md +4 -4
  147. package/src/skf-create-skill/references/step-auto-shard.md +52 -25
  148. package/src/skf-create-skill/references/step-doc-rot.md +33 -15
  149. package/src/skf-create-skill/references/step-doc-sources.md +13 -4
  150. package/src/skf-create-skill/references/sub/ccc-discover.md +2 -13
  151. package/src/skf-create-skill/references/sub/fetch-docs.md +33 -46
  152. package/src/skf-create-skill/references/sub/fetch-temporal.md +5 -20
  153. package/src/skf-create-skill/references/tier-degradation-rules.md +6 -8
  154. package/src/skf-create-skill/references/validate.md +69 -29
  155. package/src/skf-create-skill/scripts/scan-doc-rot.py +245 -0
  156. package/src/skf-create-stack-skill/SKILL.md +15 -9
  157. package/src/skf-create-stack-skill/assets/provenance-map-schema.md +1 -1
  158. package/src/skf-create-stack-skill/customize.toml +10 -0
  159. package/src/skf-create-stack-skill/references/compile-stack.md +7 -8
  160. package/src/skf-create-stack-skill/references/compose-mode-rules.md +2 -13
  161. package/src/skf-create-stack-skill/references/detect-integrations.md +49 -54
  162. package/src/skf-create-stack-skill/references/detect-manifests.md +37 -30
  163. package/src/skf-create-stack-skill/references/generate-output.md +24 -75
  164. package/src/skf-create-stack-skill/references/init.md +9 -81
  165. package/src/skf-create-stack-skill/references/manifest-patterns.md +5 -35
  166. package/src/skf-create-stack-skill/references/parallel-extract.md +12 -27
  167. package/src/skf-create-stack-skill/references/rank-and-confirm.md +6 -6
  168. package/src/skf-create-stack-skill/references/report.md +27 -62
  169. package/src/skf-create-stack-skill/references/validate.md +35 -31
  170. package/src/skf-drop-skill/SKILL.md +20 -23
  171. package/src/skf-drop-skill/customize.toml +10 -0
  172. package/src/skf-drop-skill/references/execute.md +67 -36
  173. package/src/skf-drop-skill/references/headless-contract.md +18 -0
  174. package/src/skf-drop-skill/references/health-check.md +1 -13
  175. package/src/skf-drop-skill/references/report.md +44 -10
  176. package/src/skf-drop-skill/references/select.md +93 -48
  177. package/src/skf-drop-skill/scripts/dir-sizes.py +116 -0
  178. package/src/skf-export-skill/SKILL.md +17 -14
  179. package/src/skf-export-skill/assets/managed-section-format.md +2 -5
  180. package/src/skf-export-skill/customize.toml +10 -6
  181. package/src/skf-export-skill/references/generate-snippet.md +21 -35
  182. package/src/skf-export-skill/references/load-skill.md +44 -42
  183. package/src/skf-export-skill/references/multi-skill-mode.md +1 -1
  184. package/src/skf-export-skill/references/orphan-context-detection.md +11 -3
  185. package/src/skf-export-skill/references/package.md +27 -33
  186. package/src/skf-export-skill/references/preflight-snippet-root-probe.md +24 -5
  187. package/src/skf-export-skill/references/result-envelope.md +28 -0
  188. package/src/skf-export-skill/references/summary.md +11 -5
  189. package/src/skf-export-skill/references/token-report.md +42 -24
  190. package/src/skf-export-skill/references/update-context.md +32 -33
  191. package/src/skf-forger/SKILL.md +32 -39
  192. package/src/skf-forger/references/pipeline-mode.md +34 -0
  193. package/src/skf-forger/scripts/parse-pipeline.py +270 -0
  194. package/src/skf-quick-skill/SKILL.md +10 -60
  195. package/src/skf-quick-skill/customize.toml +9 -0
  196. package/src/skf-quick-skill/references/batch-mode.md +6 -4
  197. package/src/skf-quick-skill/references/compile.md +15 -52
  198. package/src/skf-quick-skill/references/ecosystem-check.md +5 -20
  199. package/src/skf-quick-skill/references/finalize.md +12 -6
  200. package/src/skf-quick-skill/references/halt-contract.md +54 -0
  201. package/src/skf-quick-skill/references/health-check.md +3 -4
  202. package/src/skf-quick-skill/references/quick-extract.md +7 -18
  203. package/src/skf-quick-skill/references/registry-resolution.md +1 -23
  204. package/src/skf-quick-skill/references/resolve-target.md +27 -34
  205. package/src/skf-quick-skill/references/write-and-validate.md +10 -25
  206. package/src/skf-refine-architecture/SKILL.md +16 -8
  207. package/src/skf-refine-architecture/customize.toml +9 -0
  208. package/src/skf-refine-architecture/references/compile.md +10 -8
  209. package/src/skf-refine-architecture/references/gap-analysis.md +21 -50
  210. package/src/skf-refine-architecture/references/health-check.md +1 -1
  211. package/src/skf-refine-architecture/references/improvements.md +9 -25
  212. package/src/skf-refine-architecture/references/init.md +9 -16
  213. package/src/skf-refine-architecture/references/issue-detection.md +10 -25
  214. package/src/skf-refine-architecture/references/refinement-rules.md +4 -16
  215. package/src/skf-refine-architecture/references/report.md +14 -11
  216. package/src/skf-rename-skill/SKILL.md +11 -21
  217. package/src/skf-rename-skill/customize.toml +10 -0
  218. package/src/skf-rename-skill/references/execute.md +112 -82
  219. package/src/skf-rename-skill/references/exit-codes.md +12 -0
  220. package/src/skf-rename-skill/references/report.md +16 -8
  221. package/src/skf-rename-skill/references/select.md +69 -42
  222. package/src/skf-rename-skill/scripts/skf-validate-rename-name.py +161 -0
  223. package/src/skf-setup/SKILL.md +21 -13
  224. package/src/skf-setup/customize.toml +10 -0
  225. package/src/skf-setup/references/auto-index.md +11 -10
  226. package/src/skf-setup/references/ccc-index.md +14 -15
  227. package/src/skf-setup/references/detect-and-tier.md +10 -8
  228. package/src/skf-setup/references/report.md +26 -32
  229. package/src/skf-setup/references/tier-rules.md +2 -32
  230. package/src/skf-setup/references/write-config.md +9 -10
  231. package/src/skf-test-skill/SKILL.md +10 -8
  232. package/src/skf-test-skill/customize.toml +2 -0
  233. package/src/skf-test-skill/references/coherence-check.md +19 -31
  234. package/src/skf-test-skill/references/coverage-check.md +111 -67
  235. package/src/skf-test-skill/references/detect-mode.md +10 -41
  236. package/src/skf-test-skill/references/external-validators.md +11 -19
  237. package/src/skf-test-skill/references/init.md +39 -21
  238. package/src/skf-test-skill/references/migration-section-rules.md +4 -4
  239. package/src/skf-test-skill/references/report.md +60 -40
  240. package/src/skf-test-skill/references/score.md +32 -64
  241. package/src/skf-test-skill/references/scoring-rules.md +6 -62
  242. package/src/skf-test-skill/references/source-access-protocol.md +15 -5
  243. package/src/skf-test-skill/references/step-hard-gate.md +1 -3
  244. package/src/skf-test-skill/scripts/aggregate-coherence.py +276 -0
  245. package/src/skf-test-skill/scripts/check-metadata-coherence.py +359 -0
  246. package/src/skf-test-skill/scripts/combine-external-scores.py +190 -0
  247. package/src/skf-test-skill/scripts/compute-score.py +135 -4
  248. package/src/skf-test-skill/scripts/reconcile-coverage.py +327 -0
  249. package/src/skf-test-skill/scripts/validate-inventory.py +251 -0
  250. package/src/skf-test-skill/scripts/verify-declared-numerator.py +192 -0
  251. package/src/skf-update-skill/SKILL.md +17 -5
  252. package/src/skf-update-skill/customize.toml +11 -6
  253. package/src/skf-update-skill/references/detect-changes.md +48 -36
  254. package/src/skf-update-skill/references/health-check.md +5 -11
  255. package/src/skf-update-skill/references/init.md +40 -32
  256. package/src/skf-update-skill/references/manual-section-rules.md +1 -2
  257. package/src/skf-update-skill/references/merge-conflict-rules.md +1 -52
  258. package/src/skf-update-skill/references/merge.md +13 -57
  259. package/src/skf-update-skill/references/re-extract.md +27 -25
  260. package/src/skf-update-skill/references/report.md +14 -7
  261. package/src/skf-update-skill/references/validate.md +32 -30
  262. package/src/skf-update-skill/references/write.md +86 -51
  263. package/src/skf-update-skill/scripts/skf-new-file-diff.py +167 -0
  264. package/src/skf-verify-stack/SKILL.md +11 -21
  265. package/src/skf-verify-stack/customize.toml +12 -3
  266. package/src/skf-verify-stack/references/coverage-patterns.md +1 -29
  267. package/src/skf-verify-stack/references/coverage.md +21 -10
  268. package/src/skf-verify-stack/references/exit-codes.md +14 -0
  269. package/src/skf-verify-stack/references/health-check.md +1 -1
  270. package/src/skf-verify-stack/references/init.md +20 -25
  271. package/src/skf-verify-stack/references/integration-verification-rules.md +10 -19
  272. package/src/skf-verify-stack/references/integrations.md +44 -49
  273. package/src/skf-verify-stack/references/report.md +28 -34
  274. package/src/skf-verify-stack/references/requirements.md +3 -3
  275. package/src/skf-verify-stack/references/synthesize.md +36 -39
  276. package/src/skf-verify-stack/scripts/skf-coverage-tally.py +196 -0
  277. package/src/skf-verify-stack/scripts/skf-report-delta.py +256 -0
  278. package/src/skf-verify-stack/scripts/skf-verdict-rollup.py +258 -0
  279. package/tools/cli/lib/ui.js +3 -2
  280. package/docs/deepwiki.md +0 -89
  281. package/src/skf-rename-skill/references/rebuild-context.md +0 -110
@@ -1,12 +1,11 @@
1
1
  ---
2
2
  tierRulesData: 'references/tier-rules.md'
3
3
  nextStepFile: 'health-check.md'
4
- # Resolve `{emitEnvelopeHelper}` by probing `{emitEnvelopeProbeOrder}` in order
5
- # (installed SKF module path first, src/ dev-checkout fallback); first existing
6
- # path wins. HALT if neither resolves when the headless envelope must be emitted
7
- # the script is the source of truth for the SKF_SETUP_RESULT_JSON contract;
8
- # never inline-render the envelope from prose (LLM schema drift is the bug
9
- # this script exists to prevent).
4
+ # `{emitEnvelopeHelper}` = first existing path in `{emitEnvelopeProbeOrder}`;
5
+ # halt if neither exists when the headless envelope must be emitted. The script
6
+ # is the source of truth for the SKF_SETUP_RESULT_JSON contract do not
7
+ # inline-render the envelope from prose (LLM schema drift is the bug this
8
+ # script exists to prevent).
10
9
  emitEnvelopeProbeOrder:
11
10
  - '{project-root}/_bmad/skf/shared/scripts/skf-emit-result-envelope.py'
12
11
  - '{project-root}/src/shared/scripts/skf-emit-result-envelope.py'
@@ -27,19 +26,13 @@ Display the forge status report with positive capability framing, surface tier c
27
26
  - Do not list tools that are not available
28
27
  - Use tier capability descriptions from tier-rules.md
29
28
  - Never inline-render the envelope JSON — the script owns the schema; drift breaks pipelines
30
- - Chains to the local health-check step via `{nextStepFile}` after completion — the user-facing status report is NOT the terminal step
31
-
32
- ## Headless Mode Display Rule
33
-
34
- When `{headless_mode}` is `true` OR `{quiet_mode}` is `true`, sections 2 (the human-readable banner) and 3 (the REQUIRED TIER NOT MET human prose block) are **skipped entirely**. The single line of stdout in those modes is the `SKF_SETUP_RESULT_JSON: {…}` envelope from section 4 — every signal the human banner would have surfaced is already in the envelope (`tier`, `previous_tier`, `tier_changed`, `tools`, `tools_added`, `tools_removed`, `files_written`, `tier_override_*`, `require_tier_satisfied`, `warnings`, `error`). Parent skills, CI pipelines, and expert re-runners consume the envelope alone; they should not be forced to scroll past 30 lines of ASCII-art they cannot use.
35
-
36
- When both `{headless_mode}` and `{quiet_mode}` are `false`, sections 2 and 3 display normally and section 4 is skipped (interactive runs read the human banner; envelope emission would just be log noise).
29
+ - Chains to the local health-check step via `{nextStepFile}` after completion — the user-facing status report is not the terminal step
37
30
 
38
31
  ## MANDATORY SEQUENCE
39
32
 
40
33
  ### 1. Load Capability Descriptions
41
34
 
42
- Load and read {tierRulesData} for the tier capability descriptions and re-run messages. Needed by section 2; safe to load unconditionally — the data load itself is silent.
35
+ Load and read {tierRulesData} for the tier capability descriptions and re-run messages. Needed by section 2.
43
36
 
44
37
  ### 2. Display Forge Status Report (skip when `{headless_mode}` or `{quiet_mode}` is true)
45
38
 
@@ -54,7 +47,7 @@ Load and read {tierRulesData} for the tier capability descriptions and re-run me
54
47
  {tier capability description from tier-rules.md}
55
48
 
56
49
  Tools Detected:
57
- {for each tool that is available, show: tool name — version}
50
+ {for each tool that is available, show: tool name — version. ccc exposes no version string, so for ccc show its daemon health instead: ccc — daemon {ccc_daemon} (e.g. "ccc — daemon healthy")}
58
51
  {if no tools are available: (none yet — see "Climb to next tier" below)}
59
52
 
60
53
  {if calculated_tier is not Deep:}
@@ -64,7 +57,7 @@ Load and read {tierRulesData} for the tier capability descriptions and re-run me
64
57
  {if tools.ast_grep and not tools.gh_cli: - Install GitHub CLI (https://cli.github.com) — required for Deep tier (cross-repository synthesis)}
65
58
  {if tools.ast_grep and not tools.qmd and qmd_status is "absent": - Install qmd (https://github.com/tobi/qmd) — required for Deep tier (knowledge search)}
66
59
  {if tools.ast_grep and not tools.qmd and qmd_status is "daemon_stopped": - Start the qmd daemon (already installed) — run `qmd start` (or your distribution's qmd service command) to unlock Deep tier (knowledge search)}
67
- {if tools.ccc and ccc_daemon is "error": - The ccc daemon is reporting errors — run `ccc doctor` to diagnose. CCC index will fail until resolved (mirrors the qmd daemon-stopped pattern above for parity)}
60
+ {if tools.ccc and ccc_daemon is "error": - The ccc daemon is reporting errors — run `ccc doctor` to diagnose. CCC index will fail until resolved}
68
61
  {end if}
69
62
 
70
63
  {if hygiene_result is "completed":}
@@ -91,6 +84,7 @@ Load and read {tierRulesData} for the tier capability descriptions and re-run me
91
84
  CCC Index:
92
85
  {if ccc_index_result is "fresh": up to date — semantic discovery ready}
93
86
  {if ccc_index_result is "created": indexed this run — semantic discovery ready}
87
+ {if ccc_index_result is "skipped": skipped (--ccc-skip-index) — run `/skf-setup` without --ccc-skip-index to build the index when you're ready}
94
88
  {if ccc_index_result is "failed": indexing failed — semantic discovery unavailable this session}
95
89
  {end if}
96
90
 
@@ -121,13 +115,17 @@ Load and read {tierRulesData} for the tier capability descriptions and re-run me
121
115
  rely on the missing tool(s) will fail at runtime. Install the missing tool(s) or remove
122
116
  the override from preferences.yaml.
123
117
 
118
+ {if {previous_tier} is null:}
119
+ Initial detection — {calculated_tier} tier established.
120
+
124
121
  {if {tier_changed} is true:}
125
122
  {appropriate upgrade/downgrade message from tier-rules.md}
126
123
 
127
124
  {if {tier_changed} is false and {tools_added} is empty and {tools_removed} is empty and {previous_tier} is non-null:}
128
125
  {same-tier message from tier-rules.md}
126
+ {if preferences_yaml_created is false and (ccc_index_result is "fresh" or ccc_index_result is "none" or ccc_index_result is "skipped"): Nothing changed — your preferences were left untouched and the index was already current. You're good.}
129
127
 
130
- {if {tier_changed} is false and ({tools_added} or {tools_removed} is non-empty):}
128
+ {if {tier_changed} is false and ({tools_added} or {tools_removed} is non-empty) and {previous_tier} is non-null:}
131
129
  Tier unchanged: {calculated_tier}.
132
130
  {if {tools_added} non-empty:} Newly detected: {comma-separated tool names from tools_added}{if ccc was added and tier is Deep: " — ccc enhances Deep tier transparently."}
133
131
  {if {tools_removed} non-empty:} No longer detected: {comma-separated tool names from tools_removed} — re-install to restore those capabilities.
@@ -137,20 +135,14 @@ Load and read {tierRulesData} for the tier capability descriptions and re-run me
137
135
  ═══════════════════════════════════════
138
136
 
139
137
  {if {headless_mode} is false:}
140
- Next: try `/skf-brief-skill` to scope your first compilation target, or `/skf-quick-skill` for a fast template-driven path. Already have a skill? `/skf-audit-skill` drift-checks an existing skill against current sources.
138
+ Next: the fastest start is `@Ferris forge-auto <repo-or-doc-url>` — one command auto-scopes, briefs, compiles, tests at a 90% quality gate, and exports a verified skill with zero configuration. Prefer to scope by hand? `/skf-brief-skill` scopes your first compilation target, or `/skf-quick-skill` is a fast template-driven path. Already have a skill? `/skf-audit-skill` drift-checks an existing skill against current sources.
141
139
  ```
142
140
 
143
141
  All re-run-delta context flags (`{tools_added}`, `{tools_removed}`, `{tier_changed}`) come from the detector's `deltas` block bound in stage 1 — no LLM-side recomputation, no set arithmetic in prose.
144
142
 
145
- **Tool display rules:**
146
-
147
- - Only show tools that ARE available with their version strings
148
- - Do NOT list unavailable tools
149
- - Do NOT show a "missing" column or section
150
-
151
143
  ### 3. Display Required-Tier Failure Block (when applicable; skip when `{headless_mode}` or `{quiet_mode}` is true)
152
144
 
153
- If `{require_tier_satisfied}` is `false` AND both `{headless_mode}` and `{quiet_mode}` are `false`, display this block immediately after the status report. In headless or quiet modes the failure surfaces via the envelope's `require_tier_satisfied: false` and the synthesized `warnings` entry — the human prose block would be log noise.
145
+ If `{require_tier_satisfied}` is `false`, display this block immediately after the status report (the heading gate already handles the headless/quiet skip).
154
146
 
155
147
  When the block does fire (interactive run with require-tier failure):
156
148
 
@@ -168,11 +160,9 @@ When the block does fire (interactive run with require-tier failure):
168
160
  ═══════════════════════════════════════
169
161
  ```
170
162
 
171
- This block exists to make pipeline failures visible without the operator parsing the JSON envelope.
172
-
173
163
  ### 4. Emit Headless JSON Envelope
174
164
 
175
- When `{headless_mode}` is `true` OR `{quiet_mode}` is `true`, build the context payload from this step's accumulated flags and forward it to `{emitEnvelopeHelper}` on stdin. Invoke via `uv run` so the script's PEP 723 dependency declarations are honored (the canonical runtime invocation per `docs/getting-started.md`'s uv prereq — bare `python3` skips the metadata block and breaks on a fresh interpreter). The script computes derived fields (`tools_added`, `tools_removed`, `tier_changed`, `warnings`), validates the assembled envelope against the JSON Schema at `src/shared/scripts/schemas/skf-setup-result-envelope.v1.json`, and emits the single prefixed line `SKF_SETUP_RESULT_JSON: {…}` on stdout.
165
+ When `{headless_mode}` is `true` OR `{quiet_mode}` is `true`, build the context payload from this step's accumulated flags and forward it to `{emitEnvelopeHelper}` on stdin. Invoke via `uv run`. The script computes derived fields (`tools_added`, `tools_removed`, `tier_changed`, `warnings`), validates the assembled envelope against the JSON Schema at `src/shared/scripts/schemas/skf-setup-result-envelope.v1.json`, and emits the single prefixed line `SKF_SETUP_RESULT_JSON: {…}` on stdout.
176
166
 
177
167
  ```bash
178
168
  echo '{
@@ -203,16 +193,20 @@ echo '{
203
193
  "ccc_exclusion_warnings": {ccc_exclusion_warnings_list},
204
194
  "ccc_registry_stale_removed": {ccc_registry_stale_removed_paths_list},
205
195
  "ccc_indexing_failed_reason": {ccc_indexing_failed_reason_or_null},
196
+ "orphan_auto_resolution": {orphan_auto_resolution_or_null},
206
197
  "error": {error_object_or_null}
207
198
  }' | uv run {emitEnvelopeHelper} emit
208
199
  ```
209
200
 
210
201
  The script's documented context-payload shape (see `src/shared/scripts/skf-emit-result-envelope.py` docstring) tolerates two `tools` shapes — bare booleans OR `skf-detect-tools.py`'s `{key: {available: bool, ...}}` output — so either step 1's normalized booleans OR the raw detect-tools output forwarded as-is will produce the correct envelope.
211
202
 
212
- **If the script exits non-zero:** the assembled envelope failed schema validation, which means a context flag from an earlier step is malformed. Surface the error to stderr and continue (the human-readable banner is already displayed; missing JSON envelope on a headless run is a degraded but non-fatal state — the pipeline observer will see no envelope and treat that as "agent did not complete cleanly").
213
-
214
- **When both `{headless_mode}` and `{quiet_mode}` are `false`, do NOT invoke the script** — interactive runs read the human-readable banner.
203
+ **If the script exits non-zero:** the assembled envelope failed schema validation, which means a context flag from an earlier step is malformed. Surface the error to stderr and continue (missing JSON envelope on a headless run is a degraded but non-fatal state — the pipeline observer will see no envelope and treat that as "agent did not complete cleanly").
215
204
 
216
205
  ### 5. Chain to Health Check
217
206
 
218
- After the forge status report (and any failure block + JSON envelope) has been displayed, load `{nextStepFile}`, read it fully, and execute it — UNLESS `{require_tier_satisfied}` is `false`, in which case halt the workflow here without chaining to step 5. The health-check step is the true terminal step on success — do not stop after the report on a passing run even though it reads as final. step 5 in turn delegates to `shared/health-check.md`; after that returns, the setup workflow is fully done.
207
+ After the forge status report (and any failure block + JSON envelope) has been displayed:
208
+
209
+ - If `{require_tier_satisfied}` is `false`, halt the workflow here without chaining to step 5. The tier miss is terminal; `{onCompleteCommand}` does not fire on a failed run.
210
+ - Otherwise the forge is fully configured. If `{onCompleteCommand}` (resolved from `workflow.on_complete` at activation) is non-empty, execute it now — this is the workflow's terminal skill-specific action (e.g. trigger the first index build or notify an onboarding channel); in headless, log the action. Then load `{nextStepFile}`, read it fully, and execute it.
211
+
212
+ The health-check step is the true terminal step on success — do not stop after the report on a passing run even though it reads as final. Step 5 in turn delegates to `shared/health-check.md`; after that returns, the setup workflow is fully done.
@@ -1,36 +1,6 @@
1
- # Tier Calculation Rules
1
+ # Tier Report Copy
2
2
 
3
- ## Tool Detection Commands
4
-
5
- | Tool | Verification Command | What Confirms Availability |
6
- |------|---------------------|---------------------------|
7
- | ast-grep | `ast-grep --version` | Returns version string without error |
8
- | gh | `gh --version` | Returns version string without error |
9
- | qmd | `qmd status` | Returns status indicating initialized and operational |
10
- | ccc | Step A: `ccc --help` Step B: `ccc doctor` | Step A: exits 0 AND help output identifies the binary as cocoindex-code. Step B: daemon healthy. See `references/detect-and-tier.md` §7 for the full identity-marker procedure. |
11
-
12
- **Important:** Use verification commands, not existence checks (`which`, `command -v`). A tool must be functional, not just present on PATH. For daemon-based tools (ccc), verify both binary identity and daemon health — a binary with the right name but the wrong implementation is a false positive, not a tool.
13
-
14
- ## Tier Calculation
15
-
16
- | Priority | Tier | Required Tools | Rule |
17
- |----------|------|---------------|------|
18
- | 1 (highest) | Deep | ast-grep + gh + qmd | All three core tools available and functional |
19
- | 2 | Forge+ | ast-grep + ccc | ast-grep AND ccc available, regardless of gh/qmd |
20
- | 3 | Forge | ast-grep | ast-grep available, without ccc/gh/qmd |
21
- | 4 (default) | Quick | None | Default when no tools are available |
22
-
23
- **Evaluation order:** Check Deep first, then Forge+, then Forge. The first match wins. This ensures Deep always takes priority when all tools are present.
24
-
25
- **Override:** If `tier_override` is set in preferences.yaml, use that value instead of calculated tier.
26
-
27
- **Edge cases:**
28
- - gh available but no ast-grep → Quick (gh alone doesn't unlock Forge)
29
- - ast-grep + gh but no qmd → Forge (qmd required for Deep)
30
- - ast-grep + qmd but no gh → Forge (gh required for Deep)
31
- - ccc available but no ast-grep → Quick (ccc alone doesn't unlock Forge+)
32
- - ast-grep + ccc + gh but no qmd → Forge+ (qmd required for Deep)
33
- - ast-grep + gh + qmd + ccc → Deep (Deep subsumes Forge+; ccc enhances transparently)
3
+ The user-facing report strings the Step 4 report (`report.md`) consumes. Tool-detection probes and tier-calculation rules are owned by `skf-detect-tools.py` (see `references/detect-and-tier.md` §2) — this file holds only display copy, never detection or tier logic.
34
4
 
35
5
  ## Tier Capability Descriptions
36
6
 
@@ -1,12 +1,11 @@
1
1
  ---
2
2
  nextStepFile: 'auto-index.md'
3
- # Resolve `{forgeTierRwHelper}` by probing `{forgeTierRwProbeOrder}` in order
4
- # (installed SKF module path first, src/ dev-checkout fallback); first existing
5
- # path wins. HALT if neither resolves the script owns the canonical
6
- # forge-tier.yaml format AND the array-preservation contract that protects
7
- # qmd_collections / ccc_index_registry / staleness_threshold_hours from being
8
- # lost on rewrite. NEVER fall back to inline YAML emission — drift between the
9
- # script and a prose-rendered template will silently corrupt downstream skills.
3
+ # `{forgeTierRwHelper}` = first existing path in `{forgeTierRwProbeOrder}`;
4
+ # halt if neither exists. The script owns the canonical forge-tier.yaml format
5
+ # and the array-preservation contract that protects qmd_collections /
6
+ # ccc_index_registry / staleness_threshold_hours from being lost on rewrite.
7
+ # Do not fall back to inline YAML emission — a prose-rendered template drifts
8
+ # from the script and silently corrupts downstream skills.
10
9
  forgeTierRwProbeOrder:
11
10
  - '{project-root}/_bmad/skf/shared/scripts/skf-forge-tier-rw.py'
12
11
  - '{project-root}/src/shared/scripts/skf-forge-tier-rw.py'
@@ -39,7 +38,7 @@ Write the detected tool availability and calculated tier to `forge-tier.yaml` (p
39
38
 
40
39
  Build the JSON payload from context flags set by step 1 and step 1b. The payload must include `tools`, `tier`, and `ccc_index`; the script handles `tier_detected_at` defaulting to "now" if absent and preserves `qmd_collections`, `ccc_index_registry`, and a user-customized `ccc_index.staleness_threshold_hours` from any existing file.
41
40
 
42
- Invoke via `uv run` so the script's PEP 723 PyYAML dependency resolves automatically (this is what `docs/getting-started.md`'s uv prereq exists for). Bare `python3` would fail on a fresh interpreter with `ModuleNotFoundError`.
41
+ Invoke via `uv run`.
43
42
 
44
43
  ```bash
45
44
  echo '{
@@ -63,7 +62,7 @@ echo '{
63
62
  --target "{project-root}/_bmad/_memory/forger-sidecar/forge-tier.yaml"
64
63
  ```
65
64
 
66
- The script atomically writes the file via temp + fsync + rename (mirrors `skf-atomic-write.py`'s crash-safety contract) and returns a JSON response with `wrote`, `preserved_arrays.qmd_collections` count, `preserved_arrays.ccc_index_registry` count, and the resolved `tier`.
65
+ The script atomically writes the file via temp + fsync + rename (crash-safe) and returns a JSON response with `wrote`, `preserved_arrays.qmd_collections` count, `preserved_arrays.ccc_index_registry` count, and the resolved `tier`.
67
66
 
68
67
  **Parse the response and set context flags for step 4:**
69
68
 
@@ -80,7 +79,7 @@ uv run {forgeTierRwHelper} init-prefs \
80
79
  --target "{project-root}/_bmad/_memory/forger-sidecar/preferences.yaml"
81
80
  ```
82
81
 
83
- The script creates the file with first-run defaults (matching the prior inline template — `tier_override: ~`, `passive_context: true`, `headless_mode: false`, `compact_greeting: false`, plus reserved-for-future-use commented fields) IF the file does not exist. When the file already exists, the script refuses to overwrite (preserves user customization) and reports `wrote: false`.
82
+ The script creates the file with first-run defaults (`tier_override: ~`, `passive_context: true`, `headless_mode: false`, `compact_greeting: false`) if the file does not exist. When the file already exists, the script refuses to overwrite (preserves user customization) and reports `wrote: false`.
84
83
 
85
84
  **Parse the response and set context flags for step 4:**
86
85
 
@@ -7,7 +7,7 @@ description: Cognitive completeness verification — quality gate before export.
7
7
 
8
8
  ## Overview
9
9
 
10
- Verifies that a skill is complete enough to be useful to an AI agent by checking coverage of the public API surface (naive mode) or validating SKILL.md + references coherence (contextual mode). Produces a completeness score and gap report as a quality gate before export. Every finding must trace to actual code with file:line citations.
10
+ Verifies that a skill is complete enough to be useful to an AI agent by checking coverage of the public API surface (naive mode) or validating SKILL.md + references coherence (contextual mode). Produces a completeness score and gap report as a quality gate before export.
11
11
 
12
12
  ## Conventions
13
13
 
@@ -16,7 +16,6 @@ Verifies that a skill is complete enough to be useful to an AI agent by checking
16
16
  - `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives, if present).
17
17
  - `{project-root}`-prefixed paths resolve from the project working directory.
18
18
  - `{skill-name}` resolves to the skill directory's basename.
19
- - Step files use `## STEP GOAL:` headings rather than the `## MANDATORY SEQUENCE` + `## CRITICAL STEP COMPLETION NOTE` pattern used by generate-driven SKF workflows — this skill is a validation harness with score-driven step semantics, not a chain that produces new artifacts.
20
19
 
21
20
  ## Role
22
21
 
@@ -50,7 +49,7 @@ These rules apply to every step in this workflow:
50
49
 
51
50
  | Aspect | Detail |
52
51
  |--------|--------|
53
- | **Inputs** | skill_name [required]; optional flags: `--allow-workspace-drift`, `--no-discovery` (skip §4b Discovery Testing), `--no-health-check` (skip §7 health-check dispatch), `--tier=<Quick\|Forge\|Forge+\|Deep>` (bypass forge-tier.yaml sidecar requirement), `--threshold=<N>` (override pass threshold; CLI wins over per-pipeline defaults and `workflow.default_threshold` scalar) |
52
+ | **Inputs** | skill_name [required]; optional flags: `--allow-workspace-drift`, `--no-discovery` (skip the report step's Discovery Testing block), `--no-health-check` (skip §7 health-check dispatch), `--tier=<Quick\|Forge\|Forge+\|Deep>` (bypass forge-tier.yaml sidecar requirement), `--threshold=<N>` (override pass threshold; CLI wins over per-pipeline defaults and `workflow.default_threshold` scalar) |
54
53
  | **Gates** | step 6: Confirm Gate [C] |
55
54
  | **Outputs** | per-run `test-report-{skill_name}-{run_id}.md` with completeness score and result (PASS/FAIL); per-run `skf-test-skill-result-{run_id}.json` and `skf-test-skill-result-latest.json` written atomically under `{forge_version}/`; `evidence-report-fallback.md` written under `{forge_version}/` when threshold fallback occurs (score between 80% and target threshold) — downstream consumers (export-skill, update-skill `--from-test-report`) glob `test-report-{skill_name}-*.md` and pick newest by parsed ISO timestamp |
56
55
  | **Headless** | All gates auto-resolve with default action when `{headless_mode}` is true |
@@ -63,19 +62,20 @@ Every terminal state in this workflow exits with a stable code so headless autom
63
62
  | Code | Meaning | Raised by |
64
63
  | ---- | -------------------- | ------------------------------------------------------------------------------------------ |
65
64
  | 0 | success / PASS | step 6 §6b — `testResult: 'pass'` (after the result contract is written in §4c) |
65
+ | 1 | error (HARD HALT) | infrastructure / precondition HALT in step 1 or step 6 before a verdict exists — see the "Result Contract" `halt_reason` set (the hard gate uses code 2) |
66
66
  | 2 | fail / FAIL | step 4c §3 — hard gate blocked (`halt_reason: "hard-gate-blocked"`); step 6 §6b — `testResult: 'fail'` (after the result contract is written in §4c) |
67
67
  | 3 | inconclusive | step 6 §6b — `testResult: 'inconclusive'` (distinct from fail so orchestrators can route to manual-review queues) |
68
- | 4 | pass-with-drift | step 6 §6b — `testResult: 'pass-with-drift'` (distinct from clean pass — `--allow-workspace-drift` was in effect; orchestrators MUST route to re-test-against-pinned-commit queues and refuse export; never exit 0 under drift override) |
68
+ | 4 | pass-with-drift | step 6 §6b — `testResult: 'pass-with-drift'` (distinct from clean pass — `--allow-workspace-drift` was in effect; re-test against the pinned commit and refuse export exit 0 would wrongly signal a clean pass) |
69
69
 
70
70
  ## Result Contract (Headless)
71
71
 
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
+ When `{headless_mode}` is true, step 6 emits a single-line JSON envelope on **stdout** before chaining to step 7, and every HALT the Exit Codes table above marks with a non-zero code emits the same envelope shape on **stderr** with `status: "error"` and the `halt_reason` naming the failure, so a headless orchestrator branches on the reason without grepping prose:
73
73
 
74
74
  ```
75
75
  SKF_TEST_RESULT_JSON: {"status":"success|error","skill_name":"…","verdict":"PASS|FAIL|INCONCLUSIVE|pass-with-drift","score":N,"threshold":N,"report_path":"…|null","next_workflow":"export-skill|update-skill|null","exit_code":0,"halt_reason":null,"threshold_fallback":true,"original_threshold":90}
76
76
  ```
77
77
 
78
- `status` is `"success"` on the terminal happy path (any of PASS / FAIL / INCONCLUSIVE / pass-with-drift — the workflow completed), `"error"` on any HARD HALT before §4c. `verdict` is the canonical result string. `next_workflow` is `"export-skill"` only when `verdict == "PASS"`; `"update-skill"` for `FAIL` or `pass-with-drift`; `null` for `INCONCLUSIVE` (manual review). `halt_reason` is `null` on the terminal path or one of the workflow-defined halt strings (`"forge-tier-missing"`, `"target-inaccessible"`, `"write-failed"`, `"step-completeness-violation"`, `"report-anchor-missing"`, `"health-check-missing"`, `"atomic-writer-missing"`, `"hard-gate-blocked"`). `exit_code` matches the table above. When threshold fallback occurred, the envelope includes `"threshold_fallback":true` and `"original_threshold":N`; these fields are omitted when no fallback occurred.
78
+ `status` is `"success"` on the terminal happy path (PASS / FAIL / INCONCLUSIVE / pass-with-drift — the workflow completed), `"error"` on an emitted HARD HALT. `verdict` is the canonical result string (`null` on an infrastructure error halt). `next_workflow` is `"export-skill"` only when `verdict == "PASS"`; `"update-skill"` for `FAIL` or `pass-with-drift`; `null` for `INCONCLUSIVE` and error halts. `halt_reason` is `null` on the terminal path or one of the emitted strings: `"target-inaccessible"`, `"forge-tier-missing"`, `"workspace-drift"`, `"another-run-active"`, `"frontmatter-invalid"` (init HALTs), `"atomic-writer-missing"`, `"step-completeness-violation"`, `"report-anchor-missing"`, `"health-check-missing"` (report HALTs), or `"hard-gate-blocked"` (step 4c). `exit_code` is the code the Exit Codes table above assigns to the reached terminal state or HALT. Step 1 §3 frontmatter-validation now emits the `"frontmatter-invalid"` stderr envelope (see init.md §3c) and is branchable. Only the coverage/coherence analysis aborts print a diagnostic and exit non-zero **without** this envelope — they are the sole remaining outcomes outside the branchable set. When threshold fallback occurred, the envelope includes `"threshold_fallback":true` and `"original_threshold":N`; these fields are omitted when no fallback occurred.
79
79
 
80
80
  The same payload is persisted to disk by step 6 §4c (atomic write) at two locations under `{forge_version}/`:
81
81
 
@@ -115,8 +115,10 @@ The on-disk payload is the richer form: it adds `outputs[]` (report-path entries
115
115
  - `{outputFormatsPath}` ← `workflow.output_formats_path` if non-empty, else `assets/output-section-formats.md`
116
116
  - `{scoringRulesPath}` ← `workflow.scoring_rules_path` if non-empty, else `references/scoring-rules.md`
117
117
  - `{defaultThreshold}` ← `workflow.default_threshold` if non-empty/non-null, else `80`. CLI `--threshold=<N>` wins over per-pipeline defaults (from init.md §1b) which win over this scalar at the usage site in `references/score.md`.
118
- - `{onCompleteCommand}` ← `workflow.on_complete` if non-empty, else empty string. When empty, the post-finalization hook in `references/report.md` is a no-op.
118
+ - `{onCompleteCommand}` ← `workflow.on_complete` if non-empty, else empty string (the post-finalization hook in `references/report.md` is then a no-op).
119
119
 
120
- Stash all five as workflow-context variables. Stage files reference `{testReportTemplatePath}` / `{outputFormatsPath}` / `{scoringRulesPath}` / `{defaultThreshold}` / `{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 without forking the skill.
120
+ Stash all five as workflow-context variables that stage files reference directly — no conditional at the usage site.
121
+
122
+ **Apply the array surfaces** (not silent no-ops): run `workflow.activation_steps_prepend` in order now; treat each `workflow.persistent_facts` entry 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.
121
123
 
122
124
  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-test-skill.
4
+ # Team overrides: _bmad/custom/skf-test-skill.toml (under {project-root})
5
+ # Personal overrides: _bmad/custom/skf-test-skill.user.toml (under {project-root})
4
6
 
5
7
  [workflow]
6
8
 
@@ -1,8 +1,9 @@
1
1
  ---
2
2
  nextStepFile: 'external-validators.md'
3
3
  outputFile: '{forge_version}/test-report-{skill_name}-{run_id}.md'
4
- outputFormatsFile: 'assets/output-section-formats.md'
5
- scoringRulesFile: 'references/scoring-rules.md'
4
+ outputFormatsFile: '{outputFormatsPath}'
5
+ scoringRulesFile: '{scoringRulesPath}'
6
+ coherenceAggregationScript: 'scripts/aggregate-coherence.py'
6
7
  migrationSectionRules: 'references/migration-section-rules.md'
7
8
  scanSkillMdStructureProbeOrder:
8
9
  - '{project-root}/_bmad/skf/shared/scripts/skf-scan-skill-md-structure.py'
@@ -104,7 +105,7 @@ Scan SKILL.md for all cross-references:
104
105
  - Integration pattern references (middleware chains, plugin hooks, shared state)
105
106
  - Script/asset references (`scripts/{file}`, `assets/{file}`) in SKILL.md body
106
107
 
107
- Delegate to a subagent that grep/regexes SKILL.md for reference patterns and returns ONLY this JSON shape — no prose, no commentary, no markdown fences: `{"references_found": [{"line": N, "type": "file-path|skill|type-import|integration-pattern|script-asset", "target": "..."}]}`. Parent strips wrapping markdown fences (if present) before parsing. If subagent unavailable, scan in main thread.
108
+ Delegate to a subagent that grep/regexes SKILL.md for reference patterns and returns only this JSON shape — no prose, no commentary, no markdown fences: `{"references_found": [{"line": N, "type": "file-path|skill|type-import|integration-pattern|script-asset", "target": "..."}]}`. Parent strips wrapping markdown fences (if present) before parsing. If subagent unavailable, scan in main thread.
108
109
 
109
110
  ### 4. Contextual Mode: Validate Each Reference
110
111
 
@@ -117,13 +118,13 @@ For EACH reference found, delegate to a subagent that:
117
118
  - Skill references: referenced skill exists in skills output folder
118
119
  - Integration patterns: documented pattern matches actual implementation
119
120
  - Script/asset references: verify the referenced file exists in the skill's `scripts/` or `assets/` directory
120
- 3. Returns ONLY this JSON shape per reference — no prose, no commentary, no markdown fences: `{"reference": "...", "line": N, "target_exists": <bool>, "type_match": <bool>, "signature_match": <bool>, "issues": ["..."]}`
121
+ 3. Returns only this JSON shape per reference — no prose, no commentary, no markdown fences: `{"reference": "...", "line": N, "target_exists": <bool>, "type_match": <bool>, "signature_match": <bool>, "issues": ["..."]}`
121
122
 
122
123
  Parent strips wrapping markdown fences (if present) before parsing. If subagent unavailable, validate each reference in main thread.
123
124
 
124
125
  4. **Scripts/assets directory check:** If a `scripts/` or `assets/` directory exists alongside SKILL.md, verify that a "Scripts & Assets" section (Section 7b) is present in SKILL.md. This directory-level check applies in both modes (naive mode performs it in Section 2; contextual mode performs it here alongside per-reference validation). Flag absence as Medium severity gap per `{scoringRulesFile}`.
125
126
 
126
- 5. **Path containment:** for every resolved reference target, compute its canonical path (`os.path.realpath`) and require that it lives inside `{skillDir}`, inside `{source_path}` (the extraction tree recorded in metadata.json), OR — for stack skills — inside `{skills_output_folder}`. The third root applies only here in contextual mode: a stack's constituent cross-references legitimately resolve to `skills/{name}/active` under `{skills_output_folder}`, which lies outside `{skillDir}`, and a stack's metadata.json records no single `source_path` to anchor them. References whose canonical path escapes all applicable roots (e.g. `../../../etc/passwd`, absolute paths to unrelated dirs, symlink redirections outside the skill, its source, or — for a stack — the skills output tree) are **High severity** findings: `coherence — reference escapes skill/source sandbox: {raw_ref} → {canonical_path}`. Canonicalization happens before the root check, so a symlink that points outside every applicable root is still caught. Do NOT validate the target's contents for escaping references — the escape itself is the finding.
127
+ 5. **Path containment:** for every resolved reference target, compute its canonical path (`os.path.realpath`) and require that it lives inside `{skillDir}`, inside `{source_path}` (the extraction tree recorded in metadata.json), OR — for stack skills — inside `{skills_output_folder}`. The third root applies only here in contextual mode: a stack's constituent cross-references legitimately resolve to `skills/{name}/active` under `{skills_output_folder}`, which lies outside `{skillDir}`, and a stack's metadata.json records no single `source_path` to anchor them. References whose canonical path escapes all applicable roots (e.g. `../../../etc/passwd`, absolute paths to unrelated dirs, symlink redirections outside the skill, its source, or — for a stack — the skills output tree) are **High severity** findings: `coherence — reference escapes skill/source sandbox: {raw_ref} → {canonical_path}`. Canonicalization happens before the root check, so a symlink that points outside every applicable root is still caught. Do not validate the target's contents for escaping references — the escape itself is the finding.
127
128
 
128
129
  ### 5. Contextual Mode: Check Integration Pattern Completeness
129
130
 
@@ -160,17 +161,20 @@ results.
160
161
 
161
162
  ### 5c. Calculate Coherence Scores
162
163
 
163
- **Contextual mode only.** Calculate coherence percentages using the formulas defined in `{scoringRulesFile}` — Coherence Score Aggregation section:
164
+ **Contextual mode only.** The reference-validity ratio, the integration-completeness ratio, and their fixed 0.6 / 0.4 weighted mean are pure arithmetic — the judgment (which references are valid in §4, which patterns are complete in §5) has already happened. Do not compute these percentages by hand; they are aggregated by `{coherenceAggregationScript}` (the formulas it encodes are documented in `{scoringRulesFile}` — Coherence Score Aggregation).
164
165
 
165
- ```
166
- reference_validity = (valid_references / total_references) * 100
167
- integration_completeness = (complete_patterns / total_patterns) * 100
168
- combined_coherence = (reference_validity * 0.6) + (integration_completeness * 0.4)
166
+ Tally the counts from the §4 per-reference JSON (`valid_references` = references with `target_exists && type_match && signature_match && no issues`; `total_references` = references extracted in §3) and the §5 integration JSON (`patterns_documented`, `patterns_complete`), then invoke:
167
+
168
+ ```bash
169
+ echo '{"valid_references": <V>, "total_references": <T>, "patterns_documented": <PD>, "patterns_complete": <PC>}' | uv run {coherenceAggregationScript} --stdin
169
170
  ```
170
171
 
171
- **Edge case:** If no integration patterns are documented (patterns_documented = 0), combined coherence equals reference validity alone. Do not divide by zero.
172
+ The script also accepts the JSON as a positional argument or via `--json-input`. Parse its output and read:
173
+ - `referenceValidity` — reference-validity percentage
174
+ - `integrationCompleteness` — integration-completeness percentage (`null` when no patterns are documented)
175
+ - `combinedCoherence` — the combined coherence percentage passed to score.md §3a as the `coherence` input
172
176
 
173
- These values fill the `{percentage}%` placeholders in the output template loaded in Section 6.
177
+ The script handles both edge cases the formula requires: `patterns_documented == 0` → `combinedCoherence` equals `referenceValidity` (no divide-by-zero); `total_references == 0` → `referenceValidity` is 100.0 (no references means no broken references). These values fill the `{percentage}%` placeholders in the output template loaded in Section 6.
174
178
 
175
179
  ### 6. Append Coherence Analysis to Output
176
180
 
@@ -178,26 +182,10 @@ Load `{outputFormatsFile}` and use the appropriate Coherence Analysis section fo
178
182
 
179
183
  ### 7. Report Coherence Results
180
184
 
181
- **For Naive Mode:**
182
- "**Coherence check complete (naive mode).**
183
-
184
- Basic structural validation of **{skill_name}**:
185
- - {N} structural issues found
186
- - Coherence category not scored (weight redistributed to coverage)
187
-
188
- **Proceeding to external validation...**"
189
-
190
- **For Contextual Mode:**
191
- "**Coherence check complete (contextual mode).**
192
-
193
- Reference validation of **{skill_name}**:
194
- - References: {valid}/{total} valid ({percentage}%)
195
- - Integration patterns: {complete}/{total} complete ({percentage}%)
196
- - Combined coherence: {percentage}%
197
-
198
- **{N} issues found** — details in Coherence Analysis section.
185
+ Report the coherence result to the user, then proceed to external validation:
199
186
 
200
- **Proceeding to external validation...**"
187
+ - **Naive mode:** the count of structural issues found (the coherence category is not scored — its weight redistributes to coverage).
188
+ - **Contextual mode:** the reference-validity ratio, the integration-completeness ratio, the combined coherence percentage, and the issue count — full details are in the Coherence Analysis section.
201
189
 
202
190
  Update stepsCompleted, then load and execute {nextStepFile}.
203
191