@devrik-tools/claude-gates 0.7.2 → 0.9.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/.claude-plugin/marketplace.json +3 -3
- package/README.es.md +129 -11
- package/README.md +120 -10
- package/cli/doctor.mjs +132 -0
- package/cli/evidence.mjs +78 -0
- package/cli/hooks-manifest.mjs +89 -0
- package/cli/index.mjs +124 -6
- package/cli/init.mjs +97 -3
- package/cli/log.mjs +70 -0
- package/cli/materialize.mjs +36 -2
- package/cli/registry.mjs +12 -1
- package/cli/selection.mjs +18 -0
- package/cli/smoke-fixtures.json +159 -25
- package/cli/task.mjs +104 -11
- package/cli/toggle.mjs +125 -0
- package/package.json +4 -3
- package/plugins/gates/.claude-plugin/plugin.json +1 -1
- package/plugins/gates/hooks/doctor.mjs +47 -1
- package/plugins/gates/hooks/gates/atomic-commit/index.mjs +92 -119
- package/plugins/gates/hooks/gates/audit-before-build/index.mjs +101 -66
- package/plugins/gates/hooks/gates/autonomous-mode/index.mjs +8 -8
- package/plugins/gates/hooks/gates/autonomous-mode/stop.mjs +13 -64
- package/plugins/gates/hooks/gates/bash-commands/index.mjs +186 -163
- package/plugins/gates/hooks/gates/block-remote-publish/index.mjs +100 -101
- package/plugins/gates/hooks/gates/brief-approved/index.mjs +71 -140
- package/plugins/gates/hooks/gates/brief-before-delegate/index.mjs +56 -137
- package/plugins/gates/hooks/gates/capability-map/index.mjs +280 -506
- package/plugins/gates/hooks/gates/circuit-breaker/index.mjs +94 -215
- package/plugins/gates/hooks/gates/circuit-breaker/track.mjs +285 -0
- package/plugins/gates/hooks/gates/dependency-skills/index.mjs +127 -46
- package/plugins/gates/hooks/gates/diagnosis-before-patch/index.mjs +81 -19
- package/plugins/gates/hooks/gates/engram-first/index.mjs +41 -0
- package/plugins/gates/hooks/gates/engram-first/session-start.mjs +64 -0
- package/plugins/gates/hooks/gates/engram-first/shared.mjs +90 -0
- package/plugins/gates/hooks/gates/engram-first/stop.mjs +23 -0
- package/plugins/gates/hooks/gates/engram-first/track.mjs +97 -0
- package/plugins/gates/hooks/gates/feature-catalog/index.mjs +156 -50
- package/plugins/gates/hooks/gates/force-parallel/index.mjs +53 -95
- package/plugins/gates/hooks/gates/forge-flow/index.mjs +51 -83
- package/plugins/gates/hooks/gates/implementation-pipeline/index.mjs +40 -80
- package/plugins/gates/hooks/gates/intent-flow/index.mjs +23 -149
- package/plugins/gates/hooks/gates/library-docs/index.mjs +338 -0
- package/plugins/gates/hooks/gates/library-docs/track.mjs +95 -0
- package/plugins/gates/hooks/gates/lint-commit/index.mjs +88 -97
- package/plugins/gates/hooks/gates/mandatory-flow/index.mjs +48 -95
- package/plugins/gates/hooks/gates/neutral-spanish/index.mjs +69 -31
- package/plugins/gates/hooks/gates/never-assume/index.mjs +23 -18
- package/plugins/gates/hooks/gates/no-blocking/index.mjs +127 -86
- package/plugins/gates/hooks/gates/no-coauthor/index.mjs +108 -88
- package/plugins/gates/hooks/gates/no-explanatory-comments/index.mjs +281 -0
- package/plugins/gates/hooks/gates/no-lint-suppression/index.mjs +170 -110
- package/plugins/gates/hooks/gates/no-memory-dependency/index.mjs +46 -77
- package/plugins/gates/hooks/gates/no-reconfirm/index.mjs +85 -47
- package/plugins/gates/hooks/gates/no-trivial-scripts/index.mjs +114 -0
- package/plugins/gates/hooks/gates/protected-paths/index.mjs +137 -90
- package/plugins/gates/hooks/gates/recurrence-lock/index.mjs +95 -51
- package/plugins/gates/hooks/gates/require-monitor/index.mjs +126 -0
- package/plugins/gates/hooks/gates/require-task-split/index.mjs +88 -0
- package/plugins/gates/hooks/gates/reuse-before-build/index.mjs +72 -216
- package/plugins/gates/hooks/gates/risk-level/index.mjs +51 -204
- package/plugins/gates/hooks/gates/root-cause-first/index.mjs +34 -17
- package/plugins/gates/hooks/gates/root-whitelist/index.mjs +160 -95
- package/plugins/gates/hooks/gates/rule-skill-autodiscovery/index.mjs +196 -97
- package/plugins/gates/hooks/gates/sdd-specs/index.mjs +90 -143
- package/plugins/gates/hooks/gates/staged-lint/index.mjs +98 -106
- package/plugins/gates/hooks/gates/stop-pending/index.mjs +47 -148
- package/plugins/gates/hooks/gates/test-after-implementation/index.mjs +78 -68
- package/plugins/gates/hooks/gates/test-matrix/index.mjs +53 -88
- package/plugins/gates/hooks/gates/tool-map/index.mjs +80 -110
- package/plugins/gates/hooks/hooks.json +152 -42
- package/plugins/gates/hooks/lib/config.mjs +6 -3
- package/plugins/gates/hooks/lib/delegation.mjs +352 -0
- package/plugins/gates/hooks/lib/gate-log.mjs +141 -0
- package/plugins/gates/hooks/lib/git.mjs +262 -0
- package/plugins/gates/hooks/lib/hook-io.mjs +451 -83
- package/plugins/gates/hooks/lib/session-state.mjs +150 -0
- package/plugins/gates/hooks/lib/signals.mjs +18 -13
- package/plugins/gates/hooks/lib/testing.mjs +148 -0
- package/plugins/gates/hooks/lib/tools.mjs +144 -0
- package/plugins/tasks/.claude-plugin/plugin.json +1 -1
- package/plugins/tasks/hooks/lib/task-store.mjs +12 -6
- package/plugins/tasks/hooks/register-requests.mjs +37 -10
- package/registry.json +249 -38
|
@@ -1,20 +1,12 @@
|
|
|
1
|
-
// tool-map —
|
|
2
|
-
//
|
|
3
|
-
// tool
|
|
4
|
-
// .
|
|
5
|
-
//
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
// it could not record, so a silent write failure does not go unnoticed.
|
|
11
|
-
//
|
|
12
|
-
// ── What a project can configure (params) ───────────────────────────────────────────
|
|
13
|
-
// toolMapFile path to the per-project tool map, relative to the project root.
|
|
14
|
-
// Default .ai/tool-map.json.
|
|
15
|
-
|
|
16
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
17
|
-
import { dirname, extname, join } from 'node:path';
|
|
1
|
+
// tool-map — the write half of the discovery pair (reuse-before-build reads). When a tool
|
|
2
|
+
// is created WITH its audit declared, the tool and that audit line are recorded in the
|
|
3
|
+
// project's tool map so the discovery is never repeated. Never denies; warns once when it
|
|
4
|
+
// cannot record. What counts as a tool and as an audit line is the same lib definition
|
|
5
|
+
// reuse-before-build uses, so the map records exactly what the read half accepts.
|
|
6
|
+
|
|
7
|
+
import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
8
|
+
import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
|
|
9
|
+
import { projectRootOf, readJsonOrNull } from '../../lib/config.mjs';
|
|
18
10
|
import {
|
|
19
11
|
runGate,
|
|
20
12
|
warn,
|
|
@@ -22,6 +14,13 @@ import {
|
|
|
22
14
|
writtenContentOf,
|
|
23
15
|
writtenPathOf,
|
|
24
16
|
} from '../../lib/hook-io.mjs';
|
|
17
|
+
import {
|
|
18
|
+
DEFAULT_TOOL_EXTENSIONS,
|
|
19
|
+
DEFAULT_TOOL_FOLDERS,
|
|
20
|
+
DEFAULT_TOOL_NAME_PATTERNS,
|
|
21
|
+
hasAuditEvidence,
|
|
22
|
+
isToolPath,
|
|
23
|
+
} from '../../lib/tools.mjs';
|
|
25
24
|
|
|
26
25
|
const GATE_ID = 'tool-map';
|
|
27
26
|
const CONFIG_KEY = 'maintainToolMap';
|
|
@@ -30,107 +29,73 @@ const DEFAULT_TOOL_MAP_FILE = join('.ai', 'tool-map.json');
|
|
|
30
29
|
const JSON_INDENT = 2;
|
|
31
30
|
const MAX_AUDIT_LENGTH = 300;
|
|
32
31
|
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
'.jsx',
|
|
44
|
-
'.vue',
|
|
45
|
-
'.py',
|
|
46
|
-
'.sh',
|
|
47
|
-
'.ps1',
|
|
48
|
-
'.rb',
|
|
49
|
-
'.go',
|
|
50
|
-
]);
|
|
51
|
-
const TOOL_FOLDERS = [
|
|
52
|
-
'scripts/',
|
|
53
|
-
'hooks/',
|
|
54
|
-
'tools/',
|
|
55
|
-
'gates/',
|
|
56
|
-
'lib/',
|
|
57
|
-
'libs/',
|
|
58
|
-
'utils/',
|
|
59
|
-
'util/',
|
|
60
|
-
'helpers/',
|
|
61
|
-
'helper/',
|
|
62
|
-
'composables/',
|
|
63
|
-
'components/',
|
|
64
|
-
'services/',
|
|
65
|
-
'shared/',
|
|
66
|
-
'common/',
|
|
67
|
-
];
|
|
68
|
-
|
|
69
|
-
// Phrases that mark a line as the author's audit statement. Matched against one line at a
|
|
70
|
-
// time (no wrapping `.*`, which backtracks): the matching line is captured whole.
|
|
71
|
-
const AUDIT_PHRASE_PATTERN =
|
|
72
|
-
/(already exists|no existing tool|there is no plugin|audited|nothing does this|justification:)/i;
|
|
32
|
+
// Same rule as reuse-before-build: a map path outside the project root is ignored.
|
|
33
|
+
function toolMapPathFor(root, toolMapFile) {
|
|
34
|
+
const resolved = resolve(root, String(toolMapFile || DEFAULT_TOOL_MAP_FILE));
|
|
35
|
+
const relativePath = relative(root, resolved);
|
|
36
|
+
const inside =
|
|
37
|
+
relativePath !== '' &&
|
|
38
|
+
!relativePath.startsWith('..') &&
|
|
39
|
+
!isAbsolute(relativePath);
|
|
40
|
+
return inside ? resolved : join(root, DEFAULT_TOOL_MAP_FILE);
|
|
41
|
+
}
|
|
73
42
|
|
|
74
|
-
/** The first line of `content` that states an audit, trimmed — or null when none does. */
|
|
75
43
|
function auditLineOf(content) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
44
|
+
return content
|
|
45
|
+
.split('\n')
|
|
46
|
+
.map((line) => line.trim())
|
|
47
|
+
.find((line) => hasAuditEvidence(line));
|
|
80
48
|
}
|
|
81
49
|
|
|
82
|
-
function
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
const parent = dirname(current);
|
|
87
|
-
if (parent === current) return null;
|
|
88
|
-
current = parent;
|
|
89
|
-
}
|
|
50
|
+
function normalizePath(path) {
|
|
51
|
+
return String(path ?? '')
|
|
52
|
+
.replace(/\\/g, '/')
|
|
53
|
+
.replace(/^\.\//, '');
|
|
90
54
|
}
|
|
91
55
|
|
|
92
|
-
function
|
|
93
|
-
const
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
);
|
|
97
|
-
return (
|
|
98
|
-
inToolFolder && EXECUTABLE_EXTENSIONS.has(extname(filePath).toLowerCase())
|
|
99
|
-
);
|
|
56
|
+
function rootRelativePath(root, rawPath) {
|
|
57
|
+
const absolute = isAbsolute(rawPath) ? rawPath : join(root, rawPath);
|
|
58
|
+
const relativePath = normalizePath(relative(root, absolute));
|
|
59
|
+
return relativePath.startsWith('..') ? normalizePath(rawPath) : relativePath;
|
|
100
60
|
}
|
|
101
61
|
|
|
102
62
|
function readMap(path) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
const parsed = JSON.parse(readFileSync(path, 'utf8'));
|
|
106
|
-
return Array.isArray(parsed.tools) ? parsed : { tools: [] };
|
|
107
|
-
} catch {
|
|
108
|
-
return { tools: [] };
|
|
109
|
-
}
|
|
63
|
+
const parsed = readJsonOrNull(path);
|
|
64
|
+
return Array.isArray(parsed?.tools) ? parsed : { tools: [] };
|
|
110
65
|
}
|
|
111
66
|
|
|
112
|
-
|
|
113
|
-
|
|
67
|
+
// The file being recorded does not exist yet at PreToolUse time, so it is exempt from
|
|
68
|
+
// the prune; every other entry must still point at a real file.
|
|
69
|
+
function recordTool(root, mapPath, toolPath, auditLine) {
|
|
114
70
|
const map = readMap(mapPath);
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
path: normalizedPath,
|
|
119
|
-
audit: auditLine.slice(0, MAX_AUDIT_LENGTH),
|
|
120
|
-
recordedAt: new Date().toISOString(),
|
|
71
|
+
const kept = map.tools.filter((tool) => {
|
|
72
|
+
const recorded = normalizePath(tool?.path);
|
|
73
|
+
return recorded !== toolPath && existsSync(join(root, recorded));
|
|
121
74
|
});
|
|
122
|
-
|
|
75
|
+
const unchanged =
|
|
76
|
+
kept.length === map.tools.length &&
|
|
77
|
+
map.tools.some((tool) => normalizePath(tool?.path) === toolPath);
|
|
78
|
+
if (unchanged) return;
|
|
79
|
+
|
|
80
|
+
const tools = [
|
|
81
|
+
...kept,
|
|
82
|
+
{
|
|
83
|
+
path: toolPath,
|
|
84
|
+
audit: auditLine.slice(0, MAX_AUDIT_LENGTH),
|
|
85
|
+
recordedAt: new Date().toISOString(),
|
|
86
|
+
},
|
|
87
|
+
];
|
|
123
88
|
try {
|
|
124
89
|
mkdirSync(dirname(mapPath), { recursive: true });
|
|
125
90
|
writeFileSync(
|
|
126
91
|
mapPath,
|
|
127
|
-
`${JSON.stringify(map, null, JSON_INDENT)}\n`,
|
|
92
|
+
`${JSON.stringify({ ...map, tools }, null, JSON_INDENT)}\n`,
|
|
128
93
|
'utf8',
|
|
129
94
|
);
|
|
130
95
|
} catch (error) {
|
|
131
96
|
warn(
|
|
132
97
|
CONFIG_KEY,
|
|
133
|
-
`Could not record this tool in ${
|
|
98
|
+
`Could not record this tool in ${mapPath}: ${error?.message ?? error}. ` +
|
|
134
99
|
'The build proceeds, but the discovery was not remembered.',
|
|
135
100
|
);
|
|
136
101
|
}
|
|
@@ -141,28 +106,33 @@ runGate(
|
|
|
141
106
|
id: GATE_ID,
|
|
142
107
|
configKey: CONFIG_KEY,
|
|
143
108
|
enabledByDefault: false,
|
|
144
|
-
defaultParams: {
|
|
109
|
+
defaultParams: {
|
|
110
|
+
toolMapFile: DEFAULT_TOOL_MAP_FILE,
|
|
111
|
+
toolFolders: DEFAULT_TOOL_FOLDERS,
|
|
112
|
+
toolExtensions: DEFAULT_TOOL_EXTENSIONS,
|
|
113
|
+
toolNamePatterns: DEFAULT_TOOL_NAME_PATTERNS,
|
|
114
|
+
},
|
|
145
115
|
},
|
|
146
|
-
({ toolName, toolInput, parameters }) => {
|
|
116
|
+
({ toolName, toolInput, parameters, cwd }) => {
|
|
147
117
|
if (!toolInGroups(toolName, ['write'])) return;
|
|
148
118
|
|
|
149
|
-
const
|
|
150
|
-
|
|
119
|
+
const rawPath = writtenPathOf(toolInput);
|
|
120
|
+
const isTool = isToolPath(rawPath, {
|
|
121
|
+
folders: parameters.toolFolders,
|
|
122
|
+
extensions: parameters.toolExtensions,
|
|
123
|
+
namePatterns: parameters.toolNamePatterns,
|
|
124
|
+
});
|
|
125
|
+
if (!isTool) return;
|
|
151
126
|
|
|
152
|
-
|
|
153
|
-
// this tool exists and what it was checked against.
|
|
154
|
-
const content = writtenContentOf(toolInput);
|
|
155
|
-
const auditLine = auditLineOf(content);
|
|
127
|
+
const auditLine = auditLineOf(writtenContentOf(toolInput));
|
|
156
128
|
if (!auditLine) return;
|
|
157
129
|
|
|
158
|
-
const root = projectRootOf(
|
|
159
|
-
if (!root) return;
|
|
160
|
-
const toolMapFile = parameters.toolMapFile ?? DEFAULT_TOOL_MAP_FILE;
|
|
130
|
+
const root = projectRootOf(cwd) ?? cwd;
|
|
161
131
|
recordTool(
|
|
162
|
-
|
|
163
|
-
|
|
132
|
+
root,
|
|
133
|
+
toolMapPathFor(root, parameters.toolMapFile),
|
|
134
|
+
rootRelativePath(root, rawPath),
|
|
164
135
|
auditLine,
|
|
165
|
-
toolMapFile,
|
|
166
136
|
);
|
|
167
137
|
},
|
|
168
138
|
);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"hooks": {
|
|
3
3
|
"PreToolUse": [
|
|
4
4
|
{
|
|
5
|
-
"matcher": "Bash|run_command|Agent|Task|invoke_subagent|mcp__.*",
|
|
5
|
+
"matcher": "Bash|run_command|PowerShell|Agent|Task|invoke_subagent|mcp__.*",
|
|
6
6
|
"hooks": [
|
|
7
7
|
{
|
|
8
8
|
"type": "command",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
]
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
|
-
"matcher": "Bash|run_command|Agent|Task|invoke_subagent|mcp__.*",
|
|
15
|
+
"matcher": "Bash|run_command|PowerShell|Agent|Task|invoke_subagent|mcp__.*",
|
|
16
16
|
"hooks": [
|
|
17
17
|
{
|
|
18
18
|
"type": "command",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
]
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
|
-
"matcher": "Write|Edit|NotebookEdit|write_to_file|replace_file_content|Bash|run_command|mcp__.*",
|
|
25
|
+
"matcher": "Write|Edit|MultiEdit|NotebookEdit|write_to_file|replace_file_content|Bash|run_command|PowerShell|mcp__.*",
|
|
26
26
|
"hooks": [
|
|
27
27
|
{
|
|
28
28
|
"type": "command",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
]
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
|
-
"matcher": "Write|Edit|NotebookEdit|write_to_file|replace_file_content|Bash|run_command|mcp__.*",
|
|
35
|
+
"matcher": "Write|Edit|MultiEdit|NotebookEdit|write_to_file|replace_file_content|Bash|run_command|PowerShell|mcp__.*",
|
|
36
36
|
"hooks": [
|
|
37
37
|
{
|
|
38
38
|
"type": "command",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
]
|
|
43
43
|
},
|
|
44
44
|
{
|
|
45
|
-
"matcher": "Bash|run_command|Agent|Task|invoke_subagent|mcp__.*",
|
|
45
|
+
"matcher": "Bash|run_command|PowerShell|Agent|Task|invoke_subagent|mcp__.*",
|
|
46
46
|
"hooks": [
|
|
47
47
|
{
|
|
48
48
|
"type": "command",
|
|
@@ -51,6 +51,16 @@
|
|
|
51
51
|
}
|
|
52
52
|
]
|
|
53
53
|
},
|
|
54
|
+
{
|
|
55
|
+
"matcher": "Bash|run_command|PowerShell|Write|Edit|MultiEdit|NotebookEdit|write_to_file|replace_file_content|mcp__ide__executeCode|Monitor|mcp__.*",
|
|
56
|
+
"hooks": [
|
|
57
|
+
{
|
|
58
|
+
"type": "command",
|
|
59
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/require-monitor/index.mjs\"",
|
|
60
|
+
"timeout": 30
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
},
|
|
54
64
|
{
|
|
55
65
|
"matcher": "Agent|Task|invoke_subagent|mcp__.*",
|
|
56
66
|
"hooks": [
|
|
@@ -102,7 +112,17 @@
|
|
|
102
112
|
]
|
|
103
113
|
},
|
|
104
114
|
{
|
|
105
|
-
"matcher": "
|
|
115
|
+
"matcher": "Agent|Task|invoke_subagent|mcp__.*",
|
|
116
|
+
"hooks": [
|
|
117
|
+
{
|
|
118
|
+
"type": "command",
|
|
119
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/force-parallel/index.mjs\"",
|
|
120
|
+
"timeout": 30
|
|
121
|
+
}
|
|
122
|
+
]
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"matcher": "Write|Edit|MultiEdit|NotebookEdit|write_to_file|replace_file_content|Bash|run_command|PowerShell|mcp__.*",
|
|
106
126
|
"hooks": [
|
|
107
127
|
{
|
|
108
128
|
"type": "command",
|
|
@@ -112,7 +132,7 @@
|
|
|
112
132
|
]
|
|
113
133
|
},
|
|
114
134
|
{
|
|
115
|
-
"matcher": "Write|Edit|NotebookEdit|write_to_file|replace_file_content|Agent|Task|invoke_subagent|mcp__.*",
|
|
135
|
+
"matcher": "Write|Edit|MultiEdit|NotebookEdit|write_to_file|replace_file_content|Agent|Task|invoke_subagent|mcp__.*",
|
|
116
136
|
"hooks": [
|
|
117
137
|
{
|
|
118
138
|
"type": "command",
|
|
@@ -162,7 +182,7 @@
|
|
|
162
182
|
]
|
|
163
183
|
},
|
|
164
184
|
{
|
|
165
|
-
"matcher": "Write|Edit|NotebookEdit|write_to_file|replace_file_content|mcp__.*",
|
|
185
|
+
"matcher": "Write|Edit|MultiEdit|NotebookEdit|write_to_file|replace_file_content|Bash|run_command|PowerShell|mcp__.*",
|
|
166
186
|
"hooks": [
|
|
167
187
|
{
|
|
168
188
|
"type": "command",
|
|
@@ -172,7 +192,7 @@
|
|
|
172
192
|
]
|
|
173
193
|
},
|
|
174
194
|
{
|
|
175
|
-
"matcher": "Write|Edit|NotebookEdit|write_to_file|replace_file_content|Agent|Task|invoke_subagent|mcp__.*",
|
|
195
|
+
"matcher": "Write|Edit|MultiEdit|NotebookEdit|write_to_file|replace_file_content|Agent|Task|invoke_subagent|mcp__.*",
|
|
176
196
|
"hooks": [
|
|
177
197
|
{
|
|
178
198
|
"type": "command",
|
|
@@ -182,7 +202,7 @@
|
|
|
182
202
|
]
|
|
183
203
|
},
|
|
184
204
|
{
|
|
185
|
-
"matcher": "Write|Edit|NotebookEdit|write_to_file|replace_file_content|Agent|Task|invoke_subagent|mcp__.*",
|
|
205
|
+
"matcher": "Write|Edit|MultiEdit|NotebookEdit|write_to_file|replace_file_content|Agent|Task|invoke_subagent|mcp__.*",
|
|
186
206
|
"hooks": [
|
|
187
207
|
{
|
|
188
208
|
"type": "command",
|
|
@@ -192,7 +212,7 @@
|
|
|
192
212
|
]
|
|
193
213
|
},
|
|
194
214
|
{
|
|
195
|
-
"matcher": "Write|Edit|NotebookEdit|write_to_file|replace_file_content|Agent|Task|invoke_subagent|mcp__.*",
|
|
215
|
+
"matcher": "Write|Edit|MultiEdit|NotebookEdit|write_to_file|replace_file_content|Agent|Task|invoke_subagent|mcp__.*",
|
|
196
216
|
"hooks": [
|
|
197
217
|
{
|
|
198
218
|
"type": "command",
|
|
@@ -202,7 +222,7 @@
|
|
|
202
222
|
]
|
|
203
223
|
},
|
|
204
224
|
{
|
|
205
|
-
"matcher": "Write|Edit|NotebookEdit|write_to_file|replace_file_content|Bash|run_command|mcp__ide__executeCode|Agent|Task|invoke_subagent|mcp__.*",
|
|
225
|
+
"matcher": "Write|Edit|MultiEdit|NotebookEdit|write_to_file|replace_file_content|Bash|run_command|PowerShell|mcp__ide__executeCode|Agent|Task|invoke_subagent|mcp__.*",
|
|
206
226
|
"hooks": [
|
|
207
227
|
{
|
|
208
228
|
"type": "command",
|
|
@@ -212,7 +232,7 @@
|
|
|
212
232
|
]
|
|
213
233
|
},
|
|
214
234
|
{
|
|
215
|
-
"matcher": "Write|Edit|NotebookEdit|write_to_file|replace_file_content|Bash|run_command|mcp__ide__executeCode|Agent|Task|invoke_subagent|mcp__.*",
|
|
235
|
+
"matcher": "Write|Edit|MultiEdit|NotebookEdit|write_to_file|replace_file_content|Bash|run_command|PowerShell|mcp__ide__executeCode|Agent|Task|invoke_subagent|mcp__.*",
|
|
216
236
|
"hooks": [
|
|
217
237
|
{
|
|
218
238
|
"type": "command",
|
|
@@ -222,7 +242,7 @@
|
|
|
222
242
|
]
|
|
223
243
|
},
|
|
224
244
|
{
|
|
225
|
-
"matcher": "Write|Edit|NotebookEdit|write_to_file|replace_file_content|mcp__.*",
|
|
245
|
+
"matcher": "Write|Edit|MultiEdit|NotebookEdit|write_to_file|replace_file_content|mcp__.*",
|
|
226
246
|
"hooks": [
|
|
227
247
|
{
|
|
228
248
|
"type": "command",
|
|
@@ -242,7 +262,7 @@
|
|
|
242
262
|
]
|
|
243
263
|
},
|
|
244
264
|
{
|
|
245
|
-
"matcher": "Write|Edit|NotebookEdit|write_to_file|replace_file_content|mcp__.*",
|
|
265
|
+
"matcher": "Write|Edit|MultiEdit|NotebookEdit|write_to_file|replace_file_content|mcp__.*",
|
|
246
266
|
"hooks": [
|
|
247
267
|
{
|
|
248
268
|
"type": "command",
|
|
@@ -252,7 +272,7 @@
|
|
|
252
272
|
]
|
|
253
273
|
},
|
|
254
274
|
{
|
|
255
|
-
"matcher": "Write|Edit|NotebookEdit|write_to_file|replace_file_content|mcp__.*",
|
|
275
|
+
"matcher": "Write|Edit|MultiEdit|NotebookEdit|write_to_file|replace_file_content|mcp__.*",
|
|
256
276
|
"hooks": [
|
|
257
277
|
{
|
|
258
278
|
"type": "command",
|
|
@@ -262,113 +282,174 @@
|
|
|
262
282
|
]
|
|
263
283
|
},
|
|
264
284
|
{
|
|
265
|
-
"matcher": "
|
|
285
|
+
"matcher": "Bash|run_command|PowerShell|mcp__.*",
|
|
266
286
|
"hooks": [
|
|
267
287
|
{
|
|
268
288
|
"type": "command",
|
|
269
|
-
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/
|
|
289
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/lint-commit/index.mjs\"",
|
|
290
|
+
"timeout": 65
|
|
291
|
+
}
|
|
292
|
+
]
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
"matcher": "Bash|run_command|PowerShell|mcp__.*",
|
|
296
|
+
"hooks": [
|
|
297
|
+
{
|
|
298
|
+
"type": "command",
|
|
299
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/staged-lint/index.mjs\"",
|
|
300
|
+
"timeout": 65
|
|
301
|
+
}
|
|
302
|
+
]
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
"matcher": "Bash|run_command|PowerShell|mcp__.*",
|
|
306
|
+
"hooks": [
|
|
307
|
+
{
|
|
308
|
+
"type": "command",
|
|
309
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/atomic-commit/index.mjs\"",
|
|
270
310
|
"timeout": 30
|
|
271
311
|
}
|
|
272
312
|
]
|
|
273
313
|
},
|
|
274
314
|
{
|
|
275
|
-
"matcher": "
|
|
315
|
+
"matcher": "Bash|run_command|PowerShell|Agent|Task|invoke_subagent|mcp__.*",
|
|
276
316
|
"hooks": [
|
|
277
317
|
{
|
|
278
318
|
"type": "command",
|
|
279
|
-
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/
|
|
319
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/no-coauthor/index.mjs\"",
|
|
280
320
|
"timeout": 30
|
|
281
321
|
}
|
|
282
322
|
]
|
|
283
323
|
},
|
|
284
324
|
{
|
|
285
|
-
"matcher": "Write|Edit|NotebookEdit|write_to_file|replace_file_content|
|
|
325
|
+
"matcher": "Write|Edit|MultiEdit|NotebookEdit|write_to_file|replace_file_content|mcp__.*",
|
|
286
326
|
"hooks": [
|
|
287
327
|
{
|
|
288
328
|
"type": "command",
|
|
289
|
-
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/
|
|
329
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/no-lint-suppression/index.mjs\"",
|
|
290
330
|
"timeout": 30
|
|
291
331
|
}
|
|
292
332
|
]
|
|
293
333
|
},
|
|
294
334
|
{
|
|
295
|
-
"matcher": "
|
|
335
|
+
"matcher": "Write|Edit|MultiEdit|NotebookEdit|write_to_file|replace_file_content|mcp__.*",
|
|
296
336
|
"hooks": [
|
|
297
337
|
{
|
|
298
338
|
"type": "command",
|
|
299
|
-
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/
|
|
339
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/no-explanatory-comments/index.mjs\"",
|
|
300
340
|
"timeout": 30
|
|
301
341
|
}
|
|
302
342
|
]
|
|
303
343
|
},
|
|
304
344
|
{
|
|
305
|
-
"matcher": "Bash|run_command|mcp__.*",
|
|
345
|
+
"matcher": "Bash|run_command|PowerShell|mcp__.*",
|
|
306
346
|
"hooks": [
|
|
307
347
|
{
|
|
308
348
|
"type": "command",
|
|
309
|
-
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/
|
|
310
|
-
"timeout":
|
|
349
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/no-trivial-scripts/index.mjs\"",
|
|
350
|
+
"timeout": 30
|
|
311
351
|
}
|
|
312
352
|
]
|
|
313
353
|
},
|
|
314
354
|
{
|
|
315
|
-
"matcher": "
|
|
355
|
+
"matcher": "Write|Edit|MultiEdit|NotebookEdit|write_to_file|replace_file_content|Agent|Task|invoke_subagent|mcp__.*",
|
|
316
356
|
"hooks": [
|
|
317
357
|
{
|
|
318
358
|
"type": "command",
|
|
319
|
-
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/
|
|
320
|
-
"timeout":
|
|
359
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/reuse-before-build/index.mjs\"",
|
|
360
|
+
"timeout": 30
|
|
321
361
|
}
|
|
322
362
|
]
|
|
323
363
|
},
|
|
324
364
|
{
|
|
325
|
-
"matcher": "
|
|
365
|
+
"matcher": "Write|Edit|MultiEdit|NotebookEdit|write_to_file|replace_file_content|mcp__.*",
|
|
326
366
|
"hooks": [
|
|
327
367
|
{
|
|
328
368
|
"type": "command",
|
|
329
|
-
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/
|
|
369
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/tool-map/index.mjs\"",
|
|
330
370
|
"timeout": 30
|
|
331
371
|
}
|
|
332
372
|
]
|
|
333
373
|
},
|
|
334
374
|
{
|
|
335
|
-
"matcher": "
|
|
375
|
+
"matcher": "WebSearch|WebFetch|mcp__.*",
|
|
336
376
|
"hooks": [
|
|
337
377
|
{
|
|
338
378
|
"type": "command",
|
|
339
|
-
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/
|
|
379
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/engram-first/index.mjs\"",
|
|
340
380
|
"timeout": 30
|
|
341
381
|
}
|
|
342
382
|
]
|
|
343
383
|
},
|
|
344
384
|
{
|
|
345
|
-
"matcher": "Bash|run_command|mcp__.*",
|
|
385
|
+
"matcher": "Write|Edit|MultiEdit|NotebookEdit|write_to_file|replace_file_content|Bash|run_command|PowerShell|mcp__.*",
|
|
346
386
|
"hooks": [
|
|
347
387
|
{
|
|
348
388
|
"type": "command",
|
|
349
|
-
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/
|
|
389
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/library-docs/index.mjs\"",
|
|
350
390
|
"timeout": 30
|
|
351
391
|
}
|
|
352
392
|
]
|
|
353
393
|
},
|
|
354
394
|
{
|
|
355
|
-
"matcher": "Write|Edit|NotebookEdit|write_to_file|replace_file_content|mcp__.*",
|
|
395
|
+
"matcher": "Write|Edit|MultiEdit|NotebookEdit|write_to_file|replace_file_content|Bash|run_command|PowerShell|mcp__.*",
|
|
356
396
|
"hooks": [
|
|
357
397
|
{
|
|
358
398
|
"type": "command",
|
|
359
|
-
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/
|
|
399
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/forge-flow/index.mjs\"",
|
|
400
|
+
"timeout": 30
|
|
401
|
+
}
|
|
402
|
+
]
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
"matcher": "AskUserQuestion|mcp__.*",
|
|
406
|
+
"hooks": [
|
|
407
|
+
{
|
|
408
|
+
"type": "command",
|
|
409
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/autonomous-mode/index.mjs\"",
|
|
410
|
+
"timeout": 30
|
|
411
|
+
}
|
|
412
|
+
]
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
"matcher": "Write|Edit|MultiEdit|NotebookEdit|write_to_file|replace_file_content|Bash|run_command|PowerShell|mcp__ide__executeCode|mcp__.*",
|
|
416
|
+
"hooks": [
|
|
417
|
+
{
|
|
418
|
+
"type": "command",
|
|
419
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/require-task-split/index.mjs\"",
|
|
360
420
|
"timeout": 30
|
|
361
421
|
}
|
|
362
422
|
]
|
|
363
423
|
}
|
|
364
424
|
],
|
|
365
|
-
"
|
|
425
|
+
"PostToolUse": [
|
|
366
426
|
{
|
|
427
|
+
"matcher": "Agent|Task|invoke_subagent|mcp__.*",
|
|
367
428
|
"hooks": [
|
|
368
429
|
{
|
|
369
430
|
"type": "command",
|
|
370
|
-
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/
|
|
371
|
-
"timeout":
|
|
431
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/circuit-breaker/track.mjs\"",
|
|
432
|
+
"timeout": 30
|
|
433
|
+
}
|
|
434
|
+
]
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
"matcher": "WebSearch|WebFetch|mcp__.*",
|
|
438
|
+
"hooks": [
|
|
439
|
+
{
|
|
440
|
+
"type": "command",
|
|
441
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/engram-first/track.mjs\"",
|
|
442
|
+
"timeout": 30
|
|
443
|
+
}
|
|
444
|
+
]
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
"matcher": "WebSearch|WebFetch|mcp__.*",
|
|
448
|
+
"hooks": [
|
|
449
|
+
{
|
|
450
|
+
"type": "command",
|
|
451
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/library-docs/track.mjs\"",
|
|
452
|
+
"timeout": 30
|
|
372
453
|
}
|
|
373
454
|
]
|
|
374
455
|
}
|
|
@@ -378,7 +459,7 @@
|
|
|
378
459
|
"hooks": [
|
|
379
460
|
{
|
|
380
461
|
"type": "command",
|
|
381
|
-
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/
|
|
462
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/engram-first/stop.mjs\"",
|
|
382
463
|
"timeout": 30
|
|
383
464
|
}
|
|
384
465
|
]
|
|
@@ -391,9 +472,27 @@
|
|
|
391
472
|
"timeout": 30
|
|
392
473
|
}
|
|
393
474
|
]
|
|
475
|
+
},
|
|
476
|
+
{
|
|
477
|
+
"hooks": [
|
|
478
|
+
{
|
|
479
|
+
"type": "command",
|
|
480
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/stop-pending/index.mjs\"",
|
|
481
|
+
"timeout": 30
|
|
482
|
+
}
|
|
483
|
+
]
|
|
394
484
|
}
|
|
395
485
|
],
|
|
396
486
|
"SessionStart": [
|
|
487
|
+
{
|
|
488
|
+
"hooks": [
|
|
489
|
+
{
|
|
490
|
+
"type": "command",
|
|
491
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/engram-first/session-start.mjs\"",
|
|
492
|
+
"timeout": 30
|
|
493
|
+
}
|
|
494
|
+
]
|
|
495
|
+
},
|
|
397
496
|
{
|
|
398
497
|
"hooks": [
|
|
399
498
|
{
|
|
@@ -421,6 +520,17 @@
|
|
|
421
520
|
}
|
|
422
521
|
]
|
|
423
522
|
}
|
|
523
|
+
],
|
|
524
|
+
"UserPromptSubmit": [
|
|
525
|
+
{
|
|
526
|
+
"hooks": [
|
|
527
|
+
{
|
|
528
|
+
"type": "command",
|
|
529
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gates/capability-map/index.mjs\"",
|
|
530
|
+
"timeout": 10
|
|
531
|
+
}
|
|
532
|
+
]
|
|
533
|
+
}
|
|
424
534
|
]
|
|
425
535
|
}
|
|
426
536
|
}
|