bmad-module-skill-forge 0.2.0 → 0.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/README.md +73 -159
- package/docs/agents.md +2 -2
- package/docs/architecture.md +155 -25
- package/docs/concepts.md +96 -0
- package/docs/examples.md +52 -2
- package/docs/getting-started.md +30 -14
- package/docs/index.md +16 -41
- package/docs/workflows.md +3 -3
- package/package.json +6 -4
- package/src/forger/forge-tier.yaml +1 -1
- package/src/forger/preferences.yaml +8 -1
- package/src/knowledge/doc-fetcher.md +55 -0
- package/src/knowledge/overview.md +17 -16
- package/src/knowledge/progressive-capability.md +9 -1
- package/src/knowledge/provenance-tracking.md +31 -23
- package/src/knowledge/qmd-registry.md +132 -0
- package/src/knowledge/skf-knowledge-index.csv +2 -0
- package/src/module.yaml +2 -2
- package/src/workflows/analyze-source/data/skill-brief-schema.md +24 -4
- package/src/workflows/analyze-source/steps-c/step-01-init.md +19 -9
- package/src/workflows/analyze-source/steps-c/step-01b-continue.md +2 -2
- package/src/workflows/analyze-source/steps-c/step-02-scan-project.md +10 -2
- package/src/workflows/analyze-source/steps-c/step-04-map-and-detect.md +17 -2
- package/src/workflows/analyze-source/steps-c/step-05-recommend.md +2 -1
- package/src/workflows/analyze-source/steps-c/step-06-generate-briefs.md +3 -3
- package/src/workflows/analyze-source/templates/analysis-report-template.md +1 -1
- package/src/workflows/analyze-source/validation-report.md +1 -1
- package/src/workflows/analyze-source/workflow-plan-analyze-source.md +1 -1
- package/src/workflows/analyze-source/workflow.md +1 -1
- package/src/workflows/audit-skill/steps-c/step-01-init.md +8 -5
- package/src/workflows/audit-skill/steps-c/step-02-re-index.md +12 -2
- package/src/workflows/audit-skill/validation-report.md +2 -2
- package/src/workflows/audit-skill/workflow-plan-audit-skill.md +1 -1
- package/src/workflows/brief-skill/data/scope-templates.md +60 -0
- package/src/workflows/brief-skill/data/skill-brief-schema.md +38 -3
- package/src/workflows/brief-skill/steps-c/step-01-gather-intent.md +20 -4
- package/src/workflows/brief-skill/steps-c/step-03-scope-definition.md +20 -64
- package/src/workflows/brief-skill/steps-c/step-04-confirm-brief.md +1 -1
- package/src/workflows/brief-skill/steps-c/step-05-write-brief.md +60 -5
- package/src/workflows/brief-skill/workflow.md +2 -1
- package/src/workflows/create-skill/data/compile-assembly-rules.md +110 -0
- package/src/workflows/create-skill/data/extraction-patterns.md +216 -3
- package/src/workflows/create-skill/data/skill-sections.md +81 -27
- package/src/workflows/create-skill/data/source-resolution-protocols.md +138 -0
- package/src/workflows/create-skill/data/tier-degradation-rules.md +46 -0
- package/src/workflows/create-skill/steps-c/step-01-load-brief.md +7 -4
- package/src/workflows/create-skill/steps-c/step-02-ecosystem-check.md +10 -7
- package/src/workflows/create-skill/steps-c/step-03-extract.md +51 -10
- package/src/workflows/create-skill/steps-c/step-03b-fetch-temporal.md +238 -0
- package/src/workflows/create-skill/steps-c/step-03c-fetch-docs.md +220 -0
- package/src/workflows/create-skill/steps-c/step-04-enrich.md +40 -10
- package/src/workflows/create-skill/steps-c/step-05-compile.md +49 -82
- package/src/workflows/create-skill/steps-c/step-06-validate.md +152 -63
- package/src/workflows/create-skill/steps-c/step-07-generate-artifacts.md +53 -3
- package/src/workflows/create-skill/steps-c/step-08-report.md +1 -1
- package/src/workflows/create-skill/workflow-plan-create-skill.md +42 -10
- package/src/workflows/create-skill/workflow.md +3 -2
- package/src/workflows/create-stack-skill/data/stack-skill-template.md +20 -7
- package/src/workflows/create-stack-skill/steps-c/step-01-init.md +2 -2
- package/src/workflows/create-stack-skill/steps-c/step-04-parallel-extract.md +14 -0
- package/src/workflows/create-stack-skill/steps-c/step-06-compile-stack.md +28 -7
- package/src/workflows/create-stack-skill/steps-c/step-07-generate-output.md +10 -7
- package/src/workflows/create-stack-skill/steps-c/step-08-validate.md +66 -68
- package/src/workflows/create-stack-skill/validation-report.md +1 -1
- package/src/workflows/create-stack-skill/workflow-plan-create-stack-skill.md +4 -4
- package/src/workflows/export-skill/data/managed-section-format.md +1 -0
- package/src/workflows/export-skill/data/snippet-format.md +33 -14
- package/src/workflows/export-skill/steps-c/step-01-load-skill.md +16 -2
- package/src/workflows/export-skill/steps-c/step-03-generate-snippet.md +29 -22
- package/src/workflows/export-skill/steps-c/step-04-update-context.md +1 -1
- package/src/workflows/export-skill/steps-c/step-05-token-report.md +1 -1
- package/src/workflows/export-skill/validation-report.md +1 -1
- package/src/workflows/export-skill/workflow-plan-export-skill.md +8 -8
- package/src/workflows/export-skill/workflow.md +1 -1
- package/src/workflows/quick-skill/data/skill-template.md +27 -7
- package/src/workflows/quick-skill/steps-c/step-04-compile.md +44 -13
- package/src/workflows/quick-skill/steps-c/step-05-validate.md +79 -16
- package/src/workflows/quick-skill/validation-report.md +4 -4
- package/src/workflows/quick-skill/workflow-plan-quick-skill.md +4 -4
- package/src/workflows/quick-skill/workflow.md +2 -0
- package/src/workflows/setup-forge/steps-c/step-01-detect-and-tier.md +12 -3
- package/src/workflows/setup-forge/steps-c/step-02-write-config.md +10 -2
- package/src/workflows/setup-forge/steps-c/step-03-auto-index.md +111 -40
- package/src/workflows/setup-forge/steps-c/step-04-report.md +13 -0
- package/src/workflows/setup-forge/workflow.md +1 -0
- package/src/workflows/test-skill/data/scoring-rules.md +14 -6
- package/src/workflows/test-skill/data/source-access-protocol.md +45 -0
- package/src/workflows/test-skill/steps-c/step-01-init.md +38 -13
- package/src/workflows/test-skill/steps-c/step-02-detect-mode.md +2 -3
- package/src/workflows/test-skill/steps-c/step-03-coverage-check.md +25 -5
- package/src/workflows/test-skill/steps-c/step-04-coherence-check.md +22 -47
- package/src/workflows/test-skill/steps-c/step-04b-external-validators.md +219 -0
- package/src/workflows/test-skill/steps-c/step-05-score.md +25 -27
- package/src/workflows/test-skill/steps-c/step-06-report.md +9 -4
- package/src/workflows/test-skill/templates/test-report-template.md +2 -1
- package/src/workflows/test-skill/validation-report.md +1 -1
- package/src/workflows/test-skill/workflow-plan-test-skill.md +7 -3
- package/src/workflows/test-skill/workflow.md +1 -1
- package/src/workflows/update-skill/data/remote-source-resolution.md +43 -0
- package/src/workflows/update-skill/data/tier-degradation-rules.md +46 -0
- package/src/workflows/update-skill/steps-c/step-01-init.md +13 -7
- package/src/workflows/update-skill/steps-c/step-02-detect-changes.md +26 -0
- package/src/workflows/update-skill/steps-c/step-03-re-extract.md +38 -9
- package/src/workflows/update-skill/steps-c/step-04-merge.md +3 -3
- package/src/workflows/update-skill/steps-c/step-05-validate.md +63 -67
- package/src/workflows/update-skill/steps-c/step-06-write.md +37 -14
- package/src/workflows/update-skill/steps-c/step-07-report.md +1 -1
- package/src/workflows/update-skill/validation-report.md +4 -4
- package/src/workflows/update-skill/workflow-plan-update-skill.md +4 -4
- package/src/workflows/update-skill/workflow.md +1 -1
- package/tools/cli/commands/status.js +4 -4
- package/tools/cli/commands/uninstall.js +1 -1
- package/tools/cli/commands/update.js +2 -2
- package/tools/cli/lib/ui.js +60 -16
- package/tools/cli/lib/version-check.js +2 -2
|
@@ -26,13 +26,16 @@ Source reading via gh_bridge — infer exports from file structure and content.
|
|
|
26
26
|
|
|
27
27
|
## Forge Tier (AST Available)
|
|
28
28
|
|
|
29
|
-
Structural extraction via
|
|
29
|
+
Structural extraction via ast-grep — verified exports with line-level citations.
|
|
30
|
+
|
|
31
|
+
> **Note:** `ast_bridge.*` and `qmd_bridge.*` references below are **conceptual interfaces**, not callable functions. They describe the operation to perform. Use ast-grep (MCP tool or CLI) for `ast_bridge.*` operations and QMD (MCP tool or CLI) for `qmd_bridge.*` operations. See the AST Extraction Protocol section below and the TOOL/SUBPROCESS FALLBACK rule for dispatch details.
|
|
30
32
|
|
|
31
33
|
### Strategy
|
|
34
|
+
|
|
32
35
|
1. Detect language from brief or file extensions
|
|
33
|
-
2.
|
|
36
|
+
2. Use ast-grep to extract all exports from `path` for the given `language` (scan definitions)
|
|
34
37
|
3. For each export: function name, full signature, parameter types, return type, line number
|
|
35
|
-
4. `
|
|
38
|
+
4. Use ast-grep to detect co-imported symbols in `path` for the given `libraries[]`
|
|
36
39
|
5. Build extraction rules YAML for reproducibility
|
|
37
40
|
|
|
38
41
|
### Confidence
|
|
@@ -61,3 +64,213 @@ Same extraction as Forge tier. Deep tier adds enrichment in step-04, not extract
|
|
|
61
64
|
### Confidence
|
|
62
65
|
- Extraction: same as Forge (T1)
|
|
63
66
|
- Enrichment annotations added in step-04: T2
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## AST Extraction Protocol
|
|
71
|
+
|
|
72
|
+
When AST tools are available (Forge/Deep tier), follow this deterministic protocol to prevent output overflow on large codebases.
|
|
73
|
+
|
|
74
|
+
**"Files in scope"** = files remaining after applying `include_patterns` and `exclude_patterns` from the brief, filtered by the target language extension. This is NOT the total repository file count from step-01's tree listing. Use the filtered count from step-03 section 2 as the decision tree input.
|
|
75
|
+
|
|
76
|
+
### Decision Tree
|
|
77
|
+
|
|
78
|
+
Apply the first matching condition:
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
Files in scope ≤ 100
|
|
82
|
+
→ Use ast-grep MCP tool: find_code(pattern, max_results=100, output_format="text")
|
|
83
|
+
→ Parse compact text output directly into extraction inventory
|
|
84
|
+
|
|
85
|
+
Files in scope 101–500
|
|
86
|
+
→ Use ast-grep MCP tool: find_code_by_rule(yaml, max_results=150, output_format="text")
|
|
87
|
+
→ Use scoped YAML rules (see recipes below) to filter at the AST level
|
|
88
|
+
→ Parse compact text output into extraction inventory
|
|
89
|
+
|
|
90
|
+
Files in scope > 500
|
|
91
|
+
→ CLI streaming fallback: ast-grep --json=stream + line-by-line Python processing
|
|
92
|
+
→ Process in directory batches, cap per-batch output
|
|
93
|
+
→ Merge batch results into extraction inventory
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Safety Valve
|
|
97
|
+
|
|
98
|
+
If any ast-grep operation (MCP or CLI) visibly causes a timeout, returns an error related to output size, or produces unexpectedly large output: immediately switch to the CLI streaming fallback with `--json=stream`. Do not retry the same approach. When falling back to the CLI streaming template, inject the brief's `scope.exclude` patterns into the `EXCLUDES` list (use `[]` if absent) — this applies regardless of which path triggered the fallback. Note: `max_results` in the MCP tool and `| head -N` in the CLI path provide hard caps, but this safety valve covers cases where the upstream tool itself fails before returning results (e.g., OOM during JSON serialization).
|
|
99
|
+
|
|
100
|
+
### MCP Tool Usage (Preferred)
|
|
101
|
+
|
|
102
|
+
**Simple pattern search:**
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
find_code(
|
|
106
|
+
project_folder="{source_path}",
|
|
107
|
+
pattern="async def $NAME($$$PARAMS)",
|
|
108
|
+
language="python",
|
|
109
|
+
max_results=100,
|
|
110
|
+
output_format="text"
|
|
111
|
+
)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**Scoped YAML rule search (for larger repos):**
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
find_code_by_rule(
|
|
118
|
+
project_folder="{source_path}",
|
|
119
|
+
yaml="id: public-api\nlanguage: python\nrule:\n pattern: 'def $NAME($$$PARAMS)'\n inside:\n kind: module\n stopBy: end\nconstraints:\n NAME:\n regex: '^[^_]'",
|
|
120
|
+
max_results=150,
|
|
121
|
+
output_format="text"
|
|
122
|
+
)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### CLI Streaming Fallback
|
|
126
|
+
|
|
127
|
+
When MCP tools are unavailable or the repo exceeds 500 files in scope, use `--json=stream` (NEVER `--json` or `--json=pretty`) with line-by-line Python processing:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
# Note: use $$$ for variadic params in ast-grep patterns (e.g., 'def $NAME($$$PARAMS)')
|
|
131
|
+
# {exclude_patterns} = Python list from brief's scope.exclude, e.g. ['tests/**', '**/test_*']
|
|
132
|
+
# If scope.exclude is absent or empty in the brief, inject [] as the default.
|
|
133
|
+
# Patterns are matched against the full file path as emitted by ast-grep.
|
|
134
|
+
# Ensure paths are relative to the same root as the patterns (strip ./ prefix if needed).
|
|
135
|
+
ast-grep -p '{pattern}' -l {language} --json=stream {path} | python3 -c "
|
|
136
|
+
import sys, json, fnmatch, signal
|
|
137
|
+
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
|
|
138
|
+
|
|
139
|
+
EXCLUDES = {exclude_patterns}
|
|
140
|
+
|
|
141
|
+
for line in sys.stdin:
|
|
142
|
+
try:
|
|
143
|
+
m = json.loads(line)
|
|
144
|
+
f = m.get('file','')
|
|
145
|
+
if EXCLUDES and any(fnmatch.fnmatch(f, pat) for pat in EXCLUDES):
|
|
146
|
+
continue
|
|
147
|
+
v = m.get('metaVariables',{})
|
|
148
|
+
name = v.get('single',{}).get('NAME',{}).get('text','')
|
|
149
|
+
if name and not name.startswith('_'):
|
|
150
|
+
ln = m.get('range',{}).get('start',{}).get('line',0)+1
|
|
151
|
+
sig = m.get('text','').split(chr(10))[0].strip()
|
|
152
|
+
print(f'[AST:{f}:L{ln}] {sig}')
|
|
153
|
+
except: pass
|
|
154
|
+
" | head -200
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**Critical constraints:**
|
|
158
|
+
|
|
159
|
+
- ALWAYS use `--json=stream` — never `--json` (loads entire array into memory)
|
|
160
|
+
- ALWAYS process line-by-line (`for line in sys.stdin`) — never `json.load(sys.stdin)`
|
|
161
|
+
- ALWAYS cap output with `| head -N` as a safety valve
|
|
162
|
+
- For repos > 500 files, process in directory batches of 20-50 files each
|
|
163
|
+
|
|
164
|
+
### YAML Rule Recipes by Language
|
|
165
|
+
|
|
166
|
+
**Python — public functions:**
|
|
167
|
+
|
|
168
|
+
```yaml
|
|
169
|
+
id: python-public-functions
|
|
170
|
+
language: python
|
|
171
|
+
rule:
|
|
172
|
+
pattern: 'def $NAME($$$PARAMS)'
|
|
173
|
+
inside:
|
|
174
|
+
kind: module
|
|
175
|
+
stopBy: end
|
|
176
|
+
constraints:
|
|
177
|
+
NAME:
|
|
178
|
+
regex: '^[^_]'
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**Python — public classes:**
|
|
182
|
+
|
|
183
|
+
```yaml
|
|
184
|
+
id: python-public-classes
|
|
185
|
+
language: python
|
|
186
|
+
rule:
|
|
187
|
+
pattern: 'class $NAME($$$BASES)'
|
|
188
|
+
inside:
|
|
189
|
+
kind: module
|
|
190
|
+
stopBy: end
|
|
191
|
+
constraints:
|
|
192
|
+
NAME:
|
|
193
|
+
regex: '^[^_]'
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**JavaScript/TypeScript — exported functions:**
|
|
197
|
+
|
|
198
|
+
```yaml
|
|
199
|
+
id: js-exported-functions
|
|
200
|
+
language: typescript
|
|
201
|
+
rule:
|
|
202
|
+
pattern: 'export function $NAME($$$PARAMS)'
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
**JavaScript/TypeScript — exported constants:**
|
|
206
|
+
|
|
207
|
+
```yaml
|
|
208
|
+
id: js-exported-constants
|
|
209
|
+
language: typescript
|
|
210
|
+
rule:
|
|
211
|
+
pattern: 'export const $NAME = $VALUE'
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
**Rust — public functions:**
|
|
215
|
+
|
|
216
|
+
```yaml
|
|
217
|
+
id: rust-public-functions
|
|
218
|
+
language: rust
|
|
219
|
+
rule:
|
|
220
|
+
any:
|
|
221
|
+
- pattern: 'pub fn $NAME($$$PARAMS) -> $RET'
|
|
222
|
+
- pattern: 'pub fn $NAME($$$PARAMS)'
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
**Go — exported functions (capitalized):**
|
|
226
|
+
|
|
227
|
+
```yaml
|
|
228
|
+
id: go-exported-functions
|
|
229
|
+
language: go
|
|
230
|
+
rule:
|
|
231
|
+
pattern: 'func $NAME($$$PARAMS) $RET'
|
|
232
|
+
constraints:
|
|
233
|
+
NAME:
|
|
234
|
+
regex: '^[A-Z]'
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Re-Export Tracing
|
|
238
|
+
|
|
239
|
+
After initial AST extraction, some top-level exports may resolve to **module imports** rather than direct function definitions. This is common in Python libraries that use `__init__.py` re-exports for a clean public API.
|
|
240
|
+
|
|
241
|
+
**Detection heuristic:** For each top-level export from `__init__.py` (or equivalent entry point), check if the import path resolves to a directory (contains `__init__.py`) rather than a `.py` file with a matching `def` or `class`. If the initial AST scan found no function/class definition for a known public export, it is likely a module re-export.
|
|
242
|
+
|
|
243
|
+
**Tracing protocol:**
|
|
244
|
+
|
|
245
|
+
1. Read the entry point file (e.g., `{package}/__init__.py`) and extract all `from .X import Y` statements
|
|
246
|
+
2. For each import where Y was NOT found by the initial AST scan:
|
|
247
|
+
- Check if the import path resolves to a directory (e.g., `{package}/api/v1/delete/` exists with `__init__.py`)
|
|
248
|
+
- If directory: read its `__init__.py` to find the actual re-exported symbol
|
|
249
|
+
- **Handle aliases:** Check for `from .module import A as B` patterns in the intermediate `__init__.py`. If the parent imports `B`, trace through to `A` in `.module`. If the parent imports `A` but the `__init__.py` only exports it as `B` (via `from .module import A as B`), match by original name `A` and note the alias
|
|
250
|
+
- Trace the symbol to its definition file and run AST extraction on that file
|
|
251
|
+
3. Cite the actual definition location: `[AST:{definition_file}:L{line}]`
|
|
252
|
+
|
|
253
|
+
**Examples:**
|
|
254
|
+
|
|
255
|
+
```python
|
|
256
|
+
# Module re-export — follow required
|
|
257
|
+
from .api.v1.delete import delete # delete/ is a directory → read delete/__init__.py
|
|
258
|
+
|
|
259
|
+
# Direct function import — no follow needed
|
|
260
|
+
from .api.v1.add.add import add # add.py exists with def add()
|
|
261
|
+
|
|
262
|
+
# Aliased re-export — follow through alias
|
|
263
|
+
# In cognee/api/v1/visualize/__init__.py:
|
|
264
|
+
# from .start_visualization_server import visualization_server
|
|
265
|
+
# In cognee/__init__.py:
|
|
266
|
+
# from .api.v1.visualize import start_visualization_server
|
|
267
|
+
# → Match start_visualization_server against both definition names AND alias names
|
|
268
|
+
# in the intermediate __init__.py to resolve the chain
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**Unresolvable imports:** If the import statement is a star-import (`from .X import *`) or a conditional import (`try`/`except`), the symbol cannot be reliably traced via this protocol. Record it with `[SRC:{package}/__init__.py:L{line}]` (T1-low) and a note: "star/conditional import — manual trace required."
|
|
272
|
+
|
|
273
|
+
**Scope limit:** Only trace re-exports for symbols listed in the top-level entry point's public API. Do not recursively trace beyond one level of `__init__.py` indirection. If a re-export cannot be resolved after one level, record it with a `[SRC:{package}/__init__.py:L{line}]` citation (T1-low) from the import statement itself.
|
|
274
|
+
|
|
275
|
+
**Other languages:** JS/TS barrel files (`index.ts` with `export { X } from './module'`) follow the same principle — trace the re-export to the definition file. Rust `pub use` and Go package-level re-exports are less common but follow the same heuristic when encountered.
|
|
276
|
+
|
|
@@ -2,30 +2,60 @@
|
|
|
2
2
|
|
|
3
3
|
## agentskills.io Compliant Format
|
|
4
4
|
|
|
5
|
-
### Frontmatter (Required)
|
|
5
|
+
### Frontmatter (Required — agentskills.io Compliance)
|
|
6
6
|
|
|
7
7
|
```yaml
|
|
8
8
|
---
|
|
9
9
|
name: {skill-name}
|
|
10
|
-
|
|
11
|
-
description
|
|
12
|
-
|
|
10
|
+
description: >
|
|
11
|
+
{Trigger-optimized description of what the skill does and when to use it.
|
|
12
|
+
Include specific keywords for agent discovery.
|
|
13
|
+
Mention what NOT to use it for if applicable.
|
|
14
|
+
1-1024 characters.}
|
|
13
15
|
---
|
|
14
16
|
```
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
**Frontmatter rules (agentskills.io specification):**
|
|
17
19
|
|
|
18
|
-
1
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
20
|
+
- `name`: 1-64 characters, lowercase alphanumeric + hyphens only, must match parent directory name
|
|
21
|
+
- `description`: 1-1024 characters, trigger-optimized for agent matching
|
|
22
|
+
- Only 6 fields permitted: `name`, `description`, `license`, `compatibility`, `metadata`, `allowed-tools`
|
|
23
|
+
- `version` and `author` belong in metadata.json, NOT in frontmatter
|
|
24
|
+
|
|
25
|
+
### Two-Tier Section Structure
|
|
26
|
+
|
|
27
|
+
SKILL.md uses a two-tier structure to ensure actionable content survives `split-body` extraction.
|
|
28
|
+
|
|
29
|
+
#### Tier 1 — Always Inline (survives split-body, target <300 lines)
|
|
30
|
+
|
|
31
|
+
| # | Section | Budget | Purpose |
|
|
32
|
+
|---|---------|--------|---------|
|
|
33
|
+
| 1 | **Overview** | ~10 lines | What the library does, source repo, version, tier, export count |
|
|
34
|
+
| 2 | **Quick Start** | ~30 lines | 3-5 core functions with one runnable end-to-end example |
|
|
35
|
+
| 3 | **Common Workflows** | ~30 lines | 4-5 typical function call sequences for common tasks |
|
|
36
|
+
| 4 | **Key API Summary** | ~20 lines | Table of top 10-15 functions (name, purpose, key params) |
|
|
37
|
+
| 4b | **Migration & Deprecation Warnings** | ~10 lines | T2-future warnings inline (Deep tier only, skip if none) |
|
|
38
|
+
| 5 | **Key Types** | ~20 lines | Most important enum/type values inline |
|
|
39
|
+
| 6 | **Architecture at a Glance** | ~10 lines | Bullet list of subsystem categories |
|
|
40
|
+
| 7 | **CLI** | ~10 lines | Basic CLI commands (skip if no CLI) |
|
|
41
|
+
| 8 | **Manual Sections** | ~5 lines | `<!-- [MANUAL] -->` markers for update-skill |
|
|
42
|
+
|
|
43
|
+
#### Tier 2 — Reference-Eligible (extracted by split-body into references/)
|
|
44
|
+
|
|
45
|
+
| # | Section | Purpose |
|
|
46
|
+
|---|---------|---------|
|
|
47
|
+
| 9 | **Full API Reference** | Complete signatures, parameter tables, return types, examples, citations |
|
|
48
|
+
| 10 | **Full Type Definitions** | All types, interfaces, enums with full field details |
|
|
49
|
+
| 11 | **Full Integration Patterns** | Co-import patterns, adapter details, pipeline internals (Forge/Deep only) |
|
|
50
|
+
|
|
51
|
+
#### Assembly Rules
|
|
52
|
+
|
|
53
|
+
- Tier 1 sections are assembled first — they form the standalone body
|
|
54
|
+
- Tier 2 sections are assembled after — they are progressive disclosure detail
|
|
55
|
+
- Tier 1 sections are kept short enough that `split-body` targets the larger Tier 2 sections (`## Full` headings) into `references/`
|
|
56
|
+
- After split-body, SKILL.md retains all Tier 1 content — actionable without loading references
|
|
57
|
+
- An agent loading only SKILL.md (no references) must get enough to act
|
|
58
|
+
- **Section 4b (Migration & Deprecation Warnings)** is conditional: only emitted for Deep tier when T2-future annotations exist. Quick/Forge tiers and Deep tiers without T2-future annotations omit it entirely (no empty section). Parsers and validators must treat this section as optional.
|
|
29
59
|
|
|
30
60
|
### Provenance Citation Format
|
|
31
61
|
|
|
@@ -50,15 +80,31 @@ Place after Quick Start and after API Reference sections.
|
|
|
50
80
|
|
|
51
81
|
---
|
|
52
82
|
|
|
53
|
-
## context-snippet.md Format
|
|
83
|
+
## context-snippet.md Format (Vercel-aligned indexed format)
|
|
54
84
|
|
|
55
|
-
|
|
85
|
+
Indexed pipe-delimited format for CLAUDE.md managed section (~80-120 tokens per skill). Aligned with Vercel's research finding that retrieval instructions + indexed file maps + inline gotchas dramatically improve agent performance.
|
|
56
86
|
|
|
57
87
|
```markdown
|
|
58
|
-
{skill-name}
|
|
59
|
-
|
|
88
|
+
[{skill-name} v{version}]|root: skills/{skill-name}/
|
|
89
|
+
|IMPORTANT: {skill-name} v{version} — read SKILL.md before writing {skill-name} code. Do NOT rely on training data.
|
|
90
|
+
|quick-start:{SKILL.md#quick-start}
|
|
91
|
+
|api: {top exports with () for functions, comma-separated}
|
|
92
|
+
|key-types:{SKILL.md#key-types} — {inline summary of most important type values}
|
|
93
|
+
|gotchas: {2-3 most critical pitfalls or breaking changes, inline}
|
|
60
94
|
```
|
|
61
95
|
|
|
96
|
+
### Format rules
|
|
97
|
+
|
|
98
|
+
- **Line 1:** Skill name + version + root path — version signals training data staleness
|
|
99
|
+
- **Line 2 (IMPORTANT):** Retrieval instruction — always present, tells agent to read SKILL.md before acting
|
|
100
|
+
- **Lines 3+:** Pipe-delimited index mapping topics to SKILL.md sections (with `#anchor` pointers)
|
|
101
|
+
- **Inline content:** Each index line includes a brief inline summary (~10 words) so the agent can decide whether to read the full section
|
|
102
|
+
- **gotchas line:** 2-3 most critical pitfalls inline — prevents mistakes without requiring a file read
|
|
103
|
+
- **Token budget:** ~80-120 tokens per skill (justified by Vercel's finding that indexed format maintains performance at 80% compression)
|
|
104
|
+
- **T1-now content only** — no T2 annotations in the snippet
|
|
105
|
+
- **Section anchors** (`#quick-start`, `#key-types`) must match actual SKILL.md heading slugs
|
|
106
|
+
- **Version** comes from source detection (per issue #32), not brief default
|
|
107
|
+
|
|
62
108
|
---
|
|
63
109
|
|
|
64
110
|
## metadata.json Structure
|
|
@@ -67,22 +113,27 @@ Compressed 2-line-per-skill format for CLAUDE.md managed section:
|
|
|
67
113
|
{
|
|
68
114
|
"name": "{skill-name}",
|
|
69
115
|
"version": "{source-version}",
|
|
70
|
-
"skill_type": "
|
|
116
|
+
"skill_type": "single",
|
|
71
117
|
"source_authority": "{official|community|internal}",
|
|
72
118
|
"source_repo": "{github-url}",
|
|
119
|
+
"source_root": "{resolved-source-path}",
|
|
73
120
|
"source_commit": "{commit-hash}",
|
|
74
|
-
"
|
|
121
|
+
"confidence_tier": "{Quick|Forge|Deep}",
|
|
75
122
|
"spec_version": "1.3",
|
|
76
|
-
"
|
|
123
|
+
"generation_date": "{ISO-8601}",
|
|
124
|
+
"exports": [],
|
|
77
125
|
"tool_versions": {
|
|
78
126
|
"ast_grep": "{version-or-null}",
|
|
79
127
|
"qmd": "{version-or-null}",
|
|
80
|
-
"skf": "
|
|
128
|
+
"skf": "{skf_version}"
|
|
81
129
|
},
|
|
82
130
|
"stats": {
|
|
83
131
|
"exports_documented": 0,
|
|
132
|
+
"exports_public_api": 0,
|
|
133
|
+
"exports_internal": 0,
|
|
84
134
|
"exports_total": 0,
|
|
85
|
-
"
|
|
135
|
+
"public_api_coverage": 0.0,
|
|
136
|
+
"total_coverage": 0.0,
|
|
86
137
|
"confidence_t1": 0,
|
|
87
138
|
"confidence_t2": 0,
|
|
88
139
|
"confidence_t3": 0
|
|
@@ -125,7 +176,10 @@ Each reference file includes:
|
|
|
125
176
|
"generated_at": "{ISO-8601}",
|
|
126
177
|
"entries": [
|
|
127
178
|
{
|
|
128
|
-
"
|
|
179
|
+
"export_name": "getToken",
|
|
180
|
+
"export_type": "function",
|
|
181
|
+
"params": ["userId: string", "options?: TokenOptions"],
|
|
182
|
+
"return_type": "Token",
|
|
129
183
|
"source_file": "src/auth/index.ts",
|
|
130
184
|
"source_line": 42,
|
|
131
185
|
"confidence": "T1",
|
|
@@ -150,7 +204,7 @@ Each reference file includes:
|
|
|
150
204
|
## Tool Versions
|
|
151
205
|
- ast-grep: {version}
|
|
152
206
|
- QMD: {version}
|
|
153
|
-
- SKF:
|
|
207
|
+
- SKF: {skf_version}
|
|
154
208
|
|
|
155
209
|
## Extraction Summary
|
|
156
210
|
- Files scanned: {count}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# Source Resolution Protocols
|
|
2
|
+
|
|
3
|
+
## Remote Source Resolution (Forge/Deep only)
|
|
4
|
+
|
|
5
|
+
If `source_repo` is a local path: proceed with the tier-appropriate strategy as normal.
|
|
6
|
+
|
|
7
|
+
If `source_repo` is a remote URL (GitHub URL or owner/repo format) AND tier is Forge or Deep:
|
|
8
|
+
|
|
9
|
+
1. **Check `git` availability:** Verify `git` is functional (`git --version`). If `git` is not available, skip to the fallback warning below.
|
|
10
|
+
|
|
11
|
+
2. **Ephemeral shallow clone:** Clone the repository to a system temp path for AST access:
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
temp_path = {system_temp}/skf-ephemeral-{skill-name}-{timestamp}/
|
|
15
|
+
git clone --depth 1 --branch {branch} --single-branch --filter=blob:none {source_repo} {temp_path}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
**If `include_patterns` are NOT specified:**
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
git clone --depth 1 --branch {branch} --single-branch --filter=blob:none {source_repo} {temp_path}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**If `include_patterns` ARE specified**, use sparse-checkout to limit the clone scope:
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
git clone --depth 1 --branch {branch} --single-branch --filter=blob:none --sparse {source_repo} {temp_path}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Mode selection:** Choose sparse-checkout mode based on whether `exclude_patterns` exist:
|
|
31
|
+
|
|
32
|
+
- **No `exclude_patterns`:** Use default **cone mode** (faster). Convert `include_patterns` to directory roots.
|
|
33
|
+
- **`exclude_patterns` present:** Use **`--no-cone` mode** which supports gitignore-style negation patterns (`!` prefix). This applies both include and exclude at the git level, avoiding unnecessary blob downloads.
|
|
34
|
+
|
|
35
|
+
**Cone mode (no exclude patterns):**
|
|
36
|
+
|
|
37
|
+
**IMPORTANT:** `git sparse-checkout set` expects **directories**, not glob patterns. Convert `include_patterns` before passing them:
|
|
38
|
+
|
|
39
|
+
**Classification rule:** A pattern is an **individual file** if it contains no glob characters (`*`, `?`, `[`) AND does not end with `/`. Everything else is a glob — strip it to its directory root (the path prefix before the first glob character or wildcard segment).
|
|
40
|
+
|
|
41
|
+
- Strip glob suffixes to directory roots (e.g., `src/core/**/*.py` → `src/core`, `src/api/*.ts` → `src/api`)
|
|
42
|
+
- Deduplicate the resulting directory list
|
|
43
|
+
- Individual files (e.g., `pyproject.toml`, `src/utils/helpers.py`) are kept as-is
|
|
44
|
+
|
|
45
|
+
**If only directory roots (no individual files):**
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
git -C {temp_path} sparse-checkout set {converted_directory_roots}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**If any individual files are present (or mixed):**
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
git -C {temp_path} sparse-checkout set --skip-checks {converted_directory_roots} {individual_files}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Example transformation:
|
|
58
|
+
```
|
|
59
|
+
Brief include_patterns: sparse-checkout args:
|
|
60
|
+
src/core/**/*.py → src/core (directory root)
|
|
61
|
+
src/api/*.ts → src/api (directory root)
|
|
62
|
+
examples/**/*.py → examples (directory root)
|
|
63
|
+
pyproject.toml → pyproject.toml (individual file, needs --skip-checks)
|
|
64
|
+
src/utils/helpers.py → src/utils/helpers.py (individual file, needs --skip-checks)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**No-cone mode (exclude patterns present):**
|
|
68
|
+
|
|
69
|
+
When `exclude_patterns` exist, use `--no-cone` mode to pass both include and exclude patterns directly as gitignore-style rules:
|
|
70
|
+
|
|
71
|
+
1. Convert `include_patterns` to gitignore-style patterns. If a pattern contains no glob characters (`*`, `?`, `[`) and does not end with `/`, append `/**` to match directory contents recursively (e.g., `cognee` → `cognee/**`; `cognee/**` → kept as-is).
|
|
72
|
+
2. Convert `exclude_patterns` to negation patterns by prepending `!`. Apply the same anchoring rule (e.g., `cognee/tests` → `!cognee/tests/**`; `cognee/tests/**` → `!cognee/tests/**`; `**/test_*` → `!**/test_*`).
|
|
73
|
+
3. **CRITICAL:** List all include patterns BEFORE negated exclude patterns — git processes patterns in order and a negation can only suppress a prior inclusion.
|
|
74
|
+
4. Pass to sparse-checkout — include patterns first, then negated exclude patterns:
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
git -C {temp_path} sparse-checkout set --no-cone {include_gitignore_patterns} {negated_exclude_patterns}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Example transformation:
|
|
81
|
+
```
|
|
82
|
+
Brief include_patterns: Brief exclude_patterns:
|
|
83
|
+
cognee/** cognee/tests/**
|
|
84
|
+
cognee/alembic/**
|
|
85
|
+
**/test_*
|
|
86
|
+
|
|
87
|
+
sparse-checkout args (--no-cone):
|
|
88
|
+
'cognee/**' '!cognee/tests/**' '!cognee/alembic/**' '!**/test_*'
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Note:** `--no-cone` mode is slower than cone mode for very large repositories but eliminates downloading excluded blobs entirely.
|
|
92
|
+
|
|
93
|
+
**Always-included root files:**
|
|
94
|
+
|
|
95
|
+
Regardless of `include_patterns`, always add these root-level version/manifest files to the sparse-checkout pattern list. These are needed for version reconciliation and must not require a fallback to `gh api`:
|
|
96
|
+
|
|
97
|
+
`pyproject.toml`, `package.json`, `Cargo.toml`, `go.mod`, `setup.py`, `setup.cfg`, `VERSION`
|
|
98
|
+
|
|
99
|
+
In cone mode, always use the `--skip-checks` command form when adding these files — even if `include_patterns` resolved to only directory roots (which would normally use the form without `--skip-checks`). The command becomes: `git -C {temp_path} sparse-checkout set --skip-checks {directory_roots} pyproject.toml package.json Cargo.toml go.mod setup.py setup.cfg VERSION`. In no-cone mode, list them as explicit include patterns before any negation patterns. Do not flag them as extraneous inclusions during post-checkout filtering.
|
|
100
|
+
|
|
101
|
+
**Post-checkout filtering:**
|
|
102
|
+
|
|
103
|
+
After checkout, apply the original glob `include_patterns` as file-level filters when building the extraction file list — sparse-checkout gets the right directories, glob filtering narrows to the exact files. When `--no-cone` mode was used, most exclude filtering is already done at the git level, but apply `exclude_patterns` as a final pass to catch any edge cases where gitignore pattern matching diverges from the brief's glob semantics. Always-included root files (see above) are exempt from post-checkout filtering.
|
|
104
|
+
|
|
105
|
+
3. **If clone succeeds:** Update the working source path to `{temp_path}` for all subsequent AST operations in this step. Proceed with the **Forge/Deep Tier** extraction strategy below. Mark `ephemeral_clone_active = true` for cleanup.
|
|
106
|
+
|
|
107
|
+
4. **If clone fails (network error, auth failure, timeout):**
|
|
108
|
+
|
|
109
|
+
⚠️ **Warn the user explicitly:**
|
|
110
|
+
|
|
111
|
+
"Ephemeral clone of `{source_repo}` failed: {error}. Degrading to source reading (T1-low) for this run. For T1 (AST-verified) confidence, clone the repository locally and update `source_repo` in your brief to the local path."
|
|
112
|
+
|
|
113
|
+
Proceed with Quick tier extraction strategy below. Note the degradation reason in context for the evidence report.
|
|
114
|
+
|
|
115
|
+
**Ephemeral clone cleanup:** After extraction is complete for all files in scope (whether successful or partially failed), before presenting the Gate 2 summary (Section 6), if `ephemeral_clone_active`, delete the `{temp_path}` directory. Log: "Ephemeral source clone cleaned up." This ensures cleanup runs even if some extractions failed, as long as the step itself is still executing.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Version Reconciliation (all tiers, source mode only)
|
|
120
|
+
|
|
121
|
+
**If `source_type: "docs-only"`:** skip this section — no source files exist to reconcile.
|
|
122
|
+
|
|
123
|
+
After the source path is accessible (local path from step-01, or ephemeral clone from above), check whether the source contains a version identifier and reconcile it with `brief.version`. Look for the first matching version file in the resolved source path:
|
|
124
|
+
|
|
125
|
+
- Python: `pyproject.toml` (`[project] version`), `setup.py` (`version=`), `__version__` in `__init__.py`
|
|
126
|
+
- JavaScript/TypeScript: `package.json` (`"version"`)
|
|
127
|
+
- Rust: `Cargo.toml` (`[package] version`)
|
|
128
|
+
- Go: `go.mod` (module version if tagged)
|
|
129
|
+
|
|
130
|
+
**If a source version is found AND it differs from `brief.version`:**
|
|
131
|
+
|
|
132
|
+
⚠️ Warn the user: "Brief version ({brief.version}) differs from source version ({source_version}). Using source version ({source_version})."
|
|
133
|
+
|
|
134
|
+
Update the working version in context to the source version. Record the mismatch in context for the evidence report (step-08).
|
|
135
|
+
|
|
136
|
+
**If no version file is found or version cannot be extracted:** keep `brief.version` as-is. No warning needed.
|
|
137
|
+
|
|
138
|
+
**If source is remote and accessed via Quick tier (gh_bridge, no local files):** attempt to read the version file via `gh_bridge.read_file(owner, repo, "{version_file}")` for the primary version file of the detected language. If the read fails, keep `brief.version`.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Tier Degradation Rules
|
|
2
|
+
|
|
3
|
+
## Remote Source at Forge/Deep Tier
|
|
4
|
+
|
|
5
|
+
When `source_repo` is a remote URL (GitHub URL or owner/repo format) and the tier is Forge or Deep:
|
|
6
|
+
|
|
7
|
+
- **ast-grep requires local files** — it cannot operate on remote URLs
|
|
8
|
+
|
|
9
|
+
**Ephemeral clone strategy (preferred):**
|
|
10
|
+
|
|
11
|
+
1. Check `git` availability (`git --version`). `git` is effectively guaranteed at Deep tier (via `gh` dependency) but NOT guaranteed at Forge tier.
|
|
12
|
+
2. If `git` is available: perform an ephemeral shallow clone to a system temp path (`{system_temp}/skf-ephemeral-{skill-name}-{timestamp}/`).
|
|
13
|
+
3. For create-skill: use `--depth 1 --single-branch --filter=blob:none`; if `include_patterns` are specified, apply mode selection: if `exclude_patterns` are absent, use cone mode (convert include_patterns to directory roots; use `--skip-checks` for individual file paths); if `exclude_patterns` are present, use `--no-cone` mode (pass gitignore-style patterns with `!`-prefixed excludes — includes first, then negations). See source-resolution-protocols.md for the full conversion rules.
|
|
14
|
+
4. For update-skill: use sparse-checkout with `--skip-checks` scoped to the changed files from the change manifest only (file paths require `--skip-checks`). No `--branch` flag — uses the remote default branch (must match the branch used during original create-skill run).
|
|
15
|
+
5. If clone succeeds: use the local clone path for AST extraction. All results are T1 with `[AST:...]` citations.
|
|
16
|
+
6. Cleanup: delete the temp directory after extraction inventory is built and all data is in context. The clone never persists beyond the extraction step.
|
|
17
|
+
|
|
18
|
+
**Fallback (clone fails or `git` unavailable):**
|
|
19
|
+
|
|
20
|
+
- The extraction step MUST warn the user explicitly before degrading
|
|
21
|
+
- **create-skill:** Warning must include actionable guidance — clone locally and update `source_repo` in the brief to the local path
|
|
22
|
+
- **update-skill:** Warning must include actionable guidance — clone locally, re-run [CS] Create Skill with the local path to regenerate provenance data, then re-run the update
|
|
23
|
+
- Extraction proceeds using Quick tier strategy (source reading via gh_bridge)
|
|
24
|
+
- All results labeled T1-low with `[SRC:...]` citations
|
|
25
|
+
- The degradation reason is recorded in the evidence report
|
|
26
|
+
|
|
27
|
+
Silent degradation is **forbidden**. The user must always know when AST extraction was skipped and why.
|
|
28
|
+
|
|
29
|
+
## AST Tool Unavailable at Forge/Deep Tier
|
|
30
|
+
|
|
31
|
+
When the tier is Forge or Deep but ast-grep is not functional:
|
|
32
|
+
|
|
33
|
+
- The extraction step MUST warn the user explicitly before degrading
|
|
34
|
+
- Warning must include actionable guidance: run [SF] Setup Forge to detect tools
|
|
35
|
+
- Extraction proceeds using Quick tier strategy
|
|
36
|
+
- All results labeled T1-low
|
|
37
|
+
- The degradation reason is recorded in the evidence report
|
|
38
|
+
|
|
39
|
+
## Per-File AST Failure
|
|
40
|
+
|
|
41
|
+
When ast-grep fails on an individual file (parse error, unsupported syntax):
|
|
42
|
+
|
|
43
|
+
- Fall back to source reading for **that file only**
|
|
44
|
+
- Other files continue with AST extraction
|
|
45
|
+
- The affected file's results are labeled T1-low; unaffected files retain T1
|
|
46
|
+
- Log a warning noting which file degraded and why
|
|
@@ -63,9 +63,8 @@ Halt with: "Forge halted: No forge configuration found. Run [SF] Setup Forge fir
|
|
|
63
63
|
Extract and report:
|
|
64
64
|
- `tier`: Quick, Forge, or Deep
|
|
65
65
|
- `tools`: which tools are available (gh, ast-grep, qmd)
|
|
66
|
-
- `tier_override`: if set, use override tier instead of detected
|
|
67
66
|
|
|
68
|
-
|
|
67
|
+
**Apply tier override:** Read `{preferencesFile}`. If `tier_override` is set and is a valid tier value (Quick, Forge, or Deep), use it instead of the detected tier.
|
|
69
68
|
|
|
70
69
|
### 2. Discover Skill Brief
|
|
71
70
|
|
|
@@ -89,17 +88,21 @@ Check that the loaded skill-brief.yaml contains required fields:
|
|
|
89
88
|
**Required fields:**
|
|
90
89
|
- `name` — skill identifier (kebab-case)
|
|
91
90
|
- `version` — source version to compile against
|
|
92
|
-
- `source_repo` — GitHub owner/repo or local path
|
|
91
|
+
- `source_repo` — GitHub owner/repo or local path (**optional when `source_type: "docs-only"`**)
|
|
93
92
|
- `language` — primary source language
|
|
94
93
|
- `scope` — what to extract (e.g., "all public exports", specific modules)
|
|
95
94
|
|
|
96
95
|
**Optional fields:**
|
|
96
|
+
- `source_type` — `"source"` (default) or `"docs-only"` (external documentation only)
|
|
97
|
+
- `doc_urls` — array of `{url, label}` documentation URLs (required when `source_type: "docs-only"`)
|
|
97
98
|
- `source_branch` — branch to use (default: main/master)
|
|
98
|
-
- `source_authority` — official/community/internal (default: community)
|
|
99
|
+
- `source_authority` — official/community/internal (default: community; forced to `community` for docs-only)
|
|
99
100
|
- `include_patterns` — file glob patterns to include
|
|
100
101
|
- `exclude_patterns` — file glob patterns to exclude
|
|
101
102
|
- `description` — human description of the skill
|
|
102
103
|
|
|
104
|
+
**Docs-only validation:** When `source_type: "docs-only"`, `source_repo` is not required but `doc_urls` must have at least one entry. `source_authority` is forced to `community`.
|
|
105
|
+
|
|
103
106
|
**If required fields missing:**
|
|
104
107
|
Halt with specific error: "Brief validation failed: missing required field `{field}`. Update your skill-brief.yaml and re-run."
|
|
105
108
|
|