Habilidades y hooks de CodeMender para Antigravity

1. Introducción

En este codelab, configurarás un agente de programación de IA (Antigravity) para que la seguridad sea parte de su ciclo de desarrollo normal, en lugar de un paso de revisión independiente. Instalarás un conjunto de habilidades de agente que lo guiarán a través de un ciclo de Plan → Rojo → Verde → Refactorización, y un hook de PreToolUse que intercepta git push, analiza los archivos modificados con CodeMender y devuelve los hallazgos al agente con instrucciones para corregirlos primero con pruebas.

Las habilidades y el hook provienen del framework de agentes de TDD seguro de código abierto. Los instalarás en el mismo espacio de trabajo de ~/codemender-lab que creaste en Conceptos básicos de la CLI de CodeMender.

Qué aprenderás

  • Cómo Antigravity descubre las reglas, las habilidades y los hooks del espacio de trabajo en .agents/.
  • Qué hacen las seis habilidades de Secure TDD y de qué fase del bucle se encarga cada una
  • Cómo un hook de PreToolUse recibe la llamada a la herramienta del agente en stdin y devuelve una decisión de permitir o denegar.
  • Cómo el hook de la puerta de enlace de seguridad (security_gate_hook.sh) ejecuta cm find, clasifica los hallazgos por gravedad, hace un seguimiento de los intentos de corrección y escala con cm verify.
  • Cómo verificar toda la canalización de hooks sin conexión con escáneres simulados antes de apuntarla al cm real

Requisitos previos

  • Completar los conceptos básicos de la CLI de CodeMender Este lab continúa en el directorio ~/codemender-lab y reutiliza su sample_app/, CONTEXT.md, historial de Git y ~/.codemender/config.yaml.
  • Antigravity instalado, con la capacidad de abrir una carpeta local como un espacio de trabajo
  • Se instalaron git, jq y bash. Las secuencias de comandos de hook son de bash simple y se ejecutan en la versión 3.2 de bash de macOS, así como en versiones más recientes.
  • El entorno virtual de Python de los conceptos básicos de la CLI de CodeMender (~/codemender-lab/.venv) con Flask instalado.
  • Conocimientos básicos de secuencias de comandos de shell

2. Configuración de Workspace

Paso 1: Regresa al directorio del lab

Todos los comandos de este lab se ejecutan desde ~/codemender-lab con el entorno virtual activo:

cd ~/codemender-lab && source .venv/bin/activate

Confirma que el espacio de trabajo del lab anterior esté intacto y que tu árbol de trabajo esté limpio:

ls sample_app/data_service.py CONTEXT.md .gitignore
git status --short

git status --short no debería imprimir nada. Si se muestran archivos, confírmalos antes de continuar.

Paso 2: Asigna el nombre main a la rama.

La puerta de enlace de seguridad compara tu árbol de trabajo con origin/main para decidir qué archivos analizar. Si esa referencia no existe, recurre a HEAD~1, que solo abarca la confirmación más reciente. Asegúrate de que tu rama se llame main:

git branch -M main

Paso 3: Agrega un punto de entrada del paquete de pruebas

El bucle de TDD seguro le pide al agente que ejecute python3 -m unittest discover -s tests después de cada corrección, por lo que el espacio de trabajo necesita un directorio tests/. Comienza con una prueba de caracterización para que el paquete tenga algo real que ejecutar:

mkdir -p tests && touch tests/__init__.py
cat << 'EOF' > tests/test_data_service.py
import unittest

from sample_app.data_service import hash_password


class HashPasswordTests(unittest.TestCase):
    def test_returns_hex_digest(self):
        digest = hash_password("hunter2")
        self.assertIsInstance(digest, str)
        int(digest, 16)  # raises ValueError if not hexadecimal


if __name__ == "__main__":
    unittest.main()
EOF
python3 -m unittest discover -s tests

Deberías ver Ran 1 test y OK.

Paso 4: Extiende .gitignore y confirma

Agrega los archivos del entorno de ejecución que produce este lab a .gitignore y, luego, confirma el modelo de referencia:

printf '.security-gate/\nusers.db\n*.bak\n' >> .gitignore
git add -A && git commit -m "Add test suite entry point for Secure TDD"

3. Instala los archivos del framework

Las habilidades, la regla, el hook y el agente de pruebas sin conexión se encuentran en un solo directorio .agents/. En lugar de escribir manualmente unas 800 líneas de Bash, clona el framework y copia ese directorio en tu espacio de trabajo:

git clone --depth 1 https://github.com/h3xar0n/secure-tdd-agent-framework.git /tmp/secure-tdd
cp -R /tmp/secure-tdd/.agents ./.agents
rm -rf /tmp/secure-tdd

Confirma el diseño:

find .agents -type f | sort
.agents/hooks.json
.agents/lib/README.md
.agents/lib/engine_codemender.sh
.agents/lib/engine_semgrep.sh
.agents/lib/gate_common.sh
.agents/rules/secure_tdd_workflow.md
.agents/security_gate_hook.sh
.agents/skills/defensive-developer/SKILL.md
.agents/skills/history-context-seeder/SKILL.md
.agents/skills/local-refactor-scanner/SKILL.md
.agents/skills/security-test-writer/SKILL.md
.agents/skills/skill-evolution-updater/SKILL.md
.agents/skills/threat-model-assessor/SKILL.md
.agents/tests/mocks/cm
.agents/tests/mocks/semgrep
.agents/tests/run_tests.sh

Asegúrate de que el punto de entrada del hook sea ejecutable:

chmod +x .agents/security_gate_hook.sh
ls -l .agents/security_gate_hook.sh

En el resto de este lab, se explica lo que acabas de instalar, paso a paso.

4. La regla de flujo de trabajo siempre activo

Las habilidades se cargan a pedido, cuando el agente decide que la descripción de una habilidad coincide con la tarea. Algo tiene que decirle al agente que los busque en el orden correcto. Ese es el trabajo de .agents/rules/secure_tdd_workflow.md. Sus metadatos iniciales establecen trigger: always_on, por lo que la regla se inserta en cada turno:

---
trigger: always_on
---

# Test-Driven Development with Integrated Security (Secure TDD) Workflow Rule

You MUST strictly follow this 4-phase cyclical workflow for all feature implementations, refactors, and bug fixes:

1. **Phase A (Plan, Scope & Threat Model)**:
   - Ingest `CONTEXT.md` to review established project conventions, approved helpers, and trust zones.
   - Decompose feature requirements, user stories, and acceptance criteria.
   - Invoke the **Threat Model Assessor Skill** to perform a STRIDE evaluation and generate/update `threat_model.md`.

2. **Phase B (Functional & Security Test-First - RED)**:
   - Invoke the **Security Test Writer Skill**.
   - Author unit and integration tests asserting functional behavior (happy paths, business logic), edge cases, AND security boundaries (rejecting invalid inputs, unauthenticated requests, unauthorized role access).
   - Execute the tests and confirm they FAIL for the expected assertion reason (RED).

3. **Phase C (Feature Implementation & Defensive Code - GREEN)**:
   - Invoke the **Defensive Developer Skill**.
   - Author clean, modular production code strictly required to satisfy the functional tests and security assertions.
   - Apply input validation allow-lists, parameterized queries, and least-privilege payload returns.
   - Run the tests to confirm they are GREEN.

4. **Phase D (Refactor, Quality & Scan)**:
   - Invoke the **Local Refactor & Scanner Skill**.
   - Clean up code, eliminate duplication, and verify 100% passing test regressions.
   - Run fast deterministic checks (secrets, dependencies, local SAST).
   - Conduct a guided AI review to verify architectural boundaries and eliminate logic bypasses.
   - Ensure diffs remain small, surgical, and preserve baseline stability.

5. **Continuous Evolution**:
   - If a new pattern, helper function, or architectural convention was introduced, invoke the **Skill Evolution Updater Skill** to document the lesson into `CONTEXT.md` or the appropriate `SKILL.md`.

6. **Multi-Finding Remediation Protocol**:
   - When resolving multiple findings from a scan or security gate rejection, iterate sequentially one finding at a time:
     1. Author one discrete boundary test for the finding (RED).
     2. Implement the minimal defensive fix (GREEN).
     3. Verify local tests pass before moving to the next finding.
   - Avoid applying multi-finding changes in a single unverified edit. Run the full regression test suite only after all individual findings have passed their discrete TDD cycle.

La regla hace referencia a CONTEXT.md, que creaste en Conceptos básicos de la CLI de CodeMender. El mismo archivo que dirigió a cm fix hacia tu convención de consultas parametrizadas ahora dirige la planificación del agente. El elemento 6 es el más importante para este lab: es lo que sigue el agente cuando la puerta de enlace de seguridad rechaza un envío con varios hallazgos a la vez.

5. Las seis habilidades de los agentes

Cada habilidad es un directorio que contiene un archivo SKILL.md con metadatos iniciales de YAML. Se requieren dos campos:

  • name: Es un identificador en minúsculas con guiones.
  • description: qué hace la habilidad y cuándo usarla. El agente lee solo este campo cuando decide si cargar la habilidad completa, por lo que cada descripción a continuación también indica para qué no sirve la habilidad.

Habilidad

Fase

Objetivo

threat-model-assessor

A: Plan

Define el alcance de la función, ejecuta STRIDE y escribe threat_model.md.

security-test-writer

B: Rojo

Escribir pruebas funcionales y de límites que fallen por el motivo correcto

defensive-developer

C: Verde

Escribir el código mínimo que haga que las pruebas se pongan en verde, usando patrones seguros

local-refactor-scanner

D: Refactorización

Limpia, ejecuta el paquete completo, ejecuta los escáneres locales y revisa la diferencia.

skill-evolution-updater

Continuo

Registra las convenciones nuevas en los archivos CONTEXT.md y SKILL.md.

history-context-seeder

Integración

Extrae el historial de Git para propagar CONTEXT.md en un repositorio existente.

A continuación, se muestra el contenido completo para que puedas ver cómo se integran los metadatos iniciales y las instrucciones.

1. threat-model-assessor (fase A)

.agents/skills/threat-model-assessor/SKILL.md:

---
name: threat-model-assessor
description: Plans feature architecture, functional requirements, and evaluates STRIDE security boundaries in Phase A Plan. Use when scoping new features or bug fixes, defining user stories and acceptance criteria, identifying trust boundaries, and generating or updating threat_model.md. Do not use for writing test assertions, implementing production code, or running local scanners.
---

# Planning, Requirements & Threat Model Assessor Skill (Phase A: Plan Phase)

## Overview
Decompose feature requirements, establish functional acceptance criteria, and map trust boundaries before any production code is authored. This skill pairs functional engineering scoping with STRIDE threat modeling at the planning stage, establishing the functional and security acceptance criteria consumed by downstream test writers.

## System Sequence
1. **Ingest Context**: Read `CONTEXT.md` to identify existing architecture, trust boundaries, approved libraries, and conventions.
2. **Decompose Requirements**:
   - Define user stories, input/output data contracts, and functional acceptance criteria.
   - Break complex tasks into bite-sized, testable implementation stages.
3. **Apply STRIDE Threat Modeling**:
   - **Spoofing**: Authentication boundaries, session validation, caller identity checks.
   - **Tampering**: Input payload validation, integrity checks, parameter tampering.
   - **Repudiation**: Audit logging of critical state transitions.
   - **Information Disclosure**: Restrict error responses, prevent stack trace leaks, mask PII/secrets.
   - **Denial of Service**: Resource limits, payload size constraints, timeout limits.
   - **Elevation of Privilege**: Role-Based Access Control (RBAC), caller authorization checks.
4. **Generate/Update `threat_model.md`**:
   - Store or update `threat_model.md` at the workspace root with both Functional & Security Acceptance Criteria.

## Target Output Artifact (`threat_model.md`)
```markdown
# Feature Plan & Threat Model: [Feature Name]

## 1. Functional Scope & Requirements
- **Goal**: [Description of feature or bug fix]
- **Deliverables**: [Endpoints, functions, or modules to create/modify]
- **Functional Acceptance Criteria**: [Expected behaviors and outputs]

## 2. Entry Points & Data Inputs
- Endpoint / Input: [Path / Name]
- Format & Constraints: [Schema / Type]

## 3. Trust Boundaries & Access Controls
- Authentication: [Required / Public]
- Authorization Role: [User / Admin]

## 4. STRIDE Threat Matrix & Security Acceptance Criteria
- [STRIDE Category]: [Threat Description] -> [Required Mitigation & Test Assertion]
```

2. security-test-writer (fase B)

.agents/skills/security-test-writer/SKILL.md:

---
name: security-test-writer
description: Authors test-first unit and integration tests covering functional behavior, edge cases, and security boundaries in Phase B RED. Use when creating failing automated tests before writing production code, asserting HTTP status codes and contract responses, establishing boundary limits, or asserting that exploit payloads are rejected cleanly. Do not use for threat modeling during initial planning, writing production feature code, or running refactor sweeps.
---

# QA & Security Test Writer Skill (Phase B: RED Phase)

## Overview
Translate functional requirements and security criteria from `threat_model.md` and `CONTEXT.md` into executable test cases that fail initially (RED), asserting expected business logic, edge-case handling, and security boundaries before production code is authored.

## Three Verification Pillars
1. **Behavior-Driven Outcomes**:
   - Assert strictly on API/HTTP outcomes (status codes 200/302 for valid requests, 400/401/403 for invalid/unauthorized, expected JSON responses) rather than mocking internal private methods.
2. **Strict Test Isolation**:
   - Ensure test setup and teardown cleanly isolate state (e.g., transaction rollbacks, fresh test contexts) so state never bleeds between test runs.
3. **Integration Over Fragile Mocking**:
   - Utilize local test databases or real server contexts rather than fragile fake mocks to verify realistic functional and security behavior.

## Execution Sequence
1. **Consume Requirements & Threat Model**: Read the task scope, `threat_model.md`, and `CONTEXT.md` for functional requirements and security acceptance criteria.
2. **Author Test Cases**:
   - **Functional Happy Path**: Test validating standard user workflows and expected output payloads.
   - **Functional Edge Cases**: Test missing optional/required parameters, boundary limits, and unexpected data types.
   - **Authentication Boundary**: Assert requests without valid credentials return `401 Unauthorized`.
   - **Authorization Boundary**: Assert requests with insufficient role/scope return `403 Forbidden`.
   - **Input Validation**: Assert malformed, oversized, or un-whitelisted data returns `400 Bad Request`.
   - **Exploit Payloads**: Assert dangerous inputs (SQLi, path traversal `../../`, XSS) are rejected cleanly.
3. **Execute & Verify RED**:
   - Run the project's test command (e.g., `pytest`, `python3 -m unittest discover -s tests`).
   - **Requirement**: Confirm the tests fail due to the expected missing feature logic/boundary assertion and not due to a syntax or import error.
4. **Multi-Finding Handling**:
   - When remediating multiple scanner findings, write and verify one boundary test for one finding at a time before proceeding to defensive implementation.

3. defensive-developer (fase C)

.agents/skills/defensive-developer/SKILL.md:

---
name: defensive-developer
description: Implements clean, maintainable production code to deliver features and satisfy functional and security test assertions in Phase C GREEN. Use when writing minimal, modular production code to turn failing RED tests GREEN, applying input validation allow-lists, enforcing explicit caller authorization, and using parameterized sinks and least-privilege payloads. Do not use for authoring initial tests, performing initial threat modeling, or running post-implementation security scans.
---

# Feature Implementation & Defensive Developer Skill (Phase C: GREEN Phase)

## Overview
Implement clean, modular production code that delivers the requested feature or bug fix and satisfies all functional, edge-case, and security assertions from Phase B while adhering to defensive design principles and project conventions in `CONTEXT.md`.

## Three Defensive Pillars
1. **Simple Input Validation**:
   - Enforce type, size, and strict allow-list validation on all incoming data.
   - Prefer structured parsing libraries (`pydantic`, `urllib.parse`) over complex regex which may be vulnerable to ReDoS.
2. **Explicit Authorization**:
   - Validate caller identity and match required permissions before invoking business logic.
3. **Least Privilege & Safe Operations**:
   - Parameterize all SQL/database queries.
   - Use canonical path checks (`os.path.realpath`) with prefix boundary validation.
   - Return only the minimal data payload required by the client.
   - Mask credentials, PII, and omit internal stack traces in error messages.

## Execution Sequence
1. **Inspect Failing Tests & Rules**: Review the functional requirements, failing tests from Phase B, and conventions in `CONTEXT.md`.
2. **Author Clean Production Code**:
   - Implement the business logic and algorithms required to satisfy the functional feature requirements.
   - Apply defensive patterns (e.g. `utils.security.resolve_safe_path`, parameterized SQL statements, `pydantic` schemas).
3. **Confirm GREEN State**:
   - Run the project test suite.
   - Verify that all functional and security tests pass cleanly without errors.
4. **Multi-Finding Handling**:
   - When remediating multiple scanner findings, apply the minimal fix for the current failing boundary test, confirm GREEN, then proceed to the next finding's test-fix cycle.

4. local-refactor-scanner (fase D)

.agents/skills/local-refactor-scanner/SKILL.md:

---
name: local-refactor-scanner
description: Refactors code for quality and maintainability, executes full test suite regression passes, and runs local deterministic security and lint scans in Phase D REFACTOR. Use when cleaning up code structure and eliminating duplication after tests pass, running local linters and fast offline scanners for secrets or dependencies, executing full regression test suites, and performing guided code reviews. Do not use for implementing initial feature logic, writing failing test-first suites, or modifying architectural threat models.
---

# Code Refactoring, Quality & Local Scanner Skill (Phase D: REFACTOR Phase)

## Overview
Refactor implementation for clean code structure, modularity, and maintainability while ensuring 100% passing test regressions and blocking pattern-based security flaws locally prior to commit.

## Verification Guardrails
1. **Code Quality & Refactoring**:
   - Clean up boilerplate, eliminate dead code, and centralize common utilities.
   - Improve variable naming, modularity, and type annotations without altering verified behavior.
2. **Deterministic Scans (Fast & Offline)**:
   - **Secrets**: Check diffs for plaintext credentials, tokens, or private keys.
   - **Dependencies**: Flag unpinned dependencies or known CVEs in new packages.
   - **Rules-Based SAST**: Run local SAST rules on modified files (`semgrep scan --config auto --json` or `cm find`).
3. **Guided AI Review**:
   - Audit architecture and design issues that static tools miss.
   - Review business logic and edge cases for bypasses or regression risks.
4. **Small Diffs & Regression QA**:
   - Run the complete project test suite to verify zero regressions across existing and new tests.
   - Ensure the diff contains only surgical changes directly related to the task scope.

## Execution Sequence
1. Review the git diff of modified files (`git diff`).
2. Refactor code for clarity, maintainability, and helper reuse.
3. Run local linters and security scanners on changed files.
4. Run the full test suite to guarantee 100% passing tests.
5. **Continuous Evolution**: Capture new conventions in `CONTEXT.md` and suggest/apply updates to `SKILL.md` instructions via `skill-evolution-updater` to permanently prevent recurrence of issues.

5. skill-evolution-updater (Evolución continua)

.agents/skills/skill-evolution-updater/SKILL.md:

---
name: skill-evolution-updater
description: Extracts systemic conventions from resolved bugs, patterns, and refactors to update CONTEXT.md and agent skills for continuous evolution. Use when capturing durable coding rules, architectural conventions, or recurring fix patterns into CONTEXT.md after a task or bug fix, updating skill instructions to prevent recurrence of errors, and logging gate findings to findings-log.ndjson. Do not use for writing feature code, authoring unit tests, or running pre-push scanner pipelines.
---

# Skill & Conventions Evolution Updater (Continuous Evolution)

## Overview
Ensure the development team and agent fleet continuously learn from local fixes, architecture decisions, and refactoring patterns so that systemic quality and security standards are retained permanently.

## Continuous Feedback Mechanism
```
+-----------------------------------------------------------------+
|                    CONTINUOUS FEEDBACK LOOP                     |
|                                                                 |
|   1. Local Fix / Feature Verified (Refactor Phase)              |
|                               v                                 |
|   2. Systemic Lesson Extracted (Best practices & conventions)   |
|                               v                                 |
|   3. Feed Back to Shared Specs (Update SKILL.md/CONTEXT.md)     |
|                               v                                 |
|   4. Context Seeding (All future agents inherit rules upfront)  |
+-----------------------------------------------------------------+
```

## Execution Sequence
1. **Analyze Remediation Diff**: Review the code change or bug fix just completed.
2. **Extract the Systemic Rule**:
   - Formulate an actionable, project-specific rule.
   - Example: *"When implementing redirects, always use `utils.security.safe_redirect()` with allow-listed domains."*
   - Example: *"All JSON endpoints must validate request body using Pydantic schemas."*
3. **Update Shared Specifications**:
   - **Update `CONTEXT.md`**: Append the rule under `## 4. Continuous Evolution: Auto-Evolved Conventions`.
   - **Update Skills (if applicable)**: If a general coding anti-pattern or QA procedure was refined, update the relevant `SKILL.md`.
4. **Persist Insight**: Append the raw structured event to `.security-gate/findings-log.ndjson` for audit traceability.

6. history-context-seeder (Onboarding)

.agents/skills/history-context-seeder/SKILL.md:

---
name: history-context-seeder
description: Analyzes repository Git history for past bug fixes, architectural conventions, and security patterns to seed CONTEXT.md on onboarding. Use when first adopting the framework in an existing repository, mining historical commits and bug fixes for recurring risk areas, or populating the initial CONTEXT.md baseline with established conventions and helpers. Do not use for routine feature development, authoring test suites, or running the inner TDD loop on active tasks.
---

# History & Architectural Context Seeder Skill (Repository Onboarding)

## Overview
Analyzes the repository's Git history and past fix commits to extract recurring bug patterns, architectural conventions, and security patterns, seeding `CONTEXT.md` during initial repository onboarding.

## Execution Sequence
1. **Analyze Git Log**:
   - Inspect commits touching bug fixes, refactors, and sensitive modules:
     `git log --grep="fix\|bug\|refactor\|vuln\|security\|patch" -n 50 --oneline`
2. **Extract Historical Lessons**:
   - Identify which files and modules have historically been prone to bugs or regressions.
   - Extract past patterns and architectural conventions established by maintainers.
3. **Seed `CONTEXT.md`**:
   - Populate `CONTEXT.md` with known architectural risk areas, sensitive directories, approved helpers, and custom project conventions.

No usarás esta habilidad en los labs porque CONTEXT.md ya existe, pero es la que debes usar cuando lleves el framework a un repositorio que tenga años de historial y no tenga convenciones escritas.

6. Configura el hook de Antigravity

.agents/hooks.json le indica a Antigravity que ejecute la barrera de seguridad antes de cualquier comando de terminal que ejecute el agente:

{
  "security-gate": {
    "PreToolUse": [
      {
        "matcher": "run_command|.*:run_command|run_shell_command|Bash",
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'if [ -x ./security_gate_hook.sh ]; then exec ./security_gate_hook.sh; else exec ./.agents/security_gate_hook.sh; fi'",
            "timeout": 120
          }
        ]
      }
    ]
  }
}

Algunos detalles sobre este archivo explican el diseño de la secuencia de comandos que inicia:

  • matcher es una regex sobre los nombres de las herramientas, no el texto del comando. PreToolUse se activa antes de que se ejecute una herramienta, y el comparador decide qué herramientas. run_command es la herramienta de terminal de Antigravity; las otras alternativas abarcan variantes con espacio de nombres de complementos y otras plataformas de agentes que comparten estos archivos. Un comparador como git push* nunca se activaría porque ninguna herramienta tiene ese nombre. El filtrado del comando real se produce dentro de la secuencia de comandos.
  • El hook recibe la llamada a la herramienta en stdin. Antigravity canaliza una carga útil JSON, como {"toolCall": {"name": "run_command", "args": {"CommandLine": "git push origin main"}}, ...}. La secuencia de comandos lee .toolCall.args.CommandLine y sale de inmediato con una decisión de permiso para todo lo que no sea un git push.
  • El directorio de trabajo es el directorio que contiene hooks.json, por lo que el hook se inicia dentro de .agents/. El wrapper bash -c 'if [ -x ./security_gate_hook.sh ] ...' controla ese caso y el inicio desde la raíz del repositorio. Luego, la secuencia de comandos cambia el directorio (cd) a git rev-parse --show-toplevel antes de realizar cualquier trabajo.
  • La secuencia de comandos responde en stdout con JSON. {"decision": "allow"} permite que se ejecute el comando original. {"decision": "deny", "reason": "..."} lo bloquea y le muestra el motivo al agente. El framework también emite un booleano allow_tool para brindar compatibilidad con contratos de hook más antiguos.
  • Los hooks se ejecutan de forma síncrona y bloquean el bucle del agente hasta que finalizan o alcanzan el timeout (en segundos; el valor predeterminado es 30 si se omite).

El formato -i.bak funciona con GNU y BSD (macOS) sed:

sed -i.bak 's/"timeout": 120/"timeout": 900/' .agents/hooks.json && rm .agents/hooks.json.bak

7. Cómo funciona el gancho de la puerta de seguridad

security_gate_hook.sh es un punto de entrada delgado que obtiene tres módulos de .agents/lib/:

Módulo

Rol

gate_common.sh

Configuración predeterminada, salida de allow/deny, clasificación de gravedad, registro de auditoría de NDJSON, recuento de intentos, confirmación y ayudantes de CONTEXT.md.

engine_semgrep.sh

Etapa 1. Análisis determinístico opcional con Semgrep. Se omite si semgrep no está en PATH.

engine_codemender.sh

Etapa 2. Análisis semántico con cm find, clasificación, seguimiento de intentos y derivación a cm verify.

Paso 1: Decide si se trata de una notificación push

El punto de entrada extrae el comando de la carga útil de stdin y lo prueba con una regex que reconoce git push en sus formas comunes (git -C /repo push, cd x && git push, sudo git push) mientras ignora el texto entre comillas, como git commit -m "before git push". Todo lo que no sea un envío se permite de inmediato:

CMD_TO_CHECK=$(printf '%s\n' "$STDIN_INPUT" | jq -r '
  .toolCall?.args?.CommandLine? //
  .toolCall?.args?.command? //
  .tool_input?.command? //
  .CommandLine? //
  .command? //
  empty
')
...
if ! is_git_push_command "$CMD_TO_CHECK"; then
  allow
fi

Paso 2: Elige los escáneres

SECURITY_GATE_SCANNER selecciona la canalización. El valor predeterminado, auto, ejecuta Semgrep y CodeMender, en ese orden:

case "$SCANNER" in
  codemender|cm) run_codemender_gate false ;;
  semgrep)       run_semgrep_gate false ;;
  auto|pipeline|"")
    command -v semgrep >/dev/null && run_semgrep_gate true
    command -v cm      >/dev/null && run_codemender_gate true
    allow ;;
esac

Cuando la etapa 1 encuentra problemas de bloqueo en el modo de canalización, no los rechaza por sí sola, sino que los escribe en un archivo temporal que recoge la etapa 2, de modo que CodeMender tiene la última palabra.

Paso 3: La etapa de CodeMender

run_codemender_gate en engine_codemender.sh hace lo siguiente, en orden:

  1. Busca los archivos modificados con git diff --name-only origin/main (recurre a HEAD~1). Si no hay cambios, se permite.
  2. Analiza cada archivo con cm find "$file" -y --bypass-warning y, luego, extrae todo con cm report --format json. Si cm report falla o devuelve un JSON no válido, se trata de un error de análisis, no de un resultado limpio.
  3. Filtra los hallazgos cuyo estado sea OPEN o REOPENED y cuya file_path termine con uno de los archivos modificados. Se ignoran los hallazgos que ya corregiste o descartaste en Conceptos básicos de la CLI de CodeMender.
  4. Clasifica cada hallazgo. La gravedad igual o superior a SECURITY_GATE_BLOCK_SEVERITY (HIGH predeterminada) es de bloqueo; cualquier valor inferior es de aviso, se registra y se imprime, pero no detiene el envío.
  5. Permitir si no hay bloqueos. Si un hallazgo que bloqueó un envío anterior ya no está presente, la puerta de enlace lo registra como FIXED, agrega una convención a CONTEXT.md en ## 4. Continuous Evolution y confirma ese cambio.
  6. Cuenta los intentos por hallazgo de bloqueo leyendo su propio registro de auditoría. Cada denegación es un intento. En los intentos del 1 al SECURITY_GATE_MAX_RETRIES (el valor predeterminado es 3), la puerta de enlace registra DENIED_TO_AGENT y agrega el hallazgo a un mensaje de rechazo.
  7. Deriva el caso después de que se agote el presupuesto. En el cuarto intento para el mismo hallazgo, la puerta de enlace ejecuta cm verify. Si el hallazgo no se puede explotar (código de salida 1 o estado DISMISSED), se cambia a aviso. Si se confirma o si cm verify falla, la puerta de enlace registra BLOCKED y rechaza con una solicitud de revisión manual.
  8. Rechaza con instrucciones. Si queda algún hallazgo que requiera acción, la puerta de enlace devuelve este motivo al agente:
Security Gate blocked push (1 unresolved finding(s)).

Action Required: Execute the Secure TDD Loop sequentially for each finding:
For each finding below (one at a time):
  1. Invoke 'security-test-writer' to author one failing boundary test in tests/ (assert RED).
  2. Invoke 'defensive-developer' to apply the minimal defensive fix (assert GREEN).
  3. Run the local test to confirm it passes before moving to the next finding.
Once all findings are resolved, run the full regression test suite (python3 -m unittest discover -s tests) and retry 'git push'.

Open Findings:
- [80bdddd6-...] (CRITICAL) in /home/you/codemender-lab/sample_app/data_service.py (Attempt 1/3): OS Command Injection in ping_host endpoint

Este es el traspaso entre el gancho y las habilidades. El hook no llama a cm fix. Nombra las habilidades que debe usar el agente, este realiza la corrección de la prueba primero y el siguiente git push vuelve a ejecutar la puerta.

Referencia de la configuración

Todos los parámetros de configuración son variables de entorno con valores predeterminados establecidos en gate_common.sh:

Variable

Predeterminado

Efecto

SECURITY_GATE_SCANNER

auto

auto, codemender (o cm) o semgrep.

SECURITY_GATE_BLOCK_SEVERITY

HIGH

Es la gravedad más baja que bloquea. CRITICAL, HIGH, MEDIUM o LOW

SECURITY_GATE_MAX_RETRIES

3

Rechazos por hallazgo antes de que se consulte a cm verify.

SECURITY_GATE_ALLOW_ON_ERROR

false

true permite que se realice una confirmación cuando un escáner no se ejecuta, lo que etiqueta la confirmación como unverified-scan-.

SECURITY_GATE_TEST_CMD

python3 -m unittest discover -s tests

Comando de prueba citado en los mensajes de rechazo y de confirmación.

SECURITY_GATE_EVOLVE_CONTEXT

true

Agrega convenciones verificadas a CONTEXT.md.

SECURITY_GATE_LOG

.security-gate/findings-log.ndjson

Registro de auditoría de solo anexión.

SECURITY_GATE_NOTIFY_CMD

(vacío)

Es un comando opcional que recibe cada evento de puerta de enlace como JSON en stdin.

8. Verifica el hook sin conexión

Antes de que la puerta de enlace toque el cm real, confirma que se comporte correctamente con simulaciones. El framework incluye un agente de pruebas con objetos binarios cm y semgrep falsos que abarcan las rutas de acceso de permiso, aviso, denegación, error y derivación:

bash .agents/tests/run_tests.sh

La ejecución tarda unos segundos y finaliza con lo siguiente:

-- test_pipeline_tools_missing_passes_smoothly
-- test_skills_frontmatter_valid
60 passed, 0 failed

La última prueba también valida los metadatos iniciales de cada habilidad en .agents/skills/, por lo que este es el comando que se debe volver a ejecutar después de editar un SKILL.md.

A continuación, simula lo que Antigravity envía para un comando que no es un envío. La secuencia de comandos debería responder allow sin tocar ningún escáner:

echo '{"toolCall":{"name":"run_command","args":{"CommandLine":"git status"}}}' \
  | bash .agents/security_gate_hook.sh
{"allow_tool": true, "decision": "allow"}

Ahora, simula un envío sin cambios locales en origin/main. Como aún no hay un repositorio remoto, la puerta de enlace recurre a HEAD~1 y analiza los archivos de tu última confirmación. Para mantener este paso sin conexión, apúntalo a los objetos simulados cm y semgrep:

echo '{"toolCall":{"name":"run_command","args":{"CommandLine":"git push origin main"}}}' \
  | PATH="$PWD/.agents/tests/mocks:$PATH" bash .agents/security_gate_hook.sh
Stage 1: Running Deterministic AST Scan (semgrep) on: sample_app/data_service.py ...
Deterministic scan clean. No AST vulnerabilities found.
Stage 2: Running Semantic Analysis & Verification (CodeMender)...
No blocking vulnerabilities detected. Code verified clean.
{"allow_tool": true, "decision": "allow"}

Ambas etapas se ejecutaron porque el directorio de simulación contiene un semgrep falso y un cm falso. Los mensajes de progreso van a stderr y solo la decisión de JSON va a stdout, que es lo que permite que Antigravity analice el resultado.

Por último, confirma los archivos del framework para que se incluyan en el repositorio:

git add -A && git commit -m "Add Secure TDD skills, rule, and security gate hook"

9. Abre el espacio de trabajo en Antigravity

Abre ~/codemender-lab como una carpeta en Antigravity. Una vez cargado, el agente tiene lo siguiente:

  • La regla secure_tdd_workflow en cada turno.
  • Las seis habilidades disponibles on demand.
  • El hook security-gate registrado en run_command.

Una forma rápida de confirmar que las habilidades están visibles es preguntarle al agente, en una conversación nueva, "¿Qué habilidades de Workspace tienes disponibles y qué hace cada una?" Debería enumerar los seis por nombre.

Permisos

Antigravity, no el agente, inicia el hook, por lo que no pasa por las solicitudes de permiso de la herramienta. Los comandos propios del agente sí lo hacen. Durante el próximo codelab, espera mensajes de aprobación para el comando de prueba, las operaciones de git y cualquier comando de cm que el agente decida ejecutar directamente. Aprobarlas cuando se te solicite; si Antigravity ofrece recordar la decisión para un prefijo de comando, aceptar eso evita que se vuelva a solicitar en todo el bucle.

Qué sucede en git push

  1. El agente llama a su herramienta de terminal con git push origin main.
  2. Antigravity compara run_command con hooks.json y ejecuta security_gate_hook.sh con la llamada a la herramienta en stdin.
  3. La secuencia de comandos reconoce un envío, busca los archivos modificados, los analiza con cm find y lee cm report.
  4. Si no hay bloqueos, se imprime {"decision": "allow"} y la confirmación continúa.
  5. Si se bloquean los hallazgos, se imprime {"decision": "deny", "reason": "..."}. La confirmación no se ejecuta, el agente ve el motivo y la regla siempre activa, junto con las habilidades nombradas, le indican qué hacer a continuación: una prueba fallida, una corrección mínima, volver a ejecutar el conjunto de pruebas y volver a confirmar.

¡Felicitaciones! Completaste el codelab de habilidades y hooks de CodeMender para Antigravity. En el próximo codelab, le darás al agente una solicitud de función y verás cómo se ejecuta este bucle de principio a fin, desde el modelo de amenazas hasta un envío que pasa la puerta de enlace.