hool-cli 0.7.0 → 0.7.1
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/claude/be-dev.md +9 -1
- package/agents/claude/be-tech-lead.md +8 -0
- package/agents/claude/fe-dev.md +9 -1
- package/agents/claude/fe-tech-lead.md +8 -0
- package/agents/claude/forensic.md +8 -0
- package/agents/claude/governor.md +8 -0
- package/agents/claude/qa.md +8 -0
- package/dist/adapters/adapters.test.d.ts +1 -0
- package/dist/adapters/adapters.test.js +189 -0
- package/dist/adapters/adapters.test.js.map +1 -0
- package/dist/adapters/claude-code.js +21 -11
- package/dist/adapters/claude-code.js.map +1 -1
- package/dist/core/scaffold.js +20 -0
- package/dist/core/scaffold.js.map +1 -1
- package/dist/core/scaffold.test.d.ts +1 -0
- package/dist/core/scaffold.test.js +329 -0
- package/dist/core/scaffold.test.js.map +1 -0
- package/dist/core/templates.js +2 -2
- package/dist/core/templates.js.map +1 -1
- package/dist/core/templates.test.d.ts +1 -0
- package/dist/core/templates.test.js +146 -0
- package/dist/core/templates.test.js.map +1 -0
- package/dist/e2e.test.d.ts +1 -0
- package/dist/e2e.test.js +161 -0
- package/dist/e2e.test.js.map +1 -0
- package/dist/mcps/mcps.test.d.ts +1 -0
- package/dist/mcps/mcps.test.js +110 -0
- package/dist/mcps/mcps.test.js.map +1 -0
- package/hooks/inject-pl-context.sh +22 -3
- package/hooks/suggest-compact.sh +8 -12
- package/hooks/track-prompt-count.sh +24 -22
- package/package.json +13 -3
- package/prompts/agents/05-fe-tech-lead.md +3 -0
- package/prompts/agents/06-be-tech-lead.md +3 -0
- package/prompts/agents/08-be-dev.md +4 -1
- package/prompts/agents/08-fe-dev.md +4 -1
- package/prompts/agents/10-qa.md +1 -0
- package/prompts/agents/11-forensic.md +1 -0
- package/prompts/agents/governor.md +1 -0
- package/prompts/orchestrator.md +123 -31
- package/settings/be-dev.json +17 -0
- package/settings/be-tech-lead.json +17 -0
- package/settings/fe-dev.json +17 -0
- package/settings/fe-tech-lead.json +17 -0
- package/settings/forensic.json +17 -0
- package/settings/governor.json +17 -0
- package/settings/qa.json +17 -0
package/dist/e2e.test.js
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import os from 'os';
|
|
5
|
+
import { execFile } from 'child_process';
|
|
6
|
+
import { promisify } from 'util';
|
|
7
|
+
const exec = promisify(execFile);
|
|
8
|
+
let tmpDir;
|
|
9
|
+
const cliPath = path.resolve(import.meta.dirname, '..', '..', 'cli');
|
|
10
|
+
beforeEach(async () => {
|
|
11
|
+
tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'hool-e2e-'));
|
|
12
|
+
});
|
|
13
|
+
afterEach(async () => {
|
|
14
|
+
await fs.rm(tmpDir, { recursive: true, force: true });
|
|
15
|
+
});
|
|
16
|
+
async function runHool(args) {
|
|
17
|
+
return exec('npx', ['tsx', path.join(cliPath, 'src/index.ts'), ...args], {
|
|
18
|
+
cwd: tmpDir,
|
|
19
|
+
env: { ...process.env, NO_COLOR: '1' },
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
describe('hool init (e2e)', () => {
|
|
23
|
+
it('scaffolds a web-app project with all flags', async () => {
|
|
24
|
+
const { stdout } = await runHool(['init', '-d', tmpDir, '-p', 'claude-code', '-t', 'web-app', '-m', 'interactive']);
|
|
25
|
+
expect(stdout).toContain('HOOL initialized');
|
|
26
|
+
// Verify structure
|
|
27
|
+
const ops = await fs.readdir(path.join(tmpDir, '.hool/operations'));
|
|
28
|
+
expect(ops).toContain('current-phase.md');
|
|
29
|
+
expect(ops).toContain('task-board.md');
|
|
30
|
+
expect(ops).toContain('governor-rules.md');
|
|
31
|
+
// Verify phase dirs
|
|
32
|
+
await expect(fs.stat(path.join(tmpDir, '.hool/phases/03-design/cards'))).resolves.toBeTruthy();
|
|
33
|
+
await expect(fs.stat(path.join(tmpDir, '.hool/phases/05-fe-scaffold/pages'))).resolves.toBeTruthy();
|
|
34
|
+
// Verify memory dirs
|
|
35
|
+
const memAgents = await fs.readdir(path.join(tmpDir, '.hool/memory'));
|
|
36
|
+
expect(memAgents).toHaveLength(8);
|
|
37
|
+
// Verify CLAUDE.md
|
|
38
|
+
const claudeMd = await fs.readFile(path.join(tmpDir, 'CLAUDE.md'), 'utf-8');
|
|
39
|
+
expect(claudeMd).toContain('<!-- HOOL:START -->');
|
|
40
|
+
expect(claudeMd).toContain('<!-- HOOL:END -->');
|
|
41
|
+
// Verify agents.json
|
|
42
|
+
const agents = JSON.parse(await fs.readFile(path.join(tmpDir, '.hool/agents.json'), 'utf-8'));
|
|
43
|
+
expect(agents).toHaveLength(8);
|
|
44
|
+
// Verify mcps.json
|
|
45
|
+
const mcps = JSON.parse(await fs.readFile(path.join(tmpDir, '.hool/mcps.json'), 'utf-8'));
|
|
46
|
+
expect(mcps.domain).toBe('web-app');
|
|
47
|
+
expect(mcps.servers).toHaveProperty('context7');
|
|
48
|
+
}, 30000);
|
|
49
|
+
it('scaffolds a cli-tool project skipping FE phases', async () => {
|
|
50
|
+
await runHool(['init', '-d', tmpDir, '-p', 'claude-code', '-t', 'cli-tool', '-m', 'interactive']);
|
|
51
|
+
await expect(fs.access(path.join(tmpDir, '.hool/phases/03-design'))).rejects.toThrow();
|
|
52
|
+
await expect(fs.access(path.join(tmpDir, '.hool/phases/05-fe-scaffold'))).rejects.toThrow();
|
|
53
|
+
await expect(fs.stat(path.join(tmpDir, '.hool/phases/06-be-scaffold/services'))).resolves.toBeTruthy();
|
|
54
|
+
}, 30000);
|
|
55
|
+
it('scaffolds full-hool mode', async () => {
|
|
56
|
+
await runHool(['init', '-d', tmpDir, '-p', 'claude-code', '-t', 'web-app', '-m', 'full-hool']);
|
|
57
|
+
const phase = await fs.readFile(path.join(tmpDir, '.hool/operations/current-phase.md'), 'utf-8');
|
|
58
|
+
expect(phase).toContain('full-hool');
|
|
59
|
+
const profile = await fs.readFile(path.join(tmpDir, '.hool/phases/00-init/project-profile.md'), 'utf-8');
|
|
60
|
+
expect(profile).toContain('full-hool');
|
|
61
|
+
}, 30000);
|
|
62
|
+
it('copies per-role settings to .hool/settings/', async () => {
|
|
63
|
+
await runHool(['init', '-d', tmpDir, '-p', 'claude-code', '-t', 'web-app', '-m', 'interactive']);
|
|
64
|
+
const settingsDir = path.join(tmpDir, '.hool/settings');
|
|
65
|
+
const files = await fs.readdir(settingsDir);
|
|
66
|
+
// Should have role settings but NOT claude-settings.json
|
|
67
|
+
expect(files.some(f => f.endsWith('.json'))).toBe(true);
|
|
68
|
+
expect(files).not.toContain('claude-settings.json');
|
|
69
|
+
// Each settings file should be valid JSON
|
|
70
|
+
for (const f of files) {
|
|
71
|
+
if (!f.endsWith('.json'))
|
|
72
|
+
continue;
|
|
73
|
+
const content = await fs.readFile(path.join(settingsDir, f), 'utf-8');
|
|
74
|
+
expect(() => JSON.parse(content)).not.toThrow();
|
|
75
|
+
}
|
|
76
|
+
}, 30000);
|
|
77
|
+
it('copies agent definitions to .claude/agents/', async () => {
|
|
78
|
+
await runHool(['init', '-d', tmpDir, '-p', 'claude-code', '-t', 'web-app', '-m', 'interactive']);
|
|
79
|
+
const agentsDir = path.join(tmpDir, '.claude/agents');
|
|
80
|
+
const files = await fs.readdir(agentsDir);
|
|
81
|
+
expect(files.length).toBeGreaterThan(0);
|
|
82
|
+
// All should be .md files
|
|
83
|
+
expect(files.every(f => f.endsWith('.md'))).toBe(true);
|
|
84
|
+
}, 30000);
|
|
85
|
+
it('creates .claude/settings.json with hooks', async () => {
|
|
86
|
+
await runHool(['init', '-d', tmpDir, '-p', 'claude-code', '-t', 'web-app', '-m', 'interactive']);
|
|
87
|
+
const settings = JSON.parse(await fs.readFile(path.join(tmpDir, '.claude/settings.json'), 'utf-8'));
|
|
88
|
+
expect(settings).toHaveProperty('hooks');
|
|
89
|
+
}, 30000);
|
|
90
|
+
it('creates executable hooks', async () => {
|
|
91
|
+
await runHool(['init', '-d', tmpDir, '-p', 'claude-code', '-t', 'web-app', '-m', 'interactive']);
|
|
92
|
+
const hooksDir = path.join(tmpDir, '.hool/hooks');
|
|
93
|
+
const hooks = await fs.readdir(hooksDir);
|
|
94
|
+
for (const hook of hooks) {
|
|
95
|
+
if (!hook.endsWith('.sh'))
|
|
96
|
+
continue;
|
|
97
|
+
const stat = await fs.stat(path.join(hooksDir, hook));
|
|
98
|
+
expect(stat.mode & 0o111).toBeGreaterThan(0);
|
|
99
|
+
}
|
|
100
|
+
}, 30000);
|
|
101
|
+
it('scaffolds for cursor platform', async () => {
|
|
102
|
+
await runHool(['init', '-d', tmpDir, '-p', 'cursor', '-t', 'web-app', '-m', 'interactive']);
|
|
103
|
+
const rules = await fs.readFile(path.join(tmpDir, '.cursor/rules/hool.mdc'), 'utf-8');
|
|
104
|
+
expect(rules).toContain('HOOL');
|
|
105
|
+
expect(rules).toContain('Product Lead');
|
|
106
|
+
}, 30000);
|
|
107
|
+
it('scaffolds for generic platform', async () => {
|
|
108
|
+
await runHool(['init', '-d', tmpDir, '-p', 'generic', '-t', 'web-app', '-m', 'interactive']);
|
|
109
|
+
const instructions = await fs.readFile(path.join(tmpDir, 'HOOL-INSTRUCTIONS.md'), 'utf-8');
|
|
110
|
+
expect(instructions).toContain('HOOL');
|
|
111
|
+
}, 30000);
|
|
112
|
+
});
|
|
113
|
+
describe('hool onboard (e2e)', () => {
|
|
114
|
+
it('scaffolds onboarding structure', async () => {
|
|
115
|
+
await runHool(['onboard', '-d', tmpDir, '-p', 'claude-code', '-t', 'web-app', '-m', 'interactive']);
|
|
116
|
+
const phase = await fs.readFile(path.join(tmpDir, '.hool/operations/current-phase.md'), 'utf-8');
|
|
117
|
+
expect(phase).toContain('onboarding');
|
|
118
|
+
const board = await fs.readFile(path.join(tmpDir, '.hool/operations/task-board.md'), 'utf-8');
|
|
119
|
+
expect(board).toContain('ONBOARD-001');
|
|
120
|
+
const profile = await fs.readFile(path.join(tmpDir, '.hool/phases/00-init/project-profile.md'), 'utf-8');
|
|
121
|
+
expect(profile).toContain('onboarded');
|
|
122
|
+
}, 30000);
|
|
123
|
+
});
|
|
124
|
+
describe('hool status (e2e)', () => {
|
|
125
|
+
it('shows status for an initialized project', async () => {
|
|
126
|
+
await runHool(['init', '-d', tmpDir, '-p', 'claude-code', '-t', 'web-app', '-m', 'interactive']);
|
|
127
|
+
const { stdout } = await runHool(['status', '-d', tmpDir]);
|
|
128
|
+
expect(stdout).toContain('Phase');
|
|
129
|
+
expect(stdout).toContain('Tasks');
|
|
130
|
+
expect(stdout).toContain('Bugs');
|
|
131
|
+
}, 30000);
|
|
132
|
+
it('shows error for non-HOOL directory', async () => {
|
|
133
|
+
const { stdout } = await runHool(['status', '-d', tmpDir]);
|
|
134
|
+
expect(stdout).toContain('Not a HOOL project');
|
|
135
|
+
}, 30000);
|
|
136
|
+
});
|
|
137
|
+
describe('hool mode (e2e)', () => {
|
|
138
|
+
it('shows current mode', async () => {
|
|
139
|
+
await runHool(['init', '-d', tmpDir, '-p', 'claude-code', '-t', 'web-app', '-m', 'interactive']);
|
|
140
|
+
const { stdout } = await runHool(['mode', '-d', tmpDir]);
|
|
141
|
+
expect(stdout).toContain('interactive');
|
|
142
|
+
}, 30000);
|
|
143
|
+
it('switches mode from interactive to full-hool', async () => {
|
|
144
|
+
await runHool(['init', '-d', tmpDir, '-p', 'claude-code', '-t', 'web-app', '-m', 'interactive']);
|
|
145
|
+
const { stdout } = await runHool(['mode', 'full-hool', '-d', tmpDir]);
|
|
146
|
+
expect(stdout).toContain('interactive -> full-hool');
|
|
147
|
+
const profile = await fs.readFile(path.join(tmpDir, '.hool/phases/00-init/project-profile.md'), 'utf-8');
|
|
148
|
+
expect(profile).toContain('full-hool');
|
|
149
|
+
}, 30000);
|
|
150
|
+
it('reports when already in requested mode', async () => {
|
|
151
|
+
await runHool(['init', '-d', tmpDir, '-p', 'claude-code', '-t', 'web-app', '-m', 'interactive']);
|
|
152
|
+
const { stdout } = await runHool(['mode', 'interactive', '-d', tmpDir]);
|
|
153
|
+
expect(stdout).toContain('Already in');
|
|
154
|
+
}, 30000);
|
|
155
|
+
it('rejects invalid mode', async () => {
|
|
156
|
+
await runHool(['init', '-d', tmpDir, '-p', 'claude-code', '-t', 'web-app', '-m', 'interactive']);
|
|
157
|
+
const { stdout } = await runHool(['mode', 'invalid', '-d', tmpDir]);
|
|
158
|
+
expect(stdout).toContain('Invalid mode');
|
|
159
|
+
}, 30000);
|
|
160
|
+
});
|
|
161
|
+
//# sourceMappingURL=e2e.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"e2e.test.js","sourceRoot":"","sources":["../src/e2e.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { MCP_REGISTRY, getRequiredMcps, getRequiredMcpNames } from './registry.js';
|
|
3
|
+
import { checkAndInstallMcps } from './installer.js';
|
|
4
|
+
describe('MCP_REGISTRY', () => {
|
|
5
|
+
it('contains context7, playwright, deepwiki', () => {
|
|
6
|
+
expect(MCP_REGISTRY).toHaveProperty('context7');
|
|
7
|
+
expect(MCP_REGISTRY).toHaveProperty('playwright');
|
|
8
|
+
expect(MCP_REGISTRY).toHaveProperty('deepwiki');
|
|
9
|
+
});
|
|
10
|
+
it('each entry has name, installCommand, configEntry', () => {
|
|
11
|
+
for (const [key, mcp] of Object.entries(MCP_REGISTRY)) {
|
|
12
|
+
expect(mcp.name).toBe(key);
|
|
13
|
+
expect(mcp.installCommand).toBeTruthy();
|
|
14
|
+
expect(mcp.configEntry).toHaveProperty('command');
|
|
15
|
+
expect(mcp.configEntry).toHaveProperty('args');
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
describe('getRequiredMcps', () => {
|
|
20
|
+
it('returns context7 + deepwiki + playwright for web-app', () => {
|
|
21
|
+
const mcps = getRequiredMcps('web-app');
|
|
22
|
+
const names = mcps.map(m => m.name);
|
|
23
|
+
expect(names).toContain('context7');
|
|
24
|
+
expect(names).toContain('deepwiki');
|
|
25
|
+
expect(names).toContain('playwright');
|
|
26
|
+
});
|
|
27
|
+
it('returns context7 + deepwiki for cli-tool (no playwright)', () => {
|
|
28
|
+
const mcps = getRequiredMcps('cli-tool');
|
|
29
|
+
const names = mcps.map(m => m.name);
|
|
30
|
+
expect(names).toContain('context7');
|
|
31
|
+
expect(names).toContain('deepwiki');
|
|
32
|
+
expect(names).not.toContain('playwright');
|
|
33
|
+
});
|
|
34
|
+
it('returns context7 + deepwiki + playwright for browser-game', () => {
|
|
35
|
+
const mcps = getRequiredMcps('browser-game');
|
|
36
|
+
const names = mcps.map(m => m.name);
|
|
37
|
+
expect(names).toContain('playwright');
|
|
38
|
+
});
|
|
39
|
+
it('returns context7 + deepwiki for api-only', () => {
|
|
40
|
+
const mcps = getRequiredMcps('api-only');
|
|
41
|
+
const names = mcps.map(m => m.name);
|
|
42
|
+
expect(names).toEqual(['context7', 'deepwiki']);
|
|
43
|
+
});
|
|
44
|
+
it('returns McpDefinition objects with full config', () => {
|
|
45
|
+
const mcps = getRequiredMcps('web-app');
|
|
46
|
+
for (const mcp of mcps) {
|
|
47
|
+
expect(mcp).toHaveProperty('name');
|
|
48
|
+
expect(mcp).toHaveProperty('installCommand');
|
|
49
|
+
expect(mcp).toHaveProperty('configEntry');
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
describe('getRequiredMcpNames', () => {
|
|
54
|
+
it('returns string array of MCP names', () => {
|
|
55
|
+
const names = getRequiredMcpNames('web-app');
|
|
56
|
+
expect(names).toEqual(['context7', 'deepwiki', 'playwright']);
|
|
57
|
+
});
|
|
58
|
+
it('returns context7 + deepwiki for desktop', () => {
|
|
59
|
+
expect(getRequiredMcpNames('desktop')).toEqual(['context7', 'deepwiki']);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
describe('checkAndInstallMcps', () => {
|
|
63
|
+
function createMockAdapter(installed = new Set()) {
|
|
64
|
+
return {
|
|
65
|
+
platform: 'claude-code',
|
|
66
|
+
injectInstructions: vi.fn(),
|
|
67
|
+
installMcp: vi.fn(),
|
|
68
|
+
isMcpInstalled: vi.fn(async (name) => installed.has(name)),
|
|
69
|
+
getCompletionMessage: vi.fn(() => ''),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
const config = {
|
|
73
|
+
platform: 'claude-code',
|
|
74
|
+
projectType: 'cli-tool',
|
|
75
|
+
projectDir: '/tmp/test',
|
|
76
|
+
promptsDir: '/tmp/test/prompts',
|
|
77
|
+
mode: 'interactive',
|
|
78
|
+
};
|
|
79
|
+
it('returns already-installed for pre-installed MCPs', async () => {
|
|
80
|
+
const adapter = createMockAdapter(new Set(['context7', 'deepwiki']));
|
|
81
|
+
const results = await checkAndInstallMcps(adapter, config);
|
|
82
|
+
expect(results).toHaveLength(2);
|
|
83
|
+
expect(results.every(r => r.status === 'already-installed')).toBe(true);
|
|
84
|
+
expect(adapter.installMcp).not.toHaveBeenCalled();
|
|
85
|
+
});
|
|
86
|
+
it('installs missing MCPs', async () => {
|
|
87
|
+
const adapter = createMockAdapter(new Set(['context7'])); // deepwiki missing
|
|
88
|
+
const results = await checkAndInstallMcps(adapter, config);
|
|
89
|
+
const deepwikiResult = results.find(r => r.name === 'deepwiki');
|
|
90
|
+
expect(deepwikiResult?.status).toBe('installed');
|
|
91
|
+
expect(adapter.installMcp).toHaveBeenCalledOnce();
|
|
92
|
+
});
|
|
93
|
+
it('handles install failure gracefully', async () => {
|
|
94
|
+
const adapter = createMockAdapter();
|
|
95
|
+
adapter.installMcp.mockRejectedValue(new Error('Network error'));
|
|
96
|
+
const results = await checkAndInstallMcps(adapter, config);
|
|
97
|
+
expect(results.every(r => r.status === 'failed')).toBe(true);
|
|
98
|
+
expect(results[0].error).toBe('Network error');
|
|
99
|
+
});
|
|
100
|
+
it('processes all required MCPs for project type', async () => {
|
|
101
|
+
const webConfig = { ...config, projectType: 'web-app' };
|
|
102
|
+
const adapter = createMockAdapter();
|
|
103
|
+
const results = await checkAndInstallMcps(adapter, webConfig);
|
|
104
|
+
const names = results.map(r => r.name);
|
|
105
|
+
expect(names).toContain('context7');
|
|
106
|
+
expect(names).toContain('deepwiki');
|
|
107
|
+
expect(names).toContain('playwright');
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
//# sourceMappingURL=mcps.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcps.test.js","sourceRoot":"","sources":["../../src/mcps/mcps.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,6 +4,24 @@
|
|
|
4
4
|
# Outputs JSON with additionalContext to remind the PL of its identity and state
|
|
5
5
|
|
|
6
6
|
PROJECT_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || echo '.')"
|
|
7
|
+
METRICS_FILE="$PROJECT_ROOT/.hool/operations/metrics.md"
|
|
8
|
+
|
|
9
|
+
# Ensure metrics file exists with default counters
|
|
10
|
+
if [ ! -f "$METRICS_FILE" ]; then
|
|
11
|
+
mkdir -p "$(dirname "$METRICS_FILE")"
|
|
12
|
+
cat > "$METRICS_FILE" <<'EOF'
|
|
13
|
+
# HOOL Metrics
|
|
14
|
+
- Agent dispatches: 0
|
|
15
|
+
- Tool calls: 0
|
|
16
|
+
- User prompts: 0
|
|
17
|
+
EOF
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
# Increment user prompts counter
|
|
21
|
+
CURRENT_PROMPTS=$(grep -o 'User prompts: [0-9]*' "$METRICS_FILE" | grep -o '[0-9]*')
|
|
22
|
+
CURRENT_PROMPTS=${CURRENT_PROMPTS:-0}
|
|
23
|
+
NEXT_PROMPTS=$((CURRENT_PROMPTS + 1))
|
|
24
|
+
sed -i '' "s/User prompts: ${CURRENT_PROMPTS}/User prompts: ${NEXT_PROMPTS}/" "$METRICS_FILE"
|
|
7
25
|
|
|
8
26
|
# Read current phase
|
|
9
27
|
PHASE="unknown"
|
|
@@ -80,10 +98,11 @@ if [ -f "$PROJECT_ROOT/.hool/operations/inconsistencies.md" ]; then
|
|
|
80
98
|
INCONSISTENCIES=$(grep -c '^- ' "$PROJECT_ROOT/.hool/operations/inconsistencies.md" 2>/dev/null | tr -d '\n' || echo "0")
|
|
81
99
|
fi
|
|
82
100
|
|
|
83
|
-
# Check governor dispatch count
|
|
101
|
+
# Check governor dispatch count from metrics.md
|
|
84
102
|
DISPATCH_COUNT=0
|
|
85
|
-
if [ -f "$
|
|
86
|
-
DISPATCH_COUNT=$(
|
|
103
|
+
if [ -f "$METRICS_FILE" ]; then
|
|
104
|
+
DISPATCH_COUNT=$(grep -o 'Agent dispatches: [0-9]*' "$METRICS_FILE" | grep -o '[0-9]*' || echo "0")
|
|
105
|
+
DISPATCH_COUNT=${DISPATCH_COUNT:-0}
|
|
87
106
|
fi
|
|
88
107
|
GOVERNOR_DUE=""
|
|
89
108
|
if [ "$DISPATCH_COUNT" -gt 0 ] && [ $(( DISPATCH_COUNT % 3 )) -ge 2 ]; then
|
package/hooks/suggest-compact.sh
CHANGED
|
@@ -5,27 +5,23 @@
|
|
|
5
5
|
# Strategic compaction between phases preserves better context.
|
|
6
6
|
|
|
7
7
|
PROJECT_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || echo '.')"
|
|
8
|
-
|
|
9
|
-
mkdir -p "$METRICS_DIR"
|
|
10
|
-
|
|
11
|
-
COUNTER_FILE="$METRICS_DIR/tool-call-count.txt"
|
|
8
|
+
METRICS_FILE="$PROJECT_ROOT/.hool/operations/metrics.md"
|
|
12
9
|
THRESHOLD="${HOOL_COMPACT_THRESHOLD:-50}"
|
|
13
10
|
|
|
14
|
-
# Read
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
echo "$NEXT" > "$COUNTER_FILE"
|
|
11
|
+
# Read tool call count from metrics.md (format: "- Tool calls: N")
|
|
12
|
+
COUNT=$(grep -o 'Tool calls: [0-9]*' "$METRICS_FILE" 2>/dev/null | grep -o '[0-9]*')
|
|
13
|
+
COUNT="${COUNT:-0}"
|
|
18
14
|
|
|
19
15
|
# Suggest at threshold
|
|
20
|
-
if [ "$
|
|
16
|
+
if [ "$COUNT" -eq "$THRESHOLD" ]; then
|
|
21
17
|
echo "HOOL: ${THRESHOLD} tool calls reached. Consider running /compact if you're between phases or tasks." >&2
|
|
22
18
|
fi
|
|
23
19
|
|
|
24
20
|
# Suggest every 25 calls after threshold
|
|
25
|
-
if [ "$
|
|
26
|
-
OVER=$((
|
|
21
|
+
if [ "$COUNT" -gt "$THRESHOLD" ]; then
|
|
22
|
+
OVER=$((COUNT - THRESHOLD))
|
|
27
23
|
if [ $((OVER % 25)) -eq 0 ]; then
|
|
28
|
-
echo "HOOL: ${
|
|
24
|
+
echo "HOOL: ${COUNT} tool calls. Good checkpoint for /compact if context feels stale." >&2
|
|
29
25
|
fi
|
|
30
26
|
fi
|
|
31
27
|
|
|
@@ -1,39 +1,41 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
# Hook: Track
|
|
2
|
+
# Hook: Track tool calls + agent dispatches in metrics.md, trigger governor every 3 dispatches
|
|
3
3
|
# Type: PostToolUse
|
|
4
4
|
# Outputs JSON with additionalContext when governor should run
|
|
5
5
|
|
|
6
6
|
PROJECT_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || echo '.')"
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
7
|
+
METRICS_FILE="$PROJECT_ROOT/.hool/operations/metrics.md"
|
|
8
|
+
|
|
9
|
+
# Ensure metrics file exists with default counters
|
|
10
|
+
if [ ! -f "$METRICS_FILE" ]; then
|
|
11
|
+
mkdir -p "$(dirname "$METRICS_FILE")"
|
|
12
|
+
cat > "$METRICS_FILE" <<'EOF'
|
|
13
|
+
# HOOL Metrics
|
|
14
|
+
- Agent dispatches: 0
|
|
15
|
+
- Tool calls: 0
|
|
16
|
+
- User prompts: 0
|
|
17
|
+
EOF
|
|
17
18
|
fi
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
# Increment tool calls counter
|
|
21
|
+
CURRENT_TOOLS=$(grep -o 'Tool calls: [0-9]*' "$METRICS_FILE" | grep -o '[0-9]*')
|
|
22
|
+
CURRENT_TOOLS=${CURRENT_TOOLS:-0}
|
|
23
|
+
NEXT_TOOLS=$((CURRENT_TOOLS + 1))
|
|
24
|
+
sed -i '' "s/Tool calls: ${CURRENT_TOOLS}/Tool calls: ${NEXT_TOOLS}/" "$METRICS_FILE"
|
|
23
25
|
|
|
24
|
-
#
|
|
25
|
-
# Read from stdin to check tool name
|
|
26
|
+
# Read stdin to check tool name
|
|
26
27
|
INPUT=$(cat)
|
|
27
28
|
TOOL_NAME=$(echo "$INPUT" | grep -o '"tool_name"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"tool_name"[[:space:]]*:[[:space:]]*"//' | sed 's/"$//')
|
|
28
29
|
|
|
29
30
|
if [ "$TOOL_NAME" = "Agent" ]; then
|
|
30
|
-
# Increment
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
# Increment agent dispatches counter
|
|
32
|
+
CURRENT_DISPATCHES=$(grep -o 'Agent dispatches: [0-9]*' "$METRICS_FILE" | grep -o '[0-9]*')
|
|
33
|
+
CURRENT_DISPATCHES=${CURRENT_DISPATCHES:-0}
|
|
34
|
+
NEXT_DISPATCHES=$((CURRENT_DISPATCHES + 1))
|
|
35
|
+
sed -i '' "s/Agent dispatches: ${CURRENT_DISPATCHES}/Agent dispatches: ${NEXT_DISPATCHES}/" "$METRICS_FILE"
|
|
34
36
|
|
|
35
37
|
# Check if divisible by 3
|
|
36
|
-
if [ $((
|
|
38
|
+
if [ $((NEXT_DISPATCHES % 3)) -eq 0 ]; then
|
|
37
39
|
# Output JSON to inject governor reminder into conversation
|
|
38
40
|
cat <<'JSONEOF'
|
|
39
41
|
{
|
package/package.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hool-cli",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "Agent-Driven SDLC — scaffold and configure HOOL for any project",
|
|
5
5
|
"bin": {
|
|
6
6
|
"hool": "./dist/index.js"
|
|
7
7
|
},
|
|
8
8
|
"scripts": {
|
|
9
9
|
"build": "tsc",
|
|
10
|
+
"test": "vitest run",
|
|
11
|
+
"test:watch": "vitest",
|
|
10
12
|
"dev": "tsx src/index.ts",
|
|
11
13
|
"prepublishOnly": "npm run build && rm -rf ./prompts ./agents ./rules ./hooks ./settings && cp -R ../hool-mini/prompts ./prompts && cp -R ../hool-mini/agents ./agents && cp -R ../hool-mini/rules ./rules && cp -R ../hool-mini/hooks ./hooks && cp -R ../hool-mini/settings ./settings"
|
|
12
14
|
},
|
|
@@ -27,7 +29,8 @@
|
|
|
27
29
|
"devDependencies": {
|
|
28
30
|
"@types/node": "^20.11.0",
|
|
29
31
|
"tsx": "^4.7.0",
|
|
30
|
-
"typescript": "^5.4.0"
|
|
32
|
+
"typescript": "^5.4.0",
|
|
33
|
+
"vitest": "^4.0.18"
|
|
31
34
|
},
|
|
32
35
|
"type": "module",
|
|
33
36
|
"license": "MIT",
|
|
@@ -35,7 +38,14 @@
|
|
|
35
38
|
"type": "git",
|
|
36
39
|
"url": "git+https://github.com/the-wise-agents/hool.git"
|
|
37
40
|
},
|
|
38
|
-
"keywords": [
|
|
41
|
+
"keywords": [
|
|
42
|
+
"agent",
|
|
43
|
+
"sdlc",
|
|
44
|
+
"ai",
|
|
45
|
+
"cli",
|
|
46
|
+
"scaffold",
|
|
47
|
+
"autonomous"
|
|
48
|
+
],
|
|
39
49
|
"engines": {
|
|
40
50
|
"node": ">=18"
|
|
41
51
|
}
|
|
@@ -156,6 +156,9 @@ How logging works. Where logs go. How to read them.
|
|
|
156
156
|
- Code inconsistency found -> write to .hool/operations/inconsistencies.md with INC-XXX format
|
|
157
157
|
- Doc inconsistency found (spec says X, contract says Y) -> escalate to Product Lead via .hool/operations/inconsistencies.md
|
|
158
158
|
|
|
159
|
+
## Forbidden Actions
|
|
160
|
+
- NEVER run git commands (add, commit, push, etc.) — the Product Lead commits your work after you return
|
|
161
|
+
|
|
159
162
|
## Work Log
|
|
160
163
|
### Tags
|
|
161
164
|
- [ARCH-FE] — FE architectural decision -> best-practices.md
|
|
@@ -177,6 +177,9 @@ Order matters. List in execution order:
|
|
|
177
177
|
- Code inconsistency found -> write to .hool/operations/inconsistencies.md with INC-XXX format
|
|
178
178
|
- Doc inconsistency found (spec says X, contract says Y) -> escalate to Product Lead via .hool/operations/inconsistencies.md
|
|
179
179
|
|
|
180
|
+
## Forbidden Actions
|
|
181
|
+
- NEVER run git commands (add, commit, push, etc.) — the Product Lead commits your work after you return
|
|
182
|
+
|
|
180
183
|
## Work Log
|
|
181
184
|
### Tags
|
|
182
185
|
- [ARCH-BE] — BE architectural decision -> best-practices.md
|
|
@@ -58,7 +58,7 @@ If you believe your own process or rules should change based on experience, esca
|
|
|
58
58
|
5. **Logs**: Every request, DB query, and error gets a log statement.
|
|
59
59
|
6. **Contracts**: Your API responses MUST match .hool/phases/04-architecture/contracts/ exactly. Field names, types, status codes — zero deviation.
|
|
60
60
|
7. **Schema**: Your queries MUST work with .hool/phases/04-architecture/schema.md. Never modify schema without logging an inconsistency.
|
|
61
|
-
8. **
|
|
61
|
+
8. **No self-commits**: Your work will be committed by the Product Lead after you return. Focus on the implementation, not version control.
|
|
62
62
|
9. **Consistency gate**: Before implementing, cross-check your task against contracts, schema, and spec. If you find ANY inconsistency between docs, DO NOT proceed — log to .hool/operations/inconsistencies.md.
|
|
63
63
|
|
|
64
64
|
## Test Execution Requirement (MANDATORY)
|
|
@@ -133,6 +133,9 @@ logger.info('query result:', result) // log the shape, not the data (PII risk
|
|
|
133
133
|
- Need a schema change -> DON'T make it. Log to .hool/operations/inconsistencies.md for BE Tech Lead to review
|
|
134
134
|
- Architecture seems wrong -> DON'T change it. Log to .hool/operations/inconsistencies.md for BE Tech Lead to review
|
|
135
135
|
|
|
136
|
+
## Forbidden Actions
|
|
137
|
+
- NEVER run git commands (add, commit, push, etc.) — the Product Lead commits your work after you return
|
|
138
|
+
|
|
136
139
|
## Work Log
|
|
137
140
|
### Tags
|
|
138
141
|
- [BE-IMPL] — endpoint/service implemented
|
|
@@ -56,7 +56,7 @@ If you believe your own process or rules should change based on experience, esca
|
|
|
56
56
|
5. **Logs**: Every significant user action and API call gets a log statement.
|
|
57
57
|
6. **Design fidelity**: Your UI MUST match .hool/phases/03-design/cards/. Compare visually.
|
|
58
58
|
7. **Contracts**: Your API calls MUST use the shapes from .hool/phases/04-architecture/contracts/ exactly.
|
|
59
|
-
8. **
|
|
59
|
+
8. **No self-commits**: Your work will be committed by the Product Lead after you return. Focus on the implementation, not version control.
|
|
60
60
|
9. **Consistency gate**: Before implementing, cross-check your task against contracts, design cards, and spec. If you find ANY inconsistency between docs, DO NOT proceed — log to .hool/operations/inconsistencies.md.
|
|
61
61
|
|
|
62
62
|
## Test Execution Requirement (MANDATORY)
|
|
@@ -122,6 +122,9 @@ logger.info('useEffect fired') // use React DevTools
|
|
|
122
122
|
- Design seems wrong -> DON'T change design. Log to .hool/operations/inconsistencies.md for FE Tech Lead to review
|
|
123
123
|
- Need a BE endpoint that doesn't exist -> DON'T build it. Log to .hool/operations/inconsistencies.md for FE Tech Lead to review
|
|
124
124
|
|
|
125
|
+
## Forbidden Actions
|
|
126
|
+
- NEVER run git commands (add, commit, push, etc.) — the Product Lead commits your work after you return
|
|
127
|
+
|
|
125
128
|
## Work Log
|
|
126
129
|
### Tags
|
|
127
130
|
- [FE-IMPL] — component/page implemented
|
package/prompts/agents/10-qa.md
CHANGED
|
@@ -264,6 +264,7 @@ Log the score in your work log: `[QA-SCORE] [total]/100 — [verdict]`
|
|
|
264
264
|
- Don't review code quality. That's the Tech Lead's job.
|
|
265
265
|
- Don't suggest architectural changes.
|
|
266
266
|
- Don't modify source code.
|
|
267
|
+
- Don't run git commands (add, commit, push, etc.) — the Product Lead commits your work after you return.
|
|
267
268
|
|
|
268
269
|
## MCP Tools Available
|
|
269
270
|
- playwright: E2E testing, screenshot capture, browser automation
|
|
@@ -108,6 +108,7 @@ Don't fabricate a root cause. Honesty saves time.
|
|
|
108
108
|
- Don't apply fixes — document them for devs.
|
|
109
109
|
- Don't refactor surrounding code.
|
|
110
110
|
- Don't make architectural recommendations.
|
|
111
|
+
- Don't run git commands (add, commit, push, etc.) — the Product Lead commits your work after you return.
|
|
111
112
|
|
|
112
113
|
## MCP Tools Available
|
|
113
114
|
- playwright: reproduce UI bugs in browser
|
|
@@ -32,6 +32,7 @@ Agents self-enforce rules, but self-enforcement fails (as observed: Product Lead
|
|
|
32
32
|
- **NEVER** remove or modify existing entries in `.hool/operations/governor-rules.md` — append only (unless a rule is provably wrong, in which case escalate to human)
|
|
33
33
|
- **NEVER** edit application code (`src/`, `tests/`)
|
|
34
34
|
- **NEVER** modify `.hool/operations/task-board.md` or `.hool/operations/current-phase.md` — that's the Product Lead's job
|
|
35
|
+
- **NEVER** run git commands (add, commit, push, etc.) — the Product Lead commits your work after you return
|
|
35
36
|
|
|
36
37
|
## Audit Process
|
|
37
38
|
|