navori 0.11.1 → 0.11.3

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.
Files changed (53) hide show
  1. package/README.md +70 -11
  2. package/dist/assets/core/core-assets/agents/implementer.md +2 -2
  3. package/dist/assets/core/core-assets/agents/publisher.md +15 -5
  4. package/dist/assets/core/core-assets/agents/reviewer.md +32 -4
  5. package/dist/assets/core/core-assets/hooks/_partials/audit-arm.sh +7 -4
  6. package/dist/assets/core/core-assets/hooks/_partials/audit-log.sh +67 -230
  7. package/dist/assets/core/core-assets/hooks/_partials/bash-outcome.sh +120 -16
  8. package/dist/assets/core/core-assets/hooks/_partials/gate-ask.sh +11 -1
  9. package/dist/assets/core/core-assets/hooks/_partials/hook-input.sh +33 -0
  10. package/dist/assets/core/core-assets/hooks/audit-mode-close.sh +11 -4
  11. package/dist/assets/core/core-assets/hooks/audit-mode-trigger.sh +15 -36
  12. package/dist/assets/core/core-assets/hooks/engram-write-guard.sh +111 -0
  13. package/dist/assets/core/core-assets/hooks/general-purpose-confirm.sh +15 -1
  14. package/dist/assets/core/core-assets/hooks/guard-destructive.sh +168 -18
  15. package/dist/assets/core/core-assets/hooks/implementer-no-markdown.sh +324 -0
  16. package/dist/assets/core/core-assets/hooks/managed-drift-watch.sh +4 -1
  17. package/dist/assets/core/core-assets/hooks/master-accept-confirm.sh +32 -5
  18. package/dist/assets/core/core-assets/hooks/master-plan-context.sh +7 -1
  19. package/dist/assets/core/core-assets/hooks/plan-gate.sh +44 -13
  20. package/dist/assets/core/core-assets/hooks/pr-publisher-confirm.sh +16 -0
  21. package/dist/assets/core/core-assets/hooks/quality-gate-pre-commit.sh +17 -3
  22. package/dist/assets/core/core-assets/hooks/role-guard.sh +265 -0
  23. package/dist/assets/core/core-assets/hooks/routing-watch.sh +17 -0
  24. package/dist/assets/core/core-assets/hooks/session-start-context.sh +85 -2
  25. package/dist/assets/core/core-assets/hooks/subagent-no-background.sh +2 -0
  26. package/dist/assets/core/core-assets/hooks/subagent-stop-handoff.sh +40 -1
  27. package/dist/assets/core/core-assets/managed/formato-respuesta.md +7 -4
  28. package/dist/assets/core/core-assets/managed/operaciones-seguras.md +1 -1
  29. package/dist/assets/core/core-assets/managed/orquestacion.md +15 -13
  30. package/dist/assets/core/core-assets/managed/planificacion.md +1 -1
  31. package/dist/assets/core/core-assets/managed/sdd.md +2 -2
  32. package/dist/assets/core/core-assets/master-plan/delivery-master.md +52 -0
  33. package/dist/assets/core/core-assets/master-plan/en/delivery-master.md +52 -0
  34. package/dist/assets/core/core-assets/master-plan/en/slice.md +54 -0
  35. package/dist/assets/core/core-assets/master-plan/en/tasks.md +37 -5
  36. package/dist/assets/core/core-assets/master-plan/slice.md +54 -0
  37. package/dist/assets/core/core-assets/master-plan/tasks.md +34 -2
  38. package/dist/assets/core/core-assets/settings/settings-base.json +2 -0
  39. package/dist/assets/core/core-assets/skills/debug-failure.md +1 -1
  40. package/dist/assets/core/core-assets/skills/master-plan.md +18 -14
  41. package/dist/assets/core/core-assets/skills/plan-advanced.md +9 -4
  42. package/dist/assets/core/core-assets/skills/plan-simple.md +2 -0
  43. package/dist/assets/core/core-assets/skills/resolve-ticket.md +2 -0
  44. package/dist/assets/core/core-assets/skills/solution-design.md +12 -12
  45. package/dist/assets/core/core-assets/skills/spec-bootstrap.md +22 -10
  46. package/dist/assets/core/core-assets/skills/verify-before-done.md +2 -2
  47. package/dist/assets/plugins/engram/plugin.json +17 -2
  48. package/dist/assets/plugins/jscpd/scripts/check-jscpd.sh +7 -3
  49. package/dist/assets/plugins/semgrep/scripts/check-semgrep.sh +4 -2
  50. package/dist/assets/plugins/tgrep/managed/guard-destructive-search-lane.sh +6 -1
  51. package/dist/assets/plugins/tgrep/scripts/guard-search-routing.sh +9 -2
  52. package/dist/index.js +428 -687
  53. package/package.json +1 -1
package/README.md CHANGED
@@ -77,9 +77,34 @@ No instala ni actualiza automáticamente y tampoco ejecuta `render`: después de
77
77
  actualizar navori, corre `navori render --apply` para aplicar los cambios a tu
78
78
  harness.
79
79
 
80
- Si un cierre abrupto deja bloqueado el aviso, detén primero todos los procesos
81
- `navori`. Después elimina únicamente `~/.navori/update-notice/lock`; conserva los
82
- archivos de caché y reserva de ese directorio.
80
+ #### Avisos de actualización de herramientas de plugin
81
+
82
+ Plugins como `engram` pueden declarar `latestRelease` en su manifest para recibir
83
+ avisos cuando existe una versión más nueva. El aviso aparece al final del contexto de
84
+ arranque, en un espacio reservado de 300 caracteres, una vez cada 24 h por versión.
85
+
86
+ La consulta se ejecuta:
87
+ - **Fuente**: `api.github.com/repos/<owner>/<repo>/releases/latest` o
88
+ `registry.npmjs.org/<package>/latest` (sin token, solo un User-Agent `navori/<version>`)
89
+ - **Frecuencia**: máximo una solicitud por herramienta por día, reservada bajo un lock
90
+ - **Red**: la carga de red ocurre en un worker detached en segundo plano; la sesión
91
+ nunca espera
92
+ - **Caché**: `~/.navori/tool-versions/` (similar a `~/.navori/update-notice/`)
93
+ - **CI**: sin red — ni refrescos ni avisos
94
+
95
+ Desactívalo junto con el aviso de navori: `NAVORI_NO_UPDATE_NOTIFIER=1`.
96
+
97
+ **Limitaciones:**
98
+ - Codex en sandboxes sin red no obtiene refrescos ni avisos.
99
+ - pi no tiene hooks de sesión: ahí los avisos solo aparecen en `navori doctor`.
100
+ - Si el aviso no cabe en su reserva, se muestra un puntero a `navori doctor` y el aviso
101
+ se reintenta en la siguiente sesión (no se marca como entregado).
102
+ - `doctor` muestra todos los avisos como filas informativas, sin aplicar `--strict`.
103
+
104
+ Si un cierre abrupto deja bloqueado el aviso, solo intervendrás si el lock persiste
105
+ más de un minuto. En ese caso, detén todos los procesos `navori` y elimina
106
+ `~/.navori/tool-versions/lock` o `~/.navori/update-notice/lock`; conserva los archivos
107
+ de caché de ambos directorios.
83
108
 
84
109
  ## Comandos
85
110
 
@@ -93,21 +118,23 @@ archivos de caché y reserva de ese directorio.
93
118
  | `update` | Re-detecta el repo, refresca config y corre sync en un paso |
94
119
  | `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 |
95
120
  | `registry <sub>` | Registro global de tus repos con navori, para `render --all` (`ls`, `scan <dir>`, `add`, `remove`, `prune`) |
96
- | `sync` | Refresca todos los engines configurados con conflict resolution + backups |
121
+ | `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 |
97
122
  | `preset init <id>` | Scaffoldea un preset local en `.navori/presets/<id>/` |
98
123
  | `scan` | Detecta workspaces nuevos en monorepos (`pnpm-workspace.yaml` / `package.json#workspaces`) |
