You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
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)
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:
(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.
Activity
mohidmakhdoomi commentedon Sep 3, 2026
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:
resize()assigns dims + resizes the gate mirror before the drop-boolean is knownpty-session.ts:496-497packages/codev/src/terminal/pty-session.ts:567-583—this.cols/this.rowsat :568-569,this._gateScreen?.resize(cols, rows)at :572, shellper drop-boolean returned at :575servers/tower-websocket.ts:80,terminal/pty-manager.ts:243,terminal/pty-manager.ts:373— all three discard itptyInstanceis undefinedshellper-main.ts:86packages/codev/src/terminal/shellper-main.ts:89reasoncan't express the gate detaildb/schema.ts:269packages/codev/src/agent-farm/db/schema.ts:269—reason TEXT CHECK(reason IN ('busy', 'no-profile', 'no-live-pty')), verbatimGateVerdict.detailexists in-memory and feeds the liveness net, but dies at the DB edgemailbox-delivery.ts:229,387servers/mailbox-delivery.ts:348-355(DeliveryOutcome.detail),:370-372(isClassifierStuck),:594-600(carried on the hold),:1137-1147(streak → owner escalation)Sequencing facts
runGlobalMigrations(db)is atpackages/codev/src/agent-farm/db/migrations.ts:63and is exported fromdb/index.ts. Drive the new migration's test against the real runner — do not hand-roll a replica.GLOBAL_CURRENT_VERSION = 17(migrations.ts:29), so the detail column is migration v18.detail-on-the-held-row + resize drop-boolean handling; the dims-divergence hardening follows. The first slice is what makes the rest of workstream A field-diagnosable, so it should be its own phase and should be complete and coherent on its own.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/gate-profiles.ts,servers/render-gate.ts,__tests__/render-gate.test.ts.commands/inbox.ts(it de-truncates the FROM→TO column),commands/send.ts,servers/tower-routes.ts,utils/message-format.ts.servers/mailbox-delivery.tsanddb/schema.tsare 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.binring 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.
mohidmakhdoomi commentedon Sep 3, 2026
On it! Working on this with the PIR protocol (plan + dev-approval gates before PR).
[PIR #1482] Plan draft
[PIR #1482][Phase: gate-detail] feat: persist the render gate's verdi…
[PIR #1482][Phase: resize-truth] fix: commit terminal dimensions only…
[PIR #1482][Phase: dims-reconciliation] fix: adopt the shellper's rep…
[PIR #1482][Phase: tests] test: pin resize truth, attach reconciliati…
[PIR #1482] revert: drop the dashboard popover render change (not bro…
[PIR #1482] test: cover utils/hold-verdict, and record the dev-approv…
[PIR #1482] chore: move the dev-approval evidence to the project dire…
[PIR #1482] Review + retrospective
[PIR #1482] fix: address the 3-way consultation, and restore the dash…
[PIR #1482] docs: consultation rebuttal record (nothing rebutted, all…
[PIR #1482] fix: maintainer review — stop advising interrupt, render …
Merge origin/main into builder/pir-1201 (PIR cluesmith#1620)
[PIR cluesmith#1620] Gate the kimi trust pre-write behind consent and…
Fix #1664: wait on the composer, not on the recipient's output