feat(pilot): PATCH /suggested-fixes/:id/script endpoint
Called by the inline Script Builder tab on Submit. Writes ai_drafted_script + ai_drafted_parameters to the fix without stamping applied_at (a draft is not an application — that's §5 of the Phase 9 spec). Bumps state_version so Resolve/Escalate preview bundles regenerate. 409 on terminal fix status. 404 on wrong session. 422 on empty script. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -32,6 +32,7 @@ from app.schemas.session_suggested_fix import (
|
||||
SessionSuggestedFixDecisionResponse,
|
||||
SessionSuggestedFixOutcomeRequest,
|
||||
SessionSuggestedFixResponse,
|
||||
SessionSuggestedFixScriptRequest,
|
||||
)
|
||||
from app.models.draft_template import DraftTemplate
|
||||
from app.models.session_fact import SessionFact
|
||||
@@ -355,6 +356,60 @@ async def patch_suggested_fix_outcome(
|
||||
return SessionSuggestedFixResponse.model_validate(fix)
|
||||
|
||||
|
||||
# ── Suggested fix: attach drafted script ─────────────────────────────────────
|
||||
|
||||
@router.patch(
|
||||
"/suggested-fixes/{fix_id}/script",
|
||||
response_model=SessionSuggestedFixResponse,
|
||||
)
|
||||
async def patch_suggested_fix_script(
|
||||
session_id: UUID,
|
||||
fix_id: UUID,
|
||||
body: SessionSuggestedFixScriptRequest,
|
||||
current_user: Annotated[User, Depends(get_current_active_user)],
|
||||
db: Annotated[AsyncSession, Depends(get_db)],
|
||||
_: None = Depends(require_engineer_or_admin),
|
||||
) -> SessionSuggestedFixResponse:
|
||||
"""Attach an engineer-drafted script to a suggested fix.
|
||||
|
||||
Called by the inline Script Builder tab on Submit. Does NOT stamp
|
||||
applied_at — a draft is not an application. Bumps state_version so
|
||||
the Resolve/Escalate preview bundles regenerate.
|
||||
"""
|
||||
await _load_session_or_404(db, session_id)
|
||||
|
||||
fix = await db.scalar(
|
||||
select(SessionSuggestedFix).where(
|
||||
SessionSuggestedFix.id == fix_id,
|
||||
SessionSuggestedFix.session_id == session_id,
|
||||
)
|
||||
)
|
||||
if fix is None:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Suggested fix not found")
|
||||
|
||||
TERMINAL = {"applied_success", "applied_failed", "dismissed"}
|
||||
if fix.status in TERMINAL:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_409_CONFLICT,
|
||||
detail=f"Fix is already in terminal status {fix.status!r}",
|
||||
)
|
||||
|
||||
fix.ai_drafted_script = body.ai_drafted_script
|
||||
fix.ai_drafted_parameters = body.ai_drafted_parameters
|
||||
|
||||
# Bump state_version on the parent session — previews cached by
|
||||
# (session_id, state_version) must regenerate to reflect the new draft.
|
||||
await db.execute(
|
||||
update(AISession)
|
||||
.where(AISession.id == session_id)
|
||||
.values(state_version=AISession.state_version + 1)
|
||||
)
|
||||
|
||||
await db.commit()
|
||||
await db.refresh(fix)
|
||||
return SessionSuggestedFixResponse.model_validate(fix)
|
||||
|
||||
|
||||
# ── Suggested fix: clear AI outcome proposal ("Not yet") ─────────────────────
|
||||
|
||||
@router.delete(
|
||||
|
||||
Reference in New Issue
Block a user