Skip to content

GT-615: the revision ledger answers a drift question instead of only storing one - #79

Merged
beyondnetPeru merged 1 commit into
developfrom
feat/gt-615-revision-query
Jul 31, 2026
Merged

GT-615: the revision ledger answers a drift question instead of only storing one#79
beyondnetPeru merged 1 commit into
developfrom
feat/gt-615-revision-query

Conversation

@beyondnetPeru

Copy link
Copy Markdown
Contributor

Closes GT-615 (P2, Tracker). The row was registered from an external product diagnostic and explicitly not verified against code — it was verified here first, and it holds.

Verified, with one correction

repository_revision is a column of core_evaluation_transactions, written on every Core evaluation, and the HTTP surface was exactly GET / + GET /{id:guid}. The corroborating detail: TrackerPermissions.DriftRead = "tracker:drift:read" was declared and required by zero routes — the substrate and even its permission existed, and nothing emitted a signal.

The correction: "ordered by revision" cannot mean ordering by the revision string — a git SHA has no intrinsic order. It is implemented as the revision timeline, chronological by requested_at with id as tie-break for a total order.

What changed

  • RepositoryRevisionTimeline (domain): verdict projection + drift detection. Pending/failed transactions project a verdict but are Decided=false and skipped by the drift walk — a Core outage is not an architectural verdict, and counting it would turn one transport incident into two false drift signals. Same-revision verdict changes are emitted but flagged SameRevision: that is rule drift, not code drift.
  • Port GetRevisionTimelineAsync(tenantId, repositoryUrl?, sinceUtc?) with EF + InMemory implementations.
  • GET /core-evaluation-transactions?repositoryUrl=&since= (unfiltered response byte-identical to before) and GET /core-evaluation-transactions/revisions returning {revisions[], driftSignals[]}, gated by the previously dead tracker:drift:read.

The drift signal is derived, not stored — no new table, no migration. The ledger stays the single system of record.

Evidence, including the negative half

The acceptance criterion requires a test that fails without the fix, so it was watched failing twice:

  1. Compile-level — new tests against unmodified production code: CS0234 … 'GetRepositoryRevisionTimeline' does not exist, dotnet test exit 1.
  2. Behavioural, because a compile error is weak evidence — the new surface kept, only the semantics reverted to pre-fix (no filters + OrderByDescending, DetectDrift returning empty): builds clean, 10 of 16 red on real assertions (Expected senales to contain 2 item(s) … but found 0).

Green after restoring: 16/16. Full suite 1035/1037 — the 2 reds are the same two DB-gated failures present in the baseline before any change (they need a local PostgreSQL). Independently re-run by the integrating session: 16/16.

Deliberately not shipped

  • No EF migration / index. A (tenant_id, repository_url, requested_at) index is the natural follow-up; a migration plus a TrackerDbContextModelSnapshot edit is the most collision-prone change possible while sibling branches await integration. Flagged, not shipped.
  • No ADR. None is needed as built — the signal is a derived read-model. One would be needed if this is later promoted to a published domain event, and T-012 should then be restated for .NET: it names a DriftDetectedEvent in a libs/shared/ TypeScript path that does not exist in this repo, so T-012 is stale rather than implemented.
  • No frontend, no HTTP-level test — the WebApplicationFactory tests self-skip without a live PostgreSQL, so an endpoint test would have been a green that proves nothing.

🤖 Generated with Claude Code

…e el ledger de evaluaciones

El ledger `core_evaluation_transactions` persistia `repository_revision` junto al
veredicto que el Core emitio para esa revision, pero solo se podia interrogar de
dos maneras: «todas las del tenant» (`GET /`) o «una por id» (`GET /{id}`). No
habia filtro por repositorio, ni corte temporal, ni orden de revision, ni lectura
alguna que comparase revisiones consecutivas. El sustrato para detectar deriva
existia y no emitia nada.

Lo que se anade:

- `ICoreEvaluationTransactionRepository.GetRevisionTimelineAsync(tenant, repositoryUrl?,
  sinceUtc?)`: filtros opcionales combinables y ORDEN DE REVISION (la mas antigua
  primero, desempatando por id para que la serie sea total). Es deliberadamente el
  inverso del listado del ledger, que responde a otra pregunta y no se toca.
- `RepositoryRevisionTimeline` (dominio, puro): proyeccion de veredicto por revision
  y deteccion de `DriftDetected` cuando el veredicto cambia entre revisiones
  consecutivas del MISMO repositorio. Las evaluaciones pendientes y las fallidas no
  cuentan como veredicto —una caida del Core no es una opinion sobre la
  arquitectura— pero tampoco cortan la serie.
- `GET /core-evaluation-transactions?repositoryUrl=&since=`: los dos filtros que
  faltaban. Sin ellos la respuesta es identica a la de siempre.
- `GET /core-evaluation-transactions/revisions?repositoryUrl=&since=`: la linea de
  revisiones con su proyeccion de veredicto y las senales derivadas. Exige
  `tracker:drift:read`, un permiso que llevaba declarado en el vocabulario sin que
  ninguna ruta lo pidiese.

La senal se CALCULA sobre el ledger, no se almacena: el asiento de evaluacion sigue
siendo el unico sistema de registro y una tabla paralela solo podria contradecirlo.

Rojo antes / verde despues: con el codigo de produccion previo las tres suites
nuevas ni compilan (`dotnet test` sale con 1); revirtiendo solo la SEMANTICA
—consulta sin filtros y en orden del ledger, `DetectDrift` devolviendo vacio— caen
10 de 16 con aserciones reales. Con el arreglo, 16/16 en verde y la suite completa
en 1035/1037 (los 2 rojos son los mismos de la linea base: exigen un PostgreSQL
local que aqui no hay).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@beyondnetPeru
beyondnetPeru merged commit 6871b17 into develop Jul 31, 2026
5 checks passed
@beyondnetPeru
beyondnetPeru deleted the feat/gt-615-revision-query branch August 1, 2026 11:50
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.

1 participant