@devrik-tools/claude-gates 0.8.0 → 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/.claude-plugin/marketplace.json +3 -3
- package/README.es.md +102 -9
- package/README.md +93 -9
- package/cli/artifacts.mjs +213 -0
- package/cli/constants.mjs +14 -0
- package/cli/doctor.mjs +2 -1
- package/cli/index.mjs +54 -2
- package/cli/init.mjs +95 -9
- package/cli/install.mjs +53 -1
- package/cli/registry.mjs +2 -0
- package/cli/selection.mjs +23 -1
- package/cli/smoke-fixtures.json +53 -3
- package/cli/task.mjs +69 -4
- package/package.json +5 -4
- package/plugins/gates/.claude-plugin/plugin.json +1 -1
- package/plugins/gates/hooks/gates/capability-map/index.mjs +37 -208
- package/plugins/gates/hooks/gates/circuit-breaker/index.mjs +4 -11
- package/plugins/gates/hooks/gates/circuit-breaker/track.mjs +285 -0
- package/plugins/gates/hooks/gates/force-parallel/index.mjs +11 -12
- package/plugins/gates/hooks/gates/library-docs/index.mjs +107 -31
- package/plugins/gates/hooks/gates/no-trivial-scripts/index.mjs +114 -0
- 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/skill-first/index.mjs +138 -0
- package/plugins/gates/hooks/gates/skill-first/track.mjs +66 -0
- package/plugins/gates/hooks/hooks.json +61 -1
- package/plugins/gates/hooks/lib/capabilities.mjs +401 -0
- package/plugins/gates/hooks/lib/hook-io.mjs +9 -2
- package/plugins/gates/hooks/lib/signals.mjs +91 -0
- package/plugins/gates/hooks/lib/testing.mjs +15 -4
- package/plugins/tasks/.claude-plugin/plugin.json +1 -1
- package/plugins/tasks/hooks/lib/task-store.mjs +6 -0
- package/plugins/tasks/hooks/register-requests.mjs +37 -10
- package/registry.json +106 -5
|
@@ -4,20 +4,20 @@
|
|
|
4
4
|
"name": "claude-gates"
|
|
5
5
|
},
|
|
6
6
|
"metadata": {
|
|
7
|
-
"description": "Installable deterministic gates (hooks) for Claude Code, selectable per project or globally with `npx @
|
|
7
|
+
"description": "Installable deterministic gates (hooks) for Claude Code, selectable per project or globally with `npx @devrik-tools/claude-gates init`."
|
|
8
8
|
},
|
|
9
9
|
"plugins": [
|
|
10
10
|
{
|
|
11
11
|
"name": "gates",
|
|
12
12
|
"source": "./plugins/gates",
|
|
13
13
|
"description": "PreToolUse gates: destructive-command blocks, protected paths, delegation/spec/quality rules, tool-discovery and forge-pipeline enforcement. Which gates run is decided by .ai/config.json (project) or ~/.claude/claude-gates/config.json (global).",
|
|
14
|
-
"version": "0.
|
|
14
|
+
"version": "0.9.0"
|
|
15
15
|
},
|
|
16
16
|
{
|
|
17
17
|
"name": "tasks",
|
|
18
18
|
"source": "./plugins/tasks",
|
|
19
19
|
"description": "Deterministic task tracking: the model registers tasks via the CLI, a UserPromptSubmit hook reminds of open tasks every few messages, and a SessionStart hook lists active tasks when a session opens.",
|
|
20
|
-
"version": "0.
|
|
20
|
+
"version": "0.9.0"
|
|
21
21
|
}
|
|
22
22
|
]
|
|
23
23
|
}
|
package/README.es.md
CHANGED
|
@@ -30,7 +30,7 @@ npx @devrik-tools/claude-gates init
|
|
|
30
30
|
|
|
31
31
|
Reinicia la sesión de Claude Code (o ejecuta `/plugin`) para que los hooks carguen.
|
|
32
32
|
|
|
33
|
-
> **¿Por qué dos cosas?** El plugin **siempre trae los
|
|
33
|
+
> **¿Por qué dos cosas?** El plugin **siempre trae los 50 gates**; la configuración decide
|
|
34
34
|
> **cuáles se ejecutan**. Así puedes prender uno sin reinstalar: es una línea en un JSON.
|
|
35
35
|
|
|
36
36
|
---
|
|
@@ -67,7 +67,7 @@ ejecución), así que funciona aunque instales uno suelto por fuera.
|
|
|
67
67
|
|
|
68
68
|
---
|
|
69
69
|
|
|
70
|
-
## Los gates (
|
|
70
|
+
## Los gates (50, en 11 familias)
|
|
71
71
|
|
|
72
72
|
`[on]` = encendidos por defecto; `[off]` = los prendes si los quieres.
|
|
73
73
|
|
|
@@ -79,6 +79,7 @@ ejecución), así que funciona aunque instales uno suelto por fuera.
|
|
|
79
79
|
| `protected-paths` | on | Bloquea escrituras a `.env`, lockfiles y el propio harness. |
|
|
80
80
|
| `root-whitelist` | on | Bloquea crear archivos/carpetas nuevos en la raíz fuera de la lista blanca. |
|
|
81
81
|
| `no-blocking` | off | Bloquea `sleep`, `tail -f`, bucles de sondeo y servidores en primer plano. |
|
|
82
|
+
| `require-monitor` | on | Bloquea un comando en background (`run_in_background: true`) que no declara su monitor con el marcador `MONITOR-PLANNED:`, y bloquea cualquier ejecución posterior mientras quede un background sin monitorear. |
|
|
82
83
|
|
|
83
84
|
### 🤝 Delegation — exigencias sobre el brief al delegar a un subagente
|
|
84
85
|
| Gate | | Qué hace |
|
|
@@ -88,6 +89,7 @@ ejecución), así que funciona aunque instales uno suelto por fuera.
|
|
|
88
89
|
| `risk-level` | off | Exige declarar el nivel (QUESTION/MICRO/STANDARD/HIGH-RISK). |
|
|
89
90
|
| `circuit-breaker` | off | Corta la misma delegación reintentada sin cambios reales. |
|
|
90
91
|
| `no-memory-dependency` | off | Bloquea un brief que depende de que el subagente "recuerde" la conversación (marcador `memory-not-needed` para un falso positivo). |
|
|
92
|
+
| `force-parallel` | on | Bloquea la enésima delegación secuencial consecutiva dentro de una ventana de tiempo: las delegaciones independientes se lanzan juntas en un solo mensaje (marcador `SEQUENTIAL-JUSTIFIED` cuando la segunda depende de verdad de la primera). |
|
|
91
93
|
|
|
92
94
|
### 📋 Spec-driven flow — solo aplican si el proyecto adoptó desarrollo por specs
|
|
93
95
|
| Gate | | Qué hace |
|
|
@@ -118,12 +120,14 @@ ejecución), así que funciona aunque instales uno suelto por fuera.
|
|
|
118
120
|
| `no-coauthor` | on | Bloquea un `git commit` que lleve un trailer de atribución de IA (`Co-Authored-By`, `Generated with`, un trailer de sesión). Marcador `[allow-coauthor]` para un co-autor legítimo. |
|
|
119
121
|
| `no-lint-suppression` | on | Bloquea una escritura que silencia el linter/type-checker (`eslint-disable`, `@ts-ignore`, una regla en `off`) en vez de arreglar el código. Marcador `lint-ok: <razón>` en la misma línea para un falso positivo documentado. |
|
|
120
122
|
| `no-explanatory-comments` | on | Bloquea una escritura de código que agrega comentarios que narran qué hace el código. Solo pasan comentarios de decisión (el porqué, un trade-off, una limitación), directivas de herramientas, `TODO`/`FIXME` y etiquetas JSDoc con tipo. Juzga solo comentarios nuevos (diff contra disco). `comment-ok: <razón>` para una excepción documentada. |
|
|
123
|
+
| `no-trivial-scripts` | on | Bloquea un script inline de intérprete que hace una operación de archivos que las herramientas `Edit`/`Write` resuelven directo (`node -e` con `writeFileSync`, `python -c` con `open(…, 'w')`, `sed -i`, `perl -i`, `Set-Content`/`Add-Content`). Los scripts inline que solo computan no caen. |
|
|
121
124
|
|
|
122
125
|
### 🔎 Tool discovery — no reinventar la rueda
|
|
123
126
|
| Gate | | Qué hace |
|
|
124
127
|
|---|---|---|
|
|
125
128
|
| `reuse-before-build` | off | Antes de construir una herramienta, consulta el mapa de herramientas del proyecto; bloquea si no auditaste (local → Context7 → web). |
|
|
126
129
|
| `tool-map` | off | Registra las herramientas descubiertas en `.ai/tool-map.json` para no volver a explorar. |
|
|
130
|
+
| `skill-first` | off | Bloquea una escritura/comando/delegación que una **skill** disponible cubre de forma plausible hasta que la pregunta se haya hecho: cargar la skill, o decir por qué no aplica (`no skill covers this` / `using the <name> skill`). Lee el mismo catálogo que inyecta `capability-map`. |
|
|
127
131
|
|
|
128
132
|
### 🧠 Research flow — la memoria primero, nunca adivinar una librería
|
|
129
133
|
|
|
@@ -137,6 +141,26 @@ ejecución), así que funciona aunque instales uno suelto por fuera.
|
|
|
137
141
|
|---|---|---|
|
|
138
142
|
| `forge-flow` | off | En un proyecto que adoptó [forge](https://github.com/DevRik99/forge-mcp), bloquea editar/ejecutar si no hay un run de forge activo. Cierra el hueco que el MCP no puede: te obliga a pasar por el pipeline. |
|
|
139
143
|
|
|
144
|
+
### 🤖 Autonomy — que una corrida sin supervisión decida en vez de preguntar
|
|
145
|
+
|
|
146
|
+
| Gate | | Qué hace |
|
|
147
|
+
|---|---|---|
|
|
148
|
+
| `autonomous-mode` | off | Con el modo autónomo prendido, bloquea `AskUserQuestion` y bloquea que el turno termine solo para esperar: reinyecta, una vez por ciclo, la instrucción de decidir y seguir, dejando pendiente solo lo que de verdad necesita al usuario. |
|
|
149
|
+
|
|
150
|
+
### ⏹️ Completion — el turno no termina con trabajo abierto
|
|
151
|
+
|
|
152
|
+
| Gate | | Qué hace |
|
|
153
|
+
|---|---|---|
|
|
154
|
+
| `stop-pending` | on | Bloquea el evento Stop mientras el proyecto tiene tareas activas (`open`/`in_forge`); las lista y explica cómo cerrarlas con evidencia verificada o abandonarlas. Las tareas `blocked` no retienen el turno por defecto. |
|
|
155
|
+
| `require-task-split` | on | Bloquea escrituras y ejecución mientras una tarea activa más grande que `small` no tenga sub-tareas registradas: primero se parte en piezas verificables por separado (`task add --parent <id>`). |
|
|
156
|
+
|
|
157
|
+
### 🗂️ Task tracking — el plugin de tareas
|
|
158
|
+
|
|
159
|
+
| Gate | | Qué hace |
|
|
160
|
+
|---|---|---|
|
|
161
|
+
| `remind-open-tasks` | on | Hace que el asistente clasifique y registre el trabajo nuevo por el CLI, y recita las tareas activas cada N mensajes. |
|
|
162
|
+
| `list-tasks-on-session-start` | on | Lista las tareas activas del proyecto al abrir una sesión. Silencioso si no hay ninguna. |
|
|
163
|
+
|
|
140
164
|
### 🩺 Sesión y contexto — validaciones al arrancar e inyección de capacidades
|
|
141
165
|
| Gate | | Qué hace |
|
|
142
166
|
|---|---|---|
|
|
@@ -160,7 +184,7 @@ ves y editas cada perilla:
|
|
|
160
184
|
```json
|
|
161
185
|
{
|
|
162
186
|
"adopted": "partial",
|
|
163
|
-
"gateVersion": "3.
|
|
187
|
+
"gateVersion": "3.1.0",
|
|
164
188
|
"gates": {
|
|
165
189
|
"blockDestructiveShellCommands": {
|
|
166
190
|
"enabled": true,
|
|
@@ -194,12 +218,17 @@ ves y editas cada perilla:
|
|
|
194
218
|
commit), `lint-ok: <razón>` (un falso positivo documentado del linter), `[skip-lint]`
|
|
195
219
|
(saltea el chequeo de staged-lint por un commit), `[wip]` (permite un commit
|
|
196
220
|
deliberadamente amplio, no atómico), `comment-ok: <razón>` (un comentario explicativo que
|
|
197
|
-
debe quedarse)
|
|
221
|
+
debe quedarse), `SEQUENTIAL-JUSTIFIED` (una delegación que sí depende de la anterior),
|
|
222
|
+
`MONITOR-PLANNED:` (el comando en background declara cómo se va a monitorear).
|
|
223
|
+
`dependency-skills` se exime vía su lista `depsWithoutOwnApi`. `skill-first` se despeja
|
|
224
|
+
con una frase en el contenido/prompt: `no skill covers this`, o `using the <name> skill`.
|
|
198
225
|
- **Inyección de capacidades:** `capability-map` (on por defecto) es totalmente ajustable —
|
|
199
226
|
elegí qué tipos exponer (`"kinds": ["skills", "agents", "commands"]`), limitá cada blurb
|
|
200
227
|
(`maxClauseChars`, default 120), agregá raíces extra por tipo, regulá cada cuánto se
|
|
201
228
|
re-inyecta el catálogo completo (`injectEveryMessages`, default 10 — el archivo persistido
|
|
202
|
-
se refresca igual en cada mensaje
|
|
229
|
+
se refresca igual en cada mensaje; el catálogo TAMBIÉN se re-inyecta a mitad del throttle
|
|
230
|
+
cuando cambia el tipo de trabajo del prompt, por ejemplo depurar → publicar, lo que podés
|
|
231
|
+
apagar con `"reinjectOnWorkNatureChange": false`), o apagá la persistencia (`"persist": false`) y apuntá
|
|
203
232
|
el mapa a otro archivo (`mapFile`). Las skills también se escanean por defecto en
|
|
204
233
|
`~/.agents/skills`, `<proyecto>/.agents/skills`, `~/.ai/skills` y `<proyecto>/.ai/skills`
|
|
205
234
|
(raíces exclusivas de skills que usan otros instaladores además de `.claude/skills` — sin
|
|
@@ -231,17 +260,33 @@ El archivo rota una vez a los 5 MB (`gates-log.1.jsonl`). `CLAUDE_GATES_LOG=0` l
|
|
|
231
260
|
|
|
232
261
|
---
|
|
233
262
|
|
|
234
|
-
## Tareas:
|
|
263
|
+
## Tareas: se registran con criterio y se cierran con evidencia verificada
|
|
235
264
|
|
|
236
|
-
|
|
265
|
+
Una tarea lleva su criterio de verificación **desde que se crea** — `task add` rechaza una
|
|
266
|
+
tarea que nadie puede probar terminada — y `task close` rechaza texto libre: está hecha solo
|
|
267
|
+
cuando la verificación pasa de verdad.
|
|
237
268
|
|
|
238
269
|
```bash
|
|
270
|
+
# Registrar: el criterio es obligatorio (--verify-command o --verify-path)
|
|
271
|
+
claude-gates task add "migrar el cargador de configuración" \
|
|
272
|
+
--size medium --verify-command "npm test" --verify-expect "fail 0"
|
|
273
|
+
claude-gates task add "escribir la guía de migración" \
|
|
274
|
+
--parent <id> --verify-path docs/migration.md --verify-contains "## Upgrading"
|
|
275
|
+
|
|
276
|
+
claude-gates task list [--all] # tareas activas (o todo el historial)
|
|
277
|
+
|
|
278
|
+
# Cerrar: sin --check/--exists, se vuelve a correr el criterio propio de la tarea
|
|
279
|
+
claude-gates task close <id>
|
|
239
280
|
claude-gates task close <id> --check "npm test" --expect "fail 0" --note "suite en verde"
|
|
240
281
|
claude-gates task close <id> --exists dist/report.html --contains "All green"
|
|
241
282
|
claude-gates task abandon <id> --reason "obsoleta"
|
|
283
|
+
claude-gates task promote <id> <runId> # vincula la tarea a un run de forge
|
|
242
284
|
```
|
|
243
285
|
|
|
244
|
-
El resultado verificado (comando, código de salida, cola de la salida, fecha) queda guardado
|
|
286
|
+
El resultado verificado (comando, código de salida, cola de la salida, fecha) queda guardado
|
|
287
|
+
con la tarea. Dos gates se apoyan en este store: `require-task-split` bloquea implementar una
|
|
288
|
+
tarea más grande que `small` sin sub-tareas, y `stop-pending` impide que el turno termine
|
|
289
|
+
mientras queden tareas abiertas.
|
|
245
290
|
|
|
246
291
|
---
|
|
247
292
|
|
|
@@ -253,6 +298,8 @@ npx @devrik-tools/claude-gates init
|
|
|
253
298
|
|
|
254
299
|
# Sin menú (para CI o scripts):
|
|
255
300
|
claude-gates init --project|--global --defaults|--all|--none|--families a,b|--gates x,y --yes --dry-run
|
|
301
|
+
claude-gates init --new # SOLO los gates sobre los que esta config nunca decidió:
|
|
302
|
+
# actualizás sin volver a contestar ni tocar lo ya definido
|
|
256
303
|
claude-gates init --no-install # escribe la configuración pero no instala el plugin
|
|
257
304
|
claude-gates init --force # aplica cambios a gates ya presentes sin preguntar
|
|
258
305
|
|
|
@@ -263,12 +310,57 @@ claude-gates status # on/off efectivo por gate y su origen (pr
|
|
|
263
310
|
claude-gates log [--tail N] [--deny] [--gate id] [--since iso] [--json]
|
|
264
311
|
claude-gates doctor # ¿Claude Code corre ESTA versión del paquete?
|
|
265
312
|
|
|
313
|
+
# Tareas (el store que leen los gates de completion):
|
|
314
|
+
claude-gates task add <título> --size <tamaño> --verify-command <cmd>|--verify-path <ruta> [--parent <id>]
|
|
315
|
+
claude-gates task list [--all]
|
|
316
|
+
claude-gates task close <id> [--check <cmd> --expect <texto>] [--exists <ruta> --contains <texto>]
|
|
317
|
+
claude-gates task abandon <id> --reason <texto>
|
|
318
|
+
claude-gates task promote <id> <runId>
|
|
319
|
+
|
|
266
320
|
# Inspeccionar el catálogo:
|
|
267
321
|
claude-gates registry --list # lista familias y gates
|
|
268
322
|
claude-gates registry --check # valida registry.json y que hooks.json esté sincronizado
|
|
269
323
|
claude-gates registry --sync-hooks # regenera el hooks.json de cada plugin desde el registry
|
|
324
|
+
|
|
325
|
+
# Verificar que los gates realmente reaccionan (no solo que están enganchados):
|
|
326
|
+
claude-gates smoke # le da a cada gate una violación conocida; sale distinto de 0 si alguno no bloquea/avisa
|
|
270
327
|
```
|
|
271
328
|
|
|
329
|
+
`smoke` es el chequeo de comportamiento que `registry --check` (estructura) y el hook doctor
|
|
330
|
+
(que los archivos existan) no hacen: le da a cada gate una violación conocida y confirma que
|
|
331
|
+
de verdad deniega o avisa. Los gates cuya violación necesita estado sembrado (una db, un repo
|
|
332
|
+
git, estado entre llamadas) reportan `skip`, nunca un falso pase. Se corre después de
|
|
333
|
+
instalar, o en CI, para detectar un gate enganchado que en silencio deja pasar todo.
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## Artefactos generados
|
|
338
|
+
|
|
339
|
+
Todo lo que un agente produce que **no es código fuente** — un chequeo determinista que
|
|
340
|
+
escribió para que veas si algo funciona, una auditoría de lo que ya existe, una nota
|
|
341
|
+
explicando qué hizo — tiene una sola forma y un solo lugar, así se encuentra por convención
|
|
342
|
+
y se valida en CI en vez de caer donde al modelo se le ocurra.
|
|
343
|
+
|
|
344
|
+
```bash
|
|
345
|
+
claude-gates new check mi-afirmacion --title "..." --source "qué pidió esto"
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
| Tipo | Vive en | Para |
|
|
349
|
+
| ------- | ------------- | ---------------------------------------------------------------------- |
|
|
350
|
+
| `check` | `.ai/checks/` | Una afirmación verificable: el comando, qué debe imprimir, y la evidencia que realmente imprimió. |
|
|
351
|
+
| `audit` | `.ai/audits/` | Mirar antes de construir: buscado / existe / falta / decisión. |
|
|
352
|
+
| `note` | `.ai/notes/` | Razonamiento que si no quedaría solo en el chat. |
|
|
353
|
+
|
|
354
|
+
Cuando la misma cosa sale mal dos veces, el registro es dato y no documento: se anota la
|
|
355
|
+
**clase** de defecto en `.ai/reincidencias.json`, que `recurrence-lock` lee para bloquear
|
|
356
|
+
trabajo mutante hasta que la clase se cierre de raíz.
|
|
357
|
+
|
|
358
|
+
El contrato es `cli/artifacts.mjs`; las reglas completas están en
|
|
359
|
+
[`.ai/README.md`](./.ai/README.md). Dos tests lo sostienen — uno cubre el módulo, el otro
|
|
360
|
+
recorre el árbol `.ai/` real de este repo y falla ante cualquier artefacto desviado (sin
|
|
361
|
+
front matter, en el directorio equivocado, sin una sección obligatoria, o un check marcado
|
|
362
|
+
`passed` cuya evidencia sigue siendo el placeholder generado).
|
|
363
|
+
|
|
272
364
|
---
|
|
273
365
|
|
|
274
366
|
## Estructura del repositorio
|
|
@@ -285,7 +377,8 @@ plugins/gates/ El plugin de gates.
|
|
|
285
377
|
hooks/hooks.json Generado desde registry.json (`registry --sync-hooks`). Lo carga Claude Code.
|
|
286
378
|
hooks/lib/ Código compartido de los hooks (Node built-ins only).
|
|
287
379
|
hooks/gates/<id>/ Un gate por carpeta: index.mjs (la regla) + test.mjs (su test).
|
|
288
|
-
plugins/tasks/ El plugin de tareas
|
|
380
|
+
plugins/tasks/ El plugin de tareas: persiste tareas por proyecto, recuerda las abiertas
|
|
381
|
+
y las lista al arrancar la sesión.
|
|
289
382
|
.claude-plugin/marketplace.json Lista los plugins del marketplace.
|
|
290
383
|
```
|
|
291
384
|
|
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ npx @devrik-tools/claude-gates init
|
|
|
29
29
|
|
|
30
30
|
Restart the Claude Code session (or run `/plugin`) so the hooks load.
|
|
31
31
|
|
|
32
|
-
> **Why two things?** The plugin **always ships all
|
|
32
|
+
> **Why two things?** The plugin **always ships all 50 gates**; the config decides **which
|
|
33
33
|
> ones run**. So you can turn one on without reinstalling — it is one line in a JSON file.
|
|
34
34
|
|
|
35
35
|
---
|
|
@@ -65,7 +65,7 @@ works even if you install one on its own.
|
|
|
65
65
|
|
|
66
66
|
---
|
|
67
67
|
|
|
68
|
-
## The gates (in families)
|
|
68
|
+
## The gates (50, in 11 families)
|
|
69
69
|
|
|
70
70
|
`[on]` = enabled by default; `[off]` = enable it if you want it.
|
|
71
71
|
|
|
@@ -78,6 +78,7 @@ works even if you install one on its own.
|
|
|
78
78
|
| `protected-paths` | on | Blocks writes to `.env`, lockfiles and the harness itself. |
|
|
79
79
|
| `root-whitelist` | on | Blocks new root-level files/folders outside a whitelist. |
|
|
80
80
|
| `no-blocking` | off | Blocks `sleep`, `tail -f`, polling loops and foreground servers. |
|
|
81
|
+
| `require-monitor` | on | Blocks a background command (`run_in_background: true`) that does not declare its monitor with a `MONITOR-PLANNED:` marker, and blocks further execution while an unmonitored background command is still pending. |
|
|
81
82
|
|
|
82
83
|
### 🤝 Delegation — requirements on the brief when delegating to a subagent
|
|
83
84
|
|
|
@@ -88,6 +89,7 @@ works even if you install one on its own.
|
|
|
88
89
|
| `risk-level` | off | Requires a declared level (QUESTION/MICRO/STANDARD/HIGH-RISK). |
|
|
89
90
|
| `circuit-breaker` | off | Cuts the same delegation retried without real changes. |
|
|
90
91
|
| `no-memory-dependency` | off | Blocks a brief that relies on the subagent "remembering" the chat (add `memory-not-needed` to allow a false positive). |
|
|
92
|
+
| `force-parallel` | on | Blocks the Nth consecutive sequential delegation inside a time window: independent delegations must be launched together in one message (add `SEQUENTIAL-JUSTIFIED` when the second one really depends on the first). |
|
|
91
93
|
|
|
92
94
|
### 📋 Spec-driven flow — only relevant if the project adopted spec-driven development
|
|
93
95
|
|
|
@@ -120,6 +122,7 @@ works even if you install one on its own.
|
|
|
120
122
|
| `no-coauthor` | on | Blocks a `git commit` carrying an AI/agent attribution trailer (`Co-Authored-By`, `Generated with`, a session trailer). Add `[allow-coauthor]` for one legitimate co-author. |
|
|
121
123
|
| `no-lint-suppression` | on | Blocks a write that silences the linter/type-checker (`eslint-disable`, `@ts-ignore`, a rule set to `off`) instead of fixing the code. Add `lint-ok: <reason>` on the same line for a documented false positive. |
|
|
122
124
|
| `no-explanatory-comments` | on | Blocks 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 pass. Judges only new comments (diff against disk). Add `comment-ok: <reason>` for a documented exception. |
|
|
125
|
+
| `no-trivial-scripts` | on | Blocks an inline interpreter script that does a file operation the `Edit`/`Write` tool handles directly (`node -e` with `writeFileSync`, `python -c` with `open(…, 'w')`, `sed -i`, `perl -i`, `Set-Content`/`Add-Content`). Inline scripts that only compute are not caught. |
|
|
123
126
|
|
|
124
127
|
### 🔎 Tool discovery — don't reinvent the wheel
|
|
125
128
|
|
|
@@ -127,6 +130,7 @@ works even if you install one on its own.
|
|
|
127
130
|
| -------------------- | --- | ------------------------------------------------------------------------------------------------------------ |
|
|
128
131
|
| `reuse-before-build` | off | Before building a tool, consults the project tool map; blocks if you did not audit (local → Context7 → web). |
|
|
129
132
|
| `tool-map` | off | Records discovered tools in `.ai/tool-map.json` so exploration is not repeated. |
|
|
133
|
+
| `skill-first` | off | Blocks a write/command/delegation an available **skill** plausibly covers until the question was asked: load the skill, or say why it does not fit (`no skill covers this` / `using the <name> skill`). Reads the same catalog `capability-map` injects. |
|
|
130
134
|
|
|
131
135
|
### 🧠 Research flow — memory first, never guess a library
|
|
132
136
|
|
|
@@ -141,6 +145,26 @@ works even if you install one on its own.
|
|
|
141
145
|
| ------------ | --- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
142
146
|
| `forge-flow` | off | In a project that adopted [forge](https://github.com/DevRik99/forge-mcp), blocks editing/running unless an active forge run exists. Closes the hole the MCP cannot: it forces you through the pipeline. |
|
|
143
147
|
|
|
148
|
+
### 🤖 Autonomy — let an unattended run decide instead of asking
|
|
149
|
+
|
|
150
|
+
| Gate | | What it does |
|
|
151
|
+
| ------------------ | --- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
152
|
+
| `autonomous-mode` | off | With autonomous mode on, blocks `AskUserQuestion` and blocks a turn that ends only to wait: it re-injects, once per cycle, the instruction to decide and proceed, leaving pending only what genuinely needs the user. |
|
|
153
|
+
|
|
154
|
+
### ⏹️ Completion — a turn does not end with work still open
|
|
155
|
+
|
|
156
|
+
| Gate | | What it does |
|
|
157
|
+
| -------------------- | --- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
158
|
+
| `stop-pending` | on | Blocks the Stop event while this project has active tasks (`open`/`in_forge`); lists them and how to close them with verified evidence or abandon them. `blocked` tasks don't hold the turn by default. |
|
|
159
|
+
| `require-task-split` | on | Blocks writes and execution while an active task larger than `small` has no sub-tasks registered: split it into independently verifiable pieces first (`task add --parent <id>`). |
|
|
160
|
+
|
|
161
|
+
### 🗂️ Task tracking — the tasks plugin
|
|
162
|
+
|
|
163
|
+
| Gate | | What it does |
|
|
164
|
+
| ----------------------------- | --- | ---------------------------------------------------------------------------------------------------------- |
|
|
165
|
+
| `remind-open-tasks` | on | Makes the assistant classify and register new work via the CLI, and recites the active tasks every N messages. |
|
|
166
|
+
| `list-tasks-on-session-start` | on | Lists this project's active tasks when a session opens. Silent when there are none. |
|
|
167
|
+
|
|
144
168
|
### 🩺 Session & context — startup checks and capability injection
|
|
145
169
|
|
|
146
170
|
| Gate | | What it does |
|
|
@@ -165,7 +189,7 @@ see and edit every knob:
|
|
|
165
189
|
```json
|
|
166
190
|
{
|
|
167
191
|
"adopted": "partial",
|
|
168
|
-
"gateVersion": "3.
|
|
192
|
+
"gateVersion": "3.1.0",
|
|
169
193
|
"gates": {
|
|
170
194
|
"blockDestructiveShellCommands": {
|
|
171
195
|
"enabled": true,
|
|
@@ -206,13 +230,18 @@ see and edit every knob:
|
|
|
206
230
|
non-memory phrase), `[allow-coauthor]` (one legitimate co-author on a commit),
|
|
207
231
|
`lint-ok: <reason>` (a documented linter false positive), `[skip-lint]` (skip the
|
|
208
232
|
staged-lint check for one commit), `[wip]` (allow one deliberately broad,
|
|
209
|
-
non-atomic commit), `comment-ok: <reason>` (one explanatory comment that must stay)
|
|
210
|
-
`
|
|
233
|
+
non-atomic commit), `comment-ok: <reason>` (one explanatory comment that must stay),
|
|
234
|
+
`SEQUENTIAL-JUSTIFIED` (a delegation that genuinely depends on the previous one),
|
|
235
|
+
`MONITOR-PLANNED:` (the background command declares how it will be monitored).
|
|
236
|
+
`dependency-skills` opts out via its `depsWithoutOwnApi` list. `skill-first` clears on
|
|
237
|
+
one sentence in the content/prompt: `no skill covers this`, or `using the <name> skill`.
|
|
211
238
|
- **Capability injection:** `capability-map` (on by default) is fully tunable — pick which
|
|
212
239
|
kinds to surface (`"kinds": ["skills", "agents", "commands"]`), cap each blurb
|
|
213
240
|
(`maxClauseChars`, default 120), add extra roots per kind, throttle how often the full
|
|
214
241
|
catalog is re-injected (`injectEveryMessages`, default 10 — the persisted map file itself
|
|
215
|
-
still refreshes every message
|
|
242
|
+
still refreshes every message; the catalog is ALSO re-injected mid-throttle whenever the
|
|
243
|
+
prompt's kind of work changes, e.g. debugging → releasing, which you can turn off with
|
|
244
|
+
`"reinjectOnWorkNatureChange": false`), or turn off persistence (`"persist": false`) and point the
|
|
216
245
|
map file elsewhere (`mapFile`). Skills are also scanned by default under `~/.agents/skills`,
|
|
217
246
|
`<project>/.agents/skills`, `~/.ai/skills` and `<project>/.ai/skills` (skill-only roots some
|
|
218
247
|
installers use besides `.claude/skills` — no config needed), in addition to any
|
|
@@ -227,6 +256,35 @@ see and edit every knob:
|
|
|
227
256
|
|
|
228
257
|
---
|
|
229
258
|
|
|
259
|
+
## Generated artifacts
|
|
260
|
+
|
|
261
|
+
Everything an agent produces that is **not source code** — a deterministic check it wrote
|
|
262
|
+
so you can see whether something works, an audit of what already exists, a note explaining
|
|
263
|
+
what it did — has one shape and one home, so it can be found by convention and validated
|
|
264
|
+
in CI instead of landing wherever the model felt like.
|
|
265
|
+
|
|
266
|
+
```bash
|
|
267
|
+
claude-gates new check my-claim --title "..." --source "what asked for this"
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
| Kind | Lives in | For |
|
|
271
|
+
| ------- | ------------- | ------------------------------------------------------------------ |
|
|
272
|
+
| `check` | `.ai/checks/` | One verifiable claim: the command, what it must print, the evidence it actually printed. |
|
|
273
|
+
| `audit` | `.ai/audits/` | Looking before building: searched / exists / missing / decision. |
|
|
274
|
+
| `note` | `.ai/notes/` | Reasoning that would otherwise live only in a chat log. |
|
|
275
|
+
|
|
276
|
+
When the same thing goes wrong twice, the record is data rather than a document: register
|
|
277
|
+
the defect **class** in `.ai/reincidencias.json`, which `recurrence-lock` reads to block
|
|
278
|
+
mutating work until the class is closed at the root.
|
|
279
|
+
|
|
280
|
+
The contract is `cli/artifacts.mjs`; the full rules are in
|
|
281
|
+
[`.ai/README.md`](./.ai/README.md). Two tests keep it honest — one covers the module, the
|
|
282
|
+
other walks this repo's own `.ai/` tree and fails on any artifact that drifted (missing
|
|
283
|
+
front matter, wrong directory, a missing section, or a check marked `passed` whose
|
|
284
|
+
evidence is still the generated placeholder).
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
230
288
|
## Decision log
|
|
231
289
|
|
|
232
290
|
Every deny, warn and Stop-block is appended as one JSON line to
|
|
@@ -243,17 +301,33 @@ The file rotates once at 5 MB (`gates-log.1.jsonl`). Set `CLAUDE_GATES_LOG=0` to
|
|
|
243
301
|
|
|
244
302
|
---
|
|
245
303
|
|
|
246
|
-
## Tasks:
|
|
304
|
+
## Tasks: registered with a criterion, closed with verified evidence
|
|
247
305
|
|
|
248
|
-
|
|
306
|
+
A task carries its verification criterion **from the moment it is created** — `task add`
|
|
307
|
+
refuses a task nobody can prove done — and `task close` refuses free text: it is done only
|
|
308
|
+
when the check actually passes.
|
|
249
309
|
|
|
250
310
|
```bash
|
|
311
|
+
# Register: the criterion is mandatory (--verify-command or --verify-path)
|
|
312
|
+
claude-gates task add "migrate the config loader" \
|
|
313
|
+
--size medium --verify-command "npm test" --verify-expect "fail 0"
|
|
314
|
+
claude-gates task add "write the migration guide" \
|
|
315
|
+
--parent <id> --verify-path docs/migration.md --verify-contains "## Upgrading"
|
|
316
|
+
|
|
317
|
+
claude-gates task list [--all] # active tasks (or the whole history)
|
|
318
|
+
|
|
319
|
+
# Close: with no --check/--exists, the task's own verify criterion is re-run
|
|
320
|
+
claude-gates task close <id>
|
|
251
321
|
claude-gates task close <id> --check "npm test" --expect "fail 0" --note "suite green"
|
|
252
322
|
claude-gates task close <id> --exists dist/report.html --contains "All green"
|
|
253
323
|
claude-gates task abandon <id> --reason "obsolete"
|
|
324
|
+
claude-gates task promote <id> <runId> # link the task to a forge run
|
|
254
325
|
```
|
|
255
326
|
|
|
256
327
|
The verified result (command, exit code, output tail, timestamp) is stored with the task.
|
|
328
|
+
Two gates lean on this store: `require-task-split` blocks implementing a task bigger than
|
|
329
|
+
`small` that has no sub-tasks, and `stop-pending` blocks the turn from ending while tasks
|
|
330
|
+
are still open.
|
|
257
331
|
|
|
258
332
|
---
|
|
259
333
|
|
|
@@ -265,6 +339,8 @@ npx @devrik-tools/claude-gates init
|
|
|
265
339
|
|
|
266
340
|
# Non-interactive (for CI or scripts):
|
|
267
341
|
claude-gates init --project|--global --defaults|--all|--none|--families a,b|--gates x,y --yes --dry-run
|
|
342
|
+
claude-gates init --new # ONLY gates this config never decided about — upgrade
|
|
343
|
+
# without re-answering or changing anything already set
|
|
268
344
|
claude-gates init --no-install # write the config but do not install the plugin
|
|
269
345
|
claude-gates init --force # apply changes to gates already in the file without asking
|
|
270
346
|
|
|
@@ -275,6 +351,13 @@ claude-gates status # effective on/off per gate and its source
|
|
|
275
351
|
claude-gates log [--tail N] [--deny] [--gate id] [--since iso] [--json]
|
|
276
352
|
claude-gates doctor # is Claude Code running THIS package version of the plugins?
|
|
277
353
|
|
|
354
|
+
# Tasks (the store the completion gates read):
|
|
355
|
+
claude-gates task add <title> --size <size> --verify-command <cmd>|--verify-path <path> [--parent <id>]
|
|
356
|
+
claude-gates task list [--all]
|
|
357
|
+
claude-gates task close <id> [--check <cmd> --expect <text>] [--exists <path> --contains <text>]
|
|
358
|
+
claude-gates task abandon <id> --reason <text>
|
|
359
|
+
claude-gates task promote <id> <runId>
|
|
360
|
+
|
|
278
361
|
# Inspect the catalog:
|
|
279
362
|
claude-gates registry --list # list families and gates
|
|
280
363
|
claude-gates registry --check # validate registry.json and that hooks.json is in sync
|
|
@@ -306,7 +389,8 @@ plugins/gates/ The gates plugin.
|
|
|
306
389
|
hooks/hooks.json Generated from registry.json (`registry --sync-hooks`). Loaded by Claude Code.
|
|
307
390
|
hooks/lib/ Shared hook code (Node built-ins only).
|
|
308
391
|
hooks/gates/<id>/ One gate per folder: index.mjs (the rule) + test.mjs (its test).
|
|
309
|
-
plugins/tasks/ The tasks plugin
|
|
392
|
+
plugins/tasks/ The tasks plugin: persists per-project tasks, reminds of the open ones
|
|
393
|
+
and lists them on session start.
|
|
310
394
|
.claude-plugin/marketplace.json Lists the marketplace plugins.
|
|
311
395
|
```
|
|
312
396
|
|