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.
- package/.claude-plugin/marketplace.json +1 -1
- package/README.md +10 -5
- package/docs/_data/pinned.yaml +2 -2
- package/docs/agents.md +11 -2
- package/docs/architecture.md +5 -4
- package/docs/bmad-synergy.md +30 -7
- package/docs/campaign.md +172 -0
- package/docs/examples.md +7 -3
- package/docs/forge-auto.md +90 -0
- package/docs/getting-started.md +9 -0
- package/docs/how-it-works.md +6 -4
- package/docs/index.md +4 -3
- package/docs/skill-model.md +1 -1
- package/docs/troubleshooting.md +17 -1
- package/docs/verifying-a-skill.md +2 -2
- package/docs/why-skf.md +1 -1
- package/docs/workflows.md +64 -24
- package/package.json +2 -2
- package/src/module-help.csv +2 -1
- package/src/shared/data/language-corpora.json +32 -0
- package/src/shared/references/pipeline-contracts.md +6 -3
- package/src/shared/scripts/schemas/skill-brief.v1.json +6 -1
- package/src/shared/scripts/skf-derive-assembly-shape.py +107 -0
- package/src/shared/scripts/skf-detect-docs.py +8 -3
- package/src/shared/scripts/skf-detect-language.py +5 -3
- package/src/shared/scripts/skf-emit-result-envelope.py +17 -0
- package/src/shared/scripts/skf-extract-public-api.py +53 -0
- package/src/shared/scripts/skf-language-corpora.py +100 -0
- package/src/shared/scripts/skf-merge-doc-urls.py +244 -0
- package/src/shared/scripts/skf-preapply.py +1 -1
- package/src/shared/scripts/skf-shape-detect.py +576 -25
- package/src/shared/scripts/skf-validate-brief-schema.py +2 -5
- package/src/shared/scripts/skf-validate-pins.py +2 -2
- package/src/shared/scripts/skf-write-skill-brief.py +21 -5
- package/src/skf-analyze-source/SKILL.md +1 -1
- package/src/skf-analyze-source/assets/skill-brief-schema.md +1 -1
- package/src/skf-analyze-source/references/step-auto-scope.md +196 -44
- package/src/skf-analyze-source/references/step-shape-detect.md +20 -13
- package/src/skf-audit-skill/references/init.md +1 -1
- package/src/skf-brief-skill/assets/skill-brief-schema.md +1 -1
- package/src/skf-brief-skill/references/analyze-target.md +7 -4
- package/src/skf-brief-skill/references/confirm-brief.md +0 -1
- package/src/skf-brief-skill/references/gather-intent.md +8 -2
- package/src/skf-brief-skill/references/scope-definition.md +2 -1
- package/src/skf-brief-skill/references/step-auto-brief.md +21 -4
- package/src/skf-brief-skill/references/step-auto-validate.md +2 -2
- package/src/skf-brief-skill/references/write-brief.md +2 -3
- package/src/skf-campaign/SKILL.md +190 -0
- package/src/skf-campaign/assets/campaign-state-schema.json +191 -0
- package/src/skf-campaign/customize.toml +73 -0
- package/src/skf-campaign/manifest.yaml +11 -0
- package/src/skf-campaign/references/campaign-directive-spec.md +121 -0
- package/src/skf-campaign/references/health-check.md +35 -0
- package/src/skf-campaign/references/step-01-setup.md +122 -0
- package/src/skf-campaign/references/step-02-strategy.md +97 -0
- package/src/skf-campaign/references/step-03-pins.md +56 -0
- package/src/skf-campaign/references/step-04-provenance.md +63 -0
- package/src/skf-campaign/references/step-05-skill-loop.md +103 -0
- package/src/skf-campaign/references/step-06-batch.md +87 -0
- package/src/skf-campaign/references/step-07-capstone.md +63 -0
- package/src/skf-campaign/references/step-08-verify.md +75 -0
- package/src/skf-campaign/references/step-09-refine.md +83 -0
- package/src/skf-campaign/references/step-10-export.md +106 -0
- package/src/skf-campaign/references/step-11-maintenance.md +84 -0
- package/src/skf-campaign/references/step-resume.md +114 -0
- package/src/skf-campaign/scripts/.gitkeep +0 -0
- package/src/skf-campaign/scripts/campaign-deps.py +235 -0
- package/src/skf-campaign/scripts/campaign-parse-manifest.py +119 -0
- package/src/skf-campaign/scripts/campaign-provenance.py +247 -0
- package/src/skf-campaign/scripts/campaign-render-kickoff.py +158 -0
- package/src/skf-campaign/scripts/campaign-report.py +249 -0
- package/src/skf-campaign/scripts/campaign-validate-pins.py +174 -0
- package/src/skf-campaign/scripts/campaign-validate-state.py +207 -0
- package/src/skf-campaign/templates/campaign-brief-template.yaml +34 -0
- package/src/skf-campaign/templates/campaign-report-template.md +54 -0
- package/src/skf-campaign/templates/kickoff-template.md +48 -0
- package/src/skf-create-skill/SKILL.md +1 -1
- package/src/skf-create-skill/assets/compile-assembly-rules.md +22 -0
- package/src/skf-create-skill/references/compile.md +4 -1
- package/src/skf-create-skill/references/extract.md +9 -1
- package/src/skf-create-skill/references/extraction-patterns.md +3 -1
- package/src/skf-create-skill/references/generate-artifacts.md +11 -2
- package/src/skf-create-skill/references/health-check.md +2 -2
- package/src/skf-create-skill/references/report.md +17 -1
- package/src/skf-create-skill/references/source-resolution-protocols.md +1 -1
- package/src/skf-create-skill/references/step-doc-rot.md +4 -4
- package/src/skf-create-skill/references/step-doc-sources.md +11 -2
- package/src/skf-create-skill/references/sub/fetch-docs.md +29 -0
- package/src/skf-create-skill/references/validate.md +12 -3
- package/src/skf-drop-skill/SKILL.md +2 -2
- package/src/skf-drop-skill/references/execute.md +20 -9
- package/src/skf-drop-skill/references/report.md +2 -0
- package/src/skf-drop-skill/references/select.md +7 -2
- package/src/skf-forger/SKILL.md +12 -7
- package/src/skf-refine-architecture/SKILL.md +2 -1
- package/src/skf-refine-architecture/references/compile.md +1 -1
- package/src/skf-refine-architecture/references/report.md +1 -1
- package/src/skf-rename-skill/SKILL.md +2 -2
- package/src/skf-rename-skill/references/execute.md +5 -4
- package/src/skf-rename-skill/references/rebuild-context.md +2 -2
- package/src/skf-rename-skill/references/select.md +3 -3
- package/src/skf-setup/SKILL.md +1 -1
- package/src/skf-setup/references/auto-index.md +3 -1
- package/src/skf-setup/references/detect-and-tier.md +4 -0
- package/src/skf-setup/references/report.md +4 -1
- package/src/skf-setup/references/tier-rules.md +1 -1
- package/src/skf-test-skill/references/coverage-check.md +10 -0
- package/src/skf-test-skill/references/init.md +1 -1
- package/src/skf-test-skill/references/source-access-protocol.md +13 -3
- package/src/skf-test-skill/scripts/compute-score.py +4 -3
- package/src/skf-update-skill/customize.toml +0 -9
- package/src/skf-update-skill/references/detect-changes.md +33 -3
- package/src/skf-update-skill/references/health-check.md +2 -2
- package/src/skf-update-skill/references/init.md +1 -0
- package/src/skf-update-skill/references/re-extract.md +15 -1
- package/src/skf-verify-stack/references/report.md +1 -1
- package/tools/cli/lib/ui.js +3 -2
- 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:
|
|
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.
|
|
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
|
-
| `
|
|
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 `
|
|
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
|
|
33
|
-
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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
|
|
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
|
|
package/tools/cli/lib/ui.js
CHANGED
|
@@ -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)
|
|
360
|
-
|
|
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
|