Repository navigation
fix(orchestration): an OpenCode worker gets its task only once its input box exists - #24115
brennanb2025 wants to merge 11 commits into
Conversation
…put box exists Worker start waited tui-idle, which settles on a title holding only the agent's name. OpenCode sets that title before drawing its input box, and a shell auto-title names the pane at spawn, so the brief could be typed into nothing. - composerReadyCaptures: optional per-agent evidence; worker start takes the marker-only lane iff a row cites captures (zcode, opencode, opencode2) - waitForLaunchedAgentComposer picks the lane; Windows-hosted panes on OpenCode's signal stay on tui-idle until a ConPTY capture exists (temporary) - waitForFreshWorkerComposer returns the tui-idle result shape, so the wait-for-setup outcome is recorded (fixes ZCode's receipt stuck at running) - render-cursor-after-bracketed-paste is revoked on ESC[?2004l - scanner seam fix: carried chars no longer re-searched for the marker - four timed OpenCode boot captures (1.18.32 x3, 2.0.18) committed
|
Comments Outside DiffThese findings could not be posted inline.
|
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThe change adds timed OpenCode terminal captures and a loader that replays their chunks at recorded times. It updates draft-paste scanning to revoke markers when bracketed paste is disabled and to avoid joining previously scanned bytes across chunk boundaries. Agent configuration now identifies composer-ready captures. New worker starts select a readiness lane using that configuration. Launched prompt delivery can retry Enter after a configured delay. Tests cover scanner chunking, capture replay, readiness selection, and worker startup. Priority: ➖ Normal Merge Risk: 🔵 Low · up to A fast OpenCode response can finish before the retry delay and still receive an unwanted second Enter. The impact is bounded; compare turn timestamps regardless of state to avoid this extra input. Security Architecture ReviewSecurity architecture risk: 🔵 Low · up to The change strengthens readiness checks and guards delayed submission against observed progress, approval requests and stale sessions. No newly introduced security failure was established, but ownership continuity across delayed writes and session replacement could not be fully confirmed. Retained concerns Security review detailsSecurity Blast Radius
Trust Boundaries and Controls
Resilience and Maintainability Implications
Hardening Proposals
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes — full read of the 30-file diff at 24a023e; focused tests, pnpm tc:node, the changed-code quality gate, and the PTY-transcript secret scan all pass.
- Lane selection moves onto row evidence. A new
composerReadyCapturesfield on the agent row, plus a Windows-host check, decides betweenwaitForFreshWorkerComposerandtui-idle, andlocal-worker-startreplaces the hard-codedagent === 'zcode'branch with one agent-agnostic lane call. ZCode, OpenCode and OpenCode 2 wait for the input-box marker; every other agent keeps the prior wait. - The composer wait now yields a wait result.
waitForFreshWorkerComposerreturns thetui-idleresult shape, sopersistWorkerSetupWaitOutcomerecords the wait-for-setup outcome on this lane too — fixing a pre-existing stuckrunningsetup receipt for ZCode as well. - Scanner revocation and seam hardening.
render-cursor-after-bracketed-pasteis revoked on\x1b[?2004l, and carried bytes no longer re-enter the marker search, so the launching shell's own bracketed-paste toggle cannot be mistaken for a mounted composer. - Evidence and tests. Four committed OpenCode boot recordings with timed sidecars, an exhaustive per-agent lane record, self-checking capture evidence, chunking-invariance tests, and runtime replays behind a synthetic auto-titling zsh launch.
ℹ️ Windows-hosted OpenCode panes keep the old title-based wait
The gate intentionally leaves OpenCode on tui-idle for local ConPTY, WSL, and Windows SSH/paired hosts until a bundled-conpty.dll capture exists, so the silent task-loss this PR fixes on macOS/Linux still occurs there — and the linked issues include Windows reports. The PR body notes no follow-up ticket was filed, so the remaining Windows gap and the planned capture are only visible in this description; a tracking issue would keep that from being lost after merge.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
…-worker-waits-for-input-box
…its input box `worker-start --on <host>` launches the agent through the federated attach on the worker host, which still waited tui-idle for every agent. An OpenCode worker there could get its task typed before its input box existed, the same loss the local start no longer has. The attach now takes the same wait as a local start: a terminal it created waits for the composer marker when the agent's row cites captures of it (OpenCode, OpenCode 2, ZCode) and the pane is not Windows-hosted; a caller-supplied --terminal keeps tui-idle. Both paths share one helper so the fresh-vs-reused rule lives in one place. Also drops the retracted "ConPTY does not forward DECSET 2004" claim from the blind-paste comment in agent-paste-draft.ts.
…put box too A capture through Orca's bundled conpty.dll (Windows 11, PowerShell launched as Orca launches it, OpenCode 1.18.32 and 2.0.18, 8 of 8 runs) shows OpenCode's bracketed-paste enable always arriving before its input box, no disable while booting, and the composer marker firing on exactly the read that first draws the box. The temporary Windows host check that kept these panes on tui-idle is therefore removed: the lane comes from the row's evidence alone, and the pty-host-platform lookup added only for that check goes with it.
| const wait = await waitForWorkerAgentReady(runtime, terminalHandle, { | ||
| agent, | ||
| reusesTerminal: Boolean(params.terminal), | ||
| timeoutMs: readinessTimeoutMs | ||
| }) |
There was a problem hiding this comment.
Failed starts leave resources behind
If a newly created federated OpenCode worker never emits its input-box marker, this wait times out. The failure path records a failed attachment but does not close the terminal or remove a worktree created for the worker. The worker host can retain an unused terminal and worktree after reporting that the start failed; local worker start, by contrast, tears down its resources on failure.
Knowledge Base Used: Terminal runtime and interaction
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Advanced
Run ID: 1e7ec356-4175-4950-9fcf-f06ca2693e8e
📒 Files selected for processing (10)
src/main/runtime/launched-agent-composer-readiness.test.tssrc/main/runtime/launched-agent-composer-readiness.tssrc/main/runtime/opencode-worker-composer-transcript.test.tssrc/main/runtime/orca-runtime-activate-managed-worktree.tssrc/main/runtime/rpc/methods/orchestration/federation/federation-launched-agent-readiness.test.tssrc/main/runtime/rpc/methods/orchestration/federation/federation.tssrc/main/runtime/rpc/methods/orchestration/worker/launched-agent-worker-readiness.test.tssrc/main/runtime/rpc/methods/orchestration/worker/local-worker-start.tssrc/main/runtime/rpc/methods/orchestration/worker/workers-new-worktree.test.tssrc/renderer/src/lib/agent-paste-draft.ts
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.
| const wait = await waitForWorkerAgentReady(runtime, terminalHandle, { | ||
| agent, | ||
| reusesTerminal: Boolean(params.terminal), |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
🔎 Supported by static analysis
🏁 Script executed:
rg -n -C 8 --glob '*.ts' \
'\b(failFederatedAttachmentWithReceipt|prepareRemoteAttachmentAuthority|persistFederatedReadinessStage|tearDownFailedWorkerStart)\s*\(' src/main/runtime
rg -n -C 6 --glob '*.ts' \
'residualResources|terminalOwnership|federationAttachStart' \
src/main/runtime/rpc/methods/orchestrationRepository: stablyai/orca
Length of output: 42247
🏁 Script executed:
#!/bin/bash
set -e
printf '%s\n' '--- federation.ts ---'
cat -n src/main/runtime/rpc/methods/orchestration/federation/federation.ts | sed -n '150,290p'
printf '%s\n' '--- failure helper and receipt ---'
rg -n -C 30 --glob '*.ts' 'function failFederatedAttachmentWithReceipt|failFederatedAttachmentWithReceipt|residualResources' src/main/runtime/rpc/methods/orchestration/federation src/main/runtime/orchestration
printf '%s\n' '--- terminal release symbols ---'
rg -n -C 20 --glob '*.ts' 'releaseStructuredWorkerSession|worker-release|tearDownFailedWorkerStart|close.*terminal|terminal.*close|kill.*terminal' src/main/runtimeRepository: stablyai/orca
Length of output: 45668
🏁 Script executed:
#!/bin/bash
set -e
printf '%s\n' '--- federation-start-receipt.ts ---'
cat -n src/main/runtime/rpc/methods/orchestration/federation/federation-start-receipt.ts
printf '%s\n' '--- federation effects ---'
cat -n src/main/runtime/rpc/methods/orchestration/federation/federation-effects.ts
printf '%s\n' '--- failRemoteAttachment definitions/callers ---'
rg -n -C 35 --glob '*.ts' 'failRemoteAttachment\s*\(' src/main/runtime
printf '%s\n' '--- worker release definitions ---'
rg -n -C 35 --glob '*.ts' 'getWorkerTerminalResourceByOwner|beginWorkerTerminalRelease|workerRelease|releaseWorkerTerminal|terminal resource' src/main/runtime/rpc/methods/orchestration/worker src/main/runtime/orchestrationRepository: stablyai/orca
Length of output: 45667
🏁 Script executed:
#!/bin/bash
set -e
printf '%s\n' '--- federation setup persistence ---'
cat -n src/main/runtime/rpc/methods/orchestration/federation/federation-setup.ts | sed -n '1,260p'
printf '%s\n' '--- federation control ---'
cat -n src/main/runtime/rpc/methods/orchestration/federation/federation-control.ts | sed -n '1,280p'
printf '%s\n' '--- residual/effect consumers ---'
rg -n -C 15 --glob '*.ts' 'residual_resources|residualResources|isFederationResidualEffect|action === .created.|kind === .terminal.' src/main/runtime --glob '!*.test.ts'Repository: stablyai/orca
Length of output: 42537
🏁 Script executed:
#!/bin/bash
set -e
printf '%s\n' '--- federated release host ---'
cat -n src/main/runtime/rpc/methods/orchestration/federation/federated-worker-release-host.ts
printf '%s\n' '--- release callers and cleanup bindings ---'
rg -n -C 25 --glob '*.ts' 'releaseRemoteAttachment|orchestration\.federationRelease|federationRelease' src/main/runtime --glob '!*.test.ts'Repository: stablyai/orca
Length of output: 44748
🏁 Script executed:
#!/bin/bash
set -e
rg -n -C 45 --glob '*.ts' 'requestRemoteAttachmentTerminalRelease\s*\(' src/main/runtime
rg -n -C 25 --glob '*.ts' 'createWorkerTerminalResourceStatement|findTransferableWorkerTerminalResource|terminal_handle.*remote_dispatch_attachments' src/main/runtime/orchestration/dbRepository: stablyai/orca
Length of output: 42642
Close a created terminal when federation readiness fails.
When waitForWorkerAgentReady fails, execution reaches failFederatedAttachmentWithReceipt before prepareRemoteAttachmentAuthority. The failure path records the terminal as residual metadata but does not close it or create terminal ownership. federationStop skips failed attachments, and federationRelease returns no_owned_resource for this pre-authority path. A failed attachment can therefore leave its created terminal running without a task.
Add failure cleanup for the newly created terminal. Do not close a reused or external terminal.
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes — re-review of the commits since the prior review at 24a023e: af2dc3e (paired-host readiness) and cd62861 (temporary Windows host gate removed), plus the shared lane helper.
- A paired-host worker start now waits for the input box.
orchestration.federationAttachStartroutes through a newwaitForWorkerAgentReadyhelper, so a worker launched on a paired host takes the same composer-marker wait a local start takes; a reused--terminalstill keepstui-idle. Previouslyworker-start --on <host>always usedtui-idle, leaving the silent task-loss the local start had just fixed. - The temporary Windows host gate is removed.
getLaunchedAgentReadinessLanedrops its platform argument, and thegetTerminalPtyHostPlatform/getLiveTerminalPtyIdlookup added only for that check goes with it, so an OpenCode / OpenCode 2 worker on any host now waits for the input-box marker. Commitcd62861cites an 8/8 capture through the bundledconpty.dll, consistent with the earlier verification in #22593 that DECSET 2004 arrives in order on real Windows ConPTY. - Comments and tests realigned. The retracted "ConPTY does not forward DECSET 2004" claim is dropped from
agent-paste-draft.tsand from the scanner test'sdescribe, and the worker-readiness cases are consolidated intolaunched-agent-worker-readiness.test.ts. The three focused readiness suites (73 tests) pass.
ℹ️ The Windows change is described only in the commit message
The shipped behaviour now contradicts every Windows statement in the PR description: it still says Windows-hosted panes keep tui-idle, that no bundled-conpty.dll capture exists, and lists "a Windows recording … to remove the host check" as a follow-up, while the Review section still describes the host-platform lookup that no longer exists. A reviewer or future reader working from the description is misled, and the row's composerReadyCaptures remain macOS-only, so the self-checking evidence test does not cover the Windows lane.
Technical details
# Windows lane exists only in the commit message
## Affected sites
- `src/main/runtime/launched-agent-composer-readiness.ts:21` — `getLaunchedAgentReadinessLane` is platform-blind, so OpenCode takes the composer-marker lane on Windows panes.
- `src/shared/tui-agent-config.ts` — the `opencode` / `opencode2` `composerReadyCaptures` cite only `opencode-1-18-32-*` and `opencode-2-0-18-*` fixtures, all `platform: darwin`.
- PR description — "Windows-hosted panes are unchanged for now", "No recording through Orca's bundled `conpty.dll` exists yet", and the "Not verified" / "Follow-ups" / "Review" sections that still assume the host check is present.
## Required outcome
- The description matches the shipped behaviour: Windows panes on the composer lane, the host check removed, and no Windows-capture removal still listed as a follow-up.
- Optional: commit the bundled-`conpty.dll` capture and cite it on the row, so the Windows lane has the same committed-evidence trail the macOS rows carry.
## Context
- #22593 (`795b64b9a6a`) already measured DECSET 2004 arriving in order on two Windows ConPTY backends with the marker firing every run; `cd6286109c` adds an 8/8 capture through the bundled DLL, recorded only in the commit message.DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
…de boot captures The transcript replay suite reads every capture under runtime/__fixtures__, so the four OpenCode boot recordings this branch adds are replayed through the serialize round trip too. Each shows the round trip's known grid divergences after a resize (16, 16, 16 and 14 checks), and no I1 byte difference or I3 regression. The serializer and this suite are unchanged from main, so these are pre-existing limitations surfaced by new inputs; record their counts like the other captures' baselines.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to GitHub limitations.
🟠 Major · Keep OpenCode readiness on the Windows idle path. · launched-agent-composer-readiness.ts:10-20
src/main/runtime/launched-agent-composer-readiness.ts:10-20
🩺 Stability & Availability | 🟠 Major | ⚡ Quick winKeep OpenCode readiness on the Windows idle path.
getLaunchedAgentReadinessLaneignores the host platform. Freshopencodeandopencode2starts therefore enterwaitForFreshWorkerComposerin both local-worker and federation paths. If Windows loses the bracketed-paste anchor, the composer marker cannot be detected. The hard timeout then fails the worker start before prompt delivery.Suggested fix
-export function getLaunchedAgentReadinessLane(agent: TuiAgent): LaunchedAgentReadinessLane { - return TUI_AGENT_CONFIG[agent].composerReadyCaptures?.length ? 'composer-marker' : 'tui-idle' +export function getLaunchedAgentReadinessLane( + agent: TuiAgent, + platform: NodeJS.Platform = process.platform +): LaunchedAgentReadinessLane { + const useWindowsIdle = + platform === 'win32' && (agent === 'opencode' || agent === 'opencode2') + return !useWindowsIdle && TUI_AGENT_CONFIG[agent].composerReadyCaptures?.length + ? 'composer-marker' + : 'tui-idle' }
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Advanced
Run ID: d115132e-dc73-416e-aa8e-1b0f4e26b1ef
📒 Files selected for processing (1)
src/main/daemon/serialize-grid-transcript-replay.test.ts
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.
| // OpenCode boot captures: rows on its true-colour background, and the row a shrink leaves | ||
| // behind, restore inexactly after a resize. Pre-existing: they landed with no serializer change. | ||
| 'opencode-1-18-32-timed-boot-hidden-pane': 16, | ||
| 'opencode-1-18-32-timed-boot-slow': 16, | ||
| 'opencode-1-18-32-timed-first-launch': 16, | ||
| 'opencode-2-0-18-timed-boot-hidden-pane': 14, |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🔎 Supported by static analysis
🏁 Script executed:
rg -n -C 10 'new-fail|KNOWN_PREEXISTING_I2_FAILURES' src/main/daemon/serialize-grid-transcript-replay.test.ts
rg -n -C 8 'I2|checkpoint|new-fail' src/main/daemon/serialize-grid-roundtrip.ts
sed -n '180,245p' src/main/daemon/serialize-grid-transcript-replay.test.tsRepository: stablyai/orca
Length of output: 7757
🏁 Script executed:
#!/bin/bash
set -e
printf '%s\n' '--- replay test: setup and assertion path ---'
sed -n '1,80p' src/main/daemon/serialize-grid-transcript-replay.test.ts
sed -n '150,230p' src/main/daemon/serialize-grid-transcript-replay.test.ts
printf '%s\n' '--- roundtrip classification ---'
sed -n '296,345p' src/main/daemon/serialize-grid-roundtrip.ts
printf '%s\n' '--- PR diff for the reviewed file ---'
git diff --no-ext-diff --unified=25 8cc28545a2514cf14cd25187b9bd24a6d9e03ba1 5ff7d779449c6f97aedce9f3092bad2583eb7c23 -- src/main/daemon/serialize-grid-transcript-replay.test.tsRepository: stablyai/orca
Length of output: 12143
Assert OpenCode I2 failure identities, not only their count.
For the default two-seed run, each non-null gridDiff.new adds one new-fail. The OpenCode entries compare only the aggregate count. A different I2 mismatch can therefore replace the known resize mismatch and still pass. Store and compare the expected failureSignatures for each OpenCode transcript.
…one retry Enter OpenCode 2 drops an Enter that arrives before it has drawn its mode row (`Build · <model>`). Worker start pastes at the input-box marker and sends Enter about 0.5 s later, so on a loaded machine the brief could stay in the box as `[Pasted ~N lines]` while the receipt said accepted. Measured: an Enter after the mode row submitted 52/52; one before it stuck 14/18; a second Enter 2 s later submitted every stuck brief (7/7); a lone extra Enter after a landed submit, even mid-reply, changed nothing (60/60 across 2.0.18 and 1.18.32). The agent row's existing one-retry setting, `submitRetryDelayMs`, is set to 2000 ms for opencode and opencode2, and both paths now read it: - worker start (local, and `--on` when the attach launched the terminal) sends one extra Enter after that delay, under the same per-pane serialisation and generation/permission checks as the first; a refused retry leaves the first Enter's result standing. Render-gated agents (claude, codex) are excluded. Coordinator dispatch, re-dispatch, `terminal send` and reused terminals are unchanged. - the renderer's submit-after-ready paste already sent the row's retry Enter (codex); it now covers OpenCode too, which it pastes at the same marker with a 50 ms Enter gap. The paired-host attach now delivers its preamble through the same helper as a local start instead of a copy of it.
There was a problem hiding this comment.
ℹ️ No critical issues — one minor config/evidence question inline.
Reviewed changes — incremental re-review of the commits since the prior Pullfrog review at cd62861; the substantive one is 245572e, which adds a retry Enter to a launched OpenCode worker's first dispatch on top of the composer-wait fix reviewed earlier.
- A launched OpenCode worker's first dispatch gets one retry Enter.
RuntimeAgentPromptWriteOptionsgainsretrySubmitAfterLaunch;writeTerminalAgentPromptsends a second\rafter the agent row'ssubmitRetryDelayMs, under the same request / generation / permission checks as the first, and threads the resultingsubmitscount intobytesWrittenand every receipt.omp(paste-frame) andclaude/codex(render-gated) are excluded, and a reused terminal keeps one Enter. - The launch flag is threaded through both start paths.
deliverWorkerDispatchPreamble(local start and federated attach) takeslaunchedTerminal: !params.terminal; the federated attach now shares that helper instead of an inline copy.opencode/opencode2setsubmitRetryDelayMs: 2000, and the renderer's existing draft-paste retry reads it through a new sharedgetAgentSubmitRetryDelayMs, so OpenCode draft pastes now get the retry too. - Tests. A new main-process suite asserts the second Enter fires exactly at the row delay, that non-launch / render-gated / plain agents keep one Enter, and that a pane exit before the retry leaves the first Enter standing; the renderer suite covers the OpenCode retry, and the federated/local readiness suites assert the
retrySubmitAfterLaunchflag.
The commit message documents the stray-Enter risk well (a lone extra Enter after a landed submit changed nothing, 60/60 across 2.0.18 and 1.18.32), which is the concern the worker path's permission guard was added for.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
| ], | ||
| // Why: OpenCode 2 drops an Enter sent before its mode row is drawn, which can trail the box | ||
| // by over a second under load; a second Enter 2 s later submitted every stuck brief measured. | ||
| submitRetryDelayMs: 2000 |
There was a problem hiding this comment.
The rationale here describes OpenCode 2, but the same submitRetryDelayMs: 2000 is set on the OpenCode 1.18.x opencode row (and the opencode2 row points back to it). The committed 1.18.x captures show the composer marker firing at the box, and the commit message ties the Enter-drop to 2.x's mode row, so the first Enter should already land for 1.18.x — is the retry needed there, or should the field be scoped to opencode2? As written, every launched 1.18.x worker start and every 1.18.x draft paste now pays a 2 s retry that may never fire.
The OpenCode rows' retry Enter (one extra Enter 2 s after the first) is blind in the renderer's submit-after-ready paste, which reaches every OpenCode launch that pastes and submits a prompt. If OpenCode asked for a tool permission or a question inside those 2 s, the Enter could answer it. The renderer now reads the status the agent already reports for that pane (the same hook status the sidebar shows) before sending the retry. It skips the retry when the pane is waiting on the user (a permission or question prompt) or when a new turn started after the first Enter, since the first Enter then landed. With no reported status (status hooks off) it stays blind, as the worker-start retry does. Turn clocks are compared with each other, never with the renderer's clock, so a remote host's clock skew cannot flip the decision. Also adds the missing test for the worker-start retry's own permission guard: a pane that reports a permission prompt after the first Enter gets no second Enter.
…k was submitted A freshly launched OpenCode worker's first dispatch reported "accepted" once the bytes were written, even when the brief stayed unsubmitted in the input box. Orca's OpenCode status plugin posts `working` for every real submit and nothing for a stuck brief (QA: 59-77 ms after the Enter; 10/10 forced-stuck briefs posted nothing), so with status hooks on that post is now the evidence: - the retry Enter is skipped when the first Enter already started a turn for this request, which also keeps it away from a user typing or a prompt that follows a landed submit; - the receipt is observable (provider `opencode`/`opencode2`, observation `supported`): a turn observed after either Enter reports the worker ready, and none within the existing observation window reports the existing `outcome_unknown` / `turn_start_unobserved` / `turn_unobserved`. The terminal and dispatch capability are kept, so the user can still press Enter and a later worker report settles the dispatch. OpenCode's boot `done` post with an empty prompt is not a turn start: only a `working` post after the first Enter, claimed by this request, counts. With status hooks off nothing changes (blind retry, `unsupported` receipt). Coordinator dispatch, re-dispatch and `terminal send` stay unchanged. The receipt's provider type is widened in typed code to the agents whose turn start Orca observes, including antigravity, which it already carried.
…tops the OpenCode retry Enter Main and the renderer now skip the retry for the same two reasons: the pane is waiting on the user, or a turn started. This pins main's half with a hook-reported permission prompt, as OpenCode's plugin posts it.
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Advanced
Run ID: 7af4cc64-45e0-498d-b280-8f6e396c93a5
📒 Files selected for processing (12)
src/main/runtime/agent-prompt-launch-submit-retry.test.tssrc/main/runtime/agent-prompt-launch-turn-observation.test.tssrc/main/runtime/agent-prompt-submission-verification.tssrc/main/runtime/orca-runtime-write-terminal-agent-prompt.tssrc/renderer/src/lib/agent-paste-draft-submit-retry.test.tssrc/renderer/src/lib/agent-paste-draft.test.tssrc/renderer/src/lib/agent-paste-draft.tssrc/renderer/src/lib/agent-submit-retry-guard.test.tssrc/renderer/src/lib/agent-submit-retry-guard.tssrc/renderer/src/runtime/runtime-terminal-inspection.tssrc/shared/runtime-terminal-contracts.tssrc/shared/tui-agent.ts
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review.
| */ | ||
| export function isSubmitRetryStillOwed( | ||
| beforeSubmit: PaneTurnStatus | undefined, | ||
| now: PaneTurnStatus | undefined | ||
| ): boolean { | ||
| if (!now) { | ||
| return true | ||
| } | ||
| if (now.state === 'blocked' || now.state === 'waiting') { | ||
| return false | ||
| } | ||
| if (now.state !== 'working') { | ||
| return true | ||
| } | ||
| // Host-stamped turn clocks compared with each other, never with this renderer's clock. | ||
| return beforeSubmit?.state === 'working' && turnStartOf(beforeSubmit) === turnStartOf(now) | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🔎 Supported by static analysis
🏁 Script executed:
sed -n '1,100p' src/renderer/src/lib/agent-submit-retry-guard.ts
sed -n '210,280p' src/renderer/src/lib/agent-paste-draft.ts
rg -n 'turnStartedAt|state: .done.' src/main/agent* src/main/runtime src/renderer/src/store src/shared/agent-status-types.tsRepository: stablyai/orca
Length of output: 40742
🏁 Script executed:
set -o pipefail
base=8cc28545a2514cf14cd25187b9bd24a6d9e03ba1
head=07ff2e5214ec8a876b764a2bae864f8a6176b5f2
printf '%s\n' '--- diff stat ---'
git diff --stat "$base" "$head"
printf '%s\n' '--- changed paths relevant to question ---'
git diff --name-only "$base" "$head" | rg 'agent-submit-retry-guard|agent-paste-draft|agent-status|server-status|opencode|codex|agent-status-types' || true
printf '%s\n' '--- guard and caller diff ---'
git diff --unified=35 "$base" "$head" -- \
src/renderer/src/lib/agent-submit-retry-guard.ts \
src/renderer/src/lib/agent-paste-draft.ts
printf '%s\n' '--- status application ---'
cat -n src/main/agent-hooks/server/server-status-application.ts | sed -n '1,210p'
printf '%s\n' '--- persistence validation ---'
cat -n src/main/agent-hooks/server/server-persistence-validation.ts | sed -n '1,210p'
printf '%s\n' '--- live status builder ---'
cat -n src/renderer/src/store/slices/agent-status-live-entry-builder.ts | sed -n '90,235p'
printf '%s\n' '--- turn-started-at tests ---'
cat -n src/main/agent-hooks/server-turn-started-at.test.ts | sed -n '50,190p'
printf '%s\n' '--- lifecycle tests ---'
cat -n src/main/agent-hooks/server-opencode-lifecycle.test.ts | sed -n '1,130p'
rg -n -C 8 'agentType: .(codex|opencode).|turnStartedAt|state: .(working|idle|done).' src/main/agent-hooks src/renderer/src/store/slices src/shared/agent-status-types.ts | head -n 500Repository: stablyai/orca
Length of output: 42285
🏁 Script executed:
set -o pipefail
printf '%s\n' '--- retry guard tests ---'
cat -n src/renderer/src/lib/agent-submit-retry-guard.test.ts
printf '%s\n' '--- retry caller tests ---'
cat -n src/renderer/src/lib/agent-paste-draft-submit-retry.test.ts
printf '%s\n' '--- exact turn timestamp tests ---'
cat -n src/main/agent-hooks/server-turn-started-at.test.ts | sed -n '55,190p'
printf '%s\n' '--- exact live builder and status type ---'
cat -n src/renderer/src/store/slices/agent-status-live-entry-builder.ts | sed -n '105,135p'
cat -n src/shared/agent-status-types.ts | sed -n '55,115p'
printf '%s\n' '--- OpenCode lifecycle and transcript tests ---'
cat -n src/main/agent-hooks/server-opencode-lifecycle.test.ts | sed -n '1,115p'
cat -n src/main/runtime/opencode-worker-composer-transcript.test.ts | sed -n '1,130p'
printf '%s\n' '--- prompt submission and Enter handling references ---'
rg -n -C 6 'sendRuntimePtyInputVerified|inputKind|submit|\\\\r|empty prompt|Enter|carriage return' src/main src/renderer/src/lib src/shared | head -n 600Repository: stablyai/orca
Length of output: 42440
Compare turn timestamps before filtering by state.
isSubmitRetryStillOwed compares timestamps only for working status. A new turn can start and finish before the retry delay, leaving a done status with a newer turnStartedAt. The guard then returns true, and agent-paste-draft.ts sends a second '\r' to the completed agent session. This violates the skip-after-progress behavior and injects unwanted input.
Suggested fix
if (now.state === 'blocked' || now.state === 'waiting') {
return false
}
+ if (beforeSubmit && turnStartOf(beforeSubmit) !== turnStartOf(now)) {
+ return false
+ }
if (now.state !== 'working') {
return true
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| */ | |
| export function isSubmitRetryStillOwed( | |
| beforeSubmit: PaneTurnStatus | undefined, | |
| now: PaneTurnStatus | undefined | |
| ): boolean { | |
| if (!now) { | |
| return true | |
| } | |
| if (now.state === 'blocked' || now.state === 'waiting') { | |
| return false | |
| } | |
| if (now.state !== 'working') { | |
| return true | |
| } | |
| // Host-stamped turn clocks compared with each other, never with this renderer's clock. | |
| return beforeSubmit?.state === 'working' && turnStartOf(beforeSubmit) === turnStartOf(now) | |
| } | |
| */ | |
| export function isSubmitRetryStillOwed( | |
| beforeSubmit: PaneTurnStatus | undefined, | |
| now: PaneTurnStatus | undefined | |
| ): boolean { | |
| if (!now) { | |
| return true | |
| } | |
| if (now.state === 'blocked' || now.state === 'waiting') { | |
| return false | |
| } | |
| if (beforeSubmit && turnStartOf(beforeSubmit) !== turnStartOf(now)) { | |
| return false | |
| } | |
| if (now.state !== 'working') { | |
| return true | |
| } | |
| // Host-stamped turn clocks compared with each other, never with this renderer's clock. | |
| return beforeSubmit?.state === 'working' && turnStartOf(beforeSubmit) === turnStartOf(now) | |
| } |
…il a missing plugin can be told apart Step 2 made a launched OpenCode worker's receipt observable whenever status hooks were on in settings. But "on in settings" does not mean Orca's OpenCode plugin loaded: its install can fail silently, and the plugin's first post arrives only after a real submit (37-49 ms after the Enter, 8/8 panes), so a plugin that never loaded looks exactly like a stuck brief. On such a host every OpenCode worker start would have waited about 32 s longer and reported outcome_unknown for a worker that was working, which is worse than before. The receipt is back to what main reports for OpenCode (`unsupported`, so the start is ready). What stays is the useful part of the hook signal: during the retry delay Orca still watches for a turn this request started, and skips the retry Enter when it sees one. No post (a stuck brief, or a plugin that never loaded) simply means the retry goes out, as before. The watch registers the request only for that wait and always releases it, and a pane that exits during the wait leaves the first Enter's result standing, with hooks on or off. The receipt's provider type is back to its previous values, since nothing needs the widening now.
There was a problem hiding this comment.
✅ No new issues found in the new commits.
Reviewed changes — incremental re-review of the three commits since the last Pullfrog review at 245572e: deb5c06, f5229ee, 07ff2e5. They close the loop on the retry Enter by making it state-aware on both paths and by making a launched OpenCode worker's receipt honest about whether the task was submitted.
- The renderer's retry Enter is now gated on reported state.
deb5c06addsagent-submit-retry-guard.tsand wires it intoagent-paste-draft.ts: it reads the pane's hook status before the first Enter and again after the row'ssubmitRetryDelayMs, then skips the retry when the pane iswaiting/blocked(a permission or question prompt) or when a turn started after the first Enter. With no reported status it stays blind, as before. This reaches every row with a retry delay (codex,opencode,opencode2), not just OpenCode. - A launched OpenCode worker's first dispatch now has an observable receipt.
f5229eewidensresolveAgentPromptObservedProviderso OpenCode/OpenCode 2 with status hooks on is a settlement provider: the correlation request is registered before the retry wait, an inline observation probe (timeoutMs: submitRetryDelayMs, output evidence disabled) skips the retry when the first Enter already started a turn, and a turn that never starts leaves the existingoutcome_unknownreceipt instead of a false ready. The receipt'sprovidertype is widened toAgentPromptObservedProvider. - Main's permission case is pinned.
07ff2e5adds a worker-start test where a hook-reported permission prompt after the first Enter suppresses the retry.
I independently traced the register-before-retry ordering against the correlation ledger and the verifier (no spurious turn_started, no mis-attributed claim, no double registration), and re-checked the renderer guard's clock semantics. The guard's remaining blind spots (a working→working new turn for OpenCode, and a turn that completes inside the retry window) are equivalent to or weaker than the blind retry it replaces, and the commit message records the extra Enter as harmless, so I don't consider them defects.
ℹ️ The observable receipt is only in the commit message, not the PR description
The PR description's "What is different for you" and "Mechanism" still describe only the composer wait and the scanner change. They do not mention the retry Enter, and they do not mention that a launched OpenCode/OpenCode 2 worker with hooks on can now settle as turn_start_unobserved / outcome_unknown where main always returned a ready receipt. That is a coordinator-visible behavior change (the tool keeps the terminal and dispatch capability, and a later worker report still settles it), so a reader working from the description will not expect it.
Technical details
# OpenCode's post-write turn observation is undocumented
## Affected sites
- `src/main/runtime/agent-prompt-submission-verification.ts:69` — `resolveAgentPromptObservedProvider`
returns `opencode`/`opencode2` when `retrySubmitAfterLaunch` and hooks are on, so the receipt is
`observation: 'supported'` rather than `'unsupported'`.
- `src/main/runtime/rpc/methods/orchestration/worker/worker-start-readiness-settlement.ts:93` — an
unobserved turn returns `state: 'outcome_unknown'` with `turn_start_unobserved`; main returned
`ready`.
- `src/shared/tui-agent-config-types.ts:51` — the `submitRetryDelayMs` field and the retry Enter it
drives are not described either.
## Required outcome
- The description's "What is different for you" and "Mechanism" cover the retry Enter and the
turn-observed receipt, including that a launched OpenCode worker whose turn is never observed
now reports `outcome_unknown` (rescuable via a later worker report) instead of a false `ready`.
## Context
- The PR-description staleness flagged earlier was about the Windows gate; this gap is new to
`245572e`/`f5229ee` and is the only reason I am not approving alongside the clean delta.DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
There was a problem hiding this comment.
✅ No new issues found in the new commits.
Reviewed changes — incremental re-review of the single commit since the prior Pullfrog review at 07ff2e5: d0b92d0, which changes how a launched OpenCode worker's retry Enter is decided and reverts the earlier observable-receipt design.
- The OpenCode observable receipt is removed.
resolveAgentPromptObservedProviderand theAgentPromptObservedProvidertype are deleted (net-neutral againstmain), andsettlementAgentis again onlyantigravity/claude/codex. A launched OpenCode / OpenCode 2 worker's receipt is thereforeprovider: 'unsupported', observation: 'unsupported'again, so it no longer settlesturn_start_unobserved/outcome_unknownthe wayf5229eemade it. The rationale — a status plugin that never loaded is indistinguishable from a brief stuck in the box — is sound, and it brings the receipt back in line withmain. - The retry-Enter decision moves into a dedicated helper.
observeAgentPromptTurnStartWithinregisters the correlation request, runsverifyAgentPromptSubmission(allowOutputEvidence: false) for the row's retry delay, and returnstrueas soon as this request's turn starts;agent_prompt_stalledmeans "retry", while any other error rethrows into an outer best-effort catch. The request is always forgotten infinally, so nothing stays queued behind a receipt that does not own the turn. - Tests realigned. The rewritten
agent-prompt-launch-turn-observationsuite pins the skip/retry paths against the unsupported receipt, and the status-hooks mocks the removed provider needed are dropped. I ran both touched suites:agent-prompt-launch-submit-retry(8 tests) andagent-prompt-launch-turn-observation(5 tests) pass.
I traced the register/forget ordering against the correlation ledger and the outer catch: for OpenCode the accepted-unsupported receipt matches main, and codex/claude never reach the helper (render gate / no retry delay), so the settlement path is unchanged. No new issues.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
…-worker-waits-for-input-box # Conflicts: # src/main/runtime/rpc/methods/orchestration/federation/federation.ts
Review status: ready for Brennan's review at
|



ELI5
When a coordinator starts an OpenCode worker, Orca waits until OpenCode looks ready, types the task in, and presses Enter. Two things went wrong. First, Orca treated a terminal title reading just "OpenCode" as ready, but OpenCode sets that title a moment before it draws its input box, and many shells set the title to
opencodeseconds earlier, so the task was often typed into nothing and lost. Second, OpenCode 2 ignores an Enter that arrives before it has finished drawing its input area, so on a busy machine the task could sit in the box unsent. Both times the start still reported success. Now Orca waits for the moment OpenCode puts its cursor inside its input box, and presses Enter once more two seconds later unless it can already see the task was taken.What Changed
The problem.
orca orchestration worker-start --agent opencode(oropencode2) returned a receipt saying the worker was ready and its input was accepted, but OpenCode's input box stayed empty: the task never arrived, and the worker never reported back. Eight people reported it on macOS, Linux and Windows, across OpenCode 1.18.x and 2.x (#13911, #22580).Why it happened, part 1: the task was typed before the box existed. Worker start waited for the terminal to look idle (the
tui-idlewait), which accepts a title holding only the agent's name as "ready". OpenCode writes itsOpenCodetitle 30–161 ms before it draws the input box (15 of 15 recorded launches). A shell that auto-titles the pane (for example a zsh preexec hook that titles the pane with the running command) writesopencodethe moment the command starts, seconds earlier; with that title present the wait settles as soon as it is registered, before OpenCode has drawn anything. Main already had the right wait,waitForFreshWorkerComposer, which waits only for the agent's own input-box marker, but worker start used it for ZCode alone (agent === 'zcode'), and only for a start on this computer: a start on a paired host (worker-start --on <host>) waitedtui-idlefor every agent.Why it happened, part 2: OpenCode 2 drops an early Enter. OpenCode 2.x ignores an Enter that arrives before it has drawn its
Build · <model>mode row. Measured without Orca in the loop: an Enter after that row submitted 67/67 times; an Enter before it left the brief stuck 14/18 times, the whole brief sitting in the box as[Pasted ~N lines]. Worker start presses Enter about 0.5 s after the paste, which is after the row in normal conditions, but the row can trail the input-box marker by more than 0.5 s when the machine is loaded (about 9% of runs, mostly under load). Waiting for the input box (part 1) exposes this, and live QA on the head before the retry saw it once: 1 of 10 OpenCode 2.x starts stuck while the receipt saidaccepted. The renderer's launches that paste and submit a prompt hit the same thing more often, because they press Enter only 50 ms after pasting (the same measured timing left 3 of 5 briefs stuck). This stuck case is not new: main showed it too (one OpenCode 2.x start in the first QA round, after a long wait on a slow machine), and main's renderer launches use the same 50 ms gap. This PR now fixes it rather than leaving it.What is different for you.
worker-start --on <host>, once that host runs this version (the wait runs on the host that owns the terminal; an older host keeps the old wait, and nothing changes on the wire).tui-idletimeout today).--onnow waits for its input box too, the same wait a local ZCode start already used; before, that path waitedtui-idle.--terminal), structured workers, coordinator dispatch, re-dispatch,orca terminal sendand every other agent are unchanged.This PR is step 2 of a plan to stop Orca treating a terminal title that only names the agent as proof the agent is ready or idle. Step 1 (#24083) changes only what the sidebar and dashboard display for such a title. Step 2 (this PR) stops worker start from typing a task on it, for the agents whose input-box marker has been recorded, and makes sure the task it types is submitted. Later steps stop the rest of Orca from acting on it: the end of an agent's turn (notifications, mail pushed to the agent, workspace cleanup), then the status reported over the wire and on the phone. This PR changes no title classification or settle rule, so it does not depend on #24083 and the two can merge in either order.
Mechanism:
tui-agent-config.ts) gains an optionalcomposerReadyCaptures: the committed terminal recordings in which that agent's existing input-box marker (draftPasteReadySignal) fires at the box. Worker start derives its lane from it: a row with evidence waits for the marker alone; a row without keepstui-idle.zcode(its existing recording),opencode(three 1.18.32 recordings) andopencode2(one 2.0.18 recording) carry it. The hard-codedagent === 'zcode'check is gone.launched-agent-composer-readiness.ts:waitForLaunchedAgentComposerpicks the lane for a freshly launched agent (the module and function name draft feat(source-control): start the AI buttons' agents through agent.launch (step 2 of 2) #23748 uses, so the two PRs converge on one function), andwaitForWorkerAgentReadyadds the one rule both starts share: a caller-supplied--terminalwas not freshly launched, so its marker may be long gone and it keepstui-idle. The local start and the paired-host attach both call it.conpty.dll, and two through the system ConPTY as a control. In all 8, on both backends, OpenCode's own bracketed-paste enable arrived before its input box, it never turned bracketed paste off while booting, and the unchanged marker fired on exactly the read that first drew the box. So no platform check is needed: the lane comes from the agent's evidence alone. Git Bash, cmd and WSL panes, and Linux, are inferred rather than recorded: the marker's anchor still comes from OpenCode itself, and the revocation below handles a shell prompt that toggles bracketed paste. Known, unrecorded case: the standalone Orca server running under Bun spawns terminals throughBun.Terminalrather than node-pty, and no capture of that path exists.render-cursor-after-bracketed-paste: the cursor is shown after bracketed paste,ESC[?2004h, is enabled) now also ends atESC[?2004l, the same mechanism Grok, DSH and ZCode use for leaving the alternate screen. No new signal id. Why: zsh, fish and bash 5.1+ enable bracketed paste at their prompt and disable it just before running the command, so without this any launcher spinner that shows the cursor before OpenCode starts would count as "input box ready". OpenCode itself never sendsESC[?2004lwhile booting (0 in all 15 recordings).submitRetryDelayMs(until now only codex, 1200 ms), is set to 2000 ms foropencodeandopencode2, and both paths read it through one shared reader. Worker start passes a new send option,retrySubmitAfterLaunch, only from a start that launched the terminal (localdeliverWorkerDispatchPreamble, and the paired-host attach when it created the terminal; the attach now delivers its preamble through that same helper instead of a copy). The runtime sends the retry inside the existing per-pane prompt serialisation, after re-checking the pane's generation, the handle's target and that no permission prompt appeared; a refused retry leaves the first Enter's result standing. Agents whose composer Orca already waits for before the first Enter (claude, codex) are excluded on this path.working59–77 ms after a real submit and nothing for a stuck brief); a turn it sees, or a question or permission prompt, cancels the retry, and no post just means the retry goes out. The renderer reads the status the agent already reports for that pane from the existing status store and skips on a waiting or blocked pane, or on a turn that started after the first Enter (comparing the host's own timestamps, never the renderer's clock). With status hooks off, both send the retry blind.ESC[?2004h|Search ESC[?25|l more textfired though no show-cursor was ever sent. Carried characters are now used only to spot anchors and leave sequences split across reads. Latent for today's one-character markers (grok, DSH, ZCode); required before OpenCode's 6-character marker moves onto that path.waitForFreshWorkerComposernow returns the same result as thetui-idlewait, so worker start records the wait-for-setup outcome on this lane too. Pre-existing bug on main: a ZCode worker in await-for-setupworktree left its setup receipt stuck atrunningwith nosetup_settledstage. Fixed here for ZCode and OpenCode alike.src/main/runtime/__fixtures__/in the existing timed shape (.txt+.meta.json+.timing.json): 1.18.32 slowest boot (3.9 s of silence, 161 ms from title to box), 1.18.32 with hidden-pane replies, 1.18.32 first launch on an empty home, and 2.0.18 with hidden-pane replies. The repo scanner printscleanon each; the only path is a same-length/Users/USER1/…placeholder. The Codex suite's timed-fixture reader moved into the shared replay harness so both use one reader. The terminal serialize replay suite reads every recording in that folder, so the four new ones are baselined there with their pre-existing grid-restore counts (16, 16, 16 and 14; no byte differences, no regressions; the serializer is unchanged).795b64b9a6a): two test comments and the matching production comment on the blind-paste fallback inagent-paste-draft.ts.Residual (temporary). The input-box wait does not stop early when something goes wrong during boot, so these starts fail only after the full budget (60 s by default), with the error
timeout:tui-idlewait failed at once withterminal_exited; the input-box wait does not watch for exit. Racing it against the exit would fix this case.Both apply to OpenCode and OpenCode 2 (local and
--on) and to ZCode started with--on. A local ZCode start already behaves this way on main.Why
draftPasteReadySignalalone. It would also move grok (its inline mode never fires the marker, so 60 s failures), mimo (marker set by parity, never recorded), codex and DSH, without evidence.Build · <model>row instead of retrying. It would key readiness on text that depends on the agent's mode and model name, and it needs its own committed capture; the retry reuses an existing per-agent setting and is measured harmless.outcome_unknown. The receipt stays as on main; the plugin signal is used only to skip an unnecessary retry, where silence costs nothing.ESC[?2004l--ongets the input-box wait and the retry, but its attach receipt says ready without observing a turnstart_unknownagent === 'zcode'block, a textual conflict to resolve by keeping the evidence-field predicate.Linked Issue
Fixes #13911 / STA-3952 (macOS tested live on the final head; Windows PowerShell panes covered by capture; Git Bash, cmd, WSL and Linux inferred).
Part of #22580 / STA-8331 (the OpenCode half; its Crush and Devin reports are other mechanisms).
Related #6011 / STA-676.
Live QA
Real Orca worker starts (
orca orchestration worker-start) on a second Mac (M4 MacBook Air), against real OpenCode 1.18.32 and 2.0.18 in isolated homes with auto-update off. A brief counts as delivered only when its unique token shows up as a submitted message in OpenCode's own session store; "lost" means an empty input box, "stuck" means the brief sat unsent in the box.d0b92d044c1(the final code; the later merge of main changed only the brief's text)opencode2 --standalone)opencodesucceededsucceeded,setup_settledrecordedreadyandinput accepted, including every lost one.Main, OpenCode 1.18.32: the start reported success, but the input box is empty and the task is gone.
Main, OpenCode 2.0.18: the same loss.
This branch before the retry Enter: under load, OpenCode 2 kept the brief in the box unsent while the receipt said accepted.
Final head, OpenCode 2.0.18 at a load average of 52: the task was submitted (the red line is the free model's own rate-limit reply, after the submit).
Visual Proof
The change is when the task is typed and submitted, not what is drawn; the before/after screenshots are in "Live QA" above.
Testing
conpty.dll, two through the system ConPTY; replayed through the scanner, not an end-to-end worker start). Git Bash, cmd, WSL, Linux and SSH are inferred (the marker comes from OpenCode's own bytes; shells that arm and revoke bracketed paste around a command are handled by the revocation).launched-agent-composer-readiness.test.ts: an exhaustive per-agent lane record (adding an agent fails to compile until someone decides), and evidence that checks itself: every cited recording is committed with its sidecar, the row's current signal fires on it, and for OpenCode rows the first ready read is exactly the read that shows the input box (4/4).opencode-worker-composer-transcript.test.ts: each OpenCode recording replayed through the real runtime at its recorded read times, behind a zsh launch that auto-titles the paneopencode. The worker-start lane settles on the input-box read (6.7 s on the slow boot, after 3.9 s of silence); main'stui-idlewait on the same feed settles before OpenCode's first byte.draft-paste-ready-scanner-chunking.test.ts: every committed recording on the revocable path (grok alt and inline, DSH, ZCode, OpenCode ×5, OpenCode behind a zsh launch ×4) fed whole, one character at a time, in its recorded reads and in 12 seeded chunkings. Ready always lands on the read holding the offset a plain string walk finds. A regression guard for grok, DSH and ZCode.launched-agent-worker-readiness.test.ts(renamed fromzcode-worker-readiness.test.ts): zcode, opencode and opencode2 wait for the box and ask for the retry; codex, claude, grok and mimo keeptui-idle; reused terminals keeptui-idleand ask for no retry; a timeout never delivers.federation-launched-agent-readiness.test.ts(paired-host start): a terminal the attach created for opencode, opencode2 or zcode waits for the box, never callstui-idle, and asks for the retry; a reused--terminalkeepstui-idleand asks for none; a box that never appears fails the attach atagent_readinesswithtimeoutand types nothing.agent-prompt-launch-submit-retry.test.ts(real runtime, fake PTY): opencode and opencode2 send a second Enter exactly at the row delay; a send that did not launch the agent sends one; codex, claude and aider send one even when asked; a permission prompt after the first Enter stops the retry; a pane that exits before the retry keeps the first result.agent-prompt-launch-turn-observation.test.ts(real runtime, hook status rows): a turn after the first Enter skips the retry; no post sends it; the plugin's firstdonepost (empty prompt) does not count as a turn; a hook permission prompt skips it; a pane exit during the wait keeps the first result; the receipt staysunsupportedthroughout.workers-new-worktree.test.ts: on the composer lane, a wait-for-setup worktree's receipt readssucceededand asetup_settledstage is recorded.agent === 'zcode': 7 fail;tui-idle: 4 of 5 fail (the reused-terminal case passes either way, as it should);tc:nodeandtc:webpass atd0b92d044c1and again after merging main at63a7311c839; after the merge, 134 related test files pass (3111 tests);check:code-quality:changedreports 0 findings;oxlintis clean on every touched file; 122 related test files pass (2939 tests), includingorca-runtime.test.ts,pty-transcript-secret-scan.test.mjsand the terminal serialize replay suite.Review
ESC[?2004lin any of them; docs(tui-agent-config): correct the OpenCode readiness-budget rationale #22593's commit message retracts the ConPTY claim; the paired-host attach fails a composer timeout through the sameagent_readinessfailure path atui-idletimeout already takes (both waits throwtimeout); OpenCode's plugin reports permission and question prompts aswaiting, which both retry checks skip on.worker-start --on <host>start (covered by unit tests only); an end-to-end worker start on Windows; Git Bash, cmd, WSL, Linux, tmux or daemon behaviour of the marker; the standalone server'sBun.Terminalspawn path; mimo's stream; a user typing into a freshly started OpenCode pane within the 2 s window (the retry would submit their partial text; codex's renderer retry already behaves this way).--onattach, so its receipt can saystart_unknown.codex-composer-prompt's bracketed-paste anchor, the remaining un-revoked one.Agent skill upstream boundary
docs/reference/agent-skill-sharing-upstream-boundary.mdand copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred): targeted typecheck, lint and tests pass locally; the full suites and build are left to CI