99
- | `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) |
124
+ | `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`) |
100
125
  | `status` | Snapshot rápido: config, plugins activos, conteo de drift y próximos pasos |
101
- | `audit` | Reporta cómo corrió el harness de verdad: atribución de tokens y huecos de adherencia en tus sesiones |
102
- | `receipt <sign\|check>` | Firma o verifica los bytes revisados antes de publicar un cambio (`navori receipt <sign\|check> --feature <id> [--target <ref>] [--dir <path>] [--json]`) |
126
+ | `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
+ | `receipt <sub>` | Recibo de los bytes revisados antes de publicar: `sign` (`--feature <id>`, `--gate-ran scoped\|full`, `--spec <dir> --milestone <Mn>`), `check`, `gate --spec <dir> --milestone <Mn>` (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
+ | `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
+ | `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 |
103
130
  | `handoff <check>` | Valida el handoff del implementer (`impl_<feature>.json`) antes de despachar al siguiente agente (`navori handoff check <feature> [--for scribe] [--dir <path>] [--cwd <checkout>] [--json]`) |
104
131
  | `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 |
105
- | `master <sub>` | Flujo guiado del plan maestro por etapas (`init`, `mode`, `template`, `check`, `advance`, `status`, `part`, `close`) |
132
+ | `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` |
106
133
  | `bench` | Corre `render` en dry-run N veces y reporta latencias (detecta regresiones locales) |
107
- | `workspace <sub>` | Gestiona workspaces cross-repo (`init`, `ls`, `show`, `rm`) |
134
+ | `workspace <sub>` | Gestiona workspaces cross-repo (`init`, `ls`, `show`, `link`, `add-repo`, `set-default`, `render`, `rename`, `delete`) |
108
135
  | `ticket <sub>` | Gestiona tickets-as-files en un workspace (`new`, `list`, `show`, `archive`, `delete`) |
109
136
  | `dominio <sub>` | Base de conocimiento durable del workspace (`init`, `list`, `show`, `reindex`, `doctor`, `inject`) |
110
- | `global <sub>` | Harness base por máquina en `~/.claude` (`init`, `render`, `doctor`, `uninstall`) — opt-in explícito y aditivo |
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) |
111
138
  | `codex <sub>` | Comandos específicos de Codex; hoy `trust` aprueba los hooks del proyecto en `~/.codex/config.toml` |
112
139
  | `backup <sub>` | Lista y restaura backups de `~/.navori/backups/` |
113
140
  | `migrations <sub>` | Lista y restaura migraciones de `~/.navori/migrations/` |
@@ -177,7 +204,10 @@ Con `harness.planTiers: true` en `navori.config.json`, `navori plan classify` mi
177
204
  complejidad de una tarea (señales como dinero/credenciales/PII, dependencia nueva, migración de
178
205
  esquema, o tocar una ruta de `project.criticalPaths`) y la ubica en un nivel 0–3. El hook
179
206
  `PreToolUse(Agent)` (`navori plan gate`) niega el despacho de un subagente sin el workplan que su
180
- nivel exige, y escala la exigencia tras dos rechazos seguidos. `navori plan classify --diff`
207
+ nivel exige, y escala la exigencia tras dos rechazos seguidos. Si `navori` falta o su build no tiene el
208
+ subcomando `plan`, el hook no tiene veredicto y, en modos que muestran el prompt, pide
209
+ confirmación en vez de dejarte sin salida (en `bypassPermissions`, `dontAsk` o `plan` sigue
210
+ bloqueando). `navori plan classify --diff`
181
211
  corre el mismo clasificador contra `git diff --name-only <base>...HEAD` para avisar cuando el
182
212
  trabajo se salió del nivel que el workplan declaró.
183
213
 
@@ -190,12 +220,41 @@ El agente `architect` ya no tiene un flag `harness.architect` — renderiza siem
190
220
  que todavía trae `harness.architect` falla con un aviso de clave retirada en vez de ignorarla en
191
221
  silencio; `navori configure migrate` la quita.
192
222
 
223
+ ## Entregas de specs (`sdd.deliveries`)
224
+
225
+ Una spec grande no tiene por qué salir en una sola PR. `navori spec classify <feature>` la mide
226
+ contra los umbrales de `sdd.deliveries` en `navori.config.json` (`splitMinTasks`, `splitMinLoc`,
227
+ `maxPrsPerSpec`; defaults 12 tareas, 1500 LOC estimadas y 4 PRs) y dice si sale en una PR o en una
228
+ PR por entrega. `navori spec check` valida el `tasks.md` contra su gramática:
229
+
230
+ - **`E<n>`**: entrega; una PR cada una.
231
+ - **`M<n>`**: milestone; cada uno se verifica y se commitea por separado.
232
+ - **`T<n>`**: tarea; declara los `R<n>` que cubre.
233
+
234
+ El gate completo corre una vez por PR, no una vez por milestone; el gate por milestone lo decide
235
+ `navori receipt gate`.
236
+
237
+ ## Harness de workspaces (`monorepo.workspaceHarness`)
238
+
239
+ `monorepo.workspaceHarness` decide cuánto harness recibe cada workspace de un monorepo. Es un solo
240
+ valor para todo el repo:
241
+
242
+ - `minimal` (default): su archivo de contexto más las skills que la raíz no tiene ya. Una skill
243
+ idéntica a la de la raíz no se duplica.
244
+ - `full`: todo, como antes de recortar.
245
+ - `root`: solo su archivo de contexto (`CLAUDE.md`, y `AGENTS.md` bajo Codex). La raíz escribe las
246
+ skills de librería y de preset que declaran los workspaces.
247
+
248
+ `navori doctor` trata `minimal` y `root` como harness recortado, y avisa si el valor es `full`.
249
+
193
250
  ## Harness defensivo (read-only por default)
194
251
 
195
252
  El harness que genera `navori` trae permisos seguros desde el arranque, para que tengas menos prompts en lo cotidiano sin bajar la guardia en lo peligroso:
196
253
 
197
254
  - **Las lecturas no piden confirmación**: `git status/diff/log/show`, `ls`, `cat`, `grep`, `Read`/`Glob`/`Grep`, etc. corren sin interrumpirte.
198
255
  - **Lo destructivo pide confirmación** (`ask`): `rm -rf`, `git push --force`, `git reset --hard`, `git clean -f`, `chmod -R`, …
256
+ - **Descartar trabajo sin commitear se bloquea** (`guard-destructive`, `exit 2`, sin aprobación posible): `git reset --hard`, `git checkout -f`, `git checkout -- .` (o `git checkout .`), `git restore <rutas>` sin `--staged`, y `git clean -f` (sin `-n`). El bloqueo depende del estado: si el árbol está limpio, no hay nada que perder y el comando pasa. Si el directorio destino no se puede inspeccionar (variable, sustitución o ruta inexistente), también bloquea. El mensaje indica la ruta para hacerlo de forma segura.
257
+ - **El `publisher` no reescribe historia**: tras un commit fallido no ejecuta `git reset` ni reescribe commits. Reporta con `git status` y `git log -1 --stat`, y la recuperación queda para el orquestador o el usuario.
199
258
  - **Lo catastrófico se rechaza** (`deny`): `rm -rf /`, `sudo rm`, `mkfs`, …
200
259
  - Un hook `guard-destructive` actúa como backstop adicional.
201
260
 
@@ -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: 2433
8
+ maxWords: 2448
9
9
  ---
10
10
 
11
11
  # Implementer Agent
@@ -41,7 +41,7 @@ You execute **a single** task from start to verification. You don't orchestrate,
41
41
  {{qualityGate.fast}}
42
42
  ```
43
43
 
44
- 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 (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. When you can't explain WHY it failed, apply `.claude/skills/debug-failure/SKILL.md` before touching anything — the size of the output is not the trigger, the missing root cause is, and a failure whose error stream you truncated away reads the same as one you understand. If your second fix attempt fails the same way, that same skill's hypothesis re-check governs instead of throwing a third patch.
44
+ 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 — the size of the output is not the trigger, the missing root cause is, and a failure whose error stream you truncated away reads the same as one you understand. If your second fix attempt fails the same way, that same skill's hypothesis re-check governs instead of throwing a third patch.
45
45
  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
46
  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
47
  <!-- navori:if planTiers -->
@@ -4,7 +4,10 @@ description: Drafts commits in the configured style and opens the PR with the re
4
4
  tools: Read, Glob, Grep, Bash
5
5
  model: {{models.publisher}}
6
6
  effort: {{effort.publisher}}
7
- maxWords: 3800
7
+ # Spec 0044 T12 (R18, R19, R23, R26): added commit-only mode, spec delivery PR steps
8
+ # (with Spec-Delivery, git merge-base check, Refs/Closes), and prTarget warning;
9
+ # +~200 words measured. 4200 = 3987 actual + 5.3% margin.
10
+ maxWords: 4200
8
11
  ---
9
12
 
10
13
  # Publisher Agent
@@ -103,7 +106,7 @@ For every live-file `DRIFT`, the JSON provides the approved blob and the exact i
103
106
  The PR gate is the FULL one, `{{qualityGate.full}}`, not `{{qualityGate.fast}}`. Which steps sit where is a per-project decision; don't assume the fast gate covers all full steps. Three paths:
104
107
 
105
108
  - **Reviewed:** the reviewer ran `{{qualityGate.full}}` green in Pass 2 (see `review_<feature>.md`). Skip re-running **only** when `navori receipt check` reports `"fresh":true`. The `quality-gate-pre-commit` hook re-runs `fast` on `git commit` and blocks if it fails. Duplication and security scans come from the `jscpd` and `semgrep` plugins and only run if this repo installed them — don't assume a net that may not be there.
106
- - **`"fresh":false`:** no trustworthy evidence — YOU run `{{qualityGate.full}}` green in pre-flight before `gh pr create`. Follow `.claude/skills/verify-before-done/SKILL.md`'s subagent row if it outlives the timeout.
109
+ - **`"fresh":false` on `full` receipts:** no trustworthy evidence — YOU run `{{qualityGate.full}}` green in pre-flight before `gh pr create`. Follow `.claude/skills/verify-before-done/SKILL.md`'s subagent row if it outlives the timeout.
107
110
  - **Declared inline (no reviewer):** no review evidence either — run `{{qualityGate.full}}` yourself.
108
111
 
109
112
  Never open the PR with the gate red.
@@ -119,9 +122,13 @@ Never open the PR with the gate red.
119
122
  4. If you touch potentially sensitive files (`.env*`, credentials, odd lockfiles), **flag the user before staging**.
120
123
  5. `git add <files>` (prefer explicit over `git add -A`).
121
124
  6. `git commit -m "..."` with a HEREDOC for the body if applicable.
122
- 7. Validate with `git status` that the commit landed. Foreign modified files are reported as an observation and never discarded, restored or reverted.
125
+ 7. Validate with `git status` that the commit landed. If it failed, stop with `git status` + `git log -1 --stat`; recovery is the orchestrator's or the user's call. Foreign modified files are reported as an observation and never discarded, restored or reverted.
123
126
  8. **Consume the receipt:** `mv -f .navori/state/handoffs/receipt.txt .navori/state/handoffs/receipt.consumed.txt`. The approval is now frozen into the commit; renaming it (instead of deleting it) keeps the evidence on disk without it being rearmed — a plain `check` never reads a consumed receipt again, only the opt-in flag documented in `cierre-sesion.md` does.
124
127
 
128
+ ## Commit-only mode
129
+
130
+ If the brief says `mode: commit-only`, or `navori receipt check` returns `"gateKind":"scoped"`, run the Commit flow through step 8 and STOP: no push, no PR, whatever `fresh` says.
131
+
125
132
  ## PR flow
126
133
 
127
134
  1. **Gather context** (curated, not the whole repo). The PR diff is against `{{prTarget}}`:
@@ -141,10 +148,11 @@ Never open the PR with the gate red.
141
148
  Count > 0 means your PR drags foreign commits: warn the user and suggest rebase.
142
149
  - Ticket if applicable: branch name (e.g. `BT-1234-fix-x` → `BT-1234`) or first commit.
143
150
  - `.navori/state/handoffs/impl_<feature>.md` — non-obvious decisions.
151
+ - **Spec deliveries** (only for shape `split`; read shape from `navori spec classify <spec> --json`): brief names `delivery: E<n>` and `after: <sha>`; after `git fetch`, verify `git merge-base --is-ancestor <sha> origin/{{prTarget}}` (preapproved); if it fails (squash merge), use `gh pr list --state merged --base {{prTarget}}` as a signal only and ASK the user rather than abort silently. Body carries `Spec-Delivery: <spec> E<n>/<total>`. Report `head: <sha>` at the end. Always `--base {{prTarget}}`, one PR per delivery in tasks.md order, no integration branch.
144
152
 
145
153
  2. **Draft title and body**:
146
154
  - **Title**: follows the configured commit style (`{{commits}}`), ≤70 chars, imperative and without a trailing period.
147
- - **Body**: the repo's exact template (below). No empty sections.
155
+ - **Body**: the repo's exact template (below). No empty sections. For spec deliveries, include references: `Refs #<issue>` on intermediate deliveries and `Closes #<issue>` on the last; shape `single` → `Closes #<issue>`.
148
156
 
149
157
  3. **Validate** before firing `gh`:
150
158
  - Every claim in the title and body — path, command, count or decision — traces to the cycle's handoffs (`impl_<feature>.*`, `review_<feature>.md`), `git log`/`git diff` against the base, or the spec; nothing else backs a claim, so no inferred path, command, count or decision goes in. **No handoff on disk** → draft from the diff and the issue only. A fact you can't trace is omitted, or reported to the orchestrator — never filled in (#1001, #1028).
@@ -177,7 +185,7 @@ Never open the PR with the gate red.
177
185
 
178
186
  7. **Checks — read them ONCE, never wait**: `gh pr checks <N> --json name,bucket,state,link,workflow`. `bucket: pending` (the normal case right after creating the PR) → say so in **one extra line** and stop, no retry. `bucket: fail` → name the check in that line and point to `follow-up-prs` for the diagnosis. Informative only: you never hold or revert a PR over a red check.
179
187
 
180
- 8. **Confirm the close actually linked** — only when the body declares one. The body is not evidence of anything; `closingIssuesReferences` is what GitHub parsed out of it:
188
+ 8. **Confirm the close actually linked** — only when the body declares one, and warning when `{{prTarget}}` differs from the remote default branch (`git rev-parse --abbrev-ref origin/HEAD`): the issue will not auto-close, so an empty `closingIssuesReferences` is expected, not a failure. The body is not evidence of anything; `closingIssuesReferences` is what GitHub parsed out of it:
181
189
 
182
190
  ```bash
183
191
  gh pr view <N> --json closingIssuesReferences --jq '[.closingIssuesReferences[].number]'
@@ -254,6 +262,8 @@ wc -c CLAUDE.md # after
254
262
  ## Hard rules
255
263
 
256
264
  - ❌ A stop report (gate red, missing review, protected branch, etc.) is the last action of this cycle. Do not continue investigating, re-running the gate, or calling `git`/`gh` after emitting it. If flaky, the next invocation decides.
265
+ - ❌ Never write to project files through Bash (redirections, sed -i, tee, interpreter one-liners, git checkout or restore of files). When a hook blocks, the stop report is the last action; the fix is not yours.
266
+ - ❌ Never rewrite history: no git reset in any mode, no commit --amend, no rebase. A commit that lands wrong is a stop report with `git status` + `git log -1 --stat`; recovery is the orchestrator's or the user's call.
257
267
  - ❌ Never push with `--force` to `{{branchBase}}` or another protected branch.
258
268
  - ❌ Never skip hooks (`--no-verify`) unless the user explicitly asks.
259
269
  - ❌ Never ask for a merge / approve the PR yourself. Your job ends with the URL.
@@ -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: 2372
7
+ maxWords: 2966
8
8
  ---
9
9
 
10
10
  # Reviewer Agent
@@ -31,6 +31,8 @@ You are a strict reviewer. Your only function is to **approve or reject**. You d
31
31
  printf 'ABORT: branch is %s commit(s) behind origin/{{prTarget}}; integrate the target before reviewing.\n' "$behind" >&2
32
32
  exit 1
33
33
  fi
34
+ # keep the nonce; a failure here never blocks the review, it only leaves it uncorrelated
35
+ navori receipt review begin <feature> --target {{prTarget}} --dir .navori/state/handoffs --json
34
36
  git diff --stat
35
37
  # two-dot: the FULL working tree vs the target (committed AND uncommitted),
36
38
  # the exact set the receipt fingerprints below. Three-dot (`...HEAD`) would show
@@ -40,6 +42,8 @@ You are a strict reviewer. Your only function is to **approve or reject**. You d
40
42
  git ls-files --others --exclude-standard # untracked files (new, not yet staged)
41
43
  ```
42
44
 
45
+ `begin` stamps the content identity BEFORE you read the diff, so it must run first.
46
+
43
47
  A nonzero `behind` count is a hard stop: do not review, approve, or write a
44
48
  receipt. A target-only file would otherwise look like a deletion in this
45
49
  worktree and the receipt would sign that phantom deletion.
@@ -47,6 +51,7 @@ You are a strict reviewer. Your only function is to **approve or reject**. You d
47
51
  3. **Re-review** (if there's already a `.navori/state/handoffs/review_<feature>.md` from a previous cycle): focus the *reading* on (a) that the issues listed there are resolved and (b) the files the `implementer` reports having touched in this cycle (`impl_<feature>.md`). Don't re-review from scratch the already-approved code that didn't change; the full quality gate is still run anyway — a change can break something outside the delta. If the previous verdict was already `APPROVED` and the diff only moved because of an edit made after it, that's the **delta re-sign** mode below, not this one.
48
52
  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.
49
53
  5. When judging scope or an impact claim needs evidence beyond the diff itself, apply Code discovery routing (project instructions) before gathering it: occurrences from a text search don't demonstrate structural impact — confirm relationships and blast radius through the enabled structural provider, or scoped reading when it's unavailable.
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.
50
55
 
51
56
  ### Pass 1 — Spec compliance
52
57
 
@@ -56,7 +61,7 @@ Does the diff do EXACTLY what was asked? You don't review style yet.
56
61
  - Is it within the agreed scope? (If it touched files outside the audit/ticket scope → flag)
57
62
  - Is anything from the scope missing? (If the ticket asked for A+B and it only did A → flag)
58
63
  - If the task is a bugfix: does the `Root cause:` documented in `impl_<feature>.md` match the fix?
59
- - **SDD traceability** (only if `{{sdd.specsDir}}/<feature>/tasks.md` exists): each `R<n>` in the batch is covered by ≥1 test that references it with `// Covers: R<n>`. An `R<n>` in the batch without a traceable test → `SPEC_MISS`.
64
+ - **SDD traceability** (only if `{{sdd.specsDir}}/<feature>/tasks.md` exists): read `{{sdd.specsDir}}/<spec>/tasks.md` using the `<spec>` from the `spec:` line (handoff key is `<spec>-e<n>`), check the milestone's tasks and verify `effect`/`[observable]` against the diff; a `behavior` task without observable behavior → `SPEC_MISS`. Each `R<n>` is covered by ≥1 test with `// Covers: R<n>` → `SPEC_MISS` if missing.
60
65
  <!-- navori:if planTiers -->
61
66
  - With a workplan: an assigned `A<n>` without evidence in `acceptance`, a file outside the workplan's files without a covering decision, or `navori plan classify <feature> --diff` returning a higher level than declared → `CHANGES_REQUESTED`.
62
67
  - With a workplan: run `navori plan check <feature> --json`; every `A<n>` marked `cumplido` without recorded evidence (the routing-watch hook records it only when the host ran the exact `command`) is a finding → `CHANGES_REQUESTED`.
@@ -76,11 +81,23 @@ Apply `.claude/skills/review-diff/SKILL.md` — the full checklist by dimensions
76
81
 
77
82
  **Quality gate** (mandatory green, run this turn):
78
83
 
84
+ When the encargo opens with `spec: <spec> E<n> M<n>`, run first:
85
+ ```bash
86
+ navori receipt gate --feature <feature> --spec <spec> --milestone M<n> --json
87
+ ```
88
+ If the result contains `"gateKind":"scoped"`, run `{{qualityGate.fast}}` plus the milestone's `A<n>` commands instead. If `"gateKind":"full"`, the gate fails, or there is no spec line, run:
79
89
  ```bash
80
90
  {{qualityGate.full}}
81
91
  ```
82
92
 
93
+ <!-- navori:if onCodex -->
94
+ Read it in full 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
+
96
+ Start `{{qualityGate.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.
97
+ <!-- /navori:if -->
98
+ <!-- navori:if-not onCodex -->
83
99
  Read it in full 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 it in the foreground with the Bash tool's max `timeout`; if `{{qualityGate.full}}` 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.
100
+ <!-- /navori:if-not -->
84
101
 
85
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.
86
103
 
@@ -91,7 +108,7 @@ Don't gate a screen change on browser validation by default. Only if the user ex
91
108
 
92
109
  ### Content receipt (write ONLY on APPROVED)
93
110
 
94
- 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. It owns the publish-set calculation and receipt format; do not reproduce either in shell.
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.
95
112
 
96
113
  ```bash
97
114
  navori receipt sign --feature <feature> --target {{prTarget}} --dir .navori/state/handoffs --json
@@ -106,7 +123,7 @@ A second mode, distinct from the re-review of item 3: you already signed this di
106
123
  1. **The previous `APPROVED` stands.** What didn't change isn't re-opened; you're extending a verdict, not replacing it.
107
124
  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.
108
125
  3. **Re-run `{{qualityGate.full}}` anyway**, over the live bytes. The previous green expired the moment the bytes changed, and that evidence is what the pilot reuses.
109
- 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.
126
+ 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.
110
127
  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.
111
128
  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.
112
129
 
@@ -184,6 +201,17 @@ Required when `APPROVED` with no issue ≥80 (a bare approval with no Coverage i
184
201
  | Quality gate | |
185
202
  ```
186
203
 
204
+ ### Sidecar (every verdict)
205
+
206
+ Write `.navori/state/handoffs/review_<feature>.json` from scratch each round (`{feature, verdict: APPROVED|CHANGES_REQUESTED, findings: [{category, severity: critical|high|medium|low, score: 0-100 integer, file, line?, summary?}]}`; `[]` when none), then run:
207
+
208
+ ```bash
209
+ navori receipt review seal <feature> --nonce <nonce> --target {{prTarget}} --dir .navori/state/handoffs --json
210
+ navori handoff log-review <feature> --dir .navori/state/handoffs
211
+ ```
212
+
213
+ `seal` exit 2 = content changed during review: restart from `begin`; never report that verdict as the final diff's. Never edit the sidecar after `seal`. A failed `begin`/`seal`/`log-review` never blocks the verdict; it only leaves the review uncorrelated.
214
+
187
215
  ## Chat reply
188
216
 
189
217
  **A single line**:
@@ -17,22 +17,25 @@
17
17
  # charset (#503) — this function trusts it into a command line, so an unvalidated
18
18
  # id must never reach here. $2 is the payload's cwd (#454: never
19
19
  # CLAUDE_PROJECT_DIR — they differ in worktrees, and --arm wrote the flag under
20
- # the repo name resolved from the cwd). $3 is the audits root.
20
+ # the repo name resolved from the cwd). $3 is the audits root. $4 is the
21
+ # authoritative engine selected by the shared hook input adapter.
21
22
  #
22
23
  # Fail-open and silent: returns 0 ONLY when audit-mode was actually started, so
23
- # the caller can announce it; every other path returns 1 and changes nothing.
24
+ # the caller can announce it. A validated flag stays consumed if start fails;
25
+ # insecure, malformed or missing flags remain unchanged.
24
26
  # Safe under `set -euo pipefail` and `set +e` alike.
25
27
  navori_audit_consume_armed() {
26
28
  narm_sid=$1
27
29
  narm_cwd=$2
28
30
  narm_root=$3
31
+ narm_host=$4
29
32
  [ -n "$narm_sid" ] && [ -n "$narm_cwd" ] && [ -n "$narm_root" ] || return 1
33
+ case "$narm_host" in claude | codex) : ;; *) return 1 ;; esac
30
34
  narm_repo=$(navori_audit_repo_from_cwd "$narm_cwd") || return 1
31
35
  [ -n "$narm_repo" ] || return 1
32
36
  narm_file=$narm_root/$narm_repo/.armed
33
37
  [ -f "$narm_file" ] || return 1
34
38
  command -v navori >/dev/null 2>&1 || return 1
35
- rm -f "$narm_file" 2>/dev/null || true
36
- navori audit --start "$narm_sid" --cwd "$narm_cwd" >/dev/null 2>&1 || return 1
39
+ NAVORI_AUDITS_ROOT="$narm_root" navori audit --consume-arm --start "$narm_sid" --cwd "$narm_cwd" --host "$narm_host" --root "$narm_root" >/dev/null 2>&1 || return 1
37
40
  return 0
38
41
  }