Skip to content

F1 — Tower-vs-PTY dimension divergence causes indefinite false-busy (render gate) #1482

Closed

Description

@mohidmakhdoomi

F1 — Latent defect: Tower-vs-PTY dimension divergence causes indefinite false-busy

The gate classifies the ring at session.info.cols/rows — Tower-side fields. Measured on the live main-architect ring: the identical byte stream classifies clean at 104x101 but busy at every other size tested (104x99 and 100x101 → no-region-end; 80x24 → no-composer-marker). A ±2-row disagreement flips the verdict.

Meanwhile the dims fields can silently diverge from the real PTY:

  • PtySession.resize() (pty-session.ts:496-497) assigns this.cols/this.rows before checking whether the resize can reach the process; a dropped shellper resize (returns false) leaves Tower's dims changed while the kernel winsize — and the TUI's layout — did not move. All callers (tower-websocket.ts resize control message, pty-manager.resizeSession) ignore the boolean.
  • shellper-main.ts:86 ptyInstance?.resize(cols, rows) silently no-ops when ptyInstance is momentarily undefined.
  • The live system already shows dims fuzz: main's claude addresses CUP row 103 while the kernel PTY and Tower both say 101 (harmless today only because clamping happens to reconstruct cleanly at 104x101).

The pipeline distinguishes user-text (human at the line — the safe, intended hold) from no-region-end/no-composer-marker (classifier can't verify — a defect class) in GateVerdict.detail, but that detail dies inside DeliveryOutcome: afx inbox, the send response, the escalation broadcast/log, and the held log line all show only busy.

  • Cheap fixes with high payoff: carry detail onto the held row (a detail column or reuse reason sub-codes), show it in afx inbox and the escalation notification, and include a "composer occupied since " hint when the same user-text verdict has been re-confirmed across N consecutive checks.

Claude addresses CUP rows up to 103 on a 101-row PTY throughout the captured history. Benign today (xterm clamps; classification is clean at the true dims), but it narrows the clean envelope that F1 depends on — the gate's correctness rests on session.info dims matching the dims the TUI believes, and the TUI's belief is already 2 off from the kernel.


Refinement: F1's original measurement flagged row sensitivity (104x99 busy); today's snapshots are row-robust but col-sensitive. The envelope is content-dependent; the invariant is that a small dims disagreement lands in indefinite BUSY.

Activity

  1. mohidmakhdoomi commented on Sep 3, 2026

    @mohidmakhdoomi
    CollaboratorAuthor

    Pre-spawn verification (architect, 2026-09-03 @ cc83b6a3)

    The body was written 2026-08-17; every claim below still holds, but line numbers have drifted. Verified refs:

    Claim Body said Actually at HEAD Verdict
    resize() assigns dims + resizes the gate mirror before the drop-boolean is known pty-session.ts:496-497 packages/codev/src/terminal/pty-session.ts:567-583 — this.cols/this.rows at :568-569, this._gateScreen?.resize(cols, rows) at :572, shellper drop-boolean returned at :575 holds
    All callers ignore the boolean "tower-websocket resize control message, pty-manager.resizeSession" servers/tower-websocket.ts:80, terminal/pty-manager.ts:243, terminal/pty-manager.ts:373 — all three discard it holds
    shellper silently no-ops when ptyInstance is undefined shellper-main.ts:86 packages/codev/src/terminal/shellper-main.ts:89 holds
    Held-row reason can't express the gate detail db/schema.ts:269 packages/codev/src/agent-farm/db/schema.ts:269 — reason TEXT CHECK(reason IN ('busy', 'no-profile', 'no-live-pty')), verbatim holds
    GateVerdict.detail exists in-memory and feeds the liveness net, but dies at the DB edge mailbox-delivery.ts:229,387 servers/mailbox-delivery.ts:348-355 (DeliveryOutcome.detail), :370-372 (isClassifierStuck), :594-600 (carried on the hold), :1137-1147 (streak → owner escalation) holds

    Sequencing facts

    In-flight work that overlaps (do not build on these branches)

    Two sibling PRs are open and parked awaiting maintainer review. Branch from main, not from them; just know the conflict surface exists.

    servers/mailbox-delivery.ts and db/schema.ts are untouched by both.

    Reference material

    A capture/measurement rig from the Spec 1313 investigation — the one that produced this issue's dimension-sweep numbers — is available read-only outside the worktree at:

    /home/user/code/codev_root/codev/codev/spir-1313-captures/

    (README.md, gate-diag.mjs, capsweep.mjs, counterfactual.mjs, findings-ghost-cursor-false-busy.md, plus .replay.bin ring captures.) It is deliberately not committed — local artifacts, 10 MB, and we are not this repo's maintainers. Read it for grounding; do not copy the binaries into the PR. If a fixture is genuinely needed, derive a small sanitized one, the way PR #1491 did.

    Contributor constraint

    We are not cluesmith/codev maintainers. This PR needs a maintainer/reviewer approval and the maintainer merges it. Do not merge, do not close the issue, do not clean up the worktree.

  2. mohidmakhdoomi commented on Sep 3, 2026

    @mohidmakhdoomi
    CollaboratorAuthor

    On it! Working on this with the PIR protocol (plan + dev-approval gates before PR).

  3. added 12 commits that reference this issue on Sep 3, 2026
  4. added 3 commits that reference this issue on Sep 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

area/towerArea: Tower server / agent farm CLI

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions