guild-agents 0.2.6 → 0.2.7
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/bin/guild.js +7 -7
- package/package.json +3 -3
- package/src/commands/__tests__/new-agent.test.js +3 -3
- package/src/commands/__tests__/status.test.js +2 -2
- package/src/commands/init.js +44 -44
- package/src/commands/new-agent.js +37 -37
- package/src/commands/status.js +11 -11
- package/src/templates/agents/advisor.md +29 -29
- package/src/templates/agents/bugfix.md +32 -32
- package/src/templates/agents/code-reviewer.md +32 -32
- package/src/templates/agents/db-migration.md +32 -32
- package/src/templates/agents/developer.md +32 -32
- package/src/templates/agents/platform-expert.md +36 -36
- package/src/templates/agents/product-owner.md +32 -32
- package/src/templates/agents/qa.md +31 -31
- package/src/templates/agents/tech-lead.md +32 -32
- package/src/templates/skills/build-feature/SKILL.md +85 -85
- package/src/templates/skills/council/SKILL.md +68 -68
- package/src/templates/skills/dev-flow/SKILL.md +31 -31
- package/src/templates/skills/guild-specialize/SKILL.md +68 -68
- package/src/templates/skills/new-feature/SKILL.md +34 -34
- package/src/templates/skills/qa-cycle/SKILL.md +39 -39
- package/src/templates/skills/review/SKILL.md +35 -35
- package/src/templates/skills/session-end/SKILL.md +33 -33
- package/src/templates/skills/session-start/SKILL.md +32 -32
- package/src/templates/skills/status/SKILL.md +33 -33
- package/src/utils/generators.js +47 -47
- package/src/utils/github.js +20 -20
package/bin/guild.js
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* Guild v1 — CLI entry point
|
|
5
5
|
* Usage:
|
|
6
|
-
* guild init — onboarding
|
|
7
|
-
* guild new-agent —
|
|
8
|
-
* guild status —
|
|
6
|
+
* guild init — interactive onboarding v1
|
|
7
|
+
* guild new-agent — create a new agent
|
|
8
|
+
* guild status — view project status
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import { program } from 'commander';
|
|
@@ -24,7 +24,7 @@ program
|
|
|
24
24
|
// guild init
|
|
25
25
|
program
|
|
26
26
|
.command('init')
|
|
27
|
-
.description('
|
|
27
|
+
.description('Initialize Guild v1 in the current project')
|
|
28
28
|
.action(async () => {
|
|
29
29
|
try {
|
|
30
30
|
const { runInit } = await import('../src/commands/init.js');
|
|
@@ -38,8 +38,8 @@ program
|
|
|
38
38
|
// guild new-agent
|
|
39
39
|
program
|
|
40
40
|
.command('new-agent')
|
|
41
|
-
.description('
|
|
42
|
-
.argument('<name>', '
|
|
41
|
+
.description('Create a new agent')
|
|
42
|
+
.argument('<name>', 'Agent name (lowercase, hyphens)')
|
|
43
43
|
.action(async (name) => {
|
|
44
44
|
try {
|
|
45
45
|
const { runNewAgent } = await import('../src/commands/new-agent.js');
|
|
@@ -53,7 +53,7 @@ program
|
|
|
53
53
|
// guild status
|
|
54
54
|
program
|
|
55
55
|
.command('status')
|
|
56
|
-
.description('
|
|
56
|
+
.description('View Guild project status')
|
|
57
57
|
.action(async () => {
|
|
58
58
|
try {
|
|
59
59
|
const { runStatus } = await import('../src/commands/status.js');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "guild-agents",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"description": "A multi-agent framework for Claude Code — specialized AI teams for every project",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -50,9 +50,9 @@
|
|
|
50
50
|
"url": "https://github.com/guild-agents/guild/issues"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@clack/prompts": "^0.
|
|
53
|
+
"@clack/prompts": "^1.0.1",
|
|
54
54
|
"chalk": "^5.3.0",
|
|
55
|
-
"commander": "^
|
|
55
|
+
"commander": "^14.0.3",
|
|
56
56
|
"picocolors": "^1.0.0"
|
|
57
57
|
},
|
|
58
58
|
"engines": {
|
|
@@ -21,13 +21,13 @@ describe('runNewAgent', () => {
|
|
|
21
21
|
it('should throw with invalid agent name', async () => {
|
|
22
22
|
process.chdir(tempDir);
|
|
23
23
|
const { runNewAgent } = await import('../new-agent.js');
|
|
24
|
-
await expect(runNewAgent('Invalid Name!')).rejects.toThrow('
|
|
24
|
+
await expect(runNewAgent('Invalid Name!')).rejects.toThrow('Invalid name');
|
|
25
25
|
});
|
|
26
26
|
|
|
27
27
|
it('should throw when .claude/agents/ does not exist', async () => {
|
|
28
28
|
process.chdir(tempDir);
|
|
29
29
|
const { runNewAgent } = await import('../new-agent.js');
|
|
30
|
-
await expect(runNewAgent('valid-name')).rejects.toThrow('Guild
|
|
30
|
+
await expect(runNewAgent('valid-name')).rejects.toThrow('Guild is not installed');
|
|
31
31
|
});
|
|
32
32
|
|
|
33
33
|
it('should throw when agent already exists', async () => {
|
|
@@ -35,6 +35,6 @@ describe('runNewAgent', () => {
|
|
|
35
35
|
mkdirSync(join(tempDir, '.claude', 'agents'), { recursive: true });
|
|
36
36
|
writeFileSync(join(tempDir, '.claude', 'agents', 'existing.md'), '# existing');
|
|
37
37
|
const { runNewAgent } = await import('../new-agent.js');
|
|
38
|
-
await expect(runNewAgent('existing')).rejects.toThrow('
|
|
38
|
+
await expect(runNewAgent('existing')).rejects.toThrow('already exists');
|
|
39
39
|
});
|
|
40
40
|
});
|
|
@@ -21,12 +21,12 @@ describe('runStatus', () => {
|
|
|
21
21
|
it('should throw when PROJECT.md does not exist', async () => {
|
|
22
22
|
process.chdir(tempDir);
|
|
23
23
|
const { runStatus } = await import('../status.js');
|
|
24
|
-
await expect(runStatus()).rejects.toThrow('Guild
|
|
24
|
+
await expect(runStatus()).rejects.toThrow('Guild is not installed');
|
|
25
25
|
});
|
|
26
26
|
|
|
27
27
|
it('should not throw when PROJECT.md exists', async () => {
|
|
28
28
|
process.chdir(tempDir);
|
|
29
|
-
writeFileSync(join(tempDir, 'PROJECT.md'), '**
|
|
29
|
+
writeFileSync(join(tempDir, 'PROJECT.md'), '**Name:** TestProject\n**Stack:** Node.js');
|
|
30
30
|
mkdirSync(join(tempDir, '.claude', 'agents'), { recursive: true });
|
|
31
31
|
mkdirSync(join(tempDir, '.claude', 'skills'), { recursive: true });
|
|
32
32
|
const { runStatus } = await import('../status.js');
|
package/src/commands/init.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* guild init —
|
|
2
|
+
* guild init — Interactive onboarding v1
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* 1.
|
|
6
|
-
* 2.
|
|
7
|
-
* 3.
|
|
8
|
-
* 4.
|
|
9
|
-
* 5.
|
|
4
|
+
* Flow:
|
|
5
|
+
* 1. Verify that a Guild installation does not already exist
|
|
6
|
+
* 2. Collect: name, type, stack, GitHub, existing code
|
|
7
|
+
* 3. Generate PROJECT.md, CLAUDE.md, SESSION.md
|
|
8
|
+
* 4. Copy agents and skills
|
|
9
|
+
* 5. Instructions for /guild-specialize
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import * as p from '@clack/prompts';
|
|
@@ -17,68 +17,68 @@ import { copyTemplates } from '../utils/files.js';
|
|
|
17
17
|
|
|
18
18
|
export async function runInit() {
|
|
19
19
|
console.log('');
|
|
20
|
-
p.intro(chalk.bold.cyan('Guild v1 —
|
|
20
|
+
p.intro(chalk.bold.cyan('Guild v1 — New project'));
|
|
21
21
|
|
|
22
|
-
//
|
|
22
|
+
// Check for existing installation
|
|
23
23
|
if (existsSync('.claude/agents')) {
|
|
24
24
|
const overwrite = await p.confirm({
|
|
25
|
-
message: 'Guild
|
|
25
|
+
message: 'Guild is already installed in this project. Reinitialize?',
|
|
26
26
|
initialValue: false,
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
if (p.isCancel(overwrite) || !overwrite) {
|
|
30
|
-
p.cancel('
|
|
30
|
+
p.cancel('Cancelled.');
|
|
31
31
|
return;
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
// ───
|
|
35
|
+
// ─── Name ─────────────────────────────────────────────────────────────────
|
|
36
36
|
const name = await p.text({
|
|
37
|
-
message: '
|
|
38
|
-
placeholder: '
|
|
37
|
+
message: 'Project name:',
|
|
38
|
+
placeholder: 'my-project',
|
|
39
39
|
validate: (val) => {
|
|
40
|
-
if (!val) return '
|
|
40
|
+
if (!val) return 'Name is required';
|
|
41
41
|
},
|
|
42
42
|
});
|
|
43
|
-
if (p.isCancel(name)) { p.cancel('
|
|
43
|
+
if (p.isCancel(name)) { p.cancel('Cancelled.'); return; }
|
|
44
44
|
|
|
45
|
-
// ───
|
|
45
|
+
// ─── Type ───────────────────────────────────────────────────────────────────
|
|
46
46
|
const type = await p.select({
|
|
47
|
-
message: '
|
|
47
|
+
message: 'Project type:',
|
|
48
48
|
options: [
|
|
49
49
|
{ value: 'webapp', label: 'Web app (React/Vue/Angular)' },
|
|
50
50
|
{ value: 'api', label: 'API / Backend service' },
|
|
51
51
|
{ value: 'cli', label: 'CLI tool' },
|
|
52
52
|
{ value: 'mobile', label: 'Mobile (React Native)' },
|
|
53
|
-
{ value: 'fullstack', label: '
|
|
53
|
+
{ value: 'fullstack', label: 'Other / Fullstack' },
|
|
54
54
|
],
|
|
55
55
|
});
|
|
56
|
-
if (p.isCancel(type)) { p.cancel('
|
|
56
|
+
if (p.isCancel(type)) { p.cancel('Cancelled.'); return; }
|
|
57
57
|
|
|
58
58
|
// ─── Stack ──────────────────────────────────────────────────────────────────
|
|
59
59
|
const stack = await p.text({
|
|
60
|
-
message: '
|
|
61
|
-
placeholder: '
|
|
60
|
+
message: 'Main stack:',
|
|
61
|
+
placeholder: 'e.g.: Next.js, Supabase, Vercel',
|
|
62
62
|
validate: (val) => {
|
|
63
|
-
if (!val) return '
|
|
63
|
+
if (!val) return 'Stack is required';
|
|
64
64
|
},
|
|
65
65
|
});
|
|
66
|
-
if (p.isCancel(stack)) { p.cancel('
|
|
66
|
+
if (p.isCancel(stack)) { p.cancel('Cancelled.'); return; }
|
|
67
67
|
|
|
68
68
|
// ─── GitHub ─────────────────────────────────────────────────────────────────
|
|
69
69
|
let github = null;
|
|
70
70
|
const hasRepo = await p.confirm({
|
|
71
|
-
message: '
|
|
71
|
+
message: 'Has a GitHub repository?',
|
|
72
72
|
initialValue: true,
|
|
73
73
|
});
|
|
74
74
|
|
|
75
75
|
if (!p.isCancel(hasRepo) && hasRepo) {
|
|
76
76
|
const repoUrl = await p.text({
|
|
77
|
-
message: 'URL
|
|
77
|
+
message: 'Repository URL:',
|
|
78
78
|
placeholder: 'https://github.com/org/repo',
|
|
79
79
|
validate: (val) => {
|
|
80
|
-
if (!val) return '
|
|
81
|
-
if (!val.includes('github.com')) return '
|
|
80
|
+
if (!val) return 'URL is required';
|
|
81
|
+
if (!val.includes('github.com')) return 'Must be a GitHub URL';
|
|
82
82
|
},
|
|
83
83
|
});
|
|
84
84
|
if (!p.isCancel(repoUrl)) {
|
|
@@ -86,15 +86,15 @@ export async function runInit() {
|
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
// ───
|
|
89
|
+
// ─── Existing code ────────────────────────────────────────────────────────
|
|
90
90
|
const hasExistingCode = await p.confirm({
|
|
91
|
-
message: '
|
|
91
|
+
message: 'Has existing code?',
|
|
92
92
|
initialValue: true,
|
|
93
93
|
});
|
|
94
94
|
|
|
95
|
-
// ───
|
|
95
|
+
// ─── Generation ───────────────────────────────────────────────────────────
|
|
96
96
|
const spinner = p.spinner();
|
|
97
|
-
spinner.start('
|
|
97
|
+
spinner.start('Generating Guild v1 structure...');
|
|
98
98
|
|
|
99
99
|
const projectData = {
|
|
100
100
|
name,
|
|
@@ -106,35 +106,35 @@ export async function runInit() {
|
|
|
106
106
|
|
|
107
107
|
try {
|
|
108
108
|
await copyTemplates();
|
|
109
|
-
spinner.message('
|
|
109
|
+
spinner.message('Generating CLAUDE.md...');
|
|
110
110
|
await generateClaudeMd(projectData);
|
|
111
111
|
|
|
112
|
-
spinner.message('
|
|
112
|
+
spinner.message('Generating PROJECT.md...');
|
|
113
113
|
await generateProjectMd(projectData);
|
|
114
114
|
|
|
115
|
-
spinner.message('
|
|
115
|
+
spinner.message('Generating SESSION.md...');
|
|
116
116
|
await generateSessionMd();
|
|
117
117
|
|
|
118
|
-
spinner.stop('
|
|
118
|
+
spinner.stop('Structure created.');
|
|
119
119
|
} catch (error) {
|
|
120
|
-
spinner.stop('Error
|
|
120
|
+
spinner.stop('Error during initialization.');
|
|
121
121
|
throw error;
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
-
// ───
|
|
124
|
+
// ─── Summary ──────────────────────────────────────────────────────────────
|
|
125
125
|
p.log.success('CLAUDE.md');
|
|
126
126
|
p.log.success('PROJECT.md');
|
|
127
127
|
p.log.success('SESSION.md');
|
|
128
|
-
p.log.success('.claude/agents/ (8
|
|
128
|
+
p.log.success('.claude/agents/ (8 base agents)');
|
|
129
129
|
p.log.success('.claude/skills/ (10 skills)');
|
|
130
130
|
|
|
131
131
|
p.note(
|
|
132
|
-
'
|
|
132
|
+
'Open Claude Code in this directory and run:\n\n' +
|
|
133
133
|
' /guild-specialize\n\n' +
|
|
134
|
-
'
|
|
135
|
-
'
|
|
136
|
-
'
|
|
134
|
+
'This skill will explore your code and enrich CLAUDE.md\n' +
|
|
135
|
+
'with the actual project information.',
|
|
136
|
+
'Next step'
|
|
137
137
|
);
|
|
138
138
|
|
|
139
|
-
p.outro(chalk.bold.cyan('Guild v1
|
|
139
|
+
p.outro(chalk.bold.cyan('Guild v1 ready.'));
|
|
140
140
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* new-agent.js —
|
|
2
|
+
* new-agent.js — Creates a new v1 agent (plain file)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* 1.
|
|
6
|
-
* 2.
|
|
7
|
-
* 3.
|
|
8
|
-
* 4.
|
|
9
|
-
* 5.
|
|
4
|
+
* Flow:
|
|
5
|
+
* 1. Validate name (lowercase, hyphens, no spaces)
|
|
6
|
+
* 2. Verify that Guild is installed
|
|
7
|
+
* 3. Verify that the agent does NOT exist
|
|
8
|
+
* 4. Ask for agent description
|
|
9
|
+
* 5. Create .claude/agents/[name].md with placeholder
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import * as p from '@clack/prompts';
|
|
@@ -17,35 +17,35 @@ import { join } from 'path';
|
|
|
17
17
|
const AGENTS_DIR = join('.claude', 'agents');
|
|
18
18
|
|
|
19
19
|
export async function runNewAgent(agentName) {
|
|
20
|
-
p.intro(chalk.bold.cyan('Guild —
|
|
20
|
+
p.intro(chalk.bold.cyan('Guild — New agent'));
|
|
21
21
|
|
|
22
|
-
//
|
|
22
|
+
// Validate name
|
|
23
23
|
if (!isValidAgentName(agentName)) {
|
|
24
|
-
throw new Error(`
|
|
24
|
+
throw new Error(`Invalid name: "${agentName}". Only lowercase, numbers, and hyphens allowed. Example: guild new-agent security-auditor`);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
//
|
|
27
|
+
// Verify Guild is installed
|
|
28
28
|
if (!existsSync(AGENTS_DIR)) {
|
|
29
|
-
throw new Error('Guild
|
|
29
|
+
throw new Error('Guild is not installed. Run: guild init');
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
//
|
|
32
|
+
// Verify that the agent does NOT exist
|
|
33
33
|
const agentPath = join(AGENTS_DIR, `${agentName}.md`);
|
|
34
34
|
if (existsSync(agentPath)) {
|
|
35
|
-
throw new Error(`
|
|
35
|
+
throw new Error(`Agent "${agentName}" already exists.`);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
//
|
|
38
|
+
// Ask for description
|
|
39
39
|
const description = await p.text({
|
|
40
|
-
message: `
|
|
41
|
-
placeholder: '
|
|
42
|
-
validate: (val) => !val ? '
|
|
40
|
+
message: `What does "${agentName}" do? (short description):`,
|
|
41
|
+
placeholder: 'e.g.: Evaluates trading opportunities based on technical analysis',
|
|
42
|
+
validate: (val) => !val ? 'Description is required' : undefined,
|
|
43
43
|
});
|
|
44
|
-
if (p.isCancel(description)) { p.cancel('
|
|
44
|
+
if (p.isCancel(description)) { p.cancel('Cancelled.'); return; }
|
|
45
45
|
|
|
46
|
-
//
|
|
46
|
+
// Create agent
|
|
47
47
|
const spinner = p.spinner();
|
|
48
|
-
spinner.start(`
|
|
48
|
+
spinner.start(`Creating agent "${agentName}"...`);
|
|
49
49
|
|
|
50
50
|
try {
|
|
51
51
|
const content = `---
|
|
@@ -55,34 +55,34 @@ description: "${description}"
|
|
|
55
55
|
|
|
56
56
|
# ${agentName}
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
You are ${agentName} of [PROJECT].
|
|
59
59
|
|
|
60
|
-
##
|
|
61
|
-
[
|
|
60
|
+
## Responsibilities
|
|
61
|
+
[Define with /guild-specialize]
|
|
62
62
|
|
|
63
|
-
##
|
|
64
|
-
[
|
|
63
|
+
## What you do NOT do
|
|
64
|
+
[Define with /guild-specialize]
|
|
65
65
|
|
|
66
|
-
##
|
|
67
|
-
[
|
|
66
|
+
## Process
|
|
67
|
+
[Define with /guild-specialize]
|
|
68
68
|
|
|
69
|
-
##
|
|
70
|
-
-
|
|
69
|
+
## Behavioral rules
|
|
70
|
+
- Always read CLAUDE.md and SESSION.md at the start of the session
|
|
71
71
|
`;
|
|
72
72
|
|
|
73
73
|
writeFileSync(agentPath, content, 'utf8');
|
|
74
74
|
|
|
75
|
-
spinner.stop(`
|
|
75
|
+
spinner.stop(`Agent "${agentName}" created.`);
|
|
76
76
|
|
|
77
|
-
p.log.success(`
|
|
77
|
+
p.log.success(`File: ${agentPath}`);
|
|
78
78
|
p.note(
|
|
79
|
-
`
|
|
80
|
-
`
|
|
81
|
-
'
|
|
79
|
+
`Run /guild-specialize so that Claude\n` +
|
|
80
|
+
`generates the full instructions for "${agentName}".`,
|
|
81
|
+
'Specialization pending'
|
|
82
82
|
);
|
|
83
|
-
p.outro(chalk.bold.cyan(`
|
|
83
|
+
p.outro(chalk.bold.cyan(`Agent ${agentName} ready.`));
|
|
84
84
|
} catch (error) {
|
|
85
|
-
spinner.stop('Error
|
|
85
|
+
spinner.stop('Error creating agent.');
|
|
86
86
|
throw error;
|
|
87
87
|
}
|
|
88
88
|
}
|
package/src/commands/status.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* status.js —
|
|
2
|
+
* status.js — Shows the current project status v1
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import * as p from '@clack/prompts';
|
|
@@ -9,13 +9,13 @@ import { join } from 'path';
|
|
|
9
9
|
|
|
10
10
|
export async function runStatus() {
|
|
11
11
|
if (!existsSync('PROJECT.md')) {
|
|
12
|
-
throw new Error('Guild
|
|
12
|
+
throw new Error('Guild is not installed. Run: guild init');
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
const projectMd = readFileSync('PROJECT.md', 'utf8');
|
|
16
|
-
const nameMatch = projectMd.match(/\*\*
|
|
16
|
+
const nameMatch = projectMd.match(/\*\*Name:\*\*\s*(.+)/);
|
|
17
17
|
const stackMatch = projectMd.match(/\*\*Stack:\*\*\s*(.+)/);
|
|
18
|
-
const projectName = nameMatch ? nameMatch[1].trim() : '
|
|
18
|
+
const projectName = nameMatch ? nameMatch[1].trim() : 'Project';
|
|
19
19
|
|
|
20
20
|
p.intro(chalk.bold.cyan(`Guild — ${projectName}`));
|
|
21
21
|
|
|
@@ -23,20 +23,20 @@ export async function runStatus() {
|
|
|
23
23
|
p.log.info(chalk.gray(`Stack: ${stackMatch[1].trim()}`));
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
//
|
|
26
|
+
// Active session
|
|
27
27
|
if (existsSync('SESSION.md')) {
|
|
28
|
-
p.log.step('
|
|
28
|
+
p.log.step('Active session');
|
|
29
29
|
const sessionMd = readFileSync('SESSION.md', 'utf8');
|
|
30
|
-
const taskMatch = sessionMd.match(/\*\*
|
|
31
|
-
const stateMatch = sessionMd.match(/\*\*
|
|
32
|
-
if (taskMatch && taskMatch[1].trim() !== '—') p.log.info(`
|
|
30
|
+
const taskMatch = sessionMd.match(/\*\*Current task:\*\*\s*(.+)/);
|
|
31
|
+
const stateMatch = sessionMd.match(/\*\*Status:\*\*\s*(.+)/);
|
|
32
|
+
if (taskMatch && taskMatch[1].trim() !== '—') p.log.info(` Task: ${taskMatch[1].trim()}`);
|
|
33
33
|
if (stateMatch) p.log.info(chalk.gray(` ${stateMatch[1].trim()}`));
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
//
|
|
36
|
+
// Agents
|
|
37
37
|
const agentsDir = join('.claude', 'agents');
|
|
38
38
|
if (existsSync(agentsDir)) {
|
|
39
|
-
p.log.step('
|
|
39
|
+
p.log.step('Agents');
|
|
40
40
|
const agents = readdirSync(agentsDir)
|
|
41
41
|
.filter(f => f.endsWith('.md'))
|
|
42
42
|
.map(f => f.replace('.md', ''));
|
|
@@ -1,47 +1,47 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: advisor
|
|
3
|
-
description: "
|
|
3
|
+
description: "Evaluates ideas and provides strategic direction before committing work"
|
|
4
4
|
tools: Read, Glob, Grep
|
|
5
5
|
permissionMode: plan
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Advisor
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
You are the domain guardian of [PROJECT]. Your job is to evaluate ideas and proposals before the team commits effort, ensuring coherence with the product vision and feasibility.
|
|
11
11
|
|
|
12
|
-
##
|
|
12
|
+
## Responsibilities
|
|
13
13
|
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
14
|
+
- Evaluate feature proposals and changes against the project vision
|
|
15
|
+
- Identify business risks, hidden dependencies, and conflicts with existing functionality
|
|
16
|
+
- Approve, reject, or request adjustments to ideas before they move to planning
|
|
17
|
+
- Detect scope creep and keep the project focused
|
|
18
|
+
- Validate that proposed priorities make strategic sense
|
|
19
19
|
|
|
20
|
-
##
|
|
20
|
+
## What you do NOT do
|
|
21
21
|
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
22
|
+
- You do not define architecture or technical approach -- that is the Tech Lead's role
|
|
23
|
+
- You do not prioritize the backlog or write acceptance criteria -- that is the Product Owner's role
|
|
24
|
+
- You do not review code -- that is the Code Reviewer's role
|
|
25
|
+
- You do not implement anything -- that is the Developer's role
|
|
26
26
|
|
|
27
|
-
##
|
|
27
|
+
## Process
|
|
28
28
|
|
|
29
|
-
1.
|
|
30
|
-
2.
|
|
31
|
-
3.
|
|
32
|
-
4.
|
|
29
|
+
1. Read CLAUDE.md and SESSION.md to understand the current project state
|
|
30
|
+
2. Analyze the proposal in the context of the domain and [PROJECT]'s vision
|
|
31
|
+
3. Identify risks, dependencies, and conflicts
|
|
32
|
+
4. Issue your evaluation using the output format
|
|
33
33
|
|
|
34
|
-
##
|
|
34
|
+
## Output format
|
|
35
35
|
|
|
36
|
-
- **
|
|
37
|
-
- **
|
|
38
|
-
- **
|
|
39
|
-
- **
|
|
36
|
+
- **Evaluation**: Approved / Rejected / Requires adjustments
|
|
37
|
+
- **Reasoning**: Why this decision (2-3 sentences)
|
|
38
|
+
- **Suggested adjustments**: Concrete changes if applicable
|
|
39
|
+
- **Identified risks**: Prioritized list of risks
|
|
40
40
|
|
|
41
|
-
##
|
|
41
|
+
## Behavior rules
|
|
42
42
|
|
|
43
|
-
-
|
|
44
|
-
-
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
-
|
|
43
|
+
- Always read CLAUDE.md and SESSION.md before evaluating
|
|
44
|
+
- Be concise -- the team needs decisions, not essays
|
|
45
|
+
- Ground every evaluation in concrete reasons, not vague opinions
|
|
46
|
+
- If you lack sufficient context, ask for clarification before evaluating
|
|
47
|
+
- Distinguish between real risks and personal preferences
|
|
@@ -1,50 +1,50 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: bugfix
|
|
3
|
-
description: "
|
|
3
|
+
description: "Bug diagnosis and resolution"
|
|
4
4
|
tools: Read, Write, Edit, Bash, Glob, Grep
|
|
5
5
|
permissionMode: bypassPermissions
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Bugfix
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
You are the bug diagnosis and resolution specialist for [PROJECT]. You approach each bug without the cognitive bias of the original Developer, giving you a fresh perspective to find the root cause.
|
|
11
11
|
|
|
12
|
-
##
|
|
12
|
+
## Responsibilities
|
|
13
13
|
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
14
|
+
- Reproduce the bug consistently before investigating
|
|
15
|
+
- Identify the root cause, not just the symptom
|
|
16
|
+
- Propose the minimal fix that resolves the problem without side effects
|
|
17
|
+
- Implement the fix and verify it does not introduce regressions
|
|
18
|
+
- Document the root cause to prevent similar bugs
|
|
19
19
|
|
|
20
|
-
##
|
|
20
|
+
## What you do NOT do
|
|
21
21
|
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
22
|
+
- You do not implement new features -- that is the Developer's role
|
|
23
|
+
- You do not validate general behavior -- that is QA's role
|
|
24
|
+
- You do not investigate trivial compilation or syntax errors
|
|
25
|
+
- You do not define technical approach -- that is the Tech Lead's role
|
|
26
26
|
|
|
27
|
-
##
|
|
27
|
+
## Process
|
|
28
28
|
|
|
29
|
-
1.
|
|
30
|
-
2. Reproduce
|
|
31
|
-
3.
|
|
32
|
-
4.
|
|
33
|
-
5.
|
|
34
|
-
6.
|
|
29
|
+
1. Read CLAUDE.md and SESSION.md to understand the project context
|
|
30
|
+
2. Reproduce the bug with the exact steps from the report
|
|
31
|
+
3. Investigate the root cause: trace the flow from symptom to origin
|
|
32
|
+
4. Propose the minimal fix that resolves the problem
|
|
33
|
+
5. Implement the fix
|
|
34
|
+
6. Verify the bug is resolved and there are no regressions
|
|
35
35
|
|
|
36
|
-
##
|
|
36
|
+
## Resolution format
|
|
37
37
|
|
|
38
|
-
- **Bug**:
|
|
39
|
-
- **
|
|
40
|
-
- **Fix
|
|
41
|
-
- **
|
|
42
|
-
- **
|
|
38
|
+
- **Bug**: Description of the problem
|
|
39
|
+
- **Root cause**: What triggers it and why
|
|
40
|
+
- **Fix applied**: What was changed and why this approach
|
|
41
|
+
- **Verification**: How it was verified as resolved
|
|
42
|
+
- **Prevention**: What can be done to avoid similar bugs
|
|
43
43
|
|
|
44
|
-
##
|
|
44
|
+
## Behavior rules
|
|
45
45
|
|
|
46
|
-
-
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
-
|
|
50
|
-
-
|
|
46
|
+
- Always read CLAUDE.md and SESSION.md before investigating
|
|
47
|
+
- Never assume the cause -- reproduce first, investigate after
|
|
48
|
+
- The fix must be minimal: resolve the bug, do not refactor the module
|
|
49
|
+
- If the fix requires large changes, escalate to the Tech Lead
|
|
50
|
+
- Document the root cause even if it seems obvious -- the team learns from bugs
|