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,258 @@
1
+ #!/usr/bin/env python3
2
+ # /// script
3
+ # requires-python = ">=3.10"
4
+ # dependencies = []
5
+ # ///
6
+ """Deterministic overall-feasibility verdict rollup for skf-verify-stack (synthesize.md §1).
7
+
8
+ Deciding each individual finding — is this integration Blocked, is that technology
9
+ Missing, is a requirement Not Addressed — is judgment and happens upstream in
10
+ Steps 02-04, persisted to the report frontmatter/tables. Rolling those already-decided
11
+ counts up into the single overall verdict is *not* judgment: it is a fixed threshold
12
+ ladder with one correct answer per input. Walking a five-tier ordered ladder (with a
13
+ short-circuit, a downgrade rule, and a post-verdict guard) in-prompt lets the headline
14
+ verdict drift between runs, so the token computation lives here. The rationale prose —
15
+ which co-occurring problems to name, how to phrase the recommendation — stays in the
16
+ prompt; this script emits only the token plus the stable condition codes the prompt
17
+ cites when it writes that rationale.
18
+
19
+ The ladder (exactly mirrors synthesize.md §1; evaluate top-to-bottom, first match wins):
20
+
21
+ 1. Zero-coverage short-circuit — coveragePercentage == 0 -> NOT_FEASIBLE
22
+ (no live coverage: analysis is vacuous; the remainder of the ladder is skipped).
23
+ 2. NOT_FEASIBLE — any integration Blocked (pairsBlocked > 0).
24
+ 3. CONDITIONALLY_FEASIBLE — ANY of: a Missing technology (missingCount > 0),
25
+ a Risky integration (pairsRisky > 0), or — only when the requirements pass ran —
26
+ a Not Addressed or Partially Fulfilled requirement.
27
+ 4. FEASIBLE — none of the above AND zero pairs capped at
28
+ Plausible (pairsPlausible == 0). If any pair sits at Plausible, downgrade to
29
+ CONDITIONALLY_FEASIBLE.
30
+
31
+ Post-verdict zero-integration-pairs guard (applied after ANY verdict): when all four
32
+ integration counts are 0 AND the user continued past a step-2 zero-state [C] gate,
33
+ the guard fires — a FEASIBLE verdict is overridden to CONDITIONALLY_FEASIBLE, and
34
+ regardless of verdict the prompt appends the "no integration claims found" note.
35
+
36
+ Note that coveragePercentage and missingCount are independent inputs on purpose: half-up
37
+ rounding means a stack with covered=199, missing=1 rounds to coveragePercentage == 100
38
+ while missingCount is still > 0, so the Missing trigger reads missingCount directly.
39
+
40
+ CLI usage:
41
+ uv run skf-verdict-rollup.py '<JSON>' # JSON literal positional
42
+ uv run skf-verdict-rollup.py --json-input '<JSON>' # explicit flag form
43
+ cat input.json | uv run skf-verdict-rollup.py --stdin # piped input
44
+
45
+ Input schema (one object; counts come straight from the report frontmatter/tables):
46
+ {
47
+ "coveragePercentage": <int 0..100>, # from coverage.md (coverage-tally)
48
+ "missingCount": <int>, # Missing technologies (Replaced excluded)
49
+ "pairsBlocked": <int>, # from integrations.md
50
+ "pairsRisky": <int>,
51
+ "pairsPlausible": <int>, # includes Check-4-missing caps
52
+ "pairsVerified": <int>,
53
+ "requirementsEvaluated": <bool>, # optional (default false): requirementsPass == "completed"
54
+ "requirementsNotAddressed": <int>, # optional (default 0); ignored unless evaluated
55
+ "requirementsPartial": <int>, # optional (default 0); ignored unless evaluated
56
+ "continuedPastZeroState": <bool> # optional (default false): user pressed [C] past a step-2 zero-state gate
57
+ }
58
+
59
+ Output (stdout, one object):
60
+ {
61
+ "overallVerdict": "FEASIBLE" | "CONDITIONALLY_FEASIBLE" | "NOT_FEASIBLE",
62
+ "matchedConditions": [<condition codes, in ladder order>],
63
+ "zeroPairsGuardFired": <bool>
64
+ }
65
+
66
+ Condition codes (stable; the prompt cites these when synthesizing the rationale):
67
+ zero-coverage · blocked-integration · missing-coverage · risky-integration ·
68
+ requirements-not-addressed · requirements-partial · plausible-cap · zero-integration-pairs
69
+
70
+ Exit codes:
71
+ 0 — verdict emitted successfully
72
+ 1 — no input / input could not be parsed as JSON
73
+ 2 — input parsed but schema/semantics invalid (error object emitted as JSON)
74
+ """
75
+
76
+ from __future__ import annotations
77
+
78
+ import argparse
79
+ import json
80
+ import sys
81
+
82
+ VERDICTS = ("FEASIBLE", "CONDITIONALLY_FEASIBLE", "NOT_FEASIBLE")
83
+ REQUIRED_COUNTS = (
84
+ "missingCount",
85
+ "pairsBlocked",
86
+ "pairsRisky",
87
+ "pairsPlausible",
88
+ "pairsVerified",
89
+ )
90
+ OPTIONAL_COUNTS = ("requirementsNotAddressed", "requirementsPartial")
91
+
92
+
93
+ def make_error(message):
94
+ return {"error": message, "code": "INVALID_INPUT"}
95
+
96
+
97
+ def _is_nonneg_int(value):
98
+ # bool is a subclass of int; reject it so a stray true/false can't pose as a count.
99
+ return isinstance(value, int) and not isinstance(value, bool) and value >= 0
100
+
101
+
102
+ def _validate(inp):
103
+ if inp is None or not isinstance(inp, dict):
104
+ return "Input must be a JSON object"
105
+
106
+ pct = inp.get("coveragePercentage")
107
+ if not isinstance(pct, int) or isinstance(pct, bool) or not (0 <= pct <= 100):
108
+ return "coveragePercentage must be an integer in 0..100"
109
+
110
+ for field in REQUIRED_COUNTS:
111
+ if field not in inp:
112
+ return f"missing required field: {field}"
113
+ if not _is_nonneg_int(inp[field]):
114
+ return f"{field} must be a non-negative integer"
115
+
116
+ for field in OPTIONAL_COUNTS:
117
+ if field in inp and inp[field] is not None and not _is_nonneg_int(inp[field]):
118
+ return f"{field} must be a non-negative integer when present"
119
+
120
+ for field in ("requirementsEvaluated", "continuedPastZeroState"):
121
+ if field in inp and not isinstance(inp[field], bool):
122
+ return f"{field} must be a boolean when present"
123
+
124
+ return None
125
+
126
+
127
+ def rollup(inp):
128
+ """Pure verdict rollup over the persisted counts. See module docstring for the ladder."""
129
+ err = _validate(inp)
130
+ if err:
131
+ return make_error(err)
132
+
133
+ pct = inp["coveragePercentage"]
134
+ missing = inp["missingCount"]
135
+ blocked = inp["pairsBlocked"]
136
+ risky = inp["pairsRisky"]
137
+ plausible = inp["pairsPlausible"]
138
+ verified = inp["pairsVerified"]
139
+ req_eval = bool(inp.get("requirementsEvaluated", False))
140
+ not_addressed = inp.get("requirementsNotAddressed") or 0
141
+ partial = inp.get("requirementsPartial") or 0
142
+ continued = bool(inp.get("continuedPastZeroState", False))
143
+
144
+ matched: list[str] = []
145
+
146
+ # 1. Zero-coverage short-circuit — wins over everything else.
147
+ if pct == 0:
148
+ verdict = "NOT_FEASIBLE"
149
+ matched.append("zero-coverage")
150
+ # 2. Any Blocked integration is a fundamental incompatibility.
151
+ elif blocked > 0:
152
+ verdict = "NOT_FEASIBLE"
153
+ matched.append("blocked-integration")
154
+ # Co-occurring problems the rationale should also name (§1).
155
+ if missing > 0:
156
+ matched.append("missing-coverage")
157
+ if risky > 0:
158
+ matched.append("risky-integration")
159
+ else:
160
+ # 3. Any gap / risk / unmet requirement -> conditional.
161
+ conditional: list[str] = []
162
+ if missing > 0:
163
+ conditional.append("missing-coverage")
164
+ if risky > 0:
165
+ conditional.append("risky-integration")
166
+ if req_eval and not_addressed > 0:
167
+ conditional.append("requirements-not-addressed")
168
+ if req_eval and partial > 0:
169
+ conditional.append("requirements-partial")
170
+ if conditional:
171
+ verdict = "CONDITIONALLY_FEASIBLE"
172
+ matched.extend(conditional)
173
+ elif plausible > 0:
174
+ # 4. Clean bar except for Check-4-missing caps -> downgrade.
175
+ verdict = "CONDITIONALLY_FEASIBLE"
176
+ matched.append("plausible-cap")
177
+ else:
178
+ verdict = "FEASIBLE"
179
+
180
+ # Post-verdict zero-integration-pairs guard.
181
+ zero_pairs = blocked == 0 and risky == 0 and plausible == 0 and verified == 0
182
+ guard_fired = zero_pairs and continued
183
+ if guard_fired:
184
+ if verdict == "FEASIBLE":
185
+ verdict = "CONDITIONALLY_FEASIBLE"
186
+ matched.append("zero-integration-pairs")
187
+
188
+ return {
189
+ "overallVerdict": verdict,
190
+ "matchedConditions": matched,
191
+ "zeroPairsGuardFired": guard_fired,
192
+ }
193
+
194
+
195
+ # --- CLI --------------------------------------------------------------------
196
+
197
+
198
+ def _build_parser():
199
+ parser = argparse.ArgumentParser(
200
+ prog="skf-verdict-rollup",
201
+ description=(
202
+ "Deterministic overall-feasibility verdict rollup (synthesize.md §1). "
203
+ "Consumes the persisted coverage / integration / requirements counts and "
204
+ "emits the FEASIBLE / CONDITIONALLY_FEASIBLE / NOT_FEASIBLE token plus the "
205
+ "condition codes the prompt cites in its rationale."
206
+ ),
207
+ formatter_class=argparse.RawDescriptionHelpFormatter,
208
+ epilog=(
209
+ "Example:\n"
210
+ " uv run skf-verdict-rollup.py "
211
+ "'{\"coveragePercentage\":100,\"missingCount\":0,\"pairsBlocked\":0,"
212
+ "\"pairsRisky\":0,\"pairsPlausible\":0,\"pairsVerified\":3}'"
213
+ ),
214
+ )
215
+ src = parser.add_mutually_exclusive_group()
216
+ src.add_argument("json_input", nargs="?", help="JSON object as a positional argument.")
217
+ src.add_argument("--json-input", dest="json_input_flag", help="JSON object passed via flag.")
218
+ src.add_argument("--stdin", action="store_true", help="Read the JSON object from stdin.")
219
+ return parser
220
+
221
+
222
+ def _resolve_input(args):
223
+ if args.stdin:
224
+ return sys.stdin.read()
225
+ if args.json_input_flag is not None:
226
+ return args.json_input_flag
227
+ if args.json_input is not None:
228
+ return args.json_input
229
+ return ""
230
+
231
+
232
+ def main(argv=None):
233
+ parser = _build_parser()
234
+ args = parser.parse_args(argv)
235
+ raw = _resolve_input(args)
236
+ if not raw.strip():
237
+ parser.print_usage(file=sys.stderr)
238
+ print(
239
+ "error: no input provided (positional arg, --json-input, or --stdin)",
240
+ file=sys.stderr,
241
+ )
242
+ return 1
243
+
244
+ try:
245
+ data = json.loads(raw)
246
+ except json.JSONDecodeError as exc:
247
+ print(json.dumps(make_error(f"Invalid JSON: {exc.msg}"), indent=2))
248
+ return 1
249
+
250
+ result = rollup(data)
251
+ print(json.dumps(result, indent=2))
252
+ if isinstance(result, dict) and result.get("code") == "INVALID_INPUT":
253
+ return 2
254
+ return 0
255
+
256
+
257
+ if __name__ == "__main__":
258
+ raise SystemExit(main())
@@ -356,8 +356,9 @@ class UI {
356
356
  `${chalk.white.bold('Get Started')}`,
357
357
  `1. Open this folder in ${ideDisplay}`,
358
358
  `2. Activate Ferris: ${activateLine}`,
359
- '3. Ferris (your Skill Architect) will guide you through',
360
- ' setting up and forging your first agent skill',
359
+ '3. Ferris (your Skill Architect) guides you through forge setup',
360
+ `4. Fastest first skill ask Ferris to run ${brand.gold('forge-auto <repo-or-doc-url>')}:`,
361
+ ' one command auto-scopes, compiles, tests, and exports a verified skill',
361
362
  ].join('\n');
362
363
  }
363
364
 
package/docs/deepwiki.md DELETED
@@ -1,89 +0,0 @@
1
- ---
2
- title: deepwiki
3
- description: Zero-ceremony wiki-skill creation — one command turns a GitHub repo, doc URL, or pinned version into a verified wiki skill
4
- ---
5
-
6
- deepwiki is a [pipeline alias](../workflows/#pipeline-aliases) that chains five workflows into a single command. Give it a repo URL, a documentation URL, or a pinned version, and it produces a verified wiki skill in 3–5 minutes with zero configuration.
7
-
8
- If you're new to SKF and want to try it without reading anything else, start here.
9
-
10
- ---
11
-
12
- ## Invocation
13
-
14
- Three input types, one command pattern:
15
-
16
- ```
17
- @Ferris deepwiki https://github.com/honojs/hono — repo URL
18
- @Ferris deepwiki https://docs.example.com — doc URL (docs-only)
19
- @Ferris deepwiki https://github.com/honojs/hono --pin v4.6.0 — pinned version
20
- ```
21
-
22
- - **Repo URL** — analyzes the full source repository, extracts exports, and compiles a wiki skill from code + docs.
23
- - **Doc URL** — skips source analysis entirely and builds the skill from documentation alone. Useful for closed-source libraries or when the docs are the canonical reference.
24
- - **`--pin <version>`** — targets a specific release. The version tag is resolved during analysis so the resulting skill is locked to that exact API surface.
25
-
26
- ---
27
-
28
- ## Pipeline Stages
29
-
30
- deepwiki expands to `AN[auto] BS[auto] CS TS[min:90] EX`. Each stage runs in [headless mode](../workflows/#headless-mode) — no confirmation gates, no interactive prompts.
31
-
32
- | Stage | Workflow | Mode | What Happens |
33
- |-------|----------|------|-------------|
34
- | 1 | **Analyze Source** (AN) | `[auto]` | Scans the target, detects shape (library/framework/tool/app), discovers exports, and generates a scope + brief automatically. |
35
- | 2 | **Brief Skill** (BS) | `[auto]` | Enriches the auto-generated brief with doc detection results. No interactive scoping — the brief is assembled from AN's output. |
36
- | 3 | **Create Skill** (CS) | standard | Compiles the skill from the enriched brief. Extracts exports, resolves documentation sources, validates structure. |
37
- | 4 | **Test Skill** (TS) | `[min:90]` | Verifies completeness with a **90% quality threshold** (stricter than the default 80%). Fail halts the pipeline. |
38
- | 5 | **Export Skill** (EX) | standard | Validates the package, generates context snippets, and injects into your IDE's context file. |
39
-
40
- Data flows automatically between stages — the brief path from AN feeds BS, the skill name from CS feeds TS, and so on. See [Pipeline Mode](../workflows/#pipeline-mode) for the general mechanics.
41
-
42
- ---
43
-
44
- ## Automatic Behaviors
45
-
46
- deepwiki's `[auto]` flags activate several behaviors that normally require manual input:
47
-
48
- - **Auto-scope** — shape detection (library, framework, tool, application) drives scope decisions. No interactive scope confirmation.
49
- - **Auto-brief** — the brief is generated and enriched with doc-detection results in one pass, without the interactive discovery flow that `BS` uses standalone.
50
- - **Coexistence detection** — if a skill for the same target already exists, deepwiki detects it and offers three options: create alongside (new version), merge into the existing skill, or skip.
51
- - **Auto-decomposition** — for massive repos (>500 exports or >3 packages), AN automatically decomposes into multiple analysis units before proceeding.
52
-
53
- ---
54
-
55
- ## Expected Output
56
-
57
- A successful deepwiki run produces a complete skill package in your forge data directory, exported and ready for use. The skill includes:
58
-
59
- - `SKILL.md` — the compiled wiki skill with provenance-cited instructions
60
- - `metadata.json` — version, source, confidence tier breakdown
61
- - Context snippet injected into your IDE context file (CLAUDE.md, .cursorrules, AGENTS.md, etc.)
62
-
63
- The quality threshold is 90% — if the skill scores below that, the pipeline halts at TS with a gap report. Run `@Ferris US` to address gaps, then `@Ferris TS EX` to re-test and export.
64
-
65
- ---
66
-
67
- ## Timing
68
-
69
- A typical library (50–200 exports) takes **3–5 minutes** end to end. Factors that increase time:
70
-
71
- - Massive repos (>500 exports) trigger auto-decomposition, adding 1–3 minutes
72
- - Doc-only targets depend on documentation site size and structure
73
- - Deep-tier projects (with QMD and CCC) spend more time on enrichment
74
-
75
- ---
76
-
77
- ## Migration from onboard
78
-
79
- deepwiki replaces the older `onboard` alias. `onboard` still works but shows a deprecation notice on every invocation and will be removed in v2.0.
80
-
81
- The key difference: `onboard` runs `AN CS TS EX` with standard (interactive) modes. deepwiki adds auto-scope, auto-brief, a stricter quality gate (90% vs 80%), and accepts repo URLs and doc URLs — not just project paths.
82
-
83
- ---
84
-
85
- ## Related
86
-
87
- - [Workflows](../workflows/) — pipeline mode mechanics, headless mode, circuit breakers
88
- - [Concepts](../concepts/) — provenance, confidence tiers, drift, version pinning
89
- - [BMAD Synergy](../bmad-synergy/) — how deepwiki fits into BMAD phases, and standalone SKF usage
@@ -1,110 +0,0 @@
1
- ---
2
- # Static reference loaded by execute.md §7. The carve removes ~70
3
- # lines of context-rebuild loop logic from the main execute.md so
4
- # the §1–§6 + §8–§10 critical-path stays tight; §7 itself is always
5
- # reached on the success path so this file loads on every successful
6
- # rename, but the rollback paths (§4–§6 failure jumps) skip §7
7
- # entirely and never load this reference.
8
- ---
9
-
10
- <!-- Config: communicate in {communication_language}. Render the rebuilt-files report in {document_output_language}. -->
11
-
12
- # Rename: Rebuild Context Files (per-IDE managed-section sweep)
13
-
14
- ## Purpose
15
-
16
- After §6 re-keys the manifest from `{old_name}` to `{new_name}`, every IDE's context file (`CLAUDE.md`, `.cursorrules`, `AGENTS.md`, etc.) still contains the old name in its managed-section snippet rows. This step rewrites each one in-place via the surgical between-marker swap so the on-disk managed sections reflect the new name.
17
-
18
- Loaded by `execute.md` §7 once `manifest_updated == true` (§6 succeeded) and the rollback paths in §4–§6 were not taken.
19
-
20
- ## Resolve target_context_files
21
-
22
- Load the `ides` list from `config.yaml`. The installer writes IDE identifiers — these must be mapped to context files and skill roots using the "IDE → Context File Mapping" table in `{managedSectionLogic}`:
23
-
24
- 1. For each entry in `config.yaml.ides`, look up its `context_file` and `skill_root` from the mapping table.
25
- 2. For any entry not found in the table, default to AGENTS.md / `.agents/skills/` and emit a warning: `Unknown IDE '{value}' in config.yaml — defaulting to AGENTS.md`.
26
- 3. Deduplicate by `context_file` — when multiple IDEs map to the same context file, use the first configured IDE's `skill_root`.
27
- 4. If `config.yaml.ides` is absent or the mapping yields an empty list, fall back to `[{context_file: "AGENTS.md", skill_root: ".agents/skills/"}]` and emit a note: `No IDEs configured in config.yaml — defaulting to AGENTS.md`.
28
-
29
- Store the result as `target_context_files`.
30
-
31
- ## Per-file loop
32
-
33
- For each entry in `target_context_files`:
34
-
35
- ### 1. Resolve target file
36
-
37
- Resolve the absolute path at `{context_file}`.
38
-
39
- ### 2. Read the current file
40
-
41
- - If the file does not exist, skip this context file (nothing to rebuild — the file will be re-created the next time export-skill runs).
42
- - If the file exists but contains no `<!-- SKF:BEGIN -->` marker, skip this context file (no managed section to rewrite).
43
- - If the file contains `<!-- SKF:BEGIN -->` but no matching `<!-- SKF:END -->`, record the error against that context file and continue to the next entry — do not halt the entire rename on a malformed context file.
44
-
45
- ### 3. Build the exported skill set (version-aware, deprecated-excluded)
46
-
47
- Use the same logic as `skf-export-skill/references/update-context.md` §4b and the snippet resolution from §4c:
48
-
49
- - Read the manifest's `exports` object (already updated in §6, so `{new_name}` is present and `{old_name}` is absent).
50
- - For each skill, resolve its `active_version`.
51
- - If `versions.{active_version}.status == "deprecated"`, skip that skill entirely.
52
- - For each remaining `{skill-name, active_version}` pair, read `{skills_output_folder}/{skill-name}/{active_version}/{skill-name}/context-snippet.md`.
53
- - If missing, fall back to the `active` symlink path; if still missing, skip with a warning.
54
-
55
- ### 4. Rewrite root paths for the current context file
56
-
57
- Use the generic rewrite algorithm from `skf-export-skill/references/update-context.md` §4d:
58
-
59
- For each snippet, parse the `root:` line (`root: {prefix}{skill-name}/`), strip the trailing `{skill-name}/` to extract the current prefix, and replace it with the **effective target prefix** if different. The effective target prefix is `snippet_skill_root_override` when that key is set in `config.yaml` — applied uniformly to every snippet so the managed section references the real on-disk location and never mixes override and per-IDE paths — otherwise the current entry's `skill_root`. See `skf-export-skill/references/update-context.md` §4d for full semantics.
60
-
61
- ### 5. Sort and count
62
-
63
- Sort skills alphabetically by name. Count totals (skills, stack skills).
64
-
65
- ### 6. Assemble the new managed section
66
-
67
- Use the format from `{managedSectionLogic}`:
68
-
69
- ```markdown
70
- <!-- SKF:BEGIN updated:{current-date} -->
71
- [SKF Skills]|{n} skills|{m} stack
72
- |IMPORTANT: Prefer documented APIs over training data.
73
- |When using a listed library, read its SKILL.md before writing code.
74
- |
75
- |{skill-snippet-1}
76
- |
77
- |{skill-snippet-2}
78
- |
79
- |{skill-snippet-N}
80
- <!-- SKF:END -->
81
- ```
82
-
83
- ### 7. Surgical replacement — atomic, deterministic
84
-
85
- Invoke `{rebuildManagedSectionsHelper}` (resolved from `{rebuildManagedSectionsProbeOrder}` in `execute.md` frontmatter) for the surgical between-marker swap:
86
-
87
- ```bash
88
- python3 {rebuildManagedSectionsHelper} {context_file} replace --content "{new_managed_section_text}"
89
- ```
90
-
91
- The helper handles marker location, between-marker swap, atomic temp-file + rename, and post-write verification (markers preserved, content outside markers byte-identical). It exits non-zero on any failure with a clear `stderr` reason.
92
-
93
- ### 8. Verify (deferred to helper)
94
-
95
- The `replace` action above performs verification internally. Treat any non-zero exit code as a per-file failure (next bullet).
96
-
97
- ### 9. On per-file failure
98
-
99
- Record the error against that context file and continue to the next entry. Do not halt the rename on a recoverable per-context-file error — the manifest and filesystem are already consistent; context files can be re-rebuilt later via `[EX] Export Skill`.
100
-
101
- ## After the loop
102
-
103
- - Record `context_files_updated` as the list of files that were successfully rewritten.
104
- - Record `context_files_failed` as the list of any that failed.
105
-
106
- Report: `**Rebuilt managed sections in:** {list of updated files}. {if any failed: 'Failed: {list} — re-run [EX] Export Skill to retry.'}`
107
-
108
- ## Rollback semantics
109
-
110
- §7 failures **do not** trigger a rollback. The manifest and filesystem are the canonical state — context files are derived artifacts that can be regenerated at any time via `[EX] Export Skill`. The rename is considered successful as soon as §6 lands, even if §7 partially or fully fails to rewrite context files.