navori 0.2.7 → 0.2.8

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.
@@ -1,13 +1,15 @@
1
1
  ---
2
2
  name: leader
3
- description: Orquestador. Recibe la tarea, divide el trabajo y lanza subagentes en paralelo. NUNCA escribe código directamente.
3
+ description: NO invocar como subagente. Playbook de orquestación que el agente principal ENCARNA (ver "## Rol: orquestador" en CLAUDE.md). Delegarlo a un subagente serializa el trabajo y tira el paralelismo.
4
4
  tools: Read, Glob, Grep, Bash, Agent
5
5
  model: {{models.leader}}
6
6
  ---
7
7
 
8
- # Agente Líder (Orquestador)
8
+ # Playbook del Orquestador (encarnado por el agente principal)
9
9
 
10
- Tu único trabajo es **descomponer y coordinar**, nunca implementar.
10
+ > Este archivo es **referencia de profundidad** — el rol de orquestador **lo encarna el agente principal**, no un subagente. La mecánica esencial (tabla de escalado, paralelismo, síntesis) vive inline en el bloque "## Rol: orquestador" de `CLAUDE.md`, que se auto-carga. Aquí está el detalle extendido y, abajo, las **Reglas del proyecto**. NO invoques `Agent(subagent_type: leader)`.
11
+
12
+ Tu único trabajo como orquestador es **descomponer y coordinar**, nunca implementar.
11
13
 
12
14
  ## Protocolo de arranque
13
15
 
@@ -13,7 +13,24 @@
13
13
  # bottom — `$cmd` is already parsed and in scope there.
14
14
  set -euo pipefail
15
15
 
16
- cmd=$(jq -r '.tool_input.command // empty' 2>/dev/null || true)
16
+ # Extract .tool_input.command from the PreToolUse payload WITHOUT hard-depending
17
+ # on jq (NOT preinstalled on macOS — a missing jq used to make this guard wave
18
+ # every command through). Try jq, then node (Claude Code's own runtime), and if
19
+ # no JSON parser is on PATH fall back to a best-effort sed unwrap so the guard
20
+ # still inspects the command instead of failing open.
21
+ payload=$(cat)
22
+ extract_cmd() {
23
+ if command -v jq >/dev/null 2>&1; then
24
+ printf '%s' "$payload" | jq -r '.tool_input.command // empty' 2>/dev/null && return 0
25
+ fi
26
+ if command -v node >/dev/null 2>&1; then
27
+ printf '%s' "$payload" | node -e 'let s="";process.stdin.on("data",c=>s+=c).on("end",()=>{try{process.stdout.write(String(JSON.parse(s)?.tool_input?.command??""))}catch{}})' 2>/dev/null && return 0
28
+ fi
29
+ # No JSON parser on PATH: pull the "command" string out with sed. Best-effort
30
+ # (won't handle a literal embedded quote), but far better than failing open.
31
+ printf '%s' "$payload" | sed -n 's/.*"command"[[:space:]]*:[[:space:]]*"\(.*\)".*/\1/p'
32
+ }
33
+ cmd=$(extract_cmd)
17
34
  [ -z "$cmd" ] && exit 0
18
35
 
19
36
  base="{{branchBase}}"
@@ -9,7 +9,20 @@
9
9
  # bottom — they keep `cmd` and the original exit codes in scope.
10
10
  set -euo pipefail
11
11
 
12
- cmd=$(jq -r '.tool_input.command // empty' 2>/dev/null || true)
12
+ # Extract .tool_input.command WITHOUT hard-depending on jq (not preinstalled on
13
+ # macOS). Try jq, then node (Claude Code's own runtime), then a best-effort sed
14
+ # unwrap. If nothing extracts a command $cmd stays empty and the gate skips.
15
+ payload=$(cat)
16
+ extract_cmd() {
17
+ if command -v jq >/dev/null 2>&1; then
18
+ printf '%s' "$payload" | jq -r '.tool_input.command // empty' 2>/dev/null && return 0
19
+ fi
20
+ if command -v node >/dev/null 2>&1; then
21
+ printf '%s' "$payload" | node -e 'let s="";process.stdin.on("data",c=>s+=c).on("end",()=>{try{process.stdout.write(String(JSON.parse(s)?.tool_input?.command??""))}catch{}})' 2>/dev/null && return 0
22
+ fi
23
+ printf '%s' "$payload" | sed -n 's/.*"command"[[:space:]]*:[[:space:]]*"\(.*\)".*/\1/p'
24
+ }
25
+ cmd=$(extract_cmd)
13
26
 
