feat(escalations): Escalation Mode wedge — live arrival + magic-moment pickup #155
@@ -97,7 +97,21 @@ export default function AssistantChatPage() {
|
||||
const [logContent, setLogContent] = useState('')
|
||||
const [pendingUploads, setPendingUploads] = useState<PendingUpload[]>([])
|
||||
const [isDragOver, setIsDragOver] = useState(false)
|
||||
// Task-lane mount restoration is gated on (a) the persisted chatId
|
||||
// matching whatever activeChatId resolved to, AND (b) the page not being
|
||||
// entered with a prefill in location.state. The prefill case means we're
|
||||
// about to create a brand-new session and discard the previous one's
|
||||
// task lane anyway — restoring it just causes the previous chat's
|
||||
// questions/actions to flash on the first paint before sendPrefill's
|
||||
// resetSessionDerivedState clears them. Same logic for the bell-icon
|
||||
// pickup flow (?pickup=true): the senior is entering an unrelated
|
||||
// session and any leftover task-lane meta from their own prior chat is
|
||||
// noise. Both gates collapse to "are we about to leave the previous
|
||||
// chat behind?" — if yes, start clean.
|
||||
const incomingPrefill = !!(location.state as { prefill?: string } | null)?.prefill
|
||||
const skipTaskLaneRestore = incomingPrefill || isPickup
|
||||
const [activeQuestions, setActiveQuestions] = useState<QuestionItem[]>(() => {
|
||||
if (skipTaskLaneRestore) return []
|
||||
try {
|
||||
const saved = sessionStorage.getItem('rf-tasklane-meta')
|
||||
if (saved) { const d = JSON.parse(saved); if (d.chatId === activeChatId) return d.questions || [] }
|
||||
@@ -105,6 +119,7 @@ export default function AssistantChatPage() {
|
||||
return []
|
||||
})
|
||||
const [activeActions, setActiveActions] = useState<ActionItem[]>(() => {
|
||||
if (skipTaskLaneRestore) return []
|
||||
try {
|
||||
const saved = sessionStorage.getItem('rf-tasklane-meta')
|
||||
if (saved) { const d = JSON.parse(saved); if (d.chatId === activeChatId) return d.actions || [] }
|
||||
@@ -112,6 +127,7 @@ export default function AssistantChatPage() {
|
||||
return []
|
||||
})
|
||||
const [showTaskLane, setShowTaskLane] = useState(() => {
|
||||
if (skipTaskLaneRestore) return false
|
||||
try {
|
||||
const saved = sessionStorage.getItem('rf-tasklane-meta')
|
||||
if (saved) { const d = JSON.parse(saved); return d.show === true && d.chatId === activeChatId }
|
||||
@@ -479,6 +495,16 @@ export default function AssistantChatPage() {
|
||||
// Phase 9: tab strip reset
|
||||
setChatTab('chat')
|
||||
setScriptBuilderHasProgress(false)
|
||||
// Belt-and-braces: also wipe the persisted task-lane meta. Without this,
|
||||
// a remount or page reload before the next AI response can re-hydrate
|
||||
// the previous session's questions/actions from sessionStorage even
|
||||
// though the in-memory state has been cleared. The persistence effect
|
||||
// re-saves on the next state change anyway, so the only window where
|
||||
// sessionStorage is empty is between this reset and the next response —
|
||||
// which is exactly the window where stale-tag leakage was happening.
|
||||
try {
|
||||
sessionStorage.removeItem('rf-tasklane-meta')
|
||||
} catch { /* ignore */ }
|
||||
}, [])
|
||||
|
||||
// Phase 2 facts — fetch + handlers. `refreshFacts` is called from selectChat
|
||||
|
||||
Reference in New Issue
Block a user