claude-code-scanner 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DOCUMENTATION.md +1210 -0
- package/LICENSE +21 -0
- package/README.md +306 -0
- package/bin/cli.js +305 -0
- package/package.json +43 -0
- package/template/.claude/agents/api-builder.md +64 -0
- package/template/.claude/agents/architect.md +92 -0
- package/template/.claude/agents/debugger.md +69 -0
- package/template/.claude/agents/explorer.md +71 -0
- package/template/.claude/agents/frontend.md +61 -0
- package/template/.claude/agents/infra.md +66 -0
- package/template/.claude/agents/product-owner.md +73 -0
- package/template/.claude/agents/qa-lead.md +102 -0
- package/template/.claude/agents/reviewer.md +77 -0
- package/template/.claude/agents/security.md +81 -0
- package/template/.claude/agents/team-lead.md +128 -0
- package/template/.claude/agents/tester.md +72 -0
- package/template/.claude/docs/agent-error-protocol.md +89 -0
- package/template/.claude/docs/best-practices.md +93 -0
- package/template/.claude/docs/commands-template.md +73 -0
- package/template/.claude/docs/conflict-resolution-protocol.md +82 -0
- package/template/.claude/docs/context-budget.md +54 -0
- package/template/.claude/docs/execution-metrics-protocol.md +105 -0
- package/template/.claude/docs/flow-engine.md +475 -0
- package/template/.claude/docs/smithery-setup.md +51 -0
- package/template/.claude/docs/task-record-schema.md +196 -0
- package/template/.claude/hooks/drift-detector.js +143 -0
- package/template/.claude/hooks/execution-report.js +114 -0
- package/template/.claude/hooks/notify-approval.js +30 -0
- package/template/.claude/hooks/post-compact-recovery.js +68 -0
- package/template/.claude/hooks/post-edit-format.js +43 -0
- package/template/.claude/hooks/pre-compact-save.js +94 -0
- package/template/.claude/hooks/protect-files.js +39 -0
- package/template/.claude/hooks/session-start.js +76 -0
- package/template/.claude/hooks/stop-failure-handler.js +77 -0
- package/template/.claude/hooks/tool-failure-tracker.js +54 -0
- package/template/.claude/hooks/track-file-changes.js +34 -0
- package/template/.claude/hooks/validate-bash.js +34 -0
- package/template/.claude/manifest.json +22 -0
- package/template/.claude/profiles/backend.md +34 -0
- package/template/.claude/profiles/devops.md +36 -0
- package/template/.claude/profiles/frontend.md +34 -0
- package/template/.claude/rules/context-budget.md +34 -0
- package/template/.claude/scripts/verify-setup.js +210 -0
- package/template/.claude/settings.json +154 -0
- package/template/.claude/skills/context-check/SKILL.md +112 -0
- package/template/.claude/skills/execution-report/SKILL.md +229 -0
- package/template/.claude/skills/generate-environment/SKILL.md +128 -0
- package/template/.claude/skills/generate-environment/additional-skills.md +276 -0
- package/template/.claude/skills/generate-environment/artifact-templates.md +386 -0
- package/template/.claude/skills/generate-environment/domain-agents.md +202 -0
- package/template/.claude/skills/impact-analysis/SKILL.md +17 -0
- package/template/.claude/skills/metrics/SKILL.md +19 -0
- package/template/.claude/skills/progress-report/SKILL.md +27 -0
- package/template/.claude/skills/rollback/SKILL.md +75 -0
- package/template/.claude/skills/scan-codebase/SKILL.md +59 -0
- package/template/.claude/skills/scan-codebase/deep-scan-instructions.md +101 -0
- package/template/.claude/skills/scan-codebase/tech-markers.md +87 -0
- package/template/.claude/skills/setup-smithery/SKILL.md +38 -0
- package/template/.claude/skills/sync/SKILL.md +239 -0
- package/template/.claude/skills/task-tracker/SKILL.md +40 -0
- package/template/.claude/skills/validate-setup/SKILL.md +30 -0
- package/template/.claude/skills/workflow/SKILL.md +333 -0
- package/template/.claude/templates/README.md +42 -0
- package/template/CLAUDE.md +67 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Cross-platform verification of Claude Code environment — replaces verify-setup.sh
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
const GREEN = '\x1b[32m';
|
|
7
|
+
const RED = '\x1b[31m';
|
|
8
|
+
const YELLOW = '\x1b[33m';
|
|
9
|
+
const RESET = '\x1b[0m';
|
|
10
|
+
|
|
11
|
+
let PASS = 0, FAIL = 0, WARN = 0;
|
|
12
|
+
|
|
13
|
+
function check(label, condition) {
|
|
14
|
+
if (condition) { console.log(` ${GREEN}[PASS]${RESET} ${label}`); PASS++; }
|
|
15
|
+
else { console.log(` ${RED}[FAIL]${RESET} ${label}`); FAIL++; }
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function warn(label, condition) {
|
|
19
|
+
if (condition) { console.log(` ${GREEN}[OK] ${RESET} ${label}`); }
|
|
20
|
+
else { console.log(` ${YELLOW}[WARN]${RESET} ${label}`); WARN++; }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function lineCount(filePath) {
|
|
24
|
+
try { return fs.readFileSync(filePath, 'utf-8').split('\n').length; } catch { return 999; }
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function fileContains(filePath, text) {
|
|
28
|
+
try { return fs.readFileSync(filePath, 'utf-8').includes(text); } catch { return false; }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function fileMatchesRegex(filePath, regex) {
|
|
32
|
+
try { return regex.test(fs.readFileSync(filePath, 'utf-8')); } catch { return false; }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function isValidJSON(filePath) {
|
|
36
|
+
try { JSON.parse(fs.readFileSync(filePath, 'utf-8')); return true; } catch { return false; }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function globDir(dir, ext) {
|
|
40
|
+
try { return fs.readdirSync(dir).filter(f => f.endsWith(ext)).map(f => path.join(dir, f)); } catch { return []; }
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function readFile(filePath) {
|
|
44
|
+
try { return fs.readFileSync(filePath, 'utf-8'); } catch { return ''; }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const cwd = process.cwd();
|
|
48
|
+
|
|
49
|
+
console.log('=== Claude Code Environment Verification ===\n');
|
|
50
|
+
|
|
51
|
+
// --- CLAUDE.md ---
|
|
52
|
+
console.log('--- CLAUDE.md ---');
|
|
53
|
+
const claudeMd = path.join(cwd, 'CLAUDE.md');
|
|
54
|
+
check('Exists', fs.existsSync(claudeMd));
|
|
55
|
+
check('Under 200 lines (recommended)', fs.existsSync(claudeMd) && lineCount(claudeMd) <= 200);
|
|
56
|
+
warn('Under 150 lines (optimal)', fs.existsSync(claudeMd) && lineCount(claudeMd) <= 150);
|
|
57
|
+
warn('No placeholders', fs.existsSync(claudeMd) && !fileMatchesRegex(claudeMd, /\{[^}]+\}/));
|
|
58
|
+
|
|
59
|
+
// --- Rules ---
|
|
60
|
+
console.log('--- Rules ---');
|
|
61
|
+
const rulesDir = path.join(cwd, '.claude', 'rules');
|
|
62
|
+
check('Directory exists', fs.existsSync(rulesDir));
|
|
63
|
+
for (const f of globDir(rulesDir, '.md')) {
|
|
64
|
+
const name = path.basename(f);
|
|
65
|
+
check(`${name} under 50 lines`, lineCount(f) <= 50);
|
|
66
|
+
check(`${name} has paths:`, fileContains(f, 'paths:'));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// --- Agents (12 required) ---
|
|
70
|
+
console.log('--- Agents ---');
|
|
71
|
+
const agentsDir = path.join(cwd, '.claude', 'agents');
|
|
72
|
+
const requiredAgents = [
|
|
73
|
+
'team-lead', 'architect', 'product-owner', 'qa-lead',
|
|
74
|
+
'explorer', 'reviewer', 'security', 'debugger', 'tester',
|
|
75
|
+
'frontend', 'api-builder', 'infra'
|
|
76
|
+
];
|
|
77
|
+
const readOnlyAgents = ['explorer', 'reviewer', 'security', 'architect', 'product-owner', 'qa-lead'];
|
|
78
|
+
const worktreeAgents = ['frontend', 'api-builder'];
|
|
79
|
+
|
|
80
|
+
for (const agentName of requiredAgents) {
|
|
81
|
+
const agentFile = path.join(agentsDir, `${agentName}.md`);
|
|
82
|
+
check(`${agentName}.md exists`, fs.existsSync(agentFile));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
for (const f of globDir(agentsDir, '.md')) {
|
|
86
|
+
const name = path.basename(f, '.md');
|
|
87
|
+
const content = readFile(f);
|
|
88
|
+
check(`${name} has name:`, fileMatchesRegex(f, /^name:/m));
|
|
89
|
+
check(`${name} has description:`, fileMatchesRegex(f, /^description:/m));
|
|
90
|
+
check(`${name} has memory: project`, content.includes('memory: project'));
|
|
91
|
+
check(`${name} has HANDOFF block`, content.includes('HANDOFF'));
|
|
92
|
+
check(`${name} has Limitations section`, content.includes('Limitations') || content.includes('limitations'));
|
|
93
|
+
|
|
94
|
+
if (readOnlyAgents.includes(name)) {
|
|
95
|
+
check(`${name} has permissionMode: plan`, content.includes('permissionMode: plan'));
|
|
96
|
+
check(`${name} has disallowedTools`, content.includes('disallowedTools:'));
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (worktreeAgents.includes(name)) {
|
|
100
|
+
warn(`${name} has isolation: worktree`, content.includes('isolation: worktree'));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// --- Skills ---
|
|
105
|
+
console.log('--- Skills ---');
|
|
106
|
+
const skillsDir = path.join(cwd, '.claude', 'skills');
|
|
107
|
+
if (fs.existsSync(skillsDir)) {
|
|
108
|
+
for (const d of fs.readdirSync(skillsDir, { withFileTypes: true }).filter(e => e.isDirectory())) {
|
|
109
|
+
const skillMd = path.join(skillsDir, d.name, 'SKILL.md');
|
|
110
|
+
check(`${d.name} has SKILL.md`, fs.existsSync(skillMd));
|
|
111
|
+
if (fs.existsSync(skillMd)) {
|
|
112
|
+
check(`${d.name} has name:`, fileMatchesRegex(skillMd, /^name:/m));
|
|
113
|
+
check(`${d.name} has description:`, fileMatchesRegex(skillMd, /^description:/m));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Check heavy skills have context: fork
|
|
119
|
+
const heavySkills = ['scan-codebase', 'generate-environment', 'workflow', 'task-tracker', 'impact-analysis', 'metrics', 'progress-report', 'execution-report'];
|
|
120
|
+
for (const skillName of heavySkills) {
|
|
121
|
+
const skillMd = path.join(skillsDir, skillName, 'SKILL.md');
|
|
122
|
+
if (fs.existsSync(skillMd)) {
|
|
123
|
+
check(`${skillName} has context: fork`, fileContains(skillMd, 'context: fork'));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Check workflow has disable-model-invocation and handoff protocol
|
|
128
|
+
const workflowSkill = path.join(skillsDir, 'workflow', 'SKILL.md');
|
|
129
|
+
if (fs.existsSync(workflowSkill)) {
|
|
130
|
+
check('workflow has disable-model-invocation', fileContains(workflowSkill, 'disable-model-invocation: true'));
|
|
131
|
+
check('workflow has handoff protocol', fileContains(workflowSkill, 'HANDOFF'));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// --- Settings ---
|
|
135
|
+
console.log('--- Settings ---');
|
|
136
|
+
const settingsPath = path.join(cwd, '.claude', 'settings.json');
|
|
137
|
+
check('settings.json valid JSON', fs.existsSync(settingsPath) && isValidJSON(settingsPath));
|
|
138
|
+
|
|
139
|
+
if (fs.existsSync(settingsPath) && isValidJSON(settingsPath)) {
|
|
140
|
+
const settings = JSON.parse(readFile(settingsPath));
|
|
141
|
+
check('has permissions.defaultMode', settings.permissions && settings.permissions.defaultMode);
|
|
142
|
+
check('has permissions.allow', settings.permissions && Array.isArray(settings.permissions.allow));
|
|
143
|
+
check('has permissions.deny', settings.permissions && Array.isArray(settings.permissions.deny));
|
|
144
|
+
check('has env section', settings.hasOwnProperty('env'));
|
|
145
|
+
check('has hooks section', settings.hasOwnProperty('hooks'));
|
|
146
|
+
|
|
147
|
+
// Check all hook scripts referenced in settings actually exist
|
|
148
|
+
if (settings.hooks) {
|
|
149
|
+
for (const [event, matchers] of Object.entries(settings.hooks)) {
|
|
150
|
+
for (const matcher of matchers) {
|
|
151
|
+
for (const hook of (matcher.hooks || [])) {
|
|
152
|
+
if (hook.type === 'command' && hook.command) {
|
|
153
|
+
const match = hook.command.match(/node\s+(.+\.js)/);
|
|
154
|
+
if (match) {
|
|
155
|
+
const hookFile = path.join(cwd, match[1]);
|
|
156
|
+
check(`${event} hook ${path.basename(match[1])} exists`, fs.existsSync(hookFile));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const gitignorePath = path.join(cwd, '.gitignore');
|
|
166
|
+
warn('settings.local.json in .gitignore', fs.existsSync(gitignorePath) && fileContains(gitignorePath, 'settings.local.json'));
|
|
167
|
+
|
|
168
|
+
// --- Hooks ---
|
|
169
|
+
console.log('--- Hooks ---');
|
|
170
|
+
const hooksDir = path.join(cwd, '.claude', 'hooks');
|
|
171
|
+
if (fs.existsSync(hooksDir)) {
|
|
172
|
+
for (const f of fs.readdirSync(hooksDir).filter(f => f.endsWith('.js'))) {
|
|
173
|
+
const hookPath = path.join(hooksDir, f);
|
|
174
|
+
check(`${f} exists`, fs.existsSync(hookPath));
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// --- Task Record Schema ---
|
|
179
|
+
console.log('--- Docs ---');
|
|
180
|
+
const taskSchema = path.join(cwd, '.claude', 'docs', 'task-record-schema.md');
|
|
181
|
+
if (fs.existsSync(taskSchema)) {
|
|
182
|
+
check('Task schema has Loop State section', fileContains(taskSchema, 'Loop State'));
|
|
183
|
+
check('Task schema has Handoff Log section', fileContains(taskSchema, 'Handoff Log'));
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const flowEngine = path.join(cwd, '.claude', 'docs', 'flow-engine.md');
|
|
187
|
+
if (fs.existsSync(flowEngine)) {
|
|
188
|
+
check('Flow engine has Handoff Protocol', fileContains(flowEngine, 'Handoff Protocol'));
|
|
189
|
+
check('Flow engine has Orchestration Model', fileContains(flowEngine, 'Orchestration Model'));
|
|
190
|
+
check('Flow engine documents subagent limitation', fileContains(flowEngine, 'cannot spawn other subagents'));
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// --- Context Budget ---
|
|
194
|
+
console.log('--- Context Budget ---');
|
|
195
|
+
const clLines = fs.existsSync(claudeMd) ? lineCount(claudeMd) : 999;
|
|
196
|
+
let rlLines = 0;
|
|
197
|
+
for (const f of globDir(rulesDir, '.md')) {
|
|
198
|
+
rlLines += lineCount(f);
|
|
199
|
+
}
|
|
200
|
+
console.log(` CLAUDE.md: ${clLines} lines | Rules: ${rlLines} lines | Total: ${clLines + rlLines}`);
|
|
201
|
+
check('Combined under 200 lines', (clLines + rlLines) <= 200);
|
|
202
|
+
|
|
203
|
+
// --- Summary ---
|
|
204
|
+
console.log(`\n=== PASS: ${PASS} | FAIL: ${FAIL} | WARN: ${WARN} ===`);
|
|
205
|
+
if (FAIL === 0) {
|
|
206
|
+
console.log('STATUS: ALL CHECKS PASSED');
|
|
207
|
+
} else {
|
|
208
|
+
console.log(`STATUS: ${FAIL} FAILURES — fix before using`);
|
|
209
|
+
process.exit(1);
|
|
210
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"defaultMode": "default",
|
|
4
|
+
"allow": [
|
|
5
|
+
"Bash(git status)",
|
|
6
|
+
"Bash(git diff *)",
|
|
7
|
+
"Bash(git log *)",
|
|
8
|
+
"Bash(git branch *)",
|
|
9
|
+
"Bash(git checkout -b *)"
|
|
10
|
+
],
|
|
11
|
+
"deny": [
|
|
12
|
+
"Bash(rm -rf /)",
|
|
13
|
+
"Bash(sudo *)",
|
|
14
|
+
"Bash(git push --force *)",
|
|
15
|
+
"Bash(git reset --hard)"
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
"env": {},
|
|
19
|
+
"hooks": {
|
|
20
|
+
"SessionStart": [
|
|
21
|
+
{
|
|
22
|
+
"matcher": "startup|resume|compact",
|
|
23
|
+
"hooks": [
|
|
24
|
+
{
|
|
25
|
+
"type": "command",
|
|
26
|
+
"command": "node .claude/hooks/session-start.js"
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"matcher": "startup",
|
|
32
|
+
"hooks": [
|
|
33
|
+
{
|
|
34
|
+
"type": "command",
|
|
35
|
+
"command": "node .claude/hooks/drift-detector.js",
|
|
36
|
+
"statusMessage": "Checking for environment drift..."
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
"PreToolUse": [
|
|
42
|
+
{
|
|
43
|
+
"matcher": "Edit|Write",
|
|
44
|
+
"hooks": [
|
|
45
|
+
{
|
|
46
|
+
"type": "command",
|
|
47
|
+
"command": "node .claude/hooks/protect-files.js"
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"matcher": "Bash",
|
|
53
|
+
"hooks": [
|
|
54
|
+
{
|
|
55
|
+
"type": "command",
|
|
56
|
+
"command": "node .claude/hooks/validate-bash.js"
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
],
|
|
61
|
+
"PostToolUse": [
|
|
62
|
+
{
|
|
63
|
+
"matcher": "Edit|Write",
|
|
64
|
+
"hooks": [
|
|
65
|
+
{
|
|
66
|
+
"type": "command",
|
|
67
|
+
"command": "node .claude/hooks/post-edit-format.js"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"type": "command",
|
|
71
|
+
"command": "node .claude/hooks/track-file-changes.js"
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
}
|
|
75
|
+
],
|
|
76
|
+
"PostToolUseFailure": [
|
|
77
|
+
{
|
|
78
|
+
"matcher": "",
|
|
79
|
+
"hooks": [
|
|
80
|
+
{
|
|
81
|
+
"type": "command",
|
|
82
|
+
"command": "node .claude/hooks/tool-failure-tracker.js",
|
|
83
|
+
"statusMessage": "Logging tool failure..."
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
}
|
|
87
|
+
],
|
|
88
|
+
"PreCompact": [
|
|
89
|
+
{
|
|
90
|
+
"matcher": "",
|
|
91
|
+
"hooks": [
|
|
92
|
+
{
|
|
93
|
+
"type": "command",
|
|
94
|
+
"command": "node .claude/hooks/pre-compact-save.js",
|
|
95
|
+
"statusMessage": "Saving critical state before compaction..."
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
}
|
|
99
|
+
],
|
|
100
|
+
"PostCompact": [
|
|
101
|
+
{
|
|
102
|
+
"matcher": "",
|
|
103
|
+
"hooks": [
|
|
104
|
+
{
|
|
105
|
+
"type": "command",
|
|
106
|
+
"command": "node .claude/hooks/post-compact-recovery.js",
|
|
107
|
+
"statusMessage": "Recovering workflow state..."
|
|
108
|
+
}
|
|
109
|
+
]
|
|
110
|
+
}
|
|
111
|
+
],
|
|
112
|
+
"Notification": [
|
|
113
|
+
{
|
|
114
|
+
"matcher": "permission_prompt",
|
|
115
|
+
"hooks": [
|
|
116
|
+
{
|
|
117
|
+
"type": "command",
|
|
118
|
+
"command": "node .claude/hooks/notify-approval.js"
|
|
119
|
+
}
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
],
|
|
123
|
+
"SubagentStop": [],
|
|
124
|
+
"Stop": [
|
|
125
|
+
{
|
|
126
|
+
"matcher": "",
|
|
127
|
+
"hooks": [
|
|
128
|
+
{
|
|
129
|
+
"type": "command",
|
|
130
|
+
"command": "node .claude/hooks/execution-report.js",
|
|
131
|
+
"statusMessage": "Collecting execution metrics..."
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
"type": "prompt",
|
|
135
|
+
"prompt": "MANDATORY POST-EXECUTION REPORT: Before confirming completion, you MUST generate an execution report. Do the following:\n\n1. Check if task is complete (tests pass, no lint errors, no type errors)\n2. Read the latest execution snapshot from .claude/reports/executions/\n3. Generate a summary report with:\n - SUCCESS SCORE (0-100): completeness + quality + efficiency\n - TOKEN/CONTEXT USAGE: estimate tokens used, peak context %\n - AGENT COMMUNICATION: which agents ran, handoff count, loop iterations\n - HALLUCINATION CHECK: verify all file:line refs exist, function names are real, patterns match project conventions\n - REGRESSION IMPACT: run test suite, check coverage delta, flag new failures\n4. Save the report to .claude/reports/executions/\n5. Return {\"ok\": true/false, \"score\": N, \"hallucination\": 0-3, \"regression\": 0-3, \"summary\": \"one-line\"}\n\nIf score < 50 or hallucination >= 2 or regression >= 2, set ok=false with reason.",
|
|
136
|
+
"model": "haiku"
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
}
|
|
140
|
+
],
|
|
141
|
+
"StopFailure": [
|
|
142
|
+
{
|
|
143
|
+
"matcher": "rate_limit|authentication_failed|billing_error|invalid_request|server_error|max_output_tokens",
|
|
144
|
+
"hooks": [
|
|
145
|
+
{
|
|
146
|
+
"type": "command",
|
|
147
|
+
"command": "node .claude/hooks/stop-failure-handler.js",
|
|
148
|
+
"statusMessage": "Preserving state after failure..."
|
|
149
|
+
}
|
|
150
|
+
]
|
|
151
|
+
}
|
|
152
|
+
]
|
|
153
|
+
}
|
|
154
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: context-check
|
|
3
|
+
description: Check current context usage and enforce the 60% working budget. Use between workflow phases, after heavy operations, or when context feels slow. Recommends compaction if over budget.
|
|
4
|
+
user-invocable: true
|
|
5
|
+
allowed-tools: Read, Bash, Grep, Glob
|
|
6
|
+
argument-hint: "[--compact] [--force]"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Context Check: $ARGUMENTS
|
|
10
|
+
|
|
11
|
+
## Step 1: Measure Current Context
|
|
12
|
+
|
|
13
|
+
**Important:** If running inside a `context: fork` skill (like `/workflow`), `/context` measures the FORK's context, not the parent session. This is still useful — the fork has its own context budget that must be managed.
|
|
14
|
+
|
|
15
|
+
Run the built-in context command to get actual usage:
|
|
16
|
+
```
|
|
17
|
+
/context
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Read the output and extract:
|
|
21
|
+
- **Current context %**: the primary metric (of fork or parent, depending on where you are)
|
|
22
|
+
- **Largest consumers**: what's taking the most space
|
|
23
|
+
- **Conversation history size**: how much is accumulated messages
|
|
24
|
+
|
|
25
|
+
## Step 2: Evaluate Against Budget
|
|
26
|
+
|
|
27
|
+
| Threshold | Status | Action Required |
|
|
28
|
+
|-----------|--------|----------------|
|
|
29
|
+
| Under 20% | STARTUP | Normal — plenty of room |
|
|
30
|
+
| 20-40% | GREEN | Good — working comfortably |
|
|
31
|
+
| 40-60% | YELLOW | Caution — approaching budget limit |
|
|
32
|
+
| 60-75% | ORANGE | OVER BUDGET — compact immediately |
|
|
33
|
+
| 75-90% | RED | CRITICAL — compact with focus, clear if possible |
|
|
34
|
+
| 90%+ | EMERGENCY | Auto-compaction imminent — state may be lost |
|
|
35
|
+
|
|
36
|
+
## Step 3: Context Reduction Actions
|
|
37
|
+
|
|
38
|
+
### If YELLOW (40-60%):
|
|
39
|
+
1. Check: are there large file reads in history that are no longer needed?
|
|
40
|
+
2. Check: have any non-fork skills been invoked inline?
|
|
41
|
+
3. Recommend: `/compact "focus on [current phase] for [task-id]"`
|
|
42
|
+
|
|
43
|
+
### If ORANGE (60-75%) — MANDATORY ACTION:
|
|
44
|
+
1. **Compact NOW**: `/compact "Preserve: task [id] phase [N], loop state, pending decisions. Discard: file contents, exploration results, completed phase details."`
|
|
45
|
+
2. After compaction, verify: re-read active task file to restore state
|
|
46
|
+
3. Log context pressure event in task record
|
|
47
|
+
|
|
48
|
+
### If RED (75-90%) — EMERGENCY:
|
|
49
|
+
1. **Save state**: Read active task file, note current phase and loop state
|
|
50
|
+
2. **Compact aggressively**: `/compact "ONLY preserve: task [id], current phase [N], loop counters, acceptance criteria status. Discard everything else."`
|
|
51
|
+
3. **Consider session split**: If a long workflow, start a new session for remaining phases: `claude --continue`
|
|
52
|
+
4. **Route remaining work through fork**: Use `context: fork` skills or subagents for all remaining operations
|
|
53
|
+
|
|
54
|
+
### If EMERGENCY (90%+):
|
|
55
|
+
1. Auto-compaction will fire — PreCompact hook preserves critical state
|
|
56
|
+
2. After compaction, PostCompact hook re-injects loop state, handoffs, blockers
|
|
57
|
+
3. Re-read the active task file immediately to restore full context
|
|
58
|
+
4. Consider: `/clear` and start fresh if task can resume from saved state
|
|
59
|
+
|
|
60
|
+
## Step 4: Context Optimization Recommendations
|
|
61
|
+
|
|
62
|
+
Check and report on each:
|
|
63
|
+
|
|
64
|
+
### Conversation History
|
|
65
|
+
- **Accumulated file reads**: Large files read but no longer relevant — compact will reclaim this
|
|
66
|
+
- **Agent return values**: Each agent invocation in main context adds its full output — use fork agents when possible
|
|
67
|
+
- **Tool outputs**: Bash command outputs accumulate — long outputs are especially expensive
|
|
68
|
+
|
|
69
|
+
### Loaded Resources
|
|
70
|
+
- **MCP servers**: Each server loads tool definitions on every request (~200-2k tokens each)
|
|
71
|
+
- **Rules without paths**: Rules missing `paths:` frontmatter load unconditionally
|
|
72
|
+
- **Unfork'd skills**: Skills without `context: fork` load their full body into parent context
|
|
73
|
+
|
|
74
|
+
### Optimization Actions
|
|
75
|
+
1. **Largest consumer**: Identify what's using the most context and recommend action
|
|
76
|
+
2. **Unnecessary loads**: Flag any always-loaded content that could be on-demand
|
|
77
|
+
3. **Session hygiene**: Recommend `/clear` if switching to an unrelated task
|
|
78
|
+
|
|
79
|
+
## Step 5: Log Context Pressure
|
|
80
|
+
|
|
81
|
+
If context > 60%, append to active task record:
|
|
82
|
+
```markdown
|
|
83
|
+
## Context Pressure Log
|
|
84
|
+
| Timestamp | Context % | Action Taken | Result |
|
|
85
|
+
|-----------|-----------|-------------|--------|
|
|
86
|
+
| {timestamp} | {N}% | compacted with focus on Phase {N} | reduced to {M}% |
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Output Format
|
|
90
|
+
```
|
|
91
|
+
CONTEXT CHECK RESULT
|
|
92
|
+
====================
|
|
93
|
+
Current Usage: {N}%
|
|
94
|
+
Status: {GREEN/YELLOW/ORANGE/RED/EMERGENCY}
|
|
95
|
+
Budget (60%): {WITHIN/OVER by N%}
|
|
96
|
+
|
|
97
|
+
Top Consumers:
|
|
98
|
+
1. Conversation history: ~{N}%
|
|
99
|
+
2. CLAUDE.md + rules: ~{N}%
|
|
100
|
+
3. Skill/agent metadata: ~{N}%
|
|
101
|
+
4. MCP tools: ~{N}%
|
|
102
|
+
|
|
103
|
+
Action: {NONE / COMPACT RECOMMENDED / COMPACT REQUIRED / EMERGENCY}
|
|
104
|
+
Command: {specific /compact command if needed}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Auto-Invocation
|
|
108
|
+
This skill should be called:
|
|
109
|
+
1. By `/workflow` between every phase transition
|
|
110
|
+
2. By `@team-lead` before assigning heavy work
|
|
111
|
+
3. Manually whenever responses feel slow or truncated
|
|
112
|
+
4. After any operation that reads many large files
|