CreaRack-SL

record_cochanges — Handler de registro de co-cambios en el ingest

Descripción

Función nueva en .github/scripts/bib_ingest.py (líneas ~1597–1655) que registra, en cada merge a main, qué pares de archivos de código cambian juntos. Alimenta la tabla D1 bib_cochanges del Workspace vía el handler MCP bib_record_cochanges.

Firma

def record_cochanges(changed_files: list[str], mcp_token: str, repo_name: str) -> dict

Parámetros:

  • changed_files: list[str] — Lista de rutas de archivos tocados en el merge (suministrada por el contexto del ingest).
  • mcp_token: str — Bearer token del MCP Workspace (de os.environ.get("BIB_MCP_TOKEN")).
  • repo_name: str — Etiqueta del repositorio (“CreaRack-Pro” o “CreaRackSL-workspace”, según repo_name.lower()).

Retorno:

{
    "recorded_pairs": <int>,       # Número de pares registrados (>0 si éxito)
    "skipped": <str> | undefined,  # Motivo si se saltó (ej: "menos de 2 archivos de código")
    "error": <str> | undefined     # Mensaje de error si falló (str[:200])
}

Comportamiento

Filtrado de archivos

  1. Solo código: Extiende .py, .ts, .tsx, .js, .jsx, .mjs, .cjs, .astro, .vue, .html, .css, .scss, .sql.
  2. Excluye:
    • Archivos en src/content/wiki/ (documentación).
    • Scripts internos (.github/scripts/bib_*).
    • Harness: scripts/harness/.
    • Público de supercontext: public/supercontext/.
    • Especiales (alta rotación): config/settings/base.py (version bump cada release → ruido).
  3. Requisito: Mínimo 2 archivos de código tras filtrado. Si hay <2, retorna {"recorded_pairs": 0, "skipped": "menos de 2 archivos de código"}.

Invocación del MCP

Si se pasan los filtros:

raw = call_mcp(
    "bib_record_cochanges",
    {"files": code_paths, "repo": repo},
    mcp_token,
)
result = json.loads(raw) if raw else {}

El handler MCP vive en el Workspace (CreaRackSL/workspace repo) e incrementa los contadores en bib_cochanges para cada par (file_a, file_b) donde file_a < file_b.

Tolerancia a fallos

  • Si el MCP falla (RuntimeError): devuelve {"recorded_pairs": 0, "error": "<msg[:200]>"}.
  • Si responde JSON inválido: devuelve {"recorded_pairs": 0, "error": "unexpected_response"}.
  • Nunca rompe el ingest: esta función corre al margen del procesamiento LLM principal, y sus fallos no afectan el flujo.

Integración en el ingest

Se invoca en main() (líneas ~1700–1710), incondicional tras trigger_tripwires() y antes de decidir si procesar o saltar el commit (fase pre-LLM):

cochange_result = record_cochanges(changed_files, mcp_token, repo_name)
if cochange_result.get("recorded_pairs", 0) > 0:
    log(f"[Co-change] Registrados {cochange_result['recorded_pairs']} pares de co-cambio.")
elif cochange_result.get("error"):
    log(f"[Co-change] ERROR: {cochange_result['error']}")

Logs:

  • Info: [Co-change] Registrados N pares de co-cambio.
  • Error: [Co-change] ERROR: <reason>.

Esto significa que incluso si un commit es skipped por pre-LLM, su señal de co-cambio ya fue registrada (para enriquecer futuras queries de bib_impact_query).

Sincronización con bib_cochange_backfill.py

Las reglas de filtrado (extensiones, prefijos excluidos, MAX_FILES_PER_COMMIT=25, churn_denylist) deben coincidir exactamente con las del script de backfill. El comentario en el código marca: “mantener en sync”.

Fuentes

  • Función en código: .github/scripts/bib_ingest.py, líneas 1597–1655.
  • Main loop: .github/scripts/bib_ingest.py, líneas 1700–1710.
  • Docstring: Cairn cherry-pick #2 — registra qué archivos cambian JUNTOS en este merge.

Véase también

  • [[feature—biblioteca—cochange-git]]
  • [[runbook—biblioteca—bib-cochange-backfill]]
  • [[entity—supercontext—tool—bib-impact-query]]
  • [[concept—biblioteca—logical-coupling]]
  • [[concept—biblioteca—grafo-conocimiento]]