wip(agent-status): alternative resolver design from the abandoned #16157 review

Recovered from an uncommitted worktree, not authored fresh. The first #16157 review agent drafted
this before its session died on an "Invalid previous_response_id" API error; I reported the work as
lost with the session, which was wrong — it was never committed but never gone either.

Its shape differs from what shipped: a discriminated `PaneAgentDisplayIdentity` union
(`kind: 'resolved' | 'unresolved'` with a `reason`) instead of a nullable agent, an explicit
`PaneAgentDisplayPolicy`, and a `PaneAgentEvidenceOrder` that lets a consumer state its own
ranking rather than sharing one global order.

Kept for reference while the run-generation work is designed — the display/action split it proposes
is the same question the delta review raised about incomparable evidence. Not proposed for merge as
is; not rebased; not verified.
This commit is contained in:
Brennan Benson
2026-08-25 10:49:09 -07:00
parent 32e3e0502f
commit 75e452851b
2 changed files with 395 additions and 200 deletions
+251 -111
View File
@@ -1,145 +1,285 @@
import { describe, expect, it } from 'vitest'
import {
PANE_AGENT_EVIDENCE_SOURCES,
PANE_AGENT_DISPLAY_POLICIES,
type PaneAgentEvidence,
resolvePaneAgentIdentity
type PaneAgentRun,
resolvePaneAgentDisplayIdentity
} from './pane-agent-identity-resolver'
const resolve = (evidence: PaneAgentEvidence[], extra = {}) =>
resolvePaneAgentIdentity({ evidence, ...extra })
const currentRun: PaneAgentRun = { hostAuthorityId: 'host-1', generation: 8 }
const previousRun: PaneAgentRun = { hostAuthorityId: 'host-1', generation: 7 }
const otherHostRun: PaneAgentRun = { hostAuthorityId: 'host-2', generation: 8 }
describe('resolvePaneAgentIdentity', () => {
describe('a display title is the last thing consulted', () => {
it.each(PANE_AGENT_EVIDENCE_SOURCES.filter((s) => s !== 'title' && s !== 'sibling'))(
'lets %s outrank a conflicting title',
const resolveFocused = (evidence: PaneAgentEvidence[], extra = {}) =>
resolvePaneAgentDisplayIdentity({ policy: 'focused-pane', evidence, ...extra })
describe('resolvePaneAgentDisplayIdentity', () => {
describe('named display policies', () => {
it.each(PANE_AGENT_DISPLAY_POLICIES['focused-pane'].filter((s) => s !== 'title'))(
'lets focused-pane %s outrank a conflicting title',
(source) => {
const result = resolve([
{ source: 'title', agent: 'codex' },
{ source, agent: 'grok' }
])
expect(result.agent).toBe('grok')
expect(result.source).toBe(source)
expect(
resolveFocused([
{ source: 'title', agent: 'codex' },
{ source, agent: 'grok' }
])
).toMatchObject({ kind: 'resolved', agent: 'grok', source })
}
)
it('uses the title only when nothing else is eligible', () => {
expect(resolve([{ source: 'title', agent: 'codex' }])).toMatchObject({
agent: 'codex',
source: 'title'
it('lets a host-observed process override Orca launch intent', () => {
expect(
resolveFocused([
{ source: 'launch', agent: 'claude' },
{ source: 'process', agent: 'codex' }
])
).toMatchObject({ kind: 'resolved', agent: 'codex', source: 'process' })
})
it('keeps sibling evidence out of focused-pane identity', () => {
expect(resolveFocused([{ source: 'sibling', agent: 'codex' }])).toEqual({
kind: 'unresolved',
reason: 'no-evidence'
})
})
it('outranks the launch record with nothing weaker than the launch record', () => {
// The tab ladder currently puts the parsed title ABOVE activeLaunchAgent, so a string Orca
// parsed beats a fact Orca owns. That inversion cannot be expressed here.
const result = resolve([
{ source: 'launch', agent: 'claude' },
{ source: 'title', agent: 'gemini' }
])
expect(result.agent).toBe('claude')
it('uses sibling only after the active pane title for a tab aggregate', () => {
expect(
resolvePaneAgentDisplayIdentity({
policy: 'tab-aggregate',
evidence: [
{ source: 'sibling', agent: 'codex' },
{ source: 'title', agent: 'grok' }
]
})
).toMatchObject({ kind: 'resolved', agent: 'grok', source: 'title' })
})
})
describe('run generation separates the bug from the legitimate reclaim', () => {
// Both shapes are `completed hook = A, title = B`. Ordering alone cannot tell them apart.
const shape = (hookRun: number, titleRun: number): PaneAgentEvidence[] => [
{ source: 'completed-hook', agent: 'claude', runId: hookRun },
{ source: 'title', agent: 'codex', runId: titleRun }
describe('host-owned agent-run identity', () => {
const shape = (hookRun: PaneAgentRun, titleRun: PaneAgentRun): PaneAgentEvidence[] => [
{ source: 'completed-hook', agent: 'claude', run: hookRun },
{ source: 'title', agent: 'codex', run: titleRun }
]
it('keeps the completed hook when both belong to the current run', () => {
// The reported bug: nothing new started, so the hook is still the truth.
const result = resolvePaneAgentIdentity({ evidence: shape(7, 7), currentRunId: 7 })
expect(result).toMatchObject({ agent: 'claude', source: 'completed-hook' })
expect(result.supersededSources).toEqual([])
})
it('drops the completed hook once a new run has started', () => {
// The legitimate reclaim: the pane was reused, so run 7's hook describes an agent that is
// no longer there. It is ineligible, not merely outranked.
const result = resolvePaneAgentIdentity({ evidence: shape(7, 8), currentRunId: 8 })
expect(result).toMatchObject({ agent: 'codex', source: 'title' })
expect(result.supersededSources).toEqual(['completed-hook'])
})
it('produces opposite answers from identical evidence, given only the run ids', () => {
// The whole point, stated as one assertion.
const bug = resolvePaneAgentIdentity({ evidence: shape(7, 7), currentRunId: 7 })
const reclaim = resolvePaneAgentIdentity({ evidence: shape(7, 8), currentRunId: 8 })
expect(bug.agent).not.toBe(reclaim.agent)
})
})
describe('mixed-version peers', () => {
it('treats evidence with no run id as eligible', () => {
// An old host publishes no run ids. Treating unknown as stale would blank every row.
const result = resolvePaneAgentIdentity({
evidence: [{ source: 'completed-hook', agent: 'claude' }],
currentRunId: 9
it('keeps the completed hook when both observations belong to the current run', () => {
expect(
resolvePaneAgentDisplayIdentity({
policy: 'focused-pane',
evidence: shape(currentRun, currentRun),
currentRun
})
).toEqual({
kind: 'resolved',
agent: 'claude',
source: 'completed-hook',
runScope: 'current'
})
expect(result.agent).toBe('claude')
})
it('disables run filtering entirely when the pane has no current run', () => {
const result = resolvePaneAgentIdentity({
evidence: [{ source: 'completed-hook', agent: 'claude', runId: 3 }]
it('drops the completed hook after positive evidence advances the agent run', () => {
expect(
resolvePaneAgentDisplayIdentity({
policy: 'focused-pane',
evidence: shape(previousRun, currentRun),
currentRun
})
).toEqual({
kind: 'resolved',
agent: 'codex',
source: 'title',
runScope: 'current'
})
expect(result).toMatchObject({ agent: 'claude', supersededSources: [] })
})
it('includes host authority rather than comparing naked generation numbers', () => {
expect(
resolvePaneAgentDisplayIdentity({
policy: 'focused-pane',
evidence: [
{ source: 'completed-hook', agent: 'claude', run: otherHostRun },
{ source: 'title', agent: 'codex', run: currentRun }
],
currentRun
})
).toMatchObject({ kind: 'resolved', agent: 'codex', source: 'title' })
})
})
describe('siblings are tab-scoped', () => {
it('ignores a sibling by default', () => {
expect(resolve([{ source: 'sibling', agent: 'codex' }]).agent).toBeNull()
})
it('accepts a sibling when the caller opts in', () => {
expect(resolve([{ source: 'sibling', agent: 'codex' }], { allowSibling: true }).agent).toBe(
'codex'
)
})
it('still ranks a sibling above a title', () => {
const result = resolve(
[
{ source: 'title', agent: 'grok' },
{ source: 'sibling', agent: 'codex' }
],
{ allowSibling: true }
)
expect(result.source).toBe('sibling')
})
})
describe('no eligible evidence', () => {
it('returns null rather than guessing', () => {
expect(resolve([])).toMatchObject({ agent: null, source: null })
})
it('returns null when every source belongs to a superseded run', () => {
const result = resolvePaneAgentIdentity({
evidence: [
{ source: 'live-hook', agent: 'claude', runId: 1 },
{ source: 'title', agent: 'codex', runId: 1 }
],
currentRunId: 2
describe('mixed-version display evidence', () => {
it('preserves source authority when a stronger source cannot publish a run', () => {
expect(
resolvePaneAgentDisplayIdentity({
policy: 'focused-pane',
evidence: [
{ source: 'live-hook', agent: 'claude' },
{ source: 'title', agent: 'codex', run: currentRun }
],
currentRun
})
).toEqual({
kind: 'resolved',
agent: 'claude',
source: 'live-hook',
runScope: 'compatibility'
})
expect(result.agent).toBeNull()
expect(result.supersededSources).toEqual(['live-hook', 'title'])
})
it('uses exact current-run scope as a tie-breaker within one source', () => {
expect(
resolvePaneAgentDisplayIdentity({
policy: 'focused-pane',
evidence: [
{ source: 'live-hook', agent: 'claude', run: currentRun },
{ source: 'live-hook', agent: 'codex' }
],
currentRun
})
).toEqual({
kind: 'resolved',
agent: 'claude',
source: 'live-hook',
runScope: 'current'
})
})
it('disables run filtering when the peer has no current run identity', () => {
expect(
resolvePaneAgentDisplayIdentity({
policy: 'focused-pane',
evidence: [{ source: 'completed-hook', agent: 'claude', run: previousRun }]
})
).toMatchObject({ kind: 'resolved', agent: 'claude', runScope: 'compatibility' })
})
})
describe('input order does not decide the answer', () => {
it('resolves the same regardless of how evidence is listed', () => {
describe('equal-source ordering', () => {
const conflict: PaneAgentEvidence[] = [
{ source: 'live-hook', agent: 'claude' },
{ source: 'live-hook', agent: 'codex' },
{ source: 'title', agent: 'grok' }
]
it('refuses incomparable claims instead of letting a weaker source decide', () => {
expect(resolveFocused(conflict)).toEqual({
kind: 'unresolved',
reason: 'conflicting-evidence',
source: 'live-hook'
})
})
it('does not let input order break an incomparable tie', () => {
expect(resolveFocused(conflict)).toEqual(resolveFocused(conflict.toReversed()))
})
it('chooses the newest observation sequenced by one authority', () => {
const evidence: PaneAgentEvidence[] = [
{ source: 'title', agent: 'codex' },
{ source: 'launch', agent: 'grok' },
{ source: 'live-hook', agent: 'claude' }
{
source: 'process',
agent: 'claude',
order: { authorityId: 'main', revision: 4 }
},
{
source: 'process',
agent: 'codex',
order: { authorityId: 'main', revision: 5 }
}
]
const forward = resolve([...evidence])
const reverse = resolve(evidence.toReversed())
expect(forward).toEqual(reverse)
expect(forward.source).toBe('live-hook')
expect(resolveFocused(evidence)).toMatchObject({
kind: 'resolved',
agent: 'codex',
source: 'process'
})
expect(resolveFocused(evidence)).toEqual(resolveFocused(evidence.toReversed()))
})
it('refuses ordering claims from different authorities', () => {
expect(
resolveFocused([
{
source: 'process',
agent: 'claude',
order: { authorityId: 'main', revision: 5 }
},
{
source: 'process',
agent: 'codex',
order: { authorityId: 'renderer', revision: 6 }
}
])
).toMatchObject({ kind: 'unresolved', reason: 'conflicting-evidence' })
})
it('refuses different agents tied at the same authoritative revision', () => {
expect(
resolveFocused([
{
source: 'live-hook',
agent: 'claude',
order: { authorityId: 'main', revision: 5 }
},
{
source: 'live-hook',
agent: 'codex',
order: { authorityId: 'main', revision: 5 }
}
])
).toMatchObject({ kind: 'unresolved', reason: 'conflicting-evidence' })
})
it('accepts duplicate observations that agree', () => {
expect(
resolveFocused([
{ source: 'process', agent: 'codex' },
{ source: 'process', agent: 'codex' }
])
).toMatchObject({ kind: 'resolved', agent: 'codex', source: 'process' })
})
})
describe('unresolved and run-boundary states', () => {
it('returns no-evidence for an empty display input', () => {
expect(resolveFocused([])).toEqual({ kind: 'unresolved', reason: 'no-evidence' })
})
it('returns run-transition when every ranked observation is superseded', () => {
expect(
resolvePaneAgentDisplayIdentity({
policy: 'focused-pane',
evidence: [
{ source: 'live-hook', agent: 'claude', run: previousRun },
{ source: 'title', agent: 'codex', run: previousRun }
],
currentRun
})
).toEqual({ kind: 'unresolved', reason: 'run-transition' })
})
it('resolves as soon as the positive evidence for the new run is present', () => {
expect(
resolvePaneAgentDisplayIdentity({
policy: 'focused-pane',
evidence: [
{ source: 'completed-hook', agent: 'claude', run: previousRun },
{ source: 'launch', agent: 'codex', run: currentRun }
],
currentRun
})
).toMatchObject({ kind: 'resolved', agent: 'codex', source: 'launch' })
})
})
it('does not let input order decide between different sources', () => {
const evidence: PaneAgentEvidence[] = [
{ source: 'title', agent: 'codex' },
{ source: 'launch', agent: 'grok' },
{ source: 'live-hook', agent: 'claude' }
]
expect(resolveFocused(evidence)).toEqual(resolveFocused(evidence.toReversed()))
expect(resolveFocused(evidence)).toMatchObject({
kind: 'resolved',
agent: 'claude',
source: 'live-hook'
})
})
})
+144 -89
View File
@@ -1,109 +1,164 @@
import type { AgentStatusObservation } from './agent-status-observation'
import type { TuiAgent } from './tui-agent'
/**
* One place that answers "which agent is in this pane".
*
* Today four ladders answer it independently — the tab icon, the open-tab/search occupant, the
* sidebar title rows, and the sidebar hook-row fallback — and they disagree. Two of them consult
* the terminal title before the launch record, so a string Orca parsed outranks a fact Orca owns.
*
* Two rules make this resolvable where reordering alone could not:
*
* 1. Evidence is ranked by how directly it observes the process, and a display title is last.
* 2. Every observation carries the `runId` of the agent run it belongs to. Evidence from a run
* that has since been replaced is INELIGIBLE rather than merely outranked.
*
* Rule 2 is what separates two situations that are otherwise identical. A completed hook naming
* A plus a title naming B is either a bug (the hook is right, the title is stale) or a legitimate
* reclaim (the pane was reused and B really is there). Same signals, opposite answers. With run
* ids they are different facts: in the bug both belong to the current run, and in the reclaim the
* hook belongs to a previous one.
*
* A run is advanced only on positive evidence that a new agent started in the pane — an accepted
* launch, a recognized command at a shell prompt, a host-confirmed foreground change, a new
* provider session. Never by a title changing, and never by transport loss.
*/
export const PANE_AGENT_EVIDENCE_SOURCES = [
/** A live provider hook for a turn in progress. The agent is running and said so. */
'live-hook',
/** The pane's foreground process, as read on the execution host. */
'process',
/** Orca launched, resumed, or accepted a command for this agent. A fact Orca owns. */
'launch',
/** A provider hook from a turn that finished. Still authoritative about identity. */
'completed-hook',
/** A sleeping session record restored for this pane. */
'sleeping-session',
/** Another pane in the same tab. Tab-level surfaces only; never pane-scoped routing. */
'sibling',
/** Parsed from the terminal title. A decoration channel; anyone can type an agent's name. */
'title'
] as const
export type PaneAgentEvidenceSource = (typeof PANE_AGENT_EVIDENCE_SOURCES)[number]
export const PANE_AGENT_DISPLAY_POLICIES = {
'focused-pane': ['live-hook', 'process', 'launch', 'completed-hook', 'sleeping-session', 'title'],
'tab-aggregate': [
'live-hook',
'process',
'launch',
'completed-hook',
'sleeping-session',
'title',
'sibling'
]
} as const
/** Authority order, strongest first. Position here is the ONLY place precedence is expressed. */
const SOURCE_RANK: readonly PaneAgentEvidenceSource[] = PANE_AGENT_EVIDENCE_SOURCES
export type PaneAgentDisplayPolicy = keyof typeof PANE_AGENT_DISPLAY_POLICIES
export type PaneAgentEvidenceSource =
(typeof PANE_AGENT_DISPLAY_POLICIES)[PaneAgentDisplayPolicy][number]
/** Execution-host-owned identity of one agent run behind a pane key. */
export type PaneAgentRun = {
hostAuthorityId: string
generation: number
}
/** Comparable only when both observations carry the same authority id. */
export type PaneAgentEvidenceOrder = Readonly<
Pick<AgentStatusObservation, 'authorityId' | 'revision'>
>
export type PaneAgentEvidence = {
source: PaneAgentEvidenceSource
agent: TuiAgent
/**
* The agent run this evidence describes. Evidence whose run is not the pane's current run is
* ineligible. Undefined means unknown — from an old peer that does not publish run ids, or an
* ingress not yet stamped — and is treated as eligible, so a missing field never blanks a row.
*/
runId?: number
/** Absent when an older peer or unstamped ingress cannot identify the agent run. */
run?: PaneAgentRun
/** Used only to settle equal-source claims that one authority sequenced. */
order?: PaneAgentEvidenceOrder
}
export type PaneAgentIdentityInput = {
export type PaneAgentDisplayIdentityInput = {
policy: PaneAgentDisplayPolicy
evidence: readonly PaneAgentEvidence[]
/** The pane's current run. Undefined disables run filtering entirely (old peer, mixed version). */
currentRunId?: number
/**
* Pane-scoped consumers must not inherit another pane's agent. Sibling evidence is dropped
* unless the caller is a tab-level surface that opted in.
*/
allowSibling?: boolean
/** Absent on older peers; display resolution then preserves compatibility. */
currentRun?: PaneAgentRun
}
export type PaneAgentIdentity = {
agent: TuiAgent | null
/** Which class of evidence decided it. Null when nothing eligible remained. */
source: PaneAgentEvidenceSource | null
/** Evidence discarded because it belongs to a superseded run. Surfaced for diagnostics. */
supersededSources: readonly PaneAgentEvidenceSource[]
export type ResolvedPaneAgentDisplayIdentity = {
kind: 'resolved'
agent: TuiAgent
source: PaneAgentEvidenceSource
/** Compatibility means one side cannot publish agent-run identity. */
runScope: 'current' | 'compatibility'
}
export type UnresolvedPaneAgentDisplayIdentity = {
kind: 'unresolved'
reason: 'no-evidence' | 'run-transition' | 'conflicting-evidence'
/** Present when equally ranked, incomparable evidence names different agents. */
source?: PaneAgentEvidenceSource
}
export type PaneAgentDisplayIdentity =
| ResolvedPaneAgentDisplayIdentity
| UnresolvedPaneAgentDisplayIdentity
/**
* Resolves one pane's agent from ranked evidence.
*
* Returns null rather than guessing. A pane with no eligible evidence shows no agent, which is
* recoverable; showing the wrong agent is not, and at the action surfaces (orchestration routing,
* mailbox delivery, prompt-cache timers) it is a misdelivery rather than a cosmetic slip.
* Display-only identity resolution. Write authorization requires proof-bearing process, hook, or
* launch capabilities and deliberately has no resolver in this module.
*/
export function resolvePaneAgentIdentity(input: PaneAgentIdentityInput): PaneAgentIdentity {
const superseded: PaneAgentEvidenceSource[] = []
const eligible = input.evidence.filter((item) => {
if (item.source === 'sibling' && input.allowSibling !== true) {
return false
}
// Why undefined is eligible: absence means "this peer does not publish run ids", not "this
// belongs to an old run". Treating unknown as stale would blank every row from an old host.
if (input.currentRunId === undefined || item.runId === undefined) {
return true
}
if (item.runId === input.currentRunId) {
return true
}
superseded.push(item.source)
return false
})
export function resolvePaneAgentDisplayIdentity(
input: PaneAgentDisplayIdentityInput
): PaneAgentDisplayIdentity {
const sources = PANE_AGENT_DISPLAY_POLICIES[input.policy]
let rejectedSupersededRun = false
for (const source of SOURCE_RANK) {
const match = eligible.find((item) => item.source === source)
if (match) {
return { agent: match.agent, source, supersededSources: superseded }
for (const source of sources) {
const eligible: PaneAgentEvidence[] = []
for (const item of input.evidence) {
if (item.source !== source) {
continue
}
if (isSupersededRun(item.run, input.currentRun)) {
rejectedSupersededRun = true
continue
}
eligible.push(item)
}
if (eligible.length === 0) {
continue
}
const exactCurrent = eligible.filter((item) => isSameRun(item.run, input.currentRun))
const candidates = exactCurrent.length > 0 ? exactCurrent : eligible
const selected = selectEqualSourceCandidate(candidates)
if (selected === null) {
return { kind: 'unresolved', reason: 'conflicting-evidence', source }
}
return {
kind: 'resolved',
agent: selected.agent,
source,
runScope: isSameRun(selected.run, input.currentRun) ? 'current' : 'compatibility'
}
}
return { agent: null, source: null, supersededSources: superseded }
return {
kind: 'unresolved',
reason: rejectedSupersededRun ? 'run-transition' : 'no-evidence'
}
}
function selectEqualSourceCandidate(
candidates: readonly PaneAgentEvidence[]
): PaneAgentEvidence | null {
const first = candidates[0]
if (candidates.every((item) => item.agent === first.agent)) {
return first
}
const firstOrder = first.order
if (
firstOrder === undefined ||
candidates.some(
(item) => item.order === undefined || item.order.authorityId !== firstOrder.authorityId
)
) {
return null
}
let newest = first
for (const candidate of candidates.slice(1)) {
if (
candidate.order !== undefined &&
newest.order !== undefined &&
candidate.order.revision > newest.order.revision
) {
newest = candidate
}
}
if (newest.order === undefined) {
return null
}
const sameRevision = candidates.filter((item) => item.order?.revision === newest.order?.revision)
return sameRevision.every((item) => item.agent === newest.agent) ? newest : null
}
function isSupersededRun(
evidenceRun: PaneAgentRun | undefined,
currentRun: PaneAgentRun | undefined
): boolean {
return (
evidenceRun !== undefined && currentRun !== undefined && !isSameRun(evidenceRun, currentRun)
)
}
function isSameRun(left: PaneAgentRun | undefined, right: PaneAgentRun | undefined): boolean {
return (
left !== undefined &&
right !== undefined &&
left.hostAuthorityId === right.hostAuthorityId &&
left.generation === right.generation
)
}