Repository navigation
fix(T699): one liveness answer for agents, roster and send receipts - #375
Merged
Merged
Conversation
`agentmbx agents` read the session binding (liveAgents) while `mbx_agents` and the send receipt read the identity lease. When OpenCode evicted an idle MCP, the lease was released while the serve kept the session row alive, so the CLI showed "live" and the receipt showed "offline (released)" for hours. Liveness is now one answer (src/liveness.ts) composed from the lease, the live session row and the serve kind: - a released or expired lease whose session still runs is `idle` with its reason (claimable; wakeable when the T688 shared service or a registered T659 poller can start its next turn, which re-claims the mailbox); - the reason text uses only evidence every process can read, so all three surfaces agree; - `agentmbx agents` prints the shared state plus a trailing reason column and keeps shell senders visible as live; - mbx_agents/mbx_identity list follow through listIdentityStatus, and the receipt reports live-next-prompt/live-wake instead of offline; - the 30-minute lease idle TTL and the receipt's 3-minute heartbeat rule are unchanged. Adds test/liveness-agreement.test.ts covering held, released+service, released+standalone-poller, released+dead and unknown evidence. Checks: tsc --noEmit, npm run build (dist committed), identity-status, roster, opencode-poll-liveness, project-mailbox, liveness-activity, opencode-poller-wake, recipient-truth, agents-directory, chosen-identity, identity-cleanup, doctor-identities, delivery-guidance, cli-lease, mcp-leases, hooks, doctor-sessions, stranded, codex-activity, wake-dispatch, wake-contract, wake-project-mail, mcp-connection, mcp-lifecycle, cli-identity-handover.
sessionRowLive reads the real process table, so the fixture's fabricated low pid could be alive (EPERM) on CI. An expired holder whose session row still names a live process is legitimately idle under T699, so the row kept its task and lane and the T497 assertion failed with "idle" instead of "offline". Point the session binding at a reaped pid so the fixture is offline on every host. Test-only; no product change. Checks: roster.test.ts (9/9 with liveness-agreement), identity-status, agents-directory, tsc --noEmit.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
OpenCode b4ece3c (base 65f9040, v0.5.48).
agentmbx agentsused the session-row predicate (liveAgents) and called a released lease whose provider still runs "live". mbx_agents and send receipts used the lease and called it "offline". Both were wrong for a T659/T688 wake target.idlewith a reason naming the service or standalone serve and its pid (no schema change).wakeBindingsByAgent.serveBindingLiveandpollerWakeTargetsare unchanged, so http.ts keeps its standalone-only meaning.agentscase prints state plus a trailing reason column.liveAgents()is removed;sessionAgents()(the */role audience) is untouched. Shell senders staylive("shell sender, last seen N min ago").New test/liveness-agreement.test.ts covers held, released+service, released+standalone-poller, released+dead and unknown: every surface returns the same token and reason. 235 tests across 24 related files green, tsc clean, no dist drift. CHANGELOG Unreleased only.
Limitation: a standalone poller registration lives in the daemon, so from an MCP/CLI process
wakeableis false there (the receipt says live-next-prompt) while the token and reason match.🤖 Generated with Claude Code