@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
package/registry.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"gateVersion": "3.
|
|
2
|
+
"gateVersion": "3.1.0",
|
|
3
3
|
"families": [
|
|
4
4
|
{
|
|
5
5
|
"id": "security",
|
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
"event": "PreToolUse",
|
|
14
14
|
"tools": ["shell", "delegation"],
|
|
15
15
|
"script": "gates/bash-commands/index.mjs",
|
|
16
|
-
"description": "Denies git reset --hard,
|
|
16
|
+
"description": "Denies git reset --hard, recursive force deletes over protected areas, force push, git clean -f, and killing processes by name (Unix and Windows).",
|
|
17
17
|
"params": [
|
|
18
18
|
{
|
|
19
19
|
"name": "denyPatterns",
|
|
20
20
|
"type": "string[]",
|
|
21
|
-
"description": "
|
|
21
|
+
"description": "Destructive-command rules: regex sources, or [regex, reason] pairs (a bare source gets a generic reason). Replaces the built-in list."
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
24
|
"name": "rmRfProtectedAreas",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
{
|
|
45
45
|
"name": "publishRules",
|
|
46
46
|
"type": "string[]",
|
|
47
|
-
"description": "
|
|
47
|
+
"description": "Remote-publish rules: regex sources, or [regex, reason] pairs. Replaces the built-in list."
|
|
48
48
|
}
|
|
49
49
|
]
|
|
50
50
|
},
|
|
@@ -54,18 +54,18 @@
|
|
|
54
54
|
"default": true,
|
|
55
55
|
"event": "PreToolUse",
|
|
56
56
|
"tools": ["write", "shell"],
|
|
57
|
-
"description": "Denies writes to .env, lockfiles and the harness
|
|
57
|
+
"description": "Denies writes and mutating commands (Unix and PowerShell) to .env files, lockfiles and the Claude harness.",
|
|
58
58
|
"script": "gates/protected-paths/index.mjs",
|
|
59
59
|
"params": [
|
|
60
60
|
{
|
|
61
61
|
"name": "protectedPaths",
|
|
62
62
|
"type": "string[]",
|
|
63
|
-
"description": "Path fragments
|
|
63
|
+
"description": "Path fragments: a bare name matches the file's basename exactly (.env is not .env.example); a fragment ending in / matches that directory sequence (.claude/hooks/)."
|
|
64
64
|
},
|
|
65
65
|
{
|
|
66
66
|
"name": "mutatingCommands",
|
|
67
67
|
"type": "string[]",
|
|
68
|
-
"description": "
|
|
68
|
+
"description": "Regex sources matched at the start of a command segment whose arguments name a protected path; [] turns that rule off (redirections are always checked)."
|
|
69
69
|
}
|
|
70
70
|
]
|
|
71
71
|
},
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"configKey": "blockPathsOutsideRootWhitelist",
|
|
75
75
|
"default": true,
|
|
76
76
|
"event": "PreToolUse",
|
|
77
|
-
"tools": ["write"],
|
|
77
|
+
"tools": ["write", "shell"],
|
|
78
78
|
"description": "Denies new root-level files/folders outside the project's whitelist.",
|
|
79
79
|
"script": "gates/root-whitelist/index.mjs",
|
|
80
80
|
"params": [
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
{
|
|
103
103
|
"name": "blockingPatterns",
|
|
104
104
|
"type": "string[]",
|
|
105
|
-
"description": "
|
|
105
|
+
"description": "Blocking/waiting rules: regex sources, or [regex, reason] pairs, matched per command segment. Replaces the built-in list."
|
|
106
106
|
},
|
|
107
107
|
{
|
|
108
108
|
"name": "waitJustifiedMarker",
|
|
@@ -110,6 +110,22 @@
|
|
|
110
110
|
"description": "Comment marker that authorizes a justified wait as an escape hatch."
|
|
111
111
|
}
|
|
112
112
|
]
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"id": "require-monitor",
|
|
116
|
+
"configKey": "requireMonitorForBackground",
|
|
117
|
+
"default": true,
|
|
118
|
+
"event": "PreToolUse",
|
|
119
|
+
"tools": ["shell", "execution", "monitor"],
|
|
120
|
+
"description": "Enforces that every background command (run_in_background: true) has an associated Monitor. Phase 1: denies background without MONITOR-PLANNED: marker. Phase 2: denies any execution tool while unmonitored backgrounds exist.",
|
|
121
|
+
"script": "gates/require-monitor/index.mjs",
|
|
122
|
+
"params": [
|
|
123
|
+
{
|
|
124
|
+
"name": "monitorPlannedMarker",
|
|
125
|
+
"type": "string",
|
|
126
|
+
"description": "Marker the command must carry to declare its Monitor plan. Default MONITOR-PLANNED:."
|
|
127
|
+
}
|
|
128
|
+
]
|
|
113
129
|
}
|
|
114
130
|
]
|
|
115
131
|
},
|
|
@@ -187,8 +203,15 @@
|
|
|
187
203
|
"default": false,
|
|
188
204
|
"event": "PreToolUse",
|
|
189
205
|
"tools": ["delegation"],
|
|
190
|
-
"description": "Cuts
|
|
206
|
+
"description": "Cuts a delegation retried without substantial change: the attempt count is recomputed from stored signatures across the session (Dice >= similarityThreshold); retryThreshold below 2 is treated as 2. Only delegations that actually launched (allowed by all gates) count as attempts.",
|
|
191
207
|
"script": "gates/circuit-breaker/index.mjs",
|
|
208
|
+
"extraScripts": [
|
|
209
|
+
{
|
|
210
|
+
"event": "PostToolUse",
|
|
211
|
+
"script": "gates/circuit-breaker/track.mjs",
|
|
212
|
+
"tools": ["delegation"]
|
|
213
|
+
}
|
|
214
|
+
],
|
|
192
215
|
"params": [
|
|
193
216
|
{
|
|
194
217
|
"name": "retryThreshold",
|
|
@@ -214,17 +237,22 @@
|
|
|
214
237
|
{
|
|
215
238
|
"name": "memoryDependencyPatterns",
|
|
216
239
|
"type": "string[]",
|
|
217
|
-
"description": "Regex sources for phrases that
|
|
240
|
+
"description": "Regex sources for phrases that refer the subagent to prior conversation."
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"name": "escapeHatch",
|
|
244
|
+
"type": "string",
|
|
245
|
+
"description": "Marker in the prompt that states no recalled data is needed (default memory-not-needed)."
|
|
218
246
|
}
|
|
219
247
|
]
|
|
220
248
|
},
|
|
221
249
|
{
|
|
222
250
|
"id": "force-parallel",
|
|
223
251
|
"configKey": "warnSequentialDelegations",
|
|
224
|
-
"default":
|
|
252
|
+
"default": true,
|
|
225
253
|
"event": "PreToolUse",
|
|
226
254
|
"tools": ["delegation"],
|
|
227
|
-
"description": "
|
|
255
|
+
"description": "Denies the Nth consecutive sequential delegation within a time window, requiring independent delegations to be launched together in one message. Escape hatch: SEQUENTIAL-JUSTIFIED in the prompt declares a genuine dependency.",
|
|
228
256
|
"script": "gates/force-parallel/index.mjs",
|
|
229
257
|
"params": [
|
|
230
258
|
{
|
|
@@ -256,8 +284,8 @@
|
|
|
256
284
|
"configKey": "requireFeatureCatalog",
|
|
257
285
|
"default": true,
|
|
258
286
|
"event": "PreToolUse",
|
|
259
|
-
"tools": ["write"],
|
|
260
|
-
"description": "
|
|
287
|
+
"tools": ["write", "shell"],
|
|
288
|
+
"description": "Judges the change to the feature catalog: at most maxInProgress features in_progress, and no feature moved to done by a direct write (shell redirects onto the catalog are denied).",
|
|
261
289
|
"script": "gates/feature-catalog/index.mjs",
|
|
262
290
|
"params": [
|
|
263
291
|
{
|
|
@@ -320,13 +348,13 @@
|
|
|
320
348
|
"default": false,
|
|
321
349
|
"event": "PreToolUse",
|
|
322
350
|
"tools": ["delegation"],
|
|
323
|
-
"description": "Definition, writing
|
|
351
|
+
"description": "Definition, writing (verification) and a separate reviewer declared before building.",
|
|
324
352
|
"script": "gates/implementation-pipeline/index.mjs",
|
|
325
353
|
"params": [
|
|
326
354
|
{
|
|
327
355
|
"name": "builderSubagents",
|
|
328
356
|
"type": "string[]",
|
|
329
|
-
"description": "
|
|
357
|
+
"description": "Kept for compatibility: every subagent type not in exemptSubagents is held to the pipeline."
|
|
330
358
|
},
|
|
331
359
|
{
|
|
332
360
|
"name": "exemptSubagents",
|
|
@@ -347,7 +375,7 @@
|
|
|
347
375
|
{
|
|
348
376
|
"name": "activePointerPath",
|
|
349
377
|
"type": "string",
|
|
350
|
-
"description": "Path to the active-
|
|
378
|
+
"description": "Path to the active-task pointer file (relative to the project root, or absolute). The task contract is looked up under <pointer directory>/<slug>/."
|
|
351
379
|
},
|
|
352
380
|
{
|
|
353
381
|
"name": "exemptSubagents",
|
|
@@ -368,12 +396,12 @@
|
|
|
368
396
|
{
|
|
369
397
|
"name": "e2eSignals",
|
|
370
398
|
"type": "string[]",
|
|
371
|
-
"description": "Regex sources that make an E2E row mandatory (money, auth, data
|
|
399
|
+
"description": "Regex sources that make an E2E row mandatory (money, auth, persistence, data loss). An empty list means never."
|
|
372
400
|
},
|
|
373
401
|
{
|
|
374
402
|
"name": "visualSignals",
|
|
375
403
|
"type": "string[]",
|
|
376
|
-
"description": "Regex sources that make a visual/QA row mandatory
|
|
404
|
+
"description": "Regex sources that make a visual/QA row mandatory; a source starting with an escaped dot matches a file extension inside a path."
|
|
377
405
|
},
|
|
378
406
|
{
|
|
379
407
|
"name": "exemptSubagents",
|
|
@@ -394,8 +422,8 @@
|
|
|
394
422
|
"configKey": "requireSkillForNewDependency",
|
|
395
423
|
"default": true,
|
|
396
424
|
"event": "PreToolUse",
|
|
397
|
-
"tools": ["write"],
|
|
398
|
-
"description": "A new
|
|
425
|
+
"tools": ["write", "shell"],
|
|
426
|
+
"description": "A dependency new to the project (package.json write or npm/pnpm/yarn/bun install) requires a current skill.",
|
|
399
427
|
"script": "gates/dependency-skills/index.mjs",
|
|
400
428
|
"params": [
|
|
401
429
|
{
|
|
@@ -469,7 +497,7 @@
|
|
|
469
497
|
"default": false,
|
|
470
498
|
"event": "PreToolUse",
|
|
471
499
|
"tools": ["execution", "delegation"],
|
|
472
|
-
"description": "
|
|
500
|
+
"description": "Runs the project's own rules/*.mjs and .claude/skills/*/gate.mjs as sub-gates (payload on stdin; deny via JSON or exit 2). Only when enabled in the project's own .ai/config.json, never from the global config.",
|
|
473
501
|
"script": "gates/rule-skill-autodiscovery/index.mjs",
|
|
474
502
|
"params": [
|
|
475
503
|
{
|
|
@@ -490,7 +518,7 @@
|
|
|
490
518
|
"default": true,
|
|
491
519
|
"event": "PreToolUse",
|
|
492
520
|
"tools": ["execution", "delegation"],
|
|
493
|
-
"description": "A second occurrence of a defect class requires its deterministic block.",
|
|
521
|
+
"description": "A second occurrence of a defect class requires its deterministic block. Read-only commands, read-only delegations and the write to .ai/reincidencias.json itself stay allowed.",
|
|
494
522
|
"script": "gates/recurrence-lock/index.mjs",
|
|
495
523
|
"params": [
|
|
496
524
|
{
|
|
@@ -513,6 +541,11 @@
|
|
|
513
541
|
"name": "implementationExtensions",
|
|
514
542
|
"type": "string[]",
|
|
515
543
|
"description": "Source extensions whose paired test is checked."
|
|
544
|
+
},
|
|
545
|
+
{
|
|
546
|
+
"name": "escapeHatch",
|
|
547
|
+
"type": "string",
|
|
548
|
+
"description": "Marker that, present in the test content, allows a regression test written after reproducing a bug (default test-after-impl:allow)."
|
|
516
549
|
}
|
|
517
550
|
]
|
|
518
551
|
},
|
|
@@ -538,13 +571,23 @@
|
|
|
538
571
|
"default": true,
|
|
539
572
|
"event": "PreToolUse",
|
|
540
573
|
"tools": ["write"],
|
|
541
|
-
"description": "Denies
|
|
574
|
+
"description": "Denies voseo or regional lexicon in Spanish prose (text files, or content that reads as Spanish); code and English text are not scanned. Escape hatch marker allows a deliberate quote/fixture/log.",
|
|
542
575
|
"script": "gates/neutral-spanish/index.mjs",
|
|
543
576
|
"params": [
|
|
544
577
|
{
|
|
545
578
|
"name": "regionalMarkers",
|
|
546
579
|
"type": "string[]",
|
|
547
580
|
"description": "Regional words to warn about. Replaces the built-in list."
|
|
581
|
+
},
|
|
582
|
+
{
|
|
583
|
+
"name": "textExtensions",
|
|
584
|
+
"type": "string[]",
|
|
585
|
+
"description": "File extensions always scanned as prose (default .md, .mdx, .txt, .rst, .html, .htm, .adoc, .json, .yml, .yaml); other files are scanned only when their content reads as Spanish prose."
|
|
586
|
+
},
|
|
587
|
+
{
|
|
588
|
+
"name": "escapeHatch",
|
|
589
|
+
"type": "string",
|
|
590
|
+
"description": "Marker that, present in the content, allows deliberate regional text (default neutral-spanish:allow)."
|
|
548
591
|
}
|
|
549
592
|
]
|
|
550
593
|
},
|
|
@@ -554,7 +597,7 @@
|
|
|
554
597
|
"default": true,
|
|
555
598
|
"event": "PreToolUse",
|
|
556
599
|
"tools": ["write"],
|
|
557
|
-
"description": "Warns when
|
|
600
|
+
"description": "Warns when a timeout/deadline/retry VALUE changes (Edit old vs new, or Write vs disk) without evidence; a new file never warns.",
|
|
558
601
|
"script": "gates/diagnosis-before-patch/index.mjs",
|
|
559
602
|
"params": [
|
|
560
603
|
{
|
|
@@ -583,7 +626,8 @@
|
|
|
583
626
|
"type": "number",
|
|
584
627
|
"description": "Milliseconds allowed for the lint run before it counts as a failure."
|
|
585
628
|
}
|
|
586
|
-
]
|
|
629
|
+
],
|
|
630
|
+
"timeoutSeconds": 65
|
|
587
631
|
},
|
|
588
632
|
{
|
|
589
633
|
"id": "staged-lint",
|
|
@@ -614,7 +658,8 @@
|
|
|
614
658
|
"type": "string",
|
|
615
659
|
"description": "Substring in the commit command that skips the check once. Default [skip-lint]."
|
|
616
660
|
}
|
|
617
|
-
]
|
|
661
|
+
],
|
|
662
|
+
"timeoutSeconds": 65
|
|
618
663
|
},
|
|
619
664
|
{
|
|
620
665
|
"id": "atomic-commit",
|
|
@@ -643,7 +688,7 @@
|
|
|
643
688
|
{
|
|
644
689
|
"name": "natures",
|
|
645
690
|
"type": "string[]",
|
|
646
|
-
"description": "Classification table
|
|
691
|
+
"description": "Classification table of {name, source, counts?} objects, first match wins; entries without name and source are skipped. Replaces the built-in list."
|
|
647
692
|
}
|
|
648
693
|
]
|
|
649
694
|
},
|
|
@@ -653,7 +698,7 @@
|
|
|
653
698
|
"default": true,
|
|
654
699
|
"event": "PreToolUse",
|
|
655
700
|
"tools": ["shell", "delegation"],
|
|
656
|
-
"description": "Denies a git commit whose message carries an AI/agent attribution trailer (Co-Authored-By, Generated with, session trailer). Escape hatch marker allows one legitimate co-author.",
|
|
701
|
+
"description": "Denies a git commit whose message carries an AI/agent attribution trailer (Co-Authored-By, Generated with Claude/AI, session trailer), and a delegation prompt that orders one. Escape hatch marker allows one legitimate co-author.",
|
|
657
702
|
"script": "gates/no-coauthor/index.mjs",
|
|
658
703
|
"params": [
|
|
659
704
|
{
|
|
@@ -685,7 +730,7 @@
|
|
|
685
730
|
{
|
|
686
731
|
"name": "watchedConfigFiles",
|
|
687
732
|
"type": "string[]",
|
|
688
|
-
"description": "Config file basenames whose edits are scanned for rule-weakening. Replaces the built-in list."
|
|
733
|
+
"description": "Config file basenames (a * matches within a name, e.g. tsconfig.*.json) whose edits are scanned for rule-weakening. package.json counts only when it has an eslintConfig. Replaces the built-in list."
|
|
689
734
|
},
|
|
690
735
|
{
|
|
691
736
|
"name": "escapeHatch",
|
|
@@ -693,6 +738,37 @@
|
|
|
693
738
|
"description": "Substring on the same line as a suppression that allows it (a documented false positive). Default lint-ok:."
|
|
694
739
|
}
|
|
695
740
|
]
|
|
741
|
+
},
|
|
742
|
+
{
|
|
743
|
+
"id": "no-explanatory-comments",
|
|
744
|
+
"configKey": "blockExplanatoryComments",
|
|
745
|
+
"default": true,
|
|
746
|
+
"event": "PreToolUse",
|
|
747
|
+
"tools": ["write"],
|
|
748
|
+
"script": "gates/no-explanatory-comments/index.mjs",
|
|
749
|
+
"description": "Denies a code write that adds comments narrating what the code does. Only decision comments (why, trade-off, limitation), tool directives, TODO/FIXME and typed JSDoc tags are allowed. Judges only NEW comments (diff against the file on disk). Escape hatch: comment-ok: <reason>.",
|
|
750
|
+
"params": [
|
|
751
|
+
{
|
|
752
|
+
"name": "decisionMarkers",
|
|
753
|
+
"type": "string[]",
|
|
754
|
+
"description": "Regex sources (ES+EN) that mark a comment as a decision and therefore allowed. Replaces the built-in list."
|
|
755
|
+
},
|
|
756
|
+
{
|
|
757
|
+
"name": "escapeHatch",
|
|
758
|
+
"type": "string",
|
|
759
|
+
"description": "Substring inside a comment that allows it once (a documented exception). Default comment-ok:."
|
|
760
|
+
}
|
|
761
|
+
]
|
|
762
|
+
},
|
|
763
|
+
{
|
|
764
|
+
"id": "no-trivial-scripts",
|
|
765
|
+
"configKey": "blockTrivialInlineScripts",
|
|
766
|
+
"default": true,
|
|
767
|
+
"event": "PreToolUse",
|
|
768
|
+
"tools": ["shell"],
|
|
769
|
+
"description": "Denies inline interpreter scripts (node -e, python -c, sed -i, perl -i, PowerShell Set-Content/Add-Content) when they perform file operations that the Edit or Write tool handles directly. Legitimate computation scripts are not caught.",
|
|
770
|
+
"script": "gates/no-trivial-scripts/index.mjs",
|
|
771
|
+
"params": []
|
|
696
772
|
}
|
|
697
773
|
]
|
|
698
774
|
},
|
|
@@ -745,6 +821,112 @@
|
|
|
745
821
|
"name": "toolMapFile",
|
|
746
822
|
"type": "string",
|
|
747
823
|
"description": "Path to the per-project tool map (default .ai/tool-map.json)."
|
|
824
|
+
},
|
|
825
|
+
{
|
|
826
|
+
"name": "toolFolders",
|
|
827
|
+
"type": "string[]",
|
|
828
|
+
"description": "Folder names (path segments) marking a file as a tool/helper. Same defaults as reuse-before-build."
|
|
829
|
+
},
|
|
830
|
+
{
|
|
831
|
+
"name": "toolExtensions",
|
|
832
|
+
"type": "string[]",
|
|
833
|
+
"description": "File extensions considered code that can reinvent a wheel."
|
|
834
|
+
},
|
|
835
|
+
{
|
|
836
|
+
"name": "toolNamePatterns",
|
|
837
|
+
"type": "string[]",
|
|
838
|
+
"description": "Regex sources; a file whose basename matches any is a helper regardless of folder."
|
|
839
|
+
}
|
|
840
|
+
]
|
|
841
|
+
}
|
|
842
|
+
]
|
|
843
|
+
},
|
|
844
|
+
{
|
|
845
|
+
"id": "research",
|
|
846
|
+
"name": "Research flow",
|
|
847
|
+
"description": "Engram persistent memory is the first source and the mandatory sink of research; library APIs are looked up (context7) instead of guessed, then saved.",
|
|
848
|
+
"gates": [
|
|
849
|
+
{
|
|
850
|
+
"id": "engram-first",
|
|
851
|
+
"configKey": "requireEngramBeforeResearch",
|
|
852
|
+
"default": true,
|
|
853
|
+
"event": "PreToolUse",
|
|
854
|
+
"tools": ["research"],
|
|
855
|
+
"script": "gates/engram-first/index.mjs",
|
|
856
|
+
"extraScripts": [
|
|
857
|
+
{
|
|
858
|
+
"event": "PostToolUse",
|
|
859
|
+
"script": "gates/engram-first/track.mjs",
|
|
860
|
+
"tools": ["research"]
|
|
861
|
+
},
|
|
862
|
+
{
|
|
863
|
+
"event": "Stop",
|
|
864
|
+
"script": "gates/engram-first/stop.mjs"
|
|
865
|
+
},
|
|
866
|
+
{
|
|
867
|
+
"event": "SessionStart",
|
|
868
|
+
"script": "gates/engram-first/session-start.mjs"
|
|
869
|
+
}
|
|
870
|
+
],
|
|
871
|
+
"description": "Denies WebSearch/WebFetch/context7 (and MCP research tools) until a mem_search ran in the session; blocks Stop while research happened with no later mem_save; at session start warns once when engram cloud is configured but the project is not enrolled.",
|
|
872
|
+
"params": [
|
|
873
|
+
{
|
|
874
|
+
"name": "engramServers",
|
|
875
|
+
"type": "string[]",
|
|
876
|
+
"description": "MCP server names that are engram (mcp__<server>__mem_*)."
|
|
877
|
+
},
|
|
878
|
+
{
|
|
879
|
+
"name": "context7Servers",
|
|
880
|
+
"type": "string[]",
|
|
881
|
+
"description": "MCP server names that are context7."
|
|
882
|
+
},
|
|
883
|
+
{
|
|
884
|
+
"name": "researchTools",
|
|
885
|
+
"type": "string[]",
|
|
886
|
+
"description": "Native tool names that count as research."
|
|
887
|
+
},
|
|
888
|
+
{
|
|
889
|
+
"name": "engramUrl",
|
|
890
|
+
"type": "string",
|
|
891
|
+
"description": "Local engram daemon URL used for the cloud enrollment check."
|
|
892
|
+
},
|
|
893
|
+
{
|
|
894
|
+
"name": "requireSaveBeforeStop",
|
|
895
|
+
"type": "boolean",
|
|
896
|
+
"description": "Block the Stop event when research happened and nothing was saved to engram afterwards."
|
|
897
|
+
}
|
|
898
|
+
]
|
|
899
|
+
},
|
|
900
|
+
{
|
|
901
|
+
"id": "library-docs",
|
|
902
|
+
"configKey": "requireDocsBeforeUsingNewLibrary",
|
|
903
|
+
"default": true,
|
|
904
|
+
"event": "PreToolUse",
|
|
905
|
+
"tools": ["write", "shell"],
|
|
906
|
+
"script": "gates/library-docs/index.mjs",
|
|
907
|
+
"extraScripts": [
|
|
908
|
+
{
|
|
909
|
+
"event": "PostToolUse",
|
|
910
|
+
"script": "gates/library-docs/track.mjs",
|
|
911
|
+
"tools": ["research"]
|
|
912
|
+
}
|
|
913
|
+
],
|
|
914
|
+
"description": "Denies a write or shell command that imports a package the project does not use anywhere yet unless this session looked it up: an engram hit about it, or context7 docs followed by a mem_save. Shell heredocs are inspected; opaque redirections to code files are denied outright. Never guess a library API.",
|
|
915
|
+
"params": [
|
|
916
|
+
{
|
|
917
|
+
"name": "codeExtensions",
|
|
918
|
+
"type": "string[]",
|
|
919
|
+
"description": "File extensions whose imports are inspected."
|
|
920
|
+
},
|
|
921
|
+
{
|
|
922
|
+
"name": "ignoredPackages",
|
|
923
|
+
"type": "string[]",
|
|
924
|
+
"description": "Package names that never require a lookup."
|
|
925
|
+
},
|
|
926
|
+
{
|
|
927
|
+
"name": "maxScanFiles",
|
|
928
|
+
"type": "number",
|
|
929
|
+
"description": "How many project files are scanned to see whether a package is already in use."
|
|
748
930
|
}
|
|
749
931
|
]
|
|
750
932
|
}
|
|
@@ -767,7 +949,7 @@
|
|
|
767
949
|
{
|
|
768
950
|
"name": "forgeDbPath",
|
|
769
951
|
"type": "string",
|
|
770
|
-
"description": "Path to forge's global SQLite DB (default ~/.forge/forge-mcp.db)."
|
|
952
|
+
"description": "Path to forge's global SQLite DB (default ~/.forge/forge-mcp.db). forgeDatabasePath is accepted as a legacy alias."
|
|
771
953
|
}
|
|
772
954
|
]
|
|
773
955
|
}
|
|
@@ -785,7 +967,13 @@
|
|
|
785
967
|
"event": "PreToolUse",
|
|
786
968
|
"tools": ["question"],
|
|
787
969
|
"description": "When autonomous mode is on, denies AskUserQuestion so the assistant decides instead of asking. Also blocks a turn from ending to wait (via gates/autonomous-mode/stop.mjs, a Stop hook sharing this flag): it re-injects, once per cycle, an instruction to decide and proceed, leaving pending only what needs the user's own explicit decision.",
|
|
788
|
-
"script": "gates/autonomous-mode/index.mjs"
|
|
970
|
+
"script": "gates/autonomous-mode/index.mjs",
|
|
971
|
+
"extraScripts": [
|
|
972
|
+
{
|
|
973
|
+
"event": "Stop",
|
|
974
|
+
"script": "gates/autonomous-mode/stop.mjs"
|
|
975
|
+
}
|
|
976
|
+
]
|
|
789
977
|
}
|
|
790
978
|
]
|
|
791
979
|
},
|
|
@@ -800,7 +988,7 @@
|
|
|
800
988
|
"default": true,
|
|
801
989
|
"event": "Stop",
|
|
802
990
|
"tools": [],
|
|
803
|
-
"description": "Blocks the Stop event while the task store has active (open/in_forge) tasks for this project; lists them and how to close them
|
|
991
|
+
"description": "Blocks the Stop event while the task store has active (open/in_forge) tasks for this project; lists them and how to close them with verified evidence (task close --check/--exists) or abandon them. Respects stop_hook_active.",
|
|
804
992
|
"script": "gates/stop-pending/index.mjs",
|
|
805
993
|
"params": [
|
|
806
994
|
{
|
|
@@ -809,6 +997,16 @@
|
|
|
809
997
|
"description": "When true (default), a task with status 'blocked' does not prevent stop; only open/in_forge do."
|
|
810
998
|
}
|
|
811
999
|
]
|
|
1000
|
+
},
|
|
1001
|
+
{
|
|
1002
|
+
"id": "require-task-split",
|
|
1003
|
+
"configKey": "requireTaskSplitBeforeImplementing",
|
|
1004
|
+
"default": true,
|
|
1005
|
+
"event": "PreToolUse",
|
|
1006
|
+
"tools": ["write", "execution"],
|
|
1007
|
+
"description": "Denies writes and execution when an active task has size > small/trivial and no sub-tasks registered. Forces splitting into smaller, independently verifiable sub-tasks before implementation begins.",
|
|
1008
|
+
"script": "gates/require-task-split/index.mjs",
|
|
1009
|
+
"params": []
|
|
812
1010
|
}
|
|
813
1011
|
]
|
|
814
1012
|
},
|
|
@@ -861,7 +1059,7 @@
|
|
|
861
1059
|
{
|
|
862
1060
|
"name": "maxClauseChars",
|
|
863
1061
|
"type": "number",
|
|
864
|
-
"description": "Hard cap on each entry's one-line blurb length. Default
|
|
1062
|
+
"description": "Hard cap on each entry's one-line blurb length. Default 120."
|
|
865
1063
|
},
|
|
866
1064
|
{
|
|
867
1065
|
"name": "extraSkillsDirs",
|
|
@@ -887,8 +1085,19 @@
|
|
|
887
1085
|
"name": "mapFile",
|
|
888
1086
|
"type": "string",
|
|
889
1087
|
"description": "Path to the persisted capability map, relative to project root. Default .ai/capability-map.json."
|
|
1088
|
+
},
|
|
1089
|
+
{
|
|
1090
|
+
"name": "injectEveryMessages",
|
|
1091
|
+
"type": "number",
|
|
1092
|
+
"description": "Inject the catalog only every Nth message of a session (default 10); a changed catalog injects immediately."
|
|
1093
|
+
},
|
|
1094
|
+
{
|
|
1095
|
+
"name": "blurbOverridesFile",
|
|
1096
|
+
"type": "string",
|
|
1097
|
+
"description": "Path, relative to the project root, of a JSON map name -> hand-written blurb (default .ai/blurb-overrides.json)."
|
|
890
1098
|
}
|
|
891
|
-
]
|
|
1099
|
+
],
|
|
1100
|
+
"timeoutSeconds": 10
|
|
892
1101
|
}
|
|
893
1102
|
]
|
|
894
1103
|
},
|
|
@@ -912,7 +1121,8 @@
|
|
|
912
1121
|
"type": "number",
|
|
913
1122
|
"description": "How many user messages between full recitations of active tasks."
|
|
914
1123
|
}
|
|
915
|
-
]
|
|
1124
|
+
],
|
|
1125
|
+
"timeoutSeconds": 10
|
|
916
1126
|
},
|
|
917
1127
|
{
|
|
918
1128
|
"id": "list-tasks-on-session-start",
|
|
@@ -921,7 +1131,8 @@
|
|
|
921
1131
|
"event": "SessionStart",
|
|
922
1132
|
"tools": [],
|
|
923
1133
|
"description": "Lists this project's active tasks when a session opens. Silent when none are active.",
|
|
924
|
-
"script": "session-tasks.mjs"
|
|
1134
|
+
"script": "session-tasks.mjs",
|
|
1135
|
+
"timeoutSeconds": 10
|
|
925
1136
|
}
|
|
926
1137
|
]
|
|
927
1138
|
}
|