Skip to content

Commit 0999876

Browse files
authored
fix(bootstrap): simplify skill usage guidance (#368)
* fix(bootstrap): simplify skill usage guidance * fix(bootstrap): update standalone brainstorm reference
1 parent 3064aac commit 0999876

10 files changed

Lines changed: 45 additions & 200 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ The plugin exposes one tool to OpenCode:
402402
|------|-------------|
403403
| `systematic_skill` | Load Systematic bundled skills by name. Lists available skills in its description and returns formatted skill content when invoked. |
404404

405-
For non-Systematic skills (project or user-level), use OpenCode's native `skill` tool.
405+
For non-Systematic skills (project or user-level), use OpenCode's `skill` tool.
406406

407407
## How It Works
408408

docs/CONVERSION-GUIDE.md

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -306,28 +306,19 @@ systematic/
306306

307307
1. **Project skills**: `.opencode/skills/` in current project
308308
2. **User skills**: `~/.config/opencode/skills/`
309-
3. **Bundled skills**: Provided by systematic plugin
309+
3. **Bundled skills**: Provided by the Systematic plugin
310310

311-
### Tool Mapping Instruction
311+
### Tool References
312312

313-
Include this instruction in skills that reference tools:
314-
315-
```markdown
316-
**Tool Mapping for OpenCode:**
317-
When skills reference tools you don't have, substitute OpenCode equivalents:
318-
- `TodoWrite``todowrite`
319-
- `Task` tool with subagents → Use OpenCode's subagent system (@mention)
320-
- `Skill` tool → OpenCode's native `skill` tool
321-
- `SystematicSkill` tool → `systematic_skill` (Systematic plugin skills)
322-
- `Read`, `Write`, `Edit`, `Bash` → Your native tools
323-
- `AskUserQuestion` tool → Use OpenCode's native `question` tool
324-
```
313+
Author Systematic skills directly against OpenCode tool names. Do not add a
314+
generic tool-mapping block to converted skills; converter output should use the
315+
actual tool names the runtime exposes.
325316

326317
### Bootstrap Skill Pattern
327318

328319
The `using-systematic` skill is injected into the system prompt and teaches the agent:
329320
- How to discover available skills
330-
- When to use `systematic_skill` vs native `skill` tool
321+
- When to use `systematic_skill` vs the `skill` tool
331322
- Skill invocation discipline (invoke BEFORE any response)
332323

333324
---

docs/src/content/docs/guides/conversion-guide.mdx

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -307,28 +307,19 @@ systematic/
307307

308308
1. **Project skills**: `.opencode/skills/` in current project
309309
2. **User skills**: `~/.config/opencode/skills/`
310-
3. **Bundled skills**: Provided by systematic plugin
310+
3. **Bundled skills**: Provided by the Systematic plugin
311311

312-
### Tool Mapping Instruction
312+
### Tool References
313313

314-
Include this instruction in skills that reference tools:
315-
316-
```markdown
317-
**Tool Mapping for OpenCode:**
318-
When skills reference tools you don't have, substitute OpenCode equivalents:
319-
- `TodoWrite``todowrite`
320-
- `Task` tool with subagents → Use OpenCode's subagent system (@mention)
321-
- `Skill` tool → OpenCode's native `skill` tool
322-
- `SystematicSkill` tool → `systematic_skill` (Systematic plugin skills)
323-
- `Read`, `Write`, `Edit`, `Bash` → Your native tools
324-
- `AskUserQuestion` tool → Use OpenCode's native `question` tool
325-
```
314+
Author Systematic skills directly against OpenCode tool names. Do not add a
315+
generic tool-mapping block to converted skills; converter output should use the
316+
actual tool names the runtime exposes.
326317

327318
### Bootstrap Skill Pattern
328319

329320
The `using-systematic` skill is injected into the system prompt and teaches the agent:
330321
- How to discover available skills
331-
- When to use `systematic_skill` vs native `skill` tool
322+
- When to use `systematic_skill` vs the `skill` tool
332323
- Skill invocation discipline (invoke BEFORE any response)
333324

334325
---

registry/files/profiles/omo/AGENTS.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,15 @@ This loads Systematic's skills guide. Then check OMO:
7171

7272
### Typical Systematic-only Flow
7373
```
74-
/systematic:brainstorming → Design
74+
/ce:brainstorm → Design
7575
/workflows:plan → Create detailed plan
7676
/workflows:review → Architectural review
7777
/workflows:work → Disciplined execution
7878
```
7979

8080
### Combined OMO + Systematic Flow (Recommended)
8181
```
82-
1. /systematic:brainstorming → Explore design space
82+
1. /ce:brainstorm → Explore design space
8383
2. @Metis → Find hidden requirements
8484
3. /workflows:plan → Create executable plan
8585
4. @Sisyphus with parallel agents → Execute with OMO power:
@@ -95,7 +95,7 @@ This loads Systematic's skills guide. Then check OMO:
9595

9696
| Need | Tool | Why |
9797
|------|------|-----|
98-
| Systematic exploration | `/systematic:brainstorming` | Structured dialogue, captures requirements |
98+
| Systematic exploration | `/ce:brainstorm` | Structured dialogue, captures requirements |
9999
| Finding hidden issues | `@Metis` | Pre-planning expert finds gaps |
100100
| Detailed planning | `/workflows:plan` | Multi-phase plans with resource allocation |
101101
| Codebase research | `@Sisyphus` + `@explore` | Parallel search across files |
@@ -134,7 +134,7 @@ Results documented in compound-docs
134134
| Skill | Command | Use Case |
135135
|-------|---------|----------|
136136
| `using-systematic` | `/systematic:using-systematic` | Bootstrap — learn Systematic |
137-
| `brainstorming` | `/systematic:brainstorming` | Explore features, requirements |
137+
| `ce:brainstorm` | `/ce:brainstorm` | Explore features, requirements |
138138
| `git-worktree` | `/systematic:git-worktree` | Isolated parallel development |
139139
| `frontend-design` | `/systematic:frontend-design` | Production-grade UI implementation |
140140
| `create-agent-skill` | `/systematic:create-agent-skill` | Author new skills |

registry/files/profiles/standalone/AGENTS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ This skill teaches you how to discover and use all available Systematic skills.
4040
Before implementing features, explore requirements systematically:
4141

4242
```
43-
/systematic:brainstorming
43+
/ce:brainstorm
4444
```
4545

4646
This guides collaborative design thinking and requirement clarification.
@@ -84,7 +84,7 @@ Full workflow from plan to execution:
8484
| Skill | Use Case |
8585
|-------|----------|
8686
| `using-systematic` | Bootstrap — learn how to use Systematic |
87-
| `brainstorming` | Explore features before planning |
87+
| `ce:brainstorm` | Explore features before planning |
8888
| `git-worktree` | Isolated parallel development with git |
8989
| `frontend-design` | Production-grade UI implementation |
9090
| `agent-native-architecture` | Design systems where agents are first-class |

skills/using-systematic/SKILL.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ This is not negotiable. This is not optional. You cannot rationalize your way ou
1313

1414
## How to Access Skills
1515

16-
Use the `systematic_skill` tool for Systematic bundled skills. Use the native `skill` tool for non-Systematic skills. When you invoke a skill, its content is loaded and presented to you—follow it directly.
16+
Use the `systematic_skill` tool for Systematic bundled skills. Use the `skill` tool for non-Systematic skills. When you invoke a skill, its content is loaded and presented to you—follow it directly.
1717

1818
# Using Skills
1919

@@ -94,4 +94,4 @@ Instructions say WHAT, not HOW. "Add X" or "Fix Y" doesn't mean skip workflows.
9494

9595
## Skill Resolution
9696

97-
Systematic bundled skills are listed in the `systematic_skill` tool description. Use the native `skill` tool for skills outside the Systematic plugin.
97+
Systematic bundled skills are listed in the `systematic_skill` tool description. Use the `skill` tool for skills outside the Systematic plugin.

src/lib/bootstrap.ts

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -109,22 +109,15 @@ export interface BootstrapDeps {
109109
bundledSkillsDir: string
110110
}
111111

112-
function getToolMappingTemplate(): string {
113-
return `**Tool Mapping for OpenCode:**
114-
When skills reference tools you don't have, substitute OpenCode equivalents:
115-
- \`TodoWrite\` → \`todowrite\`
116-
- \`Task\` tool with subagents → Use OpenCode's subagent system (@mention)
117-
- \`Skill\` tool → OpenCode's native \`skill\` tool
118-
- \`SystematicSkill\` tool → \`systematic_skill\` (Systematic plugin skills)
119-
- \`Read\`, \`Write\`, \`Edit\`, \`Bash\` → Your native tools
120-
121-
**Skills naming:**
122-
- Bundled skills use the \`systematic:\` prefix (e.g., \`systematic:brainstorming\`)
112+
function getSkillUsageTemplate(): string {
113+
return `**Skills naming:**
114+
- Systematic bundled skills use the \`systematic:\` prefix (e.g., \`systematic:setup\`)
115+
- Workflow skills with their own namespace keep it (e.g., \`ce:brainstorm\`)
123116
- Skills can also be invoked without prefix if unambiguous
124117
125118
**Skills usage:**
126119
- Use \`systematic_skill\` to load Systematic bundled skills
127-
- Use the native \`skill\` tool for non-Systematic skills
120+
- Use the \`skill\` tool for non-Systematic skills
128121
129122
**Skills location:**
130123
Bundled skills ship with the Systematic plugin and are discoverable via \`systematic_skill\`.`
@@ -156,20 +149,20 @@ export function getBootstrapContent(
156149
const fullContent = fs.readFileSync(usingSystematicPath, 'utf8')
157150
const { body } = parseFrontmatter(fullContent)
158151
const content = body.trim()
159-
const toolMapping = getToolMappingTemplate()
152+
const skillUsage = getSkillUsageTemplate()
160153
const catalog = renderCatalogVerbose({
161154
bundledSkillsDir,
162155
disabledSkills: config.disabled_skills,
163156
})
164157
const catalogSection = catalog.length > 0 ? `\n\n${catalog}` : ''
165158

166159
return `<SYSTEMATIC_WORKFLOWS>
167-
You have access to structured engineering workflows via the systematic plugin.
160+
You have access to structured engineering workflows via the Systematic plugin.
168161
169162
**IMPORTANT: The using-systematic skill content is included below. It is ALREADY LOADED - you are currently following it. Do NOT use the systematic_skill tool to load "using-systematic" again - that would be redundant.**
170163
171164
${content}
172165
173-
${toolMapping}${catalogSection}
166+
${skillUsage}${catalogSection}
174167
</SYSTEMATIC_WORKFLOWS>`
175168
}

tests/unit/bootstrap.test.ts

Lines changed: 11 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,11 @@
1-
import {
2-
afterAll,
3-
afterEach,
4-
beforeEach,
5-
describe,
6-
expect,
7-
test,
8-
} from 'bun:test'
1+
import { afterEach, beforeEach, describe, expect, test } from 'bun:test'
92
import fs from 'node:fs'
103
import os from 'node:os'
114
import path from 'node:path'
125
import {
136
getBootstrapContent,
147
INTERNAL_AGENT_SIGNATURES,
158
} from '../../src/lib/bootstrap.ts'
16-
import { TOOL_NAME_MAP } from '../../src/lib/converter.ts'
179

1810
/**
1911
* Reconstruct the production skip predicate from src/index.ts:91-97 using the
@@ -76,7 +68,8 @@ describe('getBootstrapContent', () => {
7668
expect(content).toContain('<SYSTEMATIC_WORKFLOWS>')
7769
expect(content).toContain('</SYSTEMATIC_WORKFLOWS>')
7870
expect(content).toContain('Bootstrap body content here.')
79-
expect(content).toContain('**Tool Mapping for OpenCode:**')
71+
expect(content).toContain('**Skills naming:**')
72+
expect(content).not.toContain('**Tool Mapping for OpenCode:**')
8073
})
8174

8275
test('config.bootstrap.enabled = false returns null', () => {
@@ -181,7 +174,7 @@ describe('getBootstrapContent', () => {
181174
expect(content).not.toContain('description: Test skill')
182175
})
183176

184-
test('tool-mapping template does not embed bundledSkillsDir as a raw path', () => {
177+
test('skill-usage template does not embed bundledSkillsDir as a raw path', () => {
185178
const bundledSkillsDir = makeBundledSkillsDir(
186179
'---\nname: using-systematic\n---\nbody',
187180
)
@@ -194,16 +187,16 @@ describe('getBootstrapContent', () => {
194187
const content = getBootstrapContent(config, { bundledSkillsDir })
195188

196189
expect(content).not.toBeNull()
197-
// The tool-mapping prose must not embed the raw path. Slice from the
190+
// The skill-usage prose must not embed the raw path. Slice from the
198191
// heading up to the catalog block (or end of string if no catalog).
199-
const toolMappingHeading = '**Tool Mapping for OpenCode:**'
200-
const toolMappingStart = (content ?? '').indexOf(toolMappingHeading)
201-
expect(toolMappingStart).toBeGreaterThan(-1)
202-
const afterHeading = (content ?? '').slice(toolMappingStart)
192+
const skillUsageHeading = '**Skills naming:**'
193+
const skillUsageStart = (content ?? '').indexOf(skillUsageHeading)
194+
expect(skillUsageStart).toBeGreaterThan(-1)
195+
const afterHeading = (content ?? '').slice(skillUsageStart)
203196
const catalogStart = afterHeading.indexOf('<available_skills>')
204-
const toolMappingProse =
197+
const skillUsageProse =
205198
catalogStart >= 0 ? afterHeading.slice(0, catalogStart) : afterHeading
206-
expect(toolMappingProse).not.toContain(bundledSkillsDir)
199+
expect(skillUsageProse).not.toContain(bundledSkillsDir)
207200
expect(content).toContain(
208201
'Bundled skills ship with the Systematic plugin and are discoverable via `systematic_skill`.',
209202
)
@@ -426,124 +419,3 @@ describe('INTERNAL_AGENT_SIGNATURES skip heuristic', () => {
426419
expect(shouldSkipBootstrap(legitimate)).toBe(true)
427420
})
428421
})
429-
430-
// ---------------------------------------------------------------------------
431-
// TOOL_NAME_MAP ↔ bootstrap template consistency
432-
// ---------------------------------------------------------------------------
433-
434-
describe('TOOL_NAME_MAP / bootstrap template consistency', () => {
435-
// Track temp dirs created by createTempBundledSkillsDir for cleanup.
436-
const tempDirs: string[] = []
437-
afterAll(() => {
438-
for (const dir of tempDirs) {
439-
fs.rmSync(dir, { recursive: true, force: true })
440-
}
441-
})
442-
/**
443-
* Extract all CC tool names from the left side of `→` arrows in the
444-
* "Tool Mapping for OpenCode" section of the bootstrap template.
445-
*
446-
* Handles all three bullet forms found in the template:
447-
* - `X` → `y` (simple 1:1, backtick-delimited OC name)
448-
* - `X` tool with … → prose (prose RHS; extracts X only)
449-
* - `A`, `B`, `C` → prose (multi-name LHS; extracts A, B, C)
450-
*
451-
* Note: this is an overlap-subset check, not a full-map consistency check.
452-
* The bootstrap prose and the converter map only partially overlap by design —
453-
* the bootstrap is instructional text, not a serialised TOOL_NAME_MAP.
454-
*/
455-
// Section heading used to locate the tool-mapping block in the bootstrap
456-
// template. Must match the literal heading in src/lib/bootstrap.ts's
457-
// getToolMappingTemplate(). If that heading changes, this must be updated.
458-
const TOOL_MAPPING_HEADING = '**Tool Mapping for OpenCode:**'
459-
460-
// Matches the start of the NEXT bold markdown heading after the tool-mapping
461-
// section. The negative lookahead (?!Tool Mapping) prevents matching the
462-
// section's own heading if it appears in a self-referential context.
463-
// A new bold heading starting with "Tool" (but not "Tool Mapping") will
464-
// correctly terminate the section — the lookahead only exempts the exact
465-
// phrase "Tool Mapping".
466-
const NEXT_BOLD_HEADING_RE = /\n\*\*(?!Tool Mapping)/
467-
468-
function extractCCToolNames(template: string): string[] {
469-
// Isolate the tool-mapping section to avoid false-positive matches on
470-
// unrelated `→` arrows elsewhere in the bootstrap content.
471-
const sectionStart = template.indexOf(TOOL_MAPPING_HEADING)
472-
if (sectionStart === -1) return []
473-
const rest = template.slice(sectionStart)
474-
const nextHeading = rest.search(NEXT_BOLD_HEADING_RE)
475-
const section = nextHeading >= 0 ? rest.slice(0, nextHeading) : rest
476-
477-
// For each bullet line, extract backtick-quoted tokens from the LHS of `→`.
478-
// Uses flatMap to avoid nested loops that inflate cognitive complexity.
479-
return section
480-
.split('\n')
481-
.filter((line) => line.startsWith('- '))
482-
.flatMap((line) => {
483-
const arrowIdx = line.indexOf(' → ')
484-
const lhs = arrowIdx >= 0 ? line.slice(0, arrowIdx) : line
485-
return [...lhs.matchAll(/`([^`]+)`/g)].map((m) => m[1] ?? '')
486-
})
487-
.filter(Boolean)
488-
}
489-
490-
/**
491-
* Names that appear in the template mapping section but are intentionally
492-
* Systematic-specific rather than imported from CC. These do not need a
493-
* TOOL_NAME_MAP entry (the map covers CC→Systematic converter renames only).
494-
*/
495-
const SYSTEMATIC_ONLY_TOOLS = new Set(['systematicskill'])
496-
497-
test('rendered template contains at least one CC tool reference', () => {
498-
const content = getBootstrapContent(
499-
{
500-
bootstrap: { enabled: true, file: undefined },
501-
disabled_skills: [],
502-
disabled_agents: [],
503-
disabled_commands: [],
504-
},
505-
{ bundledSkillsDir: createTempBundledSkillsDir() },
506-
)
507-
expect(content).not.toBeNull()
508-
expect(extractCCToolNames(content ?? '').length).toBeGreaterThan(0)
509-
})
510-
511-
test('every CC tool name in the template mapping section is a key in TOOL_NAME_MAP', () => {
512-
const content = getBootstrapContent(
513-
{
514-
bootstrap: { enabled: true, file: undefined },
515-
disabled_skills: [],
516-
disabled_agents: [],
517-
disabled_commands: [],
518-
},
519-
{ bundledSkillsDir: createTempBundledSkillsDir() },
520-
)
521-
const ccNames = extractCCToolNames(content ?? '')
522-
// Guard against section-parse regressions
523-
expect(ccNames.length).toBeGreaterThan(0)
524-
525-
for (const cc of ccNames) {
526-
const normalized = cc.toLowerCase()
527-
if (SYSTEMATIC_ONLY_TOOLS.has(normalized)) continue
528-
expect(
529-
TOOL_NAME_MAP,
530-
`Bootstrap template references "${cc}" but TOOL_NAME_MAP has no key "${normalized}"`,
531-
).toHaveProperty(normalized)
532-
}
533-
})
534-
535-
function createTempBundledSkillsDir(): string {
536-
const dir = fs.mkdtempSync(
537-
path.join(os.tmpdir(), 'systematic-bootstrap-consistency-'),
538-
)
539-
tempDirs.push(dir)
540-
fs.mkdirSync(path.join(dir, 'skills', 'using-systematic'), {
541-
recursive: true,
542-
})
543-
fs.writeFileSync(
544-
path.join(dir, 'skills', 'using-systematic', 'SKILL.md'),
545-
'---\nname: using-systematic\n---\nbody',
546-
)
547-
return path.join(dir, 'skills')
548-
}
549-
})

0 commit comments

Comments
 (0)