fix: enforce active clarification lifecycle (#2669)

This commit is contained in:
José Almeida
2026-08-17 11:14:12 +00:00
committed by GitHub
parent f2014b2a90
commit 7e2c4ae84e
154 changed files with 21209 additions and 1928 deletions
@@ -200,8 +200,11 @@ type MessageRepository interface {
FindMessageByPendingID(ctx context.Context, pendingID string) (*models.Message, error)
FindMessagesByPendingID(ctx context.Context, pendingID string) ([]*models.Message, error)
FindMessageByPendingIDAndQuestion(ctx context.Context, sessionID, pendingID, questionID string) (*models.Message, error)
FindPendingClarificationMessagesBySessionID(ctx context.Context, sessionID string) ([]*models.Message, error)
FindActiveClarificationMessagesBySessionID(ctx context.Context, sessionID string) ([]*models.Message, error)
GetPendingActionsBySessionIDs(ctx context.Context, sessionIDs []string) (map[string]models.TaskPendingAction, error)
CompleteActiveClarificationBundle(ctx context.Context, pendingID, status string, responses map[string]interface{}) ([]*models.Message, bool, error)
FinalizeClarificationResponseDelivery(ctx context.Context, pendingID, terminalStatus string, claimedMessages []*models.Message) ([]*models.Message, bool, error)
RestoreActiveClarificationBundle(ctx context.Context, pendingID, terminalStatus string, claimedMessages []*models.Message) ([]*models.Message, bool, error)
UpdateMessage(ctx context.Context, message *models.Message) error
ListMessages(ctx context.Context, sessionID string) ([]*models.Message, error)
ListMessagesByTurnID(ctx context.Context, turnID string) ([]*models.Message, error)
@@ -228,6 +231,17 @@ type AttachmentRepository interface {
// TurnRepository handles conversation turn persistence.
type TurnRepository interface {
CreateTurn(ctx context.Context, turn *models.Turn) error
DeleteTurnIfUnreferenced(ctx context.Context, sessionID, turnID string) (bool, error)
// ReconcileUnpublishedPromptTurns repairs or accepts durable prompt
// reservations and response-delivery claims before startup admits new work.
// Accepted reservations retain a durable start-event outbox marker for the
// service to replay before it clears recovery metadata.
// Every production turn store must provide this recovery boundary; callers
// fail rather than skip it.
ReconcileUnpublishedPromptTurns(ctx context.Context) (int, error)
// ListTurnsPendingStartEvent returns accepted reservations whose durable
// start-event outbox marker still needs replay before startup admits work.
ListTurnsPendingStartEvent(ctx context.Context) ([]*models.Turn, error)
// CreateTurnWithStepStamp creates turn atomically with the
// workflow-step-at-start stamp: it reads the task's current step and
// inserts the turn row in the same transaction, taking the same lock
@@ -240,6 +254,29 @@ type TurnRepository interface {
GetTurn(ctx context.Context, id string) (*models.Turn, error)
GetActiveTurnBySessionID(ctx context.Context, sessionID string) (*models.Turn, error)
UpdateTurn(ctx context.Context, turn *models.Turn) error
// PatchTurnMetadata merges fields into an active or completed turn while
// preserving unrelated metadata under the session's turn-write authority.
PatchTurnMetadata(
ctx context.Context,
sessionID, turnID string,
updates map[string]interface{},
) (bool, time.Time, error)
// UpdateActiveTurnMetadata merges updates and removes named keys only while
// the turn is active and belongs to sessionID. Implementations serialize
// this authority change with other current-turn decisions for the session.
UpdateActiveTurnMetadata(
ctx context.Context,
sessionID, turnID string,
updates map[string]interface{},
removeKeys []string,
) (bool, map[string]interface{}, time.Time, error)
// ClearTurnPromptDispatchMetadata removes reservation-only metadata from
// an active or completed turn after its start event has been accepted by
// the event bus. It preserves unrelated concurrent metadata.
ClearTurnPromptDispatchMetadata(
ctx context.Context,
sessionID, turnID string,
) (bool, map[string]interface{}, time.Time, error)
CompleteTurn(ctx context.Context, id string) error
AbandonTurn(ctx context.Context, id string) error
CompletePendingToolCallsForTurn(ctx context.Context, turnID string) (int64, error)