Skip to content

Hooks y gates fiables en los cuatro backends, revisión acotada y prosa sin capacidades ausentes - #106

Merged
gmoncor merged 39 commits into
mainfrom
claude/metarepo-changes-audit-nco5e1
Oct 14, 2026
Merged

gmoncor merged 39 commits into
mainfrom
claude/metarepo-changes-audit-nco5e1

Conversation

@gmoncor

@gmoncor gmoncor commented Oct 14, 2026

Copy link
Copy Markdown
Owner

Que cambia

39 commits, uno por cambio, que corrigen prosa, hooks y gates para que hagan lo que dicen en los cuatro backends:

  • Hooks y gates
    • Codex carga sus hooks y arranca: claves del esquema, justification y un modelo de su catálogo.
    • Codex y Gemini lanzan los hooks desde la raíz y usan los nombres reales de herramientas (replace, run_shell_command, tool_input.command).
    • El review-gate contrasta el repositorio del commit observado (-C, --git-dir, GIT_DIR) con el mismo diff que el emisor (--no-ext-diff --no-textconv).
    • El analizador de órdenes git une piezas entrecomilladas, expande alias en línea y corta la recursión de funciones fallando cerrado.
    • El estado efímero de los hooks vive en una carpeta por usuario.
    • Un solo predicado enabled decide qué hooks están activos.
    • turn-budget cuenta por agente.
  • Flujo de implementación
    • Cada paso de los workflows corre con el agente de su rol.
    • El Estado de cada task se escribe.
    • Las rondas de corrección tienen tope de 3, con re-revisión sobre el delta.
    • La convergencia reporta brechas y un paso aparte crea las tasks.
    • --parallel[=N] tiene tope, serializa colisiones y pone el gate y el git del índice en exclusión mutua.
    • El revisor recibe el resultado real del gate y las desviaciones declaradas.
  • Prosa
    • Núcleo con coste de verificación y operativa.
    • Descriptions de skills y comandos con condición y frontera.
    • Las variantes de Codex, Antigravity y Gemini no prometen capacidades exclusivas de Claude Code.
    • El registro de sesiones no inventa modelo ni versión del CLI.
  • Tests
    • Contrato de hooks contra payloads reales capturados de Claude Code 2.1.296.
    • Conteos de árboles atados al disco y presupuesto de contexto por pila de rol.
    • Tests de install independientes del uid.
    • Los tests de hooks ya no escriben en el registro del proyecto instalado.

Por que

Varios mecanismos parecían enforzar y no lo hacían: Codex ignoraba su hooks.json entero, los guards de Gemini no reconocían sus herramientas reales y una función recursiva hacía fallar abiertos los hooks. La prosa también afirmaba cosas que el código no hacía, como el modelo del implementador o la señal de revisión en backends sin motor. Cada cambio se midió contra el runtime real cuando era posible (codex-cli 0.162.1, Gemini CLI 0.63.0, Claude Code 2.1.296).

Como probarlo

  • npm test: 1118 tests, 1117 pass, 0 fail. El único skip es la instalación real con el gestor de extensiones de Gemini, que necesita red y CLI.
  • node scripts/compile.js --check: sin deriva.
  • Tras node bin/cli.js install --backend claude y --backend gemini en un directorio temporal, node --test "hooks/tests/*.test.js" da 0 fallos y no añade líneas a ai_docs/audits/provenance.jsonl.

