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
@@ -0,0 +1,270 @@
1
+ #!/usr/bin/env python3
2
+ # /// script
3
+ # requires-python = ">=3.10"
4
+ # ///
5
+ """Deterministic parse + validation of a forger pipeline invocation.
6
+
7
+ Pipeline Mode (references/pipeline-mode.md §1-2) turns a raw code sequence
8
+ (`BS CS[cocoindex] TS[min:80] EX`, `AN -> CS -> TS -> EX`, or a bare alias like
9
+ `forge-auto`) into a normalized run plan and a list of sequence anti-patterns.
10
+ Splitting the tokens, expanding aliases against a fixed table, classifying each
11
+ bracket argument, and detecting anti-patterns (duplicates, ordering, missing
12
+ prerequisites) is set/order plumbing with exactly one correct answer per input —
13
+ so it runs here, not in the prompt. The prompt keeps only the judgment the
14
+ script cannot make: interpreting the user's freeform request into a code
15
+ sequence, and deciding whether to proceed past a warned anti-pattern.
16
+
17
+ The alias-expansion and anti-pattern tables mirror
18
+ `src/shared/references/pipeline-contracts.md` (the human-readable contract);
19
+ this script is the executable form the forger consumes.
20
+
21
+ CLI usage:
22
+ uv run scripts/parse-pipeline.py 'BS CS TS EX' # positional
23
+ uv run scripts/parse-pipeline.py 'forge-auto' # bare alias
24
+ echo 'AN -> CS -> TS -> EX' | uv run scripts/parse-pipeline.py --stdin
25
+
26
+ Output (stdout, one object):
27
+ {
28
+ "raw": "<input>",
29
+ "alias": "forge" | null, # set when the input was a lone alias
30
+ "deprecated_alias": "deepwiki" | null,
31
+ "removed_alias": "onboard" | null,
32
+ "expanded": ["BS", "CS", "TS", "EX"], # normalized tokens (post-expansion)
33
+ "plan": [{"code","min","mode","target"}, ...],
34
+ "codes": ["BS", "CS", "TS", "EX"],
35
+ "unknown_codes": [],
36
+ "anti_patterns": [{"pattern","message","suggestion"}, ...],
37
+ "valid": <bool> # runnable: real codes, no unknowns, not removed
38
+ }
39
+
40
+ Exit codes:
41
+ 0 — parsed, runnable (anti-patterns and a deprecated alias are warnings)
42
+ 1 — no input provided (usage error)
43
+ 2 — removed alias (e.g. `onboard`) — the forger HALTs
44
+ 3 — nothing runnable (empty, or unknown codes) — the forger corrects course
45
+ """
46
+
47
+ from __future__ import annotations
48
+
49
+ import argparse
50
+ import json
51
+ import re
52
+ import sys
53
+
54
+ # Workflow codes that can appear in a pipeline. KI/WS are inline actions, not
55
+ # pipeline steps; `campaign` is a standalone workflow, not a pipeline code.
56
+ KNOWN_CODES = frozenset(
57
+ {"SF", "AN", "BS", "CS", "QS", "SS", "US", "AS", "VS", "RA", "TS", "EX", "RS", "DS"}
58
+ )
59
+
60
+ # Only these accept a `min:N` circuit-breaker override; on other codes a
61
+ # `min:N` bracket is ignored (recorded as `min: null`).
62
+ CIRCUIT_BREAKER_CODES = frozenset({"AN", "CS", "TS", "AS", "VS"})
63
+
64
+ # Alias table — mirrors pipeline-contracts.md. `forge-auto`'s TS[min:90] gate is
65
+ # non-default and is kept in lockstep with init.md §1b's forge-auto → 90 lookup.
66
+ ALIASES = {
67
+ "forge-auto": ["AN[auto]", "BS[auto]", "CS", "TS[min:90]", "EX"],
68
+ "forge": ["BS", "CS", "TS", "EX"],
69
+ "forge-quick": ["QS", "TS", "EX"],
70
+ "maintain": ["AS", "US", "TS", "EX"],
71
+ }
72
+ DEPRECATED_ALIASES = {"deepwiki": "forge-auto"} # renamed; still expands
73
+ REMOVED_ALIASES = {"onboard"} # no expansion — the forger HALTs
74
+
75
+ _TOKEN_RE = re.compile(r"^([A-Za-z]+)(?:\[([^\]]*)\])?$")
76
+ _ARROWS = re.compile(r"->|→|—>|»")
77
+
78
+
79
+ def _tokenize(raw):
80
+ """Split a raw sequence on whitespace and arrow separators."""
81
+ normalized = _ARROWS.sub(" ", raw)
82
+ return [t for t in normalized.split() if t]
83
+
84
+
85
+ def _classify_bracket(code, value):
86
+ """Return (min, mode, target) for a bracket value on a given code."""
87
+ if value is None or value == "":
88
+ return None, None, None
89
+ m = re.fullmatch(r"min:(\d+)", value)
90
+ if m:
91
+ # min:N only applies to circuit-breaker codes; ignored elsewhere.
92
+ return (int(m.group(1)) if code in CIRCUIT_BREAKER_CODES else None), None, None
93
+ if value == "auto":
94
+ return None, "auto", None
95
+ return None, None, value
96
+
97
+
98
+ def _detect_anti_patterns(codes):
99
+ """Deterministic sequence checks — mirrors pipeline-contracts.md."""
100
+ found = []
101
+
102
+ # Duplicate codes.
103
+ seen = set()
104
+ dupes = []
105
+ for c in codes:
106
+ if c in seen and c not in dupes:
107
+ dupes.append(c)
108
+ seen.add(c)
109
+ if dupes:
110
+ found.append(
111
+ {
112
+ "pattern": "duplicate-codes",
113
+ "codes": dupes,
114
+ "message": f"same workflow appears more than once: {', '.join(dupes)}",
115
+ "suggestion": "remove the duplicate",
116
+ }
117
+ )
118
+
119
+ # EX before TS (equivalently, TS after EX).
120
+ ex_idxs = [i for i, c in enumerate(codes) if c == "EX"]
121
+ ts_idxs = [i for i, c in enumerate(codes) if c == "TS"]
122
+ if ex_idxs and ts_idxs and min(ex_idxs) < max(ts_idxs):
123
+ found.append(
124
+ {
125
+ "pattern": "ex-before-ts",
126
+ "codes": ["EX", "TS"],
127
+ "message": "EX (export) runs before TS (test) — exporting an untested skill",
128
+ "suggestion": "move TS before EX",
129
+ }
130
+ )
131
+
132
+ # CS without BS or AN.
133
+ if "CS" in codes and "BS" not in codes and "AN" not in codes:
134
+ found.append(
135
+ {
136
+ "pattern": "cs-without-brief",
137
+ "codes": ["CS"],
138
+ "message": "CS (compile) has no preceding BS or AN — compiling without a brief",
139
+ "suggestion": "use QS for the quick path, or add AN/BS to produce a brief",
140
+ }
141
+ )
142
+
143
+ # US without AS.
144
+ if "US" in codes and "AS" not in codes:
145
+ found.append(
146
+ {
147
+ "pattern": "us-without-audit",
148
+ "codes": ["US"],
149
+ "message": "US (update) has no preceding AS — updating without an audit",
150
+ "suggestion": "run AS first to detect what changed",
151
+ }
152
+ )
153
+
154
+ return found
155
+
156
+
157
+ def parse_pipeline(raw):
158
+ """Parse and validate a raw pipeline sequence. Deterministic."""
159
+ tokens = _tokenize(raw)
160
+ result = {
161
+ "raw": raw,
162
+ "alias": None,
163
+ "deprecated_alias": None,
164
+ "removed_alias": None,
165
+ "expanded": [],
166
+ "plan": [],
167
+ "codes": [],
168
+ "unknown_codes": [],
169
+ "anti_patterns": [],
170
+ "valid": False,
171
+ }
172
+ if not tokens:
173
+ return result
174
+
175
+ # Alias handling — only when the sequence is a lone alias token.
176
+ if len(tokens) == 1:
177
+ lone = tokens[0].lower()
178
+ if lone in REMOVED_ALIASES:
179
+ result["removed_alias"] = lone
180
+ return result
181
+ if lone in DEPRECATED_ALIASES:
182
+ result["deprecated_alias"] = lone
183
+ target = DEPRECATED_ALIASES[lone]
184
+ result["alias"] = target
185
+ tokens = list(ALIASES[target])
186
+ elif lone in ALIASES:
187
+ result["alias"] = lone
188
+ tokens = list(ALIASES[lone])
189
+
190
+ result["expanded"] = []
191
+ for tok in tokens:
192
+ m = _TOKEN_RE.match(tok)
193
+ if not m:
194
+ result["unknown_codes"].append(tok)
195
+ continue
196
+ code = m.group(1).upper()
197
+ value = m.group(2)
198
+ result["expanded"].append(
199
+ f"{code}[{value}]" if value not in (None, "") else code
200
+ )
201
+ if code not in KNOWN_CODES:
202
+ result["unknown_codes"].append(tok)
203
+ continue
204
+ min_n, mode, target = _classify_bracket(code, value)
205
+ result["codes"].append(code)
206
+ result["plan"].append(
207
+ {"code": code, "min": min_n, "mode": mode, "target": target}
208
+ )
209
+
210
+ result["anti_patterns"] = _detect_anti_patterns(result["codes"])
211
+ result["valid"] = bool(result["codes"]) and not result["unknown_codes"]
212
+ return result
213
+
214
+
215
+ # --- CLI --------------------------------------------------------------------
216
+
217
+
218
+ def _build_parser():
219
+ parser = argparse.ArgumentParser(
220
+ prog="parse-pipeline",
221
+ description=(
222
+ "Deterministic parse + validation of a forger pipeline invocation "
223
+ "(pipeline-mode.md §1-2): tokenize, expand aliases, classify bracket "
224
+ "arguments, and detect sequence anti-patterns, returning a normalized "
225
+ "run plan as JSON."
226
+ ),
227
+ formatter_class=argparse.RawDescriptionHelpFormatter,
228
+ )
229
+ src = parser.add_mutually_exclusive_group()
230
+ src.add_argument(
231
+ "sequence",
232
+ nargs="?",
233
+ help="Raw pipeline sequence as a positional argument.",
234
+ )
235
+ src.add_argument(
236
+ "--stdin",
237
+ action="store_true",
238
+ help="Read the raw sequence from stdin.",
239
+ )
240
+ return parser
241
+
242
+
243
+ def _resolve_input(args):
244
+ if args.stdin:
245
+ return sys.stdin.read()
246
+ if args.sequence is not None:
247
+ return args.sequence
248
+ return ""
249
+
250
+
251
+ def main(argv=None):
252
+ parser = _build_parser()
253
+ args = parser.parse_args(argv)
254
+ raw = _resolve_input(args)
255
+ if not raw.strip():
256
+ parser.print_usage(file=sys.stderr)
257
+ print("error: no input provided (positional arg or --stdin)", file=sys.stderr)
258
+ return 1
259
+
260
+ result = parse_pipeline(raw)
261
+ print(json.dumps(result, indent=2))
262
+ if result["removed_alias"]:
263
+ return 2
264
+ if not result["valid"]:
265
+ return 3
266
+ return 0
267
+
268
+
269
+ if __name__ == "__main__":
270
+ raise SystemExit(main())
@@ -7,7 +7,7 @@ description: Fast skill from a package name or GitHub URL — no brief needed. U
7
7
 
8
8
  ## Overview
9
9
 
10
- The fastest path to a skill — accept a GitHub URL or package name, resolve to source, extract the public API surface, and produce a best-effort SKILL.md with context snippet and metadata. No brief needed. Quick Skill is tier-unaware by design — all output is produced at community-tier quality regardless of available tools.
10
+ The fastest path to a skill — accept a GitHub URL or package name, resolve to source, extract the public API surface, and produce a best-effort SKILL.md with context snippet and metadata. No brief needed. Output is always community-tier quality, regardless of which tools are available.
11
11
 
12
12
  ## Conventions
13
13
 
@@ -28,7 +28,7 @@ These rules apply to every step in this workflow:
28
28
  - Never fabricate content — all data must come from source extraction or user input
29
29
  - Only load one step file at a time — never preload future steps
30
30
  - Always communicate in `{communication_language}`
31
- - **Universal cancel-line affordance** — at any interactive prompt the user may type `cancel`, `exit`, `:q`, or select the `[X] Cancel and exit` menu option (where surfaced) to leave cleanly. HARD HALT with **exit code 6 (user-cancelled)** and emit the error result contract per "Result Contract on HARD HALT" with `error.code: "user-cancelled"`. In step 4 §6 the equivalent affordance is `[Q] Quit without writing` — same exit code, same envelope contract.
31
+ - **Universal cancel-line affordance** — at any interactive prompt the user may type `cancel`, `exit`, `:q`, or select the `[X] Cancel and exit` menu option (where surfaced) to leave cleanly. HARD HALT with **exit code 6 (user-cancelled)** and emit the error result contract per `references/halt-contract.md` with `error.code: "user-cancelled"`. In step 4 §6 the equivalent affordance is `[Q] Quit without writing` — same exit code, same envelope contract.
32
32
  - If `{headless_mode}` is true, auto-proceed through confirmation gates with their default action and log each auto-decision
33
33
  - If `{headless_mode}` is true, emit a single-line JSON progress event to **stderr** at each step's entry and exit so pipeline schedulers can stream live progress instead of post-mortem-parsing the result contract:
34
34
  - entry: `{"step":N,"name":"<slug>","status":"start"}`
@@ -55,61 +55,14 @@ These rules apply to every step in this workflow:
55
55
  |--------|--------|
56
56
  | **Inputs** | target (GitHub URL or package name) [required for single-target mode], language_hint [optional], scope_hint [optional] |
57
57
  | **Overrides** | `--description`, `--exports`, `--skip-snippet`, `--no-active-pointer`, `--batch <file>`, `--fail-fast` — see On Activation step 4 |
58
- | **Gates** | step 1: Input Gate [use args]; step 2: Choice Gate [P] (if match); step 4: Review Gate [C/E/S/Q] |
58
+ | **Gates** | step 1: target input, multi-language disambiguation [C/A]; step 2: ecosystem match [P/I/A] (if match); step 3: repo-shape [C/A] + zero-exports rescue [R/P/A]; step 4: review [C/E/S/Q]; step 5: overwrite [Y/N] |
59
59
  | **Outputs** | SKILL.md, context-snippet.md, metadata.json, active pointer, result contract (timestamped + `-latest` copy). Snippet and active pointer can be skipped per overrides. |
60
60
  | **Headless** | All gates auto-resolve with default action when `{headless_mode}` is true |
61
- | **Exit codes** | See "Exit Codes" below |
61
+ | **Exit codes** | See `references/halt-contract.md` |
62
62
 
63
- ## Exit Codes
63
+ ## Exit Codes & HARD HALT Contract
64
64
 
65
- Every HARD HALT in this workflow exits with a stable, documented code so headless automators can branch on the failure class without grepping message text:
66
-
67
- | Code | Meaning | Raised by |
68
- | ---- | ---------------------- | ----------------------------------------------------------- |
69
- | 0 | success | step 7 (terminal) |
70
- | 3 | resolution-failure | step 1 §2c (prose input), step 1 §3 (registry chain failed) |
71
- | 4 | write-failure | step 5 §2 (deliverable write failed) |
72
- | 5 | overwrite-cancelled | step 5 §1 (user selected [N]) |
73
- | 6 | user-cancelled | step 1 §1 ([X] Cancel and exit, or cancel-line affordance); step 2 §3 ([A] Abort at ecosystem-match gate); step 4 §6 (user selected [Q]) — originally `compile-cancelled`, generalised to cover any interactive gate |
74
- | 7 | finalize-blocked | step 6 §1 (active-pointer flip refused — non-link in place) |
75
- | 8 | ecosystem-redirect | step 2 §3 ([I] Install at ecosystem-match gate — user opted to install the existing official skill instead of compiling a custom community skill) |
76
-
77
- Reserved: `validator-missing` may be promoted from advisory log to fatal exit code in a future revision.
78
-
79
- ## Result Contract on HARD HALT
80
-
81
- In addition to the success-variant result contract written by step 6 §3, every HARD HALT must surface an **error variant** so headless automators don't silently break when `quick-skill-result-latest.json` is missing on failed runs.
82
-
83
- **Always (every HARD HALT, regardless of phase)** — emit a single line on **stderr**:
84
-
85
- ```
86
- SKF_QUICK_SKILL_RESULT_JSON: {"status":"error","exit_code":<N>,"phase":"<slug>","error":{"code":"<class>","message":"<short>"},"outputs":{},"summary":{},"skill_package":"<path-or-null>"}
87
- ```
88
-
89
- One line, no pretty-print. Matches the prefix-and-envelope convention used by `skf-emit-result-envelope.py`.
90
-
91
- **Additionally, when `{skill_package}` is known** (HALT at step 5 §1 onward) — write the same JSON object (without the `SKF_QUICK_SKILL_RESULT_JSON: ` prefix) to disk:
92
-
93
- ```
94
- {skill_package}/quick-skill-result-{YYYYMMDD-HHmmss}.json
95
- {skill_package}/quick-skill-result-latest.json (copy, not symlink)
96
- ```
97
-
98
- so consumers that hardcode the `-latest.json` path see a deterministic file even on failed runs. HALTs at step 1/02/03/04 cannot write to disk because `{skill_package}` is computed only in step 5 §1; for those, the stderr envelope plus exit code is the contract.
99
-
100
- **Schema:**
101
-
102
- | Field | Type | Notes |
103
- | --------------- | -------------- | ----------------------------------------------------------------------------------------------------------- |
104
- | `status` | string | always `"error"` for HARD HALTs |
105
- | `exit_code` | integer | matches the Exit Codes table |
106
- | `phase` | string | step slug where the HALT occurred (e.g. `resolve-target`, `compile`) |
107
- | `error.code` | string | one of: `resolution-failure`, `write-failure`, `overwrite-cancelled`, `user-cancelled` (formerly `compile-cancelled`), `finalize-blocked`, `ecosystem-redirect` |
108
- | `error.message` | string | the user-facing message that was displayed |
109
- | `error.details` | any | optional — phase-specific context (e.g. the failed file path) |
110
- | `outputs` | object | empty `{}` on early HALTs; partial when files were already written |
111
- | `summary` | object | empty `{}` on early HALTs |
112
- | `skill_package` | string \| null | absolute path when known, `null` when HALT preceded step 5 §1 |
65
+ See `references/halt-contract.md` for the exit-code map and the error-result envelope every HARD HALT emits (the `SKF_QUICK_SKILL_RESULT_JSON:` stderr line, the on-disk `-latest.json` write once `{skill_package}` is known, and the schema). Steps load it on their failure path so the wire format survives compaction.
113
66
 
114
67
  ## On Activation
115
68
 
@@ -139,8 +92,11 @@ so consumers that hardcode the `-latest.json` path see a deterministic file even
139
92
  - `{skillTemplatePath}` ← `workflow.skill_template_path` if non-empty, else `assets/skill-template.md`
140
93
  - `{registryResolutionPath}` ← `workflow.registry_resolution_path` if non-empty, else `references/registry-resolution.md`
