mirror of
https://github.com/stablyai/orca.git
synced 2026-10-23 16:03:49 +00:00
A session could reach `recovering` / `manual-recovery` with no way back out, so the chat behind it never opened again. Three separate latches, all of them permanent: - A lease with no owner AND no reserved spawn token was treated as an unproven reservation. Nothing was ever minted that a child could carry, so it is already free — but every released record re-latched to `recovering` on the next boot. `adjudicateAgentSessionRestart` now answers `free` for that shape and the owner probe answers `reservation-unused`, neither of which moves the fence. - `claimStatus: 'conflicted'` had no clearing path anywhere in the product. The v1 to v2 record upgrade stamps every migrated row conflicted + manual-recovery, and restart adjudication refused to consult the probe at all. It now evicts when present-time evidence proves the process the conflict NAMES has exited; with no proof, and with no named process, the conflict still stands. - Recovery resolution skipped every TUI record because a TUI owner has its own recovery transport. That transport needs a process to talk to, so a TUI reservation that crashed before `commitProcessIdentity` had no exit at all. Records, journals, and provider handle chains are untouched throughout: an exit is a re-adjudication of ownership, never a deletion. Where evidence stays unavailable the refusal now names the process Orca could not prove gone and what to do about it, instead of echoing a store code. Also wires `listOrphanSpawnTokens`, which had no production caller: restart restore now stops children carrying a token no lease claims BEFORE recovery grants a new owner, so a child that went down with its record cannot end up as a second live writer on one provider session. The scan reads `/proc/<pid>/environ` and answers null - "cannot enumerate", never "none" - on macOS and Windows.
26 lines
1.1 KiB
TypeScript
26 lines
1.1 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import {
|
|
findAgentSessionSpawnTokenProcesses,
|
|
scanAgentSessionSpawnTokenProcesses
|
|
} from './agent-session-spawn-token-process-scan'
|
|
|
|
describe('agent-session spawn token process scan', () => {
|
|
it('answers null on platforms that cannot read another process environment', async () => {
|
|
// macOS and Windows have no `/proc/<pid>/environ`. Answering "none" there would free a
|
|
// reservation whose child is alive and mint a second writer on the same provider session.
|
|
expect(await scanAgentSessionSpawnTokenProcesses('darwin')).toBeNull()
|
|
expect(await scanAgentSessionSpawnTokenProcesses('win32')).toBeNull()
|
|
})
|
|
|
|
it('propagates the host non-answer rather than reporting an empty pid list', async () => {
|
|
expect(await findAgentSessionSpawnTokenProcesses('token-1', async () => null)).toBeNull()
|
|
})
|
|
|
|
it('reports the pids carrying one token', async () => {
|
|
const scan = async () => new Map([['token-1', [11, 12]]])
|
|
|
|
expect(await findAgentSessionSpawnTokenProcesses('token-1', scan)).toEqual([11, 12])
|
|
expect(await findAgentSessionSpawnTokenProcesses('token-2', scan)).toEqual([])
|
|
})
|
|
})
|