14
27
  case "$cmd" in
15
28
  'git commit'*|'git push'*)
@@ -1,15 +1,40 @@
1
- ## Rol: orquestador
1
+ ## Rol: orquestador (centro de gravedad)
2
2
 
3
- Ante una tarea no trivial **actúas como el `leader`** (`.claude/agents/leader.md`): descompones y coordinas, no implementas el código directamente. La inteligencia de orquestacióntabla de escalado, paralelismo, síntesis— vive en ese archivo; encárnala. El catálogo de subagentes está en "## Agentes disponibles".
3
+ Ante una tarea no trivial **actúas como el orquestador**: descompones y coordinas, no implementas el código directamente. Este rol **lo encarnas tú, el agente principal** es el único que puede abrir un abanico de subagentes en paralelo. **NUNCA lo delegues**: no invoques `Agent(subagent_type: leader)`. El archivo `.claude/agents/leader.md` es referencia de profundidad (y las "Reglas del proyecto"), no un subagente para delegar; delegarlo serializa el trabajo y tira el paralelismo. El catálogo de subagentes hoja está en "## Agentes disponibles".
4
4
 
5
- ### Cómo operas
5
+ ### Cómo descomponer (tabla de escalado)
6
6
 
7
- - **Descompón** la tarea y, para cada pieza, **lanza el subagente apropiado** vía la tool `Agent`: investigación → `researcher`/`explorer`; implementación → `implementer`; validación → `reviewer`; cierre con PR → `commit-pr-pilot`.
8
- - **Paraleliza lo independiente**: si necesitas varios investigadores (o varios `implementer` de scopes disjuntos), **emite todas las llamadas `Agent` en un mismo turno** — no una, esperar, otra. Es la palanca que más agiliza. El detalle (fan-out → síntesis, implementers que no se pisen) está en `leader.md`.
9
- - **Sintetiza tú**: los subagentes escriben en `.claude/progress/<archivo>.md` y te devuelven solo la referencia. Recopila los N y analiza a fondo antes de decidir.
7
+ | Complejidad | Subagentes |
8
+ |---|---|
9
+ | Trivial (1 archivo) | 1 `implementer` |
10
+ | Media (2–3 archivos) | 1 `implementer` → 1 `reviewer` |
11
+ | Multi-bug independiente (sin shared state) | N `implementer` en paralelo (1 por bug, scopes aislados) → 1 `reviewer` que valida los N diffs juntos |
12
+ | Compleja (migración, refactor multi-capa) | `ticket-audit` → 2–3 `researcher`/`explorer` en paralelo → `implementer` → `reviewer` → `commit-pr-pilot` |
13
+ | Muy compleja | Divide en sub-tareas y re-aplica la tabla |
14
+
15
+ Investigación con preguntas acotadas → `researcher`; mapas amplios (¿dónde vive X?) → `explorer`. Con audit previo, pásale al `implementer` la ruta de `.claude/progress/audit_<ID>.md`.
16
+
17
+ ### Paralelismo (la palanca — mecánica, no opcional)
18
+
19
+ El paralelismo es **analítico**, no solo velocidad: el valor está en partir el problema en piezas genuinamente independientes y en cómo integras lo que vuelve. La mecánica: cuando la tabla dice "en paralelo", eso se logra emitiendo **TODAS las llamadas `Agent` en un MISMO turno**. Claude por defecto las lanza en serie; el paralelo hay que pedirlo explícito, en un solo mensaje.
20
+
21
+ - ✅ En un mensaje, invoca `Agent` 3 veces (`explorer` auth, db, api). Corren concurrentes; el total ≈ el más lento.
22
+ - ❌ Invocar auth, esperar su `done -> archivo`, luego db, luego api. Eso es serie y tira lo que el paralelo ahorra.
23
+
24
+ Regla: sub-tareas **independientes** (no comparten estado ni una depende del output de otra) → mismo turno. Serializa solo con dependencia real (`implementer` → `reviewer`). **`implementer` en paralelo SOLO con archivos disjuntos** (dos que tocan el mismo archivo se pisan → van en serie; en la duda, serie). Reparte el scope explícito antes de abrir el abanico.
25
+
26
+ **Fan-out → síntesis:** para una pregunta amplia, descompónla en sub-preguntas y lanza un investigador por cada una en paralelo. Cuando vuelven los `done -> archivo`, **recopila y analiza a fondo TÚ**: lee los N archivos juntos, cruza hallazgos (contradicciones, gaps, qué falta) y recién ahí decides la implementación. La síntesis no se delega.
27
+
28
+ ### Ejecución continua (no pausar entre tareas)
29
+
30
+ Aprobado el plan/scope, ejecuta TODAS las sub-tareas sin pedir confirmación entre nodos. No hagas "hice la 1, ¿sigo con la 2?" — ejecuta el plan. Solo paras por: **BLOCKED** (subagente bloqueado que no puedes resolver), **spec ambigua mid-flight** (gap real fuera de scope), o **ciclo completo** (listo para PR). Cap: 2 ciclos `CHANGES_REQUESTED` sobre la misma tarea → escala al usuario en vez de reintentar en loop.
31
+
32
+ ### Síntesis sin teléfono descompuesto
33
+
34
+ Instruye a los subagentes a **escribir en `.claude/progress/<archivo>.md`**; tú recibes solo `done -> archivo`. Verifica el diff/evidencia tú mismo, no confíes ciego en el reporte. Al cerrar el ciclo, cuando `review_<feature>.md` diga `APPROVED`, invoca `commit-pr-pilot` (pre-flight: working tree limpio, no en `{{branchBase}}`, `{{qualityGate.fast}}` verde, `gh auth status` ok). Si dice `CHANGES_REQUESTED`, lanza otro `implementer` — no el pilot.
10
35
 
11
36
  ### Cuándo NO orquestar (hazlo tú directo)
12
37
 
13
- - Pregunta conceptual o lectura pura → responde sin subagentes.
14
- - Cambios en `docs/`, `.claude/`, `CLAUDE.md`, `progress/` → edítalos tú.
15
- - Una sola línea trivial en un archivo conocido → puede no valer el overhead.
38
+ - Pregunta conceptual / lectura pura → responde sin subagentes.
39
+ - Cambios en `docs/`, `.claude/`, `CLAUDE.md`, `progress/` → **edítalos tú** (esos sí los tocas; el código fuente del proyecto NUNCA — eso es del `implementer`).
40
+ - Una sola línea trivial en un archivo conocido → puede no valer el overhead del fan-out. El fan-out cuesta contexto; no abras 5 explorers para una tarea chica.
@@ -0,0 +1,20 @@
1
+ ## Stack — Express (TypeScript)
2
+
3
+ Backend HTTP sobre Express en TypeScript, agnóstico de base de datos (Socket.IO, PeerJS, DB nativo, sin DB, etc.). Las peticiones fluyen en capas: `route → validate(schema) → asyncHandler → controller → capa de datos → ApiResponse`. Los errores se propagan vía `ApiError` y las respuestas se envuelven en `ApiResponse`. El logging va por el `Logger` de winston, nunca `console.log`.
4
+
5
+ Regla de oro: nada de `res.json` / `res.status(500)` crudos; nada de `console.log`; nada de `process.env` fuera del módulo de config. La validación SIEMPRE ocurre en el boundary (con el validador del repo — Zod o Joi). Aplica las skills `express-routes` y `winston-logging` del preset según la capa que toques. Las skills de la capa de datos (mongoose, socketio, etc.) y de validación se inyectan según las dependencias que detecte navori en el repo — si están en `.claude/skills/`, aplícalas.
6
+
7
+ El trabajo de un ticket sigue el pipeline documentado en la skill `ticket-intake` (la orquestadora). No es un generador de specs: es un protocolo que el orquestador ejecuta invocando agentes y skills en orden, con gates objetivos y artefactos en `.claude/progress/`. Mapeo de fases a la infraestructura de navori:
8
+
9
+ | Fase | Quién la cubre | Artefacto |
10
+ |---|---|---|
11
+ | Audit | agente `ticket-audit` | `audit_<id>.md` |
12
+ | Explore | agente `explorer` (2-3 en paralelo) | `explore_<dim>.md` |
13
+ | Design | skill `new-endpoint` según alcance | (en el plan) |
14
+ | Implement | agente `implementer` (aplica las skills de stack) | `impl_<feature>.md` |
15
+ | Verify | skill core `verify-before-done` (Iron Law) | (evidencia en turno) |
16
+ | Review | agente `reviewer` + skill core `review-diff` | `review_<feature>.md` |
17
+ | Debug | skill core `loop-back-debug` | — |
18
+ | PR | skill `pr-create` | URL del PR |
19
+
20
+ navori bootstrapea `current.md` e `history.md`; el resto de artefactos los crea el flujo en runtime.
@@ -0,0 +1,44 @@
1
+ {
2
+ "$schema": "https://navori.dev/schema/navori.preset.v1.json",
3
+ "id": "express",
4
+ "displayName": "Express backend (DB-agnostic)",
5
+ "extends": "core",
6
+ "extras": {
7
+ "managed": [
8
+ {
9
+ "id": "stack-express",
10
+ "relPath": "presets/express/managed/stack.md"
11
+ }
12
+ ],
13
+ "agents": [],
14
+ "skills": [
15
+ {
16
+ "id": "express-routes",
17
+ "relPath": "presets/express-mongoose/skills/express-routes.md",
18
+ "destRelPath": ".claude/skills/express-routes.md"
19
+ },
20
+ {
21
+ "id": "winston-logging",
22
+ "relPath": "presets/express-mongoose/skills/winston-logging.md",
23
+ "destRelPath": ".claude/skills/winston-logging.md"
24
+ },
25
+ {
26
+ "id": "new-endpoint",
27
+ "relPath": "presets/express-mongoose/skills/new-endpoint.md",
28
+ "destRelPath": ".claude/skills/new-endpoint.md"
29
+ },
30
+ {
31
+ "id": "ticket-intake",
32
+ "relPath": "presets/express-mongoose/skills/ticket-intake.md",
33
+ "destRelPath": ".claude/skills/ticket-intake.md"
34
+ },
35
+ {
36
+ "id": "pr-create",
37
+ "relPath": "presets/express-mongoose/skills/pr-create.md",
38
+ "destRelPath": ".claude/skills/pr-create.md"
39
+ }
40
+ ],
41
+ "hooks": []
42
+ },
43
+ "invariants": ["express-routes", "asyncHandler", "ApiResponse", "ticket-intake"]
44
+ }
@@ -0,0 +1,7 @@
1
+ ## Stack — Vite + React + TypeScript
2
+
3
+ SPA sobre Vite + React 18 + TypeScript, agnóstica de UI lib (CSS Modules, Tailwind, styled-components, o una lib de componentes). Organización por feature: cada feature vive en su carpeta con sus componentes, hooks y estado local; lo compartido (UI primitives, utils, hooks genéricos) va a carpetas comunes. Los componentes son funcionales con hooks; nada de class components nuevos.
4
+
5
+ Regla de oro: tipado estricto (sin `any` injustificado — ver el bloque de tipado); side-effects en `useEffect` con deps completas; data-fetching por la capa que use el repo (fetch/axios, TanStack Query si está — se inyecta como library-skill según deps). El estado del servidor NO se duplica en estado global; el estado global (Redux/Zustand/Context) es solo para lo genuinamente compartido y de cliente. Aplica la skill `new-feature` para dar de alta una feature nueva con la estructura del repo. Las skills de UI lib, forms y state se inyectan según las dependencias que detecte navori.
6
+
7
+ El trabajo de un ticket sigue el pipeline de la infraestructura de navori: `ticket-audit` → `explorer` (en paralelo) → `implementer` (aplica las skills de stack) → `verify-before-done` → `reviewer` + `review-diff` → `commit-pr-pilot`. navori bootstrapea `current.md` e `history.md`; el resto de artefactos los crea el flujo en runtime bajo `.claude/progress/`.
@@ -0,0 +1,23 @@
1
+ {
2
+ "$schema": "https://navori.dev/schema/navori.preset.v1.json",
3
+ "id": "vite-react-ts",
4
+ "displayName": "Vite + React + TS SPA (UI-lib-agnostic)",
5
+ "extends": "core",
6
+ "extras": {
7
+ "managed": [
8
+ {
9
+ "id": "stack-vite-react-ts",
10
+ "relPath": "presets/vite-react-ts/managed/stack.md"
11
+ }
12
+ ],
13
+ "agents": [],
14
+ "skills": [
15
+ {
16
+ "id": "new-feature",
17
+ "relPath": "presets/vite-react-ts-mantine/skills/new-feature.md",
18
+ "destRelPath": ".claude/skills/new-feature.md"
19
+ }
20
+ ],
21
+ "hooks": []
22
+ }
23
+ }
@@ -87,7 +87,7 @@ No es debilidad — es eficiencia. 3 intentos a ciegas valen menos que 1 convers
87
87
  ## Conexión con el resto del harness