141
94
  - `{batchOutputPath}` ← `workflow.batch_output_path` if non-empty, else `{skills_output_folder}/_batch/`
95
+ - `{onCompleteCommand}` ← `workflow.on_complete` if non-empty, else empty (no-op — step 6 §3 skips the hook invocation entirely)
142
96
 
143
- Stash all three as workflow-context variables. Stage files reference `{skillTemplatePath}` / `{registryResolutionPath}` / `{batchOutputPath}` 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.
97
+ Stash all four as workflow-context variables. Stage files reference `{skillTemplatePath}` / `{registryResolutionPath}` / `{batchOutputPath}` / `{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 template, registry chain, batch output dir) or wire in a post-completion hook (git-add, register, notify) without forking the skill.
98
+
99
+ **Apply the array surfaces** so the declared overrides are not silent no-ops: execute each entry in `workflow.activation_steps_prepend` in order now; treat every entry in `workflow.persistent_facts` as standing context for the whole run (`file:`-prefixed entries are paths or globs whose contents load as facts — the bundled default loads any `project-context.md`); then, after activation completes and before the first stage runs, execute each entry in `workflow.activation_steps_append` in order.
144
100
 
145
101
  4. **Parse CLI overrides** — capture optional override flags into the workflow context as `{overrides}`. Each override is opt-in; when omitted, the workflow runs as today.
146
102
 
@@ -156,9 +112,3 @@ so consumers that hardcode the `-latest.json` path see a deterministic file even
156
112
  5. **If `--batch` is set**, force `{headless_mode} = true` (log "headless: coerced by --batch" if it was false), then load and read `references/batch-mode.md` in full before proceeding. Follow its protocol to read the batch file, parse the target list, and drive the batch loop that wraps the step 1 → step 7 pipeline that follows.
157
113
 
158
114
  6. Load, read the full file, and then execute `references/resolve-target.md` to begin the workflow. (In batch mode, control returns here for each subsequent target after step 7 completes; see `references/batch-mode.md`.)
159
-
160
- ## Batch Mode
161
-
162
- When `--batch <file>` is supplied, quick-skill processes a list of targets from a text file in sequence rather than a single argument.
163
-
164
- See `references/batch-mode.md` for the full protocol (input format, execution loop, summary contract, headless events, exit code).
@@ -1,6 +1,8 @@
1
1
  # DO NOT EDIT -- overwritten on every update.
2
2
  #
3
3
  # Workflow customization surface for skf-quick-skill.
4
+ # Team overrides: _bmad/custom/skf-quick-skill.toml (under {project-root})
5
+ # Personal overrides: _bmad/custom/skf-quick-skill.user.toml (under {project-root})
4
6
 
5
7
  [workflow]
6
8
 
@@ -42,3 +44,10 @@ persistent_facts = [
42
44
  skill_template_path = ""
43
45
  registry_resolution_path = ""
44
46
  batch_output_path = ""
47
+
48
+ # Optional post-completion hook. When non-empty, invoked with
49
+ # `--skill-package=<path>` after the result contract is finalized in step 6.
50
+ # Failures are logged but never fail the workflow. Use for git-add,
51
+ # skill-registry registration, or a notifier on the freshly compiled skill.
52
+
53
+ on_complete = ""
@@ -6,7 +6,7 @@ nextStepFile: 'resolve-target.md'
6
6
 
7
7
  # Batch Mode
8
8
 
9
- When `--batch <file>` is supplied, quick-skill processes a list of targets from a text file in sequence rather than a single target from arguments. Designed for unattended bulk runs (CI pipelines, mass-rebuilds, the skf-batch-skills meta-workflow when it lands).
9
+ When `--batch <file>` is supplied, quick-skill processes a list of targets from a text file in sequence rather than a single target from arguments. Designed for unattended bulk runs CI pipelines, mass-rebuilds, and batch meta-workflows.
10
10
 
11
11
  ## Input format
12
12
 
@@ -43,17 +43,19 @@ Per-line modifiers shadow the global `--description` / `--exports` / `--skip-sni
43
43
  3. After step 7 completes (success or HARD HALT), record the per-target outcome (target, status, exit_code, skill_package, error.code) into the batch result list.
44
44
  4. If `--fail-fast` is set and the target failed, exit the batch loop immediately. Otherwise continue with the next target.
45
45
 
46
- Per-target output lands in `{skill_package}/` as today, with the per-target result contract at `{skill_package}/quick-skill-result-latest.json` (success or error variant per "Result Contract on HARD HALT" above).
46
+ Per-target output lands in `{skill_package}/` as today, with the per-target result contract at `{skill_package}/quick-skill-result-latest.json` (success or error variant per `references/halt-contract.md`).
47
47
 
48
48
  ## Batch summary contract
49
49
 
50
50
  After the last target completes (or `--fail-fast` triggers an early exit), write the batch summary at:
51
51
 
