Nest chat-UI orchestration workers under the agent that started them (#34601)

* Nest chat-UI orchestration workers under the agent that started them

Main's lineage projection only walked terminal panes, so workers running
in the chat UI never got a parent link and listed flat in the sidebar.
It now also projects chat workers, keyed by their visible chat row, and
resolves a chat creator or coordinator to that chat's visible row
instead of its handle or private mailbox pane key.

* Fix public worker lineage across assignment and row identities

* Complete terminal lineage provenance and bound active session selection

* Repair lineage test runtime boundaries and SQLite counters

* Batch public lineage verification after exact recency selection

* Use checked runtime values in lineage integration tests

* Document the trusted Dispatch SQL row boundary

* Keep lineage integration imports within their test programs

* Load native lineage fixtures before test execution

* test: complete lineage inputs in runtime and sidebar fixtures

* test: seed benchmark facts from active dispatches

* test: replace partial orchestration DB casts with typed fixtures

* test: complete stale-leaf mailbox fixture session input

* fix(test): render worker lineage fixture with production list
This commit is contained in:
Brennan Benson
2026-10-28 16:06:38 -07:00
committed by GitHub
parent 9dd4dc5d17
commit f0d55e7319
64 changed files with 3873 additions and 401 deletions
+1
View File
@@ -3,6 +3,7 @@ import original from '../mobile/vitest.config.ts'
// Keep real process, native, and runtime-specific contracts on Node.
const nodeFiles = [
'src/components/WorktreeAgentList.runtime-lineage.test.tsx',
'scripts/check-tests-typecheck-incremental-cache.test.ts',
'src/tasks/mobile-agent-launch-architecture.test.ts',
'src/tasks/agent-launch-mobile-replay.test.ts',
@@ -13,6 +13,10 @@ const ERROR_LINE = /^(\S.*?)\(\d+,\d+\): error TS\d+:/
// Require every on-disk test in program except these explicit exclusions: error-only diff cannot see excluded/shadowed tests.
export const TESTS_OUTSIDE_PROGRAM = new Map([
[
'src/components/WorktreeAgentList.runtime-lineage.test.tsx',
'Node-side: renders the mobile consumer of real desktop SQLite assignment projection, against Node rather than RN libs'
],
[
'src/session/mobile-native-command-discovery.test.tsx',
'Node-side: imports the desktop ACP command discovery source, checked against @types/node rather than RN libs'
@@ -0,0 +1,83 @@
import { createElement } from 'react'
import { act, create, type ReactTestRenderer } from 'react-test-renderer'
import { expect, it, vi } from 'vitest'
import type { RuntimeWorktreeAgentRow } from '../../../src/shared/runtime-types'
import { WorktreeAgentSummary } from './WorktreeAgentSummary'
import { WorktreeAgentList } from './WorktreeAgentList'
vi.mock('react-native', () => ({
Pressable: 'Pressable',
StyleSheet: { create: <T,>(styles: T) => styles },
Text: 'Text',
View: 'View'
}))
vi.mock('lucide-react-native', () => ({
ChevronDown: 'ChevronDown',
ChevronRight: 'ChevronRight'
}))
vi.mock('./AgentStateDot', () => ({ AgentStateDot: () => null }))
vi.mock('./MobileAgentIcon', () => ({ MobileAgentIcon: () => null }))
it('renders production-built canonical assignments as nested rows and groups only roots', async () => {
const clock = vi.spyOn(Date, 'now').mockReturnValue(1_800_000_000_000)
const { publicLineageFixture, canonicalChatRow, LINEAGE_PARENT, LINEAGE_CHILD } =
await import('../../../src/main/runtime/runtime-agent-lineage.test-fixture')
const { flattenAgentRowLineage } = await import('../worktree/agent-row-lineage')
const f = publicLineageFixture()
let tree: ReactTestRenderer | undefined
try {
const agents = f.build().agents
expect(flattenAgentRowLineage(agents).map((node) => [node.row.paneKey, node.depth])).toEqual([
[canonicalChatRow(LINEAGE_PARENT), 0],
[canonicalChatRow(LINEAGE_CHILD), 1]
])
await act(async () => {
tree = create(
createElement(WorktreeAgentList, {
agents,
now: 1_800_000_000_000,
unvisited: false,
statusLive: true
})
)
})
expect(
tree?.root
.findAll((node) => node.props.agent !== undefined)
.map((node) => [node.props.agent.paneKey, node.props.depth])
).toEqual([
[canonicalChatRow(LINEAGE_PARENT), 0],
[canonicalChatRow(LINEAGE_CHILD), 1]
])
expect(tree?.root.findAllByType(WorktreeAgentSummary)).toHaveLength(0)
expect(agents[1].taskTitle).toBe('Build the worker result')
expect(JSON.stringify(tree?.toJSON())).toContain('Coordinate work')
expect(JSON.stringify(tree?.toJSON())).toContain('Implement work')
expect(JSON.stringify(tree?.toJSON())).not.toContain('2 agents')
expect(JSON.stringify(tree?.toJSON())).not.toContain(f.privateHandle)
expect(JSON.stringify(tree?.toJSON())).not.toContain(f.privatePane)
const orphan = {
...agents[1],
paneKey: 'missing-parent-worker',
parentPaneKey: 'missing-parent'
}
await act(async () =>
tree?.update(
createElement(WorktreeAgentList, {
agents: [...agents, orphan],
now: 1_800_000_000_000,
unvisited: false
})
)
)
expect(
tree?.root
.findByType(WorktreeAgentSummary)
.props.agents.map((row: RuntimeWorktreeAgentRow) => row.paneKey)
).toEqual([canonicalChatRow(LINEAGE_PARENT), orphan.paneKey])
} finally {
await act(async () => tree?.unmount())
f.db.close()
clock.mockRestore()
}
})
+1
View File
@@ -10,6 +10,7 @@
// are React Native's, where `setTimeout` answers a number rather than a NodeJS.Timeout, so
// pulling that graph in reports ~280 errors about the desktop rather than about mobile. Their
// own runtime coverage is vitest, which runs them under Node.
"src/components/WorktreeAgentList.runtime-lineage.test.tsx",
"src/session/mobile-native-command-discovery.test.tsx",
"src/tasks/agent-launch-mobile-replay.test.ts",
"src/test-support/rpc-recording/recorded-request-params.test.ts",
@@ -1,4 +1,5 @@
import { describe, expect, it, vi } from 'vitest'
import { beforeAll, describe, expect, it, vi } from 'vitest'
import type * as ChildProcess from 'node:child_process'
const {
callMock,
@@ -35,16 +36,38 @@ vi.mock('./runtime/environments', () => ({
resolveEnvironment: vi.fn()
}))
vi.mock('child_process', async () => {
vi.mock('child_process', async (importOriginal) => {
const actual = await importOriginal<typeof ChildProcess>()
const { createChildProcessModuleMock } = await import('./index-test-harness.js')
return createChildProcessModuleMock(spawnMock)
return { ...actual, ...createChildProcessModuleMock(spawnMock) }
})
import { main } from './index'
import type {
RuntimeAgentLineageTestModule,
RuntimeAgentLineageCatalogTestModule
} from '../shared/runtime-agent-lineage-consumer.test-fixture'
import { COMMAND_SPECS } from './specs'
import { okFixture, queueFixtures } from './test-fixtures'
import { pairRuntimeEnvironment, useWorktreeAwarenessEnvironment } from './index-test-harness'
let lineage: RuntimeAgentLineageTestModule
let catalog: RuntimeAgentLineageCatalogTestModule
// The CLI's Node16 program needs a hook; each test still creates its own DB and runtime.
beforeAll(async () => {
lineage = (
await vi.importActual<{ default: RuntimeAgentLineageTestModule }>(
'../main/runtime/runtime-agent-lineage.test-fixture'
)
).default
catalog = (
await vi.importActual<{ default: RuntimeAgentLineageCatalogTestModule }>(
'../main/runtime/runtime-agent-lineage-catalog.test-fixture'
)
).default
})
const TERMINAL_ROW = {
handle: 'term_1',
ptyId: 'pty-1',
@@ -71,6 +94,64 @@ describe('omittedHostIds selector annotation', () => {
spawnMock
})
it.each(['repo::/workspace', 'folder:lineage'])(
'prints canonical production-built lineage through actual CLI and worktree RPC for %s',
async (worktreeId) => {
const { publicLineageFixture, canonicalChatRow, LINEAGE_PARENT, LINEAGE_CHILD } = lineage
const f = publicLineageFixture(worktreeId)
try {
const dispatcher = catalog.createLineageCatalogDispatcher(f.build)
const resultOf = (response: unknown) => JSON.parse(JSON.stringify(response)).result
const request = (params = {}) =>
dispatcher.dispatch({
id: 'req_worktree_ps',
authToken: 'test',
method: 'worktree.ps',
params
})
const legacy = await request()
expect(legacy).toMatchObject({
ok: true,
result: {
worktrees: [
{
agents: [
{ parentPaneKey: null },
{
parentPaneKey: canonicalChatRow(LINEAGE_PARENT),
taskTitle: 'Build the worker result'
}
]
}
]
}
})
callMock.mockResolvedValueOnce(legacy)
const log = vi.spyOn(console, 'log').mockImplementation(() => {})
await main(['worktree', 'ps', '--json'], '/workspace')
const printed = JSON.parse(String(log.mock.calls[0]?.[0]))
expect(printed.result.worktrees[0].agents[1].paneKey).toBe(canonicalChatRow(LINEAGE_CHILD))
expect(JSON.stringify(printed)).not.toContain(f.privateHandle)
expect(JSON.stringify(printed)).not.toContain(f.privatePane)
const first = resultOf(await request({ afterSnapshotId: null }))
expect(resultOf(await request({ afterSnapshotId: first.snapshotId }))).toMatchObject({
unchanged: true
})
f.db.db
.prepare(
'UPDATE runs SET coordinator_orca_session_id = NULL, coordinator_orca_session_id_generation = NULL WHERE id = ?'
)
.run(f.run.id)
expect(resultOf(await request({ afterSnapshotId: first.snapshotId })).snapshotId).not.toBe(
first.snapshotId
)
log.mockRestore()
} finally {
f.db.close()
}
}
)
it('marks a stale runtime host that no caller can select', async () => {
pairRuntimeEnvironment(listEnvironmentsMock, 'env-paired', 'm4air')
queueFixtures(
@@ -44,6 +44,9 @@ import { ORCA_LAYOUT_OWNER_IS_MAIN } from '../../../shared/layout-owner-switch'
import { mainListsEveryPane } from '../terminal/surface/main-terminal-surfaces'
import { TUI_IDLE_QUIESCENCE_MS } from '../orca-runtime-postlude'
import { screenClearsBlockedTail } from '../blocked-tail-screen-clear'
import { conversationRecordReader } from '../orchestration/structured-session-lineage'
import { getStructuredAgentSessionHost } from '../../native-chat/agent-session-wire/structured-agent-session-registry'
import { peekOpenedAgentSessionRecordStore } from '../agent-session-record-store-slot'
export abstract class OrcaRuntimeWithStopRequestedPtyIds extends OrcaRuntimeWithRuntimeId {
protected readonly stopRequestedPtyIds = new Set<string>()
@@ -124,7 +127,12 @@ export abstract class OrcaRuntimeWithStopRequestedPtyIds extends OrcaRuntimeWith
getHandleForPaneKey: (paneKey) => this.getTerminalHandleForPaneKey(paneKey),
getPaneKey: (handle) => this.getPaneKeyForTerminalHandle(handle),
getDispatchAuthority: (handle) => this.getOrchestrationDispatchAuthority(handle),
getAgentStatusSnapshot: () => this.getOrchestrationFleetAgentStatusSnapshot()
getAgentStatusSnapshot: () => this.getOrchestrationFleetAgentStatusSnapshot(),
getSessionRecords: () => {
const store =
getStructuredAgentSessionHost()?.deps.store ?? peekOpenedAgentSessionRecordStore()
return store ? conversationRecordReader(store) : null
}
})
protected readonly terminalList = new RuntimeTerminalList({
@@ -0,0 +1,138 @@
import { DatabaseSync } from 'node:sqlite'
import { vi } from 'vitest'
import type SyncDatabase from '../sqlite/sync-database'
import type { SqliteBindings } from '../sqlite/sqlite-statement'
import type { OrchestrationDb } from './orchestration/db'
// SQL predicate visits complement range plans/probe counts; they are not total SQLite VM steps.
export function installSqlVisitCounters(counters: Record<string, () => number>) {
const initialized = new WeakSet<DatabaseSync>()
const prepare = DatabaseSync.prototype.prepare
return vi.spyOn(DatabaseSync.prototype, 'prepare').mockImplementation(function (
this: DatabaseSync,
sql
) {
if (!initialized.has(this)) {
for (const [name, visit] of Object.entries(counters)) {
this.function(name, {}, (_rowid: unknown) => visit())
}
initialized.add(this)
}
return prepare.call(this, sql)
})
}
export function traceDispatchPredicateVisits(
db: SyncDatabase,
functions: { candidate: string; latest?: string; observation?: string }
) {
const prepare = db.prepare.bind(db)
const executions: { query: string; parameters: SqliteBindings; rows: number }[] = []
const observed = new WeakSet<object>()
const trace = vi.spyOn(db, 'prepare').mockImplementation((query) => {
let instrumented = query.replaceAll(
'WHERE assignee_orca_session_id IS NOT NULL',
`WHERE assignee_orca_session_id IS NOT NULL AND ${functions.candidate}(rowid)`
)
if (functions.latest && query.includes('rowid AS n')) {
instrumented = instrumented.replace(
'ORDER BY rowid DESC LIMIT 1',
`AND ${functions.latest}(rowid) ORDER BY rowid DESC LIMIT 1`
)
}
if (functions.observation) {
instrumented = instrumented.replace(
'WHERE dispatch_id IN',
`WHERE ${functions.observation}(rowid) AND dispatch_id IN`
)
}
const statement = prepare(instrumented)
if (!observed.has(statement)) {
observed.add(statement)
const all = statement.all.bind(statement)
const get = statement.get.bind(statement)
vi.spyOn(statement, 'all').mockImplementation((...args) => {
const rows = all(...args)
executions.push({ query, parameters: args, rows: rows.length })
return rows
})
vi.spyOn(statement, 'get').mockImplementation((...args) => {
const row = get(...args)
executions.push({ query, parameters: args, rows: row ? 1 : 0 })
return row
})
}
return statement
})
return Object.assign(trace, { executions })
}
export function latestStatementMetrics(
trace: ReturnType<typeof traceDispatchPredicateVisits>,
native: ReturnType<typeof installSqlVisitCounters>
) {
const latest = (query: string) => query.includes('rowid AS n FROM dispatch_contexts')
const executions = trace.executions.filter(({ query }) => latest(query))
return {
cachedPrepareCalls: trace.mock.calls.filter(([query]) => latest(query)).length,
executedStatements: executions.length,
nativeCompilations: native.mock.calls.filter(([query]) => latest(query)).length,
addressEntries: executions.reduce((sum, { parameters }) => {
const addresses: unknown =
typeof parameters[0] === 'string' ? JSON.parse(parameters[0]) : null
if (!Array.isArray(addresses) || !addresses.every((value) => typeof value === 'string')) {
throw new Error('Expected actual JSON address batch')
}
return sum + addresses.length
}, 0),
returnedVerificationRows: executions.reduce((sum, { rows }) => sum + rows, 0)
}
}
export function dispatchQueryPlans(
db: SyncDatabase,
trace: ReturnType<typeof traceDispatchPredicateVisits>
) {
const queries = new Map(
trace.executions
.filter(
({ query }) =>
query.includes('idx_dispatch_session_presentation') ||
query.includes('rowid AS n FROM dispatch_contexts')
)
.map(({ query, parameters }) => [query, parameters])
)
return [...queries].map(([query, parameters]) => ({
query,
parameters,
plan: db.prepare(`EXPLAIN QUERY PLAN ${query}`).all(...parameters)
}))
}
export function seedCoarsePresentationDispatches(
db: OrchestrationDb,
runId: string,
count: number,
now: number,
prefix = 'coarse'
) {
if (!count) {
return
}
const task = db.createTask({ runId, spec: 'coarse-only history' })
db.db
.prepare(`INSERT INTO dispatch_contexts
(id, run_id, task_id, assignee_handle, assignee_orca_session_id, status, completed_at)
WITH RECURSIVE seq(n) AS (VALUES(1) UNION ALL SELECT n+1 FROM seq WHERE n < ?)
SELECT ? || n, ?, ?, CASE WHEN n % 2 = 1 THEN ? || n WHEN n % 4 = 0 THEN '' ELSE NULL END,
? || n, 'completed', ? FROM seq`)
.run(
count,
`${prefix}-id-`,
runId,
task.id,
`${prefix}-handle-`,
`${prefix}-session-`,
new Date(now - 7_200_000).toISOString()
)
}
@@ -227,6 +227,10 @@ export class InMemoryOrchestrationMessages {
return [...this.runs.values()].find((run) => run.coordinator_pane_key === paneKey)
}
listSessionDispatchesForPresentation(): never[] {
return []
}
listWorkerTerminalReleaseBacklog(): never[] {
return []
}
@@ -215,6 +215,7 @@ function makePostRevealWorkerRecoveryHarness(
)
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: This recovery fixture reaches only the listed planner, terminal settlement and authority lookup methods.
runtime.setOrchestrationDb({
listSessionDispatchesForPresentation: () => [],
reconcileMissingWorkerTerminal: vi.fn(),
getActiveDispatchForTerminal: () => undefined,
listLegacyWorkerTerminalRecoveryRows: () => [
@@ -1,3 +1,10 @@
import {
makeRuntimeOrchestrationDb,
dispatchContextRow,
coordinatorRunRow,
taskLineageRow,
runRow
} from '../runtime-orchestration-db.test-fixture'
import { describe, expect, it, vi } from 'vitest'
import {
MOCK_GIT_WORKTREES,
@@ -208,15 +215,20 @@ describe('OrcaRuntimeService', () => {
const runtime = new OrcaRuntimeService(runtimeStore as never)
const workerHandle = runtime.preAllocateHandleForPty('pty-worker')
const coordinatorHandle = runtime.preAllocateHandleForPty('pty-coordinator')
runtime.setOrchestrationDb({
getActiveDispatchForTerminal: vi.fn(() => ({
const orchestrationDb = makeRuntimeOrchestrationDb()
vi.spyOn(orchestrationDb, 'listSessionDispatchesForPresentation').mockImplementation(() => [])
vi.spyOn(orchestrationDb, 'getActiveDispatchForTerminal').mockImplementation(() =>
dispatchContextRow({
task_id: 'task-1'
})),
getActiveCoordinatorRun: vi.fn(() => ({
})
)
vi.spyOn(orchestrationDb, 'getActiveCoordinatorRun').mockImplementation(() =>
coordinatorRunRow({
id: 'run-1',
coordinator_handle: coordinatorHandle
}))
} as never)
})
)
runtime.setOrchestrationDb(orchestrationDb)
runtime.attachWindow(1)
runtime.syncWindowGraph(1, {
tabs: [
@@ -310,44 +322,54 @@ describe('OrcaRuntimeService', () => {
const coordinatorPaneKey = makePaneKey('tab-coordinator', coordinatorLeafId)
const workerHandle = runtime.preAllocateHandleForPty('pty-worker')
const coordinatorHandle = runtime.preAllocateHandleForPty('pty-coordinator')
runtime.setOrchestrationDb({
getActiveDispatchForTerminal: vi.fn((handle: string) =>
const orchestrationDb = makeRuntimeOrchestrationDb()
vi.spyOn(orchestrationDb, 'listSessionDispatchesForPresentation').mockImplementation(() => [])
vi.spyOn(orchestrationDb, 'getActiveDispatchForTerminal').mockImplementation(
(handle: string) =>
handle === workerHandle
? {
? dispatchContextRow({
id: 'ctx-1',
run_id: 'run-1',
task_id: 'task-1',
assignee_handle: workerHandle,
status: 'dispatched'
}
})
: undefined
),
getLatestDispatchForTerminal: vi.fn((handle: string) =>
)
vi.spyOn(orchestrationDb, 'getLatestDispatchForTerminal').mockImplementation(
(handle: string) =>
handle === workerHandle
? {
? dispatchContextRow({
id: 'ctx-done',
run_id: 'run-1',
task_id: 'task-done',
assignee_handle: workerHandle,
status: 'completed',
completed_at: new Date(Date.now()).toISOString()
}
})
: undefined
),
getTask: vi.fn(() => ({
)
vi.spyOn(orchestrationDb, 'getTask').mockImplementation(() =>
taskLineageRow({
id: 'task-1',
run_id: 'run-1',
task_title: 'Dispatch prompt work',
display_name: 'Review dispatch prompts and make worker labels distinct',
spec: 'Review dispatch prompts\n\nand make worker labels distinct',
created_by_terminal_handle: coordinatorHandle
})),
getRun: vi.fn(() => ({
})
)
vi.spyOn(orchestrationDb, 'getRun').mockImplementation(() =>
runRow({
id: 'run-1',
coordinator_handle: coordinatorHandle,
coordinator_orca_session_id: null,
coordinator_orca_session_id_generation: null,
consumer_generation: 0,
legacy: 0
}))
} as never)
})
)
runtime.setOrchestrationDb(orchestrationDb)
runtime.attachWindow(1)
const result = runtime.syncWindowGraph(1, {
@@ -410,32 +432,38 @@ describe('OrcaRuntimeService', () => {
const workerPaneKey = makePaneKey('tab-worker', workerLeafId)
const workerHandle = runtime.preAllocateHandleForPty('pty-worker')
const coordinatorHandle = runtime.preAllocateHandleForPty('pty-coordinator')
const getActiveCoordinatorRun = vi.fn(() => ({
id: 'run-legacy-unrelated',
coordinator_handle: coordinatorHandle
}))
runtime.setOrchestrationDb({
getActiveDispatchForTerminal: vi.fn((handle: string) =>
const getActiveCoordinatorRun = vi.fn(() =>
coordinatorRunRow({
id: 'run-legacy-unrelated',
coordinator_handle: coordinatorHandle
})
)
const orchestrationDb = makeRuntimeOrchestrationDb()
vi.spyOn(orchestrationDb, 'listSessionDispatchesForPresentation').mockImplementation(() => [])
vi.spyOn(orchestrationDb, 'getActiveDispatchForTerminal').mockImplementation(
(handle: string) =>
handle === workerHandle
? {
? dispatchContextRow({
id: 'ctx-missing-run',
run_id: dispatchRunId,
task_id: 'task-missing-run',
assignee_handle: workerHandle,
status: 'dispatched'
}
})
: undefined
),
getLatestDispatchForTerminal: vi.fn(() => undefined),
getTask: vi.fn(() => ({
)
vi.spyOn(orchestrationDb, 'getLatestDispatchForTerminal').mockImplementation(() => undefined)
vi.spyOn(orchestrationDb, 'getTask').mockImplementation(() =>
taskLineageRow({
id: 'task-missing-run',
run_id: taskRunId,
spec: 'modern task without proven Run',
created_by_terminal_handle: coordinatorHandle
})),
getRun: vi.fn(() => undefined),
getActiveCoordinatorRun
} as never)
})
)
vi.spyOn(orchestrationDb, 'getRun').mockImplementation(() => undefined)
vi.spyOn(orchestrationDb, 'getActiveCoordinatorRun').mockImplementation(getActiveCoordinatorRun)
runtime.setOrchestrationDb(orchestrationDb)
runtime.attachWindow(1)
const result = runtime.syncWindowGraph(1, {
@@ -1,3 +1,10 @@
import {
makeRuntimeOrchestrationDb,
dispatchContextRow,
taskLineageRow,
runRow,
coordinatorRunRow
} from '../runtime-orchestration-db.test-fixture'
import { describe, expect, it, vi } from 'vitest'
import {
AGENT_STATUS_STALE_AFTER_MS,
@@ -460,31 +467,40 @@ describe('OrcaRuntimeService', () => {
const coordinatorPaneKey = makePaneKey('tab-coordinator', coordinatorLeafId)
const workerHandle = runtime.preAllocateHandleForPty('pty-worker')
const coordinatorHandle = runtime.preAllocateHandleForPty('pty-coordinator')
runtime.setOrchestrationDb({
getActiveDispatchForTerminal: vi.fn(() => undefined),
getLatestDispatchForTerminal: vi.fn((handle: string) =>
const orchestrationDb = makeRuntimeOrchestrationDb()
vi.spyOn(orchestrationDb, 'listSessionDispatchesForPresentation').mockImplementation(() => [])
vi.spyOn(orchestrationDb, 'getActiveDispatchForTerminal').mockImplementation(() => undefined)
vi.spyOn(orchestrationDb, 'getLatestDispatchForTerminal').mockImplementation(
(handle: string) =>
handle === workerHandle
? {
? dispatchContextRow({
id: 'ctx-done',
run_id: 'run-1',
task_id: 'task-done',
assignee_handle: workerHandle,
status: 'completed',
completed_at: new Date(Date.now()).toISOString()
}
})
: undefined
),
getTask: vi.fn(() => ({
)
vi.spyOn(orchestrationDb, 'getTask').mockImplementation(() =>
taskLineageRow({
id: 'task-done',
run_id: 'run-1',
created_by_terminal_handle: coordinatorHandle
})),
getRun: vi.fn(() => ({
})
)
vi.spyOn(orchestrationDb, 'getRun').mockImplementation(() =>
runRow({
id: 'run-1',
coordinator_handle: coordinatorHandle,
coordinator_orca_session_id: null,
coordinator_orca_session_id_generation: null,
consumer_generation: 0,
legacy: 0
}))
} as never)
})
)
runtime.setOrchestrationDb(orchestrationDb)
runtime.attachWindow(1)
const result = runtime.syncWindowGraph(1, {
@@ -538,27 +554,33 @@ describe('OrcaRuntimeService', () => {
const workerLeafId = '55555555-5555-4555-8555-555555555555'
const workerPaneKey = makePaneKey('tab-worker', workerLeafId)
const workerHandle = runtime.preAllocateHandleForPty('pty-worker')
runtime.setOrchestrationDb({
getActiveDispatchForTerminal: vi.fn(() => undefined),
getLatestDispatchForTerminal: vi.fn((handle: string) =>
const orchestrationDb = makeRuntimeOrchestrationDb()
vi.spyOn(orchestrationDb, 'listSessionDispatchesForPresentation').mockImplementation(() => [])
vi.spyOn(orchestrationDb, 'getActiveDispatchForTerminal').mockImplementation(() => undefined)
vi.spyOn(orchestrationDb, 'getLatestDispatchForTerminal').mockImplementation(
(handle: string) =>
handle === workerHandle
? {
? dispatchContextRow({
id: 'ctx-done',
task_id: 'task-done',
assignee_handle: workerHandle,
status: 'completed',
completed_at: new Date(Date.now()).toISOString()
}
})
: undefined
),
getTask: vi.fn(() => ({
)
vi.spyOn(orchestrationDb, 'getTask').mockImplementation(() =>
taskLineageRow({
id: 'task-done'
})),
getActiveCoordinatorRun: vi.fn(() => ({
})
)
vi.spyOn(orchestrationDb, 'getActiveCoordinatorRun').mockImplementation(() =>
coordinatorRunRow({
id: 'run-unrelated',
coordinator_handle: 'term_unrelated'
}))
} as never)
})
)
runtime.setOrchestrationDb(orchestrationDb)
runtime.attachWindow(1)
const result = runtime.syncWindowGraph(1, {
@@ -1,3 +1,9 @@
import {
makeRuntimeOrchestrationDb,
dispatchContextRow,
taskLineageRow,
coordinatorRunRow
} from '../runtime-orchestration-db.test-fixture'
import { describe, expect, it, vi } from 'vitest'
import {
AGENT_STATUS_STALE_AFTER_MS,
@@ -28,21 +34,28 @@ describe('OrcaRuntimeService', () => {
const workerLeafId = '66666666-6666-4666-8666-666666666666'
const workerPaneKey = makePaneKey('tab-worker', workerLeafId)
const workerHandle = runtime.preAllocateHandleForPty('pty-worker')
const getActiveCoordinatorRun = vi.fn(() => ({
id: 'run-unrelated',
coordinator_handle: 'term_unrelated'
}))
runtime.setOrchestrationDb({
getActiveDispatchForTerminal: vi.fn(() => undefined),
getLatestDispatchForTerminal: vi.fn(() => ({
const getActiveCoordinatorRun = vi.fn(() =>
coordinatorRunRow({
id: 'run-unrelated',
coordinator_handle: 'term_unrelated'
})
)
const orchestrationDb = makeRuntimeOrchestrationDb()
vi.spyOn(orchestrationDb, 'listSessionDispatchesForPresentation').mockImplementation(() => [])
vi.spyOn(orchestrationDb, 'getActiveDispatchForTerminal').mockImplementation(() => undefined)
vi.spyOn(orchestrationDb, 'getLatestDispatchForTerminal').mockImplementation(() =>
dispatchContextRow({
id: 'ctx-settled',
task_id: 'task-settled',
assignee_handle: workerHandle,
status: dispatchStatus,
completed_at: new Date(Date.now()).toISOString()
})),
})
)
vi.spyOn(orchestrationDb, 'getActiveCoordinatorRun').mockImplementation(
getActiveCoordinatorRun
} as never)
)
runtime.setOrchestrationDb(orchestrationDb)
runtime.attachWindow(1)
const result = runtime.syncWindowGraph(1, {
@@ -80,20 +93,22 @@ describe('OrcaRuntimeService', () => {
const runtime = new OrcaRuntimeService(store)
const workerLeafId = '77777777-7777-4777-8777-777777777777'
const workerHandle = runtime.preAllocateHandleForPty('pty-worker')
runtime.setOrchestrationDb({
getActiveDispatchForTerminal: vi.fn(() => undefined),
getLatestDispatchForTerminal: vi.fn((handle: string) =>
const orchestrationDb = makeRuntimeOrchestrationDb()
vi.spyOn(orchestrationDb, 'listSessionDispatchesForPresentation').mockImplementation(() => [])
vi.spyOn(orchestrationDb, 'getActiveDispatchForTerminal').mockImplementation(() => undefined)
vi.spyOn(orchestrationDb, 'getLatestDispatchForTerminal').mockImplementation(
(handle: string) =>
handle === workerHandle
? {
? dispatchContextRow({
id: 'ctx-stale',
task_id: 'task-stale',
assignee_handle: workerHandle,
status: 'completed',
completed_at: new Date(Date.now() - AGENT_STATUS_STALE_AFTER_MS - 1).toISOString()
}
})
: undefined
)
} as never)
)
runtime.setOrchestrationDb(orchestrationDb)
runtime.attachWindow(1)
const result = runtime.syncWindowGraph(1, {
@@ -257,13 +272,16 @@ describe('OrcaRuntimeService', () => {
}
const runtime = new OrcaRuntimeService(runtimeStore as never)
const workerHandle = runtime.preAllocateHandleForPty('pty-worker')
runtime.setOrchestrationDb({
getDispatchContext: vi.fn(() => ({
const orchestrationDb = makeRuntimeOrchestrationDb()
vi.spyOn(orchestrationDb, 'listSessionDispatchesForPresentation').mockImplementation(() => [])
vi.spyOn(orchestrationDb, 'getDispatchContext').mockImplementation(() =>
dispatchContextRow({
task_id: 'task_abc123',
assignee_handle: workerHandle,
status: 'completed'
}))
} as never)
})
)
runtime.setOrchestrationDb(orchestrationDb)
runtime.attachWindow(1)
runtime.syncWindowGraph(1, {
tabs: [
@@ -355,13 +373,16 @@ describe('OrcaRuntimeService', () => {
}
const runtime = new OrcaRuntimeService(runtimeStore as never)
const parentHandle = runtime.preAllocateHandleForPty('pty-parent')
runtime.setOrchestrationDb({
getDispatchContext: vi.fn(() => undefined),
getTask: vi.fn(() => ({
const orchestrationDb = makeRuntimeOrchestrationDb()
vi.spyOn(orchestrationDb, 'listSessionDispatchesForPresentation').mockImplementation(() => [])
vi.spyOn(orchestrationDb, 'getDispatchContext').mockImplementation(() => undefined)
vi.spyOn(orchestrationDb, 'getTask').mockImplementation(() =>
taskLineageRow({
id: 'task_creator123',
created_by_terminal_handle: parentHandle
}))
} as never)
})
)
runtime.setOrchestrationDb(orchestrationDb)
runtime.attachWindow(1)
runtime.syncWindowGraph(1, {
tabs: [
@@ -1,6 +1,11 @@
import { makeRuntimeOrchestrationDb } from '../runtime-orchestration-db.test-fixture'
import { describe, expect, it, vi } from 'vitest'
import { makeAgentStatusStoreWiring } from '../agent-status-store-wiring.test-fixture'
import { OrcaRuntimeService, listWorktrees } from '../orca-runtime-test-mocks.spec'
import {
OrcaRuntimeService,
createRootDispatch,
listWorktrees
} from '../orca-runtime-test-mocks.spec'
import {
HEADLESS_LEAF_ID,
TEST_FOLDER_PROJECT_GROUP_ID,
@@ -456,26 +461,20 @@ describe('OrcaRuntimeService', () => {
]
})
const workerHandle = runtime.preAllocateHandleForPty('pty-1')
runtime.setOrchestrationDb({
getActiveDispatchForTerminal: vi.fn((handle: string) =>
handle === workerHandle
? {
id: 'ctx-1',
task_id: 'task-1',
assignee_handle: workerHandle,
status: 'dispatched'
}
: undefined
),
getLatestDispatchForTerminal: vi.fn(() => undefined),
getTask: vi.fn(() => ({
id: 'task-1',
task_title: 'Dispatch prompt work',
display_name: 'Review dispatch prompts and make worker labels distinct',
spec: 'Review dispatch prompts\n\nand make worker labels distinct'
})),
getActiveCoordinatorRun: vi.fn(() => undefined)
} as never)
const orchestrationDb = makeRuntimeOrchestrationDb()
const run = orchestrationDb.createRun({
objective: 'Hook summary projection',
coordinatorHandle: null,
coordinatorPaneKey: null
})
const task = orchestrationDb.createTask({
runId: run.id,
taskTitle: 'Dispatch prompt work',
displayName: 'Review dispatch prompts and make worker labels distinct',
spec: 'Review dispatch prompts\n\nand make worker labels distinct'
})
createRootDispatch(orchestrationDb, task.id, workerHandle, paneKey)
runtime.setOrchestrationDb(orchestrationDb)
runtime.attachWindow(1)
runtime.syncWindowGraph(1, {
tabs: [
@@ -1,3 +1,7 @@
import {
makeRuntimeOrchestrationDb,
dispatchContextRow
} from '../runtime-orchestration-db.test-fixture'
import { describe, expect, it, vi } from 'vitest'
import {
OrcaRuntimeService,
@@ -9,7 +13,6 @@ import {
setTerminalViewAttributes,
tmpdir
} from '../orca-runtime-test-mocks.spec'
import type { OrchestrationDb } from '../orchestration/db'
import { getTerminalViewerColors } from '../terminal-view-attribute-store'
import type {
TerminalViewAttributes,
@@ -112,14 +115,15 @@ describe('OrcaRuntimeService', () => {
retireAgentHookCompatibilityAuthority: retireAuthority
}
)
runtime.setOrchestrationDb({
getActiveDispatchForTerminal: (handle: string) =>
const orchestrationDb = makeRuntimeOrchestrationDb()
vi.spyOn(orchestrationDb, 'getActiveDispatchForTerminal').mockImplementation(
(handle: string) =>
handle === 'term_ssh_retained'
? { id: 'dispatch-ssh', task_id: 'task-ssh', status: 'dispatched' }
: undefined,
failDispatch,
getActiveCoordinatorRun: () => undefined
} as unknown as OrchestrationDb)
? dispatchContextRow({ id: 'dispatch-ssh', task_id: 'task-ssh', status: 'dispatched' })
: undefined
)
vi.spyOn(orchestrationDb, 'failDispatch').mockImplementation(failDispatch)
runtime.setOrchestrationDb(orchestrationDb)
runtime.attachWindow(TEST_WINDOW_ID)
runtime.syncWindowGraph(TEST_WINDOW_ID, {
tabs: [
@@ -1,3 +1,4 @@
import { makeRuntimeOrchestrationDb } from '../runtime-orchestration-db.test-fixture'
import { withDurableRuntimeStore } from '../runtime-durable-store-fixture'
import { describe, expect, it, vi } from 'vitest'
import { ORCA_LAYOUT_OWNER_IS_MAIN } from '../../../shared/layout-owner-switch'
@@ -6,7 +7,6 @@ import {
getDefaultWorkspaceSession,
makePaneKey
} from '../orca-runtime-test-mocks.spec'
import type { OrchestrationDb } from '../orchestration/db'
import type { WorkspaceSessionState } from '../orca-runtime-test-mocks.spec'
import {
HEADLESS_LEAF_ID,
@@ -469,23 +469,24 @@ describe('OrcaRuntimeService', () => {
: null
}
)
runtime.setOrchestrationDb({
getActiveDispatchForTerminal: () => undefined,
listLegacyWorkerTerminalRecoveryRows: () => [
{
dispatch_id: 'dispatch-legacy',
task_id: 'task-legacy',
dispatch_status: 'completed',
contract_version: 0,
assignee_handle: 'term_legacy',
assignee_pane_key: workerPaneKey,
process_incarnation: `pty-legacy:${incarnationId}`,
worker_state: 'ready',
worktree_id: TEST_WORKTREE_ID,
agent_terminal_handle: 'term_legacy'
}
]
} as unknown as OrchestrationDb)
const orchestrationDb = makeRuntimeOrchestrationDb()
vi.spyOn(orchestrationDb, 'listSessionDispatchesForPresentation').mockImplementation(() => [])
vi.spyOn(orchestrationDb, 'getActiveDispatchForTerminal').mockImplementation(() => undefined)
vi.spyOn(orchestrationDb, 'listLegacyWorkerTerminalRecoveryRows').mockImplementation(() => [
{
dispatch_id: 'dispatch-legacy',
task_id: 'task-legacy',
dispatch_status: 'completed',
contract_version: 0,
assignee_handle: 'term_legacy',
assignee_pane_key: workerPaneKey,
process_incarnation: `pty-legacy:${incarnationId}`,
worker_state: 'ready',
worktree_id: TEST_WORKTREE_ID,
agent_terminal_handle: 'term_legacy'
}
])
runtime.setOrchestrationDb(orchestrationDb)
const write = vi.fn(() => true)
const kill = vi.fn(() => true)
const READY_SCREEN =
@@ -1,8 +1,8 @@
import { makeRuntimeOrchestrationDb } from '../runtime-orchestration-db.test-fixture'
import { withDurableRuntimeStore } from '../runtime-durable-store-fixture'
import { describe, expect, it, vi } from 'vitest'
import { ORCA_LAYOUT_OWNER_IS_MAIN } from '../../../shared/layout-owner-switch'
import { OrcaRuntimeService, getDefaultWorkspaceSession } from '../orca-runtime-test-mocks.spec'
import type { OrchestrationDb } from '../orchestration/db'
import type { WorkspaceSessionState } from '../orca-runtime-test-mocks.spec'
import {
HEADLESS_LEAF_ID,
@@ -46,23 +46,24 @@ describe('OrcaRuntimeService', () => {
undefined,
{ canRecoverPersistentLocalPtys: () => true }
)
runtime.setOrchestrationDb({
getActiveDispatchForTerminal: () => undefined,
listLegacyWorkerTerminalRecoveryRows: () => [
{
dispatch_id: 'dispatch-reveal-retry',
task_id: 'task-reveal-retry',
dispatch_status: 'completed',
contract_version: 0,
assignee_handle: 'term_reveal_retry',
assignee_pane_key: workerPaneKey,
process_incarnation: `pty-reveal-retry:${incarnationId}`,
worker_state: 'ready',
worktree_id: TEST_WORKTREE_ID,
agent_terminal_handle: 'term_reveal_retry'
}
]
} as unknown as OrchestrationDb)
const orchestrationDb = makeRuntimeOrchestrationDb()
vi.spyOn(orchestrationDb, 'listSessionDispatchesForPresentation').mockImplementation(() => [])
vi.spyOn(orchestrationDb, 'getActiveDispatchForTerminal').mockImplementation(() => undefined)
vi.spyOn(orchestrationDb, 'listLegacyWorkerTerminalRecoveryRows').mockImplementation(() => [
{
dispatch_id: 'dispatch-reveal-retry',
task_id: 'task-reveal-retry',
dispatch_status: 'completed',
contract_version: 0,
assignee_handle: 'term_reveal_retry',
assignee_pane_key: workerPaneKey,
process_incarnation: `pty-reveal-retry:${incarnationId}`,
worker_state: 'ready',
worktree_id: TEST_WORKTREE_ID,
agent_terminal_handle: 'term_reveal_retry'
}
])
runtime.setOrchestrationDb(orchestrationDb)
runtime.setPtyController({
write: vi.fn(() => true),
kill: vi.fn(() => true),
@@ -461,22 +462,23 @@ describe('OrcaRuntimeService', () => {
undefined,
{ canRecoverPersistentLocalPtys: () => true }
)
runtime.setOrchestrationDb({
listLegacyWorkerTerminalRecoveryRows: () => [
{
dispatch_id: 'dispatch-persistence-failure',
task_id: 'task-persistence-failure',
dispatch_status: 'completed',
contract_version: 0,
assignee_handle: 'term_persistence_failure',
assignee_pane_key: workerPaneKey,
process_incarnation: `pty-persistence-failure:${incarnationId}`,
worker_state: 'ready',
worktree_id: TEST_WORKTREE_ID,
agent_terminal_handle: 'term_persistence_failure'
}
]
} as unknown as OrchestrationDb)
const orchestrationDb = makeRuntimeOrchestrationDb()
vi.spyOn(orchestrationDb, 'listSessionDispatchesForPresentation').mockImplementation(() => [])
vi.spyOn(orchestrationDb, 'listLegacyWorkerTerminalRecoveryRows').mockImplementation(() => [
{
dispatch_id: 'dispatch-persistence-failure',
task_id: 'task-persistence-failure',
dispatch_status: 'completed',
contract_version: 0,
assignee_handle: 'term_persistence_failure',
assignee_pane_key: workerPaneKey,
process_incarnation: `pty-persistence-failure:${incarnationId}`,
worker_state: 'ready',
worktree_id: TEST_WORKTREE_ID,
agent_terminal_handle: 'term_persistence_failure'
}
])
runtime.setOrchestrationDb(orchestrationDb)
runtime.setPtyController({
write: vi.fn(() => true),
kill: vi.fn(() => true),
@@ -1,3 +1,4 @@
import { makeRuntimeOrchestrationDb } from '../runtime-orchestration-db.test-fixture'
import { withDurableRuntimeStore } from '../runtime-durable-store-fixture'
import { describe, expect, it, vi } from 'vitest'
import {
@@ -279,6 +280,7 @@ describe('OrcaRuntimeService', () => {
)
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: This isolated recovery path reaches only the supplied planner and missing-terminal settlement methods.
runtime.setOrchestrationDb({
listSessionDispatchesForPresentation: () => [],
reconcileMissingWorkerTerminal: vi.fn(),
listLegacyWorkerTerminalRecoveryRows: () => [
{
@@ -390,22 +392,23 @@ describe('OrcaRuntimeService', () => {
undefined,
{ canRecoverPersistentLocalPtys: () => true }
)
runtime.setOrchestrationDb({
listLegacyWorkerTerminalRecoveryRows: () => [
{
dispatch_id: 'dispatch-inventory-unavailable',
task_id: 'task-inventory-unavailable',
dispatch_status: 'completed',
contract_version: 0,
assignee_handle: 'term_inventory_unavailable',
assignee_pane_key: workerPaneKey,
process_incarnation: `pty-inventory-unavailable:${incarnationId}`,
worker_state: 'ready',
worktree_id: TEST_WORKTREE_ID,
agent_terminal_handle: 'term_inventory_unavailable'
}
]
} as unknown as OrchestrationDb)
const orchestrationDb = makeRuntimeOrchestrationDb()
vi.spyOn(orchestrationDb, 'listSessionDispatchesForPresentation').mockImplementation(() => [])
vi.spyOn(orchestrationDb, 'listLegacyWorkerTerminalRecoveryRows').mockImplementation(() => [
{
dispatch_id: 'dispatch-inventory-unavailable',
task_id: 'task-inventory-unavailable',
dispatch_status: 'completed',
contract_version: 0,
assignee_handle: 'term_inventory_unavailable',
assignee_pane_key: workerPaneKey,
process_incarnation: `pty-inventory-unavailable:${incarnationId}`,
worker_state: 'ready',
worktree_id: TEST_WORKTREE_ID,
agent_terminal_handle: 'term_inventory_unavailable'
}
])
runtime.setOrchestrationDb(orchestrationDb)
const listProcesses = vi
.fn()
.mockRejectedValueOnce(new Error('local provider unavailable'))
@@ -1,3 +1,4 @@
import { makeRuntimeOrchestrationDb } from '../runtime-orchestration-db.test-fixture'
import { withDurableRuntimeStore } from '../runtime-durable-store-fixture'
import { describe, expect, it, vi } from 'vitest'
import {
@@ -79,6 +80,7 @@ describe('OrcaRuntimeService', () => {
)
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: This isolated recovery path reaches only the supplied planner and missing-terminal settlement methods.
runtime.setOrchestrationDb({
listSessionDispatchesForPresentation: () => [],
reconcileMissingWorkerTerminal: vi.fn(),
listLegacyWorkerTerminalRecoveryRows: () =>
cases.map(({ name, leafId, terminalHandle }) => ({
@@ -201,22 +203,23 @@ describe('OrcaRuntimeService', () => {
undefined,
{ canRecoverPersistentLocalPtys: () => true }
)
runtime.setOrchestrationDb({
listLegacyWorkerTerminalRecoveryRows: () => [
{
dispatch_id: 'dispatch-folder',
task_id: 'task-folder',
dispatch_status: 'completed',
contract_version: 0,
assignee_handle: 'term_folder',
assignee_pane_key: workerPaneKey,
process_incarnation: `pty-folder-legacy:${incarnationId}`,
worker_state: 'ready',
worktree_id: TEST_FOLDER_WORKSPACE_KEY,
agent_terminal_handle: 'term_folder'
}
]
} as unknown as OrchestrationDb)
const orchestrationDb = makeRuntimeOrchestrationDb()
vi.spyOn(orchestrationDb, 'listSessionDispatchesForPresentation').mockImplementation(() => [])
vi.spyOn(orchestrationDb, 'listLegacyWorkerTerminalRecoveryRows').mockImplementation(() => [
{
dispatch_id: 'dispatch-folder',
task_id: 'task-folder',
dispatch_status: 'completed',
contract_version: 0,
assignee_handle: 'term_folder',
assignee_pane_key: workerPaneKey,
process_incarnation: `pty-folder-legacy:${incarnationId}`,
worker_state: 'ready',
worktree_id: TEST_FOLDER_WORKSPACE_KEY,
agent_terminal_handle: 'term_folder'
}
])
runtime.setOrchestrationDb(orchestrationDb)
const listProcesses = vi.fn(async () => [
{
id: 'pty-folder-legacy',
@@ -329,22 +332,23 @@ describe('OrcaRuntimeService', () => {
undefined,
{ canRecoverPersistentLocalPtys: () => true }
)
runtime.setOrchestrationDb({
listLegacyWorkerTerminalRecoveryRows: () => [
{
dispatch_id: 'dispatch-ssh-folder',
task_id: 'task-ssh-folder',
dispatch_status: 'completed',
contract_version: 0,
assignee_handle: 'term_ssh_folder',
assignee_pane_key: workerPaneKey,
process_incarnation: `${ptyId}:${incarnationId}`,
worker_state: 'ready',
worktree_id: TEST_FOLDER_WORKSPACE_KEY,
agent_terminal_handle: 'term_ssh_folder'
}
]
} as unknown as OrchestrationDb)
const orchestrationDb = makeRuntimeOrchestrationDb()
vi.spyOn(orchestrationDb, 'listSessionDispatchesForPresentation').mockImplementation(() => [])
vi.spyOn(orchestrationDb, 'listLegacyWorkerTerminalRecoveryRows').mockImplementation(() => [
{
dispatch_id: 'dispatch-ssh-folder',
task_id: 'task-ssh-folder',
dispatch_status: 'completed',
contract_version: 0,
assignee_handle: 'term_ssh_folder',
assignee_pane_key: workerPaneKey,
process_incarnation: `${ptyId}:${incarnationId}`,
worker_state: 'ready',
worktree_id: TEST_FOLDER_WORKSPACE_KEY,
agent_terminal_handle: 'term_ssh_folder'
}
])
runtime.setOrchestrationDb(orchestrationDb)
const listProcesses = vi.fn(async () => [
{
id: ptyId,
@@ -1,3 +1,4 @@
import { makeRuntimeOrchestrationDb } from '../runtime-orchestration-db.test-fixture'
import { withDurableRuntimeStore } from '../runtime-durable-store-fixture'
import { describe, expect, it, vi } from 'vitest'
import {
@@ -5,7 +6,6 @@ import {
getDefaultWorkspaceSession,
setPlatform
} from '../orca-runtime-test-mocks.spec'
import type { OrchestrationDb } from '../orchestration/db'
import type { WorkspaceSessionState } from '../orca-runtime-test-mocks.spec'
import {
HEADLESS_LEAF_ID,
@@ -95,22 +95,23 @@ describe('OrcaRuntimeService', () => {
undefined,
{ canRecoverPersistentLocalPtys: () => true }
)
runtime.setOrchestrationDb({
listLegacyWorkerTerminalRecoveryRows: () => [
{
dispatch_id: 'dispatch-ssh',
task_id: 'task-ssh',
dispatch_status: 'completed',
contract_version: 0,
assignee_handle: 'term_ssh_legacy',
assignee_pane_key: workerPaneKey,
process_incarnation: `${ptyId}:${incarnationId}`,
worker_state: 'ready',
worktree_id: TEST_WORKTREE_ID,
agent_terminal_handle: 'term_ssh_legacy'
}
]
} as unknown as OrchestrationDb)
const orchestrationDb = makeRuntimeOrchestrationDb()
vi.spyOn(orchestrationDb, 'listSessionDispatchesForPresentation').mockImplementation(() => [])
vi.spyOn(orchestrationDb, 'listLegacyWorkerTerminalRecoveryRows').mockImplementation(() => [
{
dispatch_id: 'dispatch-ssh',
task_id: 'task-ssh',
dispatch_status: 'completed',
contract_version: 0,
assignee_handle: 'term_ssh_legacy',
assignee_pane_key: workerPaneKey,
process_incarnation: `${ptyId}:${incarnationId}`,
worker_state: 'ready',
worktree_id: TEST_WORKTREE_ID,
agent_terminal_handle: 'term_ssh_legacy'
}
])
runtime.setOrchestrationDb(orchestrationDb)
runtime.setPtyController({
write: vi.fn(() => true),
kill: vi.fn(() => true),
@@ -228,22 +229,23 @@ describe('OrcaRuntimeService', () => {
undefined,
{ canRecoverPersistentLocalPtys: () => true }
)
runtime.setOrchestrationDb({
listLegacyWorkerTerminalRecoveryRows: () => [
{
dispatch_id: 'dispatch-wsl',
task_id: 'task-wsl',
dispatch_status: 'completed',
contract_version: 0,
assignee_handle: 'term_wsl_legacy',
assignee_pane_key: workerPaneKey,
process_incarnation: `pty-wsl-legacy:${incarnationId}`,
worker_state: 'ready',
worktree_id: TEST_WORKTREE_ID,
agent_terminal_handle: 'term_wsl_legacy'
}
]
} as unknown as OrchestrationDb)
const orchestrationDb = makeRuntimeOrchestrationDb()
vi.spyOn(orchestrationDb, 'listSessionDispatchesForPresentation').mockImplementation(() => [])
vi.spyOn(orchestrationDb, 'listLegacyWorkerTerminalRecoveryRows').mockImplementation(() => [
{
dispatch_id: 'dispatch-wsl',
task_id: 'task-wsl',
dispatch_status: 'completed',
contract_version: 0,
assignee_handle: 'term_wsl_legacy',
assignee_pane_key: workerPaneKey,
process_incarnation: `pty-wsl-legacy:${incarnationId}`,
worker_state: 'ready',
worktree_id: TEST_WORKTREE_ID,
agent_terminal_handle: 'term_wsl_legacy'
}
])
runtime.setOrchestrationDb(orchestrationDb)
// Declare the scope parameter so mock.calls retains its type alongside the runtime deadline.
const listProcesses = vi.fn(async (_connectionId?: string | null) => [
{
@@ -1,3 +1,4 @@
import { AGENT_STATUS_STALE_AFTER_MS } from '../../../../../shared/agent-status-types'
import { parsePaneKey } from '../../../../../shared/stable-pane-id'
import type { DispatchContextRow } from '../../types'
import {
@@ -24,6 +25,122 @@ const ACTIVE_DISPATCH_BY_PANE_SUFFIX_SQL = `SELECT ${DISPATCH_CONTEXT_COLUMN_LIS
ORDER BY rowid DESC LIMIT 1`
const LATEST_DISPATCH_BY_HANDLE_SQL = `SELECT ${DISPATCH_CONTEXT_COLUMN_LIST} FROM dispatch_contexts WHERE assignee_handle = ? ORDER BY rowid DESC LIMIT 1`
function presentationAddressKey(column: string, address: string | null): string {
return `${column}:${address}`
}
/** Preserve the terminal projection's exact ISO/SQLite recency contract, including future dates. */
export function isRecentPresentationDispatch(dispatch: DispatchContextRow, now: number): boolean {
if (!dispatch.completed_at || dispatch.status === 'pending' || dispatch.status === 'dispatched') {
return false
}
const completedAt = Date.parse(
dispatch.completed_at.includes('T')
? dispatch.completed_at
: `${dispatch.completed_at.replace(' ', 'T')}Z`
)
return Number.isFinite(completedAt) && now - completedAt <= AGENT_STATUS_STALE_AFTER_MS
}
/** Active first, otherwise latest per address; an older eligible completion never resurfaces. */
export function listSessionDispatchesForPresentation(
this: OrchestrationDb,
now: number
): { dispatch: DispatchContextRow; order: number }[] {
const lowerBound = new Date(now - AGENT_STATUS_STALE_AFTER_MS - 86_400_000).toISOString()
const rawCandidates = this.db
.prepare(`
SELECT rowid AS presentation_order, ${DISPATCH_CONTEXT_COLUMN_LIST} FROM dispatch_contexts
INDEXED BY idx_dispatch_session_presentation
WHERE assignee_orca_session_id IS NOT NULL AND status IN ('pending', 'dispatched')
UNION ALL
SELECT rowid AS presentation_order, ${DISPATCH_CONTEXT_COLUMN_LIST} FROM dispatch_contexts
INDEXED BY idx_dispatch_session_presentation
WHERE assignee_orca_session_id IS NOT NULL
AND status IN ('completed', 'failed', 'circuit_broken') AND completed_at >= ?
`)
.all(lowerBound)
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: The complete schema-pinned Dispatch projection restores the persisted-row contract; the default integer wrapper normalizes rowid to a safe number.
const candidates = rawCandidates as (DispatchContextRow & { presentation_order: number })[]
const newestActiveOrderBySession = new Map<string, number>()
const selected = new Map<string, (typeof candidates)[number]>()
for (const candidate of candidates) {
// Include handled rows even when a newer non-public row later suppresses their address.
if (candidate.status === 'pending' || candidate.status === 'dispatched') {
const session = candidate.assignee_orca_session_id
if (session) {
newestActiveOrderBySession.set(
session,
Math.max(newestActiveOrderBySession.get(session) ?? 0, candidate.presentation_order)
)
}
}
const address = presentationAddressKey(
candidate.assignee_handle ? 'assignee_handle' : 'assignee_orca_session_id',
candidate.assignee_handle || candidate.assignee_orca_session_id
)
const previous = selected.get(address)
const active = candidate.status === 'pending' || candidate.status === 'dispatched'
const previousActive = previous?.status === 'pending' || previous?.status === 'dispatched'
if (
!previous ||
(active && !previousActive) ||
(active === previousActive && candidate.presentation_order > previous.presentation_order)
) {
selected.set(address, candidate)
}
}
const eligible = [...selected].filter(
([, candidate]) =>
candidate.status === 'pending' ||
candidate.status === 'dispatched' ||
isRecentPresentationDispatch(candidate, now)
)
const latestOrderByAddress = new Map<string, number>()
for (const [column, active] of [
['assignee_handle', true],
['assignee_handle', false],
['assignee_orca_session_id', false]
] as const) {
const addresses = eligible
.filter(
([, candidate]) =>
Boolean(candidate.assignee_handle) === (column === 'assignee_handle') &&
(candidate.status === 'pending' || candidate.status === 'dispatched') === active
)
.map(([, candidate]) => candidate[column])
if (addresses.length === 0) {
continue
}
// Batch native calls, retaining one equality-index seek per selected address.
const latest = this.db
.prepare(`SELECT requested.value AS address, (SELECT rowid AS n FROM dispatch_contexts
WHERE ${column} = requested.value
${active ? "AND status IN ('pending', 'dispatched')" : ''}
ORDER BY rowid DESC LIMIT 1) AS n FROM json_each(?) requested`)
.all(JSON.stringify(addresses))
for (const row of latest) {
if (typeof row.address === 'string' && typeof row.n === 'number') {
latestOrderByAddress.set(presentationAddressKey(column, row.address), row.n)
}
}
}
const result: { dispatch: DispatchContextRow; order: number }[] = []
for (const [address, candidate] of eligible) {
const { presentation_order, ...dispatch } = candidate
const active = dispatch.status === 'pending' || dispatch.status === 'dispatched'
const latest =
active && !candidate.assignee_handle
? newestActiveOrderBySession.get(candidate.assignee_orca_session_id ?? '')
: latestOrderByAddress.get(address)
if (latest !== presentation_order) {
continue
}
result.push({ dispatch, order: presentation_order })
}
return result
}
export function getActiveDispatchForTerminal(
this: OrchestrationDb,
handle: string,
@@ -168,6 +285,7 @@ export type DispatchLookupMethods = {
getActiveDispatchMailboxOwners: typeof getActiveDispatchMailboxOwners
isDispatchMessageSender: typeof isDispatchMessageSender
findActiveDispatchForAssignee: typeof findActiveDispatchForAssignee
listSessionDispatchesForPresentation: typeof listSessionDispatchesForPresentation
getLatestDispatchForTerminal: typeof getLatestDispatchForTerminal
}
@@ -179,6 +297,7 @@ export function attachDispatchLookup(ctor: { prototype: object }): void {
getActiveDispatchMailboxOwners,
isDispatchMessageSender,
findActiveDispatchForAssignee,
getLatestDispatchForTerminal
getLatestDispatchForTerminal,
listSessionDispatchesForPresentation
})
}
@@ -103,7 +103,8 @@ function buildProjection(db: OrchestrationDb): RuntimeAgentOrchestrationProjecti
processIncarnation: 'inc_1'
} as OrchestrationCompatibilityTerminalAuthority)
: null,
getAgentStatusSnapshot: () => []
getAgentStatusSnapshot: () => [],
getSessionRecords: () => null
})
}
@@ -62,6 +62,7 @@ function fixture(count = 1, version: 'fresh' | 'v41' = 'fresh') {
${DROP_REMOVED_WORK_TRIGGERS_SQL}
DROP INDEX idx_runs_coordinator_orca_session_id;
DROP INDEX idx_dispatch_assignee_orca_session_id;
DROP INDEX idx_dispatch_session_presentation;
DROP TRIGGER trg_runs_remember_coordinator_insert;
DROP TRIGGER trg_runs_remember_coordinator_update;
DROP TRIGGER trg_messages_route_coordinator_mail;
@@ -92,7 +93,19 @@ function fixture(count = 1, version: 'fresh' | 'v41' = 'fresh') {
.map((row) => row.name)
.toSorted()
).toEqual(DISPATCH_CONTEXT_COLUMNS.toSorted())
const priorVersion = writer.db.pragma('user_version', { simple: true })
expect(
writer.db
.prepare("SELECT name FROM sqlite_master WHERE name = 'idx_dispatch_session_presentation'")
.get()
).toBeDefined()
const reader = new OrchestrationDb(path)
expect(reader.db.pragma('user_version', { simple: true })).toBe(priorVersion)
expect(
reader.db
.prepare("SELECT name FROM sqlite_master WHERE name = 'idx_dispatch_session_presentation'")
.get()
).toBeDefined()
databases.push(reader)
return { writer, reader, run, entries }
}
@@ -7,6 +7,14 @@ export function hasColumn(this: OrchestrationDb, table: string, column: string):
}
export function createMailboxDeliveryIndexesIfPossible(this: OrchestrationDb): void {
if (
['assignee_orca_session_id', 'status', 'completed_at'].every((column) =>
this.hasColumn('dispatch_contexts', column)
)
) {
this.db.exec(`CREATE INDEX IF NOT EXISTS idx_dispatch_session_presentation
ON dispatch_contexts(status, completed_at) WHERE assignee_orca_session_id IS NOT NULL`)
}
if (this.hasColumn('deliveries', 'mailbox_handle')) {
this.db.exec(OUTSTANDING_MAILBOX_INDEX_SQL)
}
@@ -136,6 +136,7 @@ function stripOrcaSessionSchema(path: string, version: number): void {
raw.exec(`
${DROP_REMOVED_WORK_TRIGGERS_SQL}
DROP INDEX idx_runs_coordinator_orca_session_id;
DROP INDEX IF EXISTS idx_dispatch_session_presentation;
DROP INDEX idx_dispatch_assignee_orca_session_id;
DROP TRIGGER trg_runs_remember_coordinator_insert;
DROP TRIGGER trg_runs_remember_coordinator_update;
@@ -2,6 +2,10 @@
import type { AgentSessionConversationView } from '../../../shared/agent-session-conversation-view'
import { getStructuredAgentSessionHost } from '../../native-chat/agent-session-wire/structured-agent-session-registry'
import {
structuredAgentSessionPaneKey,
structuredAgentSessionTabId
} from '../../../shared/structured-agent-session-projection'
import { structuredWorkerHostScope } from '../structured-worker-identity'
export type AgentSessionRecordReader = {
@@ -56,6 +60,7 @@ export function resolveLineageRunningSession(
sessionId: string
): LineageRunningSession {
const lineage = [sessionId]
const visited = new Set(lineage)
if (!store) {
return {
kind: 'unverifiable',
@@ -86,13 +91,14 @@ export function resolveLineageRunningSession(
? { kind: 'here', ...running }
: { kind: 'other-host', ...running }
}
if (lineage.includes(next)) {
if (visited.has(next)) {
return {
kind: 'unverifiable',
reason: `The /clear lineage of structured session ${sessionId} loops back on itself.`,
lineage
}
}
visited.add(next)
lineage.push(next)
current = next
}
@@ -106,3 +112,45 @@ export function lineageLiveSession(
const running = resolveLineageRunningSession(store, sessionId)
return running.kind === 'unverifiable' ? null : running.record
}
/** Canonical host status keys; this build-local resolver shares successful suffixes and failed verdicts. */
export function createCanonicalSessionPaneResolver(
store: AgentSessionRecordReader | null
): (sessionId: string) => string {
const resolved = new Map<string, string | null>()
return (sessionId) => {
let current = sessionId
const path = new Set<string>()
let destination: string | null = null
for (;;) {
if (resolved.has(current)) {
destination = resolved.get(current) ?? null
break
}
if (path.has(current)) {
break
}
path.add(current)
let record: AgentSessionConversationView | null
try {
record = store?.getRecord(current) ?? null
} catch {
record = null
}
if (!record) {
break
}
const next = clearedInto(record)
if (!next) {
destination = current
break
}
current = next
}
for (const member of path) {
resolved.set(member, destination)
}
const id = destination ?? sessionId
return structuredAgentSessionPaneKey(structuredAgentSessionTabId(id), id)
}
}
@@ -0,0 +1,19 @@
import { vi } from 'vitest'
import { OrcaRuntimeService } from './orca-runtime'
import { RpcDispatcher } from './rpc/dispatcher'
import { WORKTREE_CATALOG_METHODS } from './rpc/methods/worktree-catalog-methods'
import type { RuntimeWorktreePsSummary } from '../../shared/runtime-types'
import type { RuntimeAgentLineageCatalogTestModule } from '../../shared/runtime-agent-lineage-consumer.test-fixture'
export function createLineageCatalogDispatcher(build: () => RuntimeWorktreePsSummary) {
const runtime = new OrcaRuntimeService()
vi.spyOn(runtime, 'getRuntimeId').mockReturnValue('lineage-test')
vi.spyOn(runtime, 'getWorktreePs').mockImplementation(async () => ({
worktrees: [build()],
totalCount: 1,
truncated: false
}))
return new RpcDispatcher({ runtime, methods: WORKTREE_CATALOG_METHODS })
}
export default { createLineageCatalogDispatcher } satisfies RuntimeAgentLineageCatalogTestModule
@@ -0,0 +1,128 @@
import { OrchestrationDb } from './orchestration/db'
import type { RuntimeAgentLineageTestModule } from '../../shared/runtime-agent-lineage-consumer.test-fixture'
import { RuntimeAgentOrchestrationProjection } from './runtime-agent-orchestration-projection'
import { attachRuntimeWorktreeAgentRows } from './runtime-worktree-agent-rows'
import type { RuntimeWorktreePsSummary } from '../../shared/runtime-types'
import type { RuntimeWorktreeAgentSource } from './runtime-worktree-agent-source'
import { testOrcaSessionId } from '../../shared/orca-session-address-test-fixture'
import {
structuredAgentSessionPaneKey,
structuredAgentSessionTabId
} from '../../shared/structured-agent-session-projection'
import {
mintStructuredWorkerHandle,
mintStructuredWorkerPaneKey,
structuredWorkerProcessIncarnation
} from './structured-worker-identity'
export const LINEAGE_PARENT = testOrcaSessionId('ca1f6c2e-8b3d-4e7a-9c15-0d2b6e8f1a37')
export const LINEAGE_CHILD = testOrcaSessionId('ce3b9d15-2c4a-4f86-a0b1-5c9e2d7f3b64')
export const canonicalChatRow = (id: string): string =>
structuredAgentSessionPaneKey(structuredAgentSessionTabId(id), id)
/** Production assignment projection and host row attachment; no preassembled agent output. */
export function publicLineageFixture(worktreeId = 'repo::/workspace') {
const db = new OrchestrationDb(':memory:')
const privateHandle = mintStructuredWorkerHandle()
const privatePane = mintStructuredWorkerPaneKey(LINEAGE_CHILD)
const run = db.createRun({
objective: 'lineage',
coordinatorHandle: null,
coordinatorPaneKey: null,
coordinatorOrcaSessionId: LINEAGE_PARENT
})
db.createDispatchContext({
taskId: db.createTask({ runId: run.id, spec: 'Build the worker result' }).id,
assigneeHandle: privateHandle,
assigneePaneKey: privatePane,
processIncarnation: structuredWorkerProcessIncarnation(LINEAGE_CHILD),
creator: { kind: 'system' },
maxDepth: 99
})
const projection = new RuntimeAgentOrchestrationProjection({
getDb: () => db,
getLeaves: () => [],
getPtys: () => [],
getSessionRecords: () => null,
paneOf: () => ({ tabId: null, paneKey: null, recordedAtGraphSequence: 0 }),
issueLeafHandle: () => '',
issuePtyHandle: () => '',
makePaneKey: () => '',
getWorktreeId: () => null,
getHandleForPaneKey: () => null,
getPaneKey: () => null,
getDispatchAuthority: () => null,
getAgentStatusSnapshot: () => []
})
const updatedAt = Date.now()
const build = (): RuntimeWorktreePsSummary => {
const row: RuntimeWorktreePsSummary = {
worktreeId,
workspaceKind: worktreeId.startsWith('folder:') ? 'folder-workspace' : 'git',
repoId: 'repo',
repo: 'repo',
path: '/workspace',
branch: 'main',
isArchived: false,
isMainWorktree: true,
hasHostSidebarActivity: false,
parentWorktreeId: null,
childWorktreeIds: [],
displayName: 'Workspace',
workspaceStatus: '',
sortOrder: 0,
linkedIssue: null,
linkedPR: null,
linkedLinearIssue: null,
linkedGitLabMR: null,
linkedGitLabIssue: null,
comment: '',
isPinned: false,
isActive: false,
unread: false,
liveTerminalCount: 0,
hasAttachedPty: false,
lastOutputAt: null,
preview: '',
status: 'inactive',
agents: []
}
const sources = new Map<string, RuntimeWorktreeAgentSource>(
[LINEAGE_PARENT, LINEAGE_CHILD].map((id) => [
canonicalChatRow(id),
{
paneKey: canonicalChatRow(id),
connectionId: null,
worktreeId,
state: 'working',
agentType: 'codex',
prompt: id === LINEAGE_PARENT ? 'Coordinate work' : 'Implement work',
lastAssistantMessage: null,
toolName: null,
toolInput: null,
interrupted: false,
stateStartedAt: 1,
updatedAt,
structuredHost: 'owned'
}
])
)
const summaries = new Map([[worktreeId, row]])
attachRuntimeWorktreeAgentRows({
summaries,
rowSources: sources,
terminalTitleEvidenceByWorktreeId: new Map(),
orchestrationByPaneKey: projection.buildByPaneKey(),
getSummary: (id) => summaries.get(id) ?? null
})
return row
}
return { db, projection, build, privateHandle, privatePane, run }
}
export default {
publicLineageFixture,
canonicalChatRow,
LINEAGE_PARENT,
LINEAGE_CHILD
} satisfies RuntimeAgentLineageTestModule
@@ -0,0 +1,240 @@
import { mkdtempSync, rmSync } from 'node:fs'
import { execFileSync } from 'node:child_process'
import { hostname, tmpdir } from 'node:os'
import { join } from 'node:path'
import { expect, vi } from 'vitest'
import { OrchestrationDb } from './orchestration/db'
import { formatOrcaSessionAddress, type OrcaSessionId } from '../../shared/orca-session-address'
import { testOrcaSessionId } from '../../shared/orca-session-address-test-fixture'
import {
structuredAgentSessionPaneKey,
structuredAgentSessionTabId
} from '../../shared/structured-agent-session-projection'
import {
installSqlVisitCounters,
traceDispatchPredicateVisits,
latestStatementMetrics,
dispatchQueryPlans,
seedCoarsePresentationDispatches
} from './dispatch-predicate-visits.test-fixture'
export function benchmarkPresentationCorpus(
corpus: {
nullAddress: boolean
history: number
terminalHistory: number
attentionFacts: number
parentSessionId: OrcaSessionId
},
build: (
db: OrchestrationDb
) => Record<string, { parentPaneKey?: string | null; dispatchId: string }> | undefined
) {
const { nullAddress, history, terminalHistory, attentionFacts, parentSessionId } = corpus
const revision = execFileSync('git', ['rev-parse', 'HEAD'], { encoding: 'utf8' }).trim()
const now = Date.parse('2026-10-27T12:00:00Z')
const clock = vi.spyOn(Date, 'now').mockReturnValue(now)
const directory = mkdtempSync(join(tmpdir(), 'orca-lineage-benchmark-'))
const path = join(directory, 'orchestration.sqlite')
let db = new OrchestrationDb(path)
let native: ReturnType<typeof installSqlVisitCounters> | undefined
let trace: ReturnType<typeof traceDispatchPredicateVisits> | undefined
try {
const run = db.createRun({
objective: 'benchmark',
coordinatorHandle: null,
coordinatorPaneKey: null,
coordinatorOrcaSessionId: parentSessionId
})
const expected = new Map<string, string>()
for (let i = 0; i < 20; i++) {
const session = testOrcaSessionId(`00000000-0000-4000-8000-${String(i).padStart(12, '0')}`)
const dispatch = db.createDispatchContext({
taskId: db.createTask({ runId: run.id, spec: 'active' }).id,
assigneeHandle: formatOrcaSessionAddress(session),
creator: { kind: 'system' },
maxDepth: 99
})
expected.set(
structuredAgentSessionPaneKey(structuredAgentSessionTabId(session), session),
dispatch.id
)
}
if (nullAddress) {
db.db.exec(
"UPDATE dispatch_contexts SET assignee_handle = NULL, assignee_pane_key = NULL WHERE status IN ('pending', 'dispatched')"
)
}
const task = db.createTask({ runId: run.id, spec: 'history' })
const insert = db.db.prepare(`INSERT INTO dispatch_contexts
(id, run_id, task_id, assignee_handle, assignee_orca_session_id, status, completed_at)
WITH RECURSIVE seq(n) AS (VALUES(1) UNION ALL SELECT n+1 FROM seq WHERE n < ?)
SELECT ? || n, ?, ?, CASE WHEN ? THEN printf('orca_session_id:00000000-0000-4000-8000-%012d', (n-1) % 20) ELSE 'terminal-address-' || n END,
CASE WHEN ? THEN CASE WHEN ? THEN printf('00000000-0000-4000-8000-%012d', (n-1) % 20) ELSE 'session-' || n END ELSE NULL END,
'completed', '2020-01-01T00:00:00Z' FROM seq`)
insert.run(history, 'session-history-', run.id, task.id, 1, 1, nullAddress ? 1 : 0)
if (terminalHistory) {
insert.run(terminalHistory, 'terminal-history-', run.id, task.id, 0, 0, 0)
}
const active = db.db
.prepare(
"SELECT id, task_id FROM dispatch_contexts WHERE status IN ('pending', 'dispatched') ORDER BY rowid"
)
.all()
expect(active.map((row) => row.id)).toEqual([...expected.values()])
const insertFact = db.db.prepare(
`INSERT INTO attempt_observation_facts(id, dispatch_id, task_id, sequence, authority_id, authority_clock, facet, payload, home_received_at) VALUES (?, ?, ?, ?, 'home', 'home', 'process_turn', '{"process":"running","turn":"working"}', ?)`
)
for (let i = 0; i < attentionFacts; i++) {
const row = active[i % active.length]
if (typeof row?.id !== 'string' || typeof row.task_id !== 'string') {
throw new Error('Missing benchmark Dispatch')
}
insertFact.run(
`observation-${i}`,
row.id,
row.task_id,
Math.floor(i / active.length),
1_800_000_000_000 + i
)
}
const sqlite = db.db.prepare('SELECT sqlite_version() AS version').get()?.version
db.db.exec('DROP INDEX idx_dispatch_session_presentation')
const first = performance.now()
db.createMailboxDeliveryIndexesIfPossible()
const indexHelperMs = performance.now() - first
db.db.exec('DROP INDEX idx_dispatch_session_presentation')
db.close()
const openStarted = performance.now()
db = new OrchestrationDb(path)
const reopenWithIndexCreationMs = performance.now() - openStarted
let candidateVisits = 0,
latestVisits = 0,
observationVisits = 0
native = installSqlVisitCounters({
lineage_bench_visit: () => {
candidateVisits++
return 1
},
lineage_latest_visit: () => {
latestVisits++
return 1
},
lineage_observation_visit: () => {
observationVisits++
return 1
}
})
trace = traceDispatchPredicateVisits(db.db, {
candidate: 'lineage_bench_visit',
latest: 'lineage_latest_visit',
observation: 'lineage_observation_visit'
})
let plans: ReturnType<typeof dispatchQueryPlans> | undefined
let previousCoarse = 0
const sweep =
!nullAddress && history === 10_000 && terminalHistory === 0 && attentionFacts === 0
for (const coarseOnly of sweep ? [0, 1_000, 10_000] : [0]) {
seedCoarsePresentationDispatches(
db,
run.id,
coarseOnly - previousCoarse,
now,
`coarse-${coarseOnly}`
)
previousCoarse = coarseOnly
trace.mockClear()
trace.executions.length = 0
native.mockClear()
candidateVisits = 0
latestVisits = 0
observationVisits = 0
const start = performance.now()
const output = build(db)
const buildMs = performance.now() - start
const production = {
cachedPrepareCalls: trace.mock.calls.length,
executedStatements: trace.executions.length,
nativeCompilations: native.mock.calls.length,
latest: latestStatementMetrics(trace, native),
candidateVisits,
latestVisits,
observationVisits
}
expect(production.latest).toEqual({
cachedPrepareCalls: nullAddress ? 0 : 1,
executedStatements: nullAddress ? 0 : 1,
nativeCompilations: nullAddress || coarseOnly ? 0 : 1,
addressEntries: nullAddress ? 0 : 20,
returnedVerificationRows: nullAddress ? 0 : 20
})
expect(
trace.executions.filter(
({ query }) =>
query.includes('rowid AS n') &&
query.includes('assignee_orca_session_id') &&
query.includes("AND status IN ('pending', 'dispatched')")
)
).toHaveLength(0)
expect(Object.keys(output ?? {}).sort()).toEqual([...expected.keys()].sort())
for (const [key, dispatchId] of expected) {
expect(output?.[key]).toMatchObject({
dispatchId,
parentPaneKey: structuredAgentSessionPaneKey(
structuredAgentSessionTabId(parentSessionId),
parentSessionId
)
})
}
expect(candidateVisits).toBe(20 + coarseOnly)
expect(latestVisits).toBe(nullAddress ? 0 : 20)
expect(observationVisits).toBe(attentionFacts)
if (!plans) {
plans = dispatchQueryPlans(db.db, trace)
}
const planText = JSON.stringify(plans)
expect(planText).not.toMatch(/SCAN dispatch_contexts|USE TEMP B-TREE/)
expect(planText).toContain('idx_dispatch_session_presentation (status=? AND completed_at>?)')
if (!nullAddress) {
expect(planText).toContain('idx_dispatch_active_assignee_handle (assignee_handle=?)')
}
console.log(
'LINEAGE_BENCH_ENVIRONMENT_EVIDENCE',
JSON.stringify({
host: hostname(),
node: process.version,
sqlite,
platform: process.platform,
arch: process.arch,
checkout: process.cwd(),
revision,
timingScope: 'instrumented production build; includes predicate/tracing overhead',
corpus,
coarseOnly,
Q: 20 + coarseOnly,
E: nullAddress ? 0 : 20,
B: nullAddress ? 0 : 1,
cachePhase: coarseOnly
? 'warm statements after coarse-only inserts'
: 'first instrumented build after constructor reopen',
indexHelperMs,
reopenWithIndexCreationMs,
buildMs,
production,
diagnostic: {
cachedPrepareCalls: trace.mock.calls.length - production.cachedPrepareCalls,
executedStatements: trace.executions.length - production.executedStatements,
nativeCompilations: native.mock.calls.length - production.nativeCompilations
},
plans
})
)
}
} finally {
trace?.mockRestore()
native?.mockRestore()
clock.mockRestore()
db.close()
rmSync(directory, { recursive: true, force: true })
}
}
@@ -0,0 +1,778 @@
import { mkdtempSync, rmSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { seedTestAgentSessionRecordStore } from './agent-session-record-store-test-harness'
import { closeTestJournalHostDatabase } from '../native-chat/agent-session-journal/journal-host-database-test-support'
import {
openAgentSessionRecordStoreOnce,
releaseAgentSessionRecordStore
} from './agent-session-record-store-slot'
import { recordingStructuredAgentSessionLogger } from '../native-chat/agent-session-wire/structured-agent-session-logger-test-support'
import { OrcaRuntimeService } from './orca-runtime'
import './rpc/unused-default-rpc-methods.test-fixture'
import { afterEach, describe, expect, it, vi } from 'vitest'
import { agentSessionConversationView } from '../../shared/agent-session-conversation-view'
import {
createSessionCallerHarness,
orchestrationRequest,
resultOf,
idOf,
SESSION_X,
SESSION_Y,
sessionRecord
} from './rpc/orchestration-session-caller-test-fixture'
import { formatOrcaSessionAddress } from '../../shared/orca-session-address'
import type { AgentSessionRecordReader } from './orchestration/structured-session-lineage'
const hostRef = vi.hoisted((): { current: unknown } => ({ current: null }))
vi.mock('../native-chat/agent-session-wire/structured-agent-session-registry', () => ({
getStructuredAgentSessionHost: () => hostRef.current
}))
import { testOrcaSessionId } from '../../shared/orca-session-address-test-fixture'
import {
structuredAgentSessionPaneKey,
structuredAgentSessionTabId
} from '../../shared/structured-agent-session-projection'
import { RuntimeAgentOrchestrationProjection } from './runtime-agent-orchestration-projection'
import {
installSqlVisitCounters,
latestStatementMetrics,
dispatchQueryPlans,
seedCoarsePresentationDispatches,
traceDispatchPredicateVisits
} from './dispatch-predicate-visits.test-fixture'
import { benchmarkPresentationCorpus } from './runtime-agent-orchestration-benchmark.test-fixture'
import { MIRROR_LEAVES_STEP_1 } from './runtime-leaf-record-projection.test-fixture'
import type { RuntimeLeafRecord } from './runtime-terminal-state-records'
import { OrchestrationDb } from './orchestration/db'
import {
mintStructuredWorkerHandle,
mintStructuredWorkerPaneKey,
structuredWorkerProcessIncarnation
} from './structured-worker-identity'
const COORDINATOR_CHAT = testOrcaSessionId('1b6f0c3a-7d2e-4a91-8c55-2e9d4b7a0f13')
const WORKER_CHAT = testOrcaSessionId('9c3e5a17-4b2d-4f60-8e91-0d7a6c2b5e48')
const TERMINAL_WORKER_HANDLE = 'term_worker'
const TERMINAL_WORKER_PANE = 'tab_w:11111111-1111-4111-8111-111111111111'
afterEach(() => vi.restoreAllMocks())
function chatRow(sessionId: string): string {
return structuredAgentSessionPaneKey(structuredAgentSessionTabId(sessionId), sessionId)
}
describe('RuntimeAgentOrchestrationProjection chat lineage', () => {
let db: OrchestrationDb
afterEach(() => {
db?.close()
hostRef.current = null
vi.restoreAllMocks()
})
it('nests chat and terminal workers under the chat that dispatched them', () => {
db = new OrchestrationDb(':memory:')
const run = db.createRun({
objective: 'chat run',
coordinatorHandle: null,
coordinatorPaneKey: null,
coordinatorOrcaSessionId: COORDINATOR_CHAT
})
const chatWorker = {
handle: mintStructuredWorkerHandle(),
sessionId: WORKER_CHAT,
paneKey: mintStructuredWorkerPaneKey(WORKER_CHAT)
}
const creator = { kind: 'session', orcaSessionId: COORDINATOR_CHAT } as const
db.createDispatchContext({
taskId: db.createTask({ runId: run.id, spec: 'chat worker' }).id,
assigneeHandle: chatWorker.handle,
assigneePaneKey: chatWorker.paneKey,
processIncarnation: structuredWorkerProcessIncarnation(WORKER_CHAT),
creator,
maxDepth: Number.MAX_SAFE_INTEGER
})
db.createDispatchContext({
taskId: db.createTask({ runId: run.id, spec: 'terminal worker' }).id,
assigneeHandle: TERMINAL_WORKER_HANDLE,
assigneePaneKey: TERMINAL_WORKER_PANE,
creator,
maxDepth: Number.MAX_SAFE_INTEGER
})
const leaf: RuntimeLeafRecord = { ...MIRROR_LEAVES_STEP_1[0], ptyId: 'pty_w' }
const projection = new RuntimeAgentOrchestrationProjection({
getDb: () => db,
getLeaves: () => [leaf],
getPtys: () => [],
paneOf: () => ({ tabId: null, paneKey: null, recordedAtGraphSequence: 0 }),
issueLeafHandle: () => TERMINAL_WORKER_HANDLE,
issuePtyHandle: () => '',
makePaneKey: () => TERMINAL_WORKER_PANE,
getWorktreeId: () => null,
getHandleForPaneKey: () => null,
getPaneKey: () => null,
getDispatchAuthority: () => null,
getAgentStatusSnapshot: () => [],
getSessionRecords: () => null
})
const contexts = projection.buildByPaneKey()
expect(contexts?.[chatRow(WORKER_CHAT)]?.parentPaneKey).toBe(chatRow(COORDINATOR_CHAT))
expect(contexts?.[TERMINAL_WORKER_PANE]?.parentPaneKey).toBe(chatRow(COORDINATOR_CHAT))
// The minted pane key authorizes the worker's mailbox; it must never reach a renderer.
expect(JSON.stringify(contexts)).not.toContain(chatWorker.paneKey)
expect(JSON.stringify(contexts)).not.toContain(chatWorker.handle)
})
})
function projectionFor(db: OrchestrationDb, records: AgentSessionRecordReader | null = null) {
return new RuntimeAgentOrchestrationProjection({
getDb: () => db,
getLeaves: () => [],
getPtys: () => [],
paneOf: () => ({ tabId: null, paneKey: null, recordedAtGraphSequence: 0 }),
issueLeafHandle: () => '',
issuePtyHandle: () => '',
makePaneKey: () => '',
getWorktreeId: () => null,
getHandleForPaneKey: () => null,
getPaneKey: () => null,
getDispatchAuthority: () => null,
getAgentStatusSnapshot: () => [],
getSessionRecords: () => records
})
}
it('publishes ordinary RPC assignments without registering display authority and honors current Run generations', async () => {
const h = createSessionCallerHarness(hostRef)
try {
const runId = idOf(
resultOf(
await h.dispatch(
orchestrationRequest(
'orchestration.runCreate',
{ objective: 'public lineage' },
{ sessionId: SESSION_X }
)
)
).run
)
const task = h.db.createTask({ runId, spec: 'existing chat task' })
const response = await h.dispatch(
orchestrationRequest(
'orchestration.dispatch',
{ task: task.id, to: formatOrcaSessionAddress(SESSION_Y) },
{ sessionId: SESSION_X }
)
)
const dispatchId = idOf(resultOf(response).dispatch)
const projection = h.runtime['agentOrchestrationProjection']
expect(projection.buildByPaneKey()?.[chatRow(SESSION_Y)]).toMatchObject({
dispatchId,
parentPaneKey: chatRow(SESSION_X),
taskTitle: 'existing chat task'
})
h.db.db
.prepare('UPDATE runs SET coordinator_orca_session_id = ? WHERE id = ?')
.run(COORDINATOR_CHAT, runId)
expect(projection.buildByPaneKey()?.[chatRow(SESSION_Y)]?.parentPaneKey).toBe(
chatRow(SESSION_X)
)
h.db.db
.prepare('UPDATE runs SET coordinator_orca_session_id = ? WHERE id = ?')
.run(SESSION_X, runId)
// A callback does not have to populate mailbox authority before the public relationship exists.
h.runtime.onStructuredSessionStatusForMail({ sessionId: SESSION_Y, status: 'attention' })
expect(projection.buildByPaneKey()?.[chatRow(SESSION_Y)]?.parentPaneKey).toBe(
chatRow(SESSION_X)
)
h.db.db
.prepare('UPDATE dispatch_contexts SET creator_orca_session_id = NULL WHERE id = ?')
.run(dispatchId)
const terminal = 'offline:11111111-1111-4111-8111-111111111111'
h.db.db
.prepare(
'UPDATE runs SET coordinator_handle = ?, coordinator_pane_key = ?, consumer_generation = consumer_generation + 1 WHERE id = ?'
)
.run('term_old_writer', terminal, runId)
expect(projection.buildByPaneKey()?.[chatRow(SESSION_Y)]?.parentPaneKey).toBe(terminal)
h.db.db
.prepare(
'UPDATE runs SET coordinator_orca_session_id_generation = consumer_generation WHERE id = ?'
)
.run(runId)
expect(projection.buildByPaneKey()?.[chatRow(SESSION_Y)]?.parentPaneKey).toBe(
chatRow(SESSION_X)
)
h.db.db
.prepare(
'UPDATE runs SET coordinator_orca_session_id_generation = NULL, coordinator_handle = ?, coordinator_pane_key = ? WHERE id = ?'
)
.run(mintStructuredWorkerHandle(), mintStructuredWorkerPaneKey(SESSION_X), runId)
expect(projection.buildByPaneKey()?.[chatRow(SESSION_Y)]?.parentPaneKey).toBeUndefined()
expect(JSON.stringify(projection.buildByPaneKey())).not.toContain('structworker_')
} finally {
h.close()
}
})
it.each([20, 200])(
'shares forward lineage and DB/attention work across %i workers; each build rederives facts',
(n) => {
const now = Date.parse('2026-10-27T12:00:00Z')
vi.spyOn(Date, 'now').mockReturnValue(now)
const db = new OrchestrationDb(':memory:')
try {
const run = db.createRun({
objective: 'shared ancestry',
coordinatorHandle: null,
coordinatorPaneKey: null,
coordinatorOrcaSessionId: SESSION_X
})
for (let i = 0; i < n; i++) {
db.createDispatchContext({
taskId: db.createTask({ runId: run.id, spec: 'shared task' }).id,
assigneeHandle: `ordinary-${i}`,
creator: { kind: 'session', orcaSessionId: SESSION_X },
maxDepth: 9999
})
db.db
.prepare(
'UPDATE dispatch_contexts SET assignee_orca_session_id = ? WHERE assignee_handle = ?'
)
.run(`worker-${i}`, `ordinary-${i}`)
}
seedCoarsePresentationDispatches(db, run.id, 2 * n, now)
const historyTask = db.createTask({ runId: run.id, spec: 'newer inactive handle history' })
const insertHistory = db.db.prepare(`INSERT INTO dispatch_contexts
(id, run_id, task_id, assignee_handle, status, completed_at)
WITH RECURSIVE seq(n) AS (VALUES(1) UNION ALL SELECT n+1 FROM seq WHERE n < ?)
SELECT ? || n, ?, ?, ?, 'completed', '2020-01-01T00:00:00Z' FROM seq`)
for (let i = 0; i < n; i++) {
insertHistory.run(n, `expired-handled-${i}-`, run.id, historyTask.id, `ordinary-${i}`)
}
let endpoint = n
const read = vi.fn((id: string): ReturnType<typeof agentSessionConversationView> | null => {
const record = sessionRecord(id)
const index = id === SESSION_X ? 0 : id.startsWith('edge-') ? Number(id.slice(5)) : endpoint
return agentSessionConversationView(
index < endpoint
? {
...record,
conversationCommand: {
command: 'clear',
runtimeFence: record.lease.runtimeFence,
operationId: 'clear',
callerKey: 'test',
phase: 'committed',
state: 'completed',
replacementSessionId: `edge-${index + 1}`
}
}
: record
)
})
const projection = projectionFor(db, { getRecord: read, listRecords: () => [] })
const tasks = vi.spyOn(db, 'getTask')
const runs = vi.spyOn(db, 'getRun')
const batch = vi.spyOn(db, 'getWorkerAttentionFactsForDispatches')
const individual = vi.spyOn(db, 'getWorkerAttentionFacts')
const roster = vi.spyOn(db, 'listSessionDispatchesForPresentation')
let candidateVisits = 0
let latestVisits = 0
const native = installSqlVisitCounters({
lineage_candidate_visit: () => {
candidateVisits++
return 1
},
lineage_latest_visit: () => {
latestVisits++
return 1
}
})
const sql = traceDispatchPredicateVisits(db.db, {
candidate: 'lineage_candidate_visit',
latest: 'lineage_latest_visit'
})
const output = projection.buildByPaneKey()
expect(Object.keys(output ?? {})).toHaveLength(n)
expect(
Object.values(output ?? {}).every(
(context) => context.parentPaneKey === chatRow(`edge-${n}`)
)
).toBe(true)
expect(read).toHaveBeenCalledTimes(n + n + 1)
expect(tasks).toHaveBeenCalledTimes(n)
expect(runs).toHaveBeenCalledTimes(1)
expect(roster).toHaveBeenCalledTimes(1)
expect(candidateVisits).toBe(3 * n)
expect(latestVisits).toBe(n)
expect(latestStatementMetrics(sql, native)).toEqual({
cachedPrepareCalls: 1,
executedStatements: 1,
nativeCompilations: 1,
addressEntries: n,
returnedVerificationRows: n
})
expect(
sql.mock.calls.filter(([query]) => query.includes('d.id AS dispatch_id'))
).toHaveLength(1)
expect(
sql.mock.calls.filter(([query]) => query.includes('FROM attempt_observation_facts'))
).toHaveLength(1)
expect(batch).toHaveBeenCalledTimes(1)
expect(individual).not.toHaveBeenCalled()
endpoint++
read.mockClear()
expect(
Object.values(projection.buildByPaneKey() ?? {}).every(
(context) => context.parentPaneKey === chatRow(`edge-${endpoint}`)
)
).toBe(true)
expect(read.mock.calls.length).toBeLessThanOrEqual(n + endpoint + 1)
expect(latestStatementMetrics(sql, native)).toEqual({
cachedPrepareCalls: 2,
executedStatements: 2,
nativeCompilations: 1,
addressEntries: 2 * n,
returnedVerificationRows: 2 * n
})
expect(candidateVisits).toBe(6 * n)
expect(latestVisits).toBe(2 * n)
const plans = dispatchQueryPlans(db.db, sql)
expect(JSON.stringify(plans)).toContain(
'idx_dispatch_active_assignee_handle (assignee_handle=?)'
)
expect(JSON.stringify(plans)).not.toMatch(/SCAN dispatch_contexts|USE TEMP B-TREE/)
for (const failure of ['missing', 'error', 'cycle', 'prepared']) {
read.mockImplementation((id) => {
if (failure === 'error') {
throw new Error('unreadable')
}
if (failure === 'missing') {
return null
}
const record = sessionRecord(id)
return agentSessionConversationView({
...record,
conversationCommand: {
command: 'clear',
runtimeFence: record.lease.runtimeFence,
operationId: 'cycle',
callerKey: 'test',
phase: failure === 'prepared' ? 'prepared' : 'committed',
state: 'completed',
replacementSessionId: SESSION_X
}
})
})
expect(
Object.values(projection.buildByPaneKey() ?? {}).every(
(context) => context.parentPaneKey === chatRow(SESSION_X)
)
).toBe(true)
}
db.db
.prepare(
"UPDATE dispatch_contexts SET status = 'completed', completed_at = ? WHERE status IN ('pending', 'dispatched')"
)
.run(new Date(now - 7_200_000).toISOString())
sql.mockClear()
sql.executions.length = 0
native.mockClear()
candidateVisits = 0
latestVisits = 0
read.mockClear()
expect(projection.buildByPaneKey()).toBeUndefined()
expect(candidateVisits).toBe(3 * n)
expect(latestVisits).toBe(0)
expect(read).not.toHaveBeenCalled()
expect(latestStatementMetrics(sql, native)).toEqual({
cachedPrepareCalls: 0,
executedStatements: 0,
nativeCompilations: 0,
addressEntries: 0,
returnedVerificationRows: 0
})
} finally {
db.close()
}
}
)
it.each([20, 200])(
'derives newest active null-address sessions from one complete batch at %i identities',
(n) => {
const db = new OrchestrationDb(':memory:')
try {
const run = db.createRun({
objective: 'null-address history',
coordinatorHandle: null,
coordinatorPaneKey: null,
coordinatorOrcaSessionId: SESSION_X
})
const task = db.createTask({ runId: run.id, spec: 'null-address selection' })
const insert = db.db.prepare(`INSERT INTO dispatch_contexts
(id, run_id, task_id, assignee_orca_session_id, status, completed_at)
WITH RECURSIVE seq(n) AS (VALUES(1) UNION ALL SELECT n+1 FROM seq WHERE n < ?)
SELECT ? || n, ?, ?, ?, 'completed', '2020-01-01T00:00:00Z' FROM seq`)
for (let i = 0; i < n; i++) {
const dispatch = db.createDispatchContext({
taskId: db.createTask({ runId: run.id, spec: 'active selection' }).id,
assigneeHandle: `old-${i}`,
creator: { kind: 'system' },
maxDepth: 99
})
db.db
.prepare(
'UPDATE dispatch_contexts SET assignee_handle = NULL, assignee_pane_key = NULL, assignee_orca_session_id = ? WHERE id = ?'
)
.run(`null-session-${i}`, dispatch.id)
insert.run(n, `expired-${i}-`, run.id, task.id, `null-session-${i}`)
}
let candidates = 0
installSqlVisitCounters({
null_candidate_visit: () => {
candidates++
return 1
}
})
const trace = traceDispatchPredicateVisits(db.db, { candidate: 'null_candidate_visit' })
const roster = vi.spyOn(db, 'listSessionDispatchesForPresentation')
const projection = projectionFor(db)
const output = projection.buildByPaneKey() ?? {}
expect(Object.keys(output)).toHaveLength(n)
for (let i = 0; i < n; i++) {
expect(output[chatRow(`null-session-${i}`)]?.parentPaneKey).toBe(chatRow(SESSION_X))
}
expect(roster).toHaveBeenCalledTimes(1)
expect(candidates).toBe(n)
expect(
trace.mock.calls.filter(
([q]) =>
q.includes('rowid AS n') &&
q.includes('assignee_orca_session_id') &&
q.includes("AND status IN ('pending', 'dispatched')")
)
).toHaveLength(0)
expect(
trace.mock.calls.filter(([q]) => q.includes('idx_dispatch_session_presentation'))
).toHaveLength(1)
trace.mockRestore()
// The newer handled active row contributes to the session maximum even if its address is suppressed.
const handled = db.createDispatchContext({
taskId: db.createTask({ runId: run.id, spec: 'active selection' }).id,
assigneeHandle: 'new-handled',
creator: { kind: 'system' },
maxDepth: 99
})
db.db
.prepare('UPDATE dispatch_contexts SET assignee_orca_session_id = ? WHERE id = ?')
.run('null-session-0', handled.id)
const newer = db.createDispatchContext({
taskId: db.createTask({ runId: run.id, spec: 'active selection' }).id,
assigneeHandle: 'newer-suppression',
creator: { kind: 'system' },
maxDepth: 99
})
db.db
.prepare('UPDATE dispatch_contexts SET assignee_handle = ? WHERE id = ?')
.run('new-handled', newer.id)
const suppressed = projection.buildByPaneKey() ?? {}
expect(suppressed[chatRow('null-session-0')]).toBeUndefined()
expect(Object.keys(suppressed)).toHaveLength(n - 1)
} finally {
db.close()
}
}
)
it('selects indexed active/latest per address with exact ISO/SQLite recency and deterministic public collisions', () => {
const db = new OrchestrationDb(':memory:')
const now = Date.parse('2026-10-27T00:00:10.000Z')
try {
const emptyRoster = vi.spyOn(db, 'listSessionDispatchesForPresentation')
const emptyRead = vi.fn(() => null)
expect(
projectionFor(db, { getRecord: emptyRead, listRecords: () => [] }).buildByPaneKey()
).toBeUndefined()
expect(emptyRoster).not.toHaveBeenCalled()
expect(emptyRead).not.toHaveBeenCalled()
const version = db.db.pragma('user_version', { simple: true })
const run = db.createRun({
objective: 'selection',
coordinatorHandle: 'term_c',
coordinatorPaneKey: 'c:11111111-1111-4111-8111-111111111111'
})
let counter = 0
const add = (
handle: string | null,
session: string | null,
status: string,
completed: string | null
) => {
const row = db.createDispatchContext({
taskId: db.createTask({ runId: run.id, spec: 'selection' }).id,
assigneeHandle: `${handle}-${counter++}`,
creator: { kind: 'system' },
maxDepth: 99
})
db.db
.prepare(
'UPDATE dispatch_contexts SET assignee_handle = ?, assignee_orca_session_id = ?, status = ?, completed_at = ? WHERE id = ?'
)
.run(handle, session, status, completed, row.id)
return row.id
}
add('suppressed', SESSION_X, 'completed', '2026-10-27T00:00:00Z')
add('suppressed', null, 'failed', null)
add('active-hidden', 'hidden', 'pending', null)
add('active-hidden', null, 'pending', null)
add('newer-expired', 'expired-hidden', 'completed', '2026-10-27T00:00:00Z')
add('newer-expired', 'expired-hidden', 'completed', '2020-01-01T00:00:00Z')
add('newer-invalid', 'invalid-hidden', 'completed', '2026-10-27T00:00:00Z')
add('newer-invalid', 'invalid-hidden', 'completed', 'zzzz')
const unhandledRecent = add('', 'session-recent', 'completed', '2026-10-27T00:00:00Z')
const collisionHandle = add(
'shared-address',
'handle-namespace-session',
'completed',
'2026-10-27T00:00:00Z'
)
const collisionSession = add(null, 'shared-address', 'completed', '2026-10-27T00:00:00Z')
const nullRecent = add(null, 'null-recent', 'completed', '2026-10-27T00:00:00Z')
const boundary = add(
'exact-boundary',
'boundary',
'completed',
new Date(now - 1_800_000).toISOString()
)
add('stale-boundary', 'stale-boundary', 'completed', new Date(now - 1_800_001).toISOString())
add(null, 'suppressed-session', 'completed', '2026-10-27T00:00:00Z')
add('suppressed-session-handle', 'suppressed-session', 'completed', '2026-10-27T00:00:00Z')
add('suppressed-session-handle', null, 'completed', '2026-10-27T00:00:00Z')
const sqlite = add('sqlite', SESSION_Y, 'completed', '2026-10-26 23:59:59')
add('expired', 'expired', 'completed', '2020-01-01T00:00:00Z')
add('invalid', 'invalid', 'completed', 'zzzz')
add('missing', 'missing', 'failed', null)
const future = add('future', 'future', 'failed', '2099-01-01T00:00:00Z')
const active = add('active', SESSION_Y, 'dispatched', null)
add('same-address', 'active-old', 'pending', null)
const newest = add('same-address', 'active-new', 'pending', null)
const native = installSqlVisitCounters({
selection_candidate: () => 1,
selection_latest: () => 1
})
const trace = traceDispatchPredicateVisits(db.db, {
candidate: 'selection_candidate',
latest: 'selection_latest'
})
expect(db.listSessionDispatchesForPresentation(now).map((row) => row.dispatch.id)).toEqual([
active,
newest,
sqlite,
boundary,
unhandledRecent,
collisionHandle,
collisionSession,
nullRecent,
future
])
const metrics = latestStatementMetrics(trace, native)
expect(metrics.cachedPrepareCalls).toBe(3)
expect(metrics.executedStatements).toBe(3)
expect(metrics.nativeCompilations).toBe(3)
expect(metrics.addressEntries).toBe(metrics.returnedVerificationRows)
const latestExecutions = trace.executions.filter(({ query }) =>
query.includes('rowid AS n FROM dispatch_contexts')
)
expect(new Set(latestExecutions.map(({ query }) => query)).size).toBe(3)
expect(latestExecutions.map(({ parameters }) => JSON.parse(String(parameters[0])))).toEqual([
['active', 'active-hidden', 'same-address'],
[
'sqlite',
'exact-boundary',
'suppressed',
'newer-expired',
'shared-address',
'suppressed-session-handle',
'future'
],
['session-recent', 'shared-address', 'null-recent', 'suppressed-session']
])
const plans = dispatchQueryPlans(db.db, trace)
const planText = JSON.stringify(plans)
for (const index of [
'idx_dispatch_active_assignee_handle (assignee_handle=?)',
'idx_dispatch_assignee_handle (assignee_handle=?)',
'idx_dispatch_assignee_orca_session_id (assignee_orca_session_id=?)',
'idx_dispatch_session_presentation (status=? AND completed_at>?)'
]) {
expect(planText).toContain(index)
}
expect(planText).not.toMatch(/SCAN dispatch_contexts|USE TEMP B-TREE/)
trace.mockRestore()
add('', 'session-recent', 'completed', 'zzzz')
expect(
db
.listSessionDispatchesForPresentation(now)
.some((row) => row.dispatch.id === unhandledRecent)
).toBe(false)
const noHandle = add('null-handle', 'null-address', 'dispatched', null)
db.db.prepare('UPDATE dispatch_contexts SET assignee_handle = NULL WHERE id = ?').run(noHandle)
expect(
db.listSessionDispatchesForPresentation(now).some((row) => row.dispatch.id === noHandle)
).toBe(true)
const columns = db.db.prepare('PRAGMA index_info(idx_dispatch_session_presentation)').all()
expect(columns).toMatchObject([{ name: 'status' }, { name: 'completed_at' }])
db.createMailboxDeliveryIndexesIfPossible()
expect(db.db.pragma('user_version', { simple: true })).toBe(version)
const plan = JSON.stringify(
db.db
.prepare(
"EXPLAIN QUERY PLAN SELECT rowid FROM dispatch_contexts INDEXED BY idx_dispatch_session_presentation WHERE assignee_orca_session_id IS NOT NULL AND status = 'completed' AND completed_at >= ?"
)
.all('2026-10-26')
)
expect(plan).toContain('idx_dispatch_session_presentation (status=? AND completed_at>?)')
expect(projectionFor(db).buildByPaneKey()?.[chatRow(SESSION_Y)]?.dispatchId).toBe(active)
const latestActive = add('cleared-address', SESSION_X, 'pending', null)
add('newer-recent-address', SESSION_Y, 'completed', '2099-01-01T00:00:00Z')
const read = (id: string) => {
const record = sessionRecord(id)
return agentSessionConversationView(
id === SESSION_X
? {
...record,
conversationCommand: {
command: 'clear',
runtimeFence: record.lease.runtimeFence,
operationId: 'destination',
callerKey: 'test',
phase: 'committed',
state: 'completed',
replacementSessionId: SESSION_Y
}
}
: record
)
}
const sharedDestination = projectionFor(db, {
getRecord: read,
listRecords: () => []
}).buildByPaneKey()
expect(sharedDestination?.[chatRow(SESSION_Y)]?.dispatchId).toBe(latestActive)
expect(sharedDestination?.[chatRow(SESSION_X)]).toBeUndefined()
} finally {
db.close()
}
})
it.skipIf(process.env.ORCA_LINEAGE_BENCH !== '1')(
'benchmarks retained-history ranges and first derived-index creation (admitted machines only)',
() => {
for (const nullAddress of [false, true]) {
for (const history of [10_000, 100_000]) {
for (const terminalHistory of [0, 100_000]) {
for (const attentionFacts of [0, 2_000]) {
benchmarkPresentationCorpus(
{ nullAddress, history, terminalHistory, attentionFacts, parentSessionId: SESSION_X },
(db) => projectionFor(db).buildByPaneKey()
)
}
}
}
}
}
)
it('reads reopened/backfilled assignments and committed clear facts from the already opened store before host installation', async () => {
const directory = mkdtempSync(join(tmpdir(), 'orca-lineage-contract-'))
const root = sessionRecord(SESSION_X)
const successor = COORDINATOR_CHAT
await seedTestAgentSessionRecordStore(directory, {
records: [
{
...root,
conversationCommand: {
command: 'clear',
runtimeFence: root.lease.runtimeFence,
operationId: 'clear',
callerKey: 'test',
phase: 'committed',
state: 'completed',
replacementSessionId: successor
}
},
sessionRecord(successor),
sessionRecord(SESSION_Y)
],
sessionTabs: [
{ tabId: 'reserved-successor', sessionId: successor },
{ tabId: 'reserved-worker', sessionId: SESSION_Y }
]
})
closeTestJournalHostDatabase(directory)
const path = join(directory, 'orchestration.sqlite')
let db = new OrchestrationDb(path)
let opened = false
try {
const run = db.createRun({
objective: 'cold public display',
coordinatorHandle: null,
coordinatorPaneKey: null,
coordinatorOrcaSessionId: SESSION_X
})
const privateHandles: string[] = []
const privatePanes: string[] = []
for (const id of [SESSION_Y, successor]) {
const handle = mintStructuredWorkerHandle()
const pane = mintStructuredWorkerPaneKey(id)
privateHandles.push(handle)
privatePanes.push(pane)
db.createDispatchContext({
taskId: db.createTask({ runId: run.id, spec: 'persisted worker' }).id,
assigneeHandle: handle,
assigneePaneKey: pane,
processIncarnation: structuredWorkerProcessIncarnation(id),
creator: { kind: 'session', orcaSessionId: SESSION_X },
maxDepth: 99
})
}
db.db.exec('UPDATE dispatch_contexts SET assignee_orca_session_id = NULL')
db.close()
db = new OrchestrationDb(path)
const runtime = new OrcaRuntimeService()
runtime.setOrchestrationDb(db)
hostRef.current = null
const before = runtime['agentOrchestrationProjection'].buildByPaneKey()
expect(before?.[chatRow(SESSION_Y)]?.parentPaneKey).toBe(chatRow(SESSION_X))
await openAgentSessionRecordStoreOnce({
stateDirectory: directory,
hostId: 'local',
logger: recordingStructuredAgentSessionLogger().logger
})
opened = true
const result = runtime['agentOrchestrationProjection'].buildByPaneKey()
expect(result?.[chatRow(SESSION_Y)]?.parentPaneKey).toBe(chatRow(successor))
expect(result?.[chatRow(successor)]?.parentPaneKey).toBeUndefined()
for (const privateValue of [...privateHandles, ...privatePanes]) {
expect(JSON.stringify(result)).not.toContain(privateValue)
}
for (const status of ['idle', 'working', 'attention'] as const) {
runtime.onStructuredSessionStatusForMail({ sessionId: SESSION_Y, status })
expect(
runtime['agentOrchestrationProjection'].buildByPaneKey()?.[chatRow(SESSION_Y)]
?.parentPaneKey
).toBe(chatRow(successor))
}
} finally {
if (opened) {
;(await releaseAgentSessionRecordStore())?.journalDatabase.close()
}
db.close()
rmSync(directory, { recursive: true, force: true })
}
})
@@ -1,7 +1,4 @@
import {
AGENT_STATUS_STALE_AFTER_MS,
type AgentStatusOrchestrationContext
} from '../../shared/agent-status-types'
import type { AgentStatusOrchestrationContext } from '../../shared/agent-status-types'
import type { FleetAgentStatusEvidence } from '../../shared/orchestration-fleet-agent-status-evidence'
import { buildOrchestrationTaskDisplayMetadata } from '../../shared/orchestration-task-display'
import { parsePaneKey } from '../../shared/stable-pane-id'
@@ -13,9 +10,14 @@ import {
projectWorkerAttentionContext
} from './orchestration/worker-attention-context'
import { worktreeIdsEqual } from '../../shared/worktree/id'
import type { AgentSessionRecordReader } from './orchestration/structured-session-lineage'
import { createOrchestrationProjectionScope } from './runtime-agent-orchestration-scope'
import { isRecentPresentationDispatch } from './orchestration/db/dispatch-context/dispatch-lookup'
import { currentRunCoordinatorOrcaSessionId } from './orchestration/db/runs/run-coordinator-orca-session'
import type { DispatchContextRow } from './orchestration/types'
import type { PtyPaneOf } from './terminal/surface/pty-pane-query'
type RuntimeAgentOrchestrationDependencies = {
export type RuntimeAgentOrchestrationDependencies = {
getDb(): OrchestrationDb | null
getLeaves(): Iterable<RuntimeLeafRecord>
getPtys(): Iterable<RuntimePtyWorktreeRecord>
@@ -28,6 +30,7 @@ type RuntimeAgentOrchestrationDependencies = {
getPaneKey(handle: string): string | null
getDispatchAuthority(handle: string): OrchestrationCompatibilityTerminalAuthority | null
getAgentStatusSnapshot(): readonly FleetAgentStatusEvidence[]
getSessionRecords(): AgentSessionRecordReader | null
}
export class RuntimeAgentOrchestrationProjection {
@@ -38,6 +41,7 @@ export class RuntimeAgentOrchestrationProjection {
if (!db || db.hasAnyDispatchContexts?.() === false) {
return undefined
}
const scope = createOrchestrationProjectionScope(db, this.deps)
const contexts: Record<string, AgentStatusOrchestrationContext> = {}
const evidenceByPaneKey = new Map(
this.deps.getAgentStatusSnapshot().map((evidence) => [evidence.activity.paneKey, evidence])
@@ -52,11 +56,16 @@ export class RuntimeAgentOrchestrationProjection {
const handle = this.deps.issueLeafHandle(leaf)
queriedHandles.add(handle)
const paneKey = this.deps.makePaneKey(leaf)
const context = this.getForHandle(handle, db, {
paneKey,
evidence: evidenceByPaneKey.get(paneKey),
deferAttention: batchAttention
})
const context = this.getForHandle(
handle,
db,
{
paneKey,
evidence: evidenceByPaneKey.get(paneKey),
deferAttention: batchAttention
},
scope
)
if (context) {
contexts[paneKey] = context
}
@@ -71,21 +80,41 @@ export class RuntimeAgentOrchestrationProjection {
continue
}
queriedHandles.add(handle)
const context = this.getForHandle(handle, db, {
paneKey,
evidence: evidenceByPaneKey.get(paneKey),
deferAttention: batchAttention
})
const context = this.getForHandle(
handle,
db,
{
paneKey,
evidence: evidenceByPaneKey.get(paneKey),
deferAttention: batchAttention
},
scope
)
if (context) {
contexts[paneKey] = context
}
}
for (const [paneKey, { dispatch }] of scope.sessionDispatches()) {
if (!contexts[paneKey]) {
contexts[paneKey] = this.projectDispatch(
dispatch,
dispatch.assignee_handle ?? '',
db,
{
paneKey,
evidence: evidenceByPaneKey.get(paneKey),
deferAttention: batchAttention
},
scope
)
}
}
const entries = Object.entries(contexts)
if (entries.length === 0) {
return undefined
}
if (batchAttention) {
const now = Date.now()
const now = scope.now
const factsByDispatch = db.getWorkerAttentionFactsForDispatches(
entries.map(([, context]) => context.dispatchId),
now
@@ -116,15 +145,27 @@ export class RuntimeAgentOrchestrationProjection {
paneKey?: string
evidence?: FleetAgentStatusEvidence
deferAttention?: boolean
} = {}
} = {},
scope = createOrchestrationProjectionScope(db, this.deps)
): AgentStatusOrchestrationContext | undefined {
const { paneKey, evidence, deferAttention = false } = options
const { paneKey } = options
const dispatch =
db?.getActiveDispatchForTerminal?.(handle, paneKey) ?? this.getRecent(handle, db)
db?.getActiveDispatchForTerminal?.(handle, paneKey) ?? this.getRecent(handle, db, scope.now)
if (!dispatch) {
return undefined
}
const task = db?.getTask?.(dispatch.task_id, dispatch.run_id)
return this.projectDispatch(dispatch, handle, db, options, scope)
}
private projectDispatch(
dispatch: DispatchContextRow,
handle: string,
db: OrchestrationDb | null,
options: { paneKey?: string; evidence?: FleetAgentStatusEvidence; deferAttention?: boolean },
scope: ReturnType<typeof createOrchestrationProjectionScope>
): AgentStatusOrchestrationContext {
const { paneKey, evidence, deferAttention = false } = options
const task = scope.task(dispatch.task_id, dispatch.run_id)
const display =
typeof task?.spec === 'string'
? buildOrchestrationTaskDisplayMetadata({
@@ -134,7 +175,7 @@ export class RuntimeAgentOrchestrationProjection {
})
: { taskTitle: '', displayName: '' }
const owningRun =
task?.run_id && task.run_id === dispatch.run_id ? db?.getRun?.(dispatch.run_id) : undefined
task?.run_id && task.run_id === dispatch.run_id ? scope.run(dispatch.run_id) : undefined
const runCoordinatorHandle = owningRun?.coordinator_handle ?? undefined
const legacyActiveRun =
owningRun?.legacy === 1 && (dispatch.status === 'pending' || dispatch.status === 'dispatched')
@@ -170,7 +211,7 @@ export class RuntimeAgentOrchestrationProjection {
currentCreatorPane &&
storedCreatorPane.leafId === currentCreatorPane.leafId))
)
const paneRun = creatorPaneKey ? db?.getCurrentRunForPane?.(creatorPaneKey) : undefined
const paneRun = creatorPaneKey ? scope.pane(creatorPaneKey) : undefined
const sameRunCreatorDispatch = Boolean(
task?.creator_dispatch_id &&
task.creator_dispatch_run_id === owningRun?.id &&
@@ -194,28 +235,48 @@ export class RuntimeAgentOrchestrationProjection {
sameCreatorPane
? (creatorPaneHandle ?? undefined)
: undefined
const coordinator = this.resolveLivePane(
coordinatorHandle,
owningRun?.legacy === 0 ? owningRun.coordinator_pane_key : null
)
const creator = currentCreatorHandle
? {
handle: currentCreatorHandle,
paneKey: this.deps.getPaneKey(currentCreatorHandle) ?? undefined
}
: creatorLineageInRun
? this.resolveLivePane(creatorPaneHandle, creatorPaneKey ?? null)
: undefined
const selfSession = dispatch.assignee_orca_session_id
const selfPane = selfSession ? scope.resolve(selfSession) : paneKey
const coordinatorSession =
owningRun?.legacy === 0 ? currentRunCoordinatorOrcaSessionId(owningRun) : null
// Why: a chat party nests by its visible row; its handle and minted pane key match no row.
const coordinator: { handle?: string; paneKey?: string } = coordinatorSession
? { paneKey: scope.resolve(coordinatorSession) }
: scope.resolveTerminal(
coordinatorHandle,
owningRun?.legacy === 0 ? owningRun.coordinator_pane_key : null
)
const creatorSession =
dispatch.creator_orca_session_id && dispatch.creator_orca_session_id !== selfSession
? dispatch.creator_orca_session_id
: null
const creator: { handle?: string; paneKey?: string } | undefined = creatorSession
? { paneKey: scope.resolve(creatorSession) }
: currentCreatorHandle
? scope.resolveTerminal(currentCreatorHandle, creatorAuthority?.paneKey ?? null)
: creatorLineageInRun
? scope.resolveTerminal(creatorPaneHandle, creatorPaneKey ?? null)
: undefined
const coordinatorIsSelf =
coordinator.handle === handle ||
(coordinatorSession !== null && coordinatorSession === selfSession) ||
(paneKey !== undefined &&
coordinator.paneKey !== undefined &&
coordinator.paneKey === paneKey)
// Why: a creator whose pane is gone still has a coordinator to nest under.
const parent = creator?.handle ? creator : coordinatorIsSelf ? {} : coordinator
const parent =
(creator?.handle || (creatorSession && creator?.paneKey)) &&
(!selfPane || creator?.paneKey !== selfPane) &&
creator?.handle !== handle
? creator
: coordinatorIsSelf
? {}
: coordinator.paneKey === selfPane
? {}
: coordinator
const attention =
!deferAttention && db && typeof db.getWorkerAttentionFacts === 'function'
? buildWorkerAttentionContext({ db, dispatch, task, evidence })
? buildWorkerAttentionContext({ db, dispatch, task, evidence, now: scope.now })
: undefined
return {
taskId: dispatch.task_id,
@@ -231,43 +292,8 @@ export class RuntimeAgentOrchestrationProjection {
}
}
/** Never publish stale process-local handles; re-resolve the durable pane key, retaining it while offline so restored rows can nest again. */
private resolveLivePane(
storedHandle: string | null | undefined,
storedPaneKey: string | null
): { handle?: string; paneKey?: string } {
if (storedHandle && this.deps.getWorktreeId(storedHandle) !== null) {
return {
handle: storedHandle,
paneKey: this.deps.getPaneKey(storedHandle) ?? storedPaneKey ?? undefined
}
}
if (!storedPaneKey) {
return {}
}
const liveHandle = this.deps.getHandleForPaneKey(storedPaneKey)
if (!liveHandle) {
return { paneKey: storedPaneKey }
}
return { handle: liveHandle, paneKey: this.deps.getPaneKey(liveHandle) ?? storedPaneKey }
}
private getRecent(handle: string, db: OrchestrationDb | null) {
private getRecent(handle: string, db: OrchestrationDb | null, now: number) {
const dispatch = db?.getLatestDispatchForTerminal?.(handle)
if (
!dispatch?.completed_at ||
dispatch.status === 'pending' ||
dispatch.status === 'dispatched'
) {
return undefined
}
const completedAt = Date.parse(
dispatch.completed_at.includes('T')
? dispatch.completed_at
: `${dispatch.completed_at.replace(' ', 'T')}Z`
)
return Number.isFinite(completedAt) && Date.now() - completedAt <= AGENT_STATUS_STALE_AFTER_MS
? dispatch
: undefined
return dispatch && isRecentPresentationDispatch(dispatch, now) ? dispatch : undefined
}
}
@@ -0,0 +1,97 @@
import type { OrchestrationDb } from './orchestration/db'
import type { RuntimeAgentOrchestrationDependencies } from './runtime-agent-orchestration-projection'
import { createCanonicalSessionPaneResolver } from './orchestration/structured-session-lineage'
import { isStructuredWorkerHandle } from '../../shared/structured-worker-handle'
export function createOrchestrationProjectionScope(
db: OrchestrationDb | null,
deps: RuntimeAgentOrchestrationDependencies
) {
const tasks = new Map<string, ReturnType<OrchestrationDb['getTask']>>()
const runs = new Map<string, ReturnType<OrchestrationDb['getRun']>>()
const panes = new Map<string, ReturnType<OrchestrationDb['getCurrentRunForPane']>>()
const now = Date.now()
const resolve = createCanonicalSessionPaneResolver(deps.getSessionRecords())
return {
now,
resolve,
sessionDispatches: () => {
const destinations = new Map<
string,
ReturnType<OrchestrationDb['listSessionDispatchesForPresentation']>[number]
>()
for (const candidate of db?.listSessionDispatchesForPresentation(now) ?? []) {
if (!candidate.dispatch.assignee_orca_session_id) {
continue
}
const paneKey = resolve(candidate.dispatch.assignee_orca_session_id)
const previous = destinations.get(paneKey)
const active =
candidate.dispatch.status === 'pending' || candidate.dispatch.status === 'dispatched'
const previousActive =
previous?.dispatch.status === 'pending' || previous?.dispatch.status === 'dispatched'
if (
!previous ||
(active && !previousActive) ||
(active === previousActive && candidate.order > previous.order)
) {
destinations.set(paneKey, candidate)
}
}
return destinations
},
resolveTerminal: (storedHandle: string | null | undefined, storedPaneKey: string | null) =>
resolveLivePane(deps, storedHandle, storedPaneKey),
task: (id: string, run: string) => {
const key = `${run}:${id}`
if (!tasks.has(key)) {
tasks.set(key, db?.getTask?.(id, run))
}
return tasks.get(key)
},
run: (id: string) => {
if (!runs.has(id)) {
runs.set(id, db?.getRun?.(id))
}
return runs.get(id)
},
pane: (id: string) => {
if (!panes.has(id)) {
panes.set(id, db?.getCurrentRunForPane?.(id))
}
return panes.get(id)
}
}
}
/** Never publish stale process-local handles; re-resolve the durable pane key, retaining it while offline so restored rows can nest again. */
function resolveLivePane(
deps: RuntimeAgentOrchestrationDependencies,
storedHandle: string | null | undefined,
storedPaneKey: string | null
): { handle?: string; paneKey?: string } {
// Structured mailbox panes are credentials, including stale rows with no current public proof.
if (isStructuredWorkerHandle(storedHandle)) {
return {}
}
if (storedHandle && deps.getWorktreeId(storedHandle) !== null) {
return {
handle: storedHandle,
paneKey: deps.getPaneKey(storedHandle) ?? storedPaneKey ?? undefined
}
}
if (storedPaneKey?.startsWith('structured-agent-session-')) {
return {}
}
if (!storedPaneKey) {
return {}
}
const liveHandle = deps.getHandleForPaneKey(storedPaneKey)
if (isStructuredWorkerHandle(liveHandle)) {
return {}
}
if (!liveHandle) {
return { paneKey: storedPaneKey }
}
return { handle: liveHandle, paneKey: deps.getPaneKey(liveHandle) ?? storedPaneKey }
}
@@ -0,0 +1,111 @@
import { afterEach, vi } from 'vitest'
import { OrchestrationDb } from './orchestration/db'
import type { TaskRuntimeLineageRow } from './orchestration/db/run-list-page'
import type { CoordinatorRun, DispatchContextRow, RunRow } from './orchestration/types'
const databases = new Set<OrchestrationDb>()
const createdAt = '2026-10-27T12:00:00Z'
afterEach(() => {
for (const db of databases) {
db.close()
}
databases.clear()
})
export function makeRuntimeOrchestrationDb(): OrchestrationDb {
const db = new OrchestrationDb(':memory:')
databases.add(db)
// These scenarios project supplied terminal contexts even without persisted Dispatches.
vi.spyOn(db, 'hasAnyDispatchContexts').mockReturnValue(true)
return db
}
export function dispatchContextRow(fields: Partial<DispatchContextRow>): DispatchContextRow {
return {
id: 'fixture-dispatch',
run_id: 'fixture-run',
task_id: 'fixture-task',
contract_version: 0,
launch_token_hash: null,
assignee_handle: null,
assignee_pane_key: null,
assignee_orca_session_id: null,
capability_hash: null,
process_incarnation: null,
capability_revoked_at: null,
retry_of_dispatch_id: null,
creator_dispatch_id: null,
creator_handle: null,
creator_pane_key: null,
creator_orca_session_id: null,
host_scope: null,
status: 'dispatched',
failure_count: 0,
last_failure: null,
termination_reason: null,
depth: 1,
consumer_generation: 0,
dispatched_at: createdAt,
completed_at: null,
created_at: createdAt,
last_heartbeat_at: null,
...fields
}
}
export function taskLineageRow(fields: Partial<TaskRuntimeLineageRow>): TaskRuntimeLineageRow {
return {
id: 'fixture-task',
run_id: 'fixture-run',
parent_id: null,
created_by_terminal_handle: null,
created_by_pane_key: null,
created_by_process_incarnation: null,
created_by_run_generation: null,
task_title: null,
display_name: null,
spec: '',
status: 'ready',
deps: '[]',
result: null,
created_at: createdAt,
completed_at: null,
creator_dispatch_id: null,
creator_dispatch_run_id: null,
creator_dispatch_pane_key: null,
creator_dispatch_process_incarnation: null,
...fields
}
}
export function runRow(fields: Partial<RunRow>): RunRow {
return {
id: 'fixture-run',
objective: '',
home_database: 'this_database',
coordinator_handle: null,
coordinator_pane_key: null,
coordinator_orca_session_id: null,
coordinator_orca_session_id_generation: null,
consumer_generation: 0,
legacy: 0,
created_at: createdAt,
updated_at: createdAt,
...fields
}
}
export function coordinatorRunRow(fields: Partial<CoordinatorRun>): CoordinatorRun {
return {
id: 'fixture-coordinator',
spec: '',
status: 'running',
coordinator_handle: 'term_fixture',
poll_interval_ms: 2000,
created_at: createdAt,
completed_at: null,
scheduler_lost_at: null,
...fields
}
}
@@ -418,6 +418,7 @@ function makeOrchestrationDbStub(toHandle: () => string) {
})
},
db: {
listSessionDispatchesForPresentation: () => [],
// Mirrors the real query: `read = 0 AND delivered_at IS NULL`.
getUndeliveredUnreadMessages: (handle: string) =>
rows.filter((row) => row.to_handle === handle && row.read === 0 && !row.delivered_at),
@@ -1,3 +1,5 @@
import { getStructuredAgentSessionTabsByPaneKey } from '@/components/native-chat/structured-agent-session-tabs'
import { parseAgentStatusPaneIdentity } from '../../../../shared/agent-status-worktree-attribution'
import { migrationUnsupportedToAgentStatusEntry } from '../../../../shared/migration-unsupported-agent-entry'
import { parsePaneKey } from '../../../../shared/stable-pane-id'
import type { TerminalTab } from '../../../../shared/terminal-tab-types'
@@ -75,7 +77,14 @@ export function appendUnsupportedAndRetainedEvents(context: {
}
for (const [paneKey, retained] of Object.entries(args.retainedAgentsByPaneKey)) {
if (!parsePaneKey(paneKey)) {
if (
!parseAgentStatusPaneIdentity(
paneKey,
args.unifiedTabsByWorktree
? getStructuredAgentSessionTabsByPaneKey(args.unifiedTabsByWorktree).get(paneKey)
: undefined
)
) {
continue
}
const owner = resolveOwner(
@@ -1,3 +1,5 @@
import { getStructuredAgentSessionTabsByPaneKey } from '@/components/native-chat/structured-agent-session-tabs'
import { parseAgentStatusPaneIdentity } from '../../../../shared/agent-status-worktree-attribution'
import { freshActivityLiveAgentState } from './activity-event-state'
import type { RetainedAgentEntry } from '@/store/slices/agent-status/agent-status-contract'
import type {
@@ -8,7 +10,6 @@ import type {
import type { ExecutionHostId } from '../../../../shared/execution-host'
import type { StructuredChatTabNames } from '@/runtime/structured-chat-tab-name'
import type { Repo } from '../../../../shared/repo-types'
import { parsePaneKey } from '../../../../shared/stable-pane-id'
import type { Tab } from '../../../../shared/tab-types'
import type { TerminalTab } from '../../../../shared/terminal-tab-types'
import type { Worktree } from '../../../../shared/worktree/types'
@@ -83,7 +84,12 @@ export function buildActivityEvents(
}
for (const [paneKey, entry] of Object.entries(args.agentStatusByPaneKey)) {
const parsed = parsePaneKey(paneKey)
const parsed = parseAgentStatusPaneIdentity(
paneKey,
args.unifiedTabsByWorktree
? getStructuredAgentSessionTabsByPaneKey(args.unifiedTabsByWorktree).get(paneKey)
: undefined
)
if (!parsed) {
continue
}
@@ -1,3 +1,4 @@
import { selectVisibleAgentOrchestration } from '@/runtime/visible-agent-orchestration'
import { useDeferredValue, useMemo, useRef } from 'react'
import { useShallow } from 'zustand/react/shallow'
import { useAppStore } from '@/store'
@@ -111,7 +112,7 @@ export function useAgentPaneThreads(args: {
const storeData = useAppStore(
useShallow((s) => ({
agentStatusByPaneKey: s.agentStatusByPaneKey,
runtimeAgentOrchestrationByPaneKey: s.runtimeAgentOrchestrationByPaneKey,
runtimeAgentOrchestrationByPaneKey: selectVisibleAgentOrchestration(s),
migrationUnsupportedByPtyId: s.migrationUnsupportedByPtyId,
retainedAgentsByPaneKey: s.retainedAgentsByPaneKey,
tabsByWorktree: s.tabsByWorktree,
@@ -70,7 +70,14 @@ export type DashboardSnapshotState = Pick<
Partial<
DashboardCardTerminalInputState &
DashboardLaunchDetectionState &
Pick<AppState, 'runtimeEnvironments' | 'sshTargetLabels' | 'unifiedTabsByWorktree'>
Pick<
AppState,
| 'runtimeEnvironments'
| 'sshTargetLabels'
| 'unifiedTabsByWorktree'
| 'activeWorktreeId'
| 'activeWorkspaceExecutionHostId'
>
>
export type DashboardSnapshotInput = DashboardSnapshotState & { chatNames: StructuredChatTabNames }
@@ -133,10 +133,10 @@ describe('agent bucket count input gate', () => {
expect(second.agentStatusEpoch).toBe(1)
})
it('carries every slice the counts read, and settings pinned to null', () => {
it('carries canonical contexts and every row-owner input the counts read', () => {
const state = storeState()
const inputs = selectAgentBucketCountState(state)
expect(inputs.settings).toBeNull()
expect(inputs.settings).toBe(state.settings)
for (const key of [
'repos',
'worktreesByRepo',
@@ -6,7 +6,11 @@ import {
buildDashboardBucketCounts,
createDashboardBucketCountsCache
} from './build-dashboard-bucket-counts'
import { selectFolderWorkspaces, selectWorktreesByRepo } from '@/store/workspace-record-selectors'
import {
selectDetectedWorktreesByRepo,
selectFolderWorkspaces,
selectWorktreesByRepo
} from '@/store/workspace-record-selectors'
export type AgentBucketCounts = Record<DashboardBucket, number>
@@ -28,10 +32,16 @@ export type AgentBucketCountState = Pick<
| 'folderWorkspaces'
| 'acknowledgedAgentsByPaneKey'
| 'agentStatusEpoch'
> & {
// Counts never render generated conversation names; keep this path off settings subscriptions.
settings: null
}
| 'settings'
| 'detectedWorktreesByRepo'
| 'projectGroups'
| 'restoredRuntimeHostIdByWorkspaceSessionKey'
| 'activeWorktreeId'
| 'activeWorkspaceExecutionHostId'
| 'runtimeEnvironments'
| 'runtimeEnvironmentCatalogHydrated'
| 'removedRuntimeEnvironmentIds'
>
// Compare slice identities directly: useShallow allocates entries/Maps per store write. This pure state projection shares one allocation-free unchanged path across consumers.
let previousState: AgentBucketCountState | null = null
@@ -59,7 +69,17 @@ export function selectAgentBucketCountState(s: AppState): AgentBucketCountState
previous.paneForegroundAgentByPaneKey === s.paneForegroundAgentByPaneKey &&
selectFolderWorkspaces(previous) === selectFolderWorkspaces(s) &&
previous.acknowledgedAgentsByPaneKey === s.acknowledgedAgentsByPaneKey &&
previous.agentStatusEpoch === s.agentStatusEpoch
previous.agentStatusEpoch === s.agentStatusEpoch &&
previous.settings === s.settings &&
selectDetectedWorktreesByRepo(previous) === selectDetectedWorktreesByRepo(s) &&
previous.projectGroups === s.projectGroups &&
previous.restoredRuntimeHostIdByWorkspaceSessionKey ===
s.restoredRuntimeHostIdByWorkspaceSessionKey &&
previous.activeWorktreeId === s.activeWorktreeId &&
previous.activeWorkspaceExecutionHostId === s.activeWorkspaceExecutionHostId &&
previous.runtimeEnvironments === s.runtimeEnvironments &&
previous.runtimeEnvironmentCatalogHydrated === s.runtimeEnvironmentCatalogHydrated &&
previous.removedRuntimeEnvironmentIds === s.removedRuntimeEnvironmentIds
) {
return previous
}
@@ -79,7 +99,15 @@ export function selectAgentBucketCountState(s: AppState): AgentBucketCountState
folderWorkspaces: selectFolderWorkspaces(s),
acknowledgedAgentsByPaneKey: s.acknowledgedAgentsByPaneKey,
agentStatusEpoch: s.agentStatusEpoch,
settings: null
settings: s.settings,
detectedWorktreesByRepo: selectDetectedWorktreesByRepo(s),
projectGroups: s.projectGroups,
restoredRuntimeHostIdByWorkspaceSessionKey: s.restoredRuntimeHostIdByWorkspaceSessionKey,
activeWorktreeId: s.activeWorktreeId,
activeWorkspaceExecutionHostId: s.activeWorkspaceExecutionHostId,
runtimeEnvironments: s.runtimeEnvironments,
runtimeEnvironmentCatalogHydrated: s.runtimeEnvironmentCatalogHydrated,
removedRuntimeEnvironmentIds: s.removedRuntimeEnvironmentIds
}
return previousState
}
@@ -79,6 +79,8 @@ export function useLiveDashboardSnapshot(): DashboardSnapshot {
buildDashboardSnapshot(
{
chatNames,
activeWorktreeId: launchRouteStore.activeWorktreeId,
activeWorkspaceExecutionHostId: launchRouteStore.activeWorkspaceExecutionHostId,
repos,
worktreesByRepo,
tabsByWorktree,
@@ -1,3 +1,4 @@
import { getStructuredAgentSessionTabsByPaneKey } from '@/components/native-chat/structured-agent-session-tabs'
import type {
AgentStatusEntry,
AgentStatusOrchestrationContext,
@@ -146,6 +147,9 @@ export function selectWorktreeAgentRowsCached(args: {
const rows = applyAgentRowLineage(
buildWorktreeAgentRows({
tabs: tabs ?? [],
representedTabs: state.unifiedTabsByWorktree
? getStructuredAgentSessionTabsByPaneKey(state.unifiedTabsByWorktree)
: undefined,
entries,
retained,
runtimePaneTitlesByTabId: paneTitlesByTabId,
@@ -1,3 +1,4 @@
import { structuredAgentSessionPaneKey } from '../../../../shared/structured-agent-session-projection'
import { isStructuredTab } from '../../../../shared/structured-agent-session-tab'
import type { Tab } from '../../../../shared/tab-types'
@@ -28,3 +29,21 @@ export function getStructuredAgentSessionTabs(
structuredTabsByUnifiedTabsSnapshot.set(unifiedTabsByWorktree, tabs)
return tabs
}
const paneTabs = new WeakMap<Record<string, Tab[]>, ReadonlyMap<string, StructuredTab>>()
export function getStructuredAgentSessionTabsByPaneKey(
tabs: Record<string, Tab[]>
): ReadonlyMap<string, StructuredTab> {
const cached = paneTabs.get(tabs)
if (cached) {
return cached
}
const result = new Map(
getStructuredAgentSessionTabs(tabs).map((tab) => [
structuredAgentSessionPaneKey(tab.id, tab.entityId),
tab
])
)
paneTabs.set(tabs, result)
return result
}
@@ -0,0 +1,61 @@
import { defineFixture } from '../../component-fixtures/component-fixture'
import WorktreeCardAgents from './WorktreeCardAgents'
import { applyAgentRowLineage } from '../dashboard/agent-row-lineage'
import { buildWorktreeAgentRows } from './worktree-agent-rows'
import { structuredAgentSessionPaneKey } from '../../../../shared/structured-agent-session-projection'
import type { Tab } from '../../../../shared/tab-types'
import type { AgentStatusEntry } from '../../../../shared/agent-status-types'
const now = 1_792_983_600_000
const tabs: Tab[] = [
'11111111-1111-4111-8111-111111111111',
'22222222-2222-4222-8222-222222222222'
].map((entityId, index) => ({
id: index === 0 ? 'reserved-chat-tab' : 'worker-chat-tab:history-1',
entityId,
contentType: 'agent-session',
agentSessionAgent: 'codex',
worktreeId: 'fixture-workspace',
groupId: 'fixture-group',
executionHostId: 'local',
label: 'Chat',
customLabel: null,
color: null,
sortOrder: index,
createdAt: now
}))
const [parent, child] = tabs.map((tab) => structuredAgentSessionPaneKey(tab.id, tab.entityId))
const entries: AgentStatusEntry[] = [parent, child].map((paneKey, index) => ({
paneKey,
worktreeId: 'fixture-workspace',
agentType: 'codex',
state: 'working',
prompt: index === 0 ? 'Coordinate the release checks' : 'Verify the worker result',
updatedAt: now,
stateStartedAt: now,
stateHistory: [],
...(index === 1
? { orchestration: { taskId: 'task', dispatchId: 'dispatch', parentPaneKey: parent } }
: {})
}))
const rows = applyAgentRowLineage(
buildWorktreeAgentRows({
tabs: [],
representedTabs: new Map(
tabs.map((tab) => [structuredAgentSessionPaneKey(tab.id, tab.entityId), tab])
),
entries,
retained: [],
now
})
)
export const nestedChatWorker = defineFixture({
width: 380,
store: { agentActivityDisplayMode: 'compact' },
render: () => (
<div className="flex flex-col gap-0.5 bg-sidebar p-2 text-sidebar-foreground">
<WorktreeCardAgents worktreeId="fixture-workspace" agents={rows} />
</div>
)
})
@@ -46,6 +46,7 @@ vi.mock('@/store', () => {
sshConnectionStates: new Map(),
sshTargetLabels: new Map(),
tabsByWorktree: {},
unifiedTabsByWorktree: {},
updateWorktreeMeta,
workspacePortScan: null,
worktreeCardProperties
@@ -0,0 +1,356 @@
import { act } from 'react'
import { expect, vi } from 'vitest'
import type { RuntimeAgentLineageTestModule } from '../../../../shared/runtime-agent-lineage-consumer.test-fixture'
import { isStructuredTab } from '../../../../shared/structured-agent-session-tab'
import { useAppStore } from '@/store'
import type { AppState } from '@/store/types'
import type { DashboardAgentRow } from '@/components/dashboard/useDashboardData'
import { makePaneKey } from '../../../../shared/stable-pane-id'
import type { AgentStatusEntry } from '../../../../shared/agent-status-types'
import { makeTab } from '@/store/slices/store-test-helpers'
// Load the native graph during collection; fixture state stays per test.
const {
default: { publicLineageFixture, canonicalChatRow, LINEAGE_PARENT, LINEAGE_CHILD }
} = await vi.importActual<{ default: RuntimeAgentLineageTestModule }>(
'../../../../main/runtime/runtime-agent-lineage.test-fixture'
)
const LEAF = '11111111-1111-4111-8111-111111111111'
export async function verifyMirroredTerminalLineage(
kind: 'default' | 'reserved' | 'collision',
{
patch,
entry,
mount,
getRows
}: {
patch: (update: Partial<AppState>) => void
entry: (key: string, worktree: string) => AgentStatusEntry
mount: () => void
getRows: () => DashboardAgentRow[]
}
): Promise<void> {
const { makeUnifiedTab, makeWorktree, TEST_REPO } =
await import('@/store/slices/store-test-helpers')
const { selectDashboardOrchestration } =
await import('@/components/dashboard/dashboard-orchestration-selection')
const { selectWorktreeAgentRowsCached } =
await import('@/components/dashboard/worktree-agent-rows-cache')
const { buildActivityEvents } = await import('@/components/activity/activity-event-builder')
const { buildMirroredAgentTabs } =
await import('@/runtime/web-session-tabs-sync/terminal-surfaces')
const { buildMirroredAgentStatusPatch } =
await import('@/runtime/web-session-tabs-sync/agent-status-patch')
const { buildTerminalUnifiedTab } = await import('@/runtime/web-session-tabs-sync/tab-builders')
const { toRemoteRuntimePtyId } =
await import('../../../../shared/remote-runtime/remote-runtime-pty-id')
const { toWebTerminalSurfaceTabId } = await import('../../../../shared/terminal-surface-id')
const { projectStatus } =
await import('@/components/native-chat/structured-agent-session-status-projection')
const { structuredAgentSessionPaneKey: pane, structuredAgentSessionTabId: tabId } =
await import('../../../../shared/structured-agent-session-projection')
const { selectVisibleAgentOrchestration } = await import('@/runtime/visible-agent-orchestration')
const worktree = makeWorktree({ id: 'folder-a', repoId: TEST_REPO.id })
patch({ repos: [TEST_REPO], worktreesByRepo: { [TEST_REPO.id]: [worktree] } })
const f = publicLineageFixture('folder-a')
try {
const context = f.projection.buildByPaneKey()?.[canonicalChatRow(LINEAGE_CHILD)]
if (!context) {
throw new Error('Missing production context')
}
const native = buildMirroredAgentTabs(
{
worktree: 'folder-a',
publicationEpoch: 'test',
snapshotVersion: 1,
activeGroupId: 'g',
activeTabId: null,
activeTabType: 'agent-session',
tabs: [
{
type: 'agent-session',
id: 'host-parent',
title: 'Parent',
sessionId: LINEAGE_PARENT,
replacesSessionId: 'previous',
agent: 'codex',
isActive: false
}
]
},
'runtime:paired',
new Map(),
'g',
0,
kind === 'default'
? []
: [
makeUnifiedTab({
id: kind === 'reserved' ? 'reserved-parent' : tabId(LINEAGE_PARENT),
entityId: kind === 'reserved' ? 'previous' : 'occupied',
worktreeId: 'folder-a',
groupId: 'g',
contentType: 'agent-session'
})
],
Date.now()
)[0].unifiedTab
if (!isStructuredTab(native)) {
throw new Error('Expected the mirrored native session tab')
}
const actualParent = pane(native.id, LINEAGE_PARENT)
const tab = makeTab({
id: toWebTerminalSurfaceTabId('host-terminal'),
worktreeId: 'folder-a',
ptyId: toRemoteRuntimePtyId('terminal', 'paired')
})
const worker = makePaneKey(tab.id, LEAF)
const terminal = buildTerminalUnifiedTab(tab, 'g', 'paired')
patch({
tabsByWorktree: { 'folder-a': [tab] },
unifiedTabsByWorktree: {},
ptyIdsByTabId: {},
agentStatusByPaneKey: {},
retainedAgentsByPaneKey: {},
runtimeAgentOrchestrationByPaneKey: {}
})
const produced = buildMirroredAgentStatusPatch(
useAppStore.getState(),
[],
[
{
type: 'terminal',
id: 'surface',
title: 'Worker',
parentTabId: 'host-terminal',
leafId: LEAF,
terminal: 'terminal',
status: 'ready',
isActive: false,
agentStatus: {
...entry(makePaneKey('host-terminal', LEAF), 'folder-a'),
orchestration: context
}
}
],
[],
'paired',
'folder-a',
new Set(),
Date.now()
)
if (!produced) {
throw new Error('Missing mirrored terminal status')
}
patch(produced)
expect(useAppStore.getState().agentStatusByPaneKey[worker].connectionId).toBe('paired')
// Status before graph: the missing parent stays rooted, then tab hydration alone joins it.
expect(selectVisibleAgentOrchestration(useAppStore.getState())[worker]?.parentPaneKey).not.toBe(
actualParent
)
patch({ unifiedTabsByWorktree: { 'folder-a': [native, terminal] } })
act(() =>
useAppStore.getState().transactAgentStatuses((transaction) =>
projectStatus(
transaction,
native,
{
sessionId: LINEAGE_PARENT,
workspaceId: 'folder-a',
agent: 'codex',
status: 'working',
latestPrompt: 'Parent',
updatedAt: Date.now(),
hostExecutionOwned: true
},
'live',
null
)
)
)
mount()
const assertNested = (parent = actualParent) => {
expect(getRows().map((row) => row.paneKey)).toEqual([parent, worker])
expect(getRows().map((row) => row.lineage?.depth)).toEqual([0, 1])
expect(getRows()[1].entry.orchestration?.parentPaneKey).toBe(parent)
expect(
useAppStore.getState().agentStatusByPaneKey[worker]?.orchestration?.parentPaneKey ??
context.parentPaneKey
).toBe(canonicalChatRow(LINEAGE_PARENT))
const state = useAppStore.getState()
const orchestration =
selectDashboardOrchestration(state, [{ worktree }]).singletonOrchestration ?? {}
const dashboard = selectWorktreeAgentRowsCached({
state,
worktreeId: 'folder-a',
orchestration,
now: Date.now(),
generation: 1
})
expect(dashboard.map((row) => [row.paneKey, row.lineage.depth])).toEqual([
[parent, 0],
[worker, 1]
])
const activity = buildActivityEvents({
...state,
chatNames: new Map(),
worktreeMap: new Map([[worktree.id, worktree]]),
repoMap: new Map([[TEST_REPO.id, TEST_REPO]]),
runtimeAgentOrchestrationByPaneKey: selectVisibleAgentOrchestration(state),
now: Date.now()
})
expect(activity.paneEntryByPaneKey[worker]?.orchestration?.parentPaneKey).toBe(parent)
expect(activity.paneEntryByPaneKey[parent]).toBeDefined()
}
assertNested()
// A host-supplied legacy connection spelling does not override actual producer proof.
patch({
agentStatusByPaneKey: {
...useAppStore.getState().agentStatusByPaneKey,
[worker]: {
...useAppStore.getState().agentStatusByPaneKey[worker],
connectionId: 'ssh-legacy'
}
}
})
assertNested()
const canonical = useAppStore.getState().agentStatusByPaneKey[worker]
const epoch = useAppStore.getState().agentStatusEpoch
// Graph before parent hydration; matching task/Dispatch producer remains valid with nonempty connectionId.
const parentEntry = useAppStore.getState().agentStatusByPaneKey[actualParent]
patch({
unifiedTabsByWorktree: { 'folder-a': [terminal] },
agentStatusByPaneKey: { [worker]: canonical }
})
act(() =>
useAppStore
.getState()
.setRuntimeAgentOrchestrationByPaneKey(
{ [worker]: structuredClone(context) },
'runtime:paired'
)
)
expect(getRows().find((row) => row.paneKey === worker)?.lineage?.depth).toBe(0)
patch({
unifiedTabsByWorktree: { 'folder-a': [native, terminal] },
agentStatusByPaneKey: { [worker]: canonical, [actualParent]: parentEntry }
})
assertNested()
act(() => useAppStore.getState().setRuntimeAgentOrchestrationByPaneKey({}))
// PTY-only hydration is an independent cache input; disagreeing tab/PTY facts must not join.
patch({
unifiedTabsByWorktree: { 'folder-a': [native] },
tabsByWorktree: { 'folder-a': [{ ...tab, ptyId: null }] }
})
expect(getRows().find((row) => row.paneKey === worker)?.lineage?.depth).toBe(0)
patch({ ptyIdsByTabId: { [tab.id]: [tab.ptyId ?? ''] } })
assertNested()
patch({
unifiedTabsByWorktree: {
'folder-a': [native, { ...terminal, executionHostId: 'runtime:other' }]
}
})
expect(getRows().find((row) => row.paneKey === worker)?.lineage?.depth).toBe(0)
patch({
unifiedTabsByWorktree: {
'folder-a': [{ ...native, executionHostId: 'runtime:other' }, terminal]
},
ptyIdsByTabId: {}
})
expect(getRows().find((row) => row.paneKey === worker)?.lineage?.depth).toBe(0)
patch({ unifiedTabsByWorktree: { 'folder-a': [native, terminal] } })
assertNested()
// Retained snapshot proves the runtime after the current terminal tab/PTY/unified row disappears.
act(() =>
useAppStore.getState().retainAgents([
{
entry: { ...canonical, state: 'done' },
worktreeId: 'folder-a',
tab,
agentType: 'claude',
startedAt: Date.now()
}
])
)
patch({
agentStatusByPaneKey: {
[actualParent]: useAppStore.getState().agentStatusByPaneKey[actualParent]
},
tabsByWorktree: {},
unifiedTabsByWorktree: { 'folder-a': [native] },
ptyIdsByTabId: {}
})
assertNested()
patch({ unifiedTabsByWorktree: { 'folder-a': [{ ...native, id: 'remapped-parent' }] } })
// The parent status arrives independently; canonical retained context did not change or need an RPC.
patch({
agentStatusByPaneKey: {
[pane('remapped-parent', LINEAGE_PARENT)]: {
...useAppStore.getState().agentStatusByPaneKey[actualParent],
paneKey: pane('remapped-parent', LINEAGE_PARENT),
tabId: 'remapped-parent'
}
}
})
assertNested(pane('remapped-parent', LINEAGE_PARENT))
expect(
useAppStore.getState().retainedAgentsByPaneKey[worker].entry.orchestration?.parentPaneKey
).toBe(canonicalChatRow(LINEAGE_PARENT))
expect(useAppStore.getState().agentStatusEpoch).toBeGreaterThanOrEqual(epoch)
// Removing the only retained PTY proof cannot infer a runtime from its connection spelling.
patch({
retainedAgentsByPaneKey: {
[worker]: {
...useAppStore.getState().retainedAgentsByPaneKey[worker],
tab: { ...tab, ptyId: null }
}
}
})
expect(getRows().find((row) => row.paneKey === worker)?.lineage?.depth).toBe(0)
expect(new Set(getRows().map((row) => row.paneKey)).size).toBe(getRows().length)
// Matching graph context identifies its producer even when terminal routing names another host.
const renamedParent = pane('remapped-parent', LINEAGE_PARENT)
patch({
retainedAgentsByPaneKey: {},
tabsByWorktree: { 'folder-a': [tab] },
unifiedTabsByWorktree: {
'folder-a': [{ ...native, id: 'remapped-parent', executionHostId: 'local' }, terminal]
},
agentStatusByPaneKey: {
[renamedParent]: useAppStore.getState().agentStatusByPaneKey[renamedParent],
[worker]: canonical
}
})
act(() =>
useAppStore
.getState()
.setRuntimeAgentOrchestrationByPaneKey({ [worker]: structuredClone(context) })
)
assertNested(renamedParent)
act(() =>
useAppStore
.getState()
.setRuntimeAgentOrchestrationByPaneKey(
{ [worker]: structuredClone(context) },
'runtime:other'
)
)
expect(getRows().find((row) => row.paneKey === worker)?.lineage?.depth).toBe(0)
act(() => useAppStore.getState().setRuntimeAgentOrchestrationByPaneKey({}))
patch({
tabsByWorktree: { 'folder-a': [{ ...tab, ptyId: 'remote:%zz@@terminal' }] },
unifiedTabsByWorktree: {
'folder-a': [{ ...native, id: 'remapped-parent', executionHostId: 'local' }]
},
agentStatusByPaneKey: {
...useAppStore.getState().agentStatusByPaneKey,
[worker]: { ...canonical, connectionId: undefined }
}
})
expect(getRows().find((row) => row.paneKey === worker)?.lineage?.depth).toBe(0)
} finally {
f.db.close()
}
}
@@ -13,9 +13,19 @@ import {
type AgentStatusEntry
} from '../../../../shared/agent-status-types'
import { useWorktreeAgentRows } from './useWorktreeAgentRows'
import { verifyMirroredTerminalLineage } from './mirrored-terminal-lineage.test-fixture'
import type { RuntimeAgentLineageTestModule } from '../../../../shared/runtime-agent-lineage-consumer.test-fixture'
import { isStructuredTab } from '../../../../shared/structured-agent-session-tab'
Reflect.set(globalThis, 'IS_REACT_ACT_ENVIRONMENT', true)
// Load the native graph during collection; fixture state stays per test.
const {
default: { publicLineageFixture, canonicalChatRow, LINEAGE_PARENT, LINEAGE_CHILD }
} = await vi.importActual<{ default: RuntimeAgentLineageTestModule }>(
'../../../../main/runtime/runtime-agent-lineage.test-fixture'
)
const LEAF = '11111111-1111-4111-8111-111111111111'
const KEY_A = makePaneKey('tab-a', LEAF)
const KEY_B = makePaneKey('tab-b', LEAF)
@@ -220,3 +230,535 @@ describe('mounted worktree agent row subscriptions', () => {
}
})
})
it.each([20, 200])(
'shares canonical receiving/alias work and preserves unaffected mounted rows at %i worktrees',
async (n) => {
const { structuredAgentSessionPaneKey: pane, structuredAgentSessionTabId: tabId } =
await import('../../../../shared/structured-agent-session-projection')
const { makeUnifiedTab } = await import('@/store/slices/store-test-helpers')
const { visibleOrchestrationWorkForTest } =
await import('@/runtime/visible-agent-orchestration')
const { _getWorktreeAgentOrchestrationIndexBuildCountForTest: indexBuilds } =
await import('./worktree-agent-orchestration-index')
const live: AppState['agentStatusByPaneKey'] = {}
const tabs: AppState['unifiedTabsByWorktree'] = {}
const raw: AppState['runtimeAgentOrchestrationByPaneKey'] = {}
const observed = new Map<number, DashboardAgentRow[]>()
const counts = new Map<number, number>()
for (let i = 0; i < n; i++) {
const worktreeId = `lineage-${i}`
tabs[worktreeId] = ['parent', 'child'].map((role) =>
makeUnifiedTab({
id: `${role}-actual-${i}`,
entityId: `${role}-${i}`,
groupId: 'group',
worktreeId,
contentType: 'agent-session',
agentSessionAgent: 'codex',
executionHostId: i === n - 1 ? 'runtime:other' : 'local'
})
)
for (const tab of tabs[worktreeId]) {
live[pane(tab.id, tab.entityId)] = {
...entry(pane(tab.id, tab.entityId), worktreeId),
agentType: 'codex',
tabId: tab.id
}
}
raw[pane(tabId(`child-${i}`), `child-${i}`)] = {
taskId: `task-${i}`,
dispatchId: `dispatch-${i}`,
dispatchStatus: 'dispatched',
parentPaneKey: pane(tabId(`parent-${i}`), `parent-${i}`)
}
}
patch({
tabsByWorktree: {},
unifiedTabsByWorktree: tabs,
agentStatusByPaneKey: live,
runtimeAgentOrchestrationByPaneKey: {},
retainedAgentsByPaneKey: {}
})
act(() => useAppStore.getState().setRuntimeAgentOrchestrationByPaneKey(raw))
function ManyProbe({ index }: { index: number }) {
observed.set(index, useWorktreeAgentRows(`lineage-${index}`))
counts.set(index, (counts.get(index) ?? 0) + 1)
return null
}
act(() =>
root.render(Array.from({ length: n }, (_, index) => <ManyProbe key={index} index={index} />))
)
const initial = new Map(observed)
counts.clear()
const beforeEqual = visibleOrchestrationWorkForTest()
const canonicalBefore = useAppStore.getState().runtimeAgentOrchestrationByPaneKey
act(() => useAppStore.getState().setRuntimeAgentOrchestrationByPaneKey(structuredClone(raw)))
expect(useAppStore.getState().runtimeAgentOrchestrationByPaneKey).toBe(canonicalBefore)
expect(counts.size).toBe(0)
expect(visibleOrchestrationWorkForTest()).toEqual(beforeEqual)
const changedKey = pane(tabId('child-0'), 'child-0')
for (const change of [
{ taskTitle: 'A real new title' },
{ dispatchStatus: 'completed' as const },
{ attention: { categories: ['input' as const], requiresAction: true } },
{ parentPaneKey: 'missing-parent' }
]) {
const before = visibleOrchestrationWorkForTest()
const beforeIndex = indexBuilds()
counts.clear()
act(() =>
useAppStore.getState().setRuntimeAgentOrchestrationByPaneKey({
...useAppStore.getState().runtimeAgentOrchestrationByPaneKey,
[changedKey]: { ...raw[changedKey], ...change }
})
)
expect(counts.get(0)).toBe(1)
expect(
observed.get(0)?.find((row) => row.paneKey === pane('child-actual-0', 'child-0'))?.entry
.orchestration
).toMatchObject(change)
for (let i = 1; i < n; i++) {
expect(counts.has(i)).toBe(false)
expect(observed.get(i)).toBe(initial.get(i))
}
const after = visibleOrchestrationWorkForTest()
expect(after.builds - before.builds).toBeLessThanOrEqual(1)
expect(after.aliasBuilds).toBe(before.aliasBuilds)
expect(indexBuilds() - beforeIndex).toBeLessThanOrEqual(1)
expect(after.visits - before.visits).toBeLessThanOrEqual(n * 14)
}
act(() => useAppStore.getState().setRuntimeAgentOrchestrationByPaneKey(raw))
// Releasing one relationship preserves unrelated arrays even while its embedded completion remains.
counts.clear()
const remaining = { ...useAppStore.getState().runtimeAgentOrchestrationByPaneKey }
delete remaining[changedKey]
act(() => useAppStore.getState().setRuntimeAgentOrchestrationByPaneKey(remaining))
for (let i = 1; i < n; i++) {
expect(observed.get(i)).toBe(initial.get(i))
}
const epoch = useAppStore.getState().agentStatusEpoch
const beforeAlias = visibleOrchestrationWorkForTest()
patch({
unifiedTabsByWorktree: {
...tabs,
'lineage-0': tabs['lineage-0'].map((tab) =>
tab.entityId === 'parent-0' ? { ...tab, id: 'remapped-parent' } : tab
)
}
})
expect(
observed.get(0)?.find((row) => row.paneKey === pane('child-actual-0', 'child-0'))?.entry
.orchestration?.parentPaneKey
).toBe(pane('remapped-parent', 'parent-0'))
expect(useAppStore.getState().agentStatusEpoch).toBe(epoch)
for (let i = 1; i < n; i++) {
expect(observed.get(i)).toBe(initial.get(i))
}
expect(visibleOrchestrationWorkForTest().builds - beforeAlias.builds).toBe(1)
// A host change cannot attach a local worker to an identically named foreign parent.
patch({
unifiedTabsByWorktree: {
...tabs,
'lineage-0': tabs['lineage-0'].map((tab) =>
tab.entityId === 'parent-0' ? { ...tab, executionHostId: 'runtime:other' } : tab
)
}
})
expect(
observed.get(0)?.find((row) => row.paneKey === pane('child-actual-0', 'child-0'))?.entry
.orchestration?.parentPaneKey
).not.toBe(pane('parent-actual-0', 'parent-0'))
for (let i = 1; i < n; i++) {
expect(observed.get(i)).toBe(initial.get(i))
}
counts.clear()
const foreignRow = pane(`child-actual-${n - 1}`, `child-${n - 1}`)
const beforeForeign = visibleOrchestrationWorkForTest()
const beforeForeignIndex = indexBuilds()
const { projectStatus } =
await import('@/components/native-chat/structured-agent-session-status-projection')
const foreignTab = tabs[`lineage-${n - 1}`][1]
if (!isStructuredTab(foreignTab)) {
throw new Error('Expected the native session tab')
}
act(() =>
useAppStore.getState().transactAgentStatuses((transaction) =>
projectStatus(
transaction,
foreignTab,
{
sessionId: foreignTab.entityId,
workspaceId: foreignTab.worktreeId,
agent: 'codex',
status: 'working',
latestPrompt: 'Another host update',
updatedAt: Date.now() + 1,
hostExecutionOwned: true
},
'live',
null
)
)
)
expect(counts.get(n - 1)).toBe(1)
expect(observed.get(n - 1)?.find((row) => row.paneKey === foreignRow)?.entry.prompt).toBe(
'Another host update'
)
for (let i = 0; i < n - 1; i++) {
expect(counts.has(i)).toBe(false)
}
const afterForeign = visibleOrchestrationWorkForTest()
expect(afterForeign.builds - beforeForeign.builds).toBeLessThanOrEqual(1)
expect(afterForeign.aliasBuilds).toBe(beforeForeign.aliasBuilds)
expect(indexBuilds() - beforeForeignIndex).toBeLessThanOrEqual(1)
expect(afterForeign.visits - beforeForeign.visits).toBeLessThanOrEqual(n * 14)
}
)
it('joins production mirrored custom/collision rows locally and keeps canonical initial, graph, retained and consumer contexts', async () => {
const { makeUnifiedTab, makeWorktree, TEST_REPO } =
await import('@/store/slices/store-test-helpers')
const { buildMirroredAgentTabs } =
await import('@/runtime/web-session-tabs-sync/terminal-surfaces')
const { projectStatus } =
await import('@/components/native-chat/structured-agent-session-status-projection')
const { getStructuredAgentSessionTabs } =
await import('@/components/native-chat/structured-agent-session-tabs')
const { selectVisibleAgentOrchestration } = await import('@/runtime/visible-agent-orchestration')
const { structuredAgentSessionPaneKey: pane, structuredAgentSessionTabId: tabId } =
await import('../../../../shared/structured-agent-session-projection')
const { selectWorktreeAgentActivitySummary } = await import('./worktree-agent-activity-summary')
const { selectDashboardOrchestration } =
await import('@/components/dashboard/dashboard-orchestration-selection')
const { selectWorktreeAgentRowsCached } =
await import('@/components/dashboard/worktree-agent-rows-cache')
const { buildActivityEvents } = await import('@/components/activity/activity-event-builder')
const f = publicLineageFixture('folder-a')
try {
const predecessor = makeUnifiedTab({
id: 'reserved-parent',
entityId: 'old-parent',
groupId: 'g',
worktreeId: 'folder-a',
contentType: 'agent-session',
agentSessionAgent: 'codex',
executionHostId: 'local'
})
const occupied = makeUnifiedTab({
id: tabId(LINEAGE_CHILD),
entityId: 'unrelated',
groupId: 'g',
worktreeId: 'folder-a'
})
const mirrored = buildMirroredAgentTabs(
{
worktree: 'folder-a',
publicationEpoch: 'test',
snapshotVersion: 1,
activeGroupId: 'g',
activeTabId: null,
activeTabType: 'agent-session',
tabs: [
{
type: 'agent-session',
id: 'host-parent',
title: 'Parent',
sessionId: LINEAGE_PARENT,
replacesSessionId: 'old-parent',
agent: 'codex',
isActive: false
},
{
type: 'agent-session',
id: 'host-child',
title: 'Child',
sessionId: LINEAGE_CHILD,
agent: 'codex',
isActive: false
}
]
},
'local',
new Map(),
'g',
0,
[predecessor, occupied],
Date.now()
).map((item) => item.unifiedTab)
expect(mirrored[0].id).toBe('reserved-parent')
expect(mirrored[1].id).toContain(':history-1')
const raw = f.projection.buildByPaneKey() ?? {}
patch({
tabsByWorktree: {},
unifiedTabsByWorktree: {},
agentStatusByPaneKey: {},
retainedAgentsByPaneKey: {},
runtimeAgentOrchestrationByPaneKey: {}
})
act(() => useAppStore.getState().setRuntimeAgentOrchestrationByPaneKey(raw))
const canonical = useAppStore.getState().runtimeAgentOrchestrationByPaneKey
patch({ unifiedTabsByWorktree: { 'folder-a': mirrored } })
const actualParent = pane(mirrored[0].id, LINEAGE_PARENT)
const actualChild = pane(mirrored[1].id, LINEAGE_CHILD)
expect(selectVisibleAgentOrchestration(useAppStore.getState())[actualChild].parentPaneKey).toBe(
actualParent
)
const emitStatuses = () =>
act(() =>
useAppStore.getState().transactAgentStatuses((transaction) => {
for (const tab of getStructuredAgentSessionTabs(
useAppStore.getState().unifiedTabsByWorktree
)) {
projectStatus(
transaction,
tab,
{
sessionId: tab.entityId,
workspaceId: tab.worktreeId,
agent: 'codex',
status: 'working',
latestPrompt: tab.label,
updatedAt: Date.now(),
hostExecutionOwned: true
},
'live',
null
)
}
})
)
emitStatuses()
expect(
useAppStore.getState().agentStatusByPaneKey[actualChild].orchestration?.parentPaneKey
).toBe(canonicalChatRow(LINEAGE_PARENT))
expect(useAppStore.getState().runtimeAgentOrchestrationByPaneKey).toBe(canonical)
act(() => root.render(<Probe />))
expect(rows.map((row) => row.paneKey)).toEqual([actualParent, actualChild])
expect(rows[1].entry.orchestration?.parentPaneKey).toBe(actualParent)
const worktree = makeWorktree({ id: 'folder-a', repoId: TEST_REPO.id })
patch({ repos: [TEST_REPO], worktreesByRepo: { [TEST_REPO.id]: [worktree] } })
const state = useAppStore.getState()
const singleton = selectDashboardOrchestration(state, [{ worktree }]).singletonOrchestration
const batch = selectDashboardOrchestration(state, [
{ worktree },
{ worktree: { ...worktree, id: 'other' } }
]).orchestrationByWorktree?.get('folder-a')
expect(batch).toBe(singleton)
const dashboard = selectWorktreeAgentRowsCached({
state,
worktreeId: 'folder-a',
orchestration: singleton ?? {},
now: Date.now(),
generation: 1
})
expect(dashboard.map((row) => row.lineage?.depth)).toEqual([0, 1])
expect(selectWorktreeAgentActivitySummary(state, 'folder-a').hasLiveWorking).toBe(true)
const activity = buildActivityEvents({
...state,
chatNames: new Map(),
tabsByWorktree: state.tabsByWorktree,
unifiedTabsByWorktree: state.unifiedTabsByWorktree,
worktreeMap: new Map([[worktree.id, worktree]]),
repoMap: new Map([[TEST_REPO.id, TEST_REPO]]),
runtimeAgentOrchestrationByPaneKey: selectVisibleAgentOrchestration(state),
now: Date.now()
})
expect(activity.paneEntryByPaneKey[actualChild]?.orchestration?.parentPaneKey).toBe(
actualParent
)
expect(activity.paneEntryByPaneKey[actualParent]).toBeDefined()
const { getWorkspaceCleanupAgentEvidence } =
await import('@/store/slices/workspace-cleanup-agent-evidence')
const { makeCandidate } = await import('@/store/slices/workspace-cleanup-slice-test-harness')
expect([
...getWorkspaceCleanupAgentEvidence(state, [
makeCandidate({ worktreeId: 'folder-a', executionHostId: 'local' })
]).values()
]).toEqual(['live'])
const { buildDashboardSnapshot } =
await import('@/components/dashboard/build-dashboard-snapshot')
const snapshot = buildDashboardSnapshot({ ...state, chatNames: new Map() }, Date.now())
expect(JSON.stringify(snapshot)).toContain(actualChild)
expect(JSON.stringify(snapshot)).toContain(actualParent)
// Payload-before-graph and a retained terminal child's embedded parent use that same read-side join.
act(() => useAppStore.getState().setRuntimeAgentOrchestrationByPaneKey({}))
expect(selectVisibleAgentOrchestration(useAppStore.getState())[actualChild].parentPaneKey).toBe(
actualParent
)
const terminal = {
...entry(KEY_B, 'folder-a'),
state: 'done' as const,
orchestration: raw[canonicalChatRow(LINEAGE_CHILD)]
}
act(() =>
useAppStore.getState().retainAgents([
{
entry: terminal,
worktreeId: 'folder-a',
tab: makeTab({ id: 'tab-b', worktreeId: 'folder-a' }),
agentType: 'codex',
startedAt: Date.now()
}
])
)
expect(selectVisibleAgentOrchestration(useAppStore.getState())[KEY_B].parentPaneKey).toBe(
actualParent
)
// Alias rederivation is immediate and writes neither canonical storage nor an epoch.
const epoch = useAppStore.getState().agentStatusEpoch
patch({
unifiedTabsByWorktree: {
'folder-a': mirrored.map((tab, index) => (index === 0 ? { ...tab, id: 'new-parent' } : tab))
}
})
expect(selectVisibleAgentOrchestration(useAppStore.getState())[actualChild].parentPaneKey).toBe(
pane('new-parent', LINEAGE_PARENT)
)
expect(useAppStore.getState().agentStatusEpoch).toBe(epoch)
patch({
unifiedTabsByWorktree: {
'folder-a': mirrored.map((tab, index) =>
index === 0 ? { ...tab, executionHostId: 'runtime:foreign' } : tab
)
}
})
expect(
selectVisibleAgentOrchestration(useAppStore.getState())[actualChild]?.parentPaneKey
).not.toBe(actualParent)
} finally {
f.db.close()
}
})
it.each(['default', 'reserved', 'collision'] as const)(
'joins mirrored live/retained terminal contexts with positive provenance and a %s parent',
async (kind) => {
await verifyMirroredTerminalLineage(kind, {
patch,
entry,
mount: () => act(() => root.render(<Probe />)),
getRows: () => rows
})
}
)
it('settles the production graph subscription/scheduler/publication/receiver loop with at most one feedback flight', async () => {
const { useRuntimeGraphSync } = await import('@/app-shell/use-runtime-graph-sync')
const { setRuntimeGraphSyncEnabled, setRuntimeGraphStoreStateGetter } =
await import('@/runtime/sync-runtime-graph')
const { graphState } = await import('@/runtime/sync-runtime-graph/graph-state')
const { makeUnifiedTab } = await import('@/store/slices/store-test-helpers')
const { selectVisibleAgentOrchestration } = await import('@/runtime/visible-agent-orchestration')
const { structuredAgentSessionPaneKey: pane } =
await import('../../../../shared/structured-agent-session-projection')
const f = publicLineageFixture('folder-a')
const response = {
runtimeId: 'lineage',
rendererGraphEpoch: 1,
graphStatus: 'ready' as const,
authoritativeWindowId: null,
liveTabCount: 0,
liveLeafCount: 0,
agentOrchestrationByPaneKey: f.projection.buildByPaneKey()
}
let release: (() => void) | undefined
let fail = false
let hold = true
const previousApi = window.api
const sync = vi.fn(async () => {
if (hold) {
await new Promise<void>((resolve) => {
release = resolve
})
}
if (fail) {
throw new Error('expected transport failure')
}
return structuredClone(response)
})
Reflect.set(window, 'api', {
...previousApi,
runtime: { ...previousApi?.runtime, syncWindowGraph: sync }
})
const error = vi.spyOn(console, 'error').mockImplementation(() => {})
function SyncProbe() {
useRuntimeGraphSync()
return null
}
const flush = () =>
act(async () => {
await vi.advanceTimersByTimeAsync(20)
})
try {
patch({
workspaceSessionReady: true,
tabsByWorktree: {},
unifiedTabsByWorktree: {},
retainedAgentsByPaneKey: {},
runtimeAgentOrchestrationByPaneKey: {},
agentStatusByPaneKey: {
[canonicalChatRow(LINEAGE_CHILD)]: entry(canonicalChatRow(LINEAGE_CHILD), 'folder-a')
}
})
act(() => root.render(<SyncProbe />))
await flush()
expect(sync).toHaveBeenCalledTimes(1)
const parent = makeUnifiedTab({
id: 'late-parent',
entityId: LINEAGE_PARENT,
groupId: 'g',
worktreeId: 'folder-a',
contentType: 'agent-session',
agentSessionAgent: 'codex',
executionHostId: 'local'
})
patch({ unifiedTabsByWorktree: { 'folder-a': [parent] } })
hold = false
await act(async () => {
release?.()
await Promise.resolve()
})
await flush()
expect(sync).toHaveBeenCalledTimes(2)
const stable = useAppStore.getState()
expect(
selectVisibleAgentOrchestration(stable)[canonicalChatRow(LINEAGE_CHILD)].parentPaneKey
).toBe(pane(parent.id, LINEAGE_PARENT))
await flush()
expect(sync).toHaveBeenCalledTimes(2)
expect(useAppStore.getState().runtimeAgentOrchestrationByPaneKey).toBe(
stable.runtimeAgentOrchestrationByPaneKey
)
expect(useAppStore.getState().agentStatusByPaneKey).toBe(stable.agentStatusByPaneKey)
expect(useAppStore.getState().agentStatusEpoch).toBe(stable.agentStatusEpoch)
fail = true
patch({ unifiedTabsByWorktree: { 'folder-a': [{ ...parent, label: 'legitimate wake' }] } })
await flush()
expect(sync).toHaveBeenCalledTimes(3)
expect(graphState.syncInFlight).toBe(false)
await flush()
expect(sync).toHaveBeenCalledTimes(3)
setRuntimeGraphSyncEnabled(false)
patch({ unifiedTabsByWorktree: { 'folder-a': [{ ...parent, id: 'disabled-local-alias' }] } })
expect(
selectVisibleAgentOrchestration(useAppStore.getState())[canonicalChatRow(LINEAGE_CHILD)]
.parentPaneKey
).toBe(pane('disabled-local-alias', LINEAGE_PARENT))
await flush()
expect(sync).toHaveBeenCalledTimes(3)
fail = false
setRuntimeGraphSyncEnabled(true)
await flush()
expect(sync).toHaveBeenCalledTimes(4)
await flush()
expect(sync).toHaveBeenCalledTimes(4)
} finally {
setRuntimeGraphSyncEnabled(false)
setRuntimeGraphStoreStateGetter(null)
Reflect.set(window, 'api', previousApi)
error.mockRestore()
f.db.close()
}
})
@@ -1,3 +1,4 @@
import { getStructuredAgentSessionTabsByPaneKey } from '@/components/native-chat/structured-agent-session-tabs'
import { useCallback, useMemo, useSyncExternalStore } from 'react'
import type { DashboardAgentRow } from '@/components/dashboard/useDashboardData'
import { applyAgentRowLineage } from '@/components/dashboard/agent-row-lineage'
@@ -117,6 +118,9 @@ export function useWorktreeAgentRows(worktreeId: string, active = true): Dashboa
return applyAgentRowLineage(
buildWorktreeAgentRows({
tabs: tabs ?? EMPTY_TABS,
representedTabs: getStructuredAgentSessionTabsByPaneKey(
useAppStore.getState().unifiedTabsByWorktree
),
entries,
retained,
runtimePaneTitlesByTabId,
@@ -64,6 +64,33 @@ describe('selectWorktreeAgentActivitySummary', () => {
vi.restoreAllMocks()
})
it('attributes migration-blocked UUID and legacy terminal panes without affecting other worktrees', () => {
for (const paneKey of [makePaneKey('tab-1', LEAF_ID), 'tab-1:0', undefined, 'malformed']) {
const state: AgentActivityInput = {
tabsByWorktree: { 'repo::/wt-1': [makeTab('tab-1', 'repo::/wt-1')] },
agentStatusEpoch: 0,
agentStatusByPaneKey: {},
retainedAgentsByPaneKey: {},
runtimeAgentOrchestrationByPaneKey: {},
migrationUnsupportedByPtyId: {
legacy: {
ptyId: 'legacy',
paneKey,
worktreeId: 'repo::/wt-1',
tabId: 'tab-1',
reason: 'legacy-numeric-pane-key',
source: 'local',
updatedAt: 1_000
}
}
}
expect(selectWorktreeAgentActivitySummary(state, 'repo::/wt-1').hasPermission).toBe(
paneKey !== undefined && paneKey !== 'malformed'
)
expect(selectWorktreeAgentActivitySummary(state, 'other').hasPermission).toBe(false)
}
})
it('builds one cached agent summary index for multiple worktree lookups', () => {
const nowSpy = vi.spyOn(Date, 'now').mockReturnValue(2_000)
const firstPaneKey = makePaneKey('tab-1', LEAF_ID)
@@ -1,3 +1,8 @@
import { getStructuredAgentSessionTabsByPaneKey } from '@/components/native-chat/structured-agent-session-tabs'
import {
selectVisibleAgentOrchestration,
type VisibleOrchestrationState
} from '@/runtime/visible-agent-orchestration'
import type { AppState } from '@/store'
import { isExplicitAgentStatusFresh } from '@/lib/agent-status'
import { migrationUnsupportedToAgentStatusEntry } from '../../../../shared/migration-unsupported-agent-entry'
@@ -56,10 +61,11 @@ export type AgentActivityInput = Pick<
| 'agentStatusByPaneKey'
| 'migrationUnsupportedByPtyId'
| 'retainedAgentsByPaneKey'
> & {
tabsByWorktree: AgentActivityTabsByWorktree
runtimeAgentOrchestrationByPaneKey?: AppState['runtimeAgentOrchestrationByPaneKey']
}
> &
VisibleOrchestrationState & {
tabsByWorktree: AgentActivityTabsByWorktree
runtimeAgentOrchestrationByPaneKey?: AppState['runtimeAgentOrchestrationByPaneKey']
}
type AgentActivityCache = {
tabsByWorktree: AgentActivityTabsByWorktree
@@ -82,7 +88,7 @@ export function selectWorktreeAgentActivitySummary(
function getWorktreeAgentActivitySummaries(
state: AgentActivityInput
): Map<string, WorktreeAgentActivitySummary> {
const runtimeAgentOrchestrationByPaneKey = state.runtimeAgentOrchestrationByPaneKey
const runtimeAgentOrchestrationByPaneKey = selectVisibleAgentOrchestration(state)
if (
agentActivityCache &&
agentActivityCache.tabsByWorktree === state.tabsByWorktree &&
@@ -114,7 +120,12 @@ function getWorktreeAgentActivitySummaries(
const now = Date.now()
for (const [paneKey, entry] of Object.entries(state.agentStatusByPaneKey)) {
const paneIdentity = parseAgentStatusPaneIdentity(paneKey)
const paneIdentity = parseAgentStatusPaneIdentity(
paneKey,
state.unifiedTabsByWorktree
? getStructuredAgentSessionTabsByPaneKey(state.unifiedTabsByWorktree).get(paneKey)
: undefined
)
if (!paneIdentity) {
continue
}
@@ -1,7 +1,10 @@
import { resolveAgentStatusWorktreeId } from '../../../../shared/agent-status-worktree-attribution'
import type { Tab } from '../../../../shared/tab-types'
import {
parseAgentStatusPaneIdentity,
resolveAgentStatusWorktreeId
} from '../../../../shared/agent-status-worktree-attribution'
import type { AppState } from '@/store/types'
import type { AgentStatusEntry } from '../../../../shared/agent-status-types'
import { parsePaneKey } from '../../../../shared/stable-pane-id'
import { isWebTerminalSurfaceTabId } from '../../../../shared/terminal-surface-id'
export type LiveEntriesByWorktreeCache = {
@@ -24,9 +27,10 @@ export function recordLiveEntriesFullRebuild(): void {
export function liveEntryWorktreeId(
paneKey: string,
entry: AgentStatusEntry,
tabIdToWorktreeId: Map<string, string>
tabIdToWorktreeId: Map<string, string>,
representedTabs?: ReadonlyMap<string, Tab>
): string | undefined {
const parsed = parsePaneKey(paneKey)
const parsed = parseAgentStatusPaneIdentity(paneKey, representedTabs?.get(paneKey))
if (!parsed) {
return undefined
}
@@ -42,7 +46,8 @@ export function liveEntryWorktreeId(
export function patchLiveEntriesByWorktree(
cache: LiveEntriesByWorktreeCache,
agentStatusByPaneKey: AppState['agentStatusByPaneKey'],
tabIdToWorktreeId: Map<string, string>
tabIdToWorktreeId: Map<string, string>,
representedTabs?: ReadonlyMap<string, Tab>
): Map<string, AgentStatusEntry[]> | null {
const previousMap = cache.agentStatusByPaneKey
const changed: { paneKey: string; entry: AgentStatusEntry }[] = []
@@ -76,7 +81,7 @@ export function patchLiveEntriesByWorktree(
const entriesByWorktree = new Map(cache.entriesByWorktree)
const clonedBuckets = new Set<string>()
for (const { paneKey, entry } of changed) {
const worktreeId = liveEntryWorktreeId(paneKey, entry, tabIdToWorktreeId)
const worktreeId = liveEntryWorktreeId(paneKey, entry, tabIdToWorktreeId, representedTabs)
if (!worktreeId) {
continue
}
@@ -1,3 +1,8 @@
import {
selectVisibleAgentOrchestration,
representedOrchestrationWorktrees,
type VisibleOrchestrationState
} from '@/runtime/visible-agent-orchestration'
import type { AppState } from '@/store/types'
import type { AgentStatusOrchestrationContext } from '../../../../shared/agent-status-types'
import { parsePaneKey } from '../../../../shared/stable-pane-id'
@@ -8,7 +13,8 @@ type OrchestrationIndexState = Pick<
| 'retainedAgentsByPaneKey'
| 'runtimeAgentOrchestrationByPaneKey'
| 'tabsByWorktree'
>
> &
VisibleOrchestrationState
type RuntimeOrchestrationRecord = Record<string, AgentStatusOrchestrationContext>
@@ -26,6 +32,7 @@ type PaneWorktreeProjectionCache = {
runtimeSource: OrchestrationIndexState['runtimeAgentOrchestrationByPaneKey']
liveSource: OrchestrationIndexState['agentStatusByPaneKey']
retainedSource: OrchestrationIndexState['retainedAgentsByPaneKey']
representedSource: OrchestrationIndexState['unifiedTabsByWorktree']
paneWorktreeIds: readonly (string | undefined)[]
}
@@ -76,27 +83,37 @@ function projectPaneWorktreeIds(
runtimeSource: OrchestrationIndexState['runtimeAgentOrchestrationByPaneKey'],
runtimeEntries: readonly [string, AgentStatusOrchestrationContext][],
agentStatusByPaneKey: OrchestrationIndexState['agentStatusByPaneKey'],
retainedAgentsByPaneKey: OrchestrationIndexState['retainedAgentsByPaneKey']
retainedAgentsByPaneKey: OrchestrationIndexState['retainedAgentsByPaneKey'],
state: OrchestrationIndexState
): readonly (string | undefined)[] {
// Cache by map identity so all cards share one attribution scan per publication.
if (
paneWorktreeProjectionCache?.runtimeSource === runtimeSource &&
paneWorktreeProjectionCache.liveSource === agentStatusByPaneKey &&
paneWorktreeProjectionCache.retainedSource === retainedAgentsByPaneKey
paneWorktreeProjectionCache.retainedSource === retainedAgentsByPaneKey &&
paneWorktreeProjectionCache.representedSource === state.unifiedTabsByWorktree
) {
return paneWorktreeProjectionCache.paneWorktreeIds
}
const paneWorktreeIds: (string | undefined)[] = []
for (const [paneKey] of runtimeEntries) {
const represented = state.unifiedTabsByWorktree
? representedOrchestrationWorktrees(state)
: new Map<string, string>()
for (const [paneKey, context] of runtimeEntries) {
paneWorktreeIds.push(
agentStatusByPaneKey[paneKey]?.worktreeId,
retainedAgentsByPaneKey[paneKey]?.worktreeId
retainedAgentsByPaneKey[paneKey]?.worktreeId,
represented.get(paneKey),
represented.size > 0 && context.parentPaneKey
? represented.get(context.parentPaneKey)
: undefined
)
}
paneWorktreeProjectionCache = {
runtimeSource,
liveSource: agentStatusByPaneKey,
retainedSource: retainedAgentsByPaneKey,
representedSource: state.unifiedTabsByWorktree,
paneWorktreeIds
}
return paneWorktreeIds
@@ -195,7 +212,15 @@ function buildIndex(
}
const liveWorktreeId = paneWorktreeIds[projectionCursor]
const retainedWorktreeId = paneWorktreeIds[projectionCursor + 1]
projectionCursor += 2
const representedWorktreeId = paneWorktreeIds[projectionCursor + 2]
const parentWorktreeId = paneWorktreeIds[projectionCursor + 3]
if (representedWorktreeId) {
targets.add(representedWorktreeId)
}
if (parentWorktreeId) {
targets.add(parentWorktreeId)
}
projectionCursor += 4
if (typeof liveWorktreeId === 'string') {
targets.add(liveWorktreeId)
}
@@ -227,8 +252,7 @@ function buildIndex(
export function selectWorktreeAgentOrchestrationIndex(
state: OrchestrationIndexState
): ReadonlyMap<string, RuntimeOrchestrationRecord> {
const runtimeAgentOrchestrationByPaneKey =
state.runtimeAgentOrchestrationByPaneKey ?? EMPTY_SOURCE
const runtimeAgentOrchestrationByPaneKey = selectVisibleAgentOrchestration(state)
// Cache context entries separately so unrelated live/retained churn cannot force enumeration.
if (runtimeEntriesCache?.source !== runtimeAgentOrchestrationByPaneKey) {
runtimeEntriesCache = {
@@ -251,7 +275,8 @@ export function selectWorktreeAgentOrchestrationIndex(
runtimeAgentOrchestrationByPaneKey,
runtimeEntries,
state.agentStatusByPaneKey ?? EMPTY_SOURCE,
state.retainedAgentsByPaneKey ?? EMPTY_SOURCE
state.retainedAgentsByPaneKey ?? EMPTY_SOURCE,
state
)
if (
orchestrationIndexCache?.runtimeSource === runtimeAgentOrchestrationByPaneKey &&
@@ -1,5 +1,6 @@
import type { AgentStatusEntry } from '../../../../shared/agent-status-types'
import { parsePaneKey } from '../../../../shared/stable-pane-id'
import { parseAgentStatusPaneIdentity } from '../../../../shared/agent-status-worktree-attribution'
import type { Tab } from '../../../../shared/tab-types'
import type { TerminalTab } from '../../../../shared/terminal-tab-types'
export function effectiveWorktreeAgentRowStartedAt(entry: AgentStatusEntry): number {
@@ -8,9 +9,10 @@ export function effectiveWorktreeAgentRowStartedAt(entry: AgentStatusEntry): num
export function tabFromWorktreeAttributedStatusEntry(
entry: AgentStatusEntry,
effectiveStartedAt: number
effectiveStartedAt: number,
representedTab?: Tab
): TerminalTab | null {
const parsed = parsePaneKey(entry.paneKey)
const parsed = parseAgentStatusPaneIdentity(entry.paneKey, representedTab)
if (!parsed || !entry.worktreeId) {
return null
}
@@ -3,21 +3,7 @@ import type {
AgentStatusOrchestrationContext
} from '../../../../shared/agent-status-types'
function orchestrationContextsEqual(
a: AgentStatusOrchestrationContext,
b: AgentStatusOrchestrationContext
): boolean {
return (
a.taskId === b.taskId &&
a.dispatchId === b.dispatchId &&
a.taskTitle === b.taskTitle &&
a.displayName === b.displayName &&
a.parentTerminalHandle === b.parentTerminalHandle &&
a.parentPaneKey === b.parentPaneKey &&
a.coordinatorHandle === b.coordinatorHandle &&
a.orchestrationRunId === b.orchestrationRunId
)
}
import { orchestrationContextsEqual } from '@/store/slices/agent-status/agent-status-orchestration-context'
export function entryWithRuntimeOrchestration(
entry: AgentStatusEntry,
@@ -1,3 +1,4 @@
import { getStructuredAgentSessionTabsByPaneKey } from '@/components/native-chat/structured-agent-session-tabs'
import type { RetainedAgentEntry } from '@/store/slices/agent-status/agent-status-contract'
import type { AppState } from '@/store/types'
import type {
@@ -129,6 +130,9 @@ function getLiveEntriesByWorktree(state: WorktreeAgentRowsState): Map<string, Ag
}
const tabIdToWorktreeId = getLiveTabIdToWorktreeId(tabsByWorktree, unifiedTabsByWorktree)
const represented = unifiedTabsByWorktree
? getStructuredAgentSessionTabsByPaneKey(unifiedTabsByWorktree)
: undefined
if (
liveEntriesByWorktreeCache?.tabsByWorktree === tabsByWorktree &&
liveEntriesByWorktreeCache.unifiedTabsByWorktree === unifiedTabsByWorktree
@@ -136,7 +140,8 @@ function getLiveEntriesByWorktree(state: WorktreeAgentRowsState): Map<string, Ag
const patched = patchLiveEntriesByWorktree(
liveEntriesByWorktreeCache,
agentStatusByPaneKey,
tabIdToWorktreeId
tabIdToWorktreeId,
represented
)
if (patched) {
liveEntriesByWorktreeCache = {
@@ -152,7 +157,7 @@ function getLiveEntriesByWorktree(state: WorktreeAgentRowsState): Map<string, Ag
const previous = liveEntriesByWorktreeCache?.entriesByWorktree
const entriesByWorktree = new Map<string, AgentStatusEntry[]>()
for (const [paneKey, entry] of Object.entries(agentStatusByPaneKey)) {
const worktreeId = liveEntryWorktreeId(paneKey, entry, tabIdToWorktreeId)
const worktreeId = liveEntryWorktreeId(paneKey, entry, tabIdToWorktreeId, represented)
if (!worktreeId) {
continue
}
@@ -1,3 +1,5 @@
import type { Tab } from '../../../../shared/tab-types'
import { parseAgentStatusPaneIdentity } from '../../../../shared/agent-status-worktree-attribution'
import type { DashboardAgentRow } from '@/components/dashboard/useDashboardData'
import { isExplicitAgentStatusFresh } from '@/lib/agent-status'
import type { RetainedAgentEntry } from '@/store/slices/agent-status/agent-status-contract'
@@ -138,6 +140,7 @@ function markCompletedWorkerParentPaneKeysSeen(args: {
export function buildWorktreeAgentRows(args: {
tabs: TerminalTab[]
representedTabs?: ReadonlyMap<string, Tab>
entries: AgentStatusEntry[]
retained: RetainedAgentEntry[]
runtimePaneTitlesByTabId?: Record<string, Record<number, string>>
@@ -153,7 +156,10 @@ export function buildWorktreeAgentRows(args: {
const entriesByTabId = new Map<string, AgentStatusEntry[]>()
for (const entry of args.entries) {
const parsed = parsePaneKey(entry.paneKey)
const parsed = parseAgentStatusPaneIdentity(
entry.paneKey,
args.representedTabs?.get(entry.paneKey)
)
if (!parsed) {
continue
}
@@ -211,7 +217,11 @@ export function buildWorktreeAgentRows(args: {
}
const rowEntry = entryWithRuntimeOrchestration(entry, args.runtimeAgentOrchestrationByPaneKey)
const startedAt = effectiveWorktreeAgentRowStartedAt(rowEntry)
const tab = tabFromWorktreeAttributedStatusEntry(rowEntry, startedAt)
const tab = tabFromWorktreeAttributedStatusEntry(
rowEntry,
startedAt,
args.representedTabs?.get(rowEntry.paneKey)
)
if (!tab) {
continue
}
@@ -1,3 +1,8 @@
import {
selectDetectedWorktreesByRepo,
selectFolderWorkspaces,
selectWorktreesByRepo
} from '@/store/workspace-record-selectors'
import {
LOCAL_EXECUTION_HOST_ID,
parseExecutionHostId,
@@ -7,12 +12,6 @@ import {
import type { Tab } from '../../../shared/tab-types'
import { getExecutionHostIdForWorktree } from '@/lib/worktree-runtime-owner'
import type { WorktreeRuntimeOwnerState } from '@/lib/worktree-runtime-owner-state'
import type { AppState } from '@/store/types'
import {
selectDetectedWorktreesByRepo,
selectFolderWorkspaces,
selectWorktreesByRepo
} from '@/store/workspace-record-selectors'
import { isTwinWorkspace, namedHostForOwnerRef, resolveOwner } from '@/lib/resolve-owner'
import { authorityKey } from '../../../shared/host-authority'
import { LOCAL_STRUCTURED_SESSION_OWNER } from './local-structured-session-owner'
@@ -92,7 +91,9 @@ export function legacyStructuredChatRenameOwner(
}
/** Catalog inputs independent of the user's current workspace selection. */
export function structuredAgentSessionCatalogOwnerInputs(state: AppState): unknown[] {
export function structuredAgentSessionCatalogOwnerInputs(
state: WorktreeRuntimeOwnerState
): unknown[] {
return [
state.repos,
selectWorktreesByRepo(state),
@@ -105,7 +106,7 @@ export function structuredAgentSessionCatalogOwnerInputs(state: AppState): unkno
}
/** Inputs to the legacy workspace-owner resolver, compared before scanning chat tabs. */
export function structuredAgentSessionOwnerInputs(state: AppState): unknown[] {
export function structuredAgentSessionOwnerInputs(state: WorktreeRuntimeOwnerState): unknown[] {
return [
...structuredAgentSessionCatalogOwnerInputs(state),
state.settings,
@@ -0,0 +1,284 @@
import type { AppState } from '@/store/types'
import type { WorktreeRuntimeOwnerState } from '@/lib/worktree-runtime-owner-state'
import { getStructuredAgentSessionTabs } from '@/components/native-chat/structured-agent-session-tabs'
import { LOCAL_EXECUTION_HOST_ID, toRuntimeExecutionHostId } from '../../../shared/execution-host'
import {
isRemoteRuntimePtyId,
parseRemoteRuntimePtyId
} from '../../../shared/remote-runtime/remote-runtime-pty-id'
import { parseAgentStatusPaneIdentity } from '../../../shared/agent-status-worktree-attribution'
import {
structuredAgentSessionPaneKey,
structuredAgentSessionTabId
} from '../../../shared/structured-agent-session-projection'
import type { AgentStatusOrchestrationContext } from '../../../shared/agent-status-types'
import { orchestrationContextsEqual } from '@/store/slices/agent-status/agent-status-orchestration-context'
import {
resolveStructuredAgentSessionOwner,
structuredAgentSessionOwnerForTab,
structuredAgentSessionOwnerInputs
} from './structured-agent-session-owner'
type Contexts = Record<string, AgentStatusOrchestrationContext>
export type VisibleOrchestrationState = WorktreeRuntimeOwnerState &
Partial<
Pick<
AppState,
| 'unifiedTabsByWorktree'
| 'agentStatusByPaneKey'
| 'retainedAgentsByPaneKey'
| 'runtimeAgentOrchestrationByPaneKey'
| 'ptyIdsByTabId'
>
> & {
tabsByWorktree?: Record<string, readonly { id: string; ptyId?: string | null }[]>
}
const EMPTY: Record<string, never> = {}
const producerByContext = new WeakMap<AgentStatusOrchestrationContext, string>()
export function orchestrationProducer(context: AgentStatusOrchestrationContext): string {
return producerByContext.get(context) ?? LOCAL_EXECUTION_HOST_ID
}
export function recordOrchestrationProducer(
context: AgentStatusOrchestrationContext,
host: string
): void {
producerByContext.set(context, host)
}
type RowIdentities = {
inputs: unknown[]
aliases: Map<string, string>
canonical: Map<string, { key: string; host: string | null }>
worktrees: Map<string, string>
}
let rowCache: RowIdentities | undefined
let cache: { inputs: unknown[]; contexts: Contexts } | undefined
let builds = 0
let aliasBuilds = 0
let visits = 0
export function visibleOrchestrationWorkForTest(): {
builds: number
aliasBuilds: number
visits: number
} {
return { builds, aliasBuilds, visits }
}
const aliasKey = (host: string, key: string) => `${host}\0${key}`
function rowIdentities(state: VisibleOrchestrationState): RowIdentities {
const inputs = [state.unifiedTabsByWorktree, ...structuredAgentSessionOwnerInputs(state)]
if (rowCache && inputs.every((value, index) => value === rowCache?.inputs[index])) {
return rowCache
}
aliasBuilds++
const aliases = new Map<string, string>()
const worktrees = new Map<string, string>()
const canonical = new Map<string, { key: string; host: string | null }>()
for (const tab of getStructuredAgentSessionTabs(state.unifiedTabsByWorktree ?? EMPTY)) {
visits++
if (!tab.entityId) {
continue
}
const key = structuredAgentSessionPaneKey(
structuredAgentSessionTabId(tab.entityId),
tab.entityId
)
const actual = structuredAgentSessionPaneKey(tab.id, tab.entityId)
const host = structuredAgentSessionOwnerForTab(state, tab)
canonical.set(actual, { key, host })
worktrees.set(actual, tab.worktreeId)
if (host && !aliases.has(aliasKey(host, key))) {
aliases.set(aliasKey(host, key), actual)
}
}
rowCache = { inputs, aliases, canonical, worktrees }
return rowCache
}
let terminalCache:
| { inputs: unknown[]; hosts: Map<string, string | null>; ptys: Map<string, string | null> }
| undefined
function terminalProvenance(state: VisibleOrchestrationState) {
const inputs = [
state.unifiedTabsByWorktree,
state.tabsByWorktree,
state.ptyIdsByTabId,
state.retainedAgentsByPaneKey
]
if (terminalCache && inputs.every((value, index) => value === terminalCache?.inputs[index])) {
return terminalCache
}
const hosts = new Map<string, string | null>()
const ptys = new Map<string, string | null>()
const merge = (map: Map<string, string | null>, key: string, host: string | null) => {
map.set(key, map.has(key) && map.get(key) !== host ? null : host)
}
const ptyHost = (id?: string | null): string | null | undefined => {
if (!id) {
return undefined
}
const remote = parseRemoteRuntimePtyId(id)
return remote?.environmentId
? toRuntimeExecutionHostId(remote.environmentId)
: isRemoteRuntimePtyId(id)
? null
: undefined
}
for (const [tab, ids] of Object.entries(state.ptyIdsByTabId ?? EMPTY)) {
for (const id of ids) {
visits++
const host = ptyHost(id)
if (host !== undefined) {
merge(ptys, tab, host)
}
}
}
for (const tabs of Object.values(state.unifiedTabsByWorktree ?? EMPTY)) {
for (const tab of tabs) {
visits++
if (tab.contentType === 'terminal' && tab.executionHostId) {
merge(hosts, aliasKey(tab.worktreeId, tab.entityId), tab.executionHostId)
}
}
}
for (const [worktree, tabs] of Object.entries(state.tabsByWorktree ?? EMPTY)) {
for (const tab of tabs) {
visits++
const host = ptyHost(tab.ptyId)
if (host !== undefined) {
merge(hosts, aliasKey(worktree, tab.id), host)
}
}
}
for (const retained of Object.values(state.retainedAgentsByPaneKey ?? EMPTY)) {
visits++
const host = ptyHost(retained.tab.ptyId)
if (host !== undefined) {
merge(hosts, aliasKey(retained.worktreeId, retained.tab.id), host)
}
}
terminalCache = { inputs, hosts, ptys }
return terminalCache
}
function projection(state: VisibleOrchestrationState): NonNullable<typeof cache> {
const rows = rowIdentities(state)
const terminals = terminalProvenance(state)
const inputs = [
state.runtimeAgentOrchestrationByPaneKey,
state.agentStatusByPaneKey,
state.retainedAgentsByPaneKey,
terminals,
rows
]
if (cache && inputs.every((value, index) => value === cache?.inputs[index])) {
return cache
}
builds++
const { aliases, canonical } = rows
const contexts: Contexts = Object.fromEntries([])
const visibleKey = (key: string, host: string | null) => {
if (!host) {
return canonical.has(key) ? aliasKey('unknown', key) : key
}
const alias = aliases.get(aliasKey(host, key))
// An identically spelled row from another runtime cannot satisfy this relationship.
return (
alias ?? (canonical.has(key) && canonical.get(key)?.host !== host ? aliasKey(host, key) : key)
)
}
const adapt = (key: string, context: AgentStatusOrchestrationContext, host: string | null) => {
visits++
const actual = visibleKey(key, host)
const parent = context.parentPaneKey ? visibleKey(context.parentPaneKey, host) : undefined
const next = parent === context.parentPaneKey ? context : { ...context, parentPaneKey: parent }
const previous = cache?.contexts[actual]
contexts[actual] =
next !== context && previous && orchestrationContextsEqual(previous, next) ? previous : next
}
for (const [key, context] of Object.entries(state.runtimeAgentOrchestrationByPaneKey ?? EMPTY)) {
adapt(key, context, producerByContext.get(context) ?? LOCAL_EXECUTION_HOST_ID)
}
const embedded = (
entry: AppState['agentStatusByPaneKey'][string],
worktreeId = entry.worktreeId
) => {
visits++
if (!entry?.orchestration) {
return
}
const row = canonical.get(entry.paneKey)
const runtime = state.runtimeAgentOrchestrationByPaneKey?.[row?.key ?? entry.paneKey]
if (
runtime &&
(!row || row.host === orchestrationProducer(runtime)) &&
runtime.taskId === entry.orchestration.taskId &&
runtime.dispatchId === entry.orchestration.dispatchId
) {
// Matching graph facts already carry the context's producer, independently of execution routing.
return
}
const tabId = parseAgentStatusPaneIdentity(entry.paneKey)?.tabId
const terminalKey = worktreeId && tabId ? aliasKey(worktreeId, tabId) : null
const tabHost = terminalKey ? terminals.hosts.get(terminalKey) : undefined
const ptyHost = tabId ? terminals.ptys.get(tabId) : undefined
const terminalHost =
tabHost === undefined
? ptyHost
: ptyHost === undefined || tabHost === ptyHost
? tabHost
: null
const host = row
? row.host
: terminalHost !== undefined
? terminalHost
: !entry.connectionId && worktreeId
? resolveStructuredAgentSessionOwner(state, worktreeId)
: null
if (
entry.orchestration.parentPaneKey &&
visibleKey(entry.orchestration.parentPaneKey, host) !== entry.orchestration.parentPaneKey
) {
adapt(entry.paneKey, entry.orchestration, host)
}
}
for (const entry of Object.values(state.agentStatusByPaneKey ?? EMPTY)) {
embedded(entry)
}
for (const retained of Object.values(state.retainedAgentsByPaneKey ?? EMPTY)) {
embedded(retained.entry, retained.worktreeId)
}
const previous = cache?.contexts
const equal =
previous &&
Object.keys(previous).length === Object.keys(contexts).length &&
Object.keys(contexts).every((key) => previous[key] === contexts[key])
cache = { inputs, contexts: equal ? previous : contexts }
return cache
}
/** Canonical contexts stay in storage; actual rows and parent aliases are a shared read-only view. */
export function selectVisibleAgentOrchestration(state: VisibleOrchestrationState): Contexts {
if (!state.unifiedTabsByWorktree) {
return state.runtimeAgentOrchestrationByPaneKey ?? EMPTY
}
return projection(state).contexts
}
/** The same row identity joins graph enrichment and first status paint, without translating stored parents. */
export function canonicalOrchestrationForRow(
state: VisibleOrchestrationState,
paneKey: string
): AgentStatusOrchestrationContext | undefined {
const row = rowIdentities(state).canonical.get(paneKey)
const context = state.runtimeAgentOrchestrationByPaneKey?.[row?.key ?? paneKey]
return context &&
(!row || row.host === (producerByContext.get(context) ?? LOCAL_EXECUTION_HOST_ID))
? context
: undefined
}
export function representedOrchestrationWorktrees(
state: VisibleOrchestrationState
): ReadonlyMap<string, string> {
return rowIdentities(state).worktrees
}
@@ -1,3 +1,4 @@
import { canonicalOrchestrationForRow } from '@/runtime/visible-agent-orchestration'
import { sameAgentStatusTerminalOwner } from '../../../../../shared/agent-status-terminal-owner'
import type { AppState } from '../../types'
import { resolveAgentStatusLiveEntryMainAgent } from './agent-status-live-entry-main-agent'
@@ -141,7 +142,7 @@ export function buildAgentStatusLiveEntry(
) {
return { entry: null, reason: 'suppressed-inherited-terminal' }
}
const runtimeOrchestration = state.runtimeAgentOrchestrationByPaneKey[paneKey]
const runtimeOrchestration = canonicalOrchestrationForRow(state, paneKey)
const runtimeMergedOrchestration = runtimeOrchestration
? mergeCurrentOrchestrationContext(existing?.orchestration, runtimeOrchestration)
: undefined
@@ -1,3 +1,9 @@
import {
canonicalOrchestrationForRow,
recordOrchestrationProducer,
orchestrationProducer
} from '@/runtime/visible-agent-orchestration'
import { LOCAL_EXECUTION_HOST_ID } from '../../../../../shared/execution-host'
import type {
AgentStatusEntry,
AgentStatusOrchestrationContext
@@ -10,7 +16,7 @@ import {
} from '../../../../../shared/agent-row-primary-text'
import {
mergeCurrentOrchestrationContext,
orchestrationMapsEqual
orchestrationContextsEqual
} from './agent-status-orchestration-context'
export function createAgentStatusOrchestrationActions(
@@ -19,20 +25,42 @@ export function createAgentStatusOrchestrationActions(
const { get, set } = runtime
return {
setRuntimeAgentOrchestrationByPaneKey: (
entries: Record<string, AgentStatusOrchestrationContext>
entries: Record<string, AgentStatusOrchestrationContext>,
producerHost = LOCAL_EXECUTION_HOST_ID
) => {
const generatedTitleUpdates: AgentStatusEntry[] = []
set((s, changedPaneKeys) => {
const runtimeMapChanged = !orchestrationMapsEqual(
s.runtimeAgentOrchestrationByPaneKey,
entries
)
const previous = s.runtimeAgentOrchestrationByPaneKey
const reconciled: Record<string, AgentStatusOrchestrationContext> = Object.fromEntries([])
let runtimeMapChanged = Object.keys(previous).length !== Object.keys(entries).length
for (const [key, context] of Object.entries(entries)) {
const old = previous[key]
const value =
old &&
orchestrationProducer(old) === producerHost &&
orchestrationContextsEqual(old, context)
? old
: context
reconciled[key] = value
recordOrchestrationProducer(value, producerHost)
if (value !== old) {
runtimeMapChanged = true
}
}
const canonicalState = {
...s,
runtimeAgentOrchestrationByPaneKey: runtimeMapChanged ? reconciled : previous
}
let nextLive = s.agentStatusByPaneKey
let liveChanged = false
let nextRetained = s.retainedAgentsByPaneKey
let retainedChanged = false
for (const [paneKey, runtimeOrchestration] of Object.entries(entries)) {
for (const paneKey of new Set([...Object.keys(nextLive), ...Object.keys(nextRetained)])) {
const runtimeOrchestration = canonicalOrchestrationForRow(canonicalState, paneKey)
if (!runtimeOrchestration) {
continue
}
const liveEntry = nextLive[paneKey]
if (liveEntry) {
const merged = mergeCurrentOrchestrationContext(
@@ -84,7 +112,7 @@ export function createAgentStatusOrchestrationActions(
}
return {
...(runtimeMapChanged ? { runtimeAgentOrchestrationByPaneKey: entries } : {}),
...(runtimeMapChanged ? { runtimeAgentOrchestrationByPaneKey: reconciled } : {}),
...(liveChanged ? { agentStatusByPaneKey: nextLive } : {}),
...(retainedChanged ? { retainedAgentsByPaneKey: nextRetained } : {}),
...(liveChanged ? { agentStatusEpoch: s.agentStatusEpoch + 1 } : {})
@@ -1,3 +1,4 @@
import { canonicalOrchestrationForRow } from '@/runtime/visible-agent-orchestration'
import type { RetainedAgentEntry } from './agent-status-contract'
import type { AgentStatusSlice } from './agent-status-slice-contract'
import type { AgentStatusRuntime } from './agent-status-runtime'
@@ -34,7 +35,7 @@ export function createAgentStatusRetentionActions(
}
const next = { ...s.retainedAgentsByPaneKey }
for (const retained of entries) {
const runtimeOrchestration = s.runtimeAgentOrchestrationByPaneKey[retained.entry.paneKey]
const runtimeOrchestration = canonicalOrchestrationForRow(s, retained.entry.paneKey)
const mergedOrchestration = runtimeOrchestration
? mergeCurrentOrchestrationContext(retained.entry.orchestration, runtimeOrchestration)
: retained.entry.orchestration
@@ -121,7 +121,8 @@ export type AgentStatusSlice = {
clearAgentLaunchConfig: (paneKey: string) => void
setRuntimeAgentOrchestrationByPaneKey: (
entries: Record<string, AgentStatusOrchestrationContext>
entries: Record<string, AgentStatusOrchestrationContext>,
producerHost?: string
) => void
setMigrationUnsupportedPty: (entry: MigrationUnsupportedPtyEntry) => void
@@ -1,3 +1,4 @@
import { getStructuredAgentSessionTabsByPaneKey } from '@/components/native-chat/structured-agent-session-tabs'
import type { AppState } from '../types'
import type { WorkspaceCleanupCandidate } from '../../../../shared/workspace-cleanup'
import { parsePaneKey } from '../../../../shared/stable-pane-id'
@@ -68,6 +69,9 @@ export function getWorkspaceCleanupAgentEvidence(
for (const [worktreeId, worktreeCandidates] of candidatesByWorktreeId) {
const rows = buildWorktreeAgentRows({
tabs: state.tabsByWorktree[worktreeId] ?? [],
representedTabs: state.unifiedTabsByWorktree
? getStructuredAgentSessionTabsByPaneKey(state.unifiedTabsByWorktree)
: undefined,
entries: selectLiveAgentStatusEntriesForWorktree(state, worktreeId),
retained: selectRetainedAgentEntriesForWorktree(state, worktreeId),
runtimePaneTitlesByTabId: state.runtimePaneTitlesByTabId,
@@ -1,3 +1,5 @@
import type { Tab } from './tab-types'
import { structuredAgentSessionPaneKey } from './structured-agent-session-projection'
import type { AgentStatusEntry, AgentStatusOrchestrationContext } from './agent-status-types'
import { isWebTerminalSurfaceTabId } from './terminal-surface-id'
import { parseLegacyNumericPaneKey, parsePaneKey } from './stable-pane-id'
@@ -5,11 +7,18 @@ import { parseLegacyNumericPaneKey, parsePaneKey } from './stable-pane-id'
export type AgentStatusPaneIdentity = { tabId: string; paneId: string }
export function parseAgentStatusPaneIdentity(
paneKey: string | undefined
paneKey: string | undefined,
representedTab?: Pick<Tab, 'id' | 'entityId' | 'contentType'>
): AgentStatusPaneIdentity | null {
if (!paneKey) {
return null
}
if (
representedTab?.contentType === 'agent-session' &&
structuredAgentSessionPaneKey(representedTab.id, representedTab.entityId) === paneKey
) {
return { tabId: representedTab.id, paneId: paneKey.slice(representedTab.id.length + 1) }
}
const parsed = parsePaneKey(paneKey)
if (parsed) {
return { tabId: parsed.tabId, paneId: parsed.leafId }
@@ -0,0 +1,35 @@
import type { AgentStatusOrchestrationContext } from './agent-status-types'
import type { OrcaSessionId } from './orca-session-address'
import type { RuntimeRpcResponse } from './runtime-rpc-envelope'
import type { RuntimeWorktreePsSummary } from './runtime-types'
// Keep desktop-only imports in the native fixture; its export checks this consumer contract.
export type RuntimeAgentLineageTestModule = {
LINEAGE_PARENT: OrcaSessionId
LINEAGE_CHILD: OrcaSessionId
canonicalChatRow(id: string): string
publicLineageFixture(worktreeId?: string): {
db: {
db: { prepare(sql: string): { run(...values: string[]): unknown } }
close(): void
}
projection: {
buildByPaneKey(): Record<string, AgentStatusOrchestrationContext> | undefined
}
build(): RuntimeWorktreePsSummary
privateHandle: string
privatePane: string
run: { id: string }
}
}
export type RuntimeAgentLineageCatalogTestModule = {
createLineageCatalogDispatcher(build: () => RuntimeWorktreePsSummary): {
dispatch(request: {
id: string
authToken: string
method: string
params?: Record<string, unknown>
}): Promise<RuntimeRpcResponse<unknown>>
}
}