@soleri/forge 9.8.0 → 9.10.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/dist/agent-schema.d.ts +11 -0
- package/dist/agent-schema.js +8 -0
- package/dist/agent-schema.js.map +1 -1
- package/dist/compose-claude-md.d.ts +11 -0
- package/dist/compose-claude-md.js +104 -0
- package/dist/compose-claude-md.js.map +1 -1
- package/dist/lib.d.ts +2 -1
- package/dist/lib.js +1 -1
- package/dist/lib.js.map +1 -1
- package/dist/scaffold-filetree.js +28 -11
- package/dist/scaffold-filetree.js.map +1 -1
- package/dist/skills/subagent-driven-development/SKILL.md +87 -20
- package/dist/templates/inject-claude-md.js +50 -5
- package/dist/templates/inject-claude-md.js.map +1 -1
- package/dist/templates/section-parser.d.ts +33 -0
- package/dist/templates/section-parser.js +75 -0
- package/dist/templates/section-parser.js.map +1 -0
- package/dist/templates/shared-rules.d.ts +14 -0
- package/dist/templates/shared-rules.js +192 -11
- package/dist/templates/shared-rules.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/compose-claude-md.test.ts +89 -0
- package/src/__tests__/scaffold-filetree.test.ts +93 -0
- package/src/__tests__/scaffolder.test.ts +7 -5
- package/src/__tests__/shared-rules.test.ts +99 -1
- package/src/agent-schema.ts +8 -0
- package/src/compose-claude-md.ts +124 -0
- package/src/lib.ts +7 -1
- package/src/scaffold-filetree.ts +34 -11
- package/src/skills/subagent-driven-development/SKILL.md +87 -20
- package/src/templates/inject-claude-md.ts +50 -5
- package/src/templates/section-parser.ts +97 -0
- package/src/templates/shared-rules.ts +203 -11
|
@@ -8,10 +8,37 @@ description: >
|
|
|
8
8
|
|
|
9
9
|
# Subagent-Driven Development
|
|
10
10
|
|
|
11
|
-
Decompose work into isolated units, dispatch subagents via the Agent tool, merge results back. You are the
|
|
11
|
+
Decompose work into isolated units, dispatch subagents via the Agent tool, merge results back. You are the orchestrator — you make all decisions, subagents execute.
|
|
12
12
|
|
|
13
13
|
**Announce at start:** "I'm using the subagent-driven-development skill to dispatch isolated agents."
|
|
14
14
|
|
|
15
|
+
## The Orchestrator Contract
|
|
16
|
+
|
|
17
|
+
**You are the boss. Subagents are the crew.**
|
|
18
|
+
|
|
19
|
+
1. **All decisions stay with the orchestrator.** Research the task, consult the vault, decide the approach. Subagents receive exact specs — scope, file boundaries, acceptance criteria. They execute, they don't decide.
|
|
20
|
+
2. **Subagents MUST NOT create plans.** Only the orchestrator creates plans. Subagent prompts must explicitly state: "Do NOT create plans, do NOT call planning tools."
|
|
21
|
+
3. **If a subagent hits ambiguity, it returns — it doesn't guess.** The orchestrator resolves, then re-dispatches.
|
|
22
|
+
4. **The orchestrator reconciles all work.** After subagents return, the orchestrator reviews changes, merges, captures knowledge.
|
|
23
|
+
|
|
24
|
+
## Hybrid Agent Routing
|
|
25
|
+
|
|
26
|
+
Not all subagents are equal. Route by complexity:
|
|
27
|
+
|
|
28
|
+
| Signal | Agent Type | Why |
|
|
29
|
+
| ------------------------------------- | ------------------------- | ----------------------------- |
|
|
30
|
+
| Single file, clear spec, no decisions | **Claude Code worker** | Fast, low overhead |
|
|
31
|
+
| Approach already in parent plan | **Claude Code worker** | Spec is decided |
|
|
32
|
+
| 3+ files, cross-cutting concerns | **Soleri agent instance** | Needs vault, brain, lifecycle |
|
|
33
|
+
| Unresolved design decisions | **Soleri agent instance** | Needs judgment |
|
|
34
|
+
| New dependencies or architecture | **Soleri agent instance** | Needs full context |
|
|
35
|
+
|
|
36
|
+
**User overrides:**
|
|
37
|
+
|
|
38
|
+
- "Use full agent for everything" → all Soleri agent instances
|
|
39
|
+
- "Just use workers" → all Claude Code workers
|
|
40
|
+
- Default: hybrid routing
|
|
41
|
+
|
|
15
42
|
## When to Dispatch
|
|
16
43
|
|
|
17
44
|
| Signal | Dispatch? |
|
|
@@ -25,47 +52,87 @@ Decompose work into isolated units, dispatch subagents via the Agent tool, merge
|
|
|
25
52
|
|
|
26
53
|
## The Process
|
|
27
54
|
|
|
28
|
-
### Step 1:
|
|
55
|
+
### Step 1: Research & Decide (Orchestrator only)
|
|
56
|
+
|
|
57
|
+
Read all relevant files. Consult the vault for patterns. Make every design decision. Define the exact spec for each subagent task: files to touch, approach to use, acceptance criteria.
|
|
29
58
|
|
|
30
|
-
|
|
59
|
+
### Step 2: Decompose & Route
|
|
31
60
|
|
|
32
|
-
|
|
61
|
+
Break work into discrete units. For each, determine: files involved, dependencies on other units, conflict risk, complexity. Assign agent type per the routing table.
|
|
62
|
+
|
|
63
|
+
### Step 3: Dispatch
|
|
64
|
+
|
|
65
|
+
Present the dispatch table to the user:
|
|
33
66
|
|
|
34
67
|
```
|
|
35
|
-
|
|
68
|
+
## Dispatching N tasks in parallel
|
|
69
|
+
|
|
70
|
+
| # | Task | Agent | Why |
|
|
71
|
+
|---|------|-------|-----|
|
|
72
|
+
| 1 | Description | Worker / Instance | Routing reason |
|
|
36
73
|
```
|
|
37
74
|
|
|
38
|
-
Each subagent prompt must include:
|
|
75
|
+
Each subagent prompt must include:
|
|
76
|
+
|
|
77
|
+
- Task scope and file boundaries
|
|
78
|
+
- Acceptance criteria
|
|
79
|
+
- "Do NOT create plans. Do NOT make design decisions. Execute this spec exactly."
|
|
80
|
+
- For Soleri instances: "Activate, execute, run orchestrate_complete when done."
|
|
39
81
|
|
|
40
82
|
Launch all independent subagents in a **single message** so they run in parallel.
|
|
83
|
+
Use `isolation: "worktree"` for file-modifying tasks.
|
|
41
84
|
|
|
42
|
-
### Step
|
|
85
|
+
### Step 4: Review and Merge
|
|
43
86
|
|
|
44
87
|
For each returning subagent:
|
|
45
88
|
|
|
46
89
|
1. **Review** — read actual file changes (do not trust self-reports alone), verify tests pass, check scope compliance
|
|
47
90
|
2. **Merge** — `git merge` or `git cherry-pick` from the worktree branch, one at a time
|
|
48
91
|
3. **Test** — run the full suite after each merge; only proceed if green
|
|
49
|
-
4. **Conflicts** — resolve manually, re-run tests, capture as anti-pattern
|
|
92
|
+
4. **Conflicts** — resolve manually, re-run tests, capture as anti-pattern
|
|
93
|
+
|
|
94
|
+
### Step 5: Reconcile & Report
|
|
95
|
+
|
|
96
|
+
After all merges, report to the user:
|
|
50
97
|
|
|
51
|
-
|
|
98
|
+
**Minimal (default):**
|
|
52
99
|
|
|
53
100
|
```
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
101
|
+
✓ N/N complete. M patterns captured to vault.
|
|
102
|
+
→ Decisions: [any design decisions the orchestrator made]
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Detailed (on request):**
|
|
106
|
+
|
|
58
107
|
```
|
|
108
|
+
| # | Task | Agent | Status | Knowledge |
|
|
109
|
+
|---|------|-------|--------|-----------|
|
|
110
|
+
| 1 | Desc | Worker | Done ✓ | — |
|
|
111
|
+
| 2 | Desc | Instance | Done ✓ | 2 patterns |
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Capture learnings to vault. Run `orchestrate_complete` for the parent plan.
|
|
115
|
+
|
|
116
|
+
## Worktree Cleanup Guarantee
|
|
117
|
+
|
|
118
|
+
Three layers — nothing accumulates:
|
|
119
|
+
|
|
120
|
+
1. **Per-task:** `finally` block in dispatcher removes worktree after each task
|
|
121
|
+
2. **Per-batch:** `cleanupAll()` runs after all subagents complete
|
|
122
|
+
3. **Per-session:** `SessionStart` hook prunes orphaned worktrees
|
|
59
123
|
|
|
60
124
|
## Anti-Patterns
|
|
61
125
|
|
|
62
|
-
| Anti-Pattern | Why It Fails
|
|
63
|
-
| -------------------------------------------- |
|
|
64
|
-
|
|
|
65
|
-
|
|
|
66
|
-
|
|
|
67
|
-
|
|
|
68
|
-
|
|
|
126
|
+
| Anti-Pattern | Why It Fails |
|
|
127
|
+
| -------------------------------------------- | --------------------------------------------------- |
|
|
128
|
+
| Subagent creating its own plan | Stale plans accumulate, lifecycle never completes |
|
|
129
|
+
| Subagent making design decisions | Inconsistent approaches, orchestrator loses control |
|
|
130
|
+
| Dispatching for a 5-line fix | Startup overhead exceeds the work |
|
|
131
|
+
| Parallel dispatch of dependent tasks | Second agent works on stale assumptions |
|
|
132
|
+
| Skipping worktree isolation for nearby files | Silent overwrites between agents |
|
|
133
|
+
| Trusting self-reports without reading code | Agents miss edge cases or misunderstand scope |
|
|
134
|
+
| Dispatching 10+ agents at once | Review bottleneck shifts to the controller |
|
|
135
|
+
| Not cleaning up worktrees after merge | Disk bloat, stale branch accumulation |
|
|
69
136
|
|
|
70
137
|
## Merge Strategy
|
|
71
138
|
|
|
@@ -67,10 +67,15 @@ export function generateInjectClaudeMd(config) {
|
|
|
67
67
|
' * `<!-- soleri:engine-rules -->`. If already present, they are updated.',
|
|
68
68
|
' * Agent block (identity + facade table) is injected under',
|
|
69
69
|
` * \`<!-- ${marker} -->\`.`,
|
|
70
|
+
' *',
|
|
71
|
+
' * @param skipEngineRules - If true, skip engine rules injection (used for global files)',
|
|
70
72
|
' */',
|
|
71
|
-
'function injectIntoFile(filePath: string): InjectResult {',
|
|
72
|
-
' // Step 1: Engine rules — shared across all agents',
|
|
73
|
-
'
|
|
73
|
+
'function injectIntoFile(filePath: string, skipEngineRules = false): InjectResult {',
|
|
74
|
+
' // Step 1: Engine rules — shared across all agents (skip for global files)',
|
|
75
|
+
' let engineAction: string = "skipped";',
|
|
76
|
+
' if (!skipEngineRules) {',
|
|
77
|
+
' engineAction = injectBlock(filePath, getEngineRulesContent(), getEngineRulesMarker());',
|
|
78
|
+
' }',
|
|
74
79
|
'',
|
|
75
80
|
' // Step 2: Agent-specific block',
|
|
76
81
|
' const agentAction = injectBlock(filePath, getClaudeMdContent(), getClaudeMdMarker());',
|
|
@@ -96,13 +101,24 @@ export function generateInjectClaudeMd(config) {
|
|
|
96
101
|
' * Inject into the global ~/.claude/CLAUDE.md.',
|
|
97
102
|
" * Creates ~/.claude/ directory if it doesn't exist.",
|
|
98
103
|
' * This makes the activation phrase work in any project.',
|
|
104
|
+
' * Engine rules are NOT injected globally — they live in project-level CLAUDE.md only.',
|
|
99
105
|
' */',
|
|
100
106
|
'export function injectClaudeMdGlobal(): InjectResult {',
|
|
101
107
|
" const claudeDir = join(homedir(), '.claude');",
|
|
102
108
|
' if (!existsSync(claudeDir)) {',
|
|
103
109
|
' mkdirSync(claudeDir, { recursive: true });',
|
|
104
110
|
' }',
|
|
105
|
-
"
|
|
111
|
+
" const filePath = join(claudeDir, 'CLAUDE.md');",
|
|
112
|
+
'',
|
|
113
|
+
' // Add header comment for new files',
|
|
114
|
+
' if (!existsSync(filePath)) {',
|
|
115
|
+
" writeFileSync(filePath, '<!-- Global agent activation file. Engine rules live in project-level CLAUDE.md only. -->\\n', 'utf-8');",
|
|
116
|
+
' }',
|
|
117
|
+
'',
|
|
118
|
+
' // Self-heal: strip engine rules if they leaked into the global file',
|
|
119
|
+
' removeBlock(filePath, getEngineRulesMarker());',
|
|
120
|
+
'',
|
|
121
|
+
' return injectIntoFile(filePath, true);',
|
|
106
122
|
'}',
|
|
107
123
|
'',
|
|
108
124
|
'/**',
|
|
@@ -151,6 +167,24 @@ export function generateInjectClaudeMd(config) {
|
|
|
151
167
|
'}',
|
|
152
168
|
'',
|
|
153
169
|
'/**',
|
|
170
|
+
' * Remove engine rules from the global ~/.claude/CLAUDE.md.',
|
|
171
|
+
' * Self-healing: strips engine rules that should not be in the global file.',
|
|
172
|
+
' */',
|
|
173
|
+
'export function removeEngineRulesFromGlobal(): { removed: boolean; path: string } {',
|
|
174
|
+
" const filePath = join(homedir(), '.claude', 'CLAUDE.md');",
|
|
175
|
+
' return { removed: removeBlock(filePath, getEngineRulesMarker()), path: filePath };',
|
|
176
|
+
'}',
|
|
177
|
+
'',
|
|
178
|
+
'/**',
|
|
179
|
+
' * Remove engine rules from the global ~/.config/opencode/AGENTS.md.',
|
|
180
|
+
' * Self-healing: strips engine rules that should not be in the global file.',
|
|
181
|
+
' */',
|
|
182
|
+
'export function removeEngineRulesFromGlobalAgentsMd(): { removed: boolean; path: string } {',
|
|
183
|
+
" const filePath = join(homedir(), '.config', 'opencode', 'AGENTS.md');",
|
|
184
|
+
' return { removed: removeBlock(filePath, getEngineRulesMarker()), path: filePath };',
|
|
185
|
+
'}',
|
|
186
|
+
'',
|
|
187
|
+
'/**',
|
|
154
188
|
' * Check if the agent marker exists in a CLAUDE.md file.',
|
|
155
189
|
' */',
|
|
156
190
|
'export function hasAgentMarker(filePath: string): boolean {',
|
|
@@ -183,13 +217,24 @@ export function generateInjectClaudeMd(config) {
|
|
|
183
217
|
' * Inject into the global ~/.config/opencode/AGENTS.md.',
|
|
184
218
|
" * Creates ~/.config/opencode/ directory if it doesn't exist.",
|
|
185
219
|
' * This makes the activation phrase work in any OpenCode project.',
|
|
220
|
+
' * Engine rules are NOT injected globally — they live in project-level AGENTS.md only.',
|
|
186
221
|
' */',
|
|
187
222
|
'export function injectAgentsMdGlobal(): InjectResult {',
|
|
188
223
|
" const opencodeDir = join(homedir(), '.config', 'opencode');",
|
|
189
224
|
' if (!existsSync(opencodeDir)) {',
|
|
190
225
|
' mkdirSync(opencodeDir, { recursive: true });',
|
|
191
226
|
' }',
|
|
192
|
-
"
|
|
227
|
+
" const filePath = join(opencodeDir, 'AGENTS.md');",
|
|
228
|
+
'',
|
|
229
|
+
' // Add header comment for new files',
|
|
230
|
+
' if (!existsSync(filePath)) {',
|
|
231
|
+
" writeFileSync(filePath, '<!-- Global agent activation file. Engine rules live in project-level AGENTS.md only. -->\\n', 'utf-8');",
|
|
232
|
+
' }',
|
|
233
|
+
'',
|
|
234
|
+
' // Self-heal: strip engine rules if they leaked into the global file',
|
|
235
|
+
' removeBlock(filePath, getEngineRulesMarker());',
|
|
236
|
+
'',
|
|
237
|
+
' return injectIntoFile(filePath, true);',
|
|
193
238
|
'}',
|
|
194
239
|
'',
|
|
195
240
|
'/**',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inject-claude-md.js","sourceRoot":"","sources":["../../src/templates/inject-claude-md.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAmB;IACxD,MAAM,MAAM,GAAG,GAAG,MAAM,CAAC,EAAE,OAAO,CAAC;IAEnC,OAAO;QACL,+EAA+E;QAC/E,oCAAoC;QACpC,mCAAmC;QACnC,8HAA8H;QAC9H,EAAE;QACF,iCAAiC;QACjC,sBAAsB;QACtB,iBAAiB;QACjB,+CAA+C;QAC/C,0BAA0B;QAC1B,GAAG;QACH,EAAE;QACF,KAAK;QACL,iDAAiD;QACjD,wEAAwE;QACxE,6CAA6C;QAC7C,KAAK;QACL,2HAA2H;QAC3H,kDAAkD;QAClD,iDAAiD;QACjD,EAAE;QACF,gCAAgC;QAChC,wDAAwD;QACxD,uBAAuB;QACvB,KAAK;QACL,EAAE;QACF,qDAAqD;QACrD,EAAE;QACF,yCAAyC;QACzC,qDAAqD;QACrD,iDAAiD;QACjD,0BAA0B;QAC1B,iFAAiF;QACjF,8DAA8D;QAC9D,OAAO;QACP,0BAA0B;QAC1B,sHAAsH;QACtH,kDAAkD;QAClD,yBAAyB;QACzB,OAAO;QACP,wGAAwG;QACxG,gDAAgD;QAChD,uBAAuB;QACvB,KAAK;QACL,EAAE;QACF,kEAAkE;QAClE,6EAA6E;QAC7E,sBAAsB;QACtB,GAAG;QACH,EAAE;QACF,KAAK;QACL,6DAA6D;QAC7D,IAAI;QACJ,+DAA+D;QAC/D,0EAA0E;QAC1E,4DAA4D;QAC5D,aAAa,MAAM,SAAS;QAC5B,KAAK;QACL,
|
|
1
|
+
{"version":3,"file":"inject-claude-md.js","sourceRoot":"","sources":["../../src/templates/inject-claude-md.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Section parser for marker-delimited engine rules content.
|
|
3
|
+
*
|
|
4
|
+
* Extracts `<!-- soleri:xxx -->` sections from the engine rules markdown,
|
|
5
|
+
* enabling selective inclusion of feature modules.
|
|
6
|
+
*
|
|
7
|
+
* Single-pass: splits on `## ` headings, maps chunks to markers, filters.
|
|
8
|
+
*/
|
|
9
|
+
export interface ParsedSection {
|
|
10
|
+
/** e.g. 'soleri:response-integrity' */
|
|
11
|
+
marker: string;
|
|
12
|
+
/** Full text including heading and marker comment */
|
|
13
|
+
content: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ParsedContent {
|
|
16
|
+
/** Everything before the first section */
|
|
17
|
+
preamble: string;
|
|
18
|
+
/** Ordered list of parsed sections */
|
|
19
|
+
sections: ParsedSection[];
|
|
20
|
+
/** Closing marker line and anything after */
|
|
21
|
+
closing: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Parse marker-delimited sections from engine rules content.
|
|
25
|
+
*
|
|
26
|
+
* Strategy: split on `## ` heading boundaries, then classify each chunk
|
|
27
|
+
* as preamble, section (has a marker), or closing (has closing marker).
|
|
28
|
+
*/
|
|
29
|
+
export declare function parseSections(content: string): ParsedContent;
|
|
30
|
+
/**
|
|
31
|
+
* Rebuild content from parsed sections, including only allowed markers.
|
|
32
|
+
*/
|
|
33
|
+
export declare function filterSections(parsed: ParsedContent, allowedMarkers: Set<string>): string;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Section parser for marker-delimited engine rules content.
|
|
3
|
+
*
|
|
4
|
+
* Extracts `<!-- soleri:xxx -->` sections from the engine rules markdown,
|
|
5
|
+
* enabling selective inclusion of feature modules.
|
|
6
|
+
*
|
|
7
|
+
* Single-pass: splits on `## ` headings, maps chunks to markers, filters.
|
|
8
|
+
*/
|
|
9
|
+
const SECTION_MARKER_RE = /<!-- (soleri:[a-z-]+) -->/;
|
|
10
|
+
const CLOSING_MARKER = '<!-- /soleri:engine-rules -->';
|
|
11
|
+
/**
|
|
12
|
+
* Parse marker-delimited sections from engine rules content.
|
|
13
|
+
*
|
|
14
|
+
* Strategy: split on `## ` heading boundaries, then classify each chunk
|
|
15
|
+
* as preamble, section (has a marker), or closing (has closing marker).
|
|
16
|
+
*/
|
|
17
|
+
export function parseSections(content) {
|
|
18
|
+
// Split at each `## ` heading — lookahead preserves the heading in the chunk
|
|
19
|
+
const chunks = content.split(/(?=^## )/m);
|
|
20
|
+
let preamble = '';
|
|
21
|
+
const sections = [];
|
|
22
|
+
let closing = '';
|
|
23
|
+
let foundFirstSection = false;
|
|
24
|
+
for (const chunk of chunks) {
|
|
25
|
+
// Check if this chunk contains the closing marker
|
|
26
|
+
const closingIdx = chunk.indexOf(CLOSING_MARKER);
|
|
27
|
+
if (closingIdx !== -1) {
|
|
28
|
+
// Content before closing marker belongs to last section or preamble
|
|
29
|
+
const beforeClosing = chunk.slice(0, closingIdx);
|
|
30
|
+
const afterClosing = chunk.slice(closingIdx);
|
|
31
|
+
if (beforeClosing.trim()) {
|
|
32
|
+
const markerMatch = beforeClosing.match(SECTION_MARKER_RE);
|
|
33
|
+
if (markerMatch && markerMatch[1] !== 'soleri:engine-rules') {
|
|
34
|
+
sections.push({ marker: markerMatch[1], content: beforeClosing });
|
|
35
|
+
foundFirstSection = true;
|
|
36
|
+
}
|
|
37
|
+
else if (!foundFirstSection) {
|
|
38
|
+
preamble += beforeClosing;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
closing = afterClosing;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
// Check if chunk has a section marker
|
|
45
|
+
const markerMatch = chunk.match(SECTION_MARKER_RE);
|
|
46
|
+
if (markerMatch && markerMatch[1] !== 'soleri:engine-rules') {
|
|
47
|
+
sections.push({ marker: markerMatch[1], content: chunk });
|
|
48
|
+
foundFirstSection = true;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
// No marker — this is preamble (before first section)
|
|
52
|
+
if (!foundFirstSection) {
|
|
53
|
+
preamble += chunk;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return { preamble, sections, closing };
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Rebuild content from parsed sections, including only allowed markers.
|
|
61
|
+
*/
|
|
62
|
+
export function filterSections(parsed, allowedMarkers) {
|
|
63
|
+
const parts = [parsed.preamble];
|
|
64
|
+
for (const section of parsed.sections) {
|
|
65
|
+
if (allowedMarkers.has(section.marker)) {
|
|
66
|
+
let text = section.content;
|
|
67
|
+
if (!text.endsWith('\n'))
|
|
68
|
+
text += '\n';
|
|
69
|
+
parts.push(text);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
parts.push(parsed.closing);
|
|
73
|
+
return parts.join('\n');
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=section-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"section-parser.js","sourceRoot":"","sources":["../../src/templates/section-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAkBH,MAAM,iBAAiB,GAAG,2BAA2B,CAAC;AACtD,MAAM,cAAc,GAAG,+BAA+B,CAAC;AAEvD;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,6EAA6E;IAC7E,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAE1C,IAAI,QAAQ,GAAG,EAAE,CAAC;IAClB,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,iBAAiB,GAAG,KAAK,CAAC;IAE9B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,kDAAkD;QAClD,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QACjD,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;YACtB,oEAAoE;YACpE,MAAM,aAAa,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;YACjD,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAE7C,IAAI,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC;gBACzB,MAAM,WAAW,GAAG,aAAa,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;gBAC3D,IAAI,WAAW,IAAI,WAAW,CAAC,CAAC,CAAC,KAAK,qBAAqB,EAAE,CAAC;oBAC5D,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,CAAC;oBAClE,iBAAiB,GAAG,IAAI,CAAC;gBAC3B,CAAC;qBAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;oBAC9B,QAAQ,IAAI,aAAa,CAAC;gBAC5B,CAAC;YACH,CAAC;YACD,OAAO,GAAG,YAAY,CAAC;YACvB,SAAS;QACX,CAAC;QAED,sCAAsC;QACtC,MAAM,WAAW,GAAG,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACnD,IAAI,WAAW,IAAI,WAAW,CAAC,CAAC,CAAC,KAAK,qBAAqB,EAAE,CAAC;YAC5D,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YAC1D,iBAAiB,GAAG,IAAI,CAAC;QAC3B,CAAC;aAAM,CAAC;YACN,sDAAsD;YACtD,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBACvB,QAAQ,IAAI,KAAK,CAAC;YACpB,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,MAAqB,EAAE,cAA2B;IAC/E,MAAM,KAAK,GAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAE1C,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACtC,IAAI,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACvC,IAAI,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;YAC3B,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE,IAAI,IAAI,IAAI,CAAC;YACvC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3B,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -11,3 +11,17 @@
|
|
|
11
11
|
export declare function getEngineMarker(): string;
|
|
12
12
|
/** Returns the full engine rules markdown content (with markers). */
|
|
13
13
|
export declare function getEngineRulesContent(): string;
|
|
14
|
+
/** Feature modules that can be selectively included in engine rules. */
|
|
15
|
+
export type EngineFeature = 'vault' | 'planning' | 'brain' | 'advanced';
|
|
16
|
+
/** All available feature modules. */
|
|
17
|
+
export declare const ENGINE_FEATURES: readonly EngineFeature[];
|
|
18
|
+
/**
|
|
19
|
+
* Returns engine rules with only selected feature modules included.
|
|
20
|
+
*
|
|
21
|
+
* Core rules are ALWAYS included. Feature modules are included when:
|
|
22
|
+
* - `features` is undefined/empty → ALL modules included (backward compatible)
|
|
23
|
+
* - `features` is specified → only listed modules + core
|
|
24
|
+
*
|
|
25
|
+
* @param features - Feature modules to include. Omit for all.
|
|
26
|
+
*/
|
|
27
|
+
export declare function getModularEngineRules(features?: EngineFeature[]): string;
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* Uses op:name syntax — the active agent provides the tool prefix.
|
|
10
10
|
*/
|
|
11
|
+
import { parseSections, filterSections } from './section-parser.js';
|
|
11
12
|
const ENGINE_MARKER = 'soleri:engine-rules';
|
|
12
13
|
export function getEngineMarker() {
|
|
13
14
|
return ENGINE_MARKER;
|
|
@@ -16,6 +17,75 @@ export function getEngineMarker() {
|
|
|
16
17
|
export function getEngineRulesContent() {
|
|
17
18
|
return ENGINE_RULES_LINES.join('\n');
|
|
18
19
|
}
|
|
20
|
+
/** All available feature modules. */
|
|
21
|
+
export const ENGINE_FEATURES = [
|
|
22
|
+
'vault',
|
|
23
|
+
'planning',
|
|
24
|
+
'brain',
|
|
25
|
+
'advanced',
|
|
26
|
+
];
|
|
27
|
+
/**
|
|
28
|
+
* Section markers grouped by module.
|
|
29
|
+
*
|
|
30
|
+
* 'core' sections are always included.
|
|
31
|
+
* Feature modules are included only when requested (or when no filter is specified).
|
|
32
|
+
*/
|
|
33
|
+
const MODULE_SECTIONS = {
|
|
34
|
+
core: [
|
|
35
|
+
'soleri:what-is-soleri',
|
|
36
|
+
'soleri:response-integrity',
|
|
37
|
+
'soleri:tool-schema-validation',
|
|
38
|
+
'soleri:memory-quality',
|
|
39
|
+
'soleri:output-formatting',
|
|
40
|
+
'soleri:clean-commits',
|
|
41
|
+
'soleri:intent-detection',
|
|
42
|
+
'soleri:overlay-mode',
|
|
43
|
+
'soleri:session',
|
|
44
|
+
'soleri:getting-started',
|
|
45
|
+
'soleri:cli',
|
|
46
|
+
'soleri:persona-self-update',
|
|
47
|
+
'soleri:workspace-routing',
|
|
48
|
+
],
|
|
49
|
+
vault: [
|
|
50
|
+
'soleri:vault-protocol',
|
|
51
|
+
'soleri:knowledge-capture',
|
|
52
|
+
'soleri:tool-advocacy',
|
|
53
|
+
'soleri:cross-project',
|
|
54
|
+
],
|
|
55
|
+
planning: [
|
|
56
|
+
'soleri:planning',
|
|
57
|
+
'soleri:workflow-overrides',
|
|
58
|
+
'soleri:yolo-mode',
|
|
59
|
+
'soleri:task-routing',
|
|
60
|
+
'soleri:validation-loop',
|
|
61
|
+
'soleri:verification-protocol',
|
|
62
|
+
],
|
|
63
|
+
brain: ['soleri:brain', 'soleri:model-routing'],
|
|
64
|
+
advanced: ['soleri:subagent-identity'],
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Returns engine rules with only selected feature modules included.
|
|
68
|
+
*
|
|
69
|
+
* Core rules are ALWAYS included. Feature modules are included when:
|
|
70
|
+
* - `features` is undefined/empty → ALL modules included (backward compatible)
|
|
71
|
+
* - `features` is specified → only listed modules + core
|
|
72
|
+
*
|
|
73
|
+
* @param features - Feature modules to include. Omit for all.
|
|
74
|
+
*/
|
|
75
|
+
export function getModularEngineRules(features) {
|
|
76
|
+
if (!features || features.length === 0) {
|
|
77
|
+
return getEngineRulesContent();
|
|
78
|
+
}
|
|
79
|
+
const allowedMarkers = new Set(MODULE_SECTIONS.core);
|
|
80
|
+
for (const feature of features) {
|
|
81
|
+
const sections = MODULE_SECTIONS[feature];
|
|
82
|
+
if (sections)
|
|
83
|
+
for (const m of sections)
|
|
84
|
+
allowedMarkers.add(m);
|
|
85
|
+
}
|
|
86
|
+
const parsed = parseSections(getEngineRulesContent());
|
|
87
|
+
return filterSections(parsed, allowedMarkers);
|
|
88
|
+
}
|
|
19
89
|
const ENGINE_RULES_LINES = [
|
|
20
90
|
`<!-- ${ENGINE_MARKER} -->`,
|
|
21
91
|
'',
|
|
@@ -212,6 +282,41 @@ const ENGINE_RULES_LINES = [
|
|
|
212
282
|
'| skipped | ... | medium | ... |',
|
|
213
283
|
'```',
|
|
214
284
|
'',
|
|
285
|
+
// ─── Workflow Overrides ──────────────────────────────────
|
|
286
|
+
'## Workflow Overrides',
|
|
287
|
+
'<!-- soleri:workflow-overrides -->',
|
|
288
|
+
'',
|
|
289
|
+
"The engine reads `gates.yaml` and `tools.yaml` from your agent's `workflows/` directory and merges them into plans.",
|
|
290
|
+
'',
|
|
291
|
+
'**Three files, three purposes:**',
|
|
292
|
+
'- `prompt.md` — Claude reads this as narrative guidance (what to do)',
|
|
293
|
+
'- `gates.yaml` — Engine enforces these as plan checkpoints (when to validate)',
|
|
294
|
+
'- `tools.yaml` — Engine merges these into plan steps (what tools to use)',
|
|
295
|
+
'',
|
|
296
|
+
'**Default mapping** (workflow name → orchestration intent):',
|
|
297
|
+
'| Workflow | Intent |',
|
|
298
|
+
'|----------|--------|',
|
|
299
|
+
'| `feature-dev` | BUILD |',
|
|
300
|
+
'| `bug-fix` | FIX |',
|
|
301
|
+
'| `code-review` | REVIEW |',
|
|
302
|
+
'| `context-handoff` | HANDOFF |',
|
|
303
|
+
'',
|
|
304
|
+
'Override in `agent.yaml`:',
|
|
305
|
+
'```yaml',
|
|
306
|
+
'workflowIntents:',
|
|
307
|
+
' my-custom-workflow: BUILD',
|
|
308
|
+
' security-review: REVIEW',
|
|
309
|
+
'```',
|
|
310
|
+
'',
|
|
311
|
+
'**How it works:**',
|
|
312
|
+
'1. You call `orchestrate_plan` with a task',
|
|
313
|
+
'2. Engine detects intent (e.g., REVIEW)',
|
|
314
|
+
'3. Engine checks if your agent has a matching workflow (e.g., `workflows/code-review/`)',
|
|
315
|
+
'4. If found: workflow gates are appended to plan gates, workflow tools are merged into plan steps',
|
|
316
|
+
'5. If not found: current behavior unchanged',
|
|
317
|
+
'',
|
|
318
|
+
'**Editing workflows changes engine behavior.** If you modify `gates.yaml` in `workflows/code-review/`, the next REVIEW plan will include your custom gates.',
|
|
319
|
+
'',
|
|
215
320
|
// ─── YOLO Mode ──────────────────────────────────────────
|
|
216
321
|
'## YOLO Mode',
|
|
217
322
|
'<!-- soleri:yolo-mode -->',
|
|
@@ -582,6 +687,17 @@ const ENGINE_RULES_LINES = [
|
|
|
582
687
|
'The scaffolded agent is ready immediately — no build step, no npm install for the agent itself.',
|
|
583
688
|
'Git is initialized by default (`git init` + initial commit). Use `--no-git` to skip. After scaffolding, the CLI offers to set up a remote via `gh repo create` (if gh CLI is available) or a manual remote URL. The `--yes` flag enables git init but skips the remote prompt.',
|
|
584
689
|
'',
|
|
690
|
+
'### Browsable Knowledge',
|
|
691
|
+
'',
|
|
692
|
+
"Your agent's vault is automatically synced to `knowledge/vault/` as markdown files. Browse them in VS Code, Obsidian, or any editor.",
|
|
693
|
+
'',
|
|
694
|
+
'```bash',
|
|
695
|
+
'# Export vault to a custom location (e.g., Obsidian)',
|
|
696
|
+
'soleri vault export --path ~/obsidian-vault/soleri',
|
|
697
|
+
'```',
|
|
698
|
+
'',
|
|
699
|
+
'The engine indexes entries in SQLite for fast search, but you always own the files.',
|
|
700
|
+
'',
|
|
585
701
|
'### Updating Soleri',
|
|
586
702
|
'',
|
|
587
703
|
'| What to update | Command |',
|
|
@@ -612,28 +728,28 @@ const ENGINE_RULES_LINES = [
|
|
|
612
728
|
'',
|
|
613
729
|
'### How Your CLAUDE.md is Built',
|
|
614
730
|
'',
|
|
615
|
-
'Your CLAUDE.md is **auto-generated** — never edit it manually
|
|
616
|
-
'',
|
|
617
|
-
'| Trigger | How |',
|
|
618
|
-
'|---------|-----|',
|
|
619
|
-
'| `soleri dev` | Hot-reloads and regenerates on file changes |',
|
|
620
|
-
'| `soleri agent refresh` | Explicitly regenerates from latest templates |',
|
|
621
|
-
'| `soleri agent update` | After engine update, regenerates to pick up new rules |',
|
|
622
|
-
'| Scaffold (`create-soleri`) | Generates initial CLAUDE.md for new agents |',
|
|
731
|
+
'Your CLAUDE.md is **auto-generated** — never edit it manually (except inside `<!-- user:custom -->` markers). Regenerated by `soleri dev`, `soleri agent refresh`, `soleri agent update`, and on scaffold.',
|
|
623
732
|
'',
|
|
624
733
|
'The composition pipeline assembles CLAUDE.md from:',
|
|
625
734
|
'',
|
|
626
735
|
'1. **Agent identity** — from `agent.yaml`',
|
|
627
736
|
'2. **Custom instructions** — from `instructions/user.md` (priority placement, before engine rules)',
|
|
628
|
-
'3. **Engine rules** —
|
|
737
|
+
'3. **Engine rules** — modular, controlled by `engine.features` in `agent.yaml`',
|
|
629
738
|
'4. **User instructions** — from `instructions/*.md` (alphabetically sorted, excluding `user.md` and `_engine.md`)',
|
|
630
739
|
'5. **Tools table** — from engine registration',
|
|
631
740
|
'6. **Workflow index** — from `workflows/`',
|
|
632
741
|
'7. **Skills index** — from `skills/`',
|
|
633
742
|
'',
|
|
634
|
-
'`
|
|
743
|
+
'**Modular engine rules:** The `engine.features` array in `agent.yaml` controls which rule modules are included. Available: `vault`, `planning`, `brain`, `advanced`. Core rules are always included. Default (no features specified) = all modules.',
|
|
635
744
|
'',
|
|
636
|
-
'
|
|
745
|
+
'### What Survives Regeneration',
|
|
746
|
+
'',
|
|
747
|
+
'| Source | Survives? |',
|
|
748
|
+
'|--------|-----------|',
|
|
749
|
+
'| `instructions/*.md` | Yes — re-read on every regen |',
|
|
750
|
+
'| `<!-- user:custom -->` zone in CLAUDE.md | Yes — extracted and re-injected |',
|
|
751
|
+
'| `agent.yaml` | Drives regen (source of truth) |',
|
|
752
|
+
'| Manual CLAUDE.md edits outside markers | No — overwritten, warning logged |',
|
|
637
753
|
'',
|
|
638
754
|
'### System Requirements',
|
|
639
755
|
'',
|
|
@@ -659,6 +775,14 @@ const ENGINE_RULES_LINES = [
|
|
|
659
775
|
'| `soleri dev` | Run agent in development mode (stdio MCP) |',
|
|
660
776
|
'| `soleri test` | Run agent tests (`--watch`, `--coverage`) |',
|
|
661
777
|
'',
|
|
778
|
+
'### Vault',
|
|
779
|
+
'',
|
|
780
|
+
'| Command | What it does |',
|
|
781
|
+
'|---------|-------------|',
|
|
782
|
+
'| `soleri vault export` | Export vault entries as browsable markdown files |',
|
|
783
|
+
'| `soleri vault export --path <dir>` | Export to custom directory (e.g., Obsidian vault) |',
|
|
784
|
+
'| `soleri vault export --domain <name>` | Export entries from a specific domain |',
|
|
785
|
+
'',
|
|
662
786
|
'### Knowledge & Packs',
|
|
663
787
|
'',
|
|
664
788
|
'| Command | What it does |',
|
|
@@ -793,6 +917,63 @@ const ENGINE_RULES_LINES = [
|
|
|
793
917
|
'- Does NOT apply to new code, new files, or greenfield features',
|
|
794
918
|
'- Advisory only — flags warnings, never blocks execution',
|
|
795
919
|
'',
|
|
920
|
+
// ─── Subagent Identity & Behavioral Contract ──────────────
|
|
921
|
+
'## Subagent Identity & Behavioral Contract',
|
|
922
|
+
'<!-- soleri:subagent-identity -->',
|
|
923
|
+
'',
|
|
924
|
+
'When the orchestrator fans out work to subagents, two agent types are available. The orchestrator routes based on task complexity.',
|
|
925
|
+
'',
|
|
926
|
+
'### Agent Types',
|
|
927
|
+
'',
|
|
928
|
+
'| Type | When to use | Capabilities | Overhead |',
|
|
929
|
+
'|------|------------|--------------|----------|',
|
|
930
|
+
'| **Claude Code worker** | Mechanical tasks: single-file edits, test fixes, config changes, clear specs | File read/write/edit, git, shell, tests | Low — fast, stateless |',
|
|
931
|
+
'| **Soleri agent instance** | Complex tasks: design decisions, multi-file with cross-cutting concerns, new dependencies | Full agent lifecycle: vault, brain, planning, knowledge capture | High — full activation cycle |',
|
|
932
|
+
'',
|
|
933
|
+
'### Routing Table',
|
|
934
|
+
'',
|
|
935
|
+
'| Signal | Route to |',
|
|
936
|
+
'|--------|---------|',
|
|
937
|
+
'| Single file, clear acceptance criteria, spec fully decided | Claude Code worker |',
|
|
938
|
+
'| Approach already described in parent plan | Claude Code worker |',
|
|
939
|
+
'| Touches 3+ files with cross-cutting concerns | Soleri agent instance |',
|
|
940
|
+
'| Unresolved design decisions not in parent plan | Soleri agent instance |',
|
|
941
|
+
'| New dependencies or architectural choices needed | Soleri agent instance |',
|
|
942
|
+
'',
|
|
943
|
+
'### The Rules',
|
|
944
|
+
'',
|
|
945
|
+
'1. **Orchestrator owns all decisions.** Subagents execute specs — they do NOT make design decisions. If a subagent encounters ambiguity, it returns to the orchestrator with a question, not a guess.',
|
|
946
|
+
'2. **Subagents MUST NOT create plans.** Only the parent orchestrator creates plans. Subagents receive task prompts with exact scope, file boundaries, and acceptance criteria. They execute and return results.',
|
|
947
|
+
'3. **Worktree cleanup is guaranteed.** Three-layer defense: (a) `finally` block in dispatcher cleans per-task worktree, (b) `cleanupAll()` runs after batch completion, (c) `SessionStart` hook prunes orphaned worktrees on every session.',
|
|
948
|
+
'4. **Escalation protocol.** When a subagent hits ambiguity or a blocking issue, it MUST return to the orchestrator with a clear description of the blocker. The orchestrator decides — ask the user or resolve — then re-dispatches.',
|
|
949
|
+
'5. **No freelancing.** Subagents stay within their assigned file boundaries and acceptance criteria. No "while I\'m here" improvements, no scope creep, no out-of-scope commits.',
|
|
950
|
+
'6. **UX output contract.** The orchestrator communicates subagent work to the user at three verbosity levels:',
|
|
951
|
+
'',
|
|
952
|
+
'### UX Output Format',
|
|
953
|
+
'',
|
|
954
|
+
'**Minimal (default):**',
|
|
955
|
+
'```',
|
|
956
|
+
'Dispatching N tasks in parallel...',
|
|
957
|
+
'',
|
|
958
|
+
'✓ N/N complete. M patterns captured to vault.',
|
|
959
|
+
' → Decisions: [list any design decisions made]',
|
|
960
|
+
'```',
|
|
961
|
+
'',
|
|
962
|
+
'**Detailed (on request or for complex work):**',
|
|
963
|
+
'```',
|
|
964
|
+
'| # | Task | Agent | Status | Knowledge |',
|
|
965
|
+
'|---|------|-------|--------|-----------|',
|
|
966
|
+
'| 1 | Description | Worker/Instance | Done ✓ | — |',
|
|
967
|
+
'```',
|
|
968
|
+
'',
|
|
969
|
+
'**Verbose (debugging):** Full lifecycle state, vault entries, plan IDs.',
|
|
970
|
+
'',
|
|
971
|
+
'### User Overrides',
|
|
972
|
+
'',
|
|
973
|
+
'- "Use full agent for everything" → all subagents are Soleri agent instances',
|
|
974
|
+
'- "Just use workers" → all subagents are Claude Code workers (no lifecycle overhead)',
|
|
975
|
+
'- Default: hybrid routing based on complexity',
|
|
976
|
+
'',
|
|
796
977
|
`<!-- /${ENGINE_MARKER} -->`,
|
|
797
978
|
];
|
|
798
979
|
//# sourceMappingURL=shared-rules.js.map
|