bmad-module-skill-forge 1.9.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/README.md +10 -5
  3. package/docs/_data/pinned.yaml +2 -2
  4. package/docs/agents.md +11 -2
  5. package/docs/architecture.md +5 -4
  6. package/docs/bmad-synergy.md +30 -7
  7. package/docs/campaign.md +172 -0
  8. package/docs/examples.md +7 -3
  9. package/docs/forge-auto.md +90 -0
  10. package/docs/getting-started.md +9 -0
  11. package/docs/how-it-works.md +6 -4
  12. package/docs/index.md +4 -3
  13. package/docs/skill-model.md +1 -1
  14. package/docs/troubleshooting.md +17 -1
  15. package/docs/verifying-a-skill.md +2 -2
  16. package/docs/why-skf.md +1 -1
  17. package/docs/workflows.md +64 -24
  18. package/package.json +2 -2
  19. package/src/module-help.csv +2 -1
  20. package/src/shared/data/language-corpora.json +32 -0
  21. package/src/shared/references/pipeline-contracts.md +6 -3
  22. package/src/shared/scripts/schemas/skill-brief.v1.json +6 -1
  23. package/src/shared/scripts/skf-derive-assembly-shape.py +107 -0
  24. package/src/shared/scripts/skf-detect-docs.py +8 -3
  25. package/src/shared/scripts/skf-detect-language.py +5 -3
  26. package/src/shared/scripts/skf-emit-result-envelope.py +17 -0
  27. package/src/shared/scripts/skf-extract-public-api.py +53 -0
  28. package/src/shared/scripts/skf-language-corpora.py +100 -0
  29. package/src/shared/scripts/skf-merge-doc-urls.py +244 -0
  30. package/src/shared/scripts/skf-preapply.py +1 -1
  31. package/src/shared/scripts/skf-shape-detect.py +576 -25
  32. package/src/shared/scripts/skf-validate-brief-schema.py +2 -5
  33. package/src/shared/scripts/skf-validate-pins.py +2 -2
  34. package/src/shared/scripts/skf-write-skill-brief.py +21 -5
  35. package/src/skf-analyze-source/SKILL.md +1 -1
  36. package/src/skf-analyze-source/assets/skill-brief-schema.md +1 -1
  37. package/src/skf-analyze-source/references/step-auto-scope.md +196 -44
  38. package/src/skf-analyze-source/references/step-shape-detect.md +20 -13
  39. package/src/skf-audit-skill/references/init.md +1 -1
  40. package/src/skf-brief-skill/assets/skill-brief-schema.md +1 -1
  41. package/src/skf-brief-skill/references/analyze-target.md +7 -4
  42. package/src/skf-brief-skill/references/confirm-brief.md +0 -1
  43. package/src/skf-brief-skill/references/gather-intent.md +8 -2
  44. package/src/skf-brief-skill/references/scope-definition.md +2 -1
  45. package/src/skf-brief-skill/references/step-auto-brief.md +21 -4
  46. package/src/skf-brief-skill/references/step-auto-validate.md +2 -2
  47. package/src/skf-brief-skill/references/write-brief.md +2 -3
  48. package/src/skf-campaign/SKILL.md +190 -0
  49. package/src/skf-campaign/assets/campaign-state-schema.json +191 -0
  50. package/src/skf-campaign/customize.toml +73 -0
  51. package/src/skf-campaign/manifest.yaml +11 -0
  52. package/src/skf-campaign/references/campaign-directive-spec.md +121 -0
  53. package/src/skf-campaign/references/health-check.md +35 -0
  54. package/src/skf-campaign/references/step-01-setup.md +122 -0
  55. package/src/skf-campaign/references/step-02-strategy.md +97 -0
  56. package/src/skf-campaign/references/step-03-pins.md +56 -0
  57. package/src/skf-campaign/references/step-04-provenance.md +63 -0
  58. package/src/skf-campaign/references/step-05-skill-loop.md +103 -0
  59. package/src/skf-campaign/references/step-06-batch.md +87 -0
  60. package/src/skf-campaign/references/step-07-capstone.md +63 -0
  61. package/src/skf-campaign/references/step-08-verify.md +75 -0
  62. package/src/skf-campaign/references/step-09-refine.md +83 -0
  63. package/src/skf-campaign/references/step-10-export.md +106 -0
  64. package/src/skf-campaign/references/step-11-maintenance.md +84 -0
  65. package/src/skf-campaign/references/step-resume.md +114 -0
  66. package/src/skf-campaign/scripts/.gitkeep +0 -0
  67. package/src/skf-campaign/scripts/campaign-deps.py +235 -0
  68. package/src/skf-campaign/scripts/campaign-parse-manifest.py +119 -0
  69. package/src/skf-campaign/scripts/campaign-provenance.py +247 -0
  70. package/src/skf-campaign/scripts/campaign-render-kickoff.py +158 -0
  71. package/src/skf-campaign/scripts/campaign-report.py +249 -0
  72. package/src/skf-campaign/scripts/campaign-validate-pins.py +174 -0
  73. package/src/skf-campaign/scripts/campaign-validate-state.py +207 -0
  74. package/src/skf-campaign/templates/campaign-brief-template.yaml +34 -0
  75. package/src/skf-campaign/templates/campaign-report-template.md +54 -0
  76. package/src/skf-campaign/templates/kickoff-template.md +48 -0
  77. package/src/skf-create-skill/SKILL.md +1 -1
  78. package/src/skf-create-skill/assets/compile-assembly-rules.md +22 -0
  79. package/src/skf-create-skill/references/compile.md +4 -1
  80. package/src/skf-create-skill/references/extract.md +9 -1
  81. package/src/skf-create-skill/references/extraction-patterns.md +3 -1
  82. package/src/skf-create-skill/references/generate-artifacts.md +11 -2
  83. package/src/skf-create-skill/references/health-check.md +2 -2
  84. package/src/skf-create-skill/references/report.md +17 -1
  85. package/src/skf-create-skill/references/source-resolution-protocols.md +1 -1
  86. package/src/skf-create-skill/references/step-doc-rot.md +4 -4
  87. package/src/skf-create-skill/references/step-doc-sources.md +11 -2
  88. package/src/skf-create-skill/references/sub/fetch-docs.md +29 -0
  89. package/src/skf-create-skill/references/validate.md +12 -3
  90. package/src/skf-drop-skill/SKILL.md +2 -2
  91. package/src/skf-drop-skill/references/execute.md +20 -9
  92. package/src/skf-drop-skill/references/report.md +2 -0
  93. package/src/skf-drop-skill/references/select.md +7 -2
  94. package/src/skf-forger/SKILL.md +12 -7
  95. package/src/skf-refine-architecture/SKILL.md +2 -1
  96. package/src/skf-refine-architecture/references/compile.md +1 -1
  97. package/src/skf-refine-architecture/references/report.md +1 -1
  98. package/src/skf-rename-skill/SKILL.md +2 -2
  99. package/src/skf-rename-skill/references/execute.md +5 -4
  100. package/src/skf-rename-skill/references/rebuild-context.md +2 -2
  101. package/src/skf-rename-skill/references/select.md +3 -3
  102. package/src/skf-setup/SKILL.md +1 -1
  103. package/src/skf-setup/references/auto-index.md +3 -1
  104. package/src/skf-setup/references/detect-and-tier.md +4 -0
  105. package/src/skf-setup/references/report.md +4 -1
  106. package/src/skf-setup/references/tier-rules.md +1 -1
  107. package/src/skf-test-skill/references/coverage-check.md +10 -0
  108. package/src/skf-test-skill/references/init.md +1 -1
  109. package/src/skf-test-skill/references/source-access-protocol.md +13 -3
  110. package/src/skf-test-skill/scripts/compute-score.py +4 -3
  111. package/src/skf-update-skill/customize.toml +0 -9
  112. package/src/skf-update-skill/references/detect-changes.md +33 -3
  113. package/src/skf-update-skill/references/health-check.md +2 -2
  114. package/src/skf-update-skill/references/init.md +1 -0
  115. package/src/skf-update-skill/references/re-extract.md +15 -1
  116. package/src/skf-verify-stack/references/report.md +1 -1
  117. package/tools/cli/lib/ui.js +3 -2
  118. package/docs/deepwiki.md +0 -89
@@ -91,6 +91,7 @@ Load and read {tierRulesData} for the tier capability descriptions and re-run me
91
91
  CCC Index:
92
92
  {if ccc_index_result is "fresh": up to date — semantic discovery ready}
93
93
  {if ccc_index_result is "created": indexed this run — semantic discovery ready}
94
+ {if ccc_index_result is "skipped": skipped (--ccc-skip-index) — run `/skf-setup` without --ccc-skip-index to build the index when you're ready}
94
95
  {if ccc_index_result is "failed": indexing failed — semantic discovery unavailable this session}
95
96
  {end if}
96
97
 
@@ -126,6 +127,7 @@ Load and read {tierRulesData} for the tier capability descriptions and re-run me
126
127
 
127
128
  {if {tier_changed} is false and {tools_added} is empty and {tools_removed} is empty and {previous_tier} is non-null:}
128
129
  {same-tier message from tier-rules.md}
130
+ {if preferences_yaml_created is false and (ccc_index_result is "fresh" or ccc_index_result is "none" or ccc_index_result is "skipped"): Nothing changed — your preferences were left untouched and the index was already current. You're good.}
129
131
 
130
132
  {if {tier_changed} is false and ({tools_added} or {tools_removed} is non-empty):}
131
133
  Tier unchanged: {calculated_tier}.
@@ -137,7 +139,7 @@ Load and read {tierRulesData} for the tier capability descriptions and re-run me
137
139
  ═══════════════════════════════════════
138
140
 
139
141
  {if {headless_mode} is false:}
140
- Next: try `/skf-brief-skill` to scope your first compilation target, or `/skf-quick-skill` for a fast template-driven path. Already have a skill? `/skf-audit-skill` drift-checks an existing skill against current sources.
142
+ Next: the fastest start is `@Ferris forge-auto <repo-or-doc-url>` — one command auto-scopes, briefs, compiles, tests at a 90% quality gate, and exports a verified skill with zero configuration. Prefer to scope by hand? `/skf-brief-skill` scopes your first compilation target, or `/skf-quick-skill` is a fast template-driven path. Already have a skill? `/skf-audit-skill` drift-checks an existing skill against current sources.
141
143
  ```
142
144
 
143
145
  All re-run-delta context flags (`{tools_added}`, `{tools_removed}`, `{tier_changed}`) come from the detector's `deltas` block bound in stage 1 — no LLM-side recomputation, no set arithmetic in prose.
@@ -203,6 +205,7 @@ echo '{
203
205
  "ccc_exclusion_warnings": {ccc_exclusion_warnings_list},
204
206
  "ccc_registry_stale_removed": {ccc_registry_stale_removed_paths_list},
205
207
  "ccc_indexing_failed_reason": {ccc_indexing_failed_reason_or_null},
208
+ "orphan_auto_resolution": {orphan_auto_resolution_or_null},
206
209
  "error": {error_object_or_null}
207
210
  }' | uv run {emitEnvelopeHelper} emit
208
211
  ```
@@ -7,7 +7,7 @@
7
7
  | ast-grep | `ast-grep --version` | Returns version string without error |
8
8
  | gh | `gh --version` | Returns version string without error |
9
9
  | qmd | `qmd status` | Returns status indicating initialized and operational |
10
- | ccc | Step A: `ccc --help` Step B: `ccc doctor` | Step A: exits 0 AND help output identifies the binary as cocoindex-code. Step B: daemon healthy. See `references/detect-and-tier.md` §7 for the full identity-marker procedure. |
10
+ | ccc | Step A: `ccc --help` Step B: `ccc doctor` | Step A: exits 0 AND help output identifies the binary as cocoindex-code. Step B: daemon healthy. The detection script (`skf-detect-tools.py`) performs the full identity-marker check (the `CocoIndex Code` substring that rejects PATH-shadowing aliases); see `references/detect-and-tier.md` §2. |
11
11
 
12
12
  **Important:** Use verification commands, not existence checks (`which`, `command -v`). A tool must be functional, not just present on PATH. For daemon-based tools (ccc), verify both binary identity and daemon health — a binary with the right name but the wrong implementation is a false positive, not a tool.
13
13
 
@@ -260,12 +260,22 @@ as-observed (or `absent` when the candidate was not present for this skill):
260
260
  - `stats.effective_denominator`: {N | absent} {← chosen if priority (1) applied}
261
261
  - `scope.tier_a_include` union: {N | absent} {← chosen if priority (2) applied}
262
262
  - `scope.include` union: {N | absent} {← chosen if priority (3) applied}
263
+ - exports-map subpath union: {N | absent} {← chosen if the multi-entry clause applied}
264
+ - root barrel: {N} {secondary candidate — root-barrel-vs-subpath-union audit}
263
265
  ```
264
266
 
265
267
  Readers can then spot-check whether the chosen denominator is reasonable
266
268
  against the other two without re-running the extraction. A future reviewer who
267
269
  suspects denominator gaming has the evidence inline.
268
270
 
271
+ **Multi-entry (exports-map) denominator (single-package multi-subpath libraries):** Before computing Export Coverage, check whether the Source Access Protocol's multi-entry clause applies to this skill (see `{sourceAccessProtocol}` §Source API Surface Definition — "Multi-entry (exports-map) packages"). It applies when the in-scope `package.json` declares an `exports` map with multiple non-root subpath entries, no monorepo markers — covering `scope.type: "full-library"` AND `scope.type: "public-api"` for such packages. When it applies:
272
+
273
+ 1. **Prefer `metadata.json.stats.effective_denominator`** when present. Use it directly as `total_exports` — subject to the same **denominator deflation guard** the stratified-scope branch applies.
274
+ 2. **Otherwise prefer `scope.tier_a_include`** (filtered by `scope.exclude`, excluding umbrella barrel files per the protocol's umbrella-barrel note) when the brief supplies it; **else** re-derive the **union of named exports across the files each NON-WILDCARD `exports` subpath resolves to** per the protocol (resolving committed `.d.ts` / `.d.mts` targets, applying the multi-line brace-accumulation and `export *` star-resolution rules, and excluding `"./*"` wildcard subpaths). Use the resulting count as `total_exports`. When the `exports` map has only a root `"."` entry or only wildcards, fall back to the standard root-barrel rule instead.
275
+ 3. **Report the root-barrel named-export count as a secondary candidate** in the Denominator Candidates block so the root-barrel-vs-subpath-union choice is auditable.
276
+
277
+ Record the denominator source in the Coverage Analysis section as `Denominator: multi-entry ({effective_denominator | tier_a_include union | subpath union}, {N} subpaths resolved; root barrel: {R})`.
278
+
269
279
  **State 2 denominator validation:** When using provenance-map as the baseline (State 2), cross-reference the provenance-map entry count against `metadata.json`'s `exports[]` array before computing Export Coverage. If they diverge, use the union as the denominator per the source-access-protocol rules. Log the gap size if any. The stratified-scope rule above takes precedence when both conditions apply — compute the stratified denominator first, then validate the provenance-map entry count against it.
270
280
 
271
281
  ### 4b. Metadata Export-Count Coherence Cross-Check
@@ -46,7 +46,7 @@ If `{pipeline_alias}` is set in the workflow data context (forwarded by the forg
46
46
 
47
47
  | Pipeline Alias | Default Threshold |
48
48
  |----------------|-------------------|
49
- | `deepwiki` | 90 |
49
+ | `forge-auto` | 90 |
50
50
  | `forge` | 80 |
51
51
  | `forge-quick` | 80 |
52
52
  | `campaign` | 90 |
@@ -41,14 +41,14 @@
41
41
 
42
42
  Leave `analysis_confidence` unchanged (still `full` or `provenance-map` per the waterfall) — stratified scope does not degrade confidence, only the denominator. Annotate the coverage report with: `Stratified scope — denominator: {effective_denominator | tier_a_include union | scope.include union} ({N} files matched, {M} exports union)`.
43
43
 
44
- **When this clause does NOT apply:** `scope.type: "full-library"` skills, single-package repositories, or stratified briefs where the full monorepo is intentionally in scope. For those, use the standard barrel-based denominator — **unless** the single-package repo is a pattern-reference app (see next bullet).
44
+ **When this clause does NOT apply:** `scope.type: "full-library"` skills, single-package repositories, or stratified briefs where the full monorepo is intentionally in scope. For those, use the standard barrel-based denominator — **unless** the single-package repo is a pattern-reference app (see next bullet) or publishes a multi-subpath `exports` map (use the multi-entry clause below).
45
45
 
46
46
  - **Pattern-reference apps (non-library source):** If the source is a single-package repo whose purpose is demonstrating an integration pattern rather than distributing a library API — typical markers are `scope.type: "full-library"` **without** a barrel file at any recognized entry-point path (`__init__.py`, `index.ts`/`index.js`, `lib.rs`, `mod.rs`) AND without a monorepo layout — the skill's value lives in wiring patterns, not exports. None of the preceding three clauses fits: there is no barrel to count from, no empty-barrel `scope.include` to consult, and no monorepo stratification to re-derive.
47
47
 
48
48
  **Trigger (either fires):**
49
49
 
50
50
  1. `scope.notes` in `forge-data/{skill_name}/skill-brief.yaml` flags pattern-reference intent (phrases such as "Reference app, not a library", "pattern-reference", "embedded-pattern skill", or "skill value is the … pattern"). The `scope.notes` field is authoritative when the author wrote it.
51
- 2. Source tree lacks a barrel file at every recognized entry-point path AND the repo is not a monorepo (no `packages/`, `workspaces`, `lerna.json`, `rush.json`, `nx.json`, or Cargo `[workspace]`). Detected at test time by filesystem inspection of `{source_path}`.
51
+ 2. Source tree lacks a barrel file at every recognized entry-point path AND the repo is not a monorepo (no `packages/`, `workspaces`, `lerna.json`, `rush.json`, `nx.json`, or Cargo `[workspace]`) AND the package does not declare a multi-subpath `exports` map (those route to the multi-entry clause below). Detected at test time by filesystem inspection of `{source_path}`.
52
52
 
53
53
  **Denominator:** canonicalized provenance-map entry count (same canonicalization as the "Provenance-map canonicalization" section below). `skf-create-skill`'s extraction pass has already curated the provenance-map to the authored pattern surface; treat it as the authoritative enumeration of the skill's documented reach.
54
54
 
@@ -56,7 +56,7 @@
56
56
 
57
57
  **Confidence:** leave `analysis_confidence` unchanged (still `full` or `provenance-map` per the waterfall). Pattern-reference does not degrade confidence — the surface is smaller than a library barrel, not lower quality. Annotate the coverage report with: `Pattern-reference — denominator: {tier_a_include union | canonicalized provenance-map count} ({N} pattern surfaces)`.
58
58
 
59
- **When this clause does NOT apply:** any repo with a non-empty barrel file, any monorepo (use the stratified-scope clause), or any single-package repo whose `scope.type` is explicitly `public-api` / `specific-modules` / `component-library` / `docs-only` (those scope types have their own denominator semantics). Also does NOT apply when `scope.type: "reference-app"` — that scope type carries its own pattern-surface denominator semantics (the brief speaks for itself), so this clause's filesystem trigger is moot.
59
+ **When this clause does NOT apply:** any repo with a non-empty barrel file, any monorepo (use the stratified-scope clause), or any single-package repo whose `scope.type` is explicitly `specific-modules` (use the specific-modules clause), `public-api` with a multi-subpath `exports` map (use the multi-entry clause below a `public-api` package WITHOUT such a map keeps the standard root-barrel rule), `component-library`, or `docs-only`. Also does NOT apply when `scope.type: "reference-app"` — that scope type carries its own pattern-surface denominator semantics (the brief speaks for itself), so this clause's filesystem trigger is moot.
60
60
 
61
61
  - **Single-crate curated subset (`scope.type: "specific-modules"`):** If the source is a single-package (non-monorepo) repo whose skill brief sets `scope.type: "specific-modules"` and uses `scope.include`/`scope.exclude` to carve a subset of the crate's public surface, the coverage denominator is the **in-scope reachable barrel** — not the full barrel.
62
62
 
@@ -72,6 +72,16 @@
72
72
 
73
73
  **When this clause does NOT apply:** monorepo packages (use the stratified-scope clause), `scope.type: "full-library"` (use the standard barrel), or empty-barrel packages (use the empty-barrel clause). This clause is specifically for single-crate repos where the brief intentionally documents a curated subset rather than the full public surface.
74
74
 
75
+ - **Multi-entry (exports-map) packages (single-package libraries publishing via a `package.json` `exports` map):** If the in-scope `package.json` declares an `exports` map with **multiple non-root subpath entries** (more than just `"."`) and the repo carries **no** monorepo markers (`packages/` layout, `workspaces` field, `lerna.json`, `rush.json`, `nx.json`, Cargo `[workspace]`), the package's public surface spans every published subpath, not just the root barrel. The standard "named exports from `index.ts`" rule undercounts: it measures only the `"."` barrel while installers reach the full subpath set. This clause covers both `scope.type: "full-library"` AND `scope.type: "public-api"` for such packages.
76
+
77
+ **Denominator:** the **union of named exports across the files each NON-WILDCARD `exports` subpath resolves to**. Resolve each subpath to its target file (or its committed `.d.ts` / `.d.mts` declaration), then apply the same multi-line brace-accumulation and `export *` star-resolution rules documented for barrel re-derivation earlier in this file ("TypeScript / JavaScript barrel re-derivation"). **Explicitly exclude wildcard subpaths** (`"./*"` forms — they map to an open-ended file set whose surface is unbounded and uncountable). If the `exports` map has only a root `"."` entry, or only wildcard subpaths, fall back to the standard root-barrel rule.
78
+
79
+ **Curation/priority (same ladder the specific-modules clause uses):** prefer `metadata.json.stats.effective_denominator` first (subject to the existing deflation guard), then `scope.tier_a_include` globs (filtered by `scope.exclude`, the umbrella-barrel note applies) when the brief supplies it, else the full subpath union.
80
+
81
+ **Audit:** the root-barrel named-export count MUST be reported as a **secondary candidate** in the Denominator Candidates audit block (coverage-check.md §4) so the root-barrel-vs-subpath-union choice is auditable. Annotate the coverage report with: `Multi-entry (exports-map) — denominator: {effective_denominator | tier_a_include union | subpath union} ({N} subpaths resolved, {M} exports union; root barrel: {R})`.
82
+
83
+ **When this clause does NOT apply:** monorepo packages (use the stratified-scope clause), empty-barrel packages (use the empty-barrel clause), pattern-reference apps (use the pattern-reference clause), `scope.type: "specific-modules"` (use the specific-modules clause), or single-entry / wildcard-only `exports` maps (use the standard root-barrel rule).
84
+
75
85
  Internal module symbols are **excluded** from the coverage denominator unless they are explicitly documented in SKILL.md (in which case they count as documented extras, not missing coverage).
76
86
 
77
87
  This matches the extraction-patterns.md convention used during skill creation: coverage measures how well SKILL.md documents what users actually import, not the entire internal codebase.
@@ -29,8 +29,10 @@ Input schema (one object):
29
29
  }
30
30
 
31
31
  Exit codes:
32
- 0 — score computed (verdict may be PASS/FAIL/INCONCLUSIVE)
33
- 1 — input error (bad JSON, missing fields, schema violation)
32
+ 0 — input was parsed; either a score was computed (verdict may be
33
+ PASS/FAIL/INCONCLUSIVE) or a schema/validation error object
34
+ ({"error": ..., "code": "INVALID_INPUT"}) was emitted as JSON
35
+ 1 — input could not be parsed at all (no input provided, or malformed JSON)
34
36
  """
35
37
 
36
38
  from __future__ import annotations
@@ -381,4 +383,3 @@ def main(argv: list[str] | None = None) -> int:
381
383
 
382
384
  if __name__ == "__main__":
383
385
  raise SystemExit(main())
384
- sys.exit(1 if "error" in result else 0)
@@ -33,12 +33,3 @@ activation_steps_append = []
33
33
  persistent_facts = [
34
34
  "file:{project-root}/**/project-context.md",
35
35
  ]
36
-
37
- # --- Optional gate thresholds ---
38
- #
39
- # Override the default thresholds used by detect-changes and merge. Empty
40
- # string or commented = use the bundled default (50% deletion ratio,
41
- # 80% rename similarity).
42
-
43
- deletion_ratio_threshold = ""
44
- rename_similarity_threshold = ""
@@ -25,6 +25,17 @@ buildChangeManifestProbeOrder:
25
25
  provenanceGapDispatchProbeOrder:
26
26
  - '{project-root}/_bmad/skf/shared/scripts/skf-provenance-gap-dispatch.py'
27
27
  - '{project-root}/src/shared/scripts/skf-provenance-gap-dispatch.py'
28
+ # Resolve `{detectScriptsAssetsHelper}` to the first existing path; HALT if
29
+ # neither candidate exists. §Category D uses `detect` to walk the current
30
+ # source tree for scripts/assets (directory conventions, shebang signals,
31
+ # `package.json` `bin` entry-points, asset filename patterns) so NEW_FILE
32
+ # detection mirrors create-skill §4c exactly. Falling back to prose-driven
33
+ # file walking would let the LLM drift on the heuristic list and miss new
34
+ # scripts/assets at deeper directory depths — and on installed modules
35
+ # (no `src/` tree) the LLM would otherwise guess a non-existent path.
36
+ detectScriptsAssetsProbeOrder:
37
+ - '{project-root}/_bmad/skf/shared/scripts/skf-detect-scripts-assets.py'
38
+ - '{project-root}/src/shared/scripts/skf-detect-scripts-assets.py'
28
39
  ---
29
40
 
30
41
  <!-- Config: communicate in {communication_language}. -->
@@ -305,7 +316,20 @@ Launch subprocesses in parallel that compare source state against provenance map
305
316
 
306
317
  **Category C — Rename detection:**
307
318
  - Cross-reference deleted files/exports with added files/exports
308
- - If content similarity > 80%: classify as RENAMED instead of deleted+added. **Similarity mechanism by tier:** Quick: compare file size ratio (within 20%) and export name overlap (>70% of exports match by name). Forge and above: use ast-grep to compare export signatures between the deleted and added files. Forge+/Deep: use CCC semantic similarity when available
319
+ - If content similarity > 80% (fixed bundled threshold — not configurable): classify as RENAMED instead of deleted+added. **Similarity mechanism by tier:** Quick: compare file size ratio (within 20%) and export name overlap (>70% of exports match by name). Forge and above: use ast-grep to compare export signatures between the deleted and added files. Forge+/Deep: use CCC semantic similarity when available
320
+
321
+ **Subprocess return contract.** Hand each Category worker its exact output slice so it returns parse-ready JSON, not prose the parent must re-read. Each worker returns ONLY its own object — no prose, no commentary, no markdown fences (parent strips wrapping fences before parsing). The slice each worker fills is exactly the key §3's `build` helper consumes (the `category_a/b/c` shape below; Category D is helper-driven, not a worker):
322
+
323
+ ```json
324
+ // Category A worker returns ONLY:
325
+ {"category_a": {"modified": [...], "added": [...], "deleted": [...]}}
326
+ // Category B worker returns ONLY:
327
+ {"category_b": {"modified_exports": [...], "new_exports": [...], "deleted_exports": [...], "moved_exports": [...]}}
328
+ // Category C worker returns ONLY:
329
+ {"category_c": {"renamed_files": [...], "renamed_exports": [...]}}
330
+ ```
331
+
332
+ The parent merges the three slices (plus Category D and the `degraded_mode`/`update_mode` flags) into the single category-JSON object §3 pipes to the `build` helper.
309
333
 
310
334
  **Category D — Script/asset file changes:**
311
335
 
@@ -334,7 +358,13 @@ Translate the helper's output into the change manifest:
334
358
  - `DELETED_FILE` rows → add to manifest as DELETED_FILE
335
359
  - `UNCHANGED` rows → omit from the manifest (no action needed)
336
360
 
337
- The helper does NOT detect NEW_FILE — its job is provenance comparison only. Detect new files via `skf-detect-scripts-assets.py` from create-skill step 3 §4c against the current source tree, then subtract the paths already present in `provenance.file_entries[].source_file`. Remaining files matching detection patterns (`scripts/`, `bin/`, `assets/`, `templates/`) and NOT under `scripts/[MANUAL]/` or `assets/[MANUAL]/` are NEW_FILE.
361
+ The helper does NOT detect NEW_FILE — its job is provenance comparison only. Detect new files by running the same deterministic detector create-skill step 3 §4c uses (resolved via `detectScriptsAssetsProbeOrder`) against the current source tree:
362
+
363
+ ```bash
364
+ uv run {detectScriptsAssetsHelper} detect <source-root>
365
+ ```
366
+
367
+ It emits `scripts_inventory[]` and `assets_inventory[]` (each entry carries `source_file`). Take every `source_file` across both inventories, then subtract the paths already present in `provenance.file_entries[].source_file`. Of the remaining files, those matching detection patterns (`scripts/`, `bin/`, `assets/`, `templates/`) and NOT under `scripts/[MANUAL]/` or `assets/[MANUAL]/` are NEW_FILE.
338
368
 
339
369
  Files in `scripts/[MANUAL]/` or `assets/[MANUAL]/` → SKIP (user-authored, preserved).
340
370
 
@@ -356,7 +386,7 @@ echo "{category JSON}" | uv run {buildChangeManifestHelper} deletion-ratio \
356
386
  --provenance-map {forge_version}/provenance-map.json
357
387
  ```
358
388
 
359
- The helper handles the three skip conditions internally — when the input has `update_mode: "gap-driven"`, `degraded_mode: true`, or the provenance has zero entries, it returns `skip_reason` set and `should_trigger: false`. The output envelope:
389
+ The helper handles the three skip conditions internally — when the input has `update_mode: "gap-driven"`, `degraded_mode: true`, or the provenance has zero entries, it returns `skip_reason` set and `should_trigger: false`. `should_trigger` fires when the deletion ratio reaches the fixed bundled threshold of 50% (`ratio >= 0.50`, baked into the helper — not configurable). The output envelope:
360
390
 
361
391
  ```json
362
392
  {
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  # `shared/health-check.md` resolves relative to the SKF module root
3
- # (`_bmad/skf/` when installed, `src/` during development), NOT relative
4
- # to this step file.
3
+ # (`{project-root}/_bmad/skf/` when installed, `{project-root}/src/` during
4
+ # development), NOT relative to this step file.
5
5
  nextStepFile: 'shared/health-check.md'
6
6
  ---
7
7
 
@@ -38,6 +38,7 @@ Provide either:
38
38
  3. If not in manifest: check for `active` symlink at `{skills_output_folder}/{skill-name}/active` — resolve to `{skill_group}/active/{skill-name}/`
39
39
  4. If neither: fall back to flat path `{skills_output_folder}/{skill-name}/`. If SKILL.md exists at the flat path, auto-migrate per `knowledge/version-paths.md` migration rules
40
40
  5. Store the resolved path as `{resolved_skill_package}` for all subsequent artifact loading
41
+ 6. Bind `{baseline_version}` to the pre-update version — for an update this is the version being updated, i.e. the `{active_version}` resolved in step 1 above (the flat-path fallback in step 4 has no version, so use the package version read from metadata.json in §2). Step 2 §1c passes `{baseline_version}` to `skf-provenance-gap-dispatch.py` as a required argument; leaving it unbound makes the helper search a wrong/empty directory and silently return `no-report`, dropping the major-version off-ramp.
41
42
 
42
43
  Resolve the path to an absolute skill folder location.
43
44
 
@@ -254,7 +254,21 @@ DO NOT BE LAZY — For EACH remaining file in the change manifest with status MO
254
254
  - Record: return type (if function/method)
255
255
  - Record: JSDoc/docstring summary (if present)
256
256
  - Label: confidence tier (T1/T1-low/T2)
257
- 4. Returns structured extraction findings to parent
257
+ 4. **Return contract.** Each extraction worker returns ONLY this per-file block — no prose, no commentary, no markdown fences (the parent strips wrapping fences before parsing). The shape is exactly the per-file record §4 aggregates (the `Per-file extractions` block, lines below), so the parent appends it verbatim rather than re-parsing free text:
258
+
259
+ ```json
260
+ {
261
+ "file_path": "...",
262
+ "exports": [
263
+ {"name": "...", "type": "function|class|type|constant",
264
+ "signature": "...", "location": "{file}:{start_line}-{end_line}",
265
+ "confidence": "T1|T1-low|T2",
266
+ "parameters": [{"name": "...", "type": "..."}],
267
+ "return_type": "...", "docstring": "...",
268
+ "qmd_evidence": "<if Deep tier, else omit>"}
269
+ ]
270
+ }
271
+ ```
258
272
 
259
273
  **For DELETED files:** No extraction needed — deletions handled in merge step.
260
274
 
@@ -106,7 +106,7 @@ Based on the overall verdict, present the appropriate recommendation:
106
106
 
107
107
  **Resolve `{atomicWriteHelper}`** from `{atomicWriteProbeOrder}`; first existing path wins. HALT if no candidate exists.
108
108
 
109
- Write the result contract per `shared/references/output-contract-schema.md`: the per-run record at `{forge_data_folder}/verify-stack-result-{YYYYMMDD-HHmmss}.json` (UTC timestamp, resolution to seconds) and a copy at `{forge_data_folder}/verify-stack-result-latest.json` (stable path for pipeline consumers — copy, not symlink). Include the feasibility report path (both `{outputFile}` and `{outputFileLatest}`) in `outputs`; include `overallVerdict` (`FEASIBLE` / `CONDITIONALLY_FEASIBLE` / `NOT_FEASIBLE`), `coveragePercentage`, and `recommendationCount` in `summary` — use the case-sensitive schema tokens.
109
+ Write the result contract per `shared/references/output-contract-schema.md` (this path resolves relative to the SKF module root — `{project-root}/_bmad/skf/` when installed, `{project-root}/src/` during development — NOT relative to this step file): the per-run record at `{forge_data_folder}/verify-stack-result-{YYYYMMDD-HHmmss}.json` (UTC timestamp, resolution to seconds) and a copy at `{forge_data_folder}/verify-stack-result-latest.json` (stable path for pipeline consumers — copy, not symlink). Include the feasibility report path (both `{outputFile}` and `{outputFileLatest}`) in `outputs`; include `overallVerdict` (`FEASIBLE` / `CONDITIONALLY_FEASIBLE` / `NOT_FEASIBLE`), `coveragePercentage`, and `recommendationCount` in `summary` — use the case-sensitive schema tokens.
110
110
 
111
111
  Write both JSON files through `python3 {atomicWriteHelper} write --target ...` to avoid partial-write corruption. On any non-zero exit: HALT (exit code 4, `halt_reason: "write-failed"`) and emit the error envelope.
112
112
 
@@ -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