@@ -55,7 +55,16 @@ function MetricCard(props: { label: string; value: string; tone?: "ok" | "warn"
5555 )
5656}
5757
58- export const OversightDashboard : Component = ( ) => {
58+ // Phase 2: OversightDashboard now accepts a selected subagent session ID so takeover/rollback
59+ // automatically target the chosen session, and trace nodes can reverse-select a subagent.
60+ export type OversightDashboardProps = {
61+ /** When provided, takeover and rollback default to this session ID. */
62+ selectedSessionID ?: string
63+ /** Called when a trace node with a sessionID is clicked so the caller can select that subagent. */
64+ onSessionSelect ?: ( sessionID : string ) => void
65+ }
66+
67+ export const OversightDashboard : Component < OversightDashboardProps > = ( props ) => {
5968 const sdk = useSDK ( )
6069 const language = useLanguage ( )
6170 const client = ( ) => sdk . client as unknown as OversightClient
@@ -118,7 +127,9 @@ export const OversightDashboard: Component = () => {
118127 if ( ! reason ) return
119128 setTakeoverBusy ( true )
120129 setTakeoverNote ( null )
121- const result = await recordHumanTakeover ( client ( ) , { reason } )
130+ // Phase 2: automatically pass the selected session ID when present.
131+ const sessionID = props . selectedSessionID
132+ const result = await recordHumanTakeover ( client ( ) , { reason, ...( sessionID ? { sessionID } : { } ) } )
122133 setTakeoverBusy ( false )
123134 if ( result . ok ) {
124135 setTakeoverReason ( "" )
@@ -133,21 +144,25 @@ export const OversightDashboard: Component = () => {
133144 }
134145
135146 // ── §D2 rollback (P4.4) ─────────────────────────────────────────────────────────
136- const [ rollbackSession , setRollbackSession ] = createSignal ( "" )
147+ // Phase 2: rollback input is pre-seeded with the selected session ID. Users may override it.
137148 const [ rollbackReason , setRollbackReason ] = createSignal ( "" )
138149 const [ rollbackBusy , setRollbackBusy ] = createSignal ( false )
139150 const [ rollbackNote , setRollbackNote ] = createSignal < string | null > ( null )
140151
152+ // The effective session ID for rollback: the input field overrides; falls back to selectedSessionID.
153+ const [ rollbackSessionOverride , setRollbackSessionOverride ] = createSignal ( "" )
154+ const effectiveRollbackSession = ( ) => rollbackSessionOverride ( ) || props . selectedSessionID || ""
155+
141156 const submitRollback = async ( ) => {
142- const sessionID = rollbackSession ( ) . trim ( )
157+ const sessionID = effectiveRollbackSession ( ) . trim ( )
143158 if ( ! sessionID ) return
144159 const reason = rollbackReason ( ) . trim ( )
145160 setRollbackBusy ( true )
146161 setRollbackNote ( null )
147162 const result = await recordRollback ( client ( ) , { sessionID, ...( reason ? { reason } : { } ) } )
148163 setRollbackBusy ( false )
149164 if ( result . ok ) {
150- setRollbackSession ( "" )
165+ setRollbackSessionOverride ( "" )
151166 setRollbackReason ( "" )
152167 setRollbackNote (
153168 result . record ?. outcome === "noop"
@@ -328,6 +343,17 @@ export const OversightDashboard: Component = () => {
328343 </ div >
329344 </ Show >
330345 < div class = "text-11-regular text-text-weaker" > { fmtTime ( node . createdAt ) } </ div >
346+ { /* Phase 2: if this node is tied to a specific subagent session, offer
347+ a reverse-select link so the user can jump to that subagent row. */ }
348+ < Show when = { node . sessionID && props . onSessionSelect } >
349+ < button
350+ type = "button"
351+ class = "mt-0.5 text-11-regular text-text-link hover:underline"
352+ onClick = { ( ) => props . onSessionSelect ! ( node . sessionID ! ) }
353+ >
354+ { language . t ( "oversight.trace.selectAgent" ) }
355+ </ button >
356+ </ Show >
331357 </ div >
332358 </ div >
333359 ) }
@@ -372,11 +398,13 @@ export const OversightDashboard: Component = () => {
372398 < section >
373399 < h3 class = "mb-1 text-13-medium text-text-strong" > { language . t ( "oversight.rollback.title" ) } </ h3 >
374400 < p class = "mb-2 text-11-regular text-text-weak" > { language . t ( "oversight.rollback.description" ) } </ p >
401+ { /* Phase 2: when a subagent is selected the placeholder is replaced by the session ID.
402+ Typing in this field overrides the pre-selected session. */ }
375403 < input
376404 class = "w-full rounded-md border border-border-weak-base bg-surface-base px-2 py-1.5 text-12-regular text-text-strong outline-none focus:ring-2 focus:ring-accent-base font-mono"
377- placeholder = { language . t ( "oversight.rollback.sessionPlaceholder" ) }
378- value = { rollbackSession ( ) }
379- onInput = { ( e ) => setRollbackSession ( e . currentTarget . value ) }
405+ placeholder = { props . selectedSessionID || language . t ( "oversight.rollback.sessionPlaceholder" ) }
406+ value = { rollbackSessionOverride ( ) }
407+ onInput = { ( e ) => setRollbackSessionOverride ( e . currentTarget . value ) }
380408 />
381409 < textarea
382410 class = "mt-2 w-full rounded-md border border-border-weak-base bg-surface-base px-2 py-1.5 text-12-regular text-text-strong outline-none resize-none focus:ring-2 focus:ring-accent-base"
@@ -391,7 +419,7 @@ export const OversightDashboard: Component = () => {
391419 size = "small"
392420 icon = "reset"
393421 onClick = { submitRollback }
394- disabled = { rollbackBusy ( ) || ! rollbackSession ( ) . trim ( ) }
422+ disabled = { rollbackBusy ( ) || ! effectiveRollbackSession ( ) . trim ( ) }
395423 >
396424 < Show when = { rollbackBusy ( ) } >
397425 < Spinner />
0 commit comments