navori 0.11.3 → 0.12.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/README.md +42 -56
- package/dist/assets/core/core-assets/agents/architect.md +1 -1
- package/dist/assets/core/core-assets/agents/implementer.md +9 -5
- package/dist/assets/core/core-assets/agents/orchestrator.md +7 -5
- package/dist/assets/core/core-assets/agents/publisher.md +23 -42
- package/dist/assets/core/core-assets/agents/reviewer.md +25 -21
- package/dist/assets/core/core-assets/hooks/_partials/audit-log.sh +2 -2
- package/dist/assets/core/core-assets/hooks/_partials/audit-signal.sh +1 -1
- package/dist/assets/core/core-assets/hooks/_partials/bash-outcome.sh +28 -3
- package/dist/assets/core/core-assets/hooks/_partials/draft-body.sh +216 -0
- package/dist/assets/core/core-assets/hooks/_partials/hook-input.sh +7 -1
- package/dist/assets/core/core-assets/hooks/_partials/inert-skeleton.sh +352 -0
- package/dist/assets/core/core-assets/hooks/_partials/resolve-worktree.sh +5 -4
- package/dist/assets/core/core-assets/hooks/comment-draft-confirm.sh +14 -195
- package/dist/assets/core/core-assets/hooks/guard-destructive.sh +142 -325
- package/dist/assets/core/core-assets/hooks/managed-drift-watch.sh +10 -0
- package/dist/assets/core/core-assets/hooks/pr-publisher-confirm.sh +36 -0
- package/dist/assets/core/core-assets/hooks/quality-gate-pre-commit.sh +106 -36
- package/dist/assets/core/core-assets/hooks/session-start-context.sh +28 -2
- package/dist/assets/core/core-assets/hooks/subagent-no-background.sh +42 -9
- package/dist/assets/core/core-assets/hooks/worktree-reclaim.sh +11 -0
- package/dist/assets/core/core-assets/managed/cierre-sesion.md +2 -2
- package/dist/assets/core/core-assets/managed/intake-tickets.md +2 -2
- package/dist/assets/core/core-assets/managed/sdd.md +4 -2
- package/dist/assets/core/core-assets/skills/resolve-ticket.md +13 -2
- package/dist/assets/core/core-assets/skills/review-diff.md +1 -1
- package/dist/assets/core/core-assets/skills/scoped-gate.md +1 -5
- package/dist/assets/core/core-assets/skills/security-invariants.md +3 -3
- package/dist/assets/core/core-assets/skills/solution-design.md +3 -1
- package/dist/assets/core/core-assets/skills/spec-bootstrap.md +6 -4
- package/dist/assets/plugins/gh/plugin.json +2 -8
- package/dist/index.js +1595 -547
- package/package.json +4 -5
- package/dist/assets/core/core-assets/hooks/_partials/scan-scope.sh +0 -113
- package/dist/assets/plugins/gh/managed/gh-protocol.md +0 -12
- package/dist/assets/plugins/jscpd/managed/jscpd-protocol.md +0 -10
- package/dist/assets/plugins/jscpd/plugin.json +0 -57
- package/dist/assets/plugins/jscpd/scripts/check-jscpd.sh +0 -329
- package/dist/assets/plugins/jscpd/skills/jscpd-review.md +0 -26
- package/dist/assets/plugins/semgrep/plugin.json +0 -51
- package/dist/assets/plugins/semgrep/scripts/check-semgrep.sh +0 -345
- package/dist/assets/plugins/semgrep/skills/semgrep-review.md +0 -27
package/README.md
CHANGED
|
@@ -18,6 +18,9 @@ También renderiza un harness Codex completo: `AGENTS.md`, skills en
|
|
|
18
18
|
|
|
19
19
|
// Solo guía universal, con el menor número de archivos
|
|
20
20
|
{ "engines": ["agents-md"] }
|
|
21
|
+
|
|
22
|
+
// Solo Pi (opt-in; ver docs/pi.md)
|
|
23
|
+
{ "engines": ["pi"] }
|
|
21
24
|
```
|
|
22
25
|
|
|
23
26
|
`codex` ya incluye y administra `AGENTS.md`; no necesitas combinarlo con
|
|
@@ -41,7 +44,7 @@ npx navori init
|
|
|
41
44
|
cd ~/tu-repo
|
|
42
45
|
navori init --recommended
|
|
43
46
|
|
|
44
|
-
# + proveedores externos (tgrep,
|
|
47
|
+
# + proveedores externos (tgrep, acli) + pre-commit hook +
|
|
45
48
|
# scan-monorepo + project block estricto — requiere instalar los binarios de esos proveedores.
|
|
46
49
|
# También avisa si falta algún binario y cómo instalarlo, sin instalarlo nunca.
|
|
47
50
|
navori init --full
|
|
@@ -115,7 +118,8 @@ de caché de ambos directorios.
|
|
|
115
118
|
| `remove <plugin>` | Desactiva un plugin y limpia sus bloques managed, sub-bloques y scripts |
|
|
116
119
|
| `configure <section>` | Ajusta una sección del config sin re-correr el wizard |
|
|
117
120
|
| `adopt <path>` | Toma un archivo de `.claude/` que escribiste a mano bajo gestión de navori: lo envuelve en un bloque managed sin reescribir su contenido (preview por default) |
|
|
118
|
-
| `
|
|
121
|
+
| `refresh` | Re-detecta el repo, refresca config y corre sync en un paso |
|
|
122
|
+
| `update` | Actualiza el propio navori desde npm y luego corre `refresh` con el binario nuevo (ver [Actualizar navori](#actualizar-navori)) |
|
|
119
123
|
| `render` | Genera los archivos nativos de cada engine configurado (preview por default; `--apply` escribe). `--all` renderea todos los repos del registro global; `--prune` limpia los que ya no existen |
|
|
120
124
|
| `registry <sub>` | Registro global de tus repos con navori, para `render --all` (`ls`, `scan <dir>`, `add`, `remove`, `prune`) |
|
|
121
125
|
| `sync` | Refresca todos los engines configurados con conflict resolution + backups. Los bloques en conflicto se resuelven con `--interactive` (diff, keep-mine / accept-new) o en bloque con `--accept-new` / `--keep-mine`. Los archivos completos sin marcador se resuelven archivo por archivo en modo interactivo (diff, keep / accept); `--accept-new-files` acepta en bloque los resolvibles |
|
|
@@ -124,17 +128,17 @@ de caché de ambos directorios.
|
|
|
124
128
|
| `doctor` | Audita el config + drift de cada managed block (CLAUDE.md **y AGENTS.md**), orden canónico, markers malformados, desincronización de monorepo y tools externas faltantes (`--strict` para CI). Informativo, sin afectar `--strict`: versiones instaladas con problema conocido (`externalTool.versionAdvisory`) y avisos de versiones nuevas de herramientas (`navori tools notice`) |
|
|
125
129
|
| `status` | Snapshot rápido: config, plugins activos, conteo de drift y próximos pasos |
|
|
126
130
|
| `audit` | Reporta cómo corrió el harness de verdad: atribución de tokens, huecos de adherencia y outcomes de revisión y receipt; disponibilidad de herramientas por ventanas; eficiencia y ciclo de vida por tarea aceptada. `--snapshot` guarda una foto nombrada del rango y `--compare` la contrasta con otra por cohorte, con causas y evidencia |
|
|
127
|
-
| `
|
|
131
|
+
| `gate <fast\|full>` | Corre `qualityGate.fast` o `qualityGate.full` con la salida completa en un log (`.navori/state/gate/`) y solo un veredicto compacto en stdout. Flag: `--cwd <path>` |
|
|
132
|
+
| `receipt <sub>` | Recibo de los bytes revisados antes de publicar: `sign` (`--feature <id>`, `--gate-ran scoped\|full`, `--spec <dir> --milestone <Mn>` o `--phase <name\|index>`), `check`, `gate --spec <dir> --milestone <Mn>` o `--phase <name\|index>` (decide si el milestone necesita el gate acotado o el completo) y `review begin` / `review seal --nonce <n>` (sidecar de revisión con identidad de contenido). Flags comunes: `--target <ref>`, `--dir <path>`, `--json` |
|
|
128
133
|
| `spec <classify\|check> <feature>` | `classify` decide si una spec sale en 1 PR o en una PR por entrega (umbrales de `sdd.deliveries`); `check` valida su `tasks.md`: milestones, criterios, cobertura y entregas verticales. Flags: `--cwd`, `--json` |
|
|
129
134
|
| `tools notice [--ack <pluginId@x.y.z,…>]` | Emite los avisos de versiones de herramientas externas pendientes para el hook de arranque; `--ack` los marca como entregados |
|
|
130
|
-
| `handoff <check>` |
|
|
135
|
+
| `handoff <check\|log-review>` | `check` valida el handoff del implementer (`impl_<feature>.json`) antes de despachar al siguiente agente; `log-review <feature>` valida `review_<feature>.json` y agrega a `findings.jsonl` los hallazgos con score >= 50 (`navori handoff check <feature> [--for scribe] [--produced-by reviewer [--since <iso>]] [--dir <path>] [--cwd <checkout>] [--json]`) |
|
|
131
136
|
| `plan <sub>` | Planificación por niveles (`harness.planTiers`): `classify [--files\|--diff]` mide complejidad y nivel de una tarea, `render`/`update` mantienen el workplan Markdown en sync con su JSON, `check` valida su esquema y reglas, `gate` es el hook `PreToolUse(Agent)` que niega el despacho sin workplan válido |
|
|
132
137
|
| `master <sub>` | Flujo guiado del plan maestro por etapas (`init`, `ux`, `mode`, `template`, `check`, `advance`, `status`, `part`, `close`) y entregas de sus partes: `delivery-slice`, `delivery-check`, `delivery-baseline`, `delivery-queue`, `delivery-criterion`, `delivery-review`, `delivery-present`, `delivery-decision`, `delivery-publication`, `delivery-revoke`. Las que autorizan o aprueban llevan `--approved-by` |
|
|
133
138
|
| `bench` | Corre `render` en dry-run N veces y reporta latencias (detecta regresiones locales) |
|
|
134
139
|
| `workspace <sub>` | Gestiona workspaces cross-repo (`init`, `ls`, `show`, `link`, `add-repo`, `set-default`, `render`, `rename`, `delete`) |
|
|
135
140
|
| `ticket <sub>` | Gestiona tickets-as-files en un workspace (`new`, `list`, `show`, `archive`, `delete`) |
|
|
136
141
|
| `dominio <sub>` | Base de conocimiento durable del workspace (`init`, `list`, `show`, `reindex`, `doctor`, `inject`) |
|
|
137
|
-
| `global <sub>` | Harness base por máquina en `~/.claude` (`init`, `render`, `doctor`, `uninstall`) — opt-in explícito y aditivo. `global collect install` / `uninstall` gestionan el receptor OTel que alimenta `audit --collect` (launchd, solo macOS) |
|
|
138
142
|
| `codex <sub>` | Comandos específicos de Codex; hoy `trust` aprueba los hooks del proyecto en `~/.codex/config.toml` |
|
|
139
143
|
| `backup <sub>` | Lista y restaura backups de `~/.navori/backups/` |
|
|
140
144
|
| `migrations <sub>` | Lista y restaura migraciones de `~/.navori/migrations/` |
|
|
@@ -185,8 +189,6 @@ La resolución es **local → bundled**: si tienes un preset local con el mismo
|
|
|
185
189
|
| `tgrep` | Descubrimiento textual de código vía CLI indexado | `tgrep` binary |
|
|
186
190
|
| `acli` | Leer tickets de Jira desde la terminal | `acli` |
|
|
187
191
|
| `gh` | GitHub Issues, PRs y workflow runs | `gh` |
|
|
188
|
-
| `jscpd` | Detección de duplicación en el diff | `jscpd` (opt-in) |
|
|
189
|
-
| `semgrep` | Security gate local | `semgrep` (opt-in) |
|
|
190
192
|
|
|
191
193
|
> `codegraph` y `tgrep` se retiraron brevemente el 2026-09-15 y se reintrodujeron el
|
|
192
194
|
> 2026-09-16 (#838) con una integración que los hace trabajar entre sí — acta en
|
|
@@ -319,7 +321,7 @@ un aviso que **nombra** los repos con bloques editados a mano (conflict, que el
|
|
|
319
321
|
render no pisa) y un roll-up `ok · changed · conflict · failed`.
|
|
320
322
|
|
|
321
323
|
El registro (`~/.navori/registry.json`) se puebla solo: cada `navori init` /
|
|
322
|
-
`navori
|
|
324
|
+
`navori refresh` te da de alta. Para arrancar con lo que ya tenías instalado,
|
|
323
325
|
escanéalo una vez:
|
|
324
326
|
|
|
325
327
|
```bash
|
|
@@ -331,52 +333,6 @@ navori registry prune # quitar los que ya no existen
|
|
|
331
333
|
Es ortogonal a los workspaces: el registro es "qué repos existen"; el workspace
|
|
332
334
|
es el perfil de policy (branchBase/prTarget) que cada repo hereda.
|
|
333
335
|
|
|
334
|
-
## Harness global por máquina (opt-in)
|
|
335
|
-
|
|
336
|
-
Todo lo de arriba es por repo. Cuando abres una sesión **fuera** de un repo con navori (un scratch,
|
|
337
|
-
un repo ajeno, tu `~`), no hay harness: ni doctrina de orquestación, ni skills, ni agentes. La capa
|
|
338
|
-
global cubre ese hueco. No la confundas con `render --all` de la sección anterior: aquélla empuja tu
|
|
339
|
-
harness a los repos que **ya** tienen navori; ésta cubre las sesiones que no están en ninguno.
|
|
340
|
-
|
|
341
|
-
Es **opt-in de huella cero**: si nunca corres `navori global init`, no existe `~/.navori/global.json`
|
|
342
|
-
y navori no escribió un solo byte en tu máquina.
|
|
343
|
-
|
|
344
|
-
```bash
|
|
345
|
-
navori global init # wizard: bloques del baseline + permisos personales.
|
|
346
|
-
# Preview: sin --apply no escribe un solo byte
|
|
347
|
-
navori global init --apply # escribe lo que el preview mostró
|
|
348
|
-
navori global init --recommended --apply # headless (CI): sin preguntas, selección recomendada
|
|
349
|
-
navori global doctor # audita: drift del hook, gate, plugin, permisos y versión
|
|
350
|
-
navori global render --apply # re-renderiza tras un bump del CLI (preview sin --apply)
|
|
351
|
-
navori global uninstall # la retira por completo
|
|
352
|
-
```
|
|
353
|
-
|
|
354
|
-
El `init` pregunta dos cosas: **qué bloques** componen el baseline (los que declaran `globalSafe`)
|
|
355
|
-
y **qué permisos personales** quieres en `~/.claude/settings.json` — ése es el único camino de UI
|
|
356
|
-
para `permissions`. Re-inicializar **preserva** lo que ya habías elegido: no te resetea a los
|
|
357
|
-
defaults. Sin TTY (CI, pipe) cae solo al camino de `--recommended`, y `--lang es|en` fija el idioma
|
|
358
|
-
del baseline y de los prompts.
|
|
359
|
-
|
|
360
|
-
Qué escribe el `init --apply`, y nada más:
|
|
361
|
-
|
|
362
|
-
- `~/.navori/global.json` — el manifest: idioma, bloques del baseline y tus permisos globales.
|
|
363
|
-
- `~/.claude/skills/navori/` — el plugin `navori@skills-dir` con los 8 agentes, las 11 skills y el
|
|
364
|
-
hook del baseline. Claude Code lo carga sin marketplace ni paso de instalación; las skills globales
|
|
365
|
-
se invocan `/navori:<nombre>` (tras un render, `/reload-plugins` o sesión nueva).
|
|
366
|
-
- `~/.claude/settings.json` — **solo** la clave `permissions`, y solo si declaraste permisos globales
|
|
367
|
-
en el manifest. Con la config por default ni siquiera lo crea.
|
|
368
|
-
|
|
369
|
-
Respeta `CLAUDE_CONFIG_DIR`: si lo tienes seteado, el plugin va ahí en vez de a `~/.claude`.
|
|
370
|
-
|
|
371
|
-
**El baseline se hace a un lado solo.** El hook corre en `SessionStart` y busca un `navori.config.json`
|
|
372
|
-
hacia arriba desde el directorio de la sesión: si lo encuentra, no emite nada — manda el harness del
|
|
373
|
-
repo, que es más específico. Por eso el baseline viaja dentro de un hook y no como bloque estático en
|
|
374
|
-
`~/.claude/CLAUDE.md`: ese archivo se carga siempre y no podría cederle el paso a nadie.
|
|
375
|
-
|
|
376
|
-
`navori global uninstall` retira **solo lo que navori escribió**: el plugin, el manifest y los permisos
|
|
377
|
-
que quedaron registrados como suyos. Un permiso que ya tenías en tu `settings.json` nunca se vuelve de
|
|
378
|
-
navori, así que el uninstall no se lo lleva.
|
|
379
|
-
|
|
380
336
|
## Managed blocks con versionado
|
|
381
337
|
|
|
382
338
|
Cada bloque que `navori` inyecta en tu `CLAUDE.md` lleva metadata:
|
|
@@ -408,9 +364,9 @@ Cambiar una sola cosa sin re-init:
|
|
|
408
364
|
|
|
409
365
|
```bash
|
|
410
366
|
navori configure plugins # multiselect de plugins activos
|
|
411
|
-
navori configure quality-gate #
|
|
367
|
+
navori configure quality-gate # comandos del quality gate
|
|
412
368
|
navori configure language en # switch a inglés (fallback a es)
|
|
413
|
-
navori configure engines # multiselect: claude / codex / agents-md / cursor / copilot
|
|
369
|
+
navori configure engines # multiselect: claude / codex / agents-md / cursor / copilot / pi
|
|
414
370
|
navori configure branch-base main # punto de fork / rama protegida
|
|
415
371
|
navori configure pr-target develop # rama destino del PR (gh pr create --base)
|
|
416
372
|
navori configure workspace bonum # asociar a un workspace
|
|
@@ -424,6 +380,24 @@ retiradas caen en la misma con valores distintos no se infiere nada — se pregu
|
|
|
424
380
|
`--scout=<modelo> --scout-effort=<nivel>`. `--dry-run` no escribe, y `--all` barre el registry
|
|
425
381
|
completo (preview salvo `--apply`).
|
|
426
382
|
|
|
383
|
+
### Claves de config para el gate y los hooks nativos
|
|
384
|
+
|
|
385
|
+
- `qualityGate.scoped` (string): carril acotado del reviewer — los checks baratos de `full` más los tests relacionados con el diff. Si falta, usa `fast`. Se interpola como `navori.scopedGate`.
|
|
386
|
+
- `qualityGate.nativeHooks` (boolean): declara que el pre-commit nativo del proyecto ya corre `fast`; el hook `quality-gate-pre-commit` omite solo su paso de gate.
|
|
387
|
+
- `plugins.<id>.nativeHook` (boolean): el hook git nativo corre el check de ese plugin, así que su hook no se registra (los scripts se siguen instalando).
|
|
388
|
+
|
|
389
|
+
### Tope de `progress/current.md`
|
|
390
|
+
|
|
391
|
+
`progress/current.md` se carga en cada sesión, así que tiene un tope. El hook pre-commit bloquea los commits de agente que lo dejan sobre el tope duro o lo hacen crecer estando ya sobre él (los commits humanos no se bloquean). `navori doctor` lo mide en bytes con los mismos topes y avisa; el hook de inicio de sesión advierte, sin bloquear, al pasar el tope suave.
|
|
392
|
+
|
|
393
|
+
## Migrando a 0.12
|
|
394
|
+
|
|
395
|
+
- Se retiró el comando `global` y el colector launchd (`audit --collect` sigue). `doctor --json` ya no emite `globalScope`.
|
|
396
|
+
- Se retiraron los plugins `jscpd` y `semgrep`: `navori add jscpd|semgrep` responde que están retirados.
|
|
397
|
+
- El piso de Pi sube a 1.1.0: Pi 0.87.x pierde `navori_subagent`. Node mínimo: >= 22.12.
|
|
398
|
+
- `navori update` ahora actualiza el CLI (consulta npm, confirma, instala y luego corre `navori refresh`). El comportamiento anterior es ahora `navori refresh`, sin alias: los scripts que usaban `navori update` para re-sincronizar el harness deben cambiar a `navori refresh`.
|
|
399
|
+
- Migra con `navori render --apply` (poda los assets retirados que navori gestionaba) y luego `navori doctor` (reporta los restos).
|
|
400
|
+
|
|
427
401
|
## Extender el harness en tu repo
|
|
428
402
|
|
|
429
403
|
navori instala un baseline; lo que lo vuelve valioso en **tu** repo es el conocimiento que sólo
|
|
@@ -477,3 +451,15 @@ Contrato del `SKILL.md`: [`docs/recipes/skill-authoring.md`](https://github.com/
|
|
|
477
451
|
## Licencia
|
|
478
452
|
|
|
479
453
|
MIT.
|
|
454
|
+
|
|
455
|
+
## Actualizar navori
|
|
456
|
+
|
|
457
|
+
`navori update` consulta npm por la última versión de navori y muestra el comando de
|
|
458
|
+
instalación según cómo lo tengas: npm global, devDependency, dependency o `npx`. Pide
|
|
459
|
+
confirmación (salvo `--yes`), instala y corre `navori refresh` con el binario nuevo.
|
|
460
|
+
|
|
461
|
+
- `--cli-only`: se detiene tras actualizar el CLI, sin `refresh`.
|
|
462
|
+
- Sin red o ya en la última versión: corre `refresh` directo.
|
|
463
|
+
- Si la instalación falla: imprime el comando manual y sale con código 1.
|
|
464
|
+
- Sin TTY y sin `--yes`: imprime el comando y sale con código 1.
|
|
465
|
+
- Solo soporta npm.
|
|
@@ -29,7 +29,7 @@ For a **master-plan** task, write the requested `<etapa>/plans/plan<n>.md` and p
|
|
|
29
29
|
|
|
30
30
|
Use URLs de documentación oficial for expiring facts and include the fecha de consulta. If a source is unavailable, label the claim `[SIN VERIFICAR]` and list the sources consulted or unavailable.
|
|
31
31
|
|
|
32
|
-
Via `Agent` you may dispatch `scout`/`scribe`; plan-gate and Agent hooks fire inside you with `agent_id`, expected
|
|
32
|
+
<!-- navori:if-not onPi -->Via `Agent` you may dispatch `scout`/`scribe`; plan-gate and Agent hooks fire inside you with `agent_id`, expected.<!-- /navori:if-not -->
|
|
33
33
|
|
|
34
34
|
## Protocol
|
|
35
35
|
|
|
@@ -5,7 +5,7 @@ tools: Read, Write, Edit, Glob, Grep, Bash
|
|
|
5
5
|
model: {{models.implementer}}
|
|
6
6
|
effort: {{effort.implementer}}
|
|
7
7
|
maxTurns: 160
|
|
8
|
-
maxWords:
|
|
8
|
+
maxWords: 2473
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
# Implementer Agent
|
|
@@ -27,7 +27,7 @@ You execute **a single** task from start to verification. You don't orchestrate,
|
|
|
27
27
|
- [ ] Define interface in <path>
|
|
28
28
|
- [ ] Implement logic in <path>
|
|
29
29
|
- [ ] Cover with a test
|
|
30
|
-
- [ ] Run `{{
|
|
30
|
+
- [ ] Run `{{gateRun.fast}}`
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
- `Expected files: <list>`
|
|
@@ -38,10 +38,12 @@ You execute **a single** task from start to verification. You don't orchestrate,
|
|
|
38
38
|
4. **Quality gate** (mandatory before returning):
|
|
39
39
|
|
|
40
40
|
```bash
|
|
41
|
-
{{
|
|
41
|
+
{{gateRun.fast}}
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
If
|
|
44
|
+
If `navori gate <kind>` prints no first line `navori gate <kind>: exit <N> — log <path>`, it did not run: run the literal `{{qualityGate.fast}}`. Open the log only on a red.
|
|
45
|
+
|
|
46
|
+
If it fails: fix it and re-run. Don't return with red. You are the single owner of this gate run: never share it with another process, never poll `pgrep`/`ps` for it, and a timeout is never a success signal. If the gate can outlive the Bash timeout, follow `.claude/skills/verify-before-done/SKILL.md`'s subagent row: run its chained steps one by one in the foreground, never background them (<!-- navori:if-not onCodex -->no shell `&`, no `run_in_background`, no `Monitor`<!-- /navori:if-not --><!-- navori:if onCodex -->no shell `&`, no background execution<!-- /navori:if -->) — you won't be re-woken to read the result. If no chained step fits under any foreground timeout, stop and report `BLOCKED` instead of improvising a background wait. When you can't explain WHY it failed, apply `.claude/skills/debug-failure/SKILL.md` before touching anything. If your second fix attempt fails the same way, that same skill's hypothesis re-check governs instead of throwing a third patch.
|
|
45
47
|
5. **UI**: for screen changes, the default evidence is the repo's tests plus a correct diff — **do NOT spin up a browser or dev server automatically**. Visual/browser validation is **optional and strictly on-request**: run it only when the user explicitly asks to check the UI in this prompt, and then drive the repo's browser-automation tool if one is set up (e.g. `playwright-cli`, whose installer ships its own skill).
|
|
46
48
|
6. **No commits** without the `reviewer`'s approval. When you finish, <!-- navori:if-not scribeOwnsMarkdown -->write the report<!-- /navori:if-not --><!-- navori:if scribeOwnsMarkdown -->write your JSON evidence<!-- /navori:if --> and return the reference.
|
|
47
49
|
<!-- navori:if planTiers -->
|
|
@@ -60,7 +62,7 @@ When the encargo opens with `workplan: <feature>`, read `.navori/state/handoffs/
|
|
|
60
62
|
- **Zero new errors** introduced by your code in the quality gate tools (vs. baseline) — classify per `verify-before-done`'s Failure attribution, never by diff location alone; see the evidence table below. Returning with any tool red (because of your change) is automatic grounds for `CHANGES_REQUESTED`.
|
|
61
63
|
- **Never mutate or discard the shared working tree**: no stashing, no checkout/reset that discards local changes, no working-tree clean — these hit the `ask` permission rule and can stall a background agent indefinitely. Same reasoning for scratch files: leave them, don't clean them with a recursive delete.
|
|
62
64
|
- **JSDoc** mandatory on public exports and functions >15 lines or with dense conditional logic.
|
|
63
|
-
- **SDD traceability** (only if the feature has `{{sdd.specsDir}}/<feature>/tasks.md`, see
|
|
65
|
+
- **SDD traceability** (only if the feature has `{{sdd.specsDir}}/<feature>/tasks.md`, see `spec-bootstrap`): each `R<n>` in your batch is covered by ≥1 test, and each test references its requirements with a `// Covers: R<n>` comment above the case. Without full traceability the `reviewer` rejects.
|
|
64
66
|
- **Guard/policy coverage** (only if your task introduces or modifies a guard, policy or permission check): your report carries the enumeration, not just the diff — every entry point that mutates the same resource (routes, bulk/admin variants, jobs, scripts) with its `file:line` evidence, each marked covered or excluded with the reason. Locate them with `locate-code`; an entry point you didn't list is one the `reviewer` has to rediscover.
|
|
65
67
|
- If a tool fails weirdly (e.g. tsc breaks with no apparent diff), **don't improvise a workaround**: note `Status: BLOCKED` + the reason in `.navori/state/handoffs/impl_<feature>.md` and stop.
|
|
66
68
|
- **While iterating, run only the tests of the area you touch** (filter by the runner's path). The full gate in step 4 runs at the end, not on each iteration — saves time and context. Never run the full `{{qualityGate.full}}` suite yourself: that's the `reviewer`'s Pass 2 job, and it commonly outlives Bash's timeout. If this repo has a diff-scoped fast check (`scoped-gate`), it's hygiene for iterating, never a substitute for step 4.
|
|
@@ -163,6 +165,8 @@ Write `.navori/state/handoffs/impl_<feature>.json` — the only artifact you pro
|
|
|
163
165
|
|
|
164
166
|
`doubts` is optional: declare one `{ "file": "<path>", "reason": "<why you are unsure>" }` entry per spot where you are unsure the change is right, so the reviewer answers it.
|
|
165
167
|
|
|
168
|
+
Types follow the handoff schema: `rootCause` is a string, present only for a bugfix (omit the key otherwise, never `null`); `blockers` is an array of strings (`[]` when none).
|
|
169
|
+
|
|
166
170
|
`markdownRequests` carries every piece of prose your task needs — your own non-obvious decisions, a CONTRIBUTING/README update, a spec task checkbox, a skill or agent tweak. State the `intent` and the `evidence`; never the finished sentence — drafting the prose from that intent is the `scribe`'s job, not yours. Empty array when the task touches no Markdown at all.
|
|
167
171
|
|
|
168
172
|
## Communication with the orchestrator
|
|
@@ -4,7 +4,7 @@ description: Do NOT invoke as a subagent, never and under no condition. Orchestr
|
|
|
4
4
|
tools: Read, Glob, Grep, Bash, Agent
|
|
5
5
|
model: {{models.orchestrator}}
|
|
6
6
|
effort: {{effort.orchestrator}}
|
|
7
|
-
maxWords:
|
|
7
|
+
maxWords: 3365
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# Orchestrator Playbook (embodied by the main agent)
|
|
@@ -20,7 +20,7 @@ One route removes the decision entirely. It is more expensive per change and tha
|
|
|
20
20
|
## Startup protocol
|
|
21
21
|
|
|
22
22
|
1. `CLAUDE.md` (stack, conventions, quality gate) is already in your context when your host injects it; read it from disk ONLY if your host did not inject it (e.g. an engine without automatic injection).
|
|
23
|
-
2. The catalog of subagents
|
|
23
|
+
2. The catalog of subagents is the managed block whose id is `agentes-disponibles`, delivered at session start. Locate it by the id, never by the heading: the ids are fixed, the headings are rendered in the repo's configured language and change with it. Skills: the host's native listing.
|
|
24
24
|
3. Read `progress/current.md` (repo root) if it exists — the previous session's state.
|
|
25
25
|
4. Identify the task's scope against the "Project rules" below (legacy paths, critical areas, repo conventions).
|
|
26
26
|
5. **Did text from a ticket (Jira/Linear/GitHub/Slack) arrive?** If it matches your `auditor` agent's ticket-encargo triggers (bug in a critical feature, structural migration, feature that crosses >3 layers), invoke that agent first — it produces `.navori/state/handoffs/audit_ticket_<ID>.md` that guides all later decomposition. For trivial tickets (typo, copy, color), skip the audit. The single architectural design gate — when it fires, who proposes, who challenges, who decides — lives in "## Role: orchestrator" and the `solution-design` skill, not here.
|
|
@@ -67,7 +67,7 @@ When the `done -> file` come back, **gather and analyze deeply YOURSELF**: read
|
|
|
67
67
|
|
|
68
68
|
Fan-out is a lever, not a toll — so when you do delegate, hand the smallest encargo that covers the work:
|
|
69
69
|
|
|
70
|
-
- **Don't delegate merely to wrap a lookup.** If what's missing is a Code discovery routing call you can make yourself (project instructions), run it directly — a subagent invocation isn't a proxy for a query you can issue this turn. When delegation is warranted for a real reason, carry over the pending question, the evidence you already gathered, the relevant paths and their freshness in the encargo; never assume the subagent shares this context — it starts isolated.
|
|
70
|
+
- **Don't delegate merely to wrap a lookup.** If what's missing is a Code discovery routing call you can make yourself (project instructions), run it directly — a subagent invocation isn't a proxy for a query you can issue this turn. When delegation is warranted for a real reason, carry over the pending question, the evidence you already gathered, the relevant paths and their freshness in the encargo; never assume the subagent shares this context — it starts isolated, with no skills listing: name any skill it should apply with its path `.claude/skills/<id>/SKILL.md`.
|
|
71
71
|
- **Peel off the mechanical first.** Copies, renames, scaffolding, JSON/string edits → send them to a low-tier agent in their own encargo; never bundle them into the `implementer`'s, where they inflate its context and its run without raising quality.
|
|
72
72
|
- **One encargo = one unit.** A pre-existing bug the `implementer` hits outside its scope → it reports and stops there (a trivial one-liner is the exception); **you** decide whether to open a separate unit. Scope doesn't self-expand mid-run.
|
|
73
73
|
- **Tier by sub-task, not by round.** A single fix round can mix tiers. Map: **low** → mechanical work (copies, renames, scaffolding, string/JSON edits, a one-line fix); **mid** → a scoped bugfix with a clear cause or a bounded feature; **high** → judgment work (design, security regex, ambiguous root-cause, removal semantics, critical areas).
|
|
@@ -155,10 +155,12 @@ And never take a merged PR as proof on its own: **squash merge leaves no ancestr
|
|
|
155
155
|
## Quality gate
|
|
156
156
|
|
|
157
157
|
```bash
|
|
158
|
-
{{
|
|
159
|
-
{{
|
|
158
|
+
{{gateRun.fast}} # fast gate — pre-step to the reviewer
|
|
159
|
+
{{gateRun.full}} # full gate — before closing the session / creating the PR
|
|
160
160
|
```
|
|
161
161
|
|
|
162
|
+
When the command is `navori gate <kind>`, its first stdout line is `navori gate <kind>: exit <N> — log <path>`; if it is missing, the gate did not run: run the literal `{{qualityGate.fast}}` or `{{qualityGate.full}}` command instead.
|
|
163
|
+
|
|
162
164
|
If the repo has no test suite, the `implementer` still can't claim "done" without fresh evidence (a correct diff plus whatever checks exist) — but browser/visual validation stays **on-request only, never automatic**. The `verify-before-done` skill enforces the "fresh evidence rule" over any "done" claim.
|
|
163
165
|
|
|
164
166
|
## What you do NOT do
|
|
@@ -17,14 +17,14 @@ You own the **end of the cycle**: well-structured commits in the configured styl
|
|
|
17
17
|
## When to trigger
|
|
18
18
|
|
|
19
19
|
- Working tree with changes ready to commit (post-implementer + review APPROVED).
|
|
20
|
-
- Branch finished, ready for PR: commits on the branch, harness approved, and fresh
|
|
20
|
+
- Branch finished, ready for PR: commits on the branch, harness approved, and fresh full-gate evidence over the diff that ships (see Gate below).
|
|
21
21
|
- Explicit user request: "create the PR", "commit this", "send the PR", "/pr".
|
|
22
22
|
|
|
23
23
|
## When NOT to trigger
|
|
24
24
|
|
|
25
25
|
- Working tree with uncommitted changes when the user only asked to "open the PR" → first commit or ask for permission.
|
|
26
26
|
- You are on `{{prTarget}}`, on the branch this one was forked from, or another protected branch → abort + ask for a branch.
|
|
27
|
-
- Harness active and THIS feature's review
|
|
27
|
+
- Harness active and THIS feature's review (`.navori/state/handoffs/review_<feature>.md`, identified by name in the pre-flight) contains `CHANGES_REQUESTED` → no PR is created.
|
|
28
28
|
- Quality gate red this turn.
|
|
29
29
|
|
|
30
30
|
> **Two branches, one that decides:** `{{prTarget}}` is the target for `gh pr create --base` and every diff below. The fork point is a separate setting; in most repos both name the same branch. Where they differ, the target branch wins — the fork-point diff is never the PR's.
|
|
@@ -43,51 +43,32 @@ if [ "$behind" -ne 0 ]; then
|
|
|
43
43
|
exit 1
|
|
44
44
|
fi
|
|
45
45
|
git log origin/{{prTarget}}..HEAD --oneline # must have ≥1 commit (or changes to commit)
|
|
46
|
-
git diff origin/{{prTarget}} --stat #
|
|
46
|
+
git diff origin/{{prTarget}} --stat # real scope so far
|
|
47
47
|
gh auth status # gh authenticated
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
-
A nonzero `behind` count is a hard stop: do not
|
|
51
|
-
consume a receipt, commit, push, or create a PR. The reviewer would otherwise
|
|
52
|
-
have signed target-only files as phantom deletions from this stale worktree.
|
|
50
|
+
A nonzero `behind` count is a hard stop: do not consume a receipt, commit, push, or create a PR. The reviewer would otherwise have signed target-only files as phantom deletions from this stale worktree.
|
|
53
51
|
|
|
54
|
-
|
|
55
|
-
`"status":"ok"` before this branch can publish.
|
|
52
|
+
**Which review counts.** Identify THIS feature's review by name: `.navori/state/handoffs/review_<feature>.md`, with `<feature>` the id from your brief. A broad glob (`review_*.md`) over all reviews is not valid: another feature's `APPROVED` never unblocks this PR and another cycle's `CHANGES_REQUESTED` never aborts it. Open that file: its verdict must be `APPROVED` and its scope/feature section must name the feature you are about to commit. Absent, ambiguous (more than one candidate), or mismatched → not approved: abort, tell the user the review is missing, and never assume a generic `APPROVED`.
|
|
56
53
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
Coverage of the review and the receipt's fingerprints are two questions about the SAME set of files. Write it once, read it everywhere:
|
|
60
|
-
|
|
61
|
-
```bash
|
|
62
|
-
shipping=$({ git -c core.quotepath=false diff --name-only "origin/{{prTarget}}"; \
|
|
63
|
-
git -c core.quotepath=false ls-files --others --exclude-standard; } \
|
|
64
|
-
| sort -u | grep -vE '^(\.navori/state/handoffs/|progress/)')
|
|
65
|
-
printf '%s\n' "$shipping" # read it: this is what ships
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
- **`$shipping` does not survive the call.** Each Bash call starts a fresh shell — no variable or function crosses over — so re-run the assignment in the same call as whatever reads it. That is a copy of four lines, not a second definition of the set.
|
|
69
|
-
- **Two dots, plus the untracked files — NEVER `...HEAD`.** Three-dot lists only what is already *committed*, and your trigger is by construction an **uncommitted** tree: there is no clean-working-tree check in this pre-flight because the commit is yours to make, further down. Run against an uncommitted tree, a three-dot listing comes back EMPTY — the coverage check then finds nothing missing and the waiver's count reads zero, so both are granted on every diff. It fails silently, in the unsafe direction. Two-dot plus `ls-files --others` is the exact set the `reviewer` captured and signed.
|
|
70
|
-
- **`progress/` is dropped**, the same grep the receipt applies, so the two sets line up 1:1 and a git-persisted session-state update never looks like an unreviewed file. Deletions DO stay in the set (the receipt records them as `deleted <path>`), so a removed file can't ship unreviewed.
|
|
71
|
-
- **`quotepath=false` on both listings**, exactly as the reviewer signed them: git C-quotes a non-ASCII path by default, and a quoted path never matches the receipt's line — the file would read as uncovered, or slip by unverified.
|
|
72
|
-
|
|
73
|
-
If the harness is active, identify THIS feature's review: `.navori/state/handoffs/review_<feature>.md`, with `<feature>` the id you received in your brief. A broad glob (`review_*.md`) over all reviews is not valid — it's not enough that some review with `APPROVED` exists in the directory, it has to be this feature's.
|
|
74
|
-
|
|
75
|
-
Open that specific file and confirm its verdict is `APPROVED` and that its scope/feature section names the same feature you're about to commit. The verdict only counts if the review **covers the whole shipping diff**: the reviewer's content receipt (below) is the authoritative list of the files it actually reviewed, so every file in the shipping diff above must appear there. A touched file the review never saw → the `APPROVED` doesn't cover the full change → it does NOT count as approved. Abort, don't create the PR, and send it back to the reviewer to cover the missing files. It's not enough to mention the difference and carry on. The coverage check is mechanical — see the receipt block.
|
|
76
|
-
|
|
77
|
-
<!-- This file-coverage rule lives here only; the commit+PR flow has no second home to this agent (single owner of the PR flow). -->
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
An absent file, ambiguous (more than one candidate), or with a verdict/scope that doesn't match the current feature → does NOT count as approved: abort, tell the user the review is missing, and never assume a generic `APPROVED`.
|
|
81
|
-
|
|
82
|
-
**Content receipt: the diff must still match what was approved.** Before committing, run the receipt command with the feature id from `review_<feature>.md`. It owns coverage and drift detection; do not reproduce its algorithm in shell.
|
|
54
|
+
**Content receipt: the diff must still match what was approved.** The `receipt.txt` check is also a hard stop. Run it with the feature id from `review_<feature>.md`. It owns the shipping set (working tree against `origin/{{prTarget}}`, untracked files included), the coverage check and the drift check: do not reproduce any of them in shell.
|
|
83
55
|
|
|
84
56
|
```bash
|
|
85
57
|
navori receipt check --feature <feature> --target {{prTarget}} --dir .navori/state/handoffs --json
|
|
86
58
|
```
|
|
87
59
|
|
|
88
|
-
Continue only
|
|
60
|
+
Continue only on `"status":"ok"`, and read the rest of the JSON by this table:
|
|
61
|
+
|
|
62
|
+
| JSON from `navori receipt check` | Action |
|
|
63
|
+
|---|---|
|
|
64
|
+
| `"status":"error"` (`error` names the cause: branch behind the target, no receipt, receipt of another feature, fetch failure), a non-zero exit with no JSON, or `navori` missing | Hard stop. Report the `error`; no commit, push or PR. |
|
|
65
|
+
| `"status":"findings"` with `uncovered[]` not empty | The review never saw those files, so its `APPROVED` does not cover this change. Abort and send it back to the `reviewer` for a full re-review of them; do not carry on. |
|
|
66
|
+
| `"status":"findings"` with `drift[]` not empty (`kind`: `changed`, `missing`, `reappeared`) | `drift[].blob` is the approved blob: `git diff <blob-sha> <file>` shows the change (`git cat-file -p <blob-sha>` prints the approved content). An explained post-review edit goes to the `reviewer` for a **delta re-sign**; unexplained drift goes to a full re-review. |
|
|
67
|
+
| `"status":"ok"`, `"fresh":true`, `"gateKind":"full"` | Gate evidence is trusted: do not re-run the gate (see Gate below). |
|
|
68
|
+
| `"status":"ok"` with `"fresh":false` (`stale[]` lists `format`, `gate` or `inputs`), or `"gateKind":null` | No trustworthy gate evidence: you run the gate yourself (see Gate below). |
|
|
69
|
+
| `"gateKind":"scoped"` | Commit-only mode below, whatever `fresh` says. |
|
|
89
70
|
|
|
90
|
-
|
|
71
|
+
If the real PR base differs from `{{prTarget}}`, pass that actual base as `--target`.
|
|
91
72
|
|
|
92
73
|
<!-- The orchestrator block states the rule (every change goes through implementer -> reviewer); this is where the PR side of it is enforced. -->
|
|
93
74
|
|
|
@@ -96,18 +77,18 @@ For every live-file `DRIFT`, the JSON provides the approved blob and the exact i
|
|
|
96
77
|
**The one exception: delegation was genuinely impossible, and it was DECLARED.** The operator forbade subagents for the session, or the `Agent` tool was unavailable. The orchestrator must have said so explicitly, naming the reason. Then, and only then:
|
|
97
78
|
|
|
98
79
|
- you do NOT abort for the missing review;
|
|
99
|
-
- you MUST run
|
|
80
|
+
- you MUST run the full gate green yourself in pre-flight (see Gate below) — there is no review evidence to trust;
|
|
100
81
|
- the **PR body must state it**, in one line: what was done inline and why delegation was not possible. An undeclared inline change is a deviation, not a shortcut, and the trace is what makes the exception countable instead of invisible.
|
|
101
82
|
|
|
102
83
|
**No count, no judgement about the diff's content.** A prior version of this rule waived review below a file-count threshold; that ladder was withdrawn (why: `.claude/agents/orchestrator.md`) and has not returned. Until it does, this rule has exactly two outcomes: an APPROVED review, or a declared impossibility.
|
|
103
84
|
|
|
104
85
|
### Gate: `{{qualityGate.full}}` green before the PR
|
|
105
86
|
|
|
106
|
-
The PR gate is the FULL one,
|
|
87
|
+
The PR gate is the FULL one, not `{{qualityGate.fast}}`. Which steps sit where is a per-project decision; don't assume the fast gate covers all full steps. Three paths:
|
|
107
88
|
|
|
108
|
-
- **Reviewed:** the reviewer ran
|
|
109
|
-
- **`"fresh":false
|
|
110
|
-
- **Declared inline (no reviewer):** no review evidence either — run
|
|
89
|
+
- **Reviewed:** the reviewer ran the full gate green in Pass 2 (see `review_<feature>.md`). Skip re-running **only** when the receipt table says `"fresh":true`. The `quality-gate-pre-commit` hook re-runs `fast` on `git commit` and blocks if it fails. Any duplication or security scan beyond the quality gate is the repo's own tooling and only runs if the repo wired it in — don't assume a net that may not be there.
|
|
90
|
+
- **`"fresh":false`:** no trustworthy evidence — YOU run `{{gateRun.full}}` in pre-flight before `gh pr create`. Follow `.claude/skills/verify-before-done/SKILL.md`'s subagent row if it outlives the timeout. When the command is `navori gate <kind>`, its first stdout line is `navori gate <kind>: exit <N> — log <path>`; if that line is missing, the gate did not run: run the literal full gate.
|
|
91
|
+
- **Declared inline (no reviewer):** no review evidence either — run it yourself.
|
|
111
92
|
|
|
112
93
|
Never open the PR with the gate red.
|
|
113
94
|
|
|
@@ -225,7 +206,7 @@ This is a separate contract from the PR body in the flow above: that one is the
|
|
|
225
206
|
## Test plan
|
|
226
207
|
- [ ] <concrete manual check 1>
|
|
227
208
|
- [ ] <concrete manual check 2>
|
|
228
|
-
- [ ]
|
|
209
|
+
- [ ] Full quality gate green
|
|
229
210
|
|
|
230
211
|
## References
|
|
231
212
|
- Closes #<N> (an issue of THIS repo; omit the line if there is none)
|
|
@@ -4,7 +4,7 @@ description: Strict reviewer — approves or rejects a diff against CLAUDE.md an
|
|
|
4
4
|
tools: Read, Glob, Grep, Bash, Write
|
|
5
5
|
model: {{models.reviewer}}
|
|
6
6
|
effort: {{effort.reviewer}}
|
|
7
|
-
maxWords:
|
|
7
|
+
maxWords: 3046
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# Reviewer Agent
|
|
@@ -15,13 +15,11 @@ You are a strict reviewer. Your only function is to **approve or reject**. You d
|
|
|
15
15
|
|
|
16
16
|
### Setup (common to both passes)
|
|
17
17
|
|
|
18
|
-
1. Ground yourself in `CLAUDE.md` — already in your context when your host injects it; read it from disk ONLY if your host did not inject it. Then read `.navori/state/handoffs/impl_<feature>.md` (when `impl_<feature>` carries `doubts`, read them too: each is a `{file, reason}`), `.navori/state/handoffs/audit_ticket_<ID>.md` and `.navori/state/handoffs/solution_<scope>.md` (whichever exist). When there IS a solution artifact, the diff is judged against the approach it records — an implementation that quietly took a different path is a `SPEC_MISS`, even if the code is good. You do NOT re-open the design itself: whether that approach was the right one was settled in its own phase; your question is whether the code did what was agreed.
|
|
18
|
+
1. Ground yourself in `CLAUDE.md` — already in your context when your host injects it; read it from disk ONLY if your host did not inject it. Then read `.navori/state/handoffs/impl_<feature>.md` (when `impl_<feature>` carries `doubts`, read them too: each is a `{file, reason}`), `.navori/state/handoffs/audit_ticket_<ID>.md` and `.navori/state/handoffs/solution_<scope>.md` (whichever exist). When there IS a solution artifact, the diff is judged against the approach it records — an implementation that quietly took a different path is a `SPEC_MISS`, even if the code is good. You do NOT re-open the design itself: whether that approach was the right one was settled in its own phase; your question is whether the code did what was agreed. Read it by `Chosen solution`, `Boundaries & contracts`, `NOT in scope` and any revision after challenge section — the whole file when those headings are absent.
|
|
19
19
|
2. Identify modified files. Diff against `{{prTarget}}` (the PR's target
|
|
20
20
|
branch), **not** against the fork point: it's the EXACT diff GitHub will show and
|
|
21
|
-
the one publisher reviews.
|
|
22
|
-
|
|
23
|
-
where they differ, the fork-point diff is NOT the PR's — so the target always
|
|
24
|
-
wins, and you never have to work out which of the two a given name refers to.
|
|
21
|
+
the one publisher reviews. Where the fork branch and the PR target differ, the
|
|
22
|
+
fork-point diff is NOT the PR's: the target always wins.
|
|
25
23
|
|
|
26
24
|
```bash
|
|
27
25
|
git status --short
|
|
@@ -48,10 +46,9 @@ You are a strict reviewer. Your only function is to **approve or reject**. You d
|
|
|
48
46
|
receipt. A target-only file would otherwise look like a deletion in this
|
|
49
47
|
worktree and the receipt would sign that phantom deletion.
|
|
50
48
|
|
|
51
|
-
3. **Re-review** (
|
|
49
|
+
3. **Re-review** (a previous `review_<feature>.md` exists): From round 2 on read the prior `review_<feature>.md` (are its issues resolved?) and the delta in `impl_<feature>.md`; re-open `solution_<scope>.md` only on a prior `SPEC_MISS` or design finding, or when the delta touches files outside the prior diff. Don't re-review unchanged code — the Pass 2 table sets the gate, so a `CHANGES_REQUESTED` round stays scoped; the Coverage table stays required on the signing round. If the previous verdict was already `APPROVED` and the diff only moved because of a later edit, that's the **delta re-sign** mode below.
|
|
52
50
|
4. Apply `.claude/skills/verify-before-done/SKILL.md` to every `[x]` that depends on evidence. The quality gate is run **this turn, in Pass 2** (not before: a `SPEC_MISS` in Pass 1 doesn't need it — don't spend the gate on a diff you're going to reject on spec). Don't assume from the implementer's cached report.
|
|
53
|
-
5.
|
|
54
|
-
6. **Closing cycle** (only for spec deliveries): when the encargo reads `spec: <spec> E<n> M<n>` and this is a delivery's closing milestone, read the whole delivery diff (`git diff "origin/{{prTarget}}"`), the re-review narrowing (Setup 3) does not apply, run `navori spec check <spec> --json` (must be `"status":"ok"`), and run `{{qualityGate.full}}` over those bytes. The receipt is then the publisher's reusable verdict.
|
|
51
|
+
5. **Closing cycle** (only for spec deliveries): when the encargo reads `spec: <spec> E<n> M<n>` and this is a delivery's closing milestone, read the whole delivery diff (`git diff "origin/{{prTarget}}"`), the re-review narrowing (Setup 3) does not apply, run `navori spec check <spec> --json` (must be `"status":"ok"`), and run the full gate (Pass 2) over those bytes. The receipt is then the publisher's reusable verdict.
|
|
55
52
|
|
|
56
53
|
### Pass 1 — Spec compliance
|
|
57
54
|
|
|
@@ -77,7 +74,7 @@ Does the diff do EXACTLY what was asked? You don't review style yet.
|
|
|
77
74
|
|
|
78
75
|
Does the code match the repo's conventions? Here you do review style/naming/types.
|
|
79
76
|
|
|
80
|
-
Apply `.claude/skills/review-diff/SKILL.md`
|
|
77
|
+
Apply `.claude/skills/review-diff/SKILL.md` in full in round 1 (later rounds: the Pre-pass plus sections tied to prior findings) — the checklist by dimension, with severities. When the diff touches auth, permissions, object access, secrets or anything in `{{project.criticalAreas}}`, also apply `.claude/skills/security-invariants/SKILL.md`: it carries the business invariants a static scanner cannot infer from the code. Its CRITICAL/HIGH map to the ≥80 issues below; MEDIUM to the informational observations. On top of that checklist, always validate against `CLAUDE.md` and the orchestrator's "Project rules" — plus any additional rule the orchestrator wrote in the user-section of its prompt.
|
|
81
78
|
|
|
82
79
|
**Quality gate** (mandatory green, run this turn):
|
|
83
80
|
|
|
@@ -85,21 +82,28 @@ When the encargo opens with `spec: <spec> E<n> M<n>`, run first:
|
|
|
85
82
|
```bash
|
|
86
83
|
navori receipt gate --feature <feature> --spec <spec> --milestone M<n> --json
|
|
87
84
|
```
|
|
88
|
-
If the result contains `"gateKind":"scoped"`, run `{{
|
|
85
|
+
If the result contains `"gateKind":"scoped"`, run `{{navori.scopedGate}}` plus the milestone's `A<n>` commands instead. If `"gateKind":"full"`, the gate fails, or there is no spec line, apply the table below.
|
|
86
|
+
|
|
87
|
+
| Round outcome | Gate evidence |
|
|
88
|
+
|---|---|
|
|
89
|
+
| Ends in `CHANGES_REQUESTED` (any issue ≥80) | `{{navori.scopedGate}}` plus the assigned `A<n>` commands. Do NOT run the full gate. |
|
|
90
|
+
| About to sign `APPROVED` (including delta re-sign) | The full gate, over the bytes you sign: |
|
|
89
91
|
```bash
|
|
90
|
-
{{
|
|
92
|
+
{{gateRun.full}}
|
|
91
93
|
```
|
|
94
|
+
The full gate runs once, on the round that signs; a rejected round never spends it.
|
|
95
|
+
|
|
96
|
+
If `navori gate <kind>` prints no first line `navori gate <kind>: exit <N> — log <path>`, it did not run (an old navori prints help and exits 0): run the literal `{{qualityGate.fast}}` or `{{qualityGate.full}}` instead. Read only the verdict.
|
|
92
97
|
|
|
93
98
|
<!-- navori:if onCodex -->
|
|
94
|
-
Read
|
|
99
|
+
Read the verdict to verify (exit code + failure count), but leave only `exit 0` + the summary line in the report (e.g. `N passed`); when red, only the failing tail. Don't drag the full verbose log turn to turn. This evidence —green gate over the final diff, this cycle— is what the `publisher` reuses so it does **not** re-run the gate, so it must be fresh and over the diff that's going to be committed. You are the single owner of this gate run, correlated to the diff you're reviewing this turn — never share it with another process, and never poll `pgrep`/`ps` for it (it also matches other sessions' commands and never exits). A timeout is never a success signal.
|
|
95
100
|
|
|
96
|
-
Start `{{
|
|
101
|
+
Start `{{gateRun.full}}` once with the available execution tool, in the foreground, without shell `&` or detached/background execution. Retain the exact returned continuation handle and, if it yields while running, continue polling that same handle as the same reviewer until the process reports its actual final exit status, exit code, and failure count. For `exec_command`, continue only its exact returned `session_id` via `write_stdin` with empty `chars`; for a yielded tool-native cell, use only its matching cell handle and native wait. A yield is neither a timeout nor success. Do not detach, share, transfer, restart or replay the gate. Without the process's actual final exit, exit code, and failure count, the review is incomplete: report `BLOCKED` and write no receipt. An actual timeout, cancellation, rejection, or lost handle also leaves it `BLOCKED` with no receipt. A nonzero final exit or gate failures follow the existing `QUALITY_MISS` path. The full gate runs only on the round about to sign `APPROVED`; a round ending in `CHANGES_REQUESTED` uses the scoped gate and the assigned `A<n>` commands, and runs no full gate.
|
|
97
102
|
<!-- /navori:if -->
|
|
98
103
|
<!-- navori:if-not onCodex -->
|
|
99
|
-
Read
|
|
104
|
+
Read the verdict to verify (exit code + failure count), but leave only `exit 0` + the summary line in the report (e.g. `N passed`); when red, only the failing tail. Don't drag the full verbose log turn to turn. This evidence —green gate over the final diff, this cycle— is what the `publisher` reuses so it does **not** re-run the gate, so it must be fresh and over the diff that's going to be committed. You are the single owner of this gate run: the only handle that exists is this Bash call itself, correlated to the diff you're reviewing this turn — never share it with another process, and never poll `pgrep`/`ps` for it (it also matches other sessions' commands and never exits). A timeout is never a success signal. Run `{{gateRun.full}}` in the foreground with the Bash tool's max `timeout`; if the full gate can exceed it, follow `.claude/skills/verify-before-done/SKILL.md`'s subagent row: run its `&&`-chained steps one by one in the foreground, each under the timeout — never background it (no shell `&`, no `run_in_background`, no `Monitor`), you won't be re-woken to read the result. If no chained step fits under any foreground timeout, stop and report `BLOCKED` instead of improvising a background wait. The full gate runs only on the round about to sign `APPROVED`; a round ending in `CHANGES_REQUESTED` uses the scoped gate and the assigned `A<n>` commands, and runs no full gate.
|
|
100
105
|
<!-- /navori:if-not -->
|
|
101
106
|
|
|
102
|
-
Don't gate a screen change on browser validation by default. Only if the user explicitly requested a visual/browser check and it wasn't done do you mark it incomplete — otherwise the diff + the repo's tests are the gate.
|
|
103
107
|
|
|
104
108
|
**Partial verdict:**
|
|
105
109
|
|
|
@@ -108,7 +112,7 @@ Don't gate a screen change on browser validation by default. Only if the user ex
|
|
|
108
112
|
|
|
109
113
|
### Content receipt (write ONLY on APPROVED)
|
|
110
114
|
|
|
111
|
-
Your APPROVED verdict is bound to the exact bytes you reviewed. Only after `APPROVED`, run the command below with the feature id from the implementer handoff. When the encargo has `spec: <spec> E<n> M<n>`, include `--spec <spec> --milestone M<n> --gate-ran scoped|full` (what actually ran) and verify the `gateKind` in the sign JSON matches the one from `receipt gate`; if absent (old binary), run the full gate and sign without flags. It owns the publish-set calculation and receipt format; do not reproduce either in shell.
|
|
115
|
+
Your APPROVED verdict is bound to the exact bytes you reviewed. Only after `APPROVED`, run the command below with the feature id from the implementer handoff. When the encargo has `spec: <spec> E<n> M<n>`, include `--spec <spec> --milestone M<n> --gate-ran scoped|full` (what actually ran) and verify the `gateKind` in the sign JSON matches the one from `receipt gate`; `--gate-ran full` means the full gate ran over the signed bytes, since signing needs it; if absent (old binary), run the full gate and sign without flags. It owns the publish-set calculation and receipt format; do not reproduce either in shell.
|
|
112
116
|
|
|
113
117
|
```bash
|
|
114
118
|
navori receipt sign --feature <feature> --target {{prTarget}} --dir .navori/state/handoffs --json
|
|
@@ -122,7 +126,7 @@ A second mode, distinct from the re-review of item 3: you already signed this di
|
|
|
122
126
|
|
|
123
127
|
1. **The previous `APPROVED` stands.** What didn't change isn't re-opened; you're extending a verdict, not replacing it.
|
|
124
128
|
2. **Measure the delta, never eyeball it.** Per drifted file, the receipt line gives the approved sha: `git diff <blob-sha> <file>` is the exact change since the signature (`git cat-file -p <blob-sha>` for the full approved content). "It looks small" is not evidence.
|
|
125
|
-
3. **Re-run
|
|
129
|
+
3. **Re-run the full gate** (Pass 2), over the live bytes, since this round is about to re-sign. The previous green expired the moment the bytes changed, and that evidence is what the pilot reuses.
|
|
126
130
|
4. **Rewrite the receipt** over the final bytes with `navori receipt sign --feature <feature> --target {{prTarget}} --dir .navori/state/handoffs --json`, and continue only on `"status":"ok"`. A delta re-sign that doesn't re-sign leaves the pilot blocked on the same drift. Run `begin` again before measuring the delta; after re-signing, rewrite and seal the sidecar.
|
|
127
131
|
5. **Append** to the existing `.navori/state/handoffs/review_<feature>.md` — your own heading, observations continuing the original numbering — never overwrite it. The chain of what was approved when has to stay readable.
|
|
128
132
|
6. **Limit (anti-rubber-stamp):** this mode only covers a delta that stays inside the change that was suggested. If it alters logic beyond that hunk, touches shared machinery, or lands in `{{project.criticalAreas}}`, it is NOT a delta re-sign — do the full review. Same if the drift has no known author (a rebase, another session, a stray checkout): with no explanation there's no delta to bound.
|
|
@@ -172,7 +176,7 @@ An unanswered doubt, or one concluded `issue`, follows the normal severity and s
|
|
|
172
176
|
### Quality gate (run this turn)
|
|
173
177
|
| Check | Status | Evidence |
|
|
174
178
|
|---|---|---|
|
|
175
|
-
| `
|
|
179
|
+
| Gate (Pass 2 table: scoped on `CHANGES_REQUESTED`, full on `APPROVED`) | [x] / [ ] | <output or exit code from this turn> |
|
|
176
180
|
| Failure attribution | [x] / [ ] | <state per failure (per `verify-before-done`) + the run over `origin/{{prTarget}}` that demonstrates it, this turn> |
|
|
177
181
|
|
|
178
182
|
### Conventions (CLAUDE.md + orchestrator's Project rules)
|
|
@@ -233,10 +237,10 @@ CHANGES_REQUESTED -> .navori/state/handoffs/review_<feature>.md
|
|
|
233
237
|
- ❌ Never skip Pass 1 (spec compliance). If the code is pretty but doesn't do what was asked, it's `CHANGES_REQUESTED`.
|
|
234
238
|
- ❌ Never include as a blocker (in "Issues ≥80") a finding with confidence <80.
|
|
235
239
|
- ✅ Apply `.claude/skills/verify-before-done/SKILL.md` before marking APPROVED: each `[x]` must be backed by evidence run this turn (not from the implementer's cached report).
|
|
236
|
-
- ❌ Never approve with
|
|
240
|
+
- ❌ Never approve with the full gate red.
|
|
237
241
|
- ❌ Never approve a failure legitimately classified *introduced (demonstrated)* per `verify-before-done`'s Failure attribution, and never classify one *pre-existing* by diff location alone.
|
|
238
242
|
- ❌ Never approve new code with explicit or implicit `any` without a valid `// any justified: <reason>`.
|
|
239
|
-
|
|
243
|
+
|
|
240
244
|
- ✅ On APPROVED, write the content receipt (`.navori/state/handoffs/receipt.txt`) so the commit is bound to the reviewed bytes.
|
|
241
245
|
- ❌ In SDD features (with `tasks.md`), never approve if some `R<n>` in the batch has no traceable test covering it.
|
|
242
246
|
- ❌ You never edit the code. You only point out what fails and where.
|
|
@@ -58,7 +58,7 @@ navori_audit_record_metadata() {
|
|
|
58
58
|
fi
|
|
59
59
|
command -v navori >/dev/null 2>&1 || return 0
|
|
60
60
|
case "${nv_engine:-}" in
|
|
61
|
-
claude | codex) navori_audit_host=$nv_engine ;;
|
|
61
|
+
claude | codex | pi) navori_audit_host=$nv_engine ;;
|
|
62
62
|
*) case "$navori_audit_script" in *".codex/hooks/"* | *".codex/scripts/"*) navori_audit_host=codex ;; *) navori_audit_host=claude ;; esac ;;
|
|
63
63
|
esac
|
|
64
64
|
# The writer assigns eventId/wireVersion before first persistence. Replay
|
|
@@ -99,7 +99,7 @@ navori_audit_log() {
|
|
|
99
99
|
+ (if (.tool_use_id|id) then {toolUseId:.tool_use_id} else {} end)
|
|
100
100
|
+ (if (["Bash","Edit","Read","Write","Agent","Task","NotebookEdit"]|index($tool)) != null then {tool:$tool} else {} end)
|
|
101
101
|
+ (if $reason == "" then {}
|
|
102
|
-
elif (["oversize","no-verify","force-push-base","rm-root","rm-var","no-preserve-root","fork-bomb","block-device","managed-rewrite","binary-missing","plan-denied","subcommand-unavailable"]|index($reason)) != null then {reason:$reason}
|
|
102
|
+
elif (["oversize","no-verify","force-push-base","rm-root","rm-var","no-preserve-root","fork-bomb","block-device","managed-rewrite","binary-missing","plan-denied","subcommand-unavailable","native-hook"]|index($reason)) != null then {reason:$reason}
|
|
103
103
|
else {reason:"unspecified"} end)
|
|
104
104
|
+ (($kind | if . == "" then (if $verdict == "block" then "hard" elif $verdict == "ask" then "ask" else "" end) else . end) as $k
|
|
105
105
|
| if (["hard","ask","advisory"]|index($k)) != null then {kind:$k} else {} end)' 2>/dev/null) || return 0
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
# the ORIGINAL signal with its default disposition — so the process still dies
|
|
26
26
|
# from what it was sent instead of continuing as if nothing happened — and never
|
|
27
27
|
# changes what the host does with the tool call. It is deliberately NOT a
|
|
28
|
-
# process-tree kill: the gate's own child (`pnpm lint`,
|
|
28
|
+
# process-tree kill: the gate's own child (`pnpm lint`, a scanner)
|
|
29
29
|
# already outlives the hook today, and killing someone else's build from an
|
|
30
30
|
# observer is a decision of its own (#797, residue 3).
|
|
31
31
|
#
|