fix(pilot): applied_at stamps on run-declaring actions, not Apply click

Per Phase 9 §5. Before: banner Apply click stamped applied_at
regardless of whether the engineer had committed to running anything,
starting the Verifying timer prematurely. After:

- handleApplyFix no longer calls applyFix(). It just routes to the
  right surface (TemplateMatchPanel / InlineNoTemplateDialog / Script
  Builder tab).
- handleScriptDecision stamps applied_at for one_off + draft_template
  (both labels are 'Run now, …' — the click is the declaration).
  build_template does not stamp.
- TemplateMatchPanel's new 'I ran this' button calls applyFix via a
  new onMarkRun prop.
- Script Builder tab Submit does not stamp (a draft is not a run).

No backend change — the /apply endpoint is unchanged. Only call sites
move.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-24 04:11:56 -04:00
parent 0386fa1fd5
commit faf1d8dd12

View File

@@ -515,6 +515,17 @@ export default function AssistantChatPage() {
} else if (decision === 'draft_template') {
toast.success('Draft template queued — review after Resolve')
}
// Phase 9 §5: one_off and draft_template declare a run ("Run now, …").
// Stamp applied_at to transition the fix into Verifying.
// build_template does NOT run — no stamp.
if (decision === 'one_off' || decision === 'draft_template') {
try {
const updated = await sessionSuggestedFixesApi.applyFix(
activeChatId, activeFix.id,
)
setActiveFix(updated)
} catch { /* non-fatal: engineer can still mark outcome later */ }
}
// Keep the panel open so the engineer can copy the rendered script.
} catch {
toast.error('Failed to record decision')
@@ -552,6 +563,20 @@ export default function AssistantChatPage() {
setChatTab('script_builder')
}, [activeFix])
// Phase 9 Task 13: TemplateMatchPanel "I ran this" — stamps applied_at so the
// ProposalBanner transitions from Proposed to Verifying. Shared useCallback so
// both render sites (narrow-drawer + side-panel) are identical.
const handleMarkRun = useCallback(async () => {
if (!activeFix || !activeChatId) return
try {
const updated = await sessionSuggestedFixesApi.applyFix(
activeChatId, activeFix.id,
)
setActiveFix(updated)
setScriptPanelOpen(false)
} catch { /* non-fatal: engineer can still mark outcome later */ }
}, [activeFix, activeChatId])
// Phase 8: record a terminal outcome for the active fix. Updates local state
// on success. For applied_success also opens the Resolve preview.
const handleSetOutcome = useCallback(async (outcome: FixOutcome, notes?: string) => {
@@ -1697,6 +1722,7 @@ export default function AssistantChatPage() {
fix={activeFix}
sessionId={activeChatId}
onClose={() => setScriptPanelOpen(false)}
onMarkRun={handleMarkRun}
/>
)}
<div className="flex items-center gap-3 px-3 mt-1">
@@ -1767,6 +1793,7 @@ export default function AssistantChatPage() {
fix={activeFix}
sessionId={activeChatId}
onClose={() => setScriptPanelOpen(false)}
onMarkRun={handleMarkRun}
/>
)}
<div className="flex items-center gap-3 px-3 mt-1">