Skip to content

Add generation/revision-guarded atomic PTY send #132

Description

@myobie

Problem

A provider adapter can establish fresh idle authority and verify its own empty-composer safety rule, but an ordinary input, child output, resize, or daemon replacement can race between that check and delivery. PTY must not guess what Enter, newline, paste, ESC, or any other bytes mean.

Depends on #129.

Proposed generic seam

Expose top-level daemon generation plus a monotonic per-generation ioRevision through live STATUS. Add one bounded conditional write request and public API:

compareAndSend(name, {
  generation,
  ioRevision,
  data,
}): Promise<{
  ok: boolean;
  generation: string;
  ioRevision: number;
  error?: string;
}>

The daemon increments revision for every accepted ordinary or guarded input, every child-output chunk, and every actual PTY size mutation. Attach, peek, and status without input or resizing do not increment it.

Guard validation and the single pty.write() occur in one daemon event-loop turn. Generation or revision mismatch, malformed/oversize input, dead/read-only state, or replay rejects with zero bytes. Success advances revision so the same token cannot succeed twice.

Provider-specific idle, composer, hook, human, Codex, Claude, and DING semantics remain outside PTY. Adapters retain inbox ownership when delivery rejects.

Required PTY tests

  • unchanged generation/revision succeeds exactly once
  • prior ordinary key/newline/paste/ESC-shaped bytes each invalidate the guard without interpreting them
  • child output and actual resize races invalidate the guard
  • replacement generation rejects
  • an attached viewer with no input or resize leaves the token eligible
  • malformed, oversize, stale, and replayed guards reject with zero guarded bytes
  • failed guard leaves the live activity lease and socket usable

Partial-draft interpretation and DING inbox retention are adapter/evals fixtures; the PTY counterpart proves that any pre-check ordinary input changes revision and makes guarded delivery zero-write.

Draft-only implementation. No merge or deployment.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions