Files
orca/src/shared/codex-subagent-roster.test.ts
T
Brennan Benson 978b207cc1 fix(agent-status): never drop a running helper for lack of room (#30416)
* fix(agent-status): never drop a running helper for lack of room

Helper state (subagents, background tasks and commands) was bounded by counts and byte budgets that refused or evicted live records once hit, so the agent kept working while Orca listed it wrong. Every one of these records already dies with its session, pane or chat, so the count and size caps go; identity-history, transcript and transport bounds stay.

* fix(agent-status): keep the status field limit, measured without the subagent roster

The previous commit dropped the 256 KiB status check outright; it still guards every other field. Only the roster, whose rows are bounded individually, is left out of the measurement.

* fix(agent-status): fit helper previews and walk lineage once

* fix(agent-status): skip an oversized Pi row instead of stopping, and parse every envelope the store can write

Review follow-up: one long row no longer hides later rows that still fit the request, and the transport envelope's reader no longer refuses a size its writer now produces.
2026-10-19 00:31:42 -07:00

111 lines
3.9 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { AGENT_MODEL_MAX_LENGTH, AGENT_TYPE_MAX_LENGTH } from './agent-status-types'
import {
codexRosterChildWorkLiveness,
codexRosterToSnapshots,
finishCodexSubagent,
setCodexSubagentModel,
upsertCodexSubagent,
type CodexSubagentRoster
} from './codex-subagent-roster'
describe('Codex subagent roster', () => {
it('normalizes retained identity fields before storing them', () => {
const roster: CodexSubagentRoster = new Map()
upsertCodexSubagent(
roster,
' child-1 ',
{
agentType: `reviewer\n${'x'.repeat(AGENT_TYPE_MAX_LENGTH * 2)}`,
description: 'Review the sidebar lifecycle',
model: `gpt-model-${'x'.repeat(AGENT_MODEL_MAX_LENGTH * 2)}`,
state: 'working'
},
10
)
const snapshot = codexRosterToSnapshots(roster)?.[0]
expect([...roster.keys()]).toEqual(['child-1'])
expect(snapshot?.agentType).toHaveLength(AGENT_TYPE_MAX_LENGTH)
expect(snapshot?.agentType).not.toContain('\n')
expect(snapshot?.description).toBe('Review the sidebar lifecycle')
expect(snapshot?.model).toHaveLength(AGENT_MODEL_MAX_LENGTH)
finishCodexSubagent(roster, ' child-1 ')
expect(roster.size).toBe(0)
})
it('rejects an id that would normalize to an invisible child', () => {
const roster: CodexSubagentRoster = new Map()
upsertCodexSubagent(roster, ' ', { state: 'waiting' }, 10)
expect(roster.size).toBe(0)
})
describe('codexRosterChildWorkLiveness', () => {
it('reads every child as agent work, a waiting one above the rest, and nothing as a watch loop', () => {
const roster: CodexSubagentRoster = new Map()
expect(codexRosterChildWorkLiveness(undefined)).toBeNull()
expect(codexRosterChildWorkLiveness(roster)).toBeNull()
upsertCodexSubagent(roster, 'a', { state: 'working' }, 1)
expect(codexRosterChildWorkLiveness(roster)).toBe('working')
upsertCodexSubagent(roster, 'b', { state: 'waiting' }, 2)
expect(codexRosterChildWorkLiveness(roster)).toBe('waiting')
finishCodexSubagent(roster, 'b')
expect(codexRosterChildWorkLiveness(roster)).toBe('working')
})
})
describe('setCodexSubagentModel', () => {
it('records the model without disturbing the child lifecycle or label', () => {
const roster: CodexSubagentRoster = new Map()
upsertCodexSubagent(roster, 'child-1', { description: '/root/audit', state: 'waiting' }, 10)
setCodexSubagentModel(roster, 'child-1', ' gpt-5.6-terra ')
expect(codexRosterToSnapshots(roster)).toEqual([
{
id: 'child-1',
agentType: undefined,
description: '/root/audit',
model: 'gpt-5.6-terra',
state: 'waiting',
startedAt: 10
}
])
})
it('never creates a row for a child that is no longer tracked', () => {
const roster: CodexSubagentRoster = new Map()
upsertCodexSubagent(roster, 'child-1', { state: 'working' }, 10)
finishCodexSubagent(roster, 'child-1')
// A model read racing a completed child must not resurrect its row.
setCodexSubagentModel(roster, 'child-1', 'gpt-5.6-terra')
expect(roster.size).toBe(0)
})
it('keeps a known model when the new value is empty', () => {
const roster: CodexSubagentRoster = new Map()
upsertCodexSubagent(roster, 'child-1', { model: 'gpt-5.6-sol', state: 'working' }, 10)
setCodexSubagentModel(roster, 'child-1', ' ')
setCodexSubagentModel(roster, 'child-1', undefined)
expect(roster.get('child-1')?.model).toBe('gpt-5.6-sol')
})
it('bounds an oversized model to the shared cap', () => {
const roster: CodexSubagentRoster = new Map()
upsertCodexSubagent(roster, 'child-1', { state: 'working' }, 10)
setCodexSubagentModel(roster, 'child-1', 'x'.repeat(AGENT_MODEL_MAX_LENGTH + 50))
expect(roster.get('child-1')?.model).toHaveLength(AGENT_MODEL_MAX_LENGTH)
})
})
})