52
52
  ```
53
- {skills_output_folder}/_batch/quick-skill-batch-{YYYYMMDD-HHmmss}.json
54
- {skills_output_folder}/_batch/quick-skill-batch-latest.json (copy, not symlink)
53
+ {batchOutputPath}quick-skill-batch-{YYYYMMDD-HHmmss}.json
54
+ {batchOutputPath}quick-skill-batch-latest.json (copy, not symlink)
55
55
  ```
56
56
 
57
+ `{batchOutputPath}` is resolved at SKILL.md On Activation §3 from `workflow.batch_output_path` (bundled default `{skills_output_folder}/_batch/`, trailing slash included).
58
+
57
59
  Schema:
58
60
 
59
61
  ```json
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  nextStepFile: 'write-and-validate.md'
3
- skillTemplateData: 'assets/skill-template.md'
3
+ skillTemplateData: '{skillTemplatePath}'
4
4
  quickMetadataRendererProbeOrder:
5
5
  - '{project-root}/_bmad/skf/shared/scripts/skf-render-quick-metadata.py'
6
6
  - '{project-root}/src/shared/scripts/skf-render-quick-metadata.py'
@@ -20,7 +20,7 @@ To assemble the best-effort SKILL.md document, context-snippet.md in Vercel-alig
20
20
  - Follow template structure exactly from {skillTemplateData}
21
21
  - Mark any sections with insufficient data as best-effort
22
22
 
23
- ## MANDATORY SEQUENCE
23
+ ## Steps
24
24
 
25
25
  ### 1. Load Skill Template
26
26
 
@@ -31,57 +31,28 @@ Load {skillTemplateData} to understand:
31
31
 
32
32
  ### 2. Assemble SKILL.md
33
33
 
34
- Using the template structure, populate each section from extraction_inventory:
34
+ Populate the SKILL.md section structure from `{skillTemplateData}` § "SKILL.md Section Structure" (the frontmatter skeleton and the Required/Optional section list live there) using extraction_inventory. The rules below are the deltas the template does not encode:
35
35
 
36
- **Frontmatter (REQUIRED — agentskills.io compliance):**
37
-
38
- The SKILL.md MUST begin with YAML frontmatter:
39
-
40
- ```yaml
41
- ---
42
- name: {skill_name}
43
- description: >
44
- {Trigger-optimized description from extraction_inventory.description.
45
- 1-1024 chars. Include what it does, when to use it, and what NOT to use it for.}
46
- ---
47
- ```
48
-
49
- **Frontmatter rules:**
36
+ **Frontmatter rules (agentskills.io compliance):**
50
37
  - `name`: lowercase alphanumeric + hyphens only, must match the skill output directory name. Prefer gerund form (`processing-pdfs`) for clarity.
51
- - `description`: non-empty, max 1024 chars, optimized for agent discovery. MUST use third-person voice ("Processes..." not "I can..." or "You can...").
38
+ - `description`: non-empty, max 1024 chars, optimized for agent discovery. Use third-person voice ("Processes..." not "I can..." / "You can...") so it reads correctly in the agent's skill index.
52
39
  - No other frontmatter fields — only `name` and `description` for community skills
53
40
 
54
- **Required sections (after frontmatter):**
55
- - **Overview:** Package name, repository, language, source authority, generation date
41
+ **Per-section override wiring:**
56
42
  - **Description:** From `{overrides.description}` if set (subject to the same length/voice checks as extracted descriptions); otherwise from extraction_inventory.description (README-derived)
57
43
  - **Key Exports:** From `{overrides.exports}` if set (comma-separated names parsed and trimmed; empty items skipped); otherwise from extraction_inventory.exports — list each with name, type, brief description
58
- - **Usage Patterns:** From extraction_inventory.usage_patterns (README examples)
59
44
 
60
- **Optional sections (include when data available):**
61
- - **Configuration:** If configuration options were found in source
62
- - **Dependencies:** Key dependencies from manifest
63
- - **Notes:** Caveats, limitations, extraction confidence level
64
- - **Scripts & Assets Note** (if source contains `scripts/`, `bin/`, `assets/`, `templates/`, or `schemas/` directories): "This package may include scripts and assets. Run create-skill for full extraction with provenance tracking."
45
+ **Scripts & Assets Note** (add as an optional section if source contains `scripts/`, `bin/`, `assets/`, `templates/`, or `schemas/` directories): "This package may include scripts and assets. Run create-skill for full extraction with provenance tracking."
65
46
 
66
- **If confidence is low:**
67
- - Include a note: "This skill was generated with limited source data. Consider running create-skill for a more thorough compilation."
47
+ **If confidence is low** — include a note: "This skill was generated with limited source data. Consider running create-skill for a more thorough compilation."
68
48
 
69
49
  ### 3. Generate Context Snippet
70
50
 
71
51
  **If `{overrides.skip_snippet}` is true** — skip generation and note in the §5 preview: "context-snippet.md skipped per `--skip-snippet` override." Step-05 §2 will skip the corresponding write; step 5 §5 advisory snippet validation will report a "skipped" entry.
72
52
 
73
- Otherwise, create context-snippet.md in Vercel-aligned indexed format (~80-120 tokens):
53
+ Otherwise, produce context-snippet.md in the Vercel-aligned indexed format from `{skillTemplateData}` § "context-snippet.md Format" (~80-120 tokens).
74
54
 
75
- ```
76
- [{skill_name} v{version}]|root: skills/{skill_name}/
77
- |IMPORTANT: {skill_name} v{version} — read SKILL.md before writing {skill_name} code. Do NOT rely on training data.
78
- |quick-start:{SKILL.md#usage-patterns}
79
- |api: {top-5 exports with () for functions}
80
- |key-types:{SKILL.md#key-exports} — {inline summary of most important type values}
81
- |gotchas: {2-3 most critical pitfalls or breaking changes, inline}
82
- ```
83
-
84
- The anchors point to the QS template's actual headings — `#usage-patterns` (Usage Patterns) and `#key-exports` (Key Exports). The QS template has no `## Quick Start` / `## Key Types` headings (those are Deep-tier sections), so the Deep-tier anchors `#quick-start` / `#key-types` would dangle. If the assembled SKILL.md is missing the referenced heading, omit that line rather than emit a dangling anchor.
55
+ The snippet anchors point to the QS template's actual headings — `#usage-patterns` (Usage Patterns) and `#key-exports` (Key Exports). The QS template has no `## Quick Start` / `## Key Types` headings (those are Deep-tier sections), so the Deep-tier anchors `#quick-start` / `#key-types` would dangle. If the assembled SKILL.md is missing the referenced heading, omit that line rather than emit a dangling anchor.
85
56
 
86
57
  **If fewer than 5 exports:** Use all available exports.
87
58
  **If no exports:** Omit the api line.
@@ -91,7 +62,7 @@ The anchors point to the QS template's actual headings — `#usage-patterns` (Us
91
62
 
92
63
  Run the shared renderer against the assembled state. The helper applies the constants, echoes input-derived fields, computes export counts and the ISO 8601 UTC timestamp, and emits the canonical envelope per `{skillTemplateData}` § "metadata.json Format".
93
64
 
94
- **Resolve `{quickMetadataRenderer}`** from `{quickMetadataRendererProbeOrder}`; first existing path wins. If no candidate exists, fall back to in-prompt rendering using the constants + input-derived rules previously documented in this section (the helper replaces but does not eliminate those rules — they live in the helper now).
65
+ **Resolve `{quickMetadataRenderer}`** from `{quickMetadataRendererProbeOrder}`; first existing path wins. If no candidate exists, fall back to in-prompt rendering of the canonical envelope per `{skillTemplateData}` § "metadata.json Format".
95
66
 
96
67
  **Probe `tool_versions.skf` first** (the helper expects it as input — the filesystem walk stays here because the helper does no I/O):
97
68
 
@@ -108,8 +79,6 @@ echo '{"name":"<name>","version":"<v>","description":"<desc>","language":"<lang>
108
79
 
109
80
  The renderer emits the rendered metadata.json on stdout. Capture the output as `metadata` for the §5 preview and step 5 §2's deliverable write.
110
81
 
111
- **Schema is canonical in the renderer.** When `{skillTemplateData}` adds a field, the renderer is updated to populate it (constants gain a row; input-derived fields gain a payload key). Do not hand-edit the rendered envelope here — the helper is the single source of truth for the population logic.
112
-
113
82
  ### 5. Present Compiled Output for Review
114
83
 
115
84
  **If `{headless_mode}` is true** — skip the inline preview (no human reviewer reads it) and emit a one-line summary instead:
@@ -156,18 +125,12 @@ Display: **Select:** [C] Continue to Validation · [E] Edit description · [S] A
156
125
  - **IF C** — Load, read entire file, then execute {nextStepFile}.
157
126
  - **IF E** — Ask the user for a replacement description ("New description (1–1024 chars):"). Update SKILL.md frontmatter `description` and `metadata.json.description` in the in-memory compiled output, then re-render the §5 preview and redisplay this menu. Do not re-run extraction.
158
127
  - **IF S** — Ask the user for an adjusted `scope_hint` ("New scope (e.g. `src/server/`, `packages/core/`):") and optionally a `language_hint`. Update the extraction context with the new hints, then load `quick-extract.md` to re-extract. The new extraction returns to §1 of this step on completion. Discards the prior compiled output.
159
- - **IF Q** — HARD HALT with **exit code 6 (user-cancelled)** per the SKILL.md exit-code map: "Compilation cancelled. No files written." Before exiting, emit the error result contract per SKILL.md "Result Contract on HARD HALT" (`phase: "compile"`, `error.code: "user-cancelled"`, `skill_package: null`). Do not proceed to validation; do not write any artifacts.
128
+ - **IF Q** — HARD HALT with **exit code 6 (user-cancelled)** per the exit-code map in `references/halt-contract.md`: "Compilation cancelled. No files written." Before exiting, emit the error result contract per `references/halt-contract.md` (`phase: "compile"`, `error.code: "user-cancelled"`, `skill_package: null`). Do not proceed to validation; do not write any artifacts.
160
129
  - **IF Any other** — Help the user adjust the compiled output (treated as a free-form revision request), then redisplay the menu.
161
130
 
162
- #### EXECUTION RULES:
131
+ #### Gate:
163
132
 
164
- - ALWAYS halt and wait for user input after presenting compiled output
133
+ - Halt and wait for user input after presenting the compiled output; only [C] (or a headless auto-approve) chains to `{nextStepFile}` for validation.
165
134
  - **GATE [default: C]** — If `{headless_mode}`: auto-proceed with [C] Continue, log: "headless: auto-approve compiled output"
166
- - ONLY proceed to validation when the user selects 'C' (or headless auto-approve)
167
- - [E] is local: re-renders the preview without re-running extraction
168
- - [S] is the heavy option: it discards the compiled output and re-runs step 3 with new hints
169
-
170
- ## CRITICAL STEP COMPLETION NOTE
171
-
172
- ONLY WHEN the user reviews the compiled output and selects 'C' (or [Q] HALTs / [S] re-runs / [E] redisplays) will you load and read fully `{nextStepFile}` to execute validation.
135
+ - [E] re-renders the preview without re-running extraction; [S] discards the compiled output and re-runs step 3 with new hints.
173
136
 
@@ -12,11 +12,10 @@ To query the agentskills.io ecosystem for an existing official skill matching th
12
12
 
13
13
  ## Rules
14
14
 
15
- - This check is advisory — never block the workflow on failure
16
15
  - 5-second timeout on ecosystem queries; tool unavailability is a silent skip, not an error
17
16
  - Do not begin extraction or compilation
18
17
 
19
- ## MANDATORY SEQUENCE
18
+ ## Steps
20
19
 
21
20
  ### 1. Query Ecosystem
22
21
 
@@ -54,34 +53,20 @@ An official skill already exists. You can:
54
53
  **[I] Install** — Install the existing official skill instead (exits this workflow)
55
54
  **[A] Abort** — Cancel compilation"
56
55
 
57
- ### 3. Handle Match Menu (ONLY if match found)
56
+ ### 3. Handle Match Menu (only when a match was found)
58
57
 
59
58
  #### Menu Handling Logic:
60
59
 
61
60
  - IF P: Set `ecosystem_status: match-proceed`, then load, read entire file, then execute {nextStepFile}
62
- - IF I: Display install instructions for the official skill, emit the HARD HALT envelope per SKILL.md "Result Contract on HARD HALT" (`phase: "ecosystem-check"`, `error.code: "ecosystem-redirect"`, `error.message: "User opted to install existing official skill instead of compiling a custom community skill."`, `skill_package: null`), exit with code 8 (ecosystem-redirect). Skill package is unknown at this phase — no on-disk result file is written.
61
+ - IF I: Display install instructions for the official skill, emit the HARD HALT envelope per `references/halt-contract.md` (`phase: "ecosystem-check"`, `error.code: "ecosystem-redirect"`, `error.message: "User opted to install existing official skill instead of compiling a custom community skill."`, `skill_package: null`), exit with code 8 (ecosystem-redirect). Skill package is unknown at this phase — no on-disk result file is written.
63
62
  - IF A: Display "Compilation cancelled.", emit the HARD HALT envelope (`phase: "ecosystem-check"`, `error.code: "user-cancelled"`, `error.message: "User aborted at ecosystem-match gate."`, `skill_package: null`), exit with code 6 (user-cancelled). Skill package is unknown at this phase — no on-disk result file is written.
64
63
  - IF Any other: help user, then redisplay the match menu
65
64
 
66
- #### EXECUTION RULES:
65
+ #### Gate:
67
66
 
68
- - ONLY display this menu when ecosystem_status is match
69
- - ALWAYS halt and wait for user input when match is found
70
67
  - **GATE [default: P]** — If `{headless_mode}` and match found: auto-proceed with [P] Proceed (compile custom skill anyway), log: "headless: ecosystem match found, auto-proceeding with custom compilation"
71
- - For no-match and skip cases, auto-proceed without menu
72
68
 
73
69
  ### 4. Auto-Proceed (No Match or Skip)
74
70
 
75
- #### Menu Handling Logic:
76
-
77
- - After no-match or skip determination, immediately load, read entire file, then execute {nextStepFile}
78
-
79
- #### EXECUTION RULES:
80
-
81
- - This is an auto-proceed path — no user interaction needed
82
- - Proceed directly to extraction step
83
-
84
- ## CRITICAL STEP COMPLETION NOTE
85
-
86
- ONLY WHEN ecosystem check completes (match with user choice, no-match, or skip) will you load and read fully `{nextStepFile}` to proceed to source extraction.
71
+ For no-match and skip, load and execute {nextStepFile} to proceed to source extraction.
87
72