88
88
 
89
89
  - `implementer`: invoca este skill cuando el primer fix no resuelve el síntoma. NO devuelve `done` hasta haber pasado por Reset hipótesis si el repro inicial falla.
90
- - `verify-before-done`: este skill se aplica AGAS de verify-before-done — primero validas que el fix realmente arregló el síntoma (esto), luego validas que el resto del quality gate sigue verde (verify-before-done).
90
+ - `verify-before-done`: este skill se aplica ANTES de verify-before-done — primero validas que el fix realmente arregló el síntoma (esto), luego validas que el resto del quality gate sigue verde (verify-before-done).
91
91
  - `ticket-audit`: cuando un bug entra al agente ticket-audit, la "Hipótesis de causa raíz" es el primer candidate del loop. Si el fix de esa hipótesis no funciona, ticket-audit puede ser reinvocado con la info nueva.
92
92
 
93
93
  ## Cierre
@@ -16,8 +16,21 @@
16
16
  set -euo pipefail
17
17
 
18
18
  # PreToolUse(Bash) passes the command — gate to commit/push. The Stop hook
19
- # passes no command — run unconditionally at session close.
20
- cmd=$(jq -r '.tool_input.command // empty' 2>/dev/null || true)
19
+ # passes no command — run unconditionally at session close. Extract without
20
+ # hard-depending on jq (not preinstalled on macOS): try jq, then node (Claude
21
+ # Code's own runtime), then a best-effort sed unwrap. No command extracted →
22
+ # empty $cmd → runs unconditionally.
23
+ payload=$(cat)
24
+ extract_cmd() {
25
+ if command -v jq >/dev/null 2>&1; then
26
+ printf '%s' "$payload" | jq -r '.tool_input.command // empty' 2>/dev/null && return 0
27
+ fi
28
+ if command -v node >/dev/null 2>&1; then
29
+ printf '%s' "$payload" | node -e 'let s="";process.stdin.on("data",c=>s+=c).on("end",()=>{try{process.stdout.write(String(JSON.parse(s)?.tool_input?.command??""))}catch{}})' 2>/dev/null && return 0
30
+ fi
31
+ printf '%s' "$payload" | sed -n 's/.*"command"[[:space:]]*:[[:space:]]*"\(.*\)".*/\1/p'
32
+ }
33
+ cmd=$(extract_cmd)
21
34
  if [ -n "$cmd" ]; then
22
35
  case "$cmd" in
23
36
  'git commit'*|'git push'*) ;;
@@ -1,14 +1,14 @@
1
1
  ---
2
2
  name: engram-leader-extension
3
- description: Protocolo Engram para el agente líder. Buscá contexto antes de descomponer, guardá decisiones proactivamente, cerrá sesión con summary.
3
+ description: Protocolo Engram para el agente líder. Busca contexto antes de descomponer, guarda decisiones proactivamente, cierra sesión con summary.
4
4
  type: behavior
5
5
  ---
6
6
 
7
7
  ## Engram (memoria persistente)
8
8
 
9
- Antes de descomponer trabajo: **buscá contexto** con `mem_search` usando keywords del ticket. Si encontrás un audit previo de la misma área o una decisión arquitectónica relacionada, leelo antes de tirar al `implementer`. No re-descubrir lo que ya está guardado.
9
+ Antes de descomponer trabajo: **busca contexto** con `mem_search` usando keywords del ticket. Si encuentras un audit previo de la misma área o una decisión arquitectónica relacionada, léelo antes de tirar al `implementer`. No re-descubrir lo que ya está guardado.
10
10
 
11
- Después de cada decisión arquitectónica, plugin nuevo o convención establecida en la sesión: `mem_save` proactivo con tipo apropiado (`decision`, `convention`, `pattern`, `bugfix`). Lead con qué decisión + por qué + dónde aplica.
11
+ Después de cada decisión arquitectónica, plugin nuevo o convención establecida en la sesión: `mem_save` proactivo con tipo apropiado (`decision`, `convention`, `pattern`, `bugfix`). Encabeza con qué decisión + por qué + dónde aplica.
12
12
 
13
13
  Antes de cerrar la sesión: `mem_session_summary` obligatorio con:
14
14
 
@@ -9,8 +9,21 @@
9
9
  set -euo pipefail
10
10
 
11
11
  # PreToolUse(Bash) passes the command — gate to commit/push. The Stop hook
12
- # passes no command — run unconditionally at session close.
13
- cmd=$(jq -r '.tool_input.command // empty' 2>/dev/null || true)
12
+ # passes no command — run unconditionally at session close. Extract without
13
+ # hard-depending on jq (not preinstalled on macOS): try jq, then node (Claude
14
+ # Code's own runtime), then a best-effort sed unwrap. No command extracted →
15
+ # empty $cmd → runs unconditionally.
16
+ payload=$(cat)
17
+ extract_cmd() {
18
+ if command -v jq >/dev/null 2>&1; then
19
+ printf '%s' "$payload" | jq -r '.tool_input.command // empty' 2>/dev/null && return 0
20
+ fi
21
+ if command -v node >/dev/null 2>&1; then
22
+ printf '%s' "$payload" | node -e 'let s="";process.stdin.on("data",c=>s+=c).on("end",()=>{try{process.stdout.write(String(JSON.parse(s)?.tool_input?.command??""))}catch{}})' 2>/dev/null && return 0
23
+ fi
24
+ printf '%s' "$payload" | sed -n 's/.*"command"[[:space:]]*:[[:space:]]*"\(.*\)".*/\1/p'
25
+ }
26
+ cmd=$(extract_cmd)
14
27
  if [ -n "$cmd" ]; then
15
28
  case "$cmd" in
16
29
  'git commit'*|'git push'*) ;;
@@ -9,8 +9,21 @@
9
9
  set -euo pipefail
10
10
 
11
11
  # PreToolUse(Bash) passes the command — gate to commit/push. The Stop hook
12
- # passes no command — run unconditionally at session close.
13
- cmd=$(jq -r '.tool_input.command // empty' 2>/dev/null || true)
12
+ # passes no command — run unconditionally at session close. Extract without
13
+ # hard-depending on jq (not preinstalled on macOS): try jq, then node (Claude
14
+ # Code's own runtime), then a best-effort sed unwrap. No command extracted →
15
+ # empty $cmd → runs unconditionally.
16
+ payload=$(cat)
17
+ extract_cmd() {
18
+ if command -v jq >/dev/null 2>&1; then
19
+ printf '%s' "$payload" | jq -r '.tool_input.command // empty' 2>/dev/null && return 0
20
+ fi
21
+ if command -v node >/dev/null 2>&1; then
22
+ printf '%s' "$payload" | node -e 'let s="";process.stdin.on("data",c=>s+=c).on("end",()=>{try{process.stdout.write(String(JSON.parse(s)?.tool_input?.command??""))}catch{}})' 2>/dev/null && return 0
23
+ fi
24
+ printf '%s' "$payload" | sed -n 's/.*"command"[[:space:]]*:[[:space:]]*"\(.*\)".*/\1/p'
25
+ }
26
+ cmd=$(extract_cmd)
14
27
  if [ -n "$cmd" ]; then
15
28
  case "$cmd" in
16
29
  'git commit'*|'git push'*) ;;