Checklist

  • El cambio tiene un unico proposito: cada commit es un único cambio acotado. La PR agrupa el lote para publicarlo junto
  • Si toca un agente, comando o skill, el cambio equivalente esta aplicado en los cuatro backends (Claude Code, Gemini CLI, Codex y Antigravity)
  • Documentacion actualizada (README.md, CLAUDE.md, GEMINI.md) si el comportamiento cambia
  • Entrada anadida en CHANGELOG.md bajo ## [Unreleased]
  • Los hooks (hooks/*.js) se ejecutan sin error con Node >= 20
  • Sin secretos, credenciales, rutas locales ni configuracion de mi IDE
  • Finales de linea LF (los normaliza .gitattributes)
  • Mensajes de commit en formato <tipo>: <descripcion>, asunto de 72 caracteres o menos: dos asuntos tienen 73 y 74 caracteres (update: descriptions de skills… y update: revisión con evidencia del gate…). El resto cumple

Compatibilidad

  • Este cambio rompe la compatibilidad con proyectos que ya usan el framework

  • Registro de sesiones: cc_version vale siempre null y session_model solo se rellena si el CLI lo envía en el arranque. Un consumidor que esperaba esos valores debe tratarlos como opcionales.

  • Codex: .codex/config.toml pasa a gpt-5.5 y las reglas usan justification. update sustituye los ficheros gestionados; si los editaste a mano, revisa el aviso de update.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS


Generated by Claude Code

claude added 30 commits October 13, 2026 18:59
Las descriptions de asesor, implementar, planificar, spec, tareas y
estado empezaban por «Se activa…», usaban frases del usuario y no
nombraban la skill vecina; planificar y spec competían por «crear una
spec». Ahora siguen la guía de CONTRIBUTING: condición observable, qué
hace y a qué skill van los casos que no son suyos. El comentario de
cabecera de asesor se alinea con esa guía.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
Estos comandos reciben $ARGUMENTS pero no indicaban qué argumento
esperan. El campo solo lo usa Claude Code: command-to-backend lee solo
description, así que ningún derivado cambia.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
Los cuatro comandos reciben $ARGUMENTS pero no declaraban argument-hint,
así que Claude Code no mostraba qué argumento esperan al autocompletar.
El campo solo lo usa Claude Code: command-to-backend lee solo
description y command-to-skill toma el frontmatter del fragmento, de
modo que ningún derivado cambia.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
La guía de contribución seguía diciendo que el repositorio no tenía
integración continua, aunque .github/workflows/test.yml ya ejecuta npm
test y el gate de deriva en cada PR y en push a main, y exigía Node
>= 20.11 para los hooks, cuando los hooks funcionan con >= 20 y 20.11
es el mínimo de engines para la suite. La entrada de [Unreleased] que
afirmaba que no había CI se reescribe.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
Los prompts de revisión por task y de auditoría exigían seguir todos los
pasos de la plantilla sin saltar ninguno, mientras los agentes aplican
los pasos pertinentes al riesgo y declaran los omitidos. Ahora los
prompts dicen lo mismo. Se retira «si la evidencia es ambigua, reporta
el hallazgo como problema», que contradecía la regla del propio prompt
de auditoría: las dudas sin evidencia van en avisos y no bloquean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
Los agentes no declaraban Grep ni Glob, y el planificador tenía que
reescribir ficheros enteros para corregir una spec. La política de
Gemini traduce ahora Grep -> grep_search y Glob -> glob en map, y ambas
salen de always, que las concatenaba sin deduplicar; retirarlas es
seguro porque los cuatro agentes las declaran. El fixture del test de
traducción declara también Grep/Glob, como el asesor real. Codex y
Antigravity no cambian.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
La plantilla de PR no decía cómo revertir el cambio, no tenía vínculo a
issue ni una frase para quien no conoce el código; ahora incluye las
tres, con la orden de revert para merge commit, squash y rebase.

/revision revisaba sin comprobar si la rama ya estaba fusionada: un
Paso 0 lo confirma primero con la PR y, sin PR, con git (avisando de
que un squash o un rebase merge no se detectan así) y, si ya lo está,
revisa como post-merge. El comando gana argument-hint. La skill de Codex
y Antigravity cambia su description a condición, acción y frontera, y su
postura aplica el criterio de bloqueo de revision_adversarial.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
El bloqueo de escrituras solo engancha las herramientas de edición
(Write, Edit, NotebookEdit); lo escrito por shell no pasa por él y lo
detecta la revisión del diff. CLAUDE.md y README lo declaran ahora.

El motivo de denegación invitaba a añadir la ruta a la task, y como
ai_docs/ está exento del guard un implementador podía ampliar su propio
alcance. Ahora separa los remedios: quien implementa se detiene y
reporta la desviación; quien planifica declara la ruta en la task.

README añade una guía por herramienta: Copilot, Windsurf y Devin leen
AGENTS.md, pero ahí no corren hooks ni workflows, y dice qué copiar.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
La skill pr tiene efecto externo: declara disable-model-invocation y una
description que deja claro, sin depender de la sintaxis de un backend,
que solo se usa cuando el usuario pide explícitamente crear o revisar
una PR. El transform de skills retira los campos de Claude Code según el
backend: Antigravity/Codex pierden argument-hint y el flag; Gemini solo
el flag. Una skill sin esos campos sigue saliendo idéntica.

La deriva de derivados se comprobaba varias veces por run de CI con la
misma severidad. Los dos casos que lanzaban compile.js --check como
subproceso se fusionan en uno, y el paso duplicado sale del workflow:
npm test ya falla con cualquier deriva.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
El caso de rutas fallidas usaba chmod 0555, que no impide escribir a
root, y se saltaba en silencio en Windows. Ahora .claude es un fichero
normal: crear .claude/workflows falla con cualquier uid y plataforma.

F3 afirmaba que siempre aborta exactamente una de las dos instalaciones
concurrentes, lo que dependía de la velocidad de copia. Ahora comprueba
invariantes lógicas (0 o 1, al menos un éxito, abortos solo por el lock,
sin EEXIST, destino completo y sin lockfile); el lock lo sigue
acreditando el test determinista del lockfile preexistente.
ejecutarAsync usa process.execPath.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
…esgo

Las skills bugfix, cleanup, commit, diff y testing empezaban por «Se
activa», citaban frases literales del usuario y no marcaban la frontera
con la skill vecina. Ahora siguen la fórmula condición + qué hace +
frontera; bugfix y commit declaran que comparten plantilla con el
comando homónimo sin depender del backend. testing baja al cuerpo la
redirección al setup de tests. El cuerpo de bugfix, cleanup, commit,
testing y pr deja de exigir todos los pasos de la plantilla: aplica los
pertinentes al riesgo y declara los omitidos, como ya hacen los agentes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
revision-adversarial y revisar-tarea se anunciaban en el mismo punto que
implementar-spec y planificar, que ya revisan cada task: su description
acota ahora el uso al trabajo hecho a mano fuera de esos workflows.
auditar recuerda que planificar ya audita e inicio pierde el «Se
activa». Ambas skills de revisión aplican los pasos pertinentes al
riesgo y declaran los omitidos.

revisar_tarea.md fija cuándo emitir cada veredicto: NECESITA_AJUSTES
solo con un hallazgo material con evidencia; la duda sin evidencia va a
avisos y no impide LISTO_PARA_IMPLEMENTAR. «NUNCA aceptes un plan sin
cuestionar» convertía cualquier duda en ajuste.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
El contador era único por sesión y solo lo reiniciaba un git commit
visto como tool call; el workflow commitea por child_process, así que
sumaba todas las tasks. Cada subagente cuenta ahora en su registro
(<sesión>-a-<agent_id>, con hash si el id es muy largo, o <sesión>-sub
sin agent_id) y el commit del hilo principal reinicia también el común.
Los avisos de subagente ya no piden commitear, y en advisory el
hard_stop propone un checkpoint en vez de ordenar interrumpir; en
enforce se sigue denegando.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
El gate de tests no volvía a correr tras la pasada de corrección, una
revisión APROBADA con problemas críticos se commiteaba y un PARCIAL
pasaba a gate y commit sin bloquear a sus dependientes. Ahora el gate se
repite tras corregir, normalizarRevision convierte el veredicto
contradictorio en NECESITA_CORRECCIONES y solo COMPLETADA satisface una
dependencia; PARCIAL se aparta en stash.

Preparación, revisión y commit comparten pathspecDeTask: en secuencial,
el proyecto salvo ai_docs/tasks y ai_docs/audits, para que el registro
de sesiones no impida arrancar y un cambio en ai_docs/core entre en el
commit de su propia task; en concurrente, solo las rutas del ámbito que
cambiaron, sin add cuando no hay ninguna, de modo que un fichero
declarado y no creado o un borrado ya preparado no rompen la
preparación. El gate deja de preparar fuera del proyecto y corre la
suite en su raíz con la salida acotada. Los prompts dejan de contradecir
a las plantillas.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
Las instrucciones raíz de los tres backends no decían nada sobre cuándo
compensa una verificación, cómo informar, cómo pasar texto largo a una
orden ni cómo esperar procesos largos. Se añaden al bloque compartido
de límites del núcleo, sin herramientas propias de un solo backend,
junto con una tabla breve de dónde vive cada tipo de información. Los
temporales siguen fuera del árbol de trabajo, con ruta absoluta literal,
como ya pide la plantilla de commit.

La regla clave 7 aclara que el revisor bloquea solo lo material, y la
fila de asesor deja de anunciarse como read-only: tiene Bash y su
restricción vive en su propio cuerpo.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
Los hooks trataban enabled ausente como encendido y gates_on del
registro de sesiones exigía enabled === true: una sección sin enabled
dejaba el hook corriendo mientras el registro lo declaraba apagado.
hookEnabled en sdd-hook-utils.js aplica un booleano explícito o el valor
por defecto de una única tabla (review-gate apagado, el resto
encendido); los cuatro hooks y gatesOn la consumen, y gates_on cuenta
también los hooks encendidos por defecto sin sección. Tests de
coherencia ejecutan cada hook y comparan con gates_on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
REVIEW_SCHEMA no tenía avisos y reviewSummary solo reenviaba veredicto,
problemas y ajustes: la duda sin evidencia que revisar_tarea.md manda a
«Avisos (no bloquean)» se perdía o acababa en problemas y abría la
segunda pasada. REVIEW_SCHEMA gana avisos opcional, el prompt por task
pide no mezclarlos con problemas, el resumen sale de la función pura
resumenDeRevisiones (lib/auditoria.js), que los reenvía como
avisos_no_bloqueantes, y el prompt del auditor los manda a sus avisos,
no a huecos ni incoherencias.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
En codex-cli 0.162.1 apply_patch entrega el parche en tool_input.command
y el guard de pipeline solo leía input/patch/content: respondía con el
aviso de ruta ilegible y nunca denegaba. Ahora lee command y, si no trae
cabeceras, el resto; y reconoce «*** Move to:», de modo que renombrar
hacia una ruta no declarada también se deniega. El guard de commits
acepta exec_command como alias defensivo (no observado como tool_name;
el shell llega como Bash). Tests con la forma medida.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
codex-cli 0.162.1 rechaza el parámetro reason en prefix_rule y no
arranca; con justification las reglas cargan y bloquean
git commit --no-verify. o4-mini no figura en el catálogo de esa versión
(aviso de metadatos): config.toml pasa a gpt-5.5. install y update con
codex o all avisan del modelo del config.toml instalado y de
`codex debug models`. El README deja de presentar las reglas como
experimentales. Tests de contrato de las reglas y del modelo frente al
catálogo medido.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
Antes cualquier veredicto distinto de APROBADA abría la corrección, el
corrector recibía también los menores, la segunda revisión empezaba de
cero sin los hallazgos previos y, tras una sola corrección, la task se
descartaba.

Ahora solo un crítico, un RECHAZADA o una revisión sin veredicto abren
ronda; los menores viajan, aplanados, en el cuerpo del commit. Cada
ronda corrige los críticos, vuelve a pasar el gate y re-revisa con los
hallazgos previos (resuelto, persistente o refutado) y el delta,
calculado sobre el último diff con revisión utilizable y acotado al
pathspec de la task, sin leer el índice compartido. Tras tres rondas la
task queda BLOQUEADA_REVISION: su trabajo se aparta con nombre, sin
destruir nada, y los hallazgos abiertos pasan al usuario.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
codex-cli 0.162.1 ignoraba .codex/hooks.json entero por las claves
_comment: ahora solo lleva claves del esquema, con un test que rechaza
claves fuera del esquema. El shell llega como tool_name Bash, así que el
matcher del guard de commits pasa a Bash. Cada orden sube desde el cwd
hasta la raíz del proyecto (primer directorio con .git,
.codex/hooks.json o hooks/hooks.json; hasta 10 niveles) y lanza desde
ahí el hook -codex correspondiente;
dentro de un subdirectorio los hooks ya no fallan por ruta relativa. Si
no encuentra el hook, falla en abierto con aviso por stderr.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
El estado efímero de turn-budget y del rastreador de lecturas vivía
suelto en la raíz del temporal del sistema. Ahora va a una subcarpeta
propia: sdd-hooks-<uid> en POSIX y sdd-hooks en Windows. Tras crearla se
valida con lstat que sea un directorio real, no un enlace, del uid
propio, y se deja en 0700; si la validación falla, se avisa una vez por
stderr y se vuelve a la raíz del temporal, como antes. La purga no sigue
enlaces, ignora ficheros de otro usuario y no cuenta los que no puede
borrar.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
La verificación de cierre de spec ya no escribe: devuelve brechas con
criterio, hallazgo, evidencia y severidad. Con alguna BLOQUEANTE, un
paso con escritura, inyectado en resolverConvergencia, las convierte en
tasks numeradas con next-task-number.sh y devuelve sus rutas; con solo
WARNING la spec converge y los avisos quedan para el usuario. Si la
creación no devuelve rutas, las brechas siguen en el resultado. El log
distingue lo reportado de lo creado.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
El gate calculaba el hash con git diff --cached en la raíz de partida,
aunque el commit apuntara a otro repositorio. Ahora localiza la raíz del
commit observado: git -C (también con ~), --git-dir/--work-tree y las
asignaciones GIT_DIR=/GIT_WORK_TREE=, o el cwd del payload; si la ruta
no se puede resolver (variables, comillas invertidas), usa la raíz de
partida como antes. El diff corre con core.fsmonitor desactivado y con
el mismo comando que el emisor de la señal, de modo que un diff.external
global da el mismo hash en los dos lados. sdd-git-command exporta
segmentar para que el gate no duplique la segmentación.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
Ninguna llamada agent() de planificar.js ni de implementar-spec.js
declaraba agentType: todos los pasos corrían con el modelo de la sesión
y sin las herramientas de su rol, y la documentación prometía un
implementador en otro modelo que el workflow no aplicaba.

Cada llamada declara ahora su rol (asesor, planificador, implementador
o revisor); el modelo y las herramientas salen del frontmatter del
agente, única fuente. Un test exige agentType existente en cada
llamada, con fixture negativo. «Modelo por defecto» deja de nombrar ids
y describe lo que hace el código.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
Gemini CLI 0.63.0 llama replace y run_shell_command a la edición y al
shell: los matchers con edit_file y run_command no cubrían ninguna de
las dos, y los cuatro agentes de .gemini/agents no cargaban (Invalid
tool name). Los matchers y el mapa de herramientas pasan a los nombres
medidos, y los comandos de hooks/hooks.json a la plantilla del
lanzador, que ejecuta cada hook desde la raíz aunque Gemini arranque en
un subdirectorio; antes fallaban con Cannot find module y la escritura
no declarada pasaba. GEMINI.md documenta además el aviso inocuo de
skills duplicadas con --backend all.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
Hasta ahora el campo Estado solo se escribía al crear la task y el
workflow calculaba el resultado en memoria: el documento seguía
PENDIENTE para siempre y /estado no podía contar el progreso.

ejecutarTask escribe EN_PROGRESO justo antes de implementar y, al
retornar, el estado final (COMPLETADA, PARCIAL, FALLIDA o
BLOQUEADA_REVISION), solo en las tasks intentadas: las bloqueadas,
las que encuentran residuo al empezar y las no ejecutadas tras una
parada siguen PENDIENTE. El escritor marcarEstado reescribe solo el
valor de la última línea Estado:, resuelve la ruta ascendiendo desde
el directorio en curso, se limita a las tasks de ai_docs/tasks/ (nunca
una spec; ruta fuera de todo commit) y ante cualquier fallo avisa sin
cambiar el resultado de la task.

La plantilla de tasks documenta quién escribe cada estado, /implementar
aplica las mismas transiciones y /estado cuenta por estado vigente.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
Gemini CLI llama replace a su edición parcial y run_shell_command a su
shell. Los conjuntos de nombres de pipeline-guard, read-before-edit,
commit-guard y turn-budget no los incluían, así que una edición o un
commit por esas herramientas salían del hook sin evaluarse aunque el
matcher los enrutara. replace se trata como escritura parcial. Se retira
edit_file, que ninguna versión medida expone ni ningún matcher enruta;
run_command se mantiene porque es la shell de Antigravity. Un test nuevo
cubre los casos positivos y negativos con la forma de payload de Gemini.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
El aviso buscaba /Estado:\s*PENDIENTE/ en las 10 primeras líneas, y la
plantilla de task escribe **Estado:** PENDIENTE, que no casaba: el aviso
no saltaba nunca con tasks reales. estaPendiente pasa a usar
estadoVigente (exportado desde sdd-plan-state) sobre el texto completo:
la misma última línea Estado: que reescribe el escritor del motor de
workflows, así que lector y escritor coinciden. Tests con fixture leído
de la plantilla y composición con marcarEstado donde el motor está
instalado.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
La skill de Codex/Antigravity prometía emitir la señal de revisión, que
solo existe en el motor de workflows de Claude Code. Ahora el revisor
revisa el diff y solo con APROBADA se commitea, con tope de 3 rondas y
BLOQUEADA_REVISION. Las dos variantes procedurales comprueban el árbol
limpio al empezar, escriben el Estado según tareas.md y apartan el
trabajo no aprobado con un stash con nombre acotado a los ficheros con
cambios, sin borrar nada; sin script de numeración informan del error.
Gemini declara su revisión no independiente. AGENTS.md documenta la
delegación de Codex con los nombres verificados en 0.162.1 y el modelo
gpt-5.5, deja de anunciar revision-adversarial como paso 5 y de decir
que el implementador commitea. El Paso 4bis usa los 4 campos del schema
del workflow. Un test escanea las salidas no Claude en busca de
capacidades exclusivas de Claude Code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
…etida

El revisor recibe del flujo el resultado del gate de tests (comando y
código de salida) y las desviaciones que declaran implementador y
corrector: el gate es la única suite completa por task, y los demás
agentes ejecutan pruebas dirigidas. La postura del revisor vive en su
agente y en la plantilla, así que los prompts dejan de repetirla, y cada
agente lee de ai_docs/core/ solo las secciones citadas (el intake
conserva la lectura completa). Cada workflow declara su tamaño.

El emisor de la señal de revisión y sdd-review-gate leen el diff con
--no-ext-diff --no-textconv: el hook ya no ejecuta herramientas de diff
configuradas en el repositorio antes de decidir, y el hash sigue atando
en los dos lados.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
Los tests de cada hook fabrican el payload con los campos que el hook
lee, así que pasan aunque el runtime envíe otros. Se añade un fixture
capturado de Claude Code 2.1.296 (anonimizado) y un banco en proceso que
comprueba, para cada hook cableado en .claude/settings.json, que los
campos que lee existen en el payload real de su evento, que los de
subagente solo llegan en llamadas de subagente y que toda lectura del
payload en la fuente del hook está declarada.

CONVENTIONS.md fija el criterio de aceptación de un cambio de hook:
fixture real con la versión del CLI, mutante que pone el test en rojo y
productor de cada dato verificado.

measure-hook-overhead.js reutiliza hookEnabled de sdd-hook-utils: su
copia local daba por encendido sdd-review-gate sin clave enabled, y el
hook real lo da por apagado.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
Los árboles de los fragmentos y del núcleo citaban a mano cuántos
comandos, skills, hooks y plantillas hay, sin nada que los atara al
disco: ahora se comprueban contra los mismos contadores que la tabla
del README. La pila que carga cada rol (CLAUDE.md + agente + las
plantillas que cita su despacho en los workflows) tiene límite propio:
la medida ×1,15, redondeada al KB. CONVENTIONS.md documenta ese
presupuesto y que subir un límite exige volver a medir.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
--parallel lanzaba el nivel entero a la vez, sin tope ni detección de
colisiones, y dos suites o dos operaciones de git podían pisarse en el
índice compartido. Ahora --parallel[=N] limita las tasks en vuelo
(MAX_CONCURRENCIA = 4 por defecto), las que comparten ficheros
declarados o no tienen ámbito legible van en serie, y el gate de tests,
la preparación del diff, el commit y el apartado pasan por un mutex; la
implementación sigue en paralelo.

El revisor recibe además los ficheros cambiados que no declara ninguna
task en vuelo. Cada sitio del mutex tiene un test con promesas
diferidas que cae si se quita el wrapper de ese sitio. El README declara
el residuo: el gate sigue viendo en el árbol compartido el trabajo a
medias de las hermanas.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
El caso de contrato de entrada de exit-code-contract ejecutaba
sdd-session-start sin SDD_PROVENANCE_FILE, y cada corrida de la suite
en un proyecto instalado añadía dos líneas a su
ai_docs/audits/provenance.jsonl. Ahora el caso inyecta el registro y
una config vacía en un temporal propio, y comprueba que el registro
llegó a ese destino. La corrección va en el llamador y no en el helper,
porque otro test necesita que falte la variable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
El SessionStart capturado de Claude Code (claude -p) no trae model ni
versión. session_model ya escribía null en ese caso, pero la prosa
prometía el modelo y los tests usaban un payload con un campo que el
runtime no envía. Ahora la prosa lo condiciona a que el CLI lo envíe,
y el payload de los tests copia las claves del fixture capturado.

cc_version deja de leer variables de entorno heredadas: medían la
versión del proceso padre, no la del CLI que lanza el hook, y un valor
falso es peor que null. El campo conserva nombre y posición y vale
null mientras el CLI no fije una fuente propia. cohort_id mantiene su
fórmula; sin modelo agrupa por configuración, y la cabecera lo
documenta.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
tokenizar cortaba la palabra en la comilla: git -c user.name='a b'
commit --no-verify dejaba 'a b' como programa y el commit pasaba sin
detectarse, igual que GIT_DIR="/a b" git commit. Ahora une las piezas
adyacentes como el shell, y entrecomillado solo vale true si todas iban
entre comillas, así "--no-"verify llega como flag. El script de bash -c
en una sola palabra con blanco también se re-analiza.

Un alias en línea (git -c alias.x='commit -n' x) añade la invocación
expandida y conserva la original: nombre sin distinguir mayúsculas, en
cadena con detección de bucles, nunca sobre un builtin de git (lista de
git 2.43.0, 140 nombres) y con ! como script anidado.

Cada invocación lleva además entorno, globales (solo las anteriores al
subcomando), separadorAntes/separadorDespues, grupos (paréntesis,
llaves, if…fi y bucles…done; null si no cuadran) y script, para que el
gate de revisión resuelva la raíz del commit. Son campos aditivos:
programa, palabras y flags conservan su forma.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
Una función que se llamaba a sí misma, como el wrapper
git() { command git "$@"; }, agotaba la pila. La excepción hacía
fallar abiertos a commit-guard y al gate de revisión, y con ello
pasaban --no-verify y el commit sin revisar.

Ahora una llamada a función conserva la invocación original y añade
la de su cuerpo. Cada cuerpo se expande como mucho una vez por orden,
lo que cubre la recursión directa y la mutua y deja el coste lineal en
las cascadas. Pasadas 32 expansiones anidadas, el cuerpo no se analiza:
cuenta como un git commit con --no-verify, marcado como incompleta,
que hereda el contexto del punto de llamada. El análisis añade las
invocaciones de un segmento una a una, sin pasarlas como argumentos,
para no agotar la pila con un cuerpo muy largo.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
Añade a [Unreleased] el Estado que escribe el flujo, las rondas de
revisión con tope, el agente por rol, el tope y la partición de
--parallel, el contrato de hooks con payloads reales, la carga de
Codex y Gemini y el refuerzo del review-gate y del analizador de
órdenes git. Marca como incompatibles los cambios del registro de
sesiones y de la configuración de Codex, y corrige las entradas que
estos cambios dejaban desfasadas.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6TkghJV3bztMnLNXV4jTS
@gmoncor
gmoncor merged commit 0d38824 into main Oct 14, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants