Files
AutopilotMonitor/src/Shared/AutopilotMonitor.Shared/DataAccess/IDecisionTransitionRepository.cs
T
Oliver Kieselbach eeaa0643a2 feat(backend): M5.a primary tables — Signals + DecisionTransitions repositories
Groundwork for the V2 ingest path (/api/agent/telemetry). Adds the two
primary Decision-Engine tables projected from the agent-side SignalLog
and Journal so the Inspector + Reducer-Verifier can replay sessions.

- Constants.TableNames: Signals, DecisionTransitions (+ All[] init).
- Shared DTOs SignalRecord / DecisionTransitionRecord carry a flat
  projection plus the agent-serialised PayloadJson for full fidelity.
  DecisionTransitionRecord eagerly carries index discriminators
  (IsTerminal, ClassifierVerdictId, ClassifierHypothesisLevel) so the
  later index fan-out can read them straight off the primary row.
- ISignalRepository / IDecisionTransitionRepository: lean interfaces
  (StoreBatchAsync only — queries land with the read endpoints in M5.c).
- TableSignalRepository / TableDecisionTransitionRepository: idempotent
  UpsertReplace via entity-group-transactions, grouped per (tenant,
  session), chunked at the 100-op Azure limit. PayloadJson goes through
  TableStorageChunking so the 32K-char property ceiling can't bite on
  large Evidence + Payload blobs.
- Registered in DataAccessServiceExtensions alongside the existing 13
  Table repositories — Cosmos swap remains a single-file change.
- 11 pure mapping tests cover key builders (PK tenant_session,
  RK D19(ordinal) / D10(stepIndex), lex-ordering invariant), full
  entity projection, chunked PayloadJson handling, dead-end paths,
  and null-payload tolerance.

Index tables (SessionsByTerminal, SessionsByStage, DeadEndsByReason,
ClassifierVerdictsByIdLevel, SignalsByKind) land with the queue-driven
fan-out in M5.b; the primary schemas are stable.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 09:19:08 +02:00

24 lines
950 B
C#

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using AutopilotMonitor.Shared.Models;
namespace AutopilotMonitor.Shared.DataAccess
{
/// <summary>
/// Repository for the <c>DecisionTransitions</c> primary table (Plan §M5). Writes projected
/// <see cref="DecisionTransitionRecord"/>s derived from agent Journal entries.
/// <para>
/// Writes are idempotent via <c>(PartitionKey, RowKey)</c>: a retried batch replays without
/// duplicating rows. Records within a single batch must share the same (TenantId, SessionId).
/// </para>
/// </summary>
public interface IDecisionTransitionRepository
{
/// <summary>
/// Upserts a batch of transition records. Returns the number of rows committed.
/// </summary>
Task<int> StoreBatchAsync(IReadOnlyList<DecisionTransitionRecord> records, CancellationToken cancellationToken = default);
}
}