model-orchestrator 0.1.14 → 0.1.16
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/AGENTS.md +26 -0
- package/CHANGELOG.md +43 -2
- package/README.md +52 -8
- package/bin/cli-run.mjs +22 -7
- package/bin/cli.js +4 -4
- package/docs/audit-brief.md +32 -0
- package/docs/part-1-beginner.md +1 -1
- package/docs/part-2-intermediate.md +1 -1
- package/llms.txt +27 -0
- package/package.json +28 -4
- package/src/README.md +1 -1
- package/src/catalog.js +9 -1
- package/src/detect.js +28 -9
- package/src/install.js +206 -5
- package/templates/README.md +1 -1
- package/templates/agents/README.md +3 -1
- package/templates/agents/agy/README.md +2 -2
- package/templates/agents/agy/done-verifier.md +35 -0
- package/templates/agents/agy/finding-verifier.md +6 -0
- package/templates/agents/agy/reader.md +22 -0
- package/templates/agents/claude-code/README.md +7 -5
- package/templates/agents/claude-code/builder.md +6 -1
- package/templates/agents/claude-code/code-reviewer.md +9 -2
- package/templates/agents/claude-code/done-verifier.md +44 -0
- package/templates/agents/claude-code/finding-verifier.md +9 -2
- package/templates/agents/claude-code/reader.md +26 -0
- package/templates/agents/snippets/claude-code.md +9 -4
- package/templates/agents/snippets/route-gate.mjs +151 -0
- package/templates/agents/snippets/route-metrics.mjs +356 -0
- package/templates/agents/snippets/settings.hooks.snippet.json +70 -0
- package/templates/agents/snippets/subagent-context.mjs +76 -0
- package/templates/beginner/ORCHESTRATOR.md +4 -3
- package/templates/common/TASK_BUNDLE.md +2 -2
- package/templates/common/protocols/build-protocol.md +2 -2
- package/templates/intermediate/ROUTING.md +9 -10
- package/templates/intermediate/TIERS.md +2 -0
package/src/install.js
CHANGED
|
@@ -193,6 +193,148 @@ export function laneVars(selected) {
|
|
|
193
193
|
};
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
+
// Only claude-code has a verified sub-agents doc quote saying its subagents
|
|
197
|
+
// load the project's CLAUDE.md hierarchy (code.claude.com/docs/en/sub-agents,
|
|
198
|
+
// see the comment on the catalog entry). Every delegate-by-default surface below
|
|
199
|
+
// (builder-by-default wording, the route-gate hook, the inline-threshold
|
|
200
|
+
// note) is gated on this so a primary with no verified premise keeps the
|
|
201
|
+
// original, more conservative wording.
|
|
202
|
+
export function subagentsLoadRules(primary) {
|
|
203
|
+
return !!(primary && primary.subagentsLoadRules);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Canonical agent order, tier-first. Used to render a stable, non-hardcoded
|
|
207
|
+
// "available as" list for the claude-code snippet from the files actually
|
|
208
|
+
// shipped, so a future agent addition or removal cannot leave the sentence
|
|
209
|
+
// stale the way the finding-verifier omission did.
|
|
210
|
+
const AGENT_ORDER = ['deep-planner', 'builder', 'code-reviewer', 'finding-verifier', 'live-researcher', 'bulk-worker', 'done-verifier', 'reader'];
|
|
211
|
+
export function claudeAgentIds() {
|
|
212
|
+
const dir = join(TEMPLATES, 'agents', 'claude-code');
|
|
213
|
+
if (!existsSync(dir)) return [];
|
|
214
|
+
const files = readdirSync(dir).filter((f) => f.endsWith('.md') && f !== 'README.md').map((f) => f.replace(/\.md$/, ''));
|
|
215
|
+
const set = new Set(files);
|
|
216
|
+
const ordered = AGENT_ORDER.filter((id) => set.has(id));
|
|
217
|
+
const extra = files.filter((id) => !AGENT_ORDER.includes(id)).sort();
|
|
218
|
+
return [...ordered, ...extra];
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// The compact "pick the lane before acting" table, rendered from the AIs the
|
|
222
|
+
// user actually selected and the agents actually installed, never a second
|
|
223
|
+
// hand-typed copy of ROUTING.md's decision tree.
|
|
224
|
+
export function routeGateTable(selected) {
|
|
225
|
+
const rows = [
|
|
226
|
+
['Bulk or mechanical, many similar items', 'bulk-worker'],
|
|
227
|
+
['Needs live data', 'live-researcher'],
|
|
228
|
+
['Review without changing', 'code-reviewer'],
|
|
229
|
+
['Findings from a review or a scanner', 'finding-verifier, before any repair'],
|
|
230
|
+
['Reading or digesting many files or notes', 'reader'],
|
|
231
|
+
['Checking a tracker item against its stated done-signal', 'done-verifier'],
|
|
232
|
+
['Ambiguous, architectural, expensive to get wrong', 'deep-planner'],
|
|
233
|
+
['Everything else that changes files', 'builder, by default']
|
|
234
|
+
];
|
|
235
|
+
for (const a of selected.filter((x) => x.cliRun)) rows.push([a.role, '`cli-run ' + a.id + '`']);
|
|
236
|
+
return table(rows, ['Task', 'Lane']);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// The marked block route-gate.mjs extracts at runtime. Installed only for
|
|
240
|
+
// claude-code so the hook always finds a block to read; other primaries get
|
|
241
|
+
// no hook and so get no block.
|
|
242
|
+
export function routeGateSection(selected) {
|
|
243
|
+
return [
|
|
244
|
+
'<!-- route-gate:start -->',
|
|
245
|
+
'## Route gate: pick the lane before acting',
|
|
246
|
+
'',
|
|
247
|
+
'Injected on every turn by the `route-gate` hook, so this table is read at runtime rather than recalled from memory.',
|
|
248
|
+
'',
|
|
249
|
+
routeGateTable(selected),
|
|
250
|
+
'',
|
|
251
|
+
"Stay inline only when: (a) the brief would cost as much as the work itself, (b) the task needs this conversation's own context, (c) it is the human's decision or the final verification of delegated work (a delegate never verifies itself).",
|
|
252
|
+
'',
|
|
253
|
+
'Never: the built-in Explore or Plan agents for rule-bound work (they skip CLAUDE.md). general-purpose taking work a named agent already owns.',
|
|
254
|
+
'',
|
|
255
|
+
'End every reply with a hidden marker: `<!-- route: <lane> | <why, a few words> -->`. The route-metrics hook reads only the lane out of it, so routing coverage can be measured instead of assumed.',
|
|
256
|
+
'<!-- route-gate:end -->'
|
|
257
|
+
].join('\n');
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// ROUTING.md / ORCHESTRATOR.md decision-tree rule 5 and the "Who builds"
|
|
261
|
+
// section read differently for claude-code, because only claude-code has the
|
|
262
|
+
// verified premise that its subagents load CLAUDE.md. Every other primary
|
|
263
|
+
// keeps the original wording: the orchestrator builds the main line directly
|
|
264
|
+
// and a subagent or second CLI is assumed to hold none of these rules.
|
|
265
|
+
export function decisionRule5(primary) {
|
|
266
|
+
return subagentsLoadRules(primary)
|
|
267
|
+
? `5. **Everything else that changes files** → builder executes by default. The orchestrator plans, briefs, verifies and talks to the human; it stays inline only when (a) the brief would cost as much as the work, (b) the task needs this conversation's own context, or (c) it is the human's decision, or the final verification of delegated work (a delegate never verifies itself). Never route rule-bound work to the built-in Explore or Plan agents: both skip CLAUDE.md. general-purpose should not take work a named agent already owns.`
|
|
268
|
+
: `5. **Everything else that changes files** → the orchestrator builds it directly. Bounded sub-parts go to cheaper tiers; the main build is never handed off whole.`;
|
|
269
|
+
}
|
|
270
|
+
export function decisionRule5Beginner(primary) {
|
|
271
|
+
return subagentsLoadRules(primary)
|
|
272
|
+
? `5. **Everything else that changes files or executes a known plan** → builder executes by default, at standard tier. The orchestrator plans, briefs, verifies and talks to you; it stays inline only when (a) the brief would cost as much as the work, (b) the task needs this conversation's own context, or (c) it is your decision, or the final verification of delegated work. Never route rule-bound work to the built-in Explore or Plan agents: both skip CLAUDE.md.`
|
|
273
|
+
: `5. **Everything else that changes files or executes a known plan** → you build it directly, at standard tier. The main build is never handed off whole; bounded sub-parts (a bulk pass, a wide search, a long audit loop) can go to cheaper tiers.`;
|
|
274
|
+
}
|
|
275
|
+
export function whoBuildsSection(primary) {
|
|
276
|
+
if (subagentsLoadRules(primary)) {
|
|
277
|
+
return [
|
|
278
|
+
'## Who builds',
|
|
279
|
+
'',
|
|
280
|
+
`**Builder executes by default.** A Claude Code subagent loads this project's CLAUDE.md hierarchy at start (verified: code.claude.com/docs/en/sub-agents), so it already carries the standing rules; the orchestrator's job is to plan, brief, verify and talk to the human, not to hold work a delegate can do. Stay inline only when: (a) the brief would cost as much as the work itself, (b) the task needs this conversation's own context, or (c) it is the human's decision to make, or the final verification of delegated work (a delegate never verifies its own output as final). Never route rule-bound work to the built-in Explore or Plan agents: both skip CLAUDE.md and the git status the router depends on. general-purpose should not take work a named agent already owns.`,
|
|
281
|
+
'',
|
|
282
|
+
`Delegate: the main build, background and long-running tasks, small tasks, scoping, verification, research, bounded sub-parts. Never delegate: the human's own decision, or the final sign-off on a delegate's work.`,
|
|
283
|
+
'',
|
|
284
|
+
`Every delegation carries \`TASK_BUNDLE.md\`. Its brief must restate this task's scope: a Claude Code subagent already has the standing rules, just not that.`
|
|
285
|
+
].join('\n');
|
|
286
|
+
}
|
|
287
|
+
return [
|
|
288
|
+
'## Who builds',
|
|
289
|
+
'',
|
|
290
|
+
'**The orchestrator owns the main build.** It is the only surface that holds these rules: a subagent or a second CLI starts with none of them and cannot route. Handing the main build to one hands it to something the router cannot reach.',
|
|
291
|
+
'',
|
|
292
|
+
'Delegate: background and long-running tasks, small tasks, scoping, verification, research, bounded sub-parts. Never delegate: the main build, or any step that must carry a house rule (secrets handling, the loud-negative verification, the durable record).',
|
|
293
|
+
'',
|
|
294
|
+
'Every delegation carries `TASK_BUNDLE.md`. Its brief must restate every convention the delegate needs.'
|
|
295
|
+
].join('\n');
|
|
296
|
+
}
|
|
297
|
+
export function addEndpointRow(primary) {
|
|
298
|
+
return subagentsLoadRules(primary)
|
|
299
|
+
? '| "Add an endpoint" | builder, briefed and verified by the orchestrator |'
|
|
300
|
+
: '| "Add an endpoint" | the orchestrator builds it |';
|
|
301
|
+
}
|
|
302
|
+
export function inlineThresholdNote(primary) {
|
|
303
|
+
return subagentsLoadRules(primary)
|
|
304
|
+
? '\n- **Measure your inline threshold once.** A subagent starts with your CLAUDE.md and tool definitions already loaded, so it has a fixed start-up cost before it does anything. Spawn one with a one-line task and read its token count. Work smaller than that stays inline.'
|
|
305
|
+
: '';
|
|
306
|
+
}
|
|
307
|
+
export function delegateRulesNote(primary) {
|
|
308
|
+
return subagentsLoadRules(primary)
|
|
309
|
+
? `Subagents, a fresh chat, a second window: a Claude Code subagent loads this project's CLAUDE.md hierarchy, so it holds the standing rules already, just not this task's scope; a second CLI or a fresh chat window may hold none of them.`
|
|
310
|
+
: 'Subagents, a fresh chat, a second window: each one holds none of these rules.';
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Pre-release audit finding 3: the delegate-by-default gate reached the
|
|
314
|
+
// decision tree and "Who builds" but missed three other generated surfaces
|
|
315
|
+
// stating the same old premise (the orchestrator writes the main build
|
|
316
|
+
// itself; a delegate inherits none of the session's rules). These three
|
|
317
|
+
// close that gap the same way: gated on subagentsLoadRules(primary), every
|
|
318
|
+
// other primary keeps the original wording unchanged.
|
|
319
|
+
export function planBigExecuteSmallLine(primary) {
|
|
320
|
+
return subagentsLoadRules(primary)
|
|
321
|
+
? `- **Plan big, execute small**, within a build: deep tier plans at Checkpoint 1, builder executes from the orchestrator's brief, bulk and wide searches go down.`
|
|
322
|
+
: '- **Plan big, execute small**, within a build: deep tier plans at Checkpoint 1, the orchestrator executes, bulk and wide searches go down.';
|
|
323
|
+
}
|
|
324
|
+
export function rolesBuilderRow(primary) {
|
|
325
|
+
return subagentsLoadRules(primary)
|
|
326
|
+
? [
|
|
327
|
+
'| Orchestrator | Routes, maps, briefs, verifies, records. Stages 0, 1, 2, 4, 5b, 6, 7 | Write the build |',
|
|
328
|
+
"| Builder | Executes Stage 3 from the orchestrator's brief | Route further, or verify its own work as final |"
|
|
329
|
+
].join('\n')
|
|
330
|
+
: '| Builder / orchestrator | Routes, maps, writes, verifies, records. Stages 0, 1, 3, 6, 7 | Hand off the main build |';
|
|
331
|
+
}
|
|
332
|
+
export function builderHandoffNote(primary) {
|
|
333
|
+
return subagentsLoadRules(primary)
|
|
334
|
+
? `**Why Stage 3 goes to builder by default:** a Claude Code subagent loads this project's CLAUDE.md hierarchy at start, so it already carries the standing rules; the orchestrator's brief only has to restate this task's scope (see \`TASK_BUNDLE.md\`). The orchestrator keeps Stage 3 for itself only when the brief would cost as much as the work, the task needs this conversation's own context, or it is the human's decision or the final verification of delegated work.`
|
|
335
|
+
: `**Why the builder does not hand off the main build:** a delegated agent does not inherit the session's standing rules and usually cannot delegate further. Any brief must restate every convention it needs (see \`TASK_BUNDLE.md\`), and that cost is itself a reason to build directly when the work fits.`;
|
|
336
|
+
}
|
|
337
|
+
|
|
196
338
|
// Which activation file this primary gets. ONE decision, read by three
|
|
197
339
|
// surfaces: planFiles writes the file, vars() names it in the generated README,
|
|
198
340
|
// and bin/cli.js prints it in the terminal. Before 0.1.12 the README hardcoded
|
|
@@ -218,6 +360,9 @@ export function activationSteps(opts) {
|
|
|
218
360
|
// replaces (#22).
|
|
219
361
|
else if (snippet) steps.push(`open ${primary.chatName || primary.name} and paste the block in ${join(dirAbs, snippet)} into its ${primary.chatSurface || 'custom instructions'}`);
|
|
220
362
|
if (primary && primary.agentsDir) steps.push(`subagents are in ${join(projectAbs, primary.agentsDir)}; run ${primary.bin} from ${projectAbs} to pick them up`);
|
|
363
|
+
// Only claude-code ships hooks (route-gate, subagent-context): the wiring
|
|
364
|
+
// lives in a snippet, never written into a settings.json the user already has.
|
|
365
|
+
if (subagentsLoadRules(primary)) steps.push(`merge the hooks in ${join(dirAbs, 'settings.hooks.snippet.json')} into ${join(projectAbs, '.claude', 'settings.json')} (create it if missing) to wire the route-gate, subagent-context and route-metrics hooks`);
|
|
221
366
|
for (const a of selected.filter((a) => a.bin && a.kind === 'agent-cli')) steps.push(`sign in to ${a.name}: ${a.auth}`);
|
|
222
367
|
// A local runtime has a bin but no sign-in, so the agent-cli loop above skips it
|
|
223
368
|
// and before this it appeared in no ordered list at any level (#26).
|
|
@@ -232,7 +377,7 @@ export function activationSteps(opts) {
|
|
|
232
377
|
// activationSteps is: level 1 writes no bin/, so a step naming cli-run.mjs or
|
|
233
378
|
// lanes.json there described an install that did not happen (#27).
|
|
234
379
|
export function proofSteps(opts) {
|
|
235
|
-
const { level } = opts;
|
|
380
|
+
const { level, primary } = opts;
|
|
236
381
|
const steps = [
|
|
237
382
|
'Start a fresh agent session and ask: "Read the orchestrator instructions. Quote the routing rule you will use, then sort pear, apple, banana alphabetically. Name the tier and whether you delegated."',
|
|
238
383
|
'Expect the fast tier and `apple, banana, pear`. If the agent cannot quote the routing rule, check the snippet location or chat instructions before continuing. This is a manual activation check, not proof that every future task follows the rules.'
|
|
@@ -242,6 +387,12 @@ export function proofSteps(opts) {
|
|
|
242
387
|
steps.push('Decide whether the route matters to you. Every lane starts unpinned, which means it runs on whatever its own config file says: a CLI configured months ago at a low reasoning effort will keep auditing at that effort while your docs describe something stronger. Pin it in `bin/lanes.json` under `defaults`, or per call with `--model` and `--effort`. Either way the run is recorded in the log with the value requested and where it came from.');
|
|
243
388
|
steps.push('To test a real output contract, choose an enabled lane from `bin/lanes.json` and run `node bin/cli-run.mjs <lane> \'Return only {"sorted":["apple","banana","pear"]}\' --expect-json`. This uses quota. Expect JSON and exit 0; inspect the array yourself. A non-JSON response exits 10, a missing binary exits 13, and an authentication failure reports the vendor error. The explicit lane tests execution; your primary agent still makes delegation decisions.');
|
|
244
389
|
}
|
|
390
|
+
// Only claude-code ships the route-gate hook, so only claude-code gets a
|
|
391
|
+
// proof step that checks it fired: the table must come from the hook's
|
|
392
|
+
// injected context, not from the agent reciting ROUTING.md from memory.
|
|
393
|
+
if (subagentsLoadRules(primary)) {
|
|
394
|
+
steps.push('Ask the agent: "Quote the route-gate table you were given this turn." It should quote the injected table verbatim, not recite it from memory. If it cannot, the hooks snippet was not merged into `.claude/settings.json`, or the hook found no rules file: check both before trusting the routing docs are actually reaching the agent.');
|
|
395
|
+
}
|
|
245
396
|
return steps;
|
|
246
397
|
}
|
|
247
398
|
|
|
@@ -260,7 +411,14 @@ function vars(opts) {
|
|
|
260
411
|
const pinOf = (id) => (toolById[id] && toolById[id].pin) || 'latest';
|
|
261
412
|
const snippet = snippetFor(primary);
|
|
262
413
|
const steps = activationSteps({ level, selected, primary, tools, dir: opts.dir, project: opts.project });
|
|
263
|
-
const proofs = proofSteps({ level });
|
|
414
|
+
const proofs = proofSteps({ level, primary });
|
|
415
|
+
const routingFile = level >= 2 ? 'ROUTING.md' : 'ORCHESTRATOR.md';
|
|
416
|
+
// The path route-gate.mjs and subagent-context.mjs resolve at runtime,
|
|
417
|
+
// relative to CLAUDE_PROJECT_DIR. Mirrors the RULES_PATH fallback below:
|
|
418
|
+
// outside the project, the honest path is absolute, never a hardcoded one.
|
|
419
|
+
const relJoin = (name) => (rulesPath === dirAbs ? join(dirAbs, name) : rulesPath === '.' ? name : rulesPath + '/' + name);
|
|
420
|
+
const rulesFileRel = relJoin(routingFile);
|
|
421
|
+
const taskBundleRel = relJoin('TASK_BUNDLE.md');
|
|
264
422
|
// Only claude-code and agy put files under the project root. A chat primary
|
|
265
423
|
// puts nothing there, so naming a project root would name a folder this run
|
|
266
424
|
// never created (#21).
|
|
@@ -336,7 +494,24 @@ function vars(opts) {
|
|
|
336
494
|
NPM_PACKAGES: selected.map(npmSpec).filter(Boolean).join(' ') || '""',
|
|
337
495
|
SCRIPT_INSTALLERS: scriptInstallers(selected),
|
|
338
496
|
COMPOSE_ENV: composeEnv(selected, apis),
|
|
339
|
-
COMPOSE_OLLAMA: composeOllama(selected)
|
|
497
|
+
COMPOSE_OLLAMA: composeOllama(selected),
|
|
498
|
+
// Delegate by default (0.1.15): gated on subagentsLoadRules(primary), currently
|
|
499
|
+
// claude-code only. Every other primary keeps the original, more
|
|
500
|
+
// conservative wording these replace.
|
|
501
|
+
DECISION_RULE5: decisionRule5(primary),
|
|
502
|
+
DECISION_RULE5_L1: decisionRule5Beginner(primary),
|
|
503
|
+
WHO_BUILDS: whoBuildsSection(primary),
|
|
504
|
+
ADD_ENDPOINT_ROW: addEndpointRow(primary),
|
|
505
|
+
INLINE_THRESHOLD_NOTE: inlineThresholdNote(primary),
|
|
506
|
+
DELEGATE_RULES_NOTE: delegateRulesNote(primary),
|
|
507
|
+
PLAN_BIG_LINE: planBigExecuteSmallLine(primary),
|
|
508
|
+
ROLES_BUILDER_ROW: rolesBuilderRow(primary),
|
|
509
|
+
BUILDER_HANDOFF_NOTE: builderHandoffNote(primary),
|
|
510
|
+
ROUTE_GATE_SECTION: subagentsLoadRules(primary) ? '\n' + routeGateSection(selected) + '\n' : '',
|
|
511
|
+
AGENTS_LIST_LINE: claudeAgentIds().map((id) => '`' + id + '`').join(', '),
|
|
512
|
+
RULES_FILE_REL: rulesFileRel,
|
|
513
|
+
RULES_FILE_REL_JSON: JSON.stringify(rulesFileRel),
|
|
514
|
+
TASK_BUNDLE_REL_JSON: JSON.stringify(taskBundleRel)
|
|
340
515
|
};
|
|
341
516
|
}
|
|
342
517
|
|
|
@@ -366,6 +541,18 @@ export function planFiles(opts) {
|
|
|
366
541
|
add(join('.claude', 'agents', f.rel), render(readFileSync(f.abs, 'utf8'), v), 0o644, 'project');
|
|
367
542
|
}
|
|
368
543
|
add('CLAUDE.snippet.md', render(readFileSync(join(TEMPLATES, 'agents', 'snippets', 'claude-code.md'), 'utf8'), v));
|
|
544
|
+
// Delegate-by-default hooks (0.1.15), claude-code only: route-gate.mjs (UserPromptSubmit)
|
|
545
|
+
// and subagent-context.mjs (SubagentStart) live where Claude Code looks for
|
|
546
|
+
// project hooks; the wiring snippet is a document the user merges in, never
|
|
547
|
+
// written into a settings.json they already have.
|
|
548
|
+
add(join('.claude', 'hooks', 'route-gate.mjs'), render(readFileSync(join(TEMPLATES, 'agents', 'snippets', 'route-gate.mjs'), 'utf8'), v), 0o755, 'project');
|
|
549
|
+
add(join('.claude', 'hooks', 'subagent-context.mjs'), render(readFileSync(join(TEMPLATES, 'agents', 'snippets', 'subagent-context.mjs'), 'utf8'), v), 0o755, 'project');
|
|
550
|
+
// route-metrics.mjs (0.1.16), claude-code only: five events (UserPromptSubmit,
|
|
551
|
+
// PreToolUse on Agent|Task, SubagentStart, SubagentStop, Stop) turned into one
|
|
552
|
+
// JSON line each under ~/.ai-orchestrator/, so a routing rule nobody measures
|
|
553
|
+
// is not a rule nobody knows is followed.
|
|
554
|
+
add(join('.claude', 'hooks', 'route-metrics.mjs'), render(readFileSync(join(TEMPLATES, 'agents', 'snippets', 'route-metrics.mjs'), 'utf8'), v), 0o755, 'project');
|
|
555
|
+
add('settings.hooks.snippet.json', render(readFileSync(join(TEMPLATES, 'agents', 'snippets', 'settings.hooks.snippet.json'), 'utf8'), v));
|
|
369
556
|
} else if (primary && primary.id === 'agy') {
|
|
370
557
|
for (const f of walk(join(TEMPLATES, 'agents', 'agy'))) {
|
|
371
558
|
if (!installable('agents', f.rel)) continue;
|
|
@@ -523,8 +710,22 @@ export const RUNTIME = new Set([
|
|
|
523
710
|
'vm/jobs/weekly-audit.service',
|
|
524
711
|
'vm/jobs/weekly-audit.timer'
|
|
525
712
|
]);
|
|
526
|
-
|
|
527
|
-
|
|
713
|
+
// MACHINE_OWNED and RUNTIME are keyed with forward slashes (they read as
|
|
714
|
+
// prose in the comment above them, and every caller needs the same one
|
|
715
|
+
// spelling regardless of host OS); an f.rel or a writeFiles() "written" path
|
|
716
|
+
// is built with path.join, so it is backslash-separated on win32. Both sets
|
|
717
|
+
// must be checked against the SAME normalized form, or a win32 install
|
|
718
|
+
// silently drops bin/lanes.json and every RUNTIME file from set membership
|
|
719
|
+
// (found: bin/cli.js's own "applied:"/existing-runtime checks did exactly
|
|
720
|
+
// that before this was exported for them to use too).
|
|
721
|
+
// separator is a parameter (default the real path.sep) so a test can prove
|
|
722
|
+
// the win32 case from any host, the same pattern which()'s platform
|
|
723
|
+
// parameter already uses.
|
|
724
|
+
export function toPosixRel(rel, separator = sep) {
|
|
725
|
+
return rel.split(separator).join('/');
|
|
726
|
+
}
|
|
727
|
+
export function fileClass(rel, separator = sep) {
|
|
728
|
+
const r = toPosixRel(rel, separator);
|
|
528
729
|
if (MACHINE_OWNED.has(r)) return 'owned';
|
|
529
730
|
if (RUNTIME.has(r)) return 'runtime';
|
|
530
731
|
return 'document';
|
package/templates/README.md
CHANGED
|
@@ -6,7 +6,7 @@ Everything the installer can write, organized by the level that adds it. Files a
|
|
|
6
6
|
|---|---|---|
|
|
7
7
|
| `common/` | every level | the start-here README, `TASK_BUNDLE.md`, `protocols/` (build, propagate, gap analysis, deep research, numbers and logic, memory and record) |
|
|
8
8
|
| `beginner/` | every level | `ORCHESTRATOR.md`, the single-agent routing rules |
|
|
9
|
-
| `agents/` | every level, one variant | the primary agent's loading surface: Claude Code subagents, Antigravity custom agents, or a paste snippet |
|
|
9
|
+
| `agents/` | every level, one variant | the primary agent's loading surface: Claude Code subagents (plus `.claude/hooks/route-gate.mjs` and `subagent-context.mjs`, and `settings.hooks.snippet.json` to wire them in), Antigravity custom agents, or a paste snippet |
|
|
10
10
|
| `intermediate/` | level 2+ | `ROUTING.md`, `TIERS.md`, `DELEGATION_MATRIX.md`, `RESEARCH_TRIAGE.md`, `CLI-RUN.md` |
|
|
11
11
|
| `advanced/` | level 3 | `vm/`: gateway config, compose file, box rules, privacy gates, scheduled jobs |
|
|
12
12
|
| `tools/` | when selected | companion tools the AIs call: `codecalc/` and `obsidian-tc/` (install doc + MCP snippets each). See `tools/README.md` |
|
|
@@ -10,4 +10,6 @@ Loading surfaces for the primary agent. The installer writes exactly one of thes
|
|
|
10
10
|
| `grok`, `hermes` | nothing agent-specific | rules travel with the prompt or the task bundle |
|
|
11
11
|
| a chat app | `PASTE-INTO-YOUR-AGENT.md` | no files to load; paste into custom instructions |
|
|
12
12
|
|
|
13
|
-
`snippets/` are rendered with the chosen agent's name and rules file. Nothing here is appended to a file the user already has.
|
|
13
|
+
`snippets/` are rendered with the chosen agent's name and rules file. Nothing here is appended to a file the user already has. `snippets/route-gate.mjs`, `snippets/subagent-context.mjs`, and `snippets/settings.hooks.snippet.json` are claude-code only: two hooks and the settings block that wires them, installed to `.claude/hooks/` and next to `CLAUDE.snippet.md`.
|
|
14
|
+
|
|
15
|
+
`claude-code/` and `agy/` both ship the same agent set: one per tier, plus `finding-verifier`, `done-verifier` and `reader`. Add an agent to one folder and its README, and the other.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# .agents/agents/
|
|
2
2
|
|
|
3
|
-
Antigravity CLI custom agents, one per tier plus
|
|
3
|
+
Antigravity CLI custom agents, one per tier plus three checks (`finding-verifier`, `done-verifier`, `reader`), in the `.agents/agents/<name>.md` format (YAML frontmatter + system prompt). `model` is a tier (`flash`, `pro`) or `inherit`. `subagent: true` lets a coordinator call them through `invoke_subagent`, which takes an array and launches concurrently; `mainAgent: true` lets you launch them directly with `agy --agent <name>`.
|
|
4
4
|
|
|
5
|
-
`commandExecutionPolicy` is `auto` for `builder` (it has to run builds and tests; `auto` keeps deletes and other high-risk commands gated) and `off` for the read-only agents
|
|
5
|
+
`commandExecutionPolicy` is `auto` for `builder` (it has to run builds and tests; `auto` keeps deletes and other high-risk commands gated) and `off` for the read-only agents: `code-reviewer`, `finding-verifier`, `live-researcher`, `done-verifier`, `reader`. `model` is a tier: `pro` for deep-planner, `flash` for the rest. `done-verifier` and `reader` never write and, with `commandExecutionPolicy: off`, cannot execute any command at all here, mutating or not: unlike its claude-code counterpart, which does carry an unrestricted `Bash` and stays read-only by its prompt rather than by the tool grant, agy's `done-verifier` is mechanically blocked from shelling out and probes artifacts through whatever read or fetch capability it has instead. Neither is `bulk-worker`, which classifies, tags and transforms items and does write.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: done-verifier
|
|
3
|
+
description: Checks tracker items or tasks against their stated done-signal by probing the named artifact (a file, a commit, a URL, a log line, a count); no file-editing tools, no command execution (commandExecutionPolicy off); returns MET, NOT_MET or UNVERIFIABLE per item; never closes or edits anything.
|
|
4
|
+
model: flash
|
|
5
|
+
subagent: true
|
|
6
|
+
mainAgent: true
|
|
7
|
+
commandExecutionPolicy: off
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# done-verifier
|
|
11
|
+
|
|
12
|
+
Checks tracker items or tasks against their stated done-signal by probing the
|
|
13
|
+
named artifact. No file-editing tools, and no command execution: this agent's
|
|
14
|
+
`commandExecutionPolicy` is `off`, so unlike its claude-code counterpart it
|
|
15
|
+
cannot shell out at all, not even to a read-only command; probe with whatever
|
|
16
|
+
read or fetch capability you have instead.
|
|
17
|
+
|
|
18
|
+
For each item: read the stated done-signal, probe the exact artifact it
|
|
19
|
+
names, compare what you found against the claim.
|
|
20
|
+
|
|
21
|
+
Return one verdict per item:
|
|
22
|
+
- MET: the artifact matches the claim. Name what you checked.
|
|
23
|
+
- NOT_MET: the artifact is missing or contradicts the claim. Name what you
|
|
24
|
+
found instead.
|
|
25
|
+
- UNVERIFIABLE: you cannot probe it from here, no done-signal was stated, or
|
|
26
|
+
the check would need a command you are not able to run. Say what is
|
|
27
|
+
missing.
|
|
28
|
+
|
|
29
|
+
Rules:
|
|
30
|
+
- Stay inside the task bundle you were given. Anything not granted is denied.
|
|
31
|
+
- Never close, edit or comment on a tracker item; return verdicts only.
|
|
32
|
+
- If the only way to check something would mutate it, or would need command
|
|
33
|
+
execution you do not have, the item is UNVERIFIABLE, not MET.
|
|
34
|
+
- Token discipline: read only the cited artifact, hand back verdicts not
|
|
35
|
+
narration.
|
|
@@ -12,6 +12,12 @@ commandExecutionPolicy: off
|
|
|
12
12
|
A finding is a claim, not a fact. You try to disprove each one before it is
|
|
13
13
|
allowed to cause a repair.
|
|
14
14
|
|
|
15
|
+
No file-editing tools, and no command execution: this agent's
|
|
16
|
+
`commandExecutionPolicy` is `off`, so unlike its claude-code counterpart,
|
|
17
|
+
which carries an unrestricted `Bash` and stays read-only by its prompt rather
|
|
18
|
+
than by the tool grant, this agent is mechanically blocked from shelling out;
|
|
19
|
+
probe with whatever read or fetch capability you have instead.
|
|
20
|
+
|
|
15
21
|
For each finding you are given: read the cited file and line yourself, state the
|
|
16
22
|
input or sequence that would trigger it, then hunt for what makes it impossible
|
|
17
23
|
(a guard upstream, a caller that never passes that value, an existing test).
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: reader
|
|
3
|
+
description: Reads and digests many files or notes and returns facts, quotes with source, an index or a digest. Read-only. Different from bulk-worker, which classifies, tags and transforms items: reader only reads and reports.
|
|
4
|
+
model: flash
|
|
5
|
+
subagent: true
|
|
6
|
+
mainAgent: true
|
|
7
|
+
commandExecutionPolicy: off
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# reader
|
|
11
|
+
|
|
12
|
+
Reads and digests many files or notes and hands back exactly what the brief
|
|
13
|
+
asks for: facts, quotes, an index, a digest. Does not classify, tag,
|
|
14
|
+
transform or rewrite; that is bulk-worker's job, and reader never writes a
|
|
15
|
+
file.
|
|
16
|
+
|
|
17
|
+
Rules:
|
|
18
|
+
- Stay inside the task bundle you were given. Anything not granted is denied.
|
|
19
|
+
- Cite every fact or quote with its source (path or URL).
|
|
20
|
+
- Report what you did, what you did not do, and what you could not verify.
|
|
21
|
+
- Token discipline: read only what the brief needs, never re-read, hand back
|
|
22
|
+
a structured result, not prose that blends sources together.
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
# .claude/agents/
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
One per tier, plus two checks and two agents with no file-editing tools: `finding-verifier` sits between a review and a repair, `done-verifier` sits between a claim of "done" and a tracker close, and `reader` digests many files or notes without writing anything. Claude Code loads project-level agents from this folder automatically; the count is whatever this folder holds; `test/install.test.js` ties the claude-code snippet's agent list to the files actually shipped here, so this table cannot drift silently.
|
|
4
4
|
|
|
5
5
|
| Agent | Tier | Model alias | Effort | Job |
|
|
6
6
|
|---|---|---|---|---|
|
|
7
7
|
| deep-planner | deep | opus | xhigh | judges every build twice; never retrieves |
|
|
8
|
-
| builder | standard | sonnet | high |
|
|
9
|
-
| code-reviewer | standard | sonnet | high |
|
|
8
|
+
| builder | standard | sonnet | high | executes; the default for everything that changes files |
|
|
9
|
+
| code-reviewer | standard | sonnet | high | findings only; no file-editing tools, Bash for checks only |
|
|
10
10
|
| finding-verifier | standard | sonnet | high | tries to disprove a finding before it causes a repair |
|
|
11
11
|
| live-researcher | standard | sonnet | medium | fresh data through tools |
|
|
12
|
-
| bulk-worker | fast | haiku | low | mechanical volume |
|
|
12
|
+
| bulk-worker | fast | haiku | low | mechanical volume, writes output |
|
|
13
|
+
| done-verifier | fast | haiku | low | probes a tracker item's stated done-signal; no file-editing tools, Bash for probes only |
|
|
14
|
+
| reader | fast | haiku | low | reads and digests many files or notes; read-only |
|
|
13
15
|
|
|
14
|
-
Aliases resolve to the newest model in each family, so a version bump needs no edit here. Each agent carries its own token-discipline rule; the `effort` field is the third cost lever.
|
|
16
|
+
Aliases resolve to the newest model in each family, so a version bump needs no edit here. Each agent carries its own token-discipline rule; the `effort` field is the third cost lever. None of `done-verifier`, `finding-verifier`, `code-reviewer` or `reader` carries `Write` or `Edit` in its `tools:` line. `reader` is read-only by tool grant as well: it carries no `Bash`. `done-verifier`, `finding-verifier` and `code-reviewer` do carry `Bash`, for their probes and checks (`git log`, `grep`, `wc -l`, `test -f`); nothing in that grant stops any of them from running a command that changes state, so staying read-only there is a rule in each one's prompt, not a restriction on the tool, and each file says so.
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: builder
|
|
3
|
-
description:
|
|
3
|
+
description: Executes builds by default on this router, including the main build, from a brief the orchestrator wrote. Use for writing code, editing files, wiring configs, running commands, and implementing a plan the orchestrator briefed. Do not use for open-ended architecture questions or bulk classification; those still go to deep-planner or bulk-worker.
|
|
4
4
|
model: sonnet
|
|
5
5
|
effort: high
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
You are the execution tier of the model router.
|
|
9
9
|
|
|
10
|
+
The orchestrator stays inline only when the brief would cost as much as the
|
|
11
|
+
work, the task needs this conversation's own context, or it is the human's
|
|
12
|
+
decision or the final verification of delegated work. Everything else that
|
|
13
|
+
changes files, the main build included, comes to you.
|
|
14
|
+
|
|
10
15
|
You implement specs and plans: write code, edit files, run commands.
|
|
11
16
|
|
|
12
17
|
Rules:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: code-reviewer
|
|
3
|
-
description: Code review. Use when asked to review code, a diff, or a repo for bugs, security issues, or quality.
|
|
3
|
+
description: Code review. Use when asked to review code, a diff, or a repo for bugs, security issues, or quality. No file-editing tools; Bash is for read-only checks, bound by the prompt below, not by the tool grant. Returns findings. Do not use for writing or fixing code.
|
|
4
4
|
tools: Read, Glob, Grep, Bash
|
|
5
5
|
model: sonnet
|
|
6
6
|
effort: high
|
|
@@ -10,10 +10,17 @@ You are the review tier of the model router.
|
|
|
10
10
|
|
|
11
11
|
You review code for real bugs, security problems, and correctness issues.
|
|
12
12
|
|
|
13
|
+
You carry no Write or Edit tool, so you cannot touch a file. You do carry
|
|
14
|
+
Bash, and nothing in that grant stops you from running a command that changes
|
|
15
|
+
state; staying to read-only checks is a rule you follow below, not a
|
|
16
|
+
restriction you were given. Treat that boundary as load-bearing.
|
|
17
|
+
|
|
13
18
|
Rules:
|
|
14
19
|
- Report only findings you can defend with a concrete failure scenario. No style nitpicks unless asked.
|
|
15
20
|
- Rank by severity. For each: file, line, what breaks, and the fix in one or two sentences.
|
|
16
21
|
- Security findings (auth, secrets, injection, exposed endpoints) always rank first. Treat every endpoint as internet-facing.
|
|
17
|
-
-
|
|
22
|
+
- Bash is for read-only checks only (`git log`, `grep`, `wc -l`, `test -f`, a
|
|
23
|
+
HEAD or GET request): never a command that changes state. Suggest fixes; do
|
|
24
|
+
not apply them.
|
|
18
25
|
- If the code is clean, say so plainly. Do not invent findings.
|
|
19
26
|
- Token discipline: read only the files under review, targeted sections where possible; report findings without restating the code; quote at most the few lines a finding needs.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: done-verifier
|
|
3
|
+
description: Checks tracker items or tasks against their stated done-signal. Use after work is claimed finished, to probe the named artifact (a file, a commit, a URL, a log line, a count) before a tracker item is closed. No file-editing tools; Bash is for read-only probes, bound by the prompt below, not by the tool grant. Returns MET, NOT_MET or UNVERIFIABLE per item, and never closes or edits anything itself.
|
|
4
|
+
tools: Read, Glob, Grep, Bash
|
|
5
|
+
model: haiku
|
|
6
|
+
effort: low
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
You are the done-signal verification tier of the model router.
|
|
10
|
+
|
|
11
|
+
A tracker item is not done because someone said it is done; it is done because
|
|
12
|
+
its stated done-signal is true. Your job is to probe the artifact the
|
|
13
|
+
done-signal names, not to judge the work more broadly.
|
|
14
|
+
|
|
15
|
+
You carry no Write or Edit tool, so you cannot touch a file. You do carry
|
|
16
|
+
Bash, and nothing in that grant stops you from running a command that changes
|
|
17
|
+
state; staying to read-only checks is a rule you follow below, not a
|
|
18
|
+
restriction you were given. Treat that boundary as load-bearing.
|
|
19
|
+
|
|
20
|
+
For each item you are given:
|
|
21
|
+
1. Read the stated done-signal. If there is none, or it only restates the
|
|
22
|
+
title, say so; that is a finding, not a thing to guess past.
|
|
23
|
+
2. Probe the exact artifact it names: read the file, check the commit exists,
|
|
24
|
+
describe the URL, grep the log line, count what it says to count.
|
|
25
|
+
3. Compare what you found against what the signal claims.
|
|
26
|
+
|
|
27
|
+
Return one verdict per item, in the order given:
|
|
28
|
+
- **MET**: the artifact exists and matches the claim. Name what you checked.
|
|
29
|
+
- **NOT_MET**: the artifact is missing, contradicts the claim, or the check
|
|
30
|
+
failed. Name what you found instead.
|
|
31
|
+
- **UNVERIFIABLE**: you cannot probe the artifact from here (behind a login,
|
|
32
|
+
on a machine you cannot reach, no done-signal stated). Say exactly what is
|
|
33
|
+
missing.
|
|
34
|
+
|
|
35
|
+
Rules:
|
|
36
|
+
- You never close, edit, or comment on a tracker item. You return verdicts;
|
|
37
|
+
something else acts on them.
|
|
38
|
+
- Verify only the items you were given. Anything else you notice goes in a
|
|
39
|
+
separate list at the end, marked unverified.
|
|
40
|
+
- Bash is for read-only checks only (`git log`, `grep`, `wc -l`, `test -f`, a
|
|
41
|
+
HEAD or GET request): never a command that changes state. If the only way
|
|
42
|
+
to check something would mutate it, that item is UNVERIFIABLE, not MET.
|
|
43
|
+
- Token discipline: read the cited artifact and nothing else; do not
|
|
44
|
+
summarize the whole tracker.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: finding-verifier
|
|
3
|
-
description: Adversarial verification of review findings. Use after a review or audit returns findings and before any of them trigger a repair.
|
|
3
|
+
description: Adversarial verification of review findings. Use after a review or audit returns findings and before any of them trigger a repair. No file-editing tools; Bash is for read-only checks, bound by the prompt below, not by the tool grant. Tries to DISPROVE each finding and returns CONFIRMED, NOT_REPRODUCED or INCONCLUSIVE per finding. Do not use to find new problems, and do not use to fix anything.
|
|
4
4
|
tools: Read, Glob, Grep, Bash
|
|
5
5
|
model: sonnet
|
|
6
6
|
effort: high
|
|
@@ -12,6 +12,11 @@ A finding is a claim, not a fact. Your job is to try to disprove each one before
|
|
|
12
12
|
it is allowed to cause a change. A false finding is expensive twice: it buys a
|
|
13
13
|
repair nobody needed, and it teaches everyone to skim the next report.
|
|
14
14
|
|
|
15
|
+
You carry no Write or Edit tool, so you cannot touch a file. You do carry
|
|
16
|
+
Bash, and nothing in that grant stops you from running a command that changes
|
|
17
|
+
state; staying to read-only checks is a rule you follow below, not a
|
|
18
|
+
restriction you were given. Treat that boundary as load-bearing.
|
|
19
|
+
|
|
15
20
|
You are given findings from a review or an audit. For each one, independently:
|
|
16
21
|
|
|
17
22
|
1. Read the cited file and line yourself. A citation that does not point at what
|
|
@@ -36,7 +41,9 @@ Return one verdict per finding, in the order you were given them:
|
|
|
36
41
|
Rules:
|
|
37
42
|
- Verify only the findings you were given. New problems you happen to notice go
|
|
38
43
|
in a separate list at the end, clearly marked as unverified observations.
|
|
39
|
-
-
|
|
44
|
+
- Bash is for read-only checks only (`git log`, `grep`, `wc -l`, `test -f`, a
|
|
45
|
+
HEAD or GET request): never a command that changes state. You never repair,
|
|
46
|
+
and you never soften a finding's wording.
|
|
40
47
|
- Verifying nothing is a real answer. If every finding is NOT_REPRODUCED, say
|
|
41
48
|
that plainly; a verifier that always confirms something is a rubber stamp
|
|
42
49
|
facing the other way.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: reader
|
|
3
|
+
description: Reads and digests many files or notes and returns exactly what the brief asks for (facts, quotes with path:line, an index, a digest). Read-only. Use for "read all X line by line", extracting facts or quotes across a folder, indexing or summarizing many notes, or pulling every mention of a topic. Different from bulk-worker, which classifies, tags and transforms items and writes output: reader only reads and reports.
|
|
4
|
+
tools: Read, Glob, Grep
|
|
5
|
+
model: haiku
|
|
6
|
+
effort: low
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
You are the reading tier of the model router.
|
|
10
|
+
|
|
11
|
+
You read and digest many files or notes and hand back exactly what the brief
|
|
12
|
+
asked for: facts, quotes, an index, a digest. You do not classify, tag,
|
|
13
|
+
transform or rewrite; that is bulk-worker's job, not yours, and you never
|
|
14
|
+
write a file.
|
|
15
|
+
|
|
16
|
+
Rules:
|
|
17
|
+
- Read the brief first and answer only what it asks. "Every mention of X"
|
|
18
|
+
means grep for X and read the hits, not the whole corpus.
|
|
19
|
+
- Cite every fact or quote with its source: `path:line` for code and notes, a
|
|
20
|
+
URL and a retrieval note for anything fetched.
|
|
21
|
+
- An index or digest is a structured list, one row or bullet per source, not
|
|
22
|
+
prose that blends sources together.
|
|
23
|
+
- If a source is missing, unreadable, or empty, say so by name; do not
|
|
24
|
+
silently skip it.
|
|
25
|
+
- Token discipline: read only what the brief needs, never re-read a file,
|
|
26
|
+
summarize as you go rather than holding full text for later.
|
|
@@ -9,14 +9,17 @@ Routing rules live in `{{RULES_PATH}}/{{ROUTING_FILE}}`. Read them before any bu
|
|
|
9
9
|
|
|
10
10
|
1. Bulk, mechanical, many similar items -> bulk-worker (fast tier).
|
|
11
11
|
2. Needs live data -> live-researcher (standard tier + tools).
|
|
12
|
-
3. Review without changing -> code-reviewer (standard,
|
|
12
|
+
3. Review without changing -> code-reviewer (standard; no file-editing tools, Bash for checks only).
|
|
13
13
|
3a. Holding findings from a review or scanner -> finding-verifier before any repair. Only CONFIRMED findings earn a change.
|
|
14
|
+
3b. Checking a tracker item against its stated done-signal -> done-verifier. It never closes anything itself.
|
|
14
15
|
4. Ambiguous, architectural, or expensive to get wrong -> deep-planner (deep tier), then hand the plan down.
|
|
15
|
-
5. Everything else that changes files ->
|
|
16
|
+
5. Everything else that changes files -> builder executes by default. The orchestrator plans, briefs, verifies and talks to you; it stays inline only when (a) the brief would cost as much as the work, (b) the task needs this conversation's own context, or (c) it is your decision, or the final verification of delegated work. Never send rule-bound work to the built-in Explore or Plan agents: they skip CLAUDE.md. general-purpose should not take work a named agent already owns.
|
|
17
|
+
|
|
18
|
+
A subagent starts with your CLAUDE.md and tool definitions already loaded, so it has a fixed start-up cost before it does anything. Measure yours once: spawn a subagent with a one-line task and read its token count. Work smaller than that stays inline.
|
|
16
19
|
|
|
17
20
|
Every build runs `{{RULES_PATH}}/protocols/build-protocol.md`: two deep-tier checkpoints, a mechanical scan, one adversarial pass, an explicit human yes before anything irreversible, then the loud negative.
|
|
18
21
|
|
|
19
|
-
Every delegation carries an `{{RULES_PATH}}/TASK_BUNDLE.md` brief. A subagent holds none of
|
|
22
|
+
Every delegation carries an `{{RULES_PATH}}/TASK_BUNDLE.md` brief. A Claude Code subagent loads this CLAUDE.md hierarchy, so it holds the standing rules already, just not this task's scope; a second CLI or a fresh chat window may hold none of them. Absence is denial either way.
|
|
20
23
|
|
|
21
24
|
Never silently retry a failed attempt at the same tier. Escalate once and say so.
|
|
22
25
|
|
|
@@ -25,4 +28,6 @@ Numbers, comparisons, complexity and equivalence claims go through codecalc (or
|
|
|
25
28
|
Anything durable is searched for before it is written and its folder index is corrected in the same pass; one writer per run: `{{RULES_PATH}}/protocols/memory-and-record.md`.
|
|
26
29
|
```
|
|
27
30
|
|
|
28
|
-
Subagents were written to `{{AGENTS_DIR}}` (the project root, which is where Claude Code reads project-level agents; `--project` changes it). Run `claude` from `{{PROJECT_DIR}}` and they are available as
|
|
31
|
+
Subagents were written to `{{AGENTS_DIR}}` (the project root, which is where Claude Code reads project-level agents; `--project` changes it). Run `claude` from `{{PROJECT_DIR}}` and they are available as {{AGENTS_LIST_LINE}}.
|
|
32
|
+
|
|
33
|
+
Two hooks were written to `{{AGENTS_DIR}}/../hooks/` (`.claude/hooks/`): `route-gate.mjs` injects the routing table on every prompt, and `subagent-context.mjs` reminds a spawned subagent where the rules and the task-bundle format live. Merge `settings.hooks.snippet.json`, written next to this file, into `.claude/settings.json` to wire them in.
|