feat(pilot): frontend fix-outcome types + patchOutcome API

Extends SessionSuggestedFix with outcome fields (status, applied_at,
verified_at, partial_notes, failure_reason, ai_outcome_proposal) and
adds a patchOutcome method hitting the new backend endpoint.

FixStatus (5 values) + FixOutcome (4 writable values) mirror the
backend Pydantic types and the DB check constraint.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-23 15:20:16 -04:00
parent 2cde6673b0
commit cdd29b460e

View File

@@ -8,6 +8,25 @@ import apiClient from './client'
export type UserDecision = 'one_off' | 'draft_template' | 'build_template' | 'dismissed'
export type FixStatus =
| 'proposed'
| 'applied_success'
| 'applied_failed'
| 'applied_partial'
| 'dismissed'
export type FixOutcome =
| 'applied_success'
| 'applied_failed'
| 'applied_partial'
| 'dismissed'
export interface AIOutcomeProposal {
fix_id: string
outcome: 'success' | 'failure' | 'partial'
reason: string
}
export interface SessionSuggestedFix {
id: string
session_id: string
@@ -18,6 +37,12 @@ export interface SessionSuggestedFix {
ai_drafted_script: string | null
ai_drafted_parameters: Record<string, unknown> | null
user_decision: UserDecision | null
status: FixStatus
applied_at: string | null
verified_at: string | null
partial_notes: string | null
failure_reason: string | null
ai_outcome_proposal: AIOutcomeProposal | null
superseded_at: string | null
created_at: string
}
@@ -86,6 +111,27 @@ export const sessionSuggestedFixesApi = {
return r.data
},
/**
* Record the outcome of applying a suggested fix. Transition rules:
* - from `proposed` or `applied_partial`: any outcome is valid (partial is
* parked, not terminal — engineer may update notes, abandon via dismiss,
* or advance to success/failed).
* - from a terminal status (`applied_success`, `applied_failed`, `dismissed`):
* server returns 409.
*/
async patchOutcome(
sessionId: string,
fixId: string,
outcome: FixOutcome,
notes?: string,
): Promise<SessionSuggestedFix> {
const r = await apiClient.patch<SessionSuggestedFix>(
`/ai-sessions/${sessionId}/suggested-fixes/${fixId}/outcome`,
{ outcome, notes },
)
return r.data
},
/**
* Fetch (or get cached) draft markdown for the Resolve note. Backend cache
* is keyed on state_version, so calling this back-to-back without intervening