bmad-module-skill-forge 1.1.0 → 1.2.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 +6 -4
- package/docs/_data/pinned.yaml +1 -1
- package/docs/bmad-synergy.md +2 -2
- package/docs/getting-started.md +1 -1
- package/docs/troubleshooting.md +1 -1
- package/docs/why-skf.md +5 -4
- package/package.json +2 -2
- package/src/knowledge/ccc-bridge.md +1 -1
- package/src/shared/scripts/schemas/skf-setup-result-envelope.v1.json +134 -0
- package/src/shared/scripts/skf-detect-tools.py +359 -0
- package/src/shared/scripts/skf-emit-result-envelope.py +419 -0
- package/src/shared/scripts/skf-forge-tier-rw.py +413 -0
- package/src/shared/scripts/skf-merge-ccc-exclusions.py +324 -0
- package/src/shared/scripts/skf-preflight.py +14 -4
- package/src/shared/scripts/skf-qmd-classify-collections.py +212 -0
- package/src/shared/scripts/skf-validate-frontmatter.py +9 -3
- package/src/skf-create-skill/steps-c/step-06-validate.md +1 -1
- package/src/skf-setup/SKILL.md +25 -10
- package/src/skf-setup/references/tier-rules.md +2 -2
- package/src/skf-setup/steps-c/step-01-detect-and-tier.md +58 -71
- package/src/skf-setup/steps-c/step-01b-ccc-index.md +49 -66
- package/src/skf-setup/steps-c/step-02-write-config.md +59 -86
- package/src/skf-setup/steps-c/step-03-auto-index.md +73 -91
- package/src/skf-setup/steps-c/step-04-report.md +135 -11
- package/src/skf-setup/steps-c/step-05-health-check.md +4 -2
- package/src/skf-test-skill/steps-c/step-01-init.md +4 -4
package/src/skf-setup/SKILL.md
CHANGED
|
@@ -7,7 +7,7 @@ description: Initialize forge environment, detect tools, and set capability tier
|
|
|
7
7
|
|
|
8
8
|
## Overview
|
|
9
9
|
|
|
10
|
-
Initializes the forge environment by detecting available tools, determining the capability tier (Quick/Forge/Forge+/Deep), writing persistent configuration, and
|
|
10
|
+
Initializes the forge environment by detecting available tools, determining the capability tier (Quick/Forge/Forge+/Deep), and writing persistent configuration to `{project-root}/_bmad/_memory/forger-sidecar/`. When `ccc` (cocoindex-code) is available, also augments `.cocoindex_code/settings.yml` with SKF exclusion patterns and creates or refreshes the project's semantic-search index. On Deep tier, reconciles the QMD collection registry; whenever ccc is available, reconciles the CCC index registry as well. The workflow is autonomous with one optional gate — orphaned QMD collection removal in step 3 (Deep tier only; default action: Keep) — which auto-resolves to the default when `{headless_mode}` is true.
|
|
11
11
|
|
|
12
12
|
## Role
|
|
13
13
|
|
|
@@ -17,7 +17,7 @@ You are a system executor performing environment resolution. Run each step in se
|
|
|
17
17
|
|
|
18
18
|
These rules apply to every step in this workflow:
|
|
19
19
|
|
|
20
|
-
-
|
|
20
|
+
- Autonomous with one optional gate (step 3 orphan-removal prompt; default: Keep) — all other steps auto-proceed with no user interaction until the final report
|
|
21
21
|
- Read each step file completely before taking any action
|
|
22
22
|
- Follow the mandatory sequence in each step exactly — do not skip, reorder, or optimize
|
|
23
23
|
- Only load one step file at a time — never preload future steps
|
|
@@ -29,9 +29,9 @@ These rules apply to every step in this workflow:
|
|
|
29
29
|
| # | Step | File | Auto-proceed |
|
|
30
30
|
|---|------|------|--------------|
|
|
31
31
|
| 1 | Detect Tools & Set Tier | steps-c/step-01-detect-and-tier.md | Yes |
|
|
32
|
-
| 1b | CCC Index | steps-c/step-01b-ccc-index.md | Yes |
|
|
32
|
+
| 1b | CCC Index (only when ccc is available) | steps-c/step-01b-ccc-index.md | Yes |
|
|
33
33
|
| 2 | Write Config | steps-c/step-02-write-config.md | Yes |
|
|
34
|
-
| 3 | QMD Hygiene | steps-c/step-03-auto-index.md | Yes |
|
|
34
|
+
| 3 | QMD + CCC Registry Hygiene | steps-c/step-03-auto-index.md | Yes |
|
|
35
35
|
| 4 | Report | steps-c/step-04-report.md | Yes |
|
|
36
36
|
| 5 | Workflow Health Check | steps-c/step-05-health-check.md | Yes |
|
|
37
37
|
|
|
@@ -39,17 +39,32 @@ These rules apply to every step in this workflow:
|
|
|
39
39
|
|
|
40
40
|
| Aspect | Detail |
|
|
41
41
|
|--------|--------|
|
|
42
|
-
| **Inputs** | (none
|
|
42
|
+
| **Inputs** | (none) |
|
|
43
|
+
| **Flags** | `--headless` / `-H` (skip prompts, auto-resolve gates to defaults); `--require-tier=<Quick\|Forge\|Forge+\|Deep>` (halt with failure if calculated tier does not satisfy the requirement) |
|
|
43
44
|
| **Gates** | One optional: orphaned QMD collection removal (step 3, Deep tier only; default: Keep) |
|
|
44
|
-
| **Outputs** | forge-tier.yaml
|
|
45
|
-
| **Headless** | All gates auto-resolve with default action when `{headless_mode}` is true |
|
|
45
|
+
| **Outputs** | `forger-sidecar/forge-tier.yaml`, `forger-sidecar/preferences.yaml`, `{forge_data_folder}/`; when ccc is available, `.cocoindex_code/settings.yml` (exclusion patterns merged) and the project ccc index |
|
|
46
|
+
| **Headless** | All gates auto-resolve with default action when `{headless_mode}` is true. step-04 emits a single-line `SKF_SETUP_RESULT_JSON: {…}` envelope after the human-readable banner so pipelines can parse the outcome without reading forge-tier.yaml. Schema documented in `steps-c/step-04-report.md` §4. |
|
|
47
|
+
| **Failure modes** | `--require-tier` not satisfied → step-04 prints a "REQUIRED TIER NOT MET" block, the JSON envelope sets `"require_tier_satisfied": false`, and the workflow halts before step-05. |
|
|
48
|
+
| **Exit codes** | The workflow runs as an LLM-driven sequence rather than a CLI process, so "exit code" describes the agent's terminal state for a calling pipeline that reads `SKF_SETUP_RESULT_JSON`. **0 — success** (no JSON `error` field, all writes completed, `require_tier_satisfied` is `true` or `null`). **1 — required-tier failure** (`require_tier_satisfied` is `false`; envelope still emitted with full state for diagnosis). **2 — write failure** (forge-tier.yaml or preferences.yaml could not be written; envelope `error` field names the path and reason). Pipelines should branch on the JSON `require_tier_satisfied` and `error` fields rather than process exit codes. |
|
|
46
49
|
|
|
47
50
|
## On Activation
|
|
48
51
|
|
|
49
|
-
1.
|
|
52
|
+
1. **Probe `uv` runtime.** Run `uv --version`. Every step in this workflow invokes shared Python helpers via `uv run` (PEP 723 inline metadata is what auto-resolves `pyyaml` for the helpers that need it — see `docs/getting-started.md`). If `uv` is missing, halt now with a single cohesive diagnostic rather than letting five separate steps each fail with `uv: command not found`:
|
|
53
|
+
|
|
54
|
+
"**Setup cannot proceed: `uv` is not installed.** SKF helpers depend on `uv` to auto-resolve their Python dependencies. Install it from <https://docs.astral.sh/uv/getting-started/installation/> and re-run `/skf-setup`. (See the Prerequisites section in <https://docs.astral.sh/uv/getting-started/installation/> or the SKF docs at `docs/getting-started.md` for details.)"
|
|
55
|
+
|
|
56
|
+
2. Load config from `{project-root}/_bmad/skf/config.yaml` and resolve:
|
|
50
57
|
- `project_name` (from installer-generated config.yaml, not module.yaml), `output_folder`, `user_name`, `communication_language`, `document_output_language`
|
|
51
58
|
- `skills_output_folder`, `forge_data_folder`, `sidecar_path`
|
|
52
59
|
|
|
53
|
-
|
|
60
|
+
**If the file does not exist**, halt with a single cohesive "wrong directory" diagnostic rather than failing later with a generic file-read error from a downstream step:
|
|
61
|
+
|
|
62
|
+
"**Setup cannot proceed: `{project-root}/_bmad/skf/config.yaml` was not found.** This directory does not appear to be an SKF-initialised project. From the project root, run `npx bmad-module-skill-forge install` (or `npx bmad-method install` and add SKF as a custom module — see `docs/getting-started.md`), then re-run `/skf-setup`. If you ARE in the right project but the file was deleted, restore it from version control or re-run the SKF installer."
|
|
63
|
+
|
|
64
|
+
**If the file exists but is malformed YAML**, halt and surface the parser error along with the file path so the user can fix it directly: "**Setup cannot proceed: `{project-root}/_bmad/skf/config.yaml` is not valid YAML.** Parser error: {error_message}. Open the file and repair the YAML, or restore from version control."
|
|
65
|
+
|
|
66
|
+
3. **Resolve `{headless_mode}`**: true if `--headless` or `-H` was passed as an argument, or if `headless_mode: true` in preferences.yaml. Default: false.
|
|
67
|
+
|
|
68
|
+
4. **Resolve `{require_tier}`**: parse `--require-tier=<value>` from the invocation arguments. Accept exactly `Quick`, `Forge`, `Forge+`, or `Deep` (case-sensitive). If absent or unparseable, leave as null (no tier requirement).
|
|
54
69
|
|
|
55
|
-
|
|
70
|
+
5. Load, read the full file, and then execute `./steps-c/step-01-detect-and-tier.md` to begin the workflow.
|
|
@@ -7,9 +7,9 @@
|
|
|
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
|
|
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 `steps-c/step-01-detect-and-tier.md` §7 for the full identity-marker procedure. |
|
|
11
11
|
|
|
12
|
-
**Important:** Use verification commands, not existence checks (`which`, `command -v`). A tool must be functional, not just present on PATH. For daemon-based tools (ccc), verify both binary
|
|
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
|
|
|
14
14
|
## Tier Calculation
|
|
15
15
|
|
|
@@ -1,111 +1,98 @@
|
|
|
1
1
|
---
|
|
2
2
|
nextStepFile: './step-01b-ccc-index.md'
|
|
3
|
-
|
|
3
|
+
# Resolve `{detectToolsHelper}` by probing `{detectToolsProbeOrder}` in order
|
|
4
|
+
# (installed SKF module path first, src/ dev-checkout fallback); first existing
|
|
5
|
+
# path wins. HALT if neither resolves — the script is the source of truth for
|
|
6
|
+
# tool detection and tier calculation; no fallback to prose-driven probes.
|
|
7
|
+
detectToolsProbeOrder:
|
|
8
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-detect-tools.py'
|
|
9
|
+
- '{project-root}/src/shared/scripts/skf-detect-tools.py'
|
|
4
10
|
---
|
|
5
11
|
|
|
12
|
+
<!-- Config: communicate in {communication_language}. The first-run preamble below is user-visible — render it in the user's language. -->
|
|
13
|
+
|
|
6
14
|
# Step 1: Detect Tools and Determine Tier
|
|
7
15
|
|
|
8
16
|
## STEP GOAL:
|
|
9
17
|
|
|
10
|
-
Verify availability of the four forge tools (ast-grep, gh, qmd, ccc), read any existing configuration for re-run comparison, check for tier override, and calculate the capability tier.
|
|
18
|
+
Verify availability of the four forge tools (ast-grep, gh, qmd, ccc), read any existing configuration for re-run comparison, check for tier override, and calculate the capability tier — all via `{detectToolsHelper}` so the deterministic work is done once, by a tested script, never by the LLM.
|
|
11
19
|
|
|
12
20
|
## Rules
|
|
13
21
|
|
|
14
22
|
- Focus only on tool detection and tier calculation — do not write any files (Step 02)
|
|
15
|
-
-
|
|
16
|
-
- Tool command failures are not errors — they indicate unavailability
|
|
23
|
+
- Never reimplement tool probes or the tier rules in prose — the script is authoritative
|
|
24
|
+
- Tool command failures are not errors — they indicate unavailability (the script swallows them)
|
|
17
25
|
|
|
18
26
|
## MANDATORY SEQUENCE
|
|
19
27
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
### 1. Load Tier Rules
|
|
23
|
-
|
|
24
|
-
Load and read {tierRulesData} for the tool detection commands and tier calculation logic.
|
|
25
|
-
|
|
26
|
-
### 2. Check for Existing Configuration (Re-run Detection)
|
|
28
|
+
### 1. Check for Existing Configuration (Re-run Detection)
|
|
27
29
|
|
|
28
30
|
**Read existing forge-tier.yaml** at `{project-root}/_bmad/_memory/forger-sidecar/forge-tier.yaml`:
|
|
29
|
-
|
|
30
|
-
- If
|
|
31
|
+
|
|
32
|
+
- If exists: store the current `tier` value as `{previous_tier}`, `tier_detected_at` as `{previous_detection_date}`, and the `tools` map as `{previous_tools}` (for the tool-set delta detection step-04 needs to surface newly-installed tools on same-tier re-runs).
|
|
33
|
+
- If not found: set `{previous_tier}` to null and `{previous_tools}` to an empty map (first run).
|
|
31
34
|
|
|
32
35
|
**Read existing preferences.yaml** at `{project-root}/_bmad/_memory/forger-sidecar/preferences.yaml`:
|
|
36
|
+
|
|
33
37
|
- If exists: check for `tier_override` value
|
|
34
38
|
- If not found: set `{tier_override}` to null
|
|
35
39
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
Run: `ast-grep --version`
|
|
39
|
-
|
|
40
|
-
- If succeeds: record `{ast_grep: true}` and store version string
|
|
41
|
-
- If fails (command not found or error): record `{ast_grep: false}`
|
|
42
|
-
|
|
43
|
-
### 4. Verify Tool: gh
|
|
44
|
-
|
|
45
|
-
Run: `gh --version`
|
|
46
|
-
|
|
47
|
-
- If succeeds: record `{gh_cli: true}` and store version string
|
|
48
|
-
- If fails: record `{gh_cli: false}`
|
|
49
|
-
|
|
50
|
-
### 5. Verify Tool: qmd
|
|
51
|
-
|
|
52
|
-
Run: `qmd status`
|
|
53
|
-
|
|
54
|
-
- If succeeds and indicates operational: record `{qmd: true}`
|
|
55
|
-
- If fails or indicates not initialized: record `{qmd: false}`
|
|
56
|
-
|
|
57
|
-
### 6. Check Optional: Security Scan (SNYK_TOKEN)
|
|
58
|
-
|
|
59
|
-
Check if the `SNYK_TOKEN` environment variable is set:
|
|
60
|
-
|
|
61
|
-
- If `SNYK_TOKEN` is non-empty: record `{security_scan: true}`
|
|
62
|
-
- If `SNYK_TOKEN` is empty or unset: record `{security_scan: false}`
|
|
63
|
-
|
|
64
|
-
This is informational only — security scan availability does NOT affect the tier level. It is recorded in forge-tier.yaml so that create-skill's validation step can report actionable guidance when security scanning is unavailable.
|
|
65
|
-
|
|
66
|
-
### 7. Verify Tool: ccc (cocoindex-code)
|
|
40
|
+
**First-run preamble** — when `{previous_tier}` is null AND `{headless_mode}` is `false`, display this preamble before continuing so the user knows what is about to happen and can abort cleanly with Esc / Ctrl+C before any writes:
|
|
67
41
|
|
|
68
|
-
**
|
|
42
|
+
"**About to set up the forge.** This workflow will:
|
|
69
43
|
|
|
70
|
-
-
|
|
71
|
-
-
|
|
44
|
+
- Detect available tools (ast-grep, gh, qmd, ccc) — read-only probes only
|
|
45
|
+
- Write `{project-root}/_bmad/_memory/forger-sidecar/forge-tier.yaml` (capability tier + tool state)
|
|
46
|
+
- Write `{project-root}/_bmad/_memory/forger-sidecar/preferences.yaml` (first-run defaults)
|
|
47
|
+
- Create `{forge_data_folder}/` if missing
|
|
48
|
+
- When ccc is available: augment `{project-root}/.cocoindex_code/settings.yml` with SKF exclusion patterns, then create or refresh the project ccc index
|
|
72
49
|
|
|
73
|
-
**
|
|
50
|
+
**About tiers:** SKF picks one of four tiers (Quick / Forge / Forge+ / Deep) based on which tools are installed. **All four are fully usable** — higher tiers add power, they don't fix gaps. If you're new and only have a base Python install, Quick tier is the right starting point and the report at the end will show you exactly which tools to install if you want to climb later.
|
|
74
51
|
|
|
75
|
-
|
|
76
|
-
- If daemon is not running: record `{ccc: true, ccc_daemon: "stopped"}` — binary available, daemon needs starting. Step-01b will handle this.
|
|
77
|
-
- If error or timeout: record `{ccc: true, ccc_daemon: "error"}` — binary works but daemon has issues.
|
|
52
|
+
Press Esc or Ctrl+C now if this isn't the right project — no files have been written yet."
|
|
78
53
|
|
|
79
|
-
|
|
54
|
+
### 2. Run Detection Helper
|
|
80
55
|
|
|
81
|
-
|
|
56
|
+
Build the Bash invocation. Start with `uv run {detectToolsHelper}` — `uv run` honors the script's PEP 723 inline-metadata dependency declarations (resolved automatically on first call; cached thereafter), which is why uv is documented as a runtime prerequisite in `docs/getting-started.md`. Do NOT call the script via bare `python3` — `python3` ignores PEP 723 metadata, and on a fresh interpreter without the declared deps installed system-wide the call fails with `ModuleNotFoundError`. If `{tier_override}` is non-null, append `--tier-override "{tier_override}"` (the script handles invalid values by flagging them — do NOT pre-validate). If `{require_tier}` (resolved in On Activation) is non-null, append `--require-tier "{require_tier}"`. Then execute.
|
|
82
57
|
|
|
83
|
-
|
|
84
|
-
- Use `{tier_override}` as `{calculated_tier}`
|
|
85
|
-
- Note that override is active for the report step
|
|
58
|
+
The script (see `src/shared/scripts/skf-detect-tools.py` docstring for the full `DETECT_OUTPUT_SCHEMA`) probes ast-grep / gh / qmd / ccc concurrently with two-step verification for qmd and ccc (binary-identity check + daemon-health check, including the `CocoIndex Code` identity-marker substring check that rejects PATH-shadowing aliases). It applies the 4-rule tier table, performs the tier-override sanity check (override is honored but flagged unsafe when underlying tools are missing), and evaluates `--require-tier` using a tool-prerequisite check (Deep does NOT subsume Forge+ — Deep does not require ccc). Output is one JSON document on stdout.
|
|
86
59
|
|
|
87
|
-
|
|
88
|
-
- `{ast_grep}` AND `{gh_cli}` AND `{qmd}` all true → **Deep**
|
|
89
|
-
- `{ast_grep}` AND `{ccc}` both true, but NOT (`{gh_cli}` AND `{qmd}`) → **Forge+**
|
|
90
|
-
- `{ast_grep}` true (regardless of ccc/gh/qmd) → **Forge**
|
|
91
|
-
- Otherwise → **Quick**
|
|
60
|
+
### 3. Parse Output and Set Context Flags
|
|
92
61
|
|
|
93
|
-
|
|
62
|
+
From the JSON, set these context flags. Field paths are relative to the script's top-level object.
|
|
94
63
|
|
|
95
|
-
|
|
64
|
+
From `tools`:
|
|
96
65
|
|
|
97
|
-
|
|
66
|
+
- `{ast_grep}` ← `tools.ast_grep.available`
|
|
67
|
+
- `{ast_grep_version}` ← `tools.ast_grep.version`
|
|
68
|
+
- `{gh_cli}` ← `tools.gh_cli.available`
|
|
69
|
+
- `{gh_cli_version}` ← `tools.gh_cli.version`
|
|
70
|
+
- `{qmd}` ← `tools.qmd.available`
|
|
71
|
+
- `{qmd_status}` ← `tools.qmd.status` (`"absent" | "daemon_stopped" | "healthy"` — drives the climb-hint distinction in step-04)
|
|
72
|
+
- `{qmd_version}` ← `tools.qmd.version`
|
|
73
|
+
- `{ccc}` ← `tools.ccc.available`
|
|
74
|
+
- `{ccc_daemon}` ← `tools.ccc.daemon` (`"healthy" | "stopped" | "error" | null`)
|
|
75
|
+
- `{ccc_version}` ← `tools.ccc.version`
|
|
76
|
+
- `{security_scan}` ← `tools.security_scan.available` (informational only — never affects tier)
|
|
98
77
|
|
|
99
|
-
|
|
78
|
+
From `tier`:
|
|
100
79
|
|
|
101
|
-
-
|
|
80
|
+
- `{calculated_tier}` ← `tier.calculated` — the tier downstream steps act on
|
|
81
|
+
- `{detected_tier}` ← `tier.detected` — what would have been chosen without override
|
|
82
|
+
- `{tier_override_active}` ← `tier.override_applied`
|
|
83
|
+
- `{tier_override_invalid}` ← `tier.override_invalid`
|
|
84
|
+
- `{tier_override_invalid_value}` ← `tier.override_invalid_value`
|
|
85
|
+
- `{tier_override_invalid_suggestion}` ← `tier.override_invalid_suggestion` (closest valid tier name from a fuzzy match — `null` when no candidate cleared the cutoff or when override is valid; consumed by step-04's invalid-override note as a "did you mean ...?" hint)
|
|
86
|
+
- `{tier_override_unsafe}` ← `tier.override_unsafe`
|
|
87
|
+
- `{tier_override_unsafe_missing}` ← `tier.override_unsafe_missing` (a list — step-04 joins with `", "` for display)
|
|
102
88
|
|
|
103
|
-
|
|
89
|
+
From `require_tier`:
|
|
104
90
|
|
|
105
|
-
-
|
|
106
|
-
-
|
|
91
|
+
- `{require_tier_satisfied}` ← `require_tier.satisfied` (`true | false | null`; null when `--require-tier` was not set)
|
|
92
|
+
- `{require_tier_failure_missing_tools}` ← `require_tier.missing_tools` (a list)
|
|
107
93
|
|
|
108
|
-
|
|
94
|
+
**The script is the source of truth.** Every tier-rules edge case (override-honored-but-unsafe, Deep-doesn't-subsume-Forge+, qmd-binary-vs-daemon distinction, ccc-identity-marker rejection of foreign binaries) is locked into the test suite at `test/test-skf-detect-tools.py`. Substituting prose-driven logic for the script's output here will cause subtle re-run regressions that the prompt's prose is no longer detailed enough to catch.
|
|
109
95
|
|
|
110
|
-
|
|
96
|
+
### 4. Auto-Proceed
|
|
111
97
|
|
|
98
|
+
After context flags are populated, display "**Proceeding to CCC index check...**", then load `{nextStepFile}`, read it fully, and execute it.
|
|
@@ -1,31 +1,39 @@
|
|
|
1
1
|
---
|
|
2
2
|
nextStepFile: './step-02-write-config.md'
|
|
3
|
+
# Resolve `{mergeCccExclusionsHelper}` by probing `{mergeCccExclusionsProbeOrder}`
|
|
4
|
+
# in order (installed SKF module path first, src/ dev-checkout fallback); first
|
|
5
|
+
# existing path wins. HALT if neither resolves — the script owns config-value
|
|
6
|
+
# validation and the set-union merge into .cocoindex_code/settings.yml; no
|
|
7
|
+
# fallback to prose-driven validation.
|
|
8
|
+
mergeCccExclusionsProbeOrder:
|
|
9
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-merge-ccc-exclusions.py'
|
|
10
|
+
- '{project-root}/src/shared/scripts/skf-merge-ccc-exclusions.py'
|
|
3
11
|
---
|
|
4
12
|
|
|
13
|
+
<!-- Config: communicate in {communication_language}. User-visible status messages (CCC exclusion summary, indexing progress message) render in the user's language. -->
|
|
14
|
+
|
|
5
15
|
# Step 1b: CCC Index Verification
|
|
6
16
|
|
|
7
17
|
## STEP GOAL:
|
|
8
18
|
|
|
9
|
-
If ccc is available (`{ccc: true}` from step-01),
|
|
19
|
+
If ccc is available (`{ccc: true}` from step-01), invoke `{mergeCccExclusionsHelper}` to validate config-driven SKF exclusion patterns and merge them into `.cocoindex_code/settings.yml`, then verify the project's ccc index exists and create or refresh it if needed. Store index state and exclusion-merge results in context for step-02 to write into forge-tier.yaml and for step-04 to surface in the JSON envelope.
|
|
10
20
|
|
|
11
21
|
For Quick and Forge tiers, or when ccc is unavailable, skip silently and proceed.
|
|
12
22
|
|
|
13
23
|
## Rules
|
|
14
24
|
|
|
15
|
-
- Focus only on ccc index verification and
|
|
25
|
+
- Focus only on ccc index verification, exclusion-pattern merge, and (re-)indexing
|
|
16
26
|
- Do not display skip messages for Quick/Forge tiers
|
|
17
27
|
- Do not fail the workflow if ccc indexing fails
|
|
18
|
-
-
|
|
28
|
+
- Never reimplement the exclusion-pattern validation in prose — the script owns the PR #248 rules
|
|
19
29
|
|
|
20
30
|
## MANDATORY SEQUENCE
|
|
21
31
|
|
|
22
|
-
**CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise.
|
|
23
|
-
|
|
24
32
|
### 1. Check Eligibility
|
|
25
33
|
|
|
26
34
|
Read `{ccc}` from step-01 context.
|
|
27
35
|
|
|
28
|
-
**If `{ccc}` is false:** Set `{ccc_index_result: "none", ccc_indexed_path: null, ccc_last_indexed: null, ccc_exclude_patterns: []}`. Proceed directly to section 4 (Auto-Proceed) — no output, no messaging.
|
|
36
|
+
**If `{ccc}` is false:** Set `{ccc_index_result: "none", ccc_indexed_path: null, ccc_last_indexed: null, ccc_exclude_patterns: [], ccc_exclusion_warnings: [], settings_yml_written: false, settings_yml_patterns_added: 0}`. Proceed directly to section 4 (Auto-Proceed) — no output, no messaging.
|
|
29
37
|
|
|
30
38
|
**If `{ccc}` is true:** Continue to section 2.
|
|
31
39
|
|
|
@@ -36,81 +44,68 @@ Read existing forge-tier.yaml at `{project-root}/_bmad/_memory/forger-sidecar/fo
|
|
|
36
44
|
Read `staleness_threshold_hours` from `ccc_index.staleness_threshold_hours` in the existing forge-tier.yaml (default: 24 if not present or not a number). Use this value for the freshness check below.
|
|
37
45
|
|
|
38
46
|
Check the `ccc_index` section:
|
|
47
|
+
|
|
39
48
|
- If `ccc_index.indexed_path` matches `{project-root}` AND `ccc_index.status` is `"fresh"` or `"created"`:
|
|
40
49
|
- Check freshness: if `ccc_index.last_indexed` is within `staleness_threshold_hours` of now → index is fresh
|
|
41
50
|
- Store `{ccc_index_result: "fresh", ccc_indexed_path: {project-root}, ccc_last_indexed: {existing timestamp}}`
|
|
42
|
-
- Set `{needs_reindex: false}` —
|
|
51
|
+
- Set `{needs_reindex: false}` — exclusions still get merged in section 3, which may force a re-index
|
|
43
52
|
|
|
44
53
|
- If `ccc_index.indexed_path` matches `{project-root}` but timestamp is older than threshold:
|
|
45
|
-
- Set `{needs_reindex: true}`
|
|
54
|
+
- Set `{needs_reindex: true}`
|
|
46
55
|
|
|
47
56
|
- If `ccc_index` is missing, has null values, or path doesn't match:
|
|
48
|
-
- Set `{needs_reindex: true}`
|
|
57
|
+
- Set `{needs_reindex: true}`
|
|
49
58
|
|
|
50
|
-
###
|
|
59
|
+
### 3. Merge SKF Exclusion Patterns
|
|
51
60
|
|
|
52
61
|
SKF infrastructure and output directories must be excluded from the CCC index — they contain workflow instructions, build artifacts, and generated skills that pollute semantic search results with zero extraction value.
|
|
53
62
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
1. Use `{skills_output_folder}` and `{forge_data_folder}` from the workflow activation context (resolved in On Activation from `{project-root}/_bmad/skf/config.yaml`).
|
|
57
|
-
|
|
58
|
-
2. Assemble the exclusion patterns using `**/` prefix format (matching `.cocoindex_code/settings.yml` convention — e.g., `**/node_modules`):
|
|
59
|
-
- `**/_bmad` — SKF framework module (workflows, agents, knowledge files)
|
|
60
|
-
- `**/_bmad-output` — Build output artifacts
|
|
61
|
-
- `**/.claude` — Claude Code configuration
|
|
62
|
-
- `**/_skf-learn` — SKF learning materials
|
|
63
|
-
- `**/{skills_output_folder}` — Generated skill files (from activation context)
|
|
64
|
-
- `**/{forge_data_folder}` — Compilation workspace (from activation context)
|
|
65
|
-
|
|
66
|
-
3. Store `{ccc_exclude_patterns}` in context for step-02 to write into forge-tier.yaml.
|
|
63
|
+
Run the merge helper, forwarding the resolved config values from the workflow activation context. Invoke via `uv run` so PEP 723 inline metadata resolves the script's PyYAML dependency automatically (per `docs/getting-started.md`'s prereq list — uv exists for this exact purpose). Bare `python3` will fail on a fresh Python with `ModuleNotFoundError: No module named 'yaml'`.
|
|
67
64
|
|
|
68
|
-
|
|
65
|
+
```bash
|
|
66
|
+
uv run {mergeCccExclusionsHelper} \
|
|
67
|
+
--project-root "{project-root}" \
|
|
68
|
+
--skills-output-folder "{skills_output_folder}" \
|
|
69
|
+
--forge-data-folder "{forge_data_folder}"
|
|
70
|
+
```
|
|
69
71
|
|
|
70
|
-
|
|
72
|
+
The script (see `src/shared/scripts/skf-merge-ccc-exclusions.py` docstring for the full schema) builds the SKF exclusion list (4 always-include hardcoded patterns + 2 conditional from validated config), applies the PR #248 validation rules to reject empty / absolute / glob-meta config values with actionable warnings, and performs an idempotent set-union merge into `{project-root}/.cocoindex_code/settings.yml`. User customizations are preserved. When the file does not exist yet (first-time setup before `ccc init`) the script creates it; when nothing new needs adding the script skips the write entirely (mtime preserved).
|
|
71
73
|
|
|
72
|
-
|
|
74
|
+
**Parse the JSON output and set context flags:**
|
|
73
75
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
4.
|
|
76
|
+
- `{settings_yml_existed}` ← `settings_yml_existed`
|
|
77
|
+
- `{settings_yml_written}` ← `written`
|
|
78
|
+
- `{settings_yml_patterns_added}` ← `patterns_added`
|
|
79
|
+
- `{ccc_exclude_patterns}` ← derive from the script's behaviour: it always merges the 4 always-include patterns plus any of the 2 config-driven ones whose value passed validation. Step-02 needs this list to write `ccc_index.exclude_patterns` into forge-tier.yaml — read it from the script's `patterns_added_list` PLUS any already-present matching SKF patterns inferred from the input. Pragmatically: re-derive the list as `["**/_bmad", "**/_bmad-output", "**/.claude", "**/_skf-learn"]` plus `"**/{skills_output_folder}"` if no warning names `skills_output_folder` plus `"**/{forge_data_folder}"` if no warning names `forge_data_folder`.
|
|
80
|
+
- `{ccc_exclusion_warnings}` ← `warnings` (a list — step-04 folds them into the envelope's warnings array)
|
|
78
81
|
|
|
79
|
-
|
|
82
|
+
**If `{settings_yml_written}` is true** (new patterns merged into settings.yml): set `{needs_reindex: true}` — new exclusions require re-indexing for the index to reflect them. Display: "**CCC exclusions configured:** {patterns_added} SKF patterns applied to .cocoindex_code/settings.yml"
|
|
80
83
|
|
|
81
|
-
If `{
|
|
84
|
+
**If `{settings_yml_written}` is false** (idempotent re-run, all patterns already present): display nothing (exclusions already configured). Do NOT change `{needs_reindex}` — it stays at whatever section 2 set it to.
|
|
82
85
|
|
|
83
86
|
**Flow decision:**
|
|
84
|
-
- If `{needs_reindex}` is true: proceed to section 3
|
|
85
|
-
- If `{needs_reindex}` is false: proceed to section 4 (Auto-Proceed)
|
|
86
|
-
|
|
87
|
-
### 3. Create or Refresh CCC Index
|
|
88
87
|
|
|
89
|
-
|
|
88
|
+
- If `{needs_reindex}` is true: proceed to section 4
|
|
89
|
+
- If `{needs_reindex}` is false: proceed to section 5 (Auto-Proceed)
|
|
90
90
|
|
|
91
|
-
|
|
91
|
+
### 4. Create or Refresh CCC Index
|
|
92
92
|
|
|
93
|
-
**If `{ccc_daemon}` is `"
|
|
93
|
+
**If `{ccc_daemon}` is `"stopped"` or `"healthy"`:** the `ccc index` command auto-starts the daemon when needed.
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
**If `{ccc_daemon}` is `"error"`:** attempt indexing anyway — errors will be caught below.
|
|
96
96
|
|
|
97
97
|
Run (CWD must be `{project-root}`):
|
|
98
|
+
|
|
98
99
|
```bash
|
|
99
100
|
ccc init
|
|
100
101
|
```
|
|
101
102
|
|
|
102
|
-
**If init fails** (project may already be initialized): continue — this is not an error.
|
|
103
|
-
|
|
104
|
-
**Apply SKF exclusion patterns (if not already applied in section 2b):**
|
|
103
|
+
**If init fails** (project may already be initialized): continue — this is not an error. Note: when `{settings_yml_existed}` was false and `ccc init` just created the settings.yml, the merge in section 3 ran BEFORE ccc init. The script handles "no settings.yml exists" by creating one with just the SKF exclusions, which `ccc init` will then either preserve (if it merges) or overwrite (in which case the next workflow run re-merges). Either way the SKF exclusions end up in the file by the time `ccc index` runs the second time.
|
|
105
104
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
1. Read `{project-root}/.cocoindex_code/settings.yml` (created by `ccc init`)
|
|
109
|
-
2. For each pattern in `{ccc_exclude_patterns}`: if the pattern is NOT already present in `exclude_patterns`, append it
|
|
110
|
-
3. Write the updated `settings.yml` back
|
|
111
|
-
4. Display: "**CCC exclusions configured:** {count} SKF patterns applied to .cocoindex_code/settings.yml"
|
|
105
|
+
Before invoking `ccc index`, display: "**Building semantic index — this can take several minutes on large codebases (1000+ files). Run `ccc status` in another terminal to monitor progress.**" so the user does not assume the workflow has hung during the long-running call.
|
|
112
106
|
|
|
113
107
|
Then run:
|
|
108
|
+
|
|
114
109
|
```bash
|
|
115
110
|
ccc index
|
|
116
111
|
```
|
|
@@ -118,29 +113,17 @@ ccc index
|
|
|
118
113
|
**Note:** `ccc index` can take several minutes on large codebases (1000+ files). Run with an extended timeout or in background mode. Use `ccc status` to verify completion — check that `Chunks` and `Files` counts are non-zero.
|
|
119
114
|
|
|
120
115
|
**If succeeds:**
|
|
116
|
+
|
|
121
117
|
- Run `ccc status` to get file count
|
|
122
118
|
- Store `{ccc_index_result: "created", ccc_indexed_path: {project-root}, ccc_last_indexed: {current ISO timestamp}, ccc_file_count: {count from ccc status}}`
|
|
123
119
|
- Display: "**CCC index created.** {ccc_file_count} files indexed for semantic discovery."
|
|
124
120
|
|
|
125
121
|
**If fails:**
|
|
126
|
-
|
|
122
|
+
|
|
123
|
+
- Store `{ccc_index_result: "failed", ccc_indexed_path: null, ccc_last_indexed: null, ccc_indexing_failed_reason: {error}}` (the failed-reason flag flows into step-04's envelope warnings)
|
|
127
124
|
- Display: "CCC indexing failed: {error}. Extraction will use direct AST scanning — semantic pre-ranking unavailable this session."
|
|
128
125
|
- Continue — this is NOT a workflow error
|
|
129
126
|
|
|
130
|
-
###
|
|
131
|
-
|
|
132
|
-
"**Proceeding to write configuration...**"
|
|
133
|
-
|
|
134
|
-
#### Menu Handling Logic:
|
|
135
|
-
|
|
136
|
-
- After ccc index check completes (or is skipped), immediately load, read entire file, then execute {nextStepFile}
|
|
137
|
-
|
|
138
|
-
#### EXECUTION RULES:
|
|
139
|
-
|
|
140
|
-
- This is an auto-proceed step with no user choices
|
|
141
|
-
- Proceed directly to next step after ccc index verification
|
|
142
|
-
|
|
143
|
-
## CRITICAL STEP COMPLETION NOTE
|
|
144
|
-
|
|
145
|
-
ONLY WHEN ccc index verification is complete (or step is skipped for ccc unavailable) will you load and read fully `{nextStepFile}` to execute the configuration write step.
|
|
127
|
+
### 5. Auto-Proceed
|
|
146
128
|
|
|
129
|
+
After ccc index verification is complete (or skipped because ccc is unavailable), display "**Proceeding to write configuration...**", then load `{nextStepFile}`, read it fully, and execute it.
|