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 (deos.environ.get("BIB_MCP_TOKEN")).repo_name: str— Etiqueta del repositorio (“CreaRack-Pro” o “CreaRackSL-workspace”, segúnrepo_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
- Solo código: Extiende
.py,.ts,.tsx,.js,.jsx,.mjs,.cjs,.astro,.vue,.html,.css,.scss,.sql. - 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).
- Archivos en
- 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]]