guild-agents 0.3.1 → 1.1.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.
Files changed (40) hide show
  1. package/README.md +5 -1
  2. package/bin/guild.js +75 -1
  3. package/package.json +12 -5
  4. package/src/commands/doctor.js +70 -1
  5. package/src/commands/logs.js +63 -0
  6. package/src/commands/reset-learnings.js +44 -0
  7. package/src/commands/run.js +105 -0
  8. package/src/templates/agents/advisor.md +1 -0
  9. package/src/templates/agents/bugfix.md +1 -0
  10. package/src/templates/agents/code-reviewer.md +1 -0
  11. package/src/templates/agents/db-migration.md +1 -0
  12. package/src/templates/agents/developer.md +1 -0
  13. package/src/templates/agents/learnings-extractor.md +49 -0
  14. package/src/templates/agents/platform-expert.md +1 -0
  15. package/src/templates/agents/product-owner.md +1 -0
  16. package/src/templates/agents/qa.md +1 -0
  17. package/src/templates/agents/tech-lead.md +1 -0
  18. package/src/templates/skills/build-feature/SKILL.md +130 -26
  19. package/src/templates/skills/council/SKILL.md +51 -4
  20. package/src/templates/skills/create-pr/SKILL.md +32 -0
  21. package/src/templates/skills/dev-flow/SKILL.md +14 -0
  22. package/src/templates/skills/guild-specialize/SKILL.md +45 -3
  23. package/src/templates/skills/new-feature/SKILL.md +33 -0
  24. package/src/templates/skills/qa-cycle/SKILL.md +48 -5
  25. package/src/templates/skills/review/SKILL.md +22 -1
  26. package/src/templates/skills/session-end/SKILL.md +27 -0
  27. package/src/templates/skills/session-start/SKILL.md +32 -0
  28. package/src/templates/skills/status/SKILL.md +19 -0
  29. package/src/utils/dispatch-protocol.js +74 -0
  30. package/src/utils/dispatch.js +172 -0
  31. package/src/utils/executor.js +183 -0
  32. package/src/utils/learnings-io.js +76 -0
  33. package/src/utils/learnings.js +204 -0
  34. package/src/utils/orchestrator-io.js +356 -0
  35. package/src/utils/orchestrator.js +590 -0
  36. package/src/utils/providers/claude-code.js +43 -0
  37. package/src/utils/skill-loader.js +83 -0
  38. package/src/utils/trace.js +400 -0
  39. package/src/utils/version.js +90 -0
  40. package/src/utils/workflow-parser.js +225 -0
package/README.md CHANGED
@@ -86,11 +86,14 @@ guild new-agent <name> # Create a custom agent
86
86
  guild status # Show project status
87
87
  guild doctor # Diagnose setup
88
88
  guild list # List agents and skills
89
+ guild run <skill> # Preview a skill's execution plan (dry-run)
90
+ guild logs # View execution traces
91
+ guild logs clean # Remove old traces (--days N, --all)
89
92
  ```
90
93
 
91
94
  ## Under the Hood
92
95
 
93
- Guild coordinates 9 specialized agents through the pipeline. Each agent handles one phase.
96
+ Guild coordinates 10 specialized agents through the pipeline. Each agent handles one phase.
94
97
 
95
98
  | Agent | Role |
96
99
  | --- | --- |
@@ -103,6 +106,7 @@ Guild coordinates 9 specialized agents through the pipeline. Each agent handles
103
106
  | bugfix | Bug diagnosis and resolution |
104
107
  | db-migration | Schema changes and safe migrations |
105
108
  | platform-expert | Diagnoses Claude Code integration issues |
109
+ | learnings-extractor | Extracts compound learnings from pipeline executions |
106
110
 
107
111
  Agents are flat `.md` files with identity and expertise. Skills orchestrate agents through structured pipelines. Everything lives in `.claude/`, readable by humans, tracked by git.
108
112
 
package/bin/guild.js CHANGED
@@ -14,14 +14,25 @@ import { program } from 'commander';
14
14
  import { readFileSync } from 'fs';
15
15
  import { fileURLToPath } from 'url';
16
16
  import { dirname, join } from 'path';
17
+ import chalk from 'chalk';
18
+ import { parseVersion, getPreReleaseWarning } from '../src/utils/version.js';
17
19
 
18
20
  const __dirname = dirname(fileURLToPath(import.meta.url));
19
21
  const pkg = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf8'));
20
22
 
23
+ const { channel } = parseVersion(pkg.version);
24
+ const prereleaseWarning = getPreReleaseWarning(pkg.version);
25
+ if (prereleaseWarning) {
26
+ const color = channel === 'snapshot' ? chalk.red : chalk.yellow;
27
+ console.error(color(`Guild v${pkg.version} -- ${prereleaseWarning}`));
28
+ }
29
+
21
30
  program
22
31
  .name('guild')
23
32
  .description('Specification-driven development CLI for Claude Code')
24
- .version(pkg.version);
33
+ .version(pkg.version)
34
+ .option('--verbose', 'Enable verbose logging (records decision trail)')
35
+ .option('--debug', 'Enable debug logging (records full prompts and responses)');
25
36
 
26
37
  // guild init
27
38
  program
@@ -94,4 +105,67 @@ program
94
105
  }
95
106
  });
96
107
 
108
+ // guild reset-learnings
109
+ program
110
+ .command('reset-learnings')
111
+ .description('Reset the compound learnings file')
112
+ .option('-f, --force', 'Skip confirmation prompt')
113
+ .action(async (options) => {
114
+ try {
115
+ const { runResetLearnings } = await import('../src/commands/reset-learnings.js');
116
+ await runResetLearnings(options);
117
+ } catch (err) {
118
+ console.error(err.message);
119
+ process.exit(1);
120
+ }
121
+ });
122
+
123
+ // guild run
124
+ program
125
+ .command('run')
126
+ .description('Execute a skill workflow')
127
+ .argument('<skill>', 'Skill name to run')
128
+ .argument('[input]', 'Input text for the skill', '')
129
+ .option('--profile <profile>', 'Model profile (max, pro)', 'max')
130
+ .option('--dry-run', 'Display the execution plan without running it')
131
+ .action(async (skill, input, options) => {
132
+ try {
133
+ const { runRun } = await import('../src/commands/run.js');
134
+ await runRun(skill, input, options);
135
+ } catch (err) {
136
+ console.error(err.message);
137
+ process.exit(1);
138
+ }
139
+ });
140
+
141
+ // guild logs (list traces)
142
+ const logsCmd = program
143
+ .command('logs')
144
+ .description('View and manage execution traces')
145
+ .action(async (options) => {
146
+ try {
147
+ const { runLogs } = await import('../src/commands/logs.js');
148
+ await runLogs('list', options);
149
+ } catch (err) {
150
+ console.error(err.message);
151
+ process.exit(1);
152
+ }
153
+ });
154
+
155
+ // guild logs clean
156
+ logsCmd
157
+ .command('clean')
158
+ .description('Remove old execution traces')
159
+ .option('--days <days>', 'Remove traces older than N days', '30')
160
+ .option('--all', 'Remove all traces')
161
+ .action(async (options) => {
162
+ try {
163
+ const { runLogs } = await import('../src/commands/logs.js');
164
+ await runLogs('clean', options);
165
+ } catch (err) {
166
+ console.error(err.message);
167
+ process.exit(1);
168
+ }
169
+ });
170
+
97
171
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "guild-agents",
3
- "version": "0.3.1",
3
+ "version": "1.1.0",
4
4
  "description": "Specification-driven development CLI for Claude Code — think before you build",
5
5
  "type": "module",
6
6
  "files": [
@@ -17,11 +17,18 @@
17
17
  "test": "vitest run",
18
18
  "test:watch": "vitest",
19
19
  "test:coverage": "vitest run --coverage",
20
- "lint": "eslint src/ && markdownlint-cli2 'src/templates/**/*.md'",
21
- "lint:js": "eslint src/",
20
+ "lint": "eslint src/ scripts/ && markdownlint-cli2 'src/templates/**/*.md'",
21
+ "lint:js": "eslint src/ scripts/",
22
22
  "lint:md": "markdownlint-cli2 'src/templates/**/*.md'",
23
23
  "dev": "node bin/guild.js",
24
- "prepublishOnly": "npm test && npm run lint"
24
+ "prepublishOnly": "npm test && npm run lint",
25
+ "version:snapshot": "node scripts/version-snapshot.js",
26
+ "version:beta": "node scripts/version-beta.js",
27
+ "version:stable": "node scripts/version-stable.js",
28
+ "publish:snapshot": "npm run version:snapshot && npm publish --tag snapshot",
29
+ "publish:beta": "npm run version:beta && npm publish --tag beta",
30
+ "publish:stable": "npm run version:stable && npm publish --tag latest",
31
+ "publish:promote-beta": "npm dist-tag add guild-agents@$(node --input-type=commonjs -p \"require('./package.json').version\") beta"
25
32
  },
26
33
  "keywords": [
27
34
  "claude",
@@ -54,7 +61,7 @@
54
61
  "@clack/prompts": "^1.0.1",
55
62
  "chalk": "^5.3.0",
56
63
  "commander": "^14.0.3",
57
- "guild-agents": "^0.3.0"
64
+ "yaml": "^2.8.2"
58
65
  },
59
66
  "engines": {
60
67
  "node": ">=20.0.0"
@@ -7,6 +7,7 @@ import chalk from 'chalk';
7
7
  import { existsSync, readdirSync } from 'fs';
8
8
  import { join } from 'path';
9
9
  import { resolveProjectRoot } from '../utils/files.js';
10
+ import { loadAllSkills } from '../utils/skill-loader.js';
10
11
 
11
12
  export async function runDoctor() {
12
13
  const root = resolveProjectRoot();
@@ -83,9 +84,77 @@ export async function runDoctor() {
83
84
  healthy = false;
84
85
  }
85
86
 
87
+ // Check workflow validation in skills
88
+ if (existsSync(skillsDir)) {
89
+ const skills = loadAllSkills(skillsDir);
90
+ let workflowCount = 0;
91
+ let workflowErrors = 0;
92
+ const errorDetails = [];
93
+
94
+ for (const [name, skill] of skills) {
95
+ if (skill.workflow) {
96
+ workflowCount++;
97
+ if (skill.errors.length > 0) {
98
+ workflowErrors++;
99
+ errorDetails.push(`${name}: ${skill.errors.join('; ')}`);
100
+ }
101
+ }
102
+
103
+ // Check that agent references exist
104
+ if (skill.workflow) {
105
+ for (const step of skill.workflow.steps) {
106
+ if (step.role !== 'system' && step.role !== 'dynamic') {
107
+ const agentPath = join(agentsDir, `${step.role}.md`);
108
+ if (!existsSync(agentPath)) {
109
+ errorDetails.push(`${name}: step "${step.id}" references agent "${step.role}" — agent not found`);
110
+ workflowErrors++;
111
+ }
112
+ }
113
+ }
114
+ }
115
+ }
116
+
117
+ if (workflowCount > 0 && workflowErrors === 0) {
118
+ checks.push({ name: `Workflows (${workflowCount} valid)`, pass: true });
119
+ } else if (workflowCount > 0 && workflowErrors > 0) {
120
+ checks.push({
121
+ name: `Workflows (${workflowErrors} issue(s))`,
122
+ pass: false,
123
+ fix: errorDetails.join('\n '),
124
+ });
125
+ healthy = false;
126
+ }
127
+ // If workflowCount === 0, don't add a check (no workflows to validate)
128
+
129
+ // Check for dual-format skills (workflow frontmatter + body step/phase headings)
130
+ // Matches "### Step 1", "## Phase 2", etc. — requires digit after Step/Phase
131
+ const STEP_PHASE_RE = /^#{1,3}\s+(Step|Phase)\s+\d/im;
132
+ const dualFormatWarnings = [];
133
+
134
+ for (const [name, skill] of skills) {
135
+ if (skill.workflow && skill.body && STEP_PHASE_RE.test(skill.body)) {
136
+ dualFormatWarnings.push(name);
137
+ }
138
+ }
139
+
140
+ if (dualFormatWarnings.length > 0) {
141
+ checks.push({
142
+ name: `Dual-format skills (${dualFormatWarnings.length} warning(s))`,
143
+ pass: true,
144
+ warn: true,
145
+ detail: `Skills with both workflow frontmatter and body step/phase headings: ${dualFormatWarnings.join(', ')}. Workflow steps take precedence — consider removing prose steps from body.`,
146
+ });
147
+ }
148
+ }
149
+
86
150
  // Display results
87
151
  for (const check of checks) {
88
- if (check.pass) {
152
+ if (check.warn) {
153
+ p.log.warn(`${chalk.yellow('⚠')} ${check.name}`);
154
+ if (check.detail) {
155
+ p.log.info(chalk.gray(` ${check.detail}`));
156
+ }
157
+ } else if (check.pass) {
89
158
  p.log.success(`${chalk.green('✓')} ${check.name}`);
90
159
  } else {
91
160
  p.log.error(`${chalk.red('✗')} ${check.name}`);
@@ -0,0 +1,63 @@
1
+ /**
2
+ * logs.js — View and manage Guild execution traces
3
+ */
4
+
5
+ import * as p from '@clack/prompts';
6
+ import chalk from 'chalk';
7
+ import { join } from 'node:path';
8
+ import { ensureProjectRoot } from '../utils/files.js';
9
+ import { listTraces, cleanTraces } from '../utils/trace.js';
10
+
11
+ /**
12
+ * Runs the `guild logs` command.
13
+ *
14
+ * @param {'list'|'clean'} action - Subcommand to run
15
+ * @param {object} [options={}] - Options
16
+ * @param {string} [options.days='30'] - Days threshold for clean
17
+ * @param {boolean} [options.all] - Remove all traces
18
+ */
19
+ export async function runLogs(action, options = {}) {
20
+ const root = ensureProjectRoot();
21
+ const tracesDir = join(root, '.claude', 'guild', 'traces');
22
+
23
+ if (action === 'clean') {
24
+ p.intro(chalk.bold.cyan('Guild — Clean Traces'));
25
+
26
+ let removed;
27
+ if (options.all) {
28
+ removed = cleanTraces(0, tracesDir);
29
+ } else {
30
+ const days = parseInt(options.days || '30', 10);
31
+ removed = cleanTraces(days, tracesDir);
32
+ }
33
+
34
+ p.log.info(chalk.gray(`Removed ${removed} trace(s).`));
35
+ p.outro('');
36
+ return;
37
+ }
38
+
39
+ // Default: list traces
40
+ p.intro(chalk.bold.cyan('Guild — Traces'));
41
+
42
+ const traces = listTraces(tracesDir);
43
+
44
+ if (traces.length === 0) {
45
+ p.log.info(chalk.gray('No traces found.'));
46
+ p.outro('');
47
+ return;
48
+ }
49
+
50
+ for (const trace of traces) {
51
+ const date = trace.date !== 'unknown' ? new Date(trace.date).toLocaleString() : 'unknown';
52
+ const result = trace.result === 'pass' ? chalk.green('pass') :
53
+ trace.result === 'fail' ? chalk.red('fail') :
54
+ chalk.gray(trace.result || 'unknown');
55
+
56
+ p.log.info(` ${chalk.white.bold(trace.workflow)} ${result}`);
57
+ p.log.info(chalk.gray(` ${date} | level: ${trace.level}`));
58
+ }
59
+
60
+ p.log.info('');
61
+ p.log.info(chalk.gray(`Total: ${traces.length} trace(s)`));
62
+ p.outro('');
63
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * reset-learnings.js — Resets the compound learnings file
3
+ */
4
+
5
+ import * as p from '@clack/prompts';
6
+ import chalk from 'chalk';
7
+ import { join } from 'path';
8
+ import { ensureProjectRoot } from '../utils/files.js';
9
+ import { learningsExist, deleteLearnings } from '../utils/learnings-io.js';
10
+ import { GUILD_LEARNINGS_PATH } from '../utils/learnings.js';
11
+
12
+ /**
13
+ * Runs the `guild reset-learnings` command.
14
+ * @param {object} [options]
15
+ * @param {boolean} [options.force] - Skip confirmation prompt
16
+ */
17
+ export async function runResetLearnings(options = {}) {
18
+ const root = ensureProjectRoot();
19
+ const filePath = join(root, GUILD_LEARNINGS_PATH);
20
+
21
+ p.intro(chalk.bold.cyan('Guild — Reset Learnings'));
22
+
23
+ if (!learningsExist(filePath)) {
24
+ p.log.info('No learnings file found. Nothing to reset.');
25
+ p.outro('Done.');
26
+ return;
27
+ }
28
+
29
+ if (!options.force) {
30
+ const confirmed = await p.confirm({
31
+ message: 'This will delete all accumulated learnings. Continue?',
32
+ initialValue: false,
33
+ });
34
+
35
+ if (p.isCancel(confirmed) || !confirmed) {
36
+ p.cancel('Reset cancelled.');
37
+ return;
38
+ }
39
+ }
40
+
41
+ deleteLearnings(filePath);
42
+ p.log.success(`${chalk.green('✓')} Learnings file deleted.`);
43
+ p.outro('Learnings have been reset. They will be regenerated on the next workflow execution.');
44
+ }
@@ -0,0 +1,105 @@
1
+ /**
2
+ * run.js — Executes a skill workflow (or displays the plan in dry-run mode)
3
+ */
4
+
5
+ import * as p from '@clack/prompts';
6
+ import chalk from 'chalk';
7
+ import { ensureProjectRoot } from '../utils/files.js';
8
+ import { orchestrate, finalizeWorkflowTrace } from '../utils/orchestrator-io.js';
9
+ import { execute } from '../utils/executor.js';
10
+ import { createClaudeCodeProvider } from '../utils/providers/claude-code.js';
11
+
12
+ /**
13
+ * Displays the execution plan without running it.
14
+ * @param {object} plan
15
+ * @param {object} dispatchInfoMap
16
+ */
17
+ function displayPlan(plan, dispatchInfoMap) {
18
+ for (let i = 0; i < plan.groups.length; i++) {
19
+ const group = plan.groups[i];
20
+ const label = group.parallel ? `Group ${i + 1} (parallel)` : `Group ${i + 1}`;
21
+ p.log.step(chalk.bold(label));
22
+
23
+ for (const step of group.steps) {
24
+ const dispatch = dispatchInfoMap[step.id] || {};
25
+ const roleLabel = step.role === 'system' ? chalk.yellow('system') : chalk.blue(step.role);
26
+ const modelLabel = dispatch.model ? chalk.gray(` → ${dispatch.model}`) : '';
27
+ const gateLabel = step.gate ? chalk.red(' GATE') : '';
28
+
29
+ p.log.info(` ${chalk.white.bold(step.id)} ${roleLabel}${modelLabel}${gateLabel}`);
30
+ p.log.info(chalk.gray(` ${step.intent}`));
31
+
32
+ if (step.requires && step.requires.length > 0) {
33
+ p.log.info(chalk.gray(` requires: ${step.requires.join(', ')}`));
34
+ }
35
+ if (step.produces && step.produces.length > 0) {
36
+ p.log.info(chalk.gray(` produces: ${step.produces.join(', ')}`));
37
+ }
38
+ if (step.condition) {
39
+ p.log.info(chalk.gray(` condition: ${step.condition}`));
40
+ }
41
+ if (step.commands && step.commands.length > 0) {
42
+ p.log.info(chalk.gray(` commands: ${step.commands.join(', ')}`));
43
+ }
44
+ }
45
+ }
46
+ }
47
+
48
+ /**
49
+ * Runs the `guild run <skill>` command.
50
+ *
51
+ * @param {string} skillName - Name of the skill to run
52
+ * @param {string} [input=''] - Optional input text for the skill
53
+ * @param {object} [options={}] - Options
54
+ * @param {string} [options.profile='max'] - Model profile
55
+ * @param {boolean} [options.dryRun=false] - Show plan without executing
56
+ */
57
+ export async function runRun(skillName, input = '', options = {}) {
58
+ const root = ensureProjectRoot();
59
+ const { profile = 'max', dryRun = false } = options;
60
+
61
+ p.intro(chalk.bold.cyan(' Guild — Run: ' + skillName + ' '));
62
+
63
+ const { plan, trace, dispatchInfoMap } = await orchestrate(skillName, input, {
64
+ profile,
65
+ projectRoot: root,
66
+ });
67
+
68
+ p.log.info(chalk.gray(`Profile: ${profile} | Steps: ${plan.totalSteps}`));
69
+
70
+ if (dryRun) {
71
+ displayPlan(plan, dispatchInfoMap);
72
+ p.outro(chalk.gray('Plan generated (dry-run). No steps were executed.'));
73
+ return;
74
+ }
75
+
76
+ // Real execution
77
+ const provider = createClaudeCodeProvider({ projectRoot: root });
78
+
79
+ const finalPlan = await execute(plan, dispatchInfoMap, {
80
+ provider,
81
+ skillBody: input,
82
+ trace,
83
+ projectRoot: root,
84
+
85
+ onStepStart(step, dispatch) {
86
+ const roleLabel = step.role === 'system' ? chalk.yellow('system') : chalk.blue(step.role);
87
+ const modelLabel = dispatch.model ? chalk.gray(` (${dispatch.model})`) : '';
88
+ p.log.step(`${chalk.bold(step.id)} ${roleLabel}${modelLabel}`);
89
+ },
90
+
91
+ onStepEnd(step, result) {
92
+ const icon = result.status === 'passed' ? chalk.green('✓') : chalk.red('✗');
93
+ p.log.info(` ${icon} ${result.status}`);
94
+ },
95
+ });
96
+
97
+ // Finalize trace
98
+ const { executionSummary } = finalizeWorkflowTrace(trace, finalPlan);
99
+
100
+ const statusLabel = finalPlan.status === 'completed'
101
+ ? chalk.green('completed')
102
+ : chalk.red(finalPlan.status);
103
+
104
+ p.outro(`${statusLabel} | ${executionSummary}`);
105
+ }
@@ -3,6 +3,7 @@ name: advisor
3
3
  description: "Evaluates ideas and provides strategic direction before committing work"
4
4
  tools: Read, Glob, Grep
5
5
  permissionMode: plan
6
+ default-tier: reasoning
6
7
  ---
7
8
 
8
9
  # Advisor
@@ -3,6 +3,7 @@ name: bugfix
3
3
  description: "Bug diagnosis and resolution"
4
4
  tools: Read, Write, Edit, Bash, Glob, Grep
5
5
  permissionMode: bypassPermissions
6
+ default-tier: execution
6
7
  ---
7
8
 
8
9
  # Bugfix
@@ -3,6 +3,7 @@ name: code-reviewer
3
3
  description: "Reviews quality, patterns, and technical debt"
4
4
  tools: Read, Glob, Grep
5
5
  permissionMode: plan
6
+ default-tier: reasoning
6
7
  ---
7
8
 
8
9
  # Code Reviewer
@@ -3,6 +3,7 @@ name: db-migration
3
3
  description: "Schema changes and safe migrations"
4
4
  tools: Read, Write, Edit, Bash, Glob, Grep
5
5
  permissionMode: bypassPermissions
6
+ default-tier: execution
6
7
  ---
7
8
 
8
9
  # DB Migration
@@ -3,6 +3,7 @@ name: developer
3
3
  description: "Implements features following the project conventions"
4
4
  tools: Read, Write, Edit, Bash, Glob, Grep
5
5
  permissionMode: bypassPermissions
6
+ default-tier: execution
6
7
  ---
7
8
 
8
9
  # Developer
@@ -0,0 +1,49 @@
1
+ ---
2
+ name: learnings-extractor
3
+ description: "Extracts compound learnings from pipeline executions"
4
+ tools: Read, Glob, Grep
5
+ permissionMode: plan
6
+ default-tier: routine
7
+ ---
8
+
9
+ # Learnings Extractor
10
+
11
+ You are the Learnings Extractor for [PROJECT]. Your job is to analyze completed pipeline traces and extract reusable patterns, recurring issues, and optimization opportunities that improve future executions.
12
+
13
+ ## Responsibilities
14
+
15
+ - Read pipeline trace files from `.claude/guild/traces/`
16
+ - Identify patterns across multiple executions (recurring review loops, common failures)
17
+ - Extract actionable learnings that reduce future iteration count
18
+ - Update `.claude/guild/learnings.md` with new findings
19
+ - Prioritize learnings by impact (reduces tokens, reduces loops, improves quality)
20
+
21
+ ## What you do NOT do
22
+
23
+ - You do not implement features — that is the Developer's role
24
+ - You do not evaluate strategy — that is the Advisor's role
25
+ - You do not modify source code — you only read traces and write learnings
26
+
27
+ ## Process
28
+
29
+ 1. Read the pipeline trace provided as input
30
+ 2. Analyze step results, loop counts, and failure patterns
31
+ 3. Compare with existing learnings in `.claude/guild/learnings.md`
32
+ 4. Extract new learnings or reinforce existing ones
33
+ 5. Write updated learnings in a structured format
34
+
35
+ ## Output format
36
+
37
+ Each learning should include:
38
+
39
+ - **Pattern**: What was observed
40
+ - **Frequency**: How often it occurs (first-seen or recurring)
41
+ - **Recommendation**: What to do differently next time
42
+ - **Impact**: Expected reduction in loops, tokens, or failures
43
+
44
+ ## Behavior rules
45
+
46
+ - Never duplicate an existing learning — update its frequency instead
47
+ - Focus on actionable recommendations, not observations
48
+ - Keep learnings concise — one paragraph maximum per entry
49
+ - Tag learnings with the workflow they came from
@@ -3,6 +3,7 @@ name: platform-expert
3
3
  description: "Diagnoses and resolves Claude Code integration issues -- permissions, subagents, hooks, settings"
4
4
  tools: Read, Write, Edit, Bash, Glob, Grep
5
5
  permissionMode: bypassPermissions
6
+ default-tier: execution
6
7
  ---
7
8
 
8
9
  # Platform Expert
@@ -3,6 +3,7 @@ name: product-owner
3
3
  description: "Converts approved ideas into concrete, implementable tasks"
4
4
  tools: Read, Glob, Grep
5
5
  permissionMode: plan
6
+ default-tier: reasoning
6
7
  ---
7
8
 
8
9
  # Product Owner
@@ -3,6 +3,7 @@ name: qa
3
3
  description: "Testing, edge cases, regression"
4
4
  tools: Read, Write, Edit, Bash, Glob, Grep
5
5
  permissionMode: bypassPermissions
6
+ default-tier: execution
6
7
  ---
7
8
 
8
9
  # QA
@@ -3,6 +3,7 @@ name: tech-lead
3
3
  description: "Defines technical approach and architecture"
4
4
  tools: Read, Glob, Grep
5
5
  permissionMode: plan
6
+ default-tier: reasoning
6
7
  ---
7
8
 
8
9
  # Tech Lead