13 KiB
Created
Created by tickets.sh create.
Decision
Clarification
The requested command is not a TUI attach/switch affordance. It should make another existing Pod known to the currently attached Pod so that the current Pod's ListPods tool can see it.
The implementation should therefore focus on Pod-authoritative visibility metadata and ListPods semantics, with the TUI : command only acting as the human-facing control path that registers that relationship.
Decision
Clarification
The requested command is not a TUI attach/switch affordance. It should initiate a Pod-authoritative peer handshake between the currently attached Pod and another existing Pod.
The intended result is broader than one-sided ListPods visibility: after a successful handshake, both Pods should be mutually visible as peers and should be able to exchange messages through an explicit peer-safe tool/method. The relationship must stay distinct from spawned-child delegation: no delegated filesystem scope, no parent/child ownership, no child completion notifications, and no child output cursor authority.
The TUI : command is the human-facing control path for initiating the handshake; the durable relationship and messaging authorization belong in Pod metadata/runtime semantics, not in TUI-local state.
Plan
Delegation intent: peer Pod handshake and messaging
Intent:
- Investigate the existing Pod visibility/messaging implementation, then implement a TUI-initiated peer Pod handshake and peer messaging path if no design blockers are found.
Requirements:
- Start with investigation. Map current authority boundaries for
ListPods,RestorePod,SendToPod, Pod metadata, spawned-child registry, protocol methods, and TUI:command handling. - If there are design blockers or ambiguous authority decisions, write findings to the ticket artifacts and stop for parent decision.
- If there are no blockers, proceed with implementation in the worktree.
- Add a TUI
:command that initiates peer handshake from the currently attached Pod to a target Pod by name. - Make the peer relationship Pod-authoritative, durable where appropriate, and reciprocal by default.
- Ensure both Pods see each other in
ListPodsas peer/known, not spawned child. - Add or safely broaden messaging semantics so a Pod can message a visible peer without granting spawned-child powers.
- Record delivered peer messages through an explainable durable path; do not silently mutate hidden context.
- Preserve explicit boundaries: no delegated filesystem scope, parent/child ownership, completion notification authority, or child output cursor authority for peer Pods.
- Add focused tests for protocol/runtime behavior, metadata persistence/restore, reciprocal
ListPods, peer message authorization/delivery, and TUI command parsing/help where feasible. - Update docs/help text for the new command and peer semantics.
Invariants:
- Do not treat peer Pods as spawned children.
- Do not reintroduce hidden context injection; model-affecting delivered messages must go through the normal committed history/event path.
- Do not add broad relationship graph semantics beyond the minimal peer relation.
- Do not edit the parent workspace; work only in the delegated worktree.
- Do not read ignored secret-like file contents.
- Do not close the ticket, merge the branch, delete worktrees, or push.
Non-goals:
- Arbitrary autonomous Pod-to-Pod background chatter.
- Replacing the multi-Pod dashboard or Pod picker.
- Delegated scope sharing between peers.
- E2E test framework design for real spawned processes.
Escalate if:
- Reciprocal handshake cannot be made atomic enough to avoid misleading partial state.
- Peer messaging requires changing history semantics in a way that could violate context/history invariants.
- Existing protocol or metadata schemas need a broad migration.
- The TUI command cannot safely deliver the runtime method while preserving current Pod authority.
SendToPodbroadening would confuse spawned-child and peer semantics.
Validation:
- Before implementation: write a short investigation summary in the implementation report or a separate artifact.
- Focused tests for touched crates.
./tickets.sh doctorandgit diff --check.nix build .#yoiif feasible; record if skipped and why.- Commit the implementation in the worktree when reviewable.
Implementation report
Implementation report: peer Pod handshake command
Date: 2026-06-02
Investigation
The current boundaries are documented in artifacts/investigation-summary.md. No escalation blocker was found. The main concern identified was avoiding reuse of spawned-child state (SpawnedPodRegistry, delegated scope, output cursors, and child completion semantics) for peer communication; the implementation therefore adds separate peer metadata and a separate peer send tool.
Implemented behavior
- Added reciprocal peer metadata to
PodMetadataaspeers, separate fromspawned_childrenandreclaimed_children. - Added protocol
Method::RegisterPeer { name }andEvent::PeerRegistered { result }. - Added controller handling for
RegisterPeer, idle/paused only, validating an existing target Pod and rejecting self-handshakes. - Added
PodDiscovery::register_peerthat persists both metadata directions and rolls back the first side on ordinary second-side write failure. - Extended
ListPodsvisibility to includeVisibilityReason::Peer; a successful handshake makes both Pods see each other aspeerthrough Pod metadata. - Added
SendToPeerPodas a distinct LLM tool. It only sends to visible live peer Pods, deliversMethod::Notifywith a source label, and does not use child delegation, output cursors, parent ownership, or child completion notifications. - Added TUI command
:peer <pod-name>for idle attached Pods. Success is reported through a transient actionbar notice when the controller returnsPeerRegistered. - Documented peer semantics in
docs/design/pod-session-state.mdand added prompt guidance that peer Pods are not spawned children.
Tests and validation run
cargo test -p protocol -p pod-store -p pod -p tui --lib./tickets.sh doctorgit diff --checknix build .#yoi
Notes
The two-file reciprocal metadata update is not crash-transactional because the existing Pod metadata store has no multi-record transaction boundary. The implementation avoids successful replies with one-sided state for normal validation/write failures by rolling back the first write if the reciprocal write fails.
Implementation report
Implementation report: peer Pod handshake command
Date: 2026-06-02
Investigation
The current boundaries are documented in artifacts/investigation-summary.md. No escalation blocker was found. The main concern identified was avoiding reuse of spawned-child state (SpawnedPodRegistry, delegated scope, output cursors, and child completion semantics) for peer communication; the implementation therefore adds separate peer metadata and a separate peer send tool.
Implemented behavior
- Added reciprocal peer metadata to
PodMetadataaspeers, separate fromspawned_childrenandreclaimed_children. - Added protocol
Method::RegisterPeer { name }andEvent::PeerRegistered { result }. - Added controller handling for
RegisterPeer, idle/paused only, validating an existing target Pod and rejecting self-handshakes. - Added
PodDiscovery::register_peerthat persists both metadata directions and restores the exact prior source-side peer state on ordinary second-side write failure. - Extended
ListPodsvisibility to includeVisibilityReason::Peer; a successful handshake makes both Pods see each other aspeerthrough Pod metadata. - Added
SendToPeerPodas a distinct LLM tool. It only sends to visible live peer Pods, deliversMethod::Notifywith a source label, and does not use child delegation, output cursors, parent ownership, or child completion notifications. - Added TUI command
:peer <pod-name>for idle attached Pods. Success is reported through a transient actionbar notice when the controller returnsPeerRegistered. - Documented peer semantics in
docs/design/pod-session-state.mdand added prompt guidance that peer Pods are not spawned children.
Reviewer blocker fixes
SendToPeerPodnow reuses the existing one-shot Pod socket client path (connect_and_send), which drains connect-timeAlert/Snapshottraffic before writingNotifyand returns an error if method delivery fails.- Added a regression test where the target socket emits an alert and snapshot before reading the peer
Notify, proving the peer send drains the prelude and still delivers the message. - Registration failure rollback now restores the exact prior source peer list instead of unconditionally removing
source -> target; a target-side injected failure test verifies a pre-existing source relation is preserved. - Wording now describes
:peeras metadata-level reciprocal registration rather than live target-controller consent, and documents thatSendToPeerPodfails for non-live peers instead of auto-restoring them.
Tests and validation run
cargo test -p protocol -p pod-store -p pod -p tui --lib./tickets.sh doctorgit diff --checknix build .#yoi
Notes
The two-file reciprocal metadata update is not crash-transactional because the existing Pod metadata store has no multi-record transaction boundary. The implementation avoids successful replies with one-sided state for normal validation/write failures by restoring the exact prior source-side peer list if the reciprocal write fails.
Review: approve
Review: peer Pod handshake command
Reviewer Pods:
- Initial review:
peer-pod-handshake-reviewer-20260602 - Re-review:
peer-pod-handshake-rereviewer-20260602
Result
Approved after fixes. No remaining blockers.
Initial blocker findings
The first reviewer found two blockers:
SendToPeerPodwroteMethod::Notifydirectly to the target socket without draining connect-timeAlert/Snapshottraffic, so a real Pod socket could fail to process the notify while the sender reported success.- Reciprocal registration rollback could delete a pre-existing
source -> targetpeer relation when the reciprocaltarget -> sourcewrite failed.
Fix verification
Coder added commit 057c2ef fix: harden peer pod registration.
The re-review confirmed:
SendToPeerPodnow uses the existingconnect_and_sendone-shot client path, which drains connect-timeAlert/Snapshottraffic before writingMethod::Notifyand reports delivery failures.- A regression test covers a target socket that emits an alert/snapshot before reading the peer notify.
register_peernow snapshots the source Pod's existing peer list and restores that exact list if the target-side write fails.- A regression test covers an injected target-side failure where the source already had the peer relation and verifies it is preserved.
Validation evidence
Coder reported:
cargo test -p pod discovery --libcargo test -p tui command --libcargo test -p protocol -p pod-store -p pod -p tui --lib./tickets.sh doctorgit diff --checknix build .#yoi
Reviewer re-ran:
cargo test -p pod --lib peercargo test -p pod --lib connect_and_send
Parent/orchestrator reran after merge:
cargo test -p pod discovery --libcargo test -p tui command --libcargo test -p protocol -p pod-store -p pod -p tui --lib./tickets.sh doctorgit diff --checknix build .#yoi./result/bin/yoi pod --help
Residual risk
Peer registration updates two metadata files and is not crash-transactional because the current Pod metadata store has no multi-record transaction boundary. Normal write failures are handled by restoring the exact prior source peer list.
The implemented peer relationship is metadata-level reciprocal registration, not live target-process consent. This is documented and remains separate from spawned-child delegation, delegated scope, output cursors, parent ownership, and child completion notifications.
Closed
Implemented TUI-initiated peer Pod handshake and peer messaging. Peers are persisted separately from spawned children, appear in ListPods as peers, and can receive peer messages through a distinct tool/method. Reviewer blockers were fixed; focused tests and nix build passed.