start-vibing 2.0.7 → 2.0.9
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/package.json
CHANGED
|
@@ -4,19 +4,62 @@ This file provides context for all agents. For user-facing rules, see `/CLAUDE.m
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## CLAUDE.md Validation (STOP HOOK ENFORCED)
|
|
8
|
+
|
|
9
|
+
The stop hook validates `/CLAUDE.md` before allowing task completion:
|
|
10
|
+
|
|
11
|
+
| Check | Requirement |
|
|
12
|
+
|-------|-------------|
|
|
13
|
+
| Character limit | Max 40,000 chars |
|
|
14
|
+
| Required sections | Last Change, 30s Overview, Stack, Architecture |
|
|
15
|
+
| Last Change | Must be updated with session info (branch, date, summary) |
|
|
16
|
+
| No stacking | Only ONE Last Change section (latest only) |
|
|
17
|
+
| Branch | Must be on main (PR merged) |
|
|
18
|
+
| Git tree | Must be clean (no uncommitted changes) |
|
|
19
|
+
|
|
20
|
+
**If CLAUDE.md exceeds 40k chars:** Compact it by removing verbose explanations, keeping critical sections.
|
|
21
|
+
|
|
22
|
+
**If not on main:** Complete PR workflow (commit, push, PR, merge, checkout main).
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
7
26
|
## System Architecture
|
|
8
27
|
|
|
9
28
|
```
|
|
10
29
|
.claude/
|
|
11
|
-
├── agents/ #
|
|
12
|
-
├── skills/ #
|
|
30
|
+
├── agents/ # 82 specialized agents in 14 categories
|
|
31
|
+
├── skills/ # 22 skill systems with cache
|
|
32
|
+
├── scripts/ # Validation scripts (validate-claude-md.ts)
|
|
13
33
|
├── config/ # Project-specific configuration
|
|
14
34
|
├── commands/ # Slash commands
|
|
15
|
-
└── hooks/ #
|
|
35
|
+
└── hooks/ # stop-validator.ts, user-prompt-submit.ts
|
|
16
36
|
```
|
|
17
37
|
|
|
18
38
|
---
|
|
19
39
|
|
|
40
|
+
## MCP Servers (MANDATORY FOR AGENTS)
|
|
41
|
+
|
|
42
|
+
All agents MUST use these MCP servers when applicable:
|
|
43
|
+
|
|
44
|
+
| Server | Purpose | Use In Agents |
|
|
45
|
+
| ------------------- | ----------------------------------------- | ---------------------------------------- |
|
|
46
|
+
| `context7` | Up-to-date library documentation | research, analyzer, tester |
|
|
47
|
+
| `sequential-thinking` | Complex problem-solving | orchestrator, analyzer, final-validator |
|
|
48
|
+
| `memory` | Persistent knowledge graph | domain-updater, commit-manager |
|
|
49
|
+
| `playwright` | Browser automation and E2E testing | tester, ui-ux-reviewer |
|
|
50
|
+
| `nextjs-devtools` | Next.js specific development tools | analyzer (Next.js projects) |
|
|
51
|
+
| `mongodb` | MongoDB database operations | tester, security-auditor |
|
|
52
|
+
|
|
53
|
+
### Agent MCP Usage Rules
|
|
54
|
+
|
|
55
|
+
- **research agent**: MUST use `context7` for library docs before recommending patterns
|
|
56
|
+
- **tester agent**: MUST use `playwright` for E2E tests
|
|
57
|
+
- **analyzer agent**: SHOULD use `context7` to verify current API patterns
|
|
58
|
+
- **domain-updater**: SHOULD use `memory` to persist patterns across sessions
|
|
59
|
+
- **ui-ux-reviewer**: MUST use `playwright` to verify UI implementations
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
20
63
|
## Configuration Files
|
|
21
64
|
|
|
22
65
|
Project-specific settings are in `.claude/config/`:
|
|
@@ -1,19 +1,31 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* Stop Validator Hook -
|
|
3
|
+
* Stop Validator Hook - Complete Validation System
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* 1. NOT on main branch (unless no source changes)
|
|
7
|
-
* 2. All modified files are documented
|
|
8
|
-
* 3. Documenter agent was executed for source changes
|
|
5
|
+
* THIS HOOK BLOCKS TASK COMPLETION IF ANY OF THESE CONDITIONS FAIL:
|
|
9
6
|
*
|
|
10
|
-
*
|
|
7
|
+
* 1. BRANCH CHECK: Must be on 'main' branch (PR must be merged)
|
|
8
|
+
* 2. GIT TREE CHECK: Working tree must be clean (no uncommitted changes)
|
|
9
|
+
* 3. CLAUDE.MD CHECK: Must be updated with session changes
|
|
10
|
+
* 4. CLAUDE.MD STRUCTURE: Must have required sections
|
|
11
|
+
* 5. CLAUDE.MD SIZE: Must not exceed 40,000 characters
|
|
12
|
+
* 6. DOCUMENTATION CHECK: All source files must be documented
|
|
13
|
+
*
|
|
14
|
+
* ERROR MESSAGES ARE DESCRIPTIVE: They guide the agent on exactly what to do.
|
|
11
15
|
*/
|
|
12
16
|
|
|
13
17
|
import { execSync } from 'child_process';
|
|
14
18
|
import { existsSync, readdirSync, readFileSync, statSync } from 'fs';
|
|
15
19
|
import { join, basename, extname } from 'path';
|
|
16
20
|
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// CONFIGURATION
|
|
23
|
+
// ============================================================================
|
|
24
|
+
|
|
25
|
+
const PROJECT_DIR = process.env['CLAUDE_PROJECT_DIR'] || process.cwd();
|
|
26
|
+
const CLAUDE_MD_PATH = join(PROJECT_DIR, 'CLAUDE.md');
|
|
27
|
+
const MAX_CHARACTERS = 40000;
|
|
28
|
+
|
|
17
29
|
const IGNORE_DIRS = new Set([
|
|
18
30
|
'.next', 'node_modules', 'dist', 'build', 'coverage',
|
|
19
31
|
'.git', '__pycache__', '.turbo', '.cache', '.husky',
|
|
@@ -32,24 +44,27 @@ const SOURCE_EXTENSIONS = new Set([
|
|
|
32
44
|
'.java', '.kt', '.swift', '.vue', '.svelte'
|
|
33
45
|
]);
|
|
34
46
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
'
|
|
38
|
-
'
|
|
39
|
-
'
|
|
47
|
+
// Required sections in CLAUDE.md
|
|
48
|
+
const REQUIRED_SECTIONS = [
|
|
49
|
+
{ pattern: /^# .+/m, name: 'Project Title (H1)' },
|
|
50
|
+
{ pattern: /^## Last Change/m, name: 'Last Change' },
|
|
51
|
+
{ pattern: /^## 30 Seconds Overview/m, name: '30 Seconds Overview' },
|
|
52
|
+
{ pattern: /^## Stack/m, name: 'Stack' },
|
|
53
|
+
{ pattern: /^## Architecture/m, name: 'Architecture' },
|
|
40
54
|
];
|
|
41
55
|
|
|
56
|
+
// ============================================================================
|
|
57
|
+
// HELPER FUNCTIONS
|
|
58
|
+
// ============================================================================
|
|
59
|
+
|
|
42
60
|
function shouldIgnoreFile(filePath: string): boolean {
|
|
43
61
|
const parts = filePath.split(/[/\\]/);
|
|
44
|
-
|
|
45
62
|
for (const part of parts) {
|
|
46
63
|
if (IGNORE_DIRS.has(part)) return true;
|
|
47
64
|
}
|
|
48
|
-
|
|
49
65
|
for (const pattern of IGNORE_PATTERNS) {
|
|
50
66
|
if (filePath.includes(pattern)) return true;
|
|
51
67
|
}
|
|
52
|
-
|
|
53
68
|
return false;
|
|
54
69
|
}
|
|
55
70
|
|
|
@@ -58,39 +73,34 @@ function isSourceFile(filePath: string): boolean {
|
|
|
58
73
|
return SOURCE_EXTENSIONS.has(ext) && !shouldIgnoreFile(filePath);
|
|
59
74
|
}
|
|
60
75
|
|
|
61
|
-
function
|
|
62
|
-
return SYSTEM_CONFIG_PATTERNS.some(pattern => filePath.includes(pattern));
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function getCurrentBranch(projectDir: string): string {
|
|
76
|
+
function getCurrentBranch(): string {
|
|
66
77
|
try {
|
|
67
|
-
|
|
68
|
-
cwd:
|
|
78
|
+
return execSync('git rev-parse --abbrev-ref HEAD', {
|
|
79
|
+
cwd: PROJECT_DIR,
|
|
69
80
|
encoding: 'utf8',
|
|
70
81
|
stdio: ['pipe', 'pipe', 'pipe']
|
|
71
|
-
});
|
|
72
|
-
return result.trim();
|
|
82
|
+
}).trim();
|
|
73
83
|
} catch {
|
|
74
84
|
return 'unknown';
|
|
75
85
|
}
|
|
76
86
|
}
|
|
77
87
|
|
|
78
|
-
function getModifiedFiles(
|
|
88
|
+
function getModifiedFiles(): string[] {
|
|
79
89
|
try {
|
|
80
90
|
const staged = execSync('git diff --name-only --cached', {
|
|
81
|
-
cwd:
|
|
91
|
+
cwd: PROJECT_DIR,
|
|
82
92
|
encoding: 'utf8',
|
|
83
93
|
stdio: ['pipe', 'pipe', 'pipe']
|
|
84
94
|
}).trim().split('\n').filter(Boolean);
|
|
85
95
|
|
|
86
96
|
const unstaged = execSync('git diff --name-only', {
|
|
87
|
-
cwd:
|
|
97
|
+
cwd: PROJECT_DIR,
|
|
88
98
|
encoding: 'utf8',
|
|
89
99
|
stdio: ['pipe', 'pipe', 'pipe']
|
|
90
100
|
}).trim().split('\n').filter(Boolean);
|
|
91
101
|
|
|
92
102
|
const untracked = execSync('git ls-files --others --exclude-standard', {
|
|
93
|
-
cwd:
|
|
103
|
+
cwd: PROJECT_DIR,
|
|
94
104
|
encoding: 'utf8',
|
|
95
105
|
stdio: ['pipe', 'pipe', 'pipe']
|
|
96
106
|
}).trim().split('\n').filter(Boolean);
|
|
@@ -103,7 +113,6 @@ function getModifiedFiles(projectDir: string): string[] {
|
|
|
103
113
|
|
|
104
114
|
function* walkDir(dir: string): Generator<string> {
|
|
105
115
|
if (!existsSync(dir)) return;
|
|
106
|
-
|
|
107
116
|
const entries = readdirSync(dir);
|
|
108
117
|
for (const entry of entries) {
|
|
109
118
|
const fullPath = join(dir, entry);
|
|
@@ -120,22 +129,20 @@ function* walkDir(dir: string): Generator<string> {
|
|
|
120
129
|
}
|
|
121
130
|
}
|
|
122
131
|
|
|
123
|
-
function searchInDocs(
|
|
132
|
+
function searchInDocs(filePath: string): boolean {
|
|
124
133
|
const fileName = basename(filePath);
|
|
125
134
|
const fileStem = basename(filePath, extname(filePath));
|
|
126
135
|
|
|
127
136
|
const docDirs = [
|
|
128
|
-
join(
|
|
129
|
-
join(
|
|
137
|
+
join(PROJECT_DIR, 'docs'),
|
|
138
|
+
join(PROJECT_DIR, '.claude', 'skills', 'codebase-knowledge', 'domains'),
|
|
130
139
|
];
|
|
131
140
|
|
|
132
141
|
for (const docDir of docDirs) {
|
|
133
142
|
if (!existsSync(docDir)) continue;
|
|
134
|
-
|
|
135
143
|
for (const docFile of walkDir(docDir)) {
|
|
136
144
|
const ext = extname(docFile);
|
|
137
145
|
if (!DOC_EXTENSIONS.has(ext)) continue;
|
|
138
|
-
|
|
139
146
|
try {
|
|
140
147
|
const content = readFileSync(docFile, 'utf8');
|
|
141
148
|
if (content.includes(fileName) || content.includes(fileStem) || content.includes(filePath)) {
|
|
@@ -146,27 +153,456 @@ function searchInDocs(projectDir: string, filePath: string): boolean {
|
|
|
146
153
|
}
|
|
147
154
|
}
|
|
148
155
|
}
|
|
149
|
-
|
|
150
156
|
return false;
|
|
151
157
|
}
|
|
152
158
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
159
|
+
// ============================================================================
|
|
160
|
+
// VALIDATION FUNCTIONS
|
|
161
|
+
// ============================================================================
|
|
162
|
+
|
|
163
|
+
interface ValidationError {
|
|
164
|
+
type: string;
|
|
165
|
+
message: string;
|
|
166
|
+
action: string;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function validateBranch(currentBranch: string, modifiedFiles: string[]): ValidationError | null {
|
|
170
|
+
const isMainBranch = currentBranch === 'main' || currentBranch === 'master';
|
|
171
|
+
|
|
172
|
+
// Case 1: On feature branch with changes - need to complete workflow
|
|
173
|
+
if (!isMainBranch && modifiedFiles.length > 0) {
|
|
174
|
+
return {
|
|
175
|
+
type: 'FEATURE_BRANCH_NOT_MERGED',
|
|
176
|
+
message: `Currently on branch '${currentBranch}' with uncommitted changes. The task cannot complete until work is merged to main.`,
|
|
177
|
+
action: `
|
|
178
|
+
================================================================================
|
|
179
|
+
COMPLETE THE GIT WORKFLOW BEFORE TASK COMPLETION
|
|
180
|
+
================================================================================
|
|
181
|
+
|
|
182
|
+
You are on branch '${currentBranch}' with ${modifiedFiles.length} modified file(s).
|
|
183
|
+
|
|
184
|
+
REQUIRED STEPS (execute in order):
|
|
185
|
+
|
|
186
|
+
1. STAGE all changes:
|
|
187
|
+
git add -A
|
|
188
|
+
|
|
189
|
+
2. COMMIT with conventional message:
|
|
190
|
+
git commit -m "feat: description of changes"
|
|
191
|
+
|
|
192
|
+
3. PUSH to remote:
|
|
193
|
+
git push -u origin ${currentBranch}
|
|
194
|
+
|
|
195
|
+
4. CREATE Pull Request:
|
|
196
|
+
gh pr create --title "Title" --body "$(cat <<'EOF'
|
|
197
|
+
## Summary
|
|
198
|
+
- What was changed
|
|
199
|
+
|
|
200
|
+
## Test plan
|
|
201
|
+
- How to verify
|
|
202
|
+
|
|
203
|
+
Generated with Claude Code
|
|
204
|
+
EOF
|
|
205
|
+
)"
|
|
206
|
+
|
|
207
|
+
5. MERGE the PR (auto-delete branch):
|
|
208
|
+
gh pr merge --merge --delete-branch
|
|
209
|
+
|
|
210
|
+
6. SWITCH to main and pull:
|
|
211
|
+
git checkout main && git pull
|
|
212
|
+
|
|
213
|
+
THEN the task can complete. The stop hook will verify main branch + clean tree.
|
|
214
|
+
================================================================================`
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Case 2: On feature branch with clean tree - just need to switch
|
|
219
|
+
if (!isMainBranch && modifiedFiles.length === 0) {
|
|
220
|
+
return {
|
|
221
|
+
type: 'NOT_ON_MAIN_BRANCH',
|
|
222
|
+
message: `Currently on branch '${currentBranch}'. Task completion requires being on 'main'.`,
|
|
223
|
+
action: `
|
|
224
|
+
================================================================================
|
|
225
|
+
SWITCH TO MAIN BRANCH
|
|
226
|
+
================================================================================
|
|
227
|
+
|
|
228
|
+
The working tree is clean but you're on branch '${currentBranch}'.
|
|
229
|
+
|
|
230
|
+
If your PR was merged:
|
|
231
|
+
git checkout main && git pull
|
|
232
|
+
|
|
233
|
+
If you still need to create/merge PR:
|
|
234
|
+
gh pr create (if not created)
|
|
235
|
+
gh pr merge --merge --delete-branch (to merge)
|
|
236
|
+
git checkout main && git pull
|
|
237
|
+
|
|
238
|
+
IMPORTANT: Task completion is BLOCKED until you are on 'main' with a clean tree.
|
|
239
|
+
================================================================================`
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Case 3: On main with changes - FORBIDDEN
|
|
244
|
+
if (isMainBranch && modifiedFiles.length > 0) {
|
|
245
|
+
const fileList = modifiedFiles.slice(0, 10).map(f => ` - ${f}`).join('\n');
|
|
246
|
+
return {
|
|
247
|
+
type: 'DIRECT_MAIN_COMMIT_FORBIDDEN',
|
|
248
|
+
message: `CRITICAL: Attempting to work directly on '${currentBranch}' branch with changes!`,
|
|
249
|
+
action: `
|
|
250
|
+
================================================================================
|
|
251
|
+
FORBIDDEN: DIRECT COMMITS TO MAIN
|
|
252
|
+
================================================================================
|
|
253
|
+
|
|
254
|
+
You have ${modifiedFiles.length} modified file(s) on main branch:
|
|
255
|
+
${fileList}${modifiedFiles.length > 10 ? '\n ... and more' : ''}
|
|
256
|
+
|
|
257
|
+
ALL work MUST be done on feature branches. This is MANDATORY.
|
|
258
|
+
|
|
259
|
+
REQUIRED STEPS:
|
|
260
|
+
|
|
261
|
+
1. CREATE a feature branch:
|
|
262
|
+
git checkout -b feature/your-feature-name
|
|
263
|
+
(or fix/, refactor/, chore/, test/ as appropriate)
|
|
264
|
+
|
|
265
|
+
2. CONTINUE your work on the new branch
|
|
266
|
+
|
|
267
|
+
3. When done, create PR to merge back to main
|
|
268
|
+
|
|
269
|
+
NEVER commit directly to main. The stop hook will BLOCK this.
|
|
270
|
+
================================================================================`
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return null; // All good - on main with clean tree
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function validateGitTree(modifiedFiles: string[]): ValidationError | null {
|
|
278
|
+
if (modifiedFiles.length === 0) return null;
|
|
279
|
+
|
|
280
|
+
const fileList = modifiedFiles.slice(0, 15).map(f => ` - ${f}`).join('\n');
|
|
281
|
+
|
|
282
|
+
return {
|
|
283
|
+
type: 'GIT_TREE_NOT_CLEAN',
|
|
284
|
+
message: `Git working tree is not clean. Found ${modifiedFiles.length} modified/untracked file(s).`,
|
|
285
|
+
action: `
|
|
286
|
+
================================================================================
|
|
287
|
+
GIT TREE MUST BE CLEAN FOR TASK COMPLETION
|
|
288
|
+
================================================================================
|
|
289
|
+
|
|
290
|
+
Modified files:
|
|
291
|
+
${fileList}${modifiedFiles.length > 15 ? '\n ... and more' : ''}
|
|
292
|
+
|
|
293
|
+
The task cannot complete with uncommitted work.
|
|
294
|
+
|
|
295
|
+
OPTIONS:
|
|
296
|
+
|
|
297
|
+
1. COMMIT the changes (recommended):
|
|
298
|
+
git add -A
|
|
299
|
+
git commit -m "type: description"
|
|
300
|
+
git push
|
|
301
|
+
|
|
302
|
+
2. STASH for later:
|
|
303
|
+
git stash push -m "WIP: description"
|
|
304
|
+
|
|
305
|
+
3. DISCARD changes (use with caution):
|
|
306
|
+
git checkout -- .
|
|
307
|
+
git clean -fd
|
|
308
|
+
|
|
309
|
+
After cleaning the tree, the stop hook will pass.
|
|
310
|
+
================================================================================`
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function validateClaudeMdExists(): ValidationError | null {
|
|
315
|
+
if (!existsSync(CLAUDE_MD_PATH)) {
|
|
316
|
+
return {
|
|
317
|
+
type: 'CLAUDE_MD_MISSING',
|
|
318
|
+
message: 'CLAUDE.md file not found at project root.',
|
|
319
|
+
action: `
|
|
320
|
+
================================================================================
|
|
321
|
+
CLAUDE.MD IS REQUIRED
|
|
322
|
+
================================================================================
|
|
323
|
+
|
|
324
|
+
The project MUST have a CLAUDE.md file at the root with these sections:
|
|
325
|
+
|
|
326
|
+
# Project Name
|
|
327
|
+
|
|
328
|
+
## Last Change
|
|
329
|
+
**Branch:** branch-name
|
|
330
|
+
**Date:** YYYY-MM-DD
|
|
331
|
+
**Summary:** What was done in this session
|
|
332
|
+
|
|
333
|
+
## 30 Seconds Overview
|
|
334
|
+
Quick description of what this project does.
|
|
335
|
+
|
|
336
|
+
## Stack
|
|
337
|
+
| Component | Technology |
|
|
338
|
+
|-----------|------------|
|
|
339
|
+
| Runtime | Bun |
|
|
340
|
+
| Language | TypeScript |
|
|
341
|
+
| Database | MongoDB |
|
|
342
|
+
|
|
343
|
+
## Architecture
|
|
344
|
+
Project structure and key directories.
|
|
345
|
+
|
|
346
|
+
CREATE this file before the task can complete.
|
|
347
|
+
================================================================================`
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
return null;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function validateClaudeMdSize(): ValidationError | null {
|
|
354
|
+
if (!existsSync(CLAUDE_MD_PATH)) return null;
|
|
355
|
+
|
|
356
|
+
const content = readFileSync(CLAUDE_MD_PATH, 'utf8');
|
|
357
|
+
if (content.length <= MAX_CHARACTERS) return null;
|
|
358
|
+
|
|
359
|
+
const excess = content.length - MAX_CHARACTERS;
|
|
360
|
+
|
|
361
|
+
return {
|
|
362
|
+
type: 'CLAUDE_MD_SIZE_EXCEEDED',
|
|
363
|
+
message: `CLAUDE.md exceeds 40,000 character limit by ${excess} characters (current: ${content.length}).`,
|
|
364
|
+
action: `
|
|
365
|
+
================================================================================
|
|
366
|
+
CLAUDE.MD MUST BE COMPACTED (MAX 40,000 CHARACTERS)
|
|
367
|
+
================================================================================
|
|
368
|
+
|
|
369
|
+
Current size: ${content.length} characters
|
|
370
|
+
Maximum allowed: ${MAX_CHARACTERS} characters
|
|
371
|
+
Excess: ${excess} characters
|
|
372
|
+
|
|
373
|
+
COMPACTION RULES (what to keep vs remove):
|
|
374
|
+
|
|
375
|
+
KEEP (critical):
|
|
376
|
+
- # Project Title
|
|
377
|
+
- ## Last Change (only the MOST RECENT)
|
|
378
|
+
- ## 30 Seconds Overview
|
|
379
|
+
- ## Stack
|
|
380
|
+
- ## Architecture
|
|
381
|
+
- ## Critical Rules
|
|
382
|
+
- ## FORBIDDEN Actions
|
|
383
|
+
- ## Quality Gates
|
|
384
|
+
|
|
385
|
+
REMOVE/CONDENSE:
|
|
386
|
+
- Verbose explanations (use bullet points)
|
|
387
|
+
- Duplicate information
|
|
388
|
+
- Old/outdated sections
|
|
389
|
+
- Long code examples (keep minimal)
|
|
390
|
+
- Multiple "Last Change" entries (keep only latest)
|
|
391
|
+
|
|
392
|
+
After editing, verify: wc -m CLAUDE.md
|
|
393
|
+
================================================================================`
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
function validateClaudeMdStructure(): ValidationError | null {
|
|
398
|
+
if (!existsSync(CLAUDE_MD_PATH)) return null;
|
|
399
|
+
|
|
400
|
+
const content = readFileSync(CLAUDE_MD_PATH, 'utf8');
|
|
401
|
+
const missingSections: string[] = [];
|
|
402
|
+
|
|
403
|
+
for (const section of REQUIRED_SECTIONS) {
|
|
404
|
+
if (!section.pattern.test(content)) {
|
|
405
|
+
missingSections.push(section.name);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
if (missingSections.length === 0) return null;
|
|
410
|
+
|
|
411
|
+
return {
|
|
412
|
+
type: 'CLAUDE_MD_MISSING_SECTIONS',
|
|
413
|
+
message: `CLAUDE.md is missing required sections: ${missingSections.join(', ')}`,
|
|
414
|
+
action: `
|
|
415
|
+
================================================================================
|
|
416
|
+
CLAUDE.MD MISSING REQUIRED SECTIONS
|
|
417
|
+
================================================================================
|
|
418
|
+
|
|
419
|
+
Missing sections:
|
|
420
|
+
${missingSections.map(s => ` - ${s}`).join('\n')}
|
|
421
|
+
|
|
422
|
+
REQUIRED STRUCTURE:
|
|
423
|
+
|
|
424
|
+
# Project Name <- H1 title
|
|
425
|
+
|
|
426
|
+
## Last Change <- ONLY the most recent change
|
|
427
|
+
**Branch:** feature/xxx
|
|
428
|
+
**Date:** YYYY-MM-DD
|
|
429
|
+
**Summary:** What was done
|
|
156
430
|
|
|
157
|
-
|
|
158
|
-
if (!isSourceFile(filePath)) continue;
|
|
431
|
+
## 30 Seconds Overview <- Quick project description
|
|
159
432
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
433
|
+
## Stack <- Technology table
|
|
434
|
+
|
|
435
|
+
## Architecture <- Project structure
|
|
436
|
+
|
|
437
|
+
ADD the missing sections before the task can complete.
|
|
438
|
+
================================================================================`
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
function validateClaudeMdLastChange(): ValidationError | null {
|
|
443
|
+
if (!existsSync(CLAUDE_MD_PATH)) return null;
|
|
444
|
+
|
|
445
|
+
const content = readFileSync(CLAUDE_MD_PATH, 'utf8');
|
|
446
|
+
const lastChangeMatch = content.match(/## Last Change\n([\s\S]*?)(?=\n## |$)/);
|
|
447
|
+
|
|
448
|
+
if (!lastChangeMatch) return null; // Covered by structure check
|
|
449
|
+
|
|
450
|
+
const lastChangeContent = lastChangeMatch[1].trim();
|
|
451
|
+
|
|
452
|
+
// Check for meaningful content
|
|
453
|
+
if (lastChangeContent.length < 50) {
|
|
454
|
+
return {
|
|
455
|
+
type: 'CLAUDE_MD_LAST_CHANGE_EMPTY',
|
|
456
|
+
message: 'The "Last Change" section exists but lacks sufficient content.',
|
|
457
|
+
action: `
|
|
458
|
+
================================================================================
|
|
459
|
+
UPDATE "LAST CHANGE" SECTION
|
|
460
|
+
================================================================================
|
|
461
|
+
|
|
462
|
+
The "## Last Change" section must contain:
|
|
463
|
+
|
|
464
|
+
**Branch:** the-branch-name-used
|
|
465
|
+
**Date:** ${new Date().toISOString().split('T')[0]}
|
|
466
|
+
**Summary:** 1-2 sentences describing what was changed/implemented
|
|
467
|
+
|
|
468
|
+
Example:
|
|
469
|
+
## Last Change
|
|
470
|
+
|
|
471
|
+
**Branch:** feature/add-auth
|
|
472
|
+
**Date:** 2025-01-05
|
|
473
|
+
**Summary:** Implemented JWT authentication with refresh tokens and session management.
|
|
474
|
+
|
|
475
|
+
IMPORTANT: This section should ONLY contain the LAST change, not a history.
|
|
476
|
+
================================================================================`
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// Check for multiple Last Change sections (stacking is forbidden)
|
|
481
|
+
const multipleChanges = content.match(/## Last Change/g);
|
|
482
|
+
if (multipleChanges && multipleChanges.length > 1) {
|
|
483
|
+
return {
|
|
484
|
+
type: 'CLAUDE_MD_STACKED_CHANGES',
|
|
485
|
+
message: `Found ${multipleChanges.length} "## Last Change" sections. Only ONE is allowed.`,
|
|
486
|
+
action: `
|
|
487
|
+
================================================================================
|
|
488
|
+
REMOVE STACKED CHANGES - KEEP ONLY THE LATEST
|
|
489
|
+
================================================================================
|
|
490
|
+
|
|
491
|
+
Rule: CLAUDE.md should only have ONE "## Last Change" section.
|
|
492
|
+
Previous changes belong in git history, not in the documentation.
|
|
493
|
+
|
|
494
|
+
Found ${multipleChanges.length} instances of "## Last Change".
|
|
495
|
+
|
|
496
|
+
ACTION: Remove all but the most recent "## Last Change" section.
|
|
497
|
+
|
|
498
|
+
This keeps the file focused and within the 40k character limit.
|
|
499
|
+
================================================================================`
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
return null;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
function validateClaudeMdUpdated(modifiedFiles: string[]): ValidationError | null {
|
|
507
|
+
// If no source files modified, no need to check
|
|
508
|
+
const sourceFiles = modifiedFiles.filter(isSourceFile);
|
|
509
|
+
if (sourceFiles.length === 0) return null;
|
|
510
|
+
|
|
511
|
+
// Check if CLAUDE.md is in the modified files
|
|
512
|
+
const claudeMdModified = modifiedFiles.some(f =>
|
|
513
|
+
f === 'CLAUDE.md' || f.endsWith('/CLAUDE.md') || f.endsWith('\\CLAUDE.md')
|
|
514
|
+
);
|
|
515
|
+
|
|
516
|
+
if (claudeMdModified) return null;
|
|
517
|
+
|
|
518
|
+
return {
|
|
519
|
+
type: 'CLAUDE_MD_NOT_UPDATED',
|
|
520
|
+
message: `${sourceFiles.length} source file(s) were modified but CLAUDE.md was not updated.`,
|
|
521
|
+
action: `
|
|
522
|
+
================================================================================
|
|
523
|
+
UPDATE CLAUDE.MD WITH SESSION CHANGES (MANDATORY)
|
|
524
|
+
================================================================================
|
|
525
|
+
|
|
526
|
+
You modified source files but did not update CLAUDE.md.
|
|
527
|
+
|
|
528
|
+
Modified source files:
|
|
529
|
+
${sourceFiles.slice(0, 10).map(f => ` - ${f}`).join('\n')}${sourceFiles.length > 10 ? '\n ... and more' : ''}
|
|
530
|
+
|
|
531
|
+
REQUIRED UPDATES TO CLAUDE.MD:
|
|
532
|
+
|
|
533
|
+
1. Update "## Last Change" section:
|
|
534
|
+
**Branch:** current-branch-name
|
|
535
|
+
**Date:** ${new Date().toISOString().split('T')[0]}
|
|
536
|
+
**Summary:** What you implemented/fixed
|
|
537
|
+
|
|
538
|
+
2. If architecture changed:
|
|
539
|
+
Update "## Architecture" section
|
|
540
|
+
|
|
541
|
+
3. If new patterns/rules were established:
|
|
542
|
+
Add to appropriate section
|
|
543
|
+
|
|
544
|
+
4. If user mentioned preferences or corrections:
|
|
545
|
+
Add as rules in relevant section
|
|
546
|
+
|
|
547
|
+
CONTEXT SYNTHESIS:
|
|
548
|
+
Think about what the user asked and what you learned.
|
|
549
|
+
Capture important decisions and patterns for the next session.
|
|
550
|
+
|
|
551
|
+
The stop hook will BLOCK until CLAUDE.md is updated.
|
|
552
|
+
================================================================================`
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
function validateDocumentation(sourceFiles: string[]): ValidationError | null {
|
|
557
|
+
if (sourceFiles.length === 0) return null;
|
|
558
|
+
|
|
559
|
+
const undocumented: string[] = [];
|
|
560
|
+
for (const filePath of sourceFiles) {
|
|
561
|
+
if (!searchInDocs(filePath)) {
|
|
163
562
|
undocumented.push(filePath);
|
|
164
563
|
}
|
|
165
564
|
}
|
|
166
565
|
|
|
167
|
-
|
|
566
|
+
if (undocumented.length === 0) return null;
|
|
567
|
+
|
|
568
|
+
const fileList = undocumented.slice(0, 15).map(f => ` - ${f}`).join('\n');
|
|
569
|
+
|
|
570
|
+
return {
|
|
571
|
+
type: 'SOURCE_FILES_NOT_DOCUMENTED',
|
|
572
|
+
message: `${undocumented.length} source file(s) are not documented.`,
|
|
573
|
+
action: `
|
|
574
|
+
================================================================================
|
|
575
|
+
DOCUMENT ALL MODIFIED SOURCE FILES (MANDATORY)
|
|
576
|
+
================================================================================
|
|
577
|
+
|
|
578
|
+
Undocumented files:
|
|
579
|
+
${fileList}${undocumented.length > 15 ? '\n ... and more' : ''}
|
|
580
|
+
|
|
581
|
+
REQUIRED ACTION:
|
|
582
|
+
|
|
583
|
+
Run the documenter agent to update documentation:
|
|
584
|
+
|
|
585
|
+
Task(subagent_type="documenter", prompt="Update documentation for all modified files")
|
|
586
|
+
|
|
587
|
+
The documenter will:
|
|
588
|
+
1. Detect changed files via git diff
|
|
589
|
+
2. Update domain files in .claude/skills/codebase-knowledge/domains/
|
|
590
|
+
3. Update docs/ as needed
|
|
591
|
+
4. Ensure all modified files are mentioned in documentation
|
|
592
|
+
|
|
593
|
+
A file is considered documented if its name appears in:
|
|
594
|
+
- docs/ folder
|
|
595
|
+
- .claude/skills/codebase-knowledge/domains/ folder
|
|
596
|
+
|
|
597
|
+
The stop hook will BLOCK until all source files are documented.
|
|
598
|
+
================================================================================`
|
|
599
|
+
};
|
|
168
600
|
}
|
|
169
601
|
|
|
602
|
+
// ============================================================================
|
|
603
|
+
// MAIN HOOK LOGIC
|
|
604
|
+
// ============================================================================
|
|
605
|
+
|
|
170
606
|
interface HookInput {
|
|
171
607
|
stop_hook_active?: boolean;
|
|
172
608
|
}
|
|
@@ -205,8 +641,6 @@ async function readStdinWithTimeout(timeoutMs: number): Promise<string> {
|
|
|
205
641
|
}
|
|
206
642
|
|
|
207
643
|
async function main(): Promise<void> {
|
|
208
|
-
const projectDir = process.env['CLAUDE_PROJECT_DIR'] || process.cwd();
|
|
209
|
-
|
|
210
644
|
let hookInput: HookInput = {};
|
|
211
645
|
try {
|
|
212
646
|
const stdin = await readStdinWithTimeout(1000);
|
|
@@ -224,122 +658,107 @@ async function main(): Promise<void> {
|
|
|
224
658
|
process.exit(0);
|
|
225
659
|
}
|
|
226
660
|
|
|
227
|
-
|
|
228
|
-
const
|
|
661
|
+
// Gather state
|
|
662
|
+
const currentBranch = getCurrentBranch();
|
|
663
|
+
const modifiedFiles = getModifiedFiles();
|
|
229
664
|
const sourceFiles = modifiedFiles.filter(isSourceFile);
|
|
230
|
-
const
|
|
665
|
+
const isMainBranch = currentBranch === 'main' || currentBranch === 'master';
|
|
666
|
+
const isCleanTree = modifiedFiles.length === 0;
|
|
231
667
|
|
|
232
|
-
|
|
668
|
+
// Run all validations
|
|
669
|
+
const errors: ValidationError[] = [];
|
|
233
670
|
|
|
234
|
-
//
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
const more = modifiedFiles.length > 15 ? '\n ... and more' : '';
|
|
671
|
+
// Validation order matters - most critical first
|
|
672
|
+
const branchError = validateBranch(currentBranch, modifiedFiles);
|
|
673
|
+
if (branchError) errors.push(branchError);
|
|
238
674
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
675
|
+
// Only check these if we're close to completion (on main or clean tree)
|
|
676
|
+
if (isMainBranch || isCleanTree) {
|
|
677
|
+
const treeError = validateGitTree(modifiedFiles);
|
|
678
|
+
if (treeError) errors.push(treeError);
|
|
679
|
+
}
|
|
243
680
|
|
|
244
|
-
|
|
245
|
-
|
|
681
|
+
const claudeMdExistsError = validateClaudeMdExists();
|
|
682
|
+
if (claudeMdExistsError) errors.push(claudeMdExistsError);
|
|
246
683
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
3. Continue your work on the new branch
|
|
251
|
-
4. Create PR to merge back to main
|
|
684
|
+
if (!claudeMdExistsError) {
|
|
685
|
+
const sizeError = validateClaudeMdSize();
|
|
686
|
+
if (sizeError) errors.push(sizeError);
|
|
252
687
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
});
|
|
256
|
-
}
|
|
688
|
+
const structureError = validateClaudeMdStructure();
|
|
689
|
+
if (structureError) errors.push(structureError);
|
|
257
690
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
const { undocumented } = validateDocumentation(projectDir, sourceFiles);
|
|
691
|
+
const lastChangeError = validateClaudeMdLastChange();
|
|
692
|
+
if (lastChangeError) errors.push(lastChangeError);
|
|
261
693
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
694
|
+
const updatedError = validateClaudeMdUpdated(modifiedFiles);
|
|
695
|
+
if (updatedError) errors.push(updatedError);
|
|
696
|
+
}
|
|
265
697
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
message: `
|
|
269
|
-
BLOCKED: ${undocumented.length} source file(s) are NOT documented!
|
|
698
|
+
const docError = validateDocumentation(sourceFiles);
|
|
699
|
+
if (docError) errors.push(docError);
|
|
270
700
|
|
|
271
|
-
|
|
272
|
-
|
|
701
|
+
// ============================================================================
|
|
702
|
+
// OUTPUT RESULTS
|
|
703
|
+
// ============================================================================
|
|
273
704
|
|
|
274
|
-
|
|
275
|
-
|
|
705
|
+
if (errors.length > 0) {
|
|
706
|
+
let output = `
|
|
707
|
+
################################################################################
|
|
708
|
+
# STOP VALIDATOR - TASK COMPLETION BLOCKED #
|
|
709
|
+
################################################################################
|
|
276
710
|
|
|
277
|
-
|
|
711
|
+
${errors.length} validation(s) failed. You MUST fix these before the task can complete.
|
|
278
712
|
|
|
279
|
-
|
|
280
|
-
1. Detect changed files via git diff
|
|
281
|
-
2. Update domain files in .claude/skills/codebase-knowledge/domains/
|
|
282
|
-
3. Update docs/CHANGELOG.md
|
|
283
|
-
4. Ensure all modified files are mentioned in documentation
|
|
713
|
+
`;
|
|
284
714
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
715
|
+
for (let i = 0; i < errors.length; i++) {
|
|
716
|
+
const err = errors[i];
|
|
717
|
+
output += `
|
|
718
|
+
--------------------------------------------------------------------------------
|
|
719
|
+
ERROR ${i + 1}/${errors.length}: ${err.type}
|
|
720
|
+
--------------------------------------------------------------------------------
|
|
290
721
|
|
|
291
|
-
if (errors.length > 0) {
|
|
292
|
-
let errorOutput = `
|
|
293
|
-
================================================================================
|
|
294
|
-
STOP VALIDATOR - BLOCKING TASK COMPLETION
|
|
295
|
-
================================================================================
|
|
296
|
-
`;
|
|
297
|
-
for (const err of errors) {
|
|
298
|
-
errorOutput += `
|
|
299
|
-
--- ${err.type} ---
|
|
300
722
|
${err.message}
|
|
723
|
+
|
|
724
|
+
${err.action}
|
|
301
725
|
`;
|
|
302
726
|
}
|
|
303
727
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
FIX
|
|
307
|
-
|
|
728
|
+
output += `
|
|
729
|
+
################################################################################
|
|
730
|
+
# FIX ALL ERRORS ABOVE BEFORE TASK CAN COMPLETE #
|
|
731
|
+
################################################################################
|
|
732
|
+
|
|
733
|
+
SYNTHESIS REMINDER:
|
|
734
|
+
Before completing, ask yourself:
|
|
735
|
+
- Did the user mention any preferences I should remember?
|
|
736
|
+
- Did I learn any patterns that should be documented?
|
|
737
|
+
- Were there any corrections I should add as rules?
|
|
738
|
+
|
|
739
|
+
Update CLAUDE.md with any learnings from this session.
|
|
308
740
|
`;
|
|
309
741
|
|
|
310
|
-
const result: HookResult = { decision: 'block', reason:
|
|
742
|
+
const result: HookResult = { decision: 'block', reason: output.trim() };
|
|
311
743
|
console.log(JSON.stringify(result));
|
|
312
744
|
process.exit(0);
|
|
313
745
|
}
|
|
314
746
|
|
|
315
747
|
// All validations passed
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
✓ ALL VALIDATIONS PASSED
|
|
321
|
-
================================================================================
|
|
748
|
+
const successOutput = `
|
|
749
|
+
################################################################################
|
|
750
|
+
# STOP VALIDATOR - ALL CHECKS PASSED #
|
|
751
|
+
################################################################################
|
|
322
752
|
|
|
323
753
|
Branch: ${currentBranch}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
MANDATORY NEXT STEP:
|
|
327
|
-
You MUST now commit, push, and create a PR:
|
|
328
|
-
|
|
329
|
-
1. git add -A
|
|
330
|
-
2. git commit with conventional commit message
|
|
331
|
-
3. git push -u origin ${currentBranch}
|
|
332
|
-
4. gh pr create to main branch
|
|
754
|
+
Tree: ${isCleanTree ? 'Clean' : `${modifiedFiles.length} modified files`}
|
|
755
|
+
CLAUDE.md: Valid
|
|
333
756
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
================================================================================
|
|
757
|
+
All validations passed. Task may complete.
|
|
758
|
+
################################################################################
|
|
337
759
|
`;
|
|
338
|
-
} else {
|
|
339
|
-
nextStepMessage = `All validations passed. Branch: ${currentBranch}, no files modified.`;
|
|
340
|
-
}
|
|
341
760
|
|
|
342
|
-
const result: HookResult = { decision: 'approve', reason:
|
|
761
|
+
const result: HookResult = { decision: 'approve', reason: successOutput.trim() };
|
|
343
762
|
console.log(JSON.stringify(result));
|
|
344
763
|
process.exit(0);
|
|
345
764
|
}
|
|
@@ -29,14 +29,18 @@ const STRICT_WORKFLOW = `
|
|
|
29
29
|
│ 4. BRANCH → Create feature/ | fix/ | refactor/ | test/ │
|
|
30
30
|
│ 5. IMPLEMENT → Follow rules + analyzer approval │
|
|
31
31
|
│ 6. DOCUMENT → Document ALL modified files (MANDATORY) │
|
|
32
|
-
│ 7.
|
|
33
|
-
│ 8.
|
|
32
|
+
│ 7. UPDATE → Update CLAUDE.md with session changes │
|
|
33
|
+
│ 8. QUALITY → typecheck + lint + test (Husky enforced) │
|
|
34
|
+
│ 9. FINISH → PR + merge to main (clean tree required) │
|
|
34
35
|
└─────────────────────────────────────────────────────────────────┘
|
|
35
36
|
|
|
36
37
|
⚠️ STOP HOOK ACTIVE - Task completion will be BLOCKED if:
|
|
37
|
-
-
|
|
38
|
-
-
|
|
39
|
-
-
|
|
38
|
+
- NOT on main branch (PR must be merged first)
|
|
39
|
+
- Git tree NOT clean (all changes must be committed)
|
|
40
|
+
- CLAUDE.md NOT updated (must reflect session changes)
|
|
41
|
+
- CLAUDE.md missing required sections (Last Change, Stack, etc.)
|
|
42
|
+
- CLAUDE.md exceeds 40,000 characters (must compact)
|
|
43
|
+
- Source files NOT documented (must run documenter agent)
|
|
40
44
|
`;
|
|
41
45
|
|
|
42
46
|
// ============================================================================
|
|
@@ -725,11 +729,36 @@ async function main(): Promise<void> {
|
|
|
725
729
|
|
|
726
730
|
const recommendedStr = bestAgents.map(([cat, agent, reason], i) => ` ${i + 1}. ${cat}/${agent} - ${reason}`).join('\n');
|
|
727
731
|
|
|
732
|
+
const claudeMdReminder = `
|
|
733
|
+
================================================================================
|
|
734
|
+
CLAUDE.MD UPDATE REQUIREMENT (MANDATORY)
|
|
735
|
+
================================================================================
|
|
736
|
+
|
|
737
|
+
Before completing ANY task, you MUST update CLAUDE.md at project root with:
|
|
738
|
+
|
|
739
|
+
1. "## Last Change" section (ONLY keep the latest, do NOT stack):
|
|
740
|
+
**Branch:** your-branch-name
|
|
741
|
+
**Date:** ${new Date().toISOString().split('T')[0]}
|
|
742
|
+
**Summary:** What you implemented/fixed
|
|
743
|
+
|
|
744
|
+
2. Update "## Architecture" if structure changed
|
|
745
|
+
|
|
746
|
+
3. Add new rules/patterns learned to appropriate sections
|
|
747
|
+
|
|
748
|
+
4. SYNTHESIZE: If user mentioned preferences or corrections, add as rules
|
|
749
|
+
|
|
750
|
+
CHARACTER LIMIT: 40,000 max. If exceeded, COMPACT the file (keep critical sections).
|
|
751
|
+
|
|
752
|
+
STOP HOOK WILL BLOCK if CLAUDE.md is not properly updated!
|
|
753
|
+
================================================================================
|
|
754
|
+
`;
|
|
755
|
+
|
|
728
756
|
const output = `
|
|
729
757
|
================================================================================
|
|
730
758
|
STRICT WORKFLOW ENFORCEMENT - UserPromptSubmit Hook
|
|
731
759
|
================================================================================
|
|
732
760
|
${STRICT_WORKFLOW}
|
|
761
|
+
${claudeMdReminder}
|
|
733
762
|
|
|
734
763
|
${isNewFeature ? '⚠️ NEW FEATURE DETECTED - RESEARCH AGENT IS MANDATORY!' : ''}
|
|
735
764
|
${isUiTask ? '⚠️ UI TASK DETECTED - SEPARATE UIs FOR MOBILE/TABLET/DESKTOP REQUIRED!' : ''}
|
package/template/CLAUDE.md
CHANGED
|
@@ -4,16 +4,47 @@
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
## Workflow
|
|
7
|
+
## Workflow (STRICT FLOW)
|
|
8
8
|
|
|
9
9
|
```
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
0. INIT TASK → Run commit-manager to REGISTER task start
|
|
11
|
+
1. TODO LIST → ALWAYS create detailed todo list from prompt
|
|
12
|
+
2. RESEARCH → Run research agent for NEW features (MANDATORY)
|
|
13
|
+
3. AUDIT → Check docs from last audit OR run fresh audit
|
|
14
|
+
4. CREATE BRANCH → feature/ | fix/ | refactor/ | test/
|
|
15
|
+
5. IMPLEMENT → Follow project rules + analyzer approval
|
|
16
|
+
6. DOCUMENT → Document ALL modified files (MANDATORY)
|
|
17
|
+
7. QUALITY GATES → Run typecheck && lint && test (Husky enforced)
|
|
18
|
+
8. FINISH → commit-manager creates PR with task summary
|
|
15
19
|
```
|
|
16
20
|
|
|
21
|
+
> **CRITICAL:** Research agent is MANDATORY for any new feature or complex bug fix.
|
|
22
|
+
> **CRITICAL:** All documentation must reference commit hashes for audit trail.
|
|
23
|
+
> **CRITICAL:** Stop hook BLOCKS task completion if files not documented.
|
|
24
|
+
> **FALLBACK:** If Task tool fails to invoke an agent, READ the agent file directly from `.claude/agents/[agent-name].md` and follow its instructions manually.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## MCP Servers (MANDATORY)
|
|
29
|
+
|
|
30
|
+
Configure these in `.mcp.json` at project root:
|
|
31
|
+
|
|
32
|
+
| Server | Purpose | When to Use |
|
|
33
|
+
| ------------------- | ----------------------------------------- | ---------------------------------------- |
|
|
34
|
+
| `context7` | Up-to-date library documentation | Before implementing with ANY library |
|
|
35
|
+
| `sequential-thinking` | Complex problem-solving | Multi-step tasks, planning |
|
|
36
|
+
| `memory` | Persistent knowledge graph | Store/recall project patterns |
|
|
37
|
+
| `playwright` | Browser automation and E2E testing | UI testing, page verification |
|
|
38
|
+
| `nextjs-devtools` | Next.js specific development tools | Next.js projects only |
|
|
39
|
+
| `mongodb` | MongoDB database operations | Database queries, schema inspection |
|
|
40
|
+
|
|
41
|
+
### Usage Rules
|
|
42
|
+
|
|
43
|
+
- **ALWAYS** use `context7` before implementing features with external libraries
|
|
44
|
+
- **ALWAYS** use `playwright` for E2E tests instead of manual browser testing
|
|
45
|
+
- **ALWAYS** check `memory` for existing patterns before creating new ones
|
|
46
|
+
- **NEVER** hardcode library APIs - query `context7` for current docs
|
|
47
|
+
|
|
17
48
|
---
|
|
18
49
|
|
|
19
50
|
## Agent System
|
|
@@ -36,6 +67,18 @@ This project uses 11 specialized AI agents:
|
|
|
36
67
|
|
|
37
68
|
---
|
|
38
69
|
|
|
70
|
+
## Stop Hook Enforcement
|
|
71
|
+
|
|
72
|
+
The Stop hook runs when Claude is about to finish and BLOCKS if:
|
|
73
|
+
|
|
74
|
+
| Violation | Action Required |
|
|
75
|
+
|-----------|-----------------|
|
|
76
|
+
| On main branch with source changes | Create feature/fix branch first |
|
|
77
|
+
| Source files not documented | Run documenter agent |
|
|
78
|
+
| Documenter not executed | Invoke documenter via Task tool |
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
39
82
|
## Configuration
|
|
40
83
|
|
|
41
84
|
Edit these files in `.claude/config/` for your project:
|
|
@@ -46,39 +89,17 @@ Edit these files in `.claude/config/` for your project:
|
|
|
46
89
|
| `quality-gates.json` | Quality check commands |
|
|
47
90
|
| `testing-config.json` | Test framework config |
|
|
48
91
|
| `security-rules.json` | Security audit rules |
|
|
49
|
-
|
|
50
|
-
---
|
|
51
|
-
|
|
52
|
-
## Quick Start
|
|
53
|
-
|
|
54
|
-
```bash
|
|
55
|
-
# 1. Start a task
|
|
56
|
-
python .claude/hooks/workflow-manager.py start-task --type feature --description "Add user authentication"
|
|
57
|
-
|
|
58
|
-
# 2. Approve files for modification
|
|
59
|
-
python .claude/hooks/workflow-manager.py approve-files --files "src/auth/*.ts"
|
|
60
|
-
|
|
61
|
-
# 3. Mark agents as executed
|
|
62
|
-
python .claude/hooks/workflow-manager.py agent-executed --agent analyzer --result approved
|
|
63
|
-
|
|
64
|
-
# 4. Run quality gates
|
|
65
|
-
python .claude/hooks/workflow-manager.py quality-gate --gate typecheck --passed true
|
|
66
|
-
|
|
67
|
-
# 5. Final validation
|
|
68
|
-
python .claude/hooks/workflow-manager.py final-validation --result approved --ready-to-commit true
|
|
69
|
-
|
|
70
|
-
# 6. Complete task
|
|
71
|
-
python .claude/hooks/workflow-manager.py complete-task --commit-hash abc123
|
|
72
|
-
```
|
|
92
|
+
| `domain-mapping.json` | File patterns to domains |
|
|
73
93
|
|
|
74
94
|
---
|
|
75
95
|
|
|
76
96
|
## Critical Rules
|
|
77
97
|
|
|
78
|
-
1. **ALWAYS
|
|
79
|
-
2. **ALWAYS
|
|
98
|
+
1. **ALWAYS use MCP servers** - Context7 for docs, Playwright for E2E
|
|
99
|
+
2. **ALWAYS start with todo list** - Track progress with TodoWrite tool
|
|
80
100
|
3. **NEVER skip agents** - Stop hook blocks incomplete workflows
|
|
81
101
|
4. **ALWAYS use conventional commits** - feat:, fix:, refactor:, docs:
|
|
102
|
+
5. **NEVER commit to main** - Create feature/fix branches
|
|
82
103
|
|
|
83
104
|
---
|
|
84
105
|
|