Skip to content

charter drift sale con exit 0 cuando no puede comprobar nada: el hook de pre-push pasó en verde durante todo un Charter #424

Description

@montfort

Qué pasó

Durante una cadena de charters en un proyecto adoptante (ri-ceiba, CLI 3.48.0), un script de edición mío borró por accidente el encabezado ## Archivos a modificar de un Charter in-progress, dejando la tabla huérfana en el cuerpo.

straymark charter drift lo detectó correctamente y avisó:

WARN: no files extracted from §Files to modify in .straymark/charters/33-....md
  Either the section is missing, the table format is unusual, or the
  declared paths don't have recognized extensions. Script can't help — exit clean.

Y salió con código 0.

$ straymark charter drift CHARTER-33 --range main...HEAD >/dev/null 2>&1
$ echo $?
0

El parser no tiene ningún fallo. Leí core/src/charter_files.rs::parse_files_to_modify y hace exactamente lo correcto: el encabezado no estaba, así que no había nada que extraer. El problema es qué ocurre después.

Por qué importa

El Charter estuvo así diez commits, y no lo noté. .githooks/pre-push invoca straymark-pre-pr.sh, que corre el drift check sobre los Charters in-progress; como sale con 0, el hook pasó en verde en cada push.

O sea: el mecanismo que existe para detectar que lo ejecutado se apartó de lo declarado estuvo apagado durante todo un Charter, y su forma de decírmelo fue idéntica a la de decirme que todo iba bien — un mensaje en stderr que se pierde entre la salida de un hook que también compila y corre 3 900 tests.

Lo descubrí por casualidad, al preparar el PR y ver que el conteo de «Declared» no aparecía.

La asimetría

El comando ya distingue dos situaciones y las trata igual:

Situación Significado Hoy
declared.is_empty() No pude comprobar WARN, exit 0
modified.is_empty() El Charter no se ejecutó WARN, exit 0
Deriva detectada Comprobé y hay problema Reporte, exit ≠ 0

«No pude comprobar» se comporta como «comprobé y está bien». Para una herramienta cuyo propósito es que los artefactos de gobernanza no deriven en silencio, es justo el modo de fallo que busca prevenir — el mismo argumento del #419, aplicado al comprobador en vez de al artefacto.

Lo que sugeriría

No tengo preferencia fuerte entre estas, y quizá haya mejores:

  1. Salir ≠ 0 cuando la sección falta y el Charter está in-progress. Es cuando el drift check debería estar vigilando de verdad. Un Charter declared sin sección es legítimo (aún no hay reconocimiento hecho); uno in-progress sin ella es una sección perdida.
  2. Una bandera --strict que convierta los WARN en error, para que los hooks puedan optar. Menos intrusivo, pero deja el valor por omisión inseguro y los adoptantes que más lo necesitan son los que no saben que existe.
  3. Distinguir los dos casos en el mensaje: «la sección no existe» (probablemente un error) frente a «existe y no extraje rutas» (probablemente formato). Ayuda al diagnóstico aunque el código de salida no cambie.

La (1) me parece la que más se acerca al espíritu del framework, pero rompería builds de adoptantes con Charters mal formados — que es exactamente lo que se quiere, aunque conviene decidirlo a conciencia.

Nota sobre el diagnóstico

Mi primera hipótesis fue que el parser se detenía ante texto suelto entre el encabezado y la tabla, y estuve a punto de reportarlo así. Leer parse_files_to_modify la descartó: recorre hasta el siguiente ## sin detenerse en párrafos. Lo menciono porque el mensaje actual lista tres causas posibles y la primera —«the section is missing»— era la correcta; con un código de salida distinto la habría mirado antes en vez de asumir la del formato.


Reportado desde ri-ceiba (CLI 3.48.0, fw 4.33). Con gusto pruebo un parche contra este repositorio, que tiene la cadena CHARTER-32→36 en curso.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions