bmad-module-skill-forge 1.3.0 → 1.4.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/docs/_data/pinned.yaml +1 -1
- package/docs/workflows.md +34 -15
- package/package.json +2 -2
- package/src/shared/scripts/schemas/skf-brief-result-envelope.v1.json +58 -0
- package/src/shared/scripts/schemas/skill-brief.v1.json +77 -0
- package/src/shared/scripts/schemas/workspace-detection.v1.json +44 -0
- package/src/shared/scripts/skf-detect-language.py +277 -0
- package/src/shared/scripts/skf-detect-workspaces.py +427 -0
- package/src/shared/scripts/skf-emit-brief-result-envelope.py +257 -0
- package/src/shared/scripts/skf-extract-public-api.py +29 -0
- package/src/shared/scripts/skf-forge-tier-rw.py +73 -0
- package/src/shared/scripts/skf-recommend-scope-type.py +369 -0
- package/src/shared/scripts/skf-validate-brief-inputs.py +293 -0
- package/src/shared/scripts/skf-write-skill-brief.py +509 -0
- package/src/skf-brief-skill/SKILL.md +41 -12
- package/src/skf-brief-skill/assets/description-voice-examples.md +19 -0
- package/src/skf-brief-skill/assets/scope-templates.md +5 -0
- package/src/skf-brief-skill/assets/skill-brief-schema.md +1 -40
- package/src/skf-brief-skill/references/draft-checkpoint.md +46 -0
- package/src/skf-brief-skill/references/headless-args.md +22 -0
- package/src/skf-brief-skill/references/headless-source-authority-detection.md +26 -0
- package/src/skf-brief-skill/references/portfolio-similarity-check.md +35 -0
- package/src/skf-brief-skill/references/qmd-collection-registration.md +52 -0
- package/src/skf-brief-skill/references/version-resolution.md +46 -0
- package/src/skf-brief-skill/steps-c/step-01-gather-intent.md +164 -14
- package/src/skf-brief-skill/steps-c/step-02-analyze-target.md +118 -50
- package/src/skf-brief-skill/steps-c/step-03-scope-definition.md +48 -5
- package/src/skf-brief-skill/steps-c/step-04-confirm-brief.md +33 -19
- package/src/skf-brief-skill/steps-c/step-05-write-brief.md +93 -97
- package/src/skf-brief-skill/steps-c/step-06-health-check.md +11 -2
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
nextStepFile: './step-03-scope-definition.md'
|
|
3
|
+
versionResolutionFile: 'references/version-resolution.md'
|
|
4
|
+
extractPublicApiScript: '{project-root}/src/shared/scripts/skf-extract-public-api.py'
|
|
5
|
+
detectWorkspacesScript: '{project-root}/src/shared/scripts/skf-detect-workspaces.py'
|
|
6
|
+
detectLanguageScript: '{project-root}/src/shared/scripts/skf-detect-language.py'
|
|
3
7
|
---
|
|
4
8
|
|
|
5
9
|
# Step 2: Analyze Target
|
|
@@ -13,6 +17,7 @@ To analyze the target repository by resolving its location, reading its structur
|
|
|
13
17
|
- Focus only on analysis — do not define scope yet (Step 03)
|
|
14
18
|
- Do not make scoping decisions or recommendations
|
|
15
19
|
- Do not hallucinate or guess about repository contents
|
|
20
|
+
- All user-facing output in `{communication_language}`
|
|
16
21
|
|
|
17
22
|
## MANDATORY SEQUENCE
|
|
18
23
|
|
|
@@ -21,23 +26,68 @@ To analyze the target repository by resolving its location, reading its structur
|
|
|
21
26
|
### 1. Resolve Target Location
|
|
22
27
|
|
|
23
28
|
**For GitHub URLs:**
|
|
24
|
-
-
|
|
25
|
-
-
|
|
29
|
+
- Issue both probes in **one message with two parallel Bash calls** — they are independent:
|
|
30
|
+
- `gh api repos/{owner}/{repo}` (verify repo exists)
|
|
31
|
+
- `gh api repos/{owner}/{repo}/git/trees/HEAD?recursive=1` (fetch file tree)
|
|
32
|
+
- If the repo-existence probe fails, fall through to the failure-class triage below; the tree response from the parallel call is discarded in that case.
|
|
26
33
|
|
|
27
34
|
**Truncation detection:** After receiving the tree response, check the `truncated` field in the JSON output. If `truncated: true`:
|
|
28
35
|
- Display: "Note: GitHub API returned a truncated tree response ({count} items). Full analysis may require a local clone."
|
|
29
36
|
- Record in analysis summary: "Tree listing is partial — some files may not appear in the analysis."
|
|
30
|
-
- For very large repos (>1000 files in tree response):
|
|
37
|
+
- For very large repos (>1000 files in tree response): offer a recovery path instead of just warning. Interactive — present:
|
|
38
|
+
```
|
|
39
|
+
Tree is truncated. How would you like to proceed?
|
|
40
|
+
[L] Clone locally and re-analyze (slower but complete)
|
|
41
|
+
[P] Proceed with the partial tree (faster, may miss exports under deeper paths)
|
|
42
|
+
```
|
|
43
|
+
On `[L]`: shallow-clone (`git clone --depth 1 {url} {tmp_dir}`), restart this section against the local path, and remove `{tmp_dir}` after the analysis summary in §5. On `[P]` (or under headless): record `tree_truncated: true` in the analysis summary and continue without HALT.
|
|
31
44
|
|
|
32
|
-
|
|
45
|
+
**On API failure (non-200 from `gh api`):**
|
|
46
|
+
|
|
47
|
+
Distinguish the failure class before reporting:
|
|
48
|
+
- Auto-run `gh auth status` and capture its output. If it reports an unauthenticated state or expired token: HALT (exit code 3, `halt_reason: "gh-auth-failed"`) — "**Error:** GitHub CLI is not authenticated. `gh auth status` says: `{captured output}`. Run `gh auth login` and retry."
|
|
49
|
+
- If `gh auth status` reports authenticated but the call still failed (404/403): HALT (exit code 3, `halt_reason: "target-inaccessible"`) — "**Error:** Cannot access repository at `{url}`. The CLI is authenticated but the API returned `{status}`. Check the URL and that the account has access to private repositories if applicable."
|
|
50
|
+
- If `gh auth status` itself fails to run (binary missing): HALT (exit code 3, `halt_reason: "gh-auth-failed"`) — "**Error:** `gh` CLI not found on PATH. Install it from <https://cli.github.com> and re-run."
|
|
33
51
|
|
|
34
52
|
**For local paths:**
|
|
35
53
|
- Verify the directory exists
|
|
36
54
|
- List the directory tree
|
|
37
|
-
- If path doesn't exist: **HALT** — "**Error:** Directory not found at {path}.
|
|
55
|
+
- If path doesn't exist: **HALT** — "**Error:** Directory not found at {path}. Verify the path is correct."
|
|
38
56
|
|
|
39
57
|
Display: "**Resolving target...**"
|
|
40
58
|
|
|
59
|
+
### 1b. Detect Monorepo / Workspace Layout
|
|
60
|
+
|
|
61
|
+
Delegate workspace detection to `{detectWorkspacesScript}` instead of reasoning through manifest rules in prose. Build a payload from the tree fetched in §1 plus the small set of root manifests the detector needs, then invoke the script:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
echo '{"tree": [<flat list of repo-relative file paths>], "manifests": {"package.json": "<raw text>", "Cargo.toml": "<raw text>", "pnpm-workspace.yaml": "<raw text>", "lerna.json": "<raw text>"}}' | \
|
|
65
|
+
uv run {detectWorkspacesScript}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
- **`tree`** — pass the flat list of repo-relative file paths already fetched in §1 (for GitHub: the `path` values from the `gh api .../git/trees/HEAD?recursive=1` response; for local: the equivalent listing).
|
|
69
|
+
- **`manifests`** — only the root manifests need contents; child-workspace manifests are looked up from the tree by the script. Include any of `package.json`, `Cargo.toml`, `pnpm-workspace.yaml`, `lerna.json` that appears at the repo root. Fetch them in **one message with N parallel Bash calls** (`gh api .../contents/{path}` for GitHub, file reads for local), then base64-decode together. Per-workspace manifest contents (e.g. `packages/foo/package.json`) are optional — including them populates the workspace `name` field with the manifest's declared package name; omitting them falls back to the directory basename.
|
|
70
|
+
|
|
71
|
+
The script returns a JSON envelope: `{is_monorepo, manifest_kind, workspaces[], warnings[]}`. Apply the result deterministically — see `src/shared/scripts/schemas/workspace-detection.v1.json` for the full contract.
|
|
72
|
+
|
|
73
|
+
**If `is_monorepo: false`** — skip this section silently and continue to §2.
|
|
74
|
+
|
|
75
|
+
**If `is_monorepo: true`** — present the discovered workspaces and prompt:
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
This looks like a monorepo ({manifest_kind}) with these workspaces:
|
|
79
|
+
1. {workspaces[0].name} ({workspaces[0].path})
|
|
80
|
+
2. {workspaces[1].name} ({workspaces[1].path})
|
|
81
|
+
...
|
|
82
|
+
Which one should the skill cover? Pick a number, type 'all' to scope at the repo root, or 'list' to keep listing more.
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Interactive: wait for the user choice. On a numbered choice, store `monorepo_workspace: {path}` and rebase §2-§4b against that path. On `'all'`, leave `monorepo_workspace` unset and proceed at the repo root with a note in the analysis summary that scope is unfiltered.
|
|
86
|
+
|
|
87
|
+
Headless: if the input contract supplied an `include` glob that begins with one of the workspace paths, auto-select that workspace (log `"headless: auto-selected workspace {name} from include glob"`). Otherwise default to repo root and log `"warn: monorepo detected ({manifest_kind}) but no workspace pre-selected — analyzing at repo root"`.
|
|
88
|
+
|
|
89
|
+
Surface any non-empty `warnings[]` from the script to the operator log so a malformed root manifest is debuggable; the workflow does not HALT — falling back to repo-root analysis is always safe.
|
|
90
|
+
|
|
41
91
|
### 2. Read Repository Structure
|
|
42
92
|
|
|
43
93
|
List the top-level directory structure:
|
|
@@ -54,53 +104,79 @@ List the top-level directory structure:
|
|
|
54
104
|
|
|
55
105
|
### 3. Detect Primary Language
|
|
56
106
|
|
|
57
|
-
|
|
107
|
+
Delegate the rule walk to `{detectLanguageScript}` instead of evaluating manifest presence and extension frequency in prose:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
echo '{"tree": [<flat list of repo-relative file paths from §1>]}' | uv run {detectLanguageScript}
|
|
111
|
+
```
|
|
58
112
|
|
|
59
|
-
|
|
60
|
-
1. `package.json` → JavaScript/TypeScript
|
|
61
|
-
2. `tsconfig.json` → TypeScript
|
|
62
|
-
3. `Cargo.toml` → Rust
|
|
63
|
-
4. `pyproject.toml` or `setup.py` or `setup.cfg` → Python
|
|
64
|
-
5. `go.mod` → Go
|
|
65
|
-
6. `pom.xml` or `build.gradle` → Java
|
|
66
|
-
7. `*.csproj` or `*.sln` → C#
|
|
67
|
-
8. `Gemfile` → Ruby
|
|
68
|
-
9. File extension frequency analysis as fallback
|
|
113
|
+
The script returns `{language, confidence, detection_source, fallback_to_extension_frequency}` after walking the documented rule table (manifest presence first — package.json with tsconfig.json disambiguation, Cargo.toml, pyproject.toml/setup.py/setup.cfg, go.mod, pom.xml, build.gradle.kts, build.gradle Groovy with Java/Kotlin disambiguation, *.csproj/*.sln, Gemfile — then extension-frequency fallback over recognized source extensions). Use the returned values directly:
|
|
69
114
|
|
|
70
115
|
"**Detected language:** {language}
|
|
71
|
-
**Confidence:** {
|
|
72
|
-
**Detection source:** {
|
|
116
|
+
**Confidence:** {confidence}
|
|
117
|
+
**Detection source:** {detection_source}"
|
|
73
118
|
|
|
74
|
-
If confidence is low or
|
|
119
|
+
If `confidence` is `low` (or `unknown` is returned for `language`): flag for user override in step 03 §4.
|
|
75
120
|
|
|
76
121
|
### 4. List Top-Level Modules and Exports
|
|
77
122
|
|
|
78
|
-
|
|
123
|
+
Identify the public API surface. **Delegate the parsing to `{extractPublicApiScript}` whenever the detected language is supported** — the script is the single source of truth for manifest parsing, export discovery, and version detection across the whole SKF pipeline. Hand-rolling these in prose creates drift seams the LLM cannot fully close.
|
|
79
124
|
|
|
80
|
-
**
|
|
81
|
-
- Check `package.json` for `main`, `exports`, `module` fields
|
|
82
|
-
- Look for `index.ts`/`index.js` in `src/`
|
|
83
|
-
- List directories under `src/` as potential modules
|
|
125
|
+
**Script-supported languages** (use the script): `js`, `ts`, `javascript`, `typescript`, `python`, `rust`, `go`, `java`, `kotlin`.
|
|
84
126
|
|
|
85
|
-
|
|
86
|
-
- Check `__init__.py` files for public exports
|
|
87
|
-
- List top-level packages under the source directory
|
|
127
|
+
This section runs exactly one of §4.1 (script path) or §4.2 (fallback path) based on the detected language, then always emits §4.3 (output format) and conditionally §4.4 (semantic signals).
|
|
88
128
|
|
|
89
|
-
|
|
90
|
-
- Check `lib.rs` for `pub mod` declarations
|
|
91
|
-
- List modules from `src/` directory
|
|
129
|
+
#### 4.1 Procedure — script-supported languages
|
|
92
130
|
|
|
93
|
-
**For
|
|
94
|
-
|
|
95
|
-
|
|
131
|
+
1. Read the relevant files into memory (no parsing yet — just collect content). For GitHub sources, issue **all N `gh api repos/{owner}/{repo}/contents/{file}` calls in a single message with N parallel Bash calls** (one per manifest + each entry point), then base64-decode the responses together — these are 2-4 independent fetches per typical run. For local sources read directly (also parallelisable, but local reads are fast enough that serial Read tool calls are acceptable).
|
|
132
|
+
|
|
133
|
+
| Language | Manifest | Entry points (mode=quick) |
|
|
134
|
+
|----------|----------|--------------------------|
|
|
135
|
+
| js / ts / javascript / typescript | `package.json` (root, or primary workspace package per `references/version-resolution.md`) | `index.{ts,js}` and/or `src/index.{ts,js}` if present |
|
|
136
|
+
| python | `pyproject.toml` (or `setup.py` / `setup.cfg` if no `pyproject.toml`) | top-level `__init__.py` of the package, plus `_version.py` if present |
|
|
137
|
+
| rust | `Cargo.toml` (`[package]` — workspace root if `version = { workspace = true }`) | `src/lib.rs` |
|
|
138
|
+
| go | `go.mod` | top-level `*.go` exporting the package surface |
|
|
139
|
+
| java | `pom.xml` | (manifest alone is sufficient for the modules listing) |
|
|
140
|
+
| kotlin | `build.gradle` / `build.gradle.kts` | (manifest alone) |
|
|
141
|
+
|
|
142
|
+
2. Build a JSON payload matching the script contract:
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"language": "<one of the supported values>",
|
|
147
|
+
"manifest": {"path": "<relative path>", "content": "<file contents>"},
|
|
148
|
+
"entries": [{"path": "<relative path>", "content": "<file contents>"}, ...],
|
|
149
|
+
"mode": "quick"
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
3. Invoke the script and parse its JSON stdout:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
echo '<payload-json>' | uv run {extractPublicApiScript} --language <lang> --mode quick
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
On a non-zero exit (codes 1 or 2 per the script's docstring), capture stderr, log it, and fall through to §4.2 (the prose-fallback path) — never HALT just because the script choked on an unusual manifest.
|
|
160
|
+
|
|
161
|
+
4. Render the returned `package_name`, `exports` (each entry's `name`/`type`/`source_file`), `dependencies`, and any `warnings` to the user. The script also returns `version` — feed that into §4b instead of re-deriving.
|
|
162
|
+
|
|
163
|
+
5. The script does not enumerate directories under `src/`. The LLM still lists those as "Top-Level Modules/Directories" so the user sees structural context (Maven and Gradle are the exception — for those, the script returns a `modules` array which IS the list).
|
|
164
|
+
|
|
165
|
+
#### 4.2 Procedure — fallback (not script-supported)
|
|
166
|
+
|
|
167
|
+
Languages outside the script coverage (Ruby / C# / Swift / etc.) take this path. The §4.1 fall-through on script error also lands here.
|
|
168
|
+
|
|
169
|
+
Fall back to ad-hoc inspection — `Gemfile` / `*.csproj` / `*.sln` / `Package.swift` / file extension frequency. List top-level source directories as potential modules and note any obvious entry points. Flag the limitation in the analysis summary so the user knows scoping is on coarser signals.
|
|
170
|
+
|
|
171
|
+
#### 4.3 Output format (both paths)
|
|
96
172
|
|
|
97
173
|
"**Top-Level Modules/Directories:**
|
|
98
174
|
{numbered list of modules with brief description of each}
|
|
99
175
|
|
|
100
176
|
**Detected Exports/Entry Points:**
|
|
101
|
-
{numbered list of public-facing items found}"
|
|
177
|
+
{numbered list of public-facing items found — from script output when available, ad-hoc inspection otherwise}"
|
|
102
178
|
|
|
103
|
-
|
|
179
|
+
#### 4.4 Semantic Signals (Forge+/Deep with ccc only)
|
|
104
180
|
|
|
105
181
|
**Remote source guard:** If the target source was resolved via GitHub API (remote URL, not a local file path), skip this CCC subsection — CCC requires a local source index and cannot operate on remote-only sources. Note: "CCC semantic discovery skipped — target is remote. CCC discovery will run automatically during create-skill after the source is cloned."
|
|
106
182
|
|
|
@@ -124,29 +200,21 @@ If CCC is unavailable or returns no results: skip this subsection silently.
|
|
|
124
200
|
|
|
125
201
|
### 4b. Detect Source Version
|
|
126
202
|
|
|
127
|
-
**
|
|
128
|
-
- Display: "**Target version:** {target_version} (user-specified)"
|
|
129
|
-
- Still run auto-detection below for informational purposes.
|
|
203
|
+
**When the language was script-supported (§4 took the script path):** the `version` field returned by `{extractPublicApiScript}` IS the detected version — do not re-derive it and do not load `{versionResolutionFile}`. The script already implements the language-specific lookups documented in that reference, so loading the reference here only burns context.
|
|
130
204
|
|
|
131
|
-
|
|
205
|
+
**When the language was not script-supported:** load `{versionResolutionFile}` and follow the prose Detection Algorithm directly (Ruby / C# / Swift / etc. fall outside the script's coverage).
|
|
132
206
|
|
|
133
|
-
|
|
134
|
-
**For JavaScript/TypeScript:** Check root `package.json` `"version"` field → if root has `"private": true` with a `"workspaces"` array or lacks a `"version"` field, fall back to a primary workspace package's `package.json` (e.g., `code/core/package.json`, or the first matching `packages/*/package.json`). For GitHub sources, prefer `gh api repos/{owner}/{repo}/releases/latest` → `tag_name` when a non-pre-release tag exists, over a default-branch pre-release. Treat a version containing `-alpha`, `-beta`, `-rc`, `-next`, or `-canary` as a pre-release.
|
|
135
|
-
**For Rust:** Check `Cargo.toml` `[package] version` (static) → if `version = { workspace = true }`, resolve from workspace root `Cargo.toml` → `git describe --tags --abbrev=0`
|
|
136
|
-
**For Go:** Check `go.mod` or `git describe --tags --abbrev=0`
|
|
207
|
+
Surface the result regardless of which path produced it:
|
|
137
208
|
|
|
138
|
-
**
|
|
139
|
-
**
|
|
209
|
+
**If `target_version` was provided in step 01:**
|
|
210
|
+
- Display: "**Target version:** {target_version} (user-specified)"
|
|
140
211
|
|
|
141
212
|
Display: "**Detected version:** {version or 'Not detected — will default to 1.0.0'}"
|
|
142
213
|
|
|
143
214
|
{If target_version was provided AND auto-detected version differs:}
|
|
144
|
-
"**Note:** Detected version ({detected_version}) differs from your target version ({target_version}). Using target version."
|
|
145
|
-
|
|
146
|
-
{If target_version was provided:}
|
|
147
|
-
Store `target_version` as the brief's `version` field (overrides auto-detection).
|
|
215
|
+
"**Note:** Detected version ({detected_version}) differs from your target version ({target_version}). Using target version (per `references/version-resolution.md` precedence rules)."
|
|
148
216
|
|
|
149
|
-
If detection fails or returns a non-semver value: note that version will default to `"1.0.0"` and the user can override in step 04.
|
|
217
|
+
If detection fails or returns a non-semver value: note that version will default to `"1.0.0"` and the user can override in step 04. The actual write happens in step 05.
|
|
150
218
|
|
|
151
219
|
### 5. Report Analysis Summary
|
|
152
220
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
nextStepFile: './step-04-confirm-brief.md'
|
|
3
3
|
scopeTemplatesFile: 'assets/scope-templates.md'
|
|
4
|
+
recommendScopeTypeScript: '{project-root}/src/shared/scripts/skf-recommend-scope-type.py'
|
|
4
5
|
advancedElicitationSkill: '/bmad-advanced-elicitation'
|
|
5
6
|
partyModeSkill: '/bmad-party-mode'
|
|
6
7
|
---
|
|
@@ -16,6 +17,8 @@ To collaboratively define the skill's inclusion and exclusion boundaries using t
|
|
|
16
17
|
- Focus only on defining scope boundaries — do not write the brief yet (Step 05)
|
|
17
18
|
- Do not make scope decisions unilaterally — user drives all scope choices
|
|
18
19
|
- Produce: scope type, include patterns, exclude patterns
|
|
20
|
+
- All user-facing output in `{communication_language}`
|
|
21
|
+
- **Re-entry from step-04 [R] revise:** prior selections (`scope.type`, `scope.include`, `scope.exclude`, `scope.notes`, `scripts_intent`, `assets_intent`, supplemental `doc_urls`) are preserved as the current state. Re-present them at each section as the existing answer; the user only re-confirms or overrides. Do not reset to the §2c template menu unless the user explicitly asks to start scope over.
|
|
19
22
|
|
|
20
23
|
## MANDATORY SEQUENCE
|
|
21
24
|
|
|
@@ -65,6 +68,10 @@ Add, remove, or confirm these URLs."
|
|
|
65
68
|
|
|
66
69
|
Wait for confirmation. Record any changes to `doc_urls`.
|
|
67
70
|
|
|
71
|
+
HEAD-check the URLs in parallel — issue all N `curl -sI --max-time 5 {url}` calls in a **single message with N parallel Bash calls**, then process the responses together. On a 4xx/5xx, DNS failure, or timeout per URL, warn `"Could not reach {url} — {status or error}."` and offer the same correct/keep choice as step-01 §3. The check is best-effort — never HALT on a failed HEAD — but the failure must surface here so it is not discovered downstream during compilation.
|
|
72
|
+
|
|
73
|
+
**On re-entry from step-04 [R]:** if `doc_urls` is byte-identical to the list that was probed on the previous pass through this subsection AND the prior per-URL probe results are still recoverable from conversation context, skip the parallel HEAD-check and reuse those results. Re-running the probes when the list has not changed wastes round-trips and can flap on transient failures. Any addition, removal, or edit to a URL invalidates the cache — re-probe the entire updated set. If the prior results are not recoverable (long session, compaction, etc.), re-probe — never cache-hit on a list whose results you cannot cite.
|
|
74
|
+
|
|
68
75
|
**If no supplemental doc_urls were collected:** Skip this subsection.
|
|
69
76
|
|
|
70
77
|
**Scope guidance for first-time users:** A well-scoped skill covers one cohesive capability with 3-8 primary functions. If the scope includes unrelated concerns (e.g., authentication AND data visualization), suggest splitting into separate briefs. If the scope is too narrow (single utility function), suggest expanding to the surrounding capability surface.
|
|
@@ -73,11 +80,41 @@ Wait for confirmation. Record any changes to `doc_urls`.
|
|
|
73
80
|
|
|
74
81
|
Load `{scopeTemplatesFile}` for the scope type options ([F], [M], [P], [C], [R]) and their descriptions.
|
|
75
82
|
|
|
76
|
-
|
|
83
|
+
**Recommend a scope type — don't present the five options as equal weight.** SKILL.md states this workflow "steers toward the smaller, sharper version when scope is unclear" — surface that opinion at decision time. Use the analysis from step-02 and the user's intent from step-01 to pick the best-fit recommendation, then present the menu with that option marked as the suggested default.
|
|
84
|
+
|
|
85
|
+
**Delegate the recommendation to `{recommendScopeTypeScript}`** instead of walking the heuristic ladder in prose. The script is the single source of truth for the five-rule ladder (component-registry → reference-app keywords → specific-modules naming/count → narrow-public-api → default full-library) plus the docs-only short-circuit. Both the interactive recommendation and the §6 headless GATE invoke the same script — same inputs, same outputs, no drift.
|
|
86
|
+
|
|
87
|
+
**Fetch registry-file contents before building the payload.** Step-02 §4.1 fetches `package.json` plus the entry-point files but does not fetch `registry.ts` / `components.ts` — the deep-match branch of the component-registry rule needs those contents. Scan the tree for any of `registry.ts` / `registry.tsx` / `components.ts` / `components.tsx` (any depth). For each match, fetch its contents in **one message with N parallel Bash calls** (`gh api repos/{owner}/{repo}/contents/{path}` for GitHub, file reads for local), then base64-decode the responses together. Skip the fetch if the tree contains no registry files.
|
|
88
|
+
|
|
89
|
+
Build the payload and invoke:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
echo '{
|
|
93
|
+
"intent": "<combined intent + scope_hint text from step-01>",
|
|
94
|
+
"module_count": <count from step-02 §4.3>,
|
|
95
|
+
"export_count": <count from step-02 §4.3>,
|
|
96
|
+
"tree": [<flat list of repo-relative file paths from step-02 §1>],
|
|
97
|
+
"entry_files": [{"path": "<registry path>", "content": "<contents>"}, ...],
|
|
98
|
+
"source_type": "source",
|
|
99
|
+
"mode": "interactive"
|
|
100
|
+
}' | uv run {recommendScopeTypeScript}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
`entry_files` carries the registry contents fetched above; omit when no registry files exist in the tree. `mode: "interactive"` activates the content-inspection branch of the component-registry rule (10+ entries or `Component[]` annotation); the headless GATE in §6 uses `mode: "headless"` which falls back to presence-only matching. `source_type: "docs-only"` short-circuits to `docs-only` regardless of the other signals.
|
|
104
|
+
|
|
105
|
+
The script returns `{scope_type, matched_heuristic, signals, rationale}`. Use `rationale` directly — it already names the specific signals that fired.
|
|
106
|
+
|
|
107
|
+
Present:
|
|
108
|
+
|
|
109
|
+
"**Recommended scope type: [{letter}] {Name}** — {rationale from the script}.
|
|
110
|
+
|
|
111
|
+
How broadly should this skill cover the library?
|
|
112
|
+
|
|
113
|
+
{full menu from `{scopeTemplatesFile}` with the recommended letter marked, e.g. '[F] Full Library', '[M] Specific Modules', '[P] Public API Only ← recommended', '[C] Component Library', '[R] Reference App'}
|
|
77
114
|
|
|
78
|
-
|
|
115
|
+
Press Enter to accept the recommendation, or pick a different letter."
|
|
79
116
|
|
|
80
|
-
Wait for user selection.
|
|
117
|
+
Wait for user selection. Empty input or just Enter accepts the recommendation; any of the five letters overrides.
|
|
81
118
|
|
|
82
119
|
### 3. Define Boundaries Based on Selection
|
|
83
120
|
|
|
@@ -128,19 +165,25 @@ Record the response as `scripts_intent` and `assets_intent` in the brief. Defaul
|
|
|
128
165
|
|
|
129
166
|
### 6. Present MENU OPTIONS
|
|
130
167
|
|
|
131
|
-
Display: **Select an Option:** [A] Advanced Elicitation [P] Party Mode [C] Continue to Brief Confirmation
|
|
168
|
+
Display: **Select an Option:** [A] Advanced Elicitation [P] Party Mode [C] Continue to Brief Confirmation [X] Cancel and exit
|
|
132
169
|
|
|
133
170
|
#### Menu Handling Logic:
|
|
134
171
|
|
|
135
172
|
- IF A: Invoke {advancedElicitationSkill}, and when finished redisplay the menu
|
|
136
173
|
- IF P: Invoke {partyModeSkill}, and when finished redisplay the menu
|
|
137
174
|
- IF C: Load, read entire file, then execute {nextStepFile}
|
|
175
|
+
- IF X: Treat as user-cancellation. Display `"Cancelled — no brief was written."` and HALT (exit code 6, `halt_reason: "user-cancelled"`). Cancellation here is non-destructive — no files have been written yet. `[X]` is interactive-only; the headless GATE never reaches this branch.
|
|
138
176
|
- IF Any other comments or queries: help user respond then [Redisplay Menu Options](#6-present-menu-options)
|
|
139
177
|
|
|
140
178
|
#### EXECUTION RULES:
|
|
141
179
|
|
|
142
180
|
- ALWAYS halt and wait for user input after presenting menu
|
|
143
|
-
- **GATE [default: C]** — If `{headless_mode}`:
|
|
181
|
+
- **GATE [default: C]** — If `{headless_mode}`: consume the headless inputs from step-01 in priority order:
|
|
182
|
+
- If `scope_type` was supplied, use it (must match one of the six valid types) and skip the §2c template menu.
|
|
183
|
+
- Otherwise auto-select via `{recommendScopeTypeScript}` — invoke the script with the **same payload shape** documented in §2c but with `mode: "headless"` (presence-only matching for the component-registry rule, since `entry_files` may not be available without an interactive context). Use the returned `scope_type` and log `"headless: scope_type={value} from heuristic={matched_heuristic}"`. The script's docs-only short-circuit handles `source_type=docs-only` automatically.
|
|
184
|
+
- If `include`/`exclude` were supplied, use them verbatim (split on comma) instead of running the boundary prompts in §3.
|
|
185
|
+
- If `scripts_intent`/`assets_intent` were supplied, record them and skip §5b; otherwise default to `detect`.
|
|
186
|
+
- Log: `"headless: scope_type={value} include={n} exclude={n} scripts_intent={value} assets_intent={value}"`.
|
|
144
187
|
- ONLY proceed to next step when user selects 'C'
|
|
145
188
|
- After other menu items execution, return to this menu
|
|
146
189
|
- User can chat or ask questions — always respond and then redisplay menu
|
|
@@ -16,16 +16,15 @@ To present the complete skill brief in human-readable format, highlighting all f
|
|
|
16
16
|
|
|
17
17
|
- Focus only on presenting and confirming — do not write files yet (Step 05)
|
|
18
18
|
- Do not proceed without explicit user approval (P2 confirmation gate)
|
|
19
|
+
- All user-facing output in `{communication_language}`
|
|
19
20
|
|
|
20
21
|
## MANDATORY SEQUENCE
|
|
21
22
|
|
|
22
23
|
**CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise unless user explicitly requests a change.
|
|
23
24
|
|
|
24
|
-
### 1.
|
|
25
|
+
### 1. Assemble Complete Brief
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
### 2. Assemble Complete Brief
|
|
27
|
+
Use the values already accepted in steps 01-03 directly — do not re-load `{briefSchemaFile}` here. The 18 fields below are all in conversation; the schema is only consulted in §4 if an inline adjustment needs a specific field's validation rule cited.
|
|
29
28
|
|
|
30
29
|
Compile all gathered data from steps 01-03 into the complete brief:
|
|
31
30
|
|
|
@@ -48,11 +47,11 @@ Compile all gathered data from steps 01-03 into the complete brief:
|
|
|
48
47
|
- **assets_intent:** {detect/none/description from step 03, or "detect" if not explicitly set}
|
|
49
48
|
- **source_authority:** {official/community/internal from step 01 — default "community"}
|
|
50
49
|
|
|
51
|
-
###
|
|
50
|
+
### 2. Present Brief for Review
|
|
52
51
|
|
|
53
|
-
Using the
|
|
52
|
+
Using the format below:
|
|
54
53
|
|
|
55
|
-
"**
|
|
54
|
+
"**Review the complete skill brief before I write it.**
|
|
56
55
|
|
|
57
56
|
---
|
|
58
57
|
|
|
@@ -62,7 +61,7 @@ Skill Brief: {name}
|
|
|
62
61
|
|
|
63
62
|
Target: {source_repo}
|
|
64
63
|
Language: {language}
|
|
65
|
-
Forge Tier: {forge_tier}
|
|
64
|
+
Forge Tier: {forge_tier} — {tier_gloss}
|
|
66
65
|
Description: {description}
|
|
67
66
|
|
|
68
67
|
Scope: {scope.type}
|
|
@@ -79,9 +78,8 @@ Doc URLs:
|
|
|
79
78
|
Supplemental Docs:
|
|
80
79
|
{doc_urls, one per line with labels}
|
|
81
80
|
|
|
82
|
-
{
|
|
83
|
-
|
|
84
|
-
Assets: {assets_intent}
|
|
81
|
+
Scripts: {scripts_intent} — {scripts_gloss}
|
|
82
|
+
Assets: {assets_intent} — {assets_gloss}
|
|
85
83
|
|
|
86
84
|
Source Authority: {source_authority}
|
|
87
85
|
|
|
@@ -95,17 +93,31 @@ Created: {created}
|
|
|
95
93
|
Created by: {created_by}
|
|
96
94
|
```
|
|
97
95
|
|
|
98
|
-
---
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
Glosses (substitute the matching one-liner for `{tier_gloss}`, `{scripts_gloss}`, `{assets_gloss}` above so the user can decode each value at a glance):
|
|
99
|
+
|
|
100
|
+
- **Forge tier glosses** —
|
|
101
|
+
- `Quick`: text-only extraction; AST and semantic discovery off
|
|
102
|
+
- `Forge`: AST-grep on; semantic and re-ranking off
|
|
103
|
+
- `Forge+`: AST-grep + ccc semantic discovery; re-ranking off
|
|
104
|
+
- `Deep`: full pipeline — AST + ccc + qmd portfolio search + LLM re-ranking
|
|
105
|
+
|
|
106
|
+
- **`scripts_intent` / `assets_intent` glosses** —
|
|
107
|
+
- `detect`: SKF will scan source for the standard `scripts/`/`bin/`/`tools/`/`cli/` (or `assets/`/`templates/`/`schemas/`/`configs/`) directories during create-skill and decide automatically
|
|
108
|
+
- `none`: no script/asset packaging — create-skill will skip the detection pass
|
|
109
|
+
- free-text (anything else): a description of what to package; create-skill treats it as the user's spec
|
|
110
|
+
|
|
111
|
+
(For `docs-only` and `public-api` scope types the scripts/assets prompt is skipped in step-03 §5b — the values default to `detect` but the create-skill detection pass also no-ops for these scope types, so the gloss just clarifies that the recorded value will not actually fire any scan.)"
|
|
99
112
|
|
|
100
|
-
###
|
|
113
|
+
### 3. Highlight Items Needing Attention
|
|
101
114
|
|
|
102
115
|
Flag any fields that may need review:
|
|
103
116
|
|
|
104
117
|
{If language was overridden or low confidence:}
|
|
105
118
|
"**Note:** Language was {auto-detected / manually overridden}."
|
|
106
119
|
|
|
107
|
-
|
|
108
|
-
"**Note:** Description was derived from your stated intent. Adjust if needed."
|
|
120
|
+
"**Description:** synthesized and confirmed in step-01 §7b. This is the text agents read when deciding whether to route to your skill — refine here if you want to tighten it now that the full brief is visible."
|
|
109
121
|
|
|
110
122
|
{If forge tier was defaulted:}
|
|
111
123
|
"**Note:** Forge tier defaulted to Quick (no forge-tier.yaml found)."
|
|
@@ -123,16 +135,17 @@ You can:
|
|
|
123
135
|
- Revise scope boundaries by selecting [R]
|
|
124
136
|
- Proceed to write by selecting [C]"
|
|
125
137
|
|
|
126
|
-
###
|
|
138
|
+
### 4. Handle Inline Adjustments
|
|
127
139
|
|
|
128
140
|
If the user requests changes to specific fields (name, description, version, etc.):
|
|
141
|
+
- If the adjustment requires explaining a field's validation rule or allowed values, load `{briefSchemaFile}` now (otherwise skip the read — the common path does not need it)
|
|
129
142
|
- Make the adjustment
|
|
130
143
|
- Re-present the updated brief
|
|
131
144
|
- Return to the menu
|
|
132
145
|
|
|
133
|
-
###
|
|
146
|
+
### 5. Present MENU OPTIONS
|
|
134
147
|
|
|
135
|
-
Display: **Select an Option:** [R] Revise Scope [A] Advanced Elicitation [P] Party Mode [C] Approve and Write
|
|
148
|
+
Display: **Select an Option:** [R] Revise Scope [A] Advanced Elicitation [P] Party Mode [C] Approve and Write [X] Cancel and exit
|
|
136
149
|
|
|
137
150
|
#### Menu Handling Logic:
|
|
138
151
|
|
|
@@ -140,7 +153,8 @@ Display: **Select an Option:** [R] Revise Scope [A] Advanced Elicitation [P] Par
|
|
|
140
153
|
- IF A: Invoke {advancedElicitationSkill}, and when finished redisplay the menu
|
|
141
154
|
- IF P: Invoke {partyModeSkill}, and when finished redisplay the menu
|
|
142
155
|
- IF C: Load, read entire file, then execute {nextStepFile}
|
|
143
|
-
- IF
|
|
156
|
+
- IF X: Treat as user-cancellation. Display `"Cancelled — no brief was written."` and HALT (exit code 6, `halt_reason: "user-cancelled"`). Cancellation here is non-destructive — step-05 has not run, no skill-brief.yaml file exists yet. `[X]` is interactive-only; the headless GATE never reaches this branch.
|
|
157
|
+
- IF Any other comments or queries: help user respond, apply any field adjustments, re-present brief if changed, then [Redisplay Menu Options](#5-present-menu-options)
|
|
144
158
|
|
|
145
159
|
#### EXECUTION RULES:
|
|
146
160
|
|