Skip to content

Never read an unanswerable hasPty probe as proven PTY absence - #16932

Open
brennanb2025 wants to merge 3 commits into
mainfrom
brennanb2025/haspty-null-demotion-r1
Open

brennanb2025 wants to merge 3 commits into
mainfrom
brennanb2025/haspty-null-demotion-r1

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Aug 28, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 2 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​242 0 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​242
Prod 2 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​75 $\color{#cf222e}{\Huge{\mathbf{−}}}$​4 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​71

Summary

  • resolve the terminal-list "proven absence" rescue through an exhaustive live | unverifiable | exited presence observation instead of hasPty !== true
  • a null (unanswerable) per-pane presence answer now records an unverifiable liveness verdict instead of demoting the pane to connected:false
  • a later confirmed live observation clears the recorded doubt; a confirmed false still demotes exactly as before

Author: @BrennanKB5

ELI5

Orca keeps a list of your terminals and asks the terminal engine "does this pane still have a live process?" The engine has three honest answers: "yes", "no", and "I couldn't check right now." Before this fix, "I couldn't check right now" was treated the same as "no" — so a terminal whose agent was alive and working could be shown as disconnected, and the orchestrator would write the worker off. Now "I couldn't check" is kept as its own answer: the pane stays connected, the doubt is recorded, and it's re-checked on the next look.

User-facing before / after

When you'd hit this: you're coordinating worker agents in Orca terminals (or just running orca terminal list) at a moment when the PTY backend can't answer the per-pane presence probe — e.g. the daemon-backed provider is mid-restart/being swapped, or the pane's provider lookup fails — and the same refresh's inventory snapshot happens to miss that pane.

Before: the pane flips to disconnected in terminal.list / orca terminal list, the coordinator's availability filter drops that worker terminal from the dispatchable pool, and worker/federation status surfaces read the pane's connected:false as exited — while the agent process is alive and still working. A live worker gets written off from one unanswerable query.

After: the pane stays connected in the list, and the unanswerable query is recorded as an unverifiable liveness verdict with a reason — the same verdict vocabulary orchestration.workerShow / federationShow already publish — so observation surfaces say "unverifiable", never "exited", until a confirmed answer arrives. A confirmed "no" (the engine positively observed the pane absent) demotes exactly as before, and a confirmed "yes" clears any recorded doubt.

Reliability contract

  • Invariant: an unanswerable pane-presence query can never become a confirmed "no PTY". exited requires positive evidence; loss of the ability to ask is unverifiable (docs/reference/ssh-execution-boundary.md rule 2).
  • Failure source: buildTerminalSummary's rescue read hasPty !== true, so the controller adapter's documented null ("the query could not be answered": failed provider lookup, probe-less provider, probe threw) counted as proof of absence.
  • Type carry: the answer resolves through PtyPresenceObservation (live | exited | unverifiable); the demotion gate isConfirmedPtyAbsence(presence: ConfirmedPtyPresence) excludes the unverifiable arm at the type level — doubt is not assignable where a confirmed answer is expected. No casts or widenings.
  • Oracle: pre-fix, the new tests fail with connected:false, no recorded verdict, and listAvailableWorkerTerminals returning [] for a live worker terminal; the pre-existing inventory-absence, hasPty-rescue, SSH/remote-exclusion, and unavailable-inventory tests all still pass unchanged.
  • Ablation: each production hunk reverted individually goes red — resolver null arm (3 tests), unverifiable-marking arm (2), live-rescue forget arm (1), exited demotion arm (3, including the pre-existing proven-absence test).
  • Consumers checked (all readers of the changed field/verdict): coordinator listAvailableWorkerTerminals (now keeps the terminal dispatchable); CLI terminal list formatter (prints connected truthfully); resolveGroupAddress, plugin listWorktreeTerminals, federation/topology terminal-effect recorders, and the active-terminal fallback (none read connected — unaffected); renderer remote-worktree-sleep (reads connected === true for ssh panes, which this predicate never demoted); verdict readers inspectWorkerTerminal (workerShow/workerRead/workerStop/release-completion) and inspectRemoteAttachment (federationShow/Read/ReadOutput/Stop) — both branch on unverifiable before the connected === false → exited fallback; unverifiableStopVerdict keeps a failed stop unverifiable.
  • Remote wire: no RPC params, stream frames, or opcodes change. Value-level (Rule 3) review: terminal.list stops publishing a false connected:false during an unanswerable blip (old clients read connected:true exactly as before), and observation.status: 'unverifiable' can occur in a window that previously misreported — that value and its reason field already ship on these surfaces, so mixed-version peers parse it today. No capability gating needed.
  • Performance: the inventory-hit path short-circuits before the probe (pinned by test) — zero added work; the missed-pane path makes the same single sync hasPty call as before plus O(1) writes to the existing 256-capped verdict map. No new polling, timers, subprocesses, or unbounded state.
  • Residual risk: a provider that answers a confident-but-wrong false for a pane it does not own (e.g. the pre-swap local provider during daemon startup) is a separate coercion site of this class and is deliberately not touched here, matching the sibling-site split in Preserve legacy daemon ownership when liveness is unavailable #16900/Fix Windows daemon host pruning on unverifiable liveness #16908/Keep relay completion evidence live/unverifiable/exited, never coerced #16926.

Verification

  • pnpm test src/main/runtime/terminal-list-stale-leaf-liveness.test.ts src/main/runtime/orchestration/coordinator-task-dispatch.test.ts (12/12 post-fix; 3 fail pre-fix)
  • pnpm test src/main/runtime/orca-runtime.test.ts (1213 passed) and src/main/runtime liveness + src/main/runtime/rpc suites (201 files, 1695 passed)
  • pnpm tc (all projects), oxlint + oxfmt --check on changed files (lint gate proven live with a canary)

@brennanb2025

Copy link
Copy Markdown
Contributor Author

Push verified: git ls-remote origin refs/heads/brennanb2025/haspty-null-demotion-r1 returns exactly 19705c64752680eea46e0336f29b7c0a169a2af4, matching the local HEAD of this PR. Pre-fix reproduction, consumer enumeration, and per-hunk ablation are documented in the PR body.

@coderabbitai

coderabbitai Bot commented Aug 28, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

Next included review available in 5 minutes.

View limit details

Limit details: You’ve used all 10 included reviews currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f253761b-51ca-47d6-8730-6b9e14e34842

📥 Commits

Reviewing files that changed from the base of the PR and between a41679f and 2fdd443.

📒 Files selected for processing (2)
  • src/main/runtime/orca-runtime.ts
  • src/main/runtime/terminal-list-stale-leaf-liveness.test.ts
📝 Walkthrough

Walkthrough

The change adds typed PTY presence verdicts for live, exited, and unverifiable states. Unanswerable probes record an unverifiable verdict instead of confirming absence. Live probes clear stale verdicts, while confirmed exited probes permit demotion. Tests cover terminal listing, worker dispatch, recovery, and inventory-listed PTYs.

Merge Risk: ⚪ Minimal · up to a4167

The change preserves unverifiable probe failures without false disconnection, while confirmed absence still clears uncertainty and demotes the terminal correctly. No actionable merge-blocking risk remains after normal checks and review.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 3 files. (1 skipped: 1… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: unanswerable hasPty probes must not be treated as confirmed PTY absence.
Description check ✅ Passed The description is detailed and relevant. It includes the ELI5 explanation, behavior changes, rationale, reliability contract, compatibility considerations, and verification results. It does not inclu…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description is detailed and relevant. It includes the ELI5 explanation, behavior changes, rationale, reliability contract, compatibility considerations, and verification results. It does not include an explicit Linked Issue reference, the required template headings and checklist, or the required Visual Proof section with N/A or attachments.

Full details: Docstring Coverage

Explanation

Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 3 files. (1 skipped: 1 too large.)

✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@brennanb2025

Copy link
Copy Markdown
Contributor Author

Independent adversarial review — 19705c6

Reviewed as sole reviewer; every author claim re-tested from scratch in a clean worktree at this exact SHA. Verdict: merge-ready. No P0/P1. Three P2 nits, none blocking. All CI checks green at review time.

Pre-fix repro (re-run, not taken on faith)

Reverted only src/main/runtime/orca-runtime.ts + src/shared/pty-liveness-verdict.ts to origin/main (4f14d6d) under the PR's test files: 3 failed / 9 passed, exactly as claimed — connected:false + no recorded verdict for the null-answer pane, and listAvailableWorkerTerminals returning [] for a live worker terminal on the real listTerminals path. The live hole was buildTerminalSummary's hasPty !== true: confirmed, null (probe could not be asked — hasPtyFromRuntimeController returns it on a failed provider lookup or probe-less provider, and never throws) read as proven absence.

Ablation (re-run individually; 12 tests each run)

Arm ablated Red Claimed Match
resolver null arm (null → exited) 3 3 ✓
markPtyLivenessUnverifiable arm 2 2 ✓
live-rescue forgetPtyLivenessVerdict arm 1 1 ✓
exited demotion arm (provenAbsent never set) 3 — incl. the pre-existing stale-leaf demotion test 3 ✓

The last row matters: the original demotion behavior (undefined/probe-less controller → inventory is authority → exited) is still pinned by main's own test, so this PR does not regress the stale-leaf fix. Recovery of stale doubt is double-covered: the inventory refresh (forgetPtyLivenessVerdict on every listed session) clears it when the pane reappears in the listing, and the live rescue clears it when only the per-id probe recovers; spawn/registration also forget.

Consumer enumeration (independently derived, then diffed)

No wire shape or type changed anywhere, so every consumer compiles unchanged — the review question is value semantics per consumer. My grep of every terminal.list/listTerminals consumer and every verdict reader confirms all of the author's entries (coordinator filter fixed; CLI formatter truthful; resolveGroupAddress, plugin listWorktreeTerminals, topology/federation effect recorders, active-terminal fallback and renderer note-send all handle-only; remote-worktree-sleep unaffected; inspectWorkerTerminal/inspectRemoteAttachment check unverifiable before the connected===false → exited fallback; unverifiableStopVerdict consistent).

My list is a superset — 5 consumers the PR body does not enumerate, all verified unaffected:

  1. src/renderer/src/runtime/host-live-terminal-probe.ts — passes requireFreshPtyLiveness:true, and listTerminals drops inventory-missing leaves before buildTerminalSummary runs, so the changed value never reaches it.
  2. src/renderer/src/runtime/web-session-terminal-orphan-recovery.ts — same fresh-liveness exclusion, plus it filters orphaned === true (leaf summaries are always orphaned:false).
  3. src/renderer/src/lib/agent-hibernation-coordinator.ts — reads terminal.connected, but also fresh-liveness-gated; the changed panes are never listed for it. Fail-closed behavior unchanged.
  4. Mobile session screen terminal.list consumer + mobile-terminal-records.ts — membership/handle-driven (prune, subscriptions, budgets); no connected reads. List membership is unchanged by this PR.
  5. Close-receipt path stopExplicitlyClosedTabPtys → describeTerminalClose — handles unverifiable verdicts (shipped CLI renders ptyStopVerdict:'unverifiable'); see P2-1 below.

Wire claim (the risky part) — proven, not asserted

Checked at shipped tag v1.4.190, the realistic old client:

  • observation.status's union already includes 'unverifiable' with a producing branch in both orchestration-worker-observation.ts and orchestration-federation-control.ts; pty-liveness-verdict.ts shipped with the unverifiable arm; the CLI already formats ptyStopVerdict === 'unverifiable'. Old clients were compiled against exactly this vocabulary.
  • No renderer or mobile code consumes workerShow/federationShow at v1.4.190 (grep is empty); those surfaces are CLI/agent-facing JSON, and the spec text already documents unverifiable. I found no old-client branch that collapses not-live into absent on any surface that can now receive the new value.
  • The other changed publication is connected:true where the old host published a false connected:false — old clients read it exactly as any healthy pane; no reader can be broken by a truthful true.
  • Skew direction new-client/old-host: nothing new is required from the host; the old misreport simply persists until the host updates. Rule 3 review holds: value-level only, no capability gate needed.
  • Host-side status consumers were also checked for gating: worker-stop explicitly proceeds on unverifiable; release-completion branches only on identity_changed/missing/unattached and uses exited solely for the processAction label. No flow wedges on the new value.

Residual risk (confident-false sibling) — safe to leave open

The non-owning-provider confident-false window is real and reachable today: the degraded daemon provider answers hasPty from findProviderForExistingSession(id) !== null before discovery completes, and a plain local provider answers ptyProcesses.has(id) for ids it doesn't own. This PR does not make it more reachable: the false → demote arm is byte-for-byte the same decision pre- and post-fix (!== true already demoted on false), the PR only narrows the demotion set (removes null), and a wrong false demotion is per-listing, not sticky — rememberPtyLivenessVerdict deletes on exited, so the next refresh in which the owning adapter answers heals it (live rescue + forget). Deferring it matches the sibling-site split in #16900/#16908/#16926.

Task-spec correction — verified

src/main/runtime/orchestration-worker-observation.ts and federation-control.ts do not exist; the real files are src/main/runtime/rpc/methods/orchestration-worker-observation.ts and .../orchestration-federation-control.ts, and both were already verdict-guarded at v1.4.190 with unverifiable checked before the connected === false → exited fallback. The "already guarded" claim holds; no hole remains there.

Performance (by hand; the perf skill is disable-model-invocation for workers)

Inventory-hit path short-circuits before the probe (pinned by the "never consults" test) — zero added work on the hot path. Missed-pane path: same single sync hasPty call as before plus O(1) map writes; the verdict map is capped at 256 with orphan-only eviction (worst-case eviction scan is O(256), on the already-cold missed-pane path). No new timers, polling, subprocesses, or unbounded state. Repeated re-marking on every listing for a persistently-null pane is a delete+reinsert on a small map — negligible, and it keeps observedAt fresh for the sweep's staleness check.

P2 nits (none blocking)

  1. Close-receipt reason precedence — stopExplicitlyClosedTabPtys (orca-runtime.ts:30551) only overwrites the verdict when !verdict || verdict.status === 'live'. A pane carrying the new NO_OBSERVING_PROVIDER_REASON doubt that then fails a stop keeps the generic reason instead of the more specific "a follow-up stop was issued but its outcome could not be verified". Both are honest unverifiable; cosmetic only.
  2. Duplicated mapping — the record-level sweep (orca-runtime.ts:33768–33777) hand-rolls the identical true/false/null policy the new resolveUnlistedPtyPresence encodes. From scratch, both sites would share the resolver. Worth a follow-up, not a blocker.
  3. Ceremonial gate at the call site — isConfirmedPtyAbsence(unlistedPresence) inside case 'exited' is tautological at runtime (the switch already narrowed it). Its value is purely that the ConfirmedPtyPresence parameter type refuses the doubt arm under future refactors; fine, but the gate is documentation more than enforcement here.

Also noted, by design rather than defect: between the blip and the next inventory refresh, workerShow/federationShow report unverifiable where pre-fix they reported live (the sticky verdict is new; showTerminal never demoted). That is the honest answer under the execution-boundary contract and gates no control flow.

Checklist sweep

SSH/remote: verdict vocabulary and rule 2 followed exactly; SSH/remote: ids remain excluded from the local demotion gate. Crash/cast: no casts, total resolver, exhaustive switch, capped map. Security/supply chain: no deps, no shell, no I/O. Backcompat/data loss: in-memory state only, no persisted schema; no mobile-facing surface shape touched (value-only, verified above). Cross-platform: pure TS, no platform branches needed; folder workspaces unaffected (worktreeId-agnostic). Code organization: new types live with the incumbent verdict vocabulary in src/shared/pty-liveness-verdict.ts — correct home.

Merge-ready. CI fully green. Never merged/approved/closed by this review, per task.

…bsence

A null hasPty answer means the per-id presence query could not be asked
(failed provider lookup, probe-less provider behind the adapter). The list
summary's proven-absence rescue treated any non-true answer as confirmation,
so a live worker pane that missed one inventory snapshot while its probe was
unanswerable published connected:false — and orchestration wrote the worker
off as exited.

The controller's answer now resolves through an exhaustive
live/unverifiable/exited presence observation: only an observed false (or a
controller with no per-id probe, where the successful inventory stays the
authority) demotes; null records an unverifiable liveness verdict instead,
and a later live observation clears the recorded doubt. The typed gate
isConfirmedPtyAbsence does not accept the unverifiable arm.
…es live

The unlisted-pane rescue cleared the liveness verdict on any `live` answer.
For a leaf already marked disconnected by an unverified stop that published
`connected:false` with no verdict on record — the exact pair worker
observation and federation control read as a confirmed exit.

Clear the verdict only while the leaf still publishes as connected.
@brennanb2025
brennanb2025 force-pushed the brennanb2025/haspty-null-demotion-r1 branch from 19705c6 to a41679f Compare August 28, 2026 12:31
@coderabbitai

coderabbitai Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@brennanb2025

Copy link
Copy Markdown
Contributor Author

Review loop — patched, not superseded

Rebased onto current origin/main (94e7586665) and reviewed. The core change is right and I kept it: null from the per-id hasPty rescue means the probe could not be asked, and reading that as proven absence is the bug. null is genuinely reachable in production — hasPtyFromRuntimeController (src/main/ipc/pty/runtime/operations.ts:155) returns it when the provider lookup throws or the provider exposes no per-id probe — and the call is in-process, so no IPC coercion flattens it before it arrives.

One defect found and fixed (a41679f13f)

The live arm cleared the liveness verdict unconditionally. That is safe for a healthy pane, but a leaf can be connected:false while it still holds its ptyId:

  • orca-runtime.ts:16140-16143 — the exit handler forgets the verdict only on exitCode >= 0 || hostExitConfirmed. The synthetic -1 from a failed/unverified stop deliberately keeps the unverifiable verdict.
  • orca-runtime.ts:16163-16166 — that same exit sets leaf.connected = false while the leaf retains its ptyId.
  • orca-runtime.ts:30552,30565 — markPtyLivenessUnverifiable is recorded for any ptyId, local included.
  • orca-runtime.ts:33764 — the incumbent rescue loop is gated on !leafExistsForPty(...), so it skips leaf-backed panes. buildTerminalSummary is the only rescue covering them.

Erasing the verdict there published connected:false with no verdict on record — and that is exactly the pair orchestration-worker-observation.ts and orchestration-federation-control.ts read as 'exited'. So a PTY that survived an unverified stop went from unverifiable (pre-PR) to exited (post-PR): a fabricated death certificate, the class this change exists to remove.

The fix clears the verdict only while the leaf still publishes as connected. Normal panes are unaffected (leaf.connected = ptyId !== null), so the PR's own stale-doubt-clearing behaviour is preserved.

I deliberately did not mirror the incumbent at :33785-33787 by promoting connected = true instead — degraded-daemon-pty-provider.ts:92-95 returns mapped.hasPty?.(id) ?? true, an optimistic default rather than an observation, and promoting on that would assert life without evidence.

Evidence

Regression proven in an isolated worktree, both directions:

tree probe
pre-PR origin/main PASS — verdict survives, consumer reads unverifiable
PR head 19705c6475 FAIL — connected:false + verdict erased → consumer reads exited
PR head + fix PASS

New test keeps recorded doubt for a disconnected leaf the presence query answers live is red against the unfixed head and green with the fix.

Gate ablation table (each gate reverted individually):

ablation result
null → unverifiable arm removed RED (3)
markPtyLivenessUnverifiable removed RED (2)
forgetPtyLivenessVerdict removed RED (1)
hasPtyAnswer === true → live arm removed RED (2)
isConfirmedPtyAbsence(...) → true GREEN — see note

No two gates are only jointly pinned; every load-bearing gate goes red on its own.

Gates: pnpm tc exit 0, oxlint clean on all 4 files, git diff --check clean, PR suites 13/13, plus 9 related liveness suites 94/94.

Does an unanswerable probe still reach a caller as a positive absence?

No. null only originates at the runtime-controller adapter and the pty:hasPty IPC handler — provider-level hasPty is strict boolean (pty-provider-contract.ts:139, ssh-pty-provider.ts:295, local-pty-provider.ts:1098), so the !hasPty(...) sites in write-input.ts:181 and ssh-relay-session.ts:1953 can never see it. Of the two controller-level consumers, the incumbent sweep at :33775 was already tri-state (covered by pty-inventory-liveness-verdict.test.ts), and buildTerminalSummary is this PR plus the fix above. On the renderer side shouldReconcileMissingSession returns early unless isLive === false, so null never tears a pane down.

Notes, not blockers

  • isConfirmedPtyAbsence is a compile-time guard, not a runtime gate. Its only call site is inside case 'exited':, where the switch has already narrowed the value, so it can only ever return true — which is why substituting true stays green. That is structural, not a missing test, but the docstring calling it a "typed demotion gate" reads as though it has runtime force.
  • Second tri-state resolution in the same file. orca-runtime.ts:33775-33799 already resolves the same three-way hasPty answer for leafless PTYs, with the same NO_OBSERVING_PROVIDER_REASON constant. The two populations are disjoint (leafExistsForPty), so there is no double probe, but they now disagree on undefined and could drift.
  • resolveUnlistedPtyPresence folds undefined into exited. That preserves pre-fix !== true semantics so it is not a weakening, but the exported signature accepts boolean | null | undefined, and a future caller whose undefined means "not asked" would silently get a death certificate.

Composition with #16953

They compose, and they are not mutually redundant — reverting either leaves the bug live:

That is a mechanistic confirmation of the same-release constraint. No file overlap; git merge-tree origin/main HEAD exits 0.

Two things for #16953's own lane, not this PR: it is based on a stale 4bb337741c and currently conflicts with origin/main in src/main/ipc/pty/ipc/inspect.ts, so it needs a gh pr update-branch. And both PRs stub hasPty directly on the controller, bypassing hasPtyFromRuntimeController — so the producer/consumer seam the two jointly depend on is untested by either.

Not verified

No Electron/CDP run (this change has no rendered surface), nothing on Windows or a real SSH host, and no packaged-build check. The cross-version wire harness covers the terminal stream only, so the connected/writable publication-timing change has no automated old-client coverage — the reasoning above is the only check on it. Behaviour there moves in the safe direction (strictly fewer false connected:false), so no capability gate is needed.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 29f0ecea-e30a-43cc-9890-fee4ebb2ab0b

📥 Commits

Reviewing files that changed from the base of the PR and between 94e7586 and a41679f.

📒 Files selected for processing (4)
  • src/main/runtime/orca-runtime.ts
  • src/main/runtime/orchestration/coordinator-task-dispatch.test.ts
  • src/main/runtime/terminal-list-stale-leaf-liveness.test.ts
  • src/shared/pty-liveness-verdict.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/shared/pty-liveness-verdict.ts
  • src/main/runtime/orca-runtime.ts
  • src/main/runtime/orchestration/coordinator-task-dispatch.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 2 remain after this review.

…absent

The exited arm set provenAbsent but left any verdict an earlier unanswerable
probe had recorded, so a null-then-false transition published connected:false
while getPtyLivenessVerdict still reported unverifiable — under-reporting a pane
the probe positively answered about.

The live arm's asymmetry is deliberate and unchanged: it clears doubt only while
the leaf still publishes connected, because dropping a verdict under
connected:false is what worker observation reads as a confirmed exit. Here that
reading is the correct one.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant