GT-615: the revision ledger answers a drift question instead of only storing one - #79
Merged
Merged
Conversation
…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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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_revisionis a column ofcore_evaluation_transactions, written on every Core evaluation, and the HTTP surface was exactlyGET /+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_atwithidas tie-break for a total order.What changed
RepositoryRevisionTimeline(domain): verdict projection + drift detection. Pending/failed transactions project a verdict but areDecided=falseand 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 flaggedSameRevision: that is rule drift, not code drift.GetRevisionTimelineAsync(tenantId, repositoryUrl?, sinceUtc?)with EF + InMemory implementations.GET /core-evaluation-transactions?repositoryUrl=&since=(unfiltered response byte-identical to before) andGET /core-evaluation-transactions/revisionsreturning{revisions[], driftSignals[]}, gated by the previously deadtracker: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:
CS0234 … 'GetRepositoryRevisionTimeline' does not exist,dotnet testexit 1.OrderByDescending,DetectDriftreturning 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
(tenant_id, repository_url, requested_at)index is the natural follow-up; a migration plus aTrackerDbContextModelSnapshotedit is the most collision-prone change possible while sibling branches await integration. Flagged, not shipped.T-012should then be restated for .NET: it names aDriftDetectedEventin alibs/shared/TypeScript path that does not exist in this repo, so T-012 is stale rather than implemented.WebApplicationFactorytests self-skip without a live PostgreSQL, so an endpoint test would have been a green that proves nothing.🤖 Generated with Claude Code