Skip to content

feat(ssh): batch process evidence in PTY inventory - #17525

Merged
brennanb2025 merged 3 commits into
mainfrom
brennanb2025/r1-build
Aug 31, 2026
Merged

brennanb2025 merged 3 commits into
mainfrom
brennanb2025/r1-build

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Aug 31, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 5 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​260 $\color{#cf222e}{\Huge{\mathbf{−}}}$​1 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​259
Prod 13 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​516 $\color{#cf222e}{\Huge{\mathbf{−}}}$​59 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​457

Summary

  • Extend POSIX process-table captures with pgid/tpgid and add a strict parser that treats malformed or incomplete captures as unreadable.
  • Build one host-wide process index and correlate all managed PTYs in linear time, using terminal foreground-group association for agent evidence.
  • Add optional, validated foreground evidence to the existing pty.listProcesses inventory frame while preserving legacy fields and renderer gates.

Tests

  • Focused Vitest suites (25 tests): strict parser, sentinel and failure taxonomy, batched correlation, 1/50/200-pane counters, and evidence admission.
  • Existing process-table, foreground-process, relay inventory, SSH mapping, and admission suites (82 tests) pass.
  • tsc --noEmit -p config/tsconfig.node.json passes.
  • Oxlint passes on all changed files.
  • git diff --check passes.
  • Red proof: temporarily added the naive per-pane full-table scan; the 1/50/200-pane scan-volume gate failed (row visits grew from 2/100/400 to 3/2600/40400), then restored the indexed implementation and the gate passed.
  • Live SSH relay/electron validation remains for the coordinator's integration pass; this change is additive and does not open renderer gates.

@greptile-apps

greptile-apps Bot commented Aug 31, 2026 •

Copy link
Copy Markdown

Greptile Summary

The PR adds batched POSIX process-table correlation and carries validated foreground-process evidence from SSH relay PTY inventory into the renderer.

  • Extends process snapshots with process-group and terminal foreground-group identifiers.
  • Builds one host-wide index to correlate all managed PTYs without per-pane table scans.
  • Adds optional evidence admission, transport, and renderer monitoring while preserving legacy inventory fields.
  • Updates the strict parser to accept valid Linux kernel rows with pgid=0.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
src/shared/process-table-snapshot.ts Adds strict process-table parsing and indexing; the prior rejection of valid zero PGIDs is corrected with matching coverage.
src/main/providers/agent-foreground-process-batch.ts Correlates PTY roots and foreground process groups from a shared process-table index.
src/relay/pty-handler.ts Captures one POSIX process table per inventory request and attaches additive foreground evidence to PTY summaries.
src/main/providers/pty-process-list-admission.ts Validates, accounts for, and clones optional foreground-process evidence at the provider boundary.
src/renderer/src/components/terminal-pane/agent-completion-process-monitor.ts Integrates admitted host foreground evidence into terminal agent process monitoring.

Sequence Diagram

sequenceDiagram
    participant Renderer
    participant Main as Main Process
    participant Relay as SSH Relay
    participant PS as POSIX Process Table
    Renderer->>Main: Request PTY inventory
    Main->>Relay: pty.listProcesses
    Relay->>PS: Capture one host-wide snapshot
    PS-->>Relay: pid/ppid/pgid/tpgid/stat/command rows
    Relay->>Relay: Strictly parse and build process index
    Relay->>Relay: Correlate each PTY with foreground group
    Relay-->>Main: Inventory with optional foreground evidence
    Main->>Main: Validate and clone evidence
    Main-->>Renderer: Admitted PTY inventory
    Renderer->>Renderer: Update process monitor
Loading

Reviews (3): Last reviewed commit: "fix(ssh): preserve process evidence poll..." | Re-trigger Greptile

Comment thread src/shared/process-table-snapshot.ts Resolved
@coderabbitai

coderabbitai Bot commented Aug 31, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The change adds strict process-table parsing with process-group indexes and snapshot APIs. It adds batched foreground-agent resolution with explicit unavailable reasons and evidence conversion. It defines validated foreground-process evidence and preserves it during PTY process admission. POSIX PTY listings now capture one process-table snapshot, resolve entries in a batch, and attach evidence metadata. The renderer now controls process polling by host and recent pane activity.

Merge Risk: 🔵 Low · up to bf758

The PR adds foreground-process evidence to PTY inventory, but a correlation failure can currently lose the existing process-resolution fallback, and callers reaching the relay route may receive recognized agent-activity metadata without an explicit authorization check. The change is mergeable with owner awareness and follow-up on these bounded correctness and disclosure risks.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description includes a useful summary and testing section, but it omits most required template sections, including ELI5, What Changed, Why, Linked Issue, Visual Proof, AI Disclosure, Review, Notes… Complete the required template sections. Add a linked issue using Fixes #..., provide visual proof or state N/A with a reason, document manual and platform testing, complete the AI Disclosure and checklist sections, and record the pendi…
Docstring Coverage ⚠️ Warning Docstring coverage is 29.63% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 27 functions across 17 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the primary change: batching process evidence for PTY inventory in the SSH path.
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 includes a useful summary and testing section, but it omits most required template sections, including ELI5, What Changed, Why, Linked Issue, Visual Proof, AI Disclosure, Review, Notes, and Checklist.

Resolution

Complete the required template sections. Add a linked issue using Fixes #..., provide visual proof or state N/A with a reason, document manual and platform testing, complete the AI Disclosure and checklist sections, and record the pending live SSH validation.

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • 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.

@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

🧹 Nitpick comments (3)
src/shared/process-table-snapshot.ts (1)

53-55: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the unreachable fallbacks and the cast in parseProcessTableRows.

Groups 5 and 6 are mandatory in the pattern, so match[5] and match[6] are always defined on a successful match. ?? match[3] and ?? match[4] never run. The as ProcessTableRow cast is what hides this from the type checker.

♻️ Proposed simplification
-      stat: match[5] ?? match[3],
-      command: match[6] ?? match[4]
-    } as ProcessTableRow)
+      stat: match[5],
+      command: match[6]
+    })
src/main/providers/agent-foreground-process-batch.ts (1)

129-134: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

One lookup-counting helper is defined twice. lookupIndex and the exported lookupProcessTableIndex have identical bodies, so the two copies can drift on how lookups are counted.

  • src/main/providers/agent-foreground-process-batch.ts#L129-L134: delete lookupIndex and import lookupProcessTableIndex from ../../shared/process-table-snapshot.
  • src/shared/process-table-snapshot.ts#L163-L172: keep this helper as the single definition. If no other caller needs it exported, also drop the unused parseProcessTableRowsStrict alias at Line 111 in the same pass.
src/relay/pty-shell-utils.ts (1)

244-244: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Accept readonly ProcessTableRow[] to avoid a per-pane copy of the whole process table.

The mutable parameter type forces the caller to clone. src/relay/pty-handler.ts:2290 calls this function with [...evidenceRows] inside the per-entry loop, so a listing with 200 panes copies the entire host process table 200 times. The function only reads rows.

♻️ Proposed signature change
 export function getForegroundProcessNameFromProcessTable(
-  rows: ProcessTableRow[],
+  rows: readonly ProcessTableRow[],
   pid: number,
   fallbackProcess?: string | null
 ): string | null {

collectDescendants needs the same widening:

 function collectDescendants(
-  rows: ProcessTableRow[],
+  rows: readonly ProcessTableRow[],
   rootPid: number
 ): (ProcessTableRow & { depth: number })[] {

Then drop the spread at the call site in src/relay/pty-handler.ts:

-              [...evidenceRows],
+              evidenceRows,

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d151269e-398d-4efa-9cc9-5dbbc55f299a

📥 Commits

Reviewing files that changed from the base of the PR and between a4bf9bb and 1ac1ab4.

📒 Files selected for processing (10)
  • src/main/providers/agent-foreground-process-batch.test.ts
  • src/main/providers/agent-foreground-process-batch.ts
  • src/main/providers/agent-foreground-process.ts
  • src/main/providers/pty-process-info.ts
  • src/main/providers/pty-process-list-admission.test.ts
  • src/main/providers/pty-process-list-admission.ts
  • src/relay/pty-handler.ts
  • src/relay/pty-shell-utils.ts
  • src/shared/foreground-process-evidence.ts
  • src/shared/process-table-snapshot.ts

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

Comment thread src/shared/process-table-snapshot.ts Resolved

@pullfrog pullfrog 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.

Caution

parseStrictProcessTableRows rejects pgid <= 0, but every real Linux ps -axo … pgid=,tpgid=… capture contains kernel threads with pgid=0, so the strict evidence snapshot throws on every scan. The feature never produces live evidence in production — see the inline comment for details.

Reviewed changes

  • Strict evidence capture — PS_ARGS gains pgid/tpgid columns and a new parseStrictProcessTableRows treats any malformed row as an unreadable capture, backed by a single-pass buildProcessTableIndex.
  • Batched correlation — resolveAgentForegroundProcessesBatch/…FromIndex walk one host-wide index once and resolve foreground agents for all managed PTYs via pgid === tpgid association.
  • Relay inventory wiring — PtyHandler.listProcesses captures one strict snapshot per listing (POSIX only) and attaches optional foregroundProcessEvidence to each summary, while Windows keeps the legacy title/liveness path.
  • Admission validation — PtyProcessListAdmission validates, clones, and byte-budgets the new foregroundProcessEvidence field.
  • Refactor — getForegroundProcessNameFromProcessTable is extracted from the relay shell utils for reuse against the shared snapshot.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

Comment thread src/shared/process-table-snapshot.ts Resolved
Comment thread src/relay/pty-handler.ts Resolved
const children = childrenByPpid.get(row.ppid) ?? []
children.push(row)
childrenByPpid.set(row.ppid, children)
if (row.pgid !== undefined) {

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.

byPgid and byTpgid are built on every capture but never read — resolveAgentForegroundProcessesFromIndex filters rowsByOwner (descendants) by row.pgid === root.tpgid instead. That also misses a foreground process that was reparented away from the shell (parent exited while the PTY survives), which byTpgid would find. Either consume byTpgid for the foreground-group association or drop both unused maps.

Comment thread src/relay/pty-handler.ts
{
authorityGeneration: this.ptyIdMintEpoch,
observationEpoch: evidenceEpoch,
capturedAgeMs: 0

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.

capturedAgeMs is hardcoded to 0, but the field's contract ("receivers rebase this onto their monotonic clock") implies a real measured age. The strict reader already tracks capturedAtMs internally — expose it and populate this field, or drop capturedAgeMs until it is actually measured.

@pullfrog

pullfrog Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

the model provider had a temporary upstream failure.

The provider refused or dropped the request mid-run — nothing in your repo or your credentials is at fault. Re-trigger Pullfrog; if it keeps happening, check the provider's status page.

provider error: {"code":504,"message":"Upstream idle timeout exceeded","metadata":{"error_type":"timeout"}}

Pullfrog  | Rerun failed job ➔ | View workflow run | via Pullfrog | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

@brennanb2025

Copy link
Copy Markdown
Contributor Author

PR #17525 Electron visual proof — PTY/process inventory

PR: #17525
Branch: brennanb2025/r1-build @ d9f7c9cee0
Worktree: /Users/brennanbenson/orca/workspaces/orca/r1-build
Date: 2026-08-31

No source files were modified.

Identity

Launched this exact worktree via config/scripts/run-electron-vite-dev.mjs with isolated ORCA_DEV_USER_DATA_PATH, CDP 9338, renderer 5178 (5173 was already held by another worktree).

window.api.app.getIdentity():

{
  "name": "Orca: brennanb2025/r1-build",
  "isDev": true,
  "devLabel": "r1-build",
  "devBranch": "brennanb2025/r1-build",
  "devWorktreeName": "r1-build",
  "devRepoRoot": "/Users/brennanbenson/orca/workspaces/orca/r1-build",
  "dockBadgeLabel": null
}

Launch log: [orca-dev] Instance: r1-build and [orca-dev] Remote debugging on http://127.0.0.1:9338.

macOS Dock tile names included Orca/ brennanb2025-r1-build. Document title remained Orca (no badge). CDP page URL was http://127.0.0.1:5178/.

Scenario exercised

Isolated fresh profile (no imported user sessions).

  1. Empty onboarding with Resource Manager showing 0 terminal sessions.
  2. Added local git repo /Users/brennanbenson/orca/orca via window.api.repos.add (bypassed native folder picker). Activated main worktree (…/orca/orca on main).
  3. Created a terminal tab via store createTab. PTY spawned.
  4. Wrote a distinctive foreground command into the PTY:
    printf "ORCA_INVENTORY_PROBE\n"; exec -a orca-inventory-probe sleep 3600
  5. Opened Resource Manager from the status bar and inspected the live session row.

SSH/relay inventory was not reachable in this isolated profile (no SSH target configured). That is the PR’s stated remaining live-validation gap.

Visible evidence

1. Empty inventory (0 sessions)

01-empty-onboarding.png

  • Center: “Add a project to get started.”
  • Status bar Resource Manager: Off · 980.3 MB · 0.
  • Accessibility name: Resource Manager, 0 terminal sessions.

2. Terminal pane with live PTY + probe command

02-terminal-with-session.png

  • Tab Terminal 1 on worktree main / primary.
  • Visible command and output:
    • brennanbenson ~/orca/orca [main] $ printf "ORCA_INVENTORY_PROBE\n"; exec -a orca-inventory-probe sleep 3600
    • ORCA_INVENTORY_PROBE
  • Status bar Resource Manager count flipped to 1.
  • Sidebar: Hiding 579 discovered worktrees (only main kept visible in this profile).

3. Resource Manager inventory popover

03-resource-manager.png

  • Dialog title Resource Manager.
  • Header 0.3% · 631.4 MB Σ RSS.
  • Worktree main → bound session Terminal 1 (0.0% / 8.3 MB) with green live-bound dot.
  • App row ORCA 0.3% / 623.2 MB.
  • Kill affordance present on the session (Kill session <ptyId>).
  • Status bar after open: 631.4 MB · 1.

Accessibility snapshot of the session row:

Terminal 1 0.0% 8.3 MB Kill session 81971d5c-d099-4fc6-9562-87567ff26a05::/Users/brennanbenson/orca/orca@@188d3ddc

The Resource Manager row label is the tab title Terminal 1. It does not show foreground process name (orca-inventory-probe / sleep). That matches the PR claim that optional foreground evidence is additive and does not open renderer gates.

Local screenshots also live at:

  • .playwright-cli/proof-17525/01-empty-onboarding.png
  • .playwright-cli/proof-17525/02-terminal-with-session.png
  • .playwright-cli/proof-17525/03-resource-manager.png

Backing state

PTY id: 81971d5c-d099-4fc6-9562-87567ff26a05::/Users/brennanbenson/orca/orca@@188d3ddc

window.api.pty.listSessions():

[{
  "id": "81971d5c-d099-4fc6-9562-87567ff26a05::/Users/brennanbenson/orca/orca@@188d3ddc",
  "cwd": "/Users/brennanbenson/orca/orca",
  "title": "shell",
  "agentOwnership": "absent"
}]

window.api.pty.management.listSessions() (not degraded):

{
  "sessionId": "81971d5c-d099-4fc6-9562-87567ff26a05::/Users/brennanbenson/orca/orca@@188d3ddc",
  "incarnationId": "2abea51e-73b8-4916-8840-b82f9cc41f18",
  "state": "running",
  "shellState": "unsupported",
  "isAlive": true,
  "terminalHandle": "term_b420ee13-4b9f-42f5-80c7-f2f70f433dca",
  "wslDistro": null,
  "pid": 10999,
  "cols": 135,
  "rows": 60,
  "agentSessionOwners": [],
  "protocolVersion": 36
}

window.api.pty.inspectProcess / getForegroundProcess / confirmForegroundProcess:

{ "foregroundProcess": "login", "hasChildProcesses": true }

Host process evidence (outside the app):

  • PTY root pid 10999: /usr/bin/login -flpq brennanbenson … /bin/zsh -l on ttys692
  • Live probe: pgrep -lf orca-inventory-probe → 11430 orca-inventory-probe 3600

window.__store.getState().memorySnapshot matched the popover:

  • worktree session pid 10999, memory 8650752 (~8.3 MB)
  • app total memory ~795 MB RSS before popover; UI later showed 631.4 MB Σ RSS

PTY buffer snapshot (getMainBufferSnapshot, source headless) contained the probe command and ORCA_INVENTORY_PROBE output.

listSessions / management listings do not include foregroundProcessEvidence. That field is admitted on the pty.listProcesses inventory frame (SSH/relay), not on the renderer-facing pty:listSessions shape used by Resource Manager.

Local inspect reporting login (the macOS TCC login wrapper) rather than orca-inventory-probe is consistent with inspect walking the PTY root rather than the TTY foreground group. The PR’s TPGID-indexed batch evidence is on the SSH POSIX inventory path, which this run did not hit.

Logs

Launch log /tmp/orca-r1-build-electron-launch.log:

  • [orca-dev] Instance: r1-build
  • [orca-dev] Remote debugging on http://127.0.0.1:9338
  • [ws-transport] Failed to bind port 6769 … using an OS-assigned port (expected with many concurrent Orca Dev instances)
  • Keychain: userCanceledErr; [secrets] The OS keychain is unavailable, so secrets are stored unencrypted (isolated profile)
  • [claude-rate-limits] … status: 429 (unrelated)
  • [runtime-graph] reload revision=1/2 window=1 outcome=success
  • [pty:history:gc] Skipped: live worktree set is empty (before repo add)

Renderer CDP console: 0 errors, 2 warnings (no inventory-related failures observed).

Gaps

  • No live SSH/relay inventory. Isolated profile had no SSH target. The new host-wide PGID/TPGID batch evidence on pty.listProcesses was not observed on the wire or in the UI. The PR already flags this as remaining coordinator integration work.
  • No renderer surface for foreground evidence. Resource Manager and pty:listSessions still show tab title / shell, not foregroundProcessEvidence. Gates were not opened; visible inventory is session presence + CPU/RSS only.
  • Local inspectProcess named login, not the probe. macOS PTY root is /usr/bin/login; the actual foreground (orca-inventory-probe pid 11430) was confirmed only via host pgrep and the terminal buffer. This run did not prove the new batched TPGID correlator on a POSIX SSH host.
  • Did not exercise 50/200-pane inventory, malformed-table fail-closed behavior, or Linux kernel PGID-zero rows in the live app (those are covered by Vitest).
  • Did not connect a remote client / mixed-version relay.
  • Playwright comments overlay is visible in the lower-right of screenshots (CDP attach chrome); it is not product UI.
  • Folder-workspace path was not separately exercised (repo was a git checkout’s main worktree).
  • Gemini visual review was not used; screenshots were inspected directly.

This is not a merge-confidence claim for the SSH inventory change. It is visual proof that this worktree’s app boots, that local PTY session inventory is reachable in Resource Manager, and that foreground-process evidence is not shown in the current renderer.

@brennanb2025

Copy link
Copy Markdown
Contributor Author

Review status — land after fixes (PASS WITH RISK)

Reviewed the PR through the final pushed commit bf758b955e.

Fixes applied

  • Removed per-PTY process-tree rescans from relay inventory title generation; titles now reuse the batched correlation result.
  • Preserved legacy wrapper ambiguity/fallback behavior in batched foreground-process resolution.
  • Prevented hidden/background PTY output from re-arming process inspections when the pane is not visible.
  • Kept remote no-evidence polling enabled until the optional inventory evidence is actually consumed by the renderer, preserving mixed-version/older-relay behavior.
  • Added a regression test for hidden-pane activity rearming.

Verification

  • Focused process-table, batch-correlation, admission, and cadence suites: 44 tests passed (the review worker also reran the expanded set with 48 passing checks).
  • pnpm tc: passed.
  • Oxlint on changed files: passed.
  • git diff --check: passed.
  • Relay build: passed for supported targets.
  • Electron visual proof: exact brennanb2025/r1-build identity verified over CDP; local PTY was created and exercised through the visible terminal/Resource Manager UI, with screenshots attached in the preceding proof comment.

Remaining validation gap

Live SSH relay pty.listProcesses evidence and reconnect/network-failure testing were not completed: the Docker SSH fixture could not start because the local Docker daemon was unavailable, and the saved remote environment was unreachable. The local Electron proof therefore validates app startup and PTY inventory visibility, but not the new remote PGID/TPGID wire path.

No remaining proven P0/P1/P2 code issues were found. The worktree is clean, and the fixes are pushed to the PR branch.

@pullfrog pullfrog 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.

ℹ️ No critical issues — the strict-parser blocker from the prior review is resolved, and the delta is clean. One informational note on renderer wiring below.

Reviewed changes

  • Strict parser accepts kernel rows — parseStrictProcessTableRows now rejects only domain-invalid values (pid <= 0, ppid < 0, pgid < 0, tpgid < -1), accepting the pgid=0/tpgid=-1 kernel-thread rows that broke every real scan, pinned by a real-capture fixture.
  • Batched title reuse — the per-PTY title now reads the batched evidence result instead of rebuilding a per-pane descendant walk, removing the O(panes × table) copy the prior review flagged.
  • Wrapper-foreground alignment — the batch path now mirrors the legacy inspection filter (isExpectedAgentProcess(getFirstCommandToken(...))) and hands all descendants to resolveOuterWrapperForegroundProcess, so the outer-wrapper walk can see non-foreground ancestors.
  • Push-driven no-evidence polling option — a shouldPollNoEvidenceProcessCadence coordinator option, a null-init lastPaneActivityAt, and a hot-window re-arm were added with three focused tests.

ℹ️ The new no-evidence polling option is tested but not wired

shouldPollNoEvidenceProcessCadence is added to the coordinator API and exercised by three new tests, but no production caller sets it: terminal-keydown-fit.ts was reverted in bf758b9 to preserve existing polling semantics, and its comment now says the no-evidence cadence stays on "until inventory evidence is consumed by this renderer; mixed-version relays may omit the optional field." The result is that none of the new renderer coordinator behavior is reachable in production today — the new option, the hot-window re-arm branch, and the lastPaneActivityAt null-refactor are all inert (the latter is behavior-neutral). This looks consistent with the PR's stated "does not open renderer gates" scope, but it means the delta ships speculative plumbing plus tests for a path nothing activates; if the renderer evidence-consumption lands as a follow-up, consider moving the option and its tests with it.

Technical details
# No-evidence polling option is dead until a renderer consumes evidence

## Affected sites
- src/renderer/src/components/terminal-pane/agent-completion-coordinator-types.ts:46 — `shouldPollNoEvidenceProcessCadence` option.
- src/renderer/src/components/terminal-pane/agent-completion-process-monitor.ts:203-207 — the third/fourth `shouldRunCadenceInspection` clauses are only reachable when the option returns `false`.
- src/renderer/src/components/terminal-pane/pty-connection/terminal-keydown-fit.ts:230-242 — the only production coordinator site does not set the option; the comment records the deferred consumption.
- src/renderer/src/components/terminal-pane/agent-completion-no-evidence-cadence.test.ts — three tests exercise a configuration no production caller constructs.

## Open questions for the human
- Is the renderer evidence-consumption (disabling no-evidence polling when the relay publishes `foregroundProcessEvidence`) a separate PR? If so, does the option + tests belong there rather than here?

Pullfrog  | Fix it ➔ | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

@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: 86df83bb-928a-4e66-bd1c-a425924358fc

📥 Commits

Reviewing files that changed from the base of the PR and between d9f7c9c and bf758b9.

📒 Files selected for processing (6)
  • src/main/providers/agent-foreground-process-batch.ts
  • src/relay/pty-handler.ts
  • src/renderer/src/components/terminal-pane/agent-completion-no-evidence-cadence.test.ts
  • src/renderer/src/components/terminal-pane/agent-completion-process-monitor.ts
  • src/renderer/src/components/terminal-pane/pty-connection/terminal-keydown-fit.ts
  • src/shared/process-table-snapshot.ts

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

Comment thread src/relay/pty-handler.ts
const title =
(await getForegroundProcessName(managed.pty.pid, managed.pty.process || null)) || 'shell'
(evidenceRows
? (evidenceResults[entryIndex]?.processName ?? managed.pty.process ?? null)

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🔎 Supported by static analysis

🏁 Script executed:

printf '%s\n' '--- applicable repository guidance ---'
find /tmp/coderabbit-repo-knowledge/stablyai-orca-89dc44e4 -maxdepth 2 -type f -name '*.md' -print
printf '%s\n' '--- changed hunk ---'
git diff -- src/relay/pty-handler.ts | sed -n '/^@@/,$p' | head -240
printf '%s\n' '--- target context ---'
sed -n '2240,2320p' src/relay/pty-handler.ts

Repository: stablyai/orca

Length of output: 6747


🏁 Script executed:

for f in /tmp/coderabbit-repo-knowledge/stablyai-orca-89dc44e4/*/*.md; do
  case "$f" in
    */learnings/*|*/architecture/*) continue ;;
  esac
  printf '\n--- %s ---\n' "$f"
  head -160 "$f"
done

Repository: stablyai/orca

Length of output: 5356


🏁 Script executed:

printf '%s\n' '--- bound imports and definitions ---'
rg -n -C 5 'getForegroundProcessName|resolveAgentForegroundProcessesBatch|getStrictProcessTableSnapshot|evidenceRows|evidenceResults' src/relay/pty-handler.ts src/relay
printf '%s\n' '--- relay learnings ---'
cat /tmp/coderabbit-repo-knowledge/stablyai-orca-89dc44e4/learnings/src-relay.md

Repository: stablyai/orca

Length of output: 25564


🏁 Script executed:

printf '%s\n' '--- batch resolver implementation ---'
rg -n -C 12 'export async function resolveAgentForegroundProcessesBatch|function resolveAgentForegroundProcessesBatch' src/main/providers/agent-foreground-process.ts
printf '%s\n' '--- strict snapshot contract ---'
rg -n -C 10 'export async function getStrictProcessTableSnapshot|function getStrictProcessTableSnapshot' src/shared/process-table-snapshot.ts
printf '%s\n' '--- legacy foreground resolver ---'
sed -n '215,315p' src/relay/pty-shell-utils.ts

Repository: stablyai/orca

Length of output: 4677


🏁 Script executed:

rg -n -C 16 'resolveAgentForegroundProcessesBatch' src/main src/shared src/relay

Repository: stablyai/orca

Length of output: 16287


🏁 Script executed:

sed -n '1,125p' src/main/providers/agent-foreground-process-batch.ts
rg -n -C 12 'export function buildProcessTableIndex|function buildProcessTableIndex|export function resolveAgentForegroundProcessesFromIndex' src/shared/process-table-snapshot.ts src/main/providers/agent-foreground-process-batch.ts

Repository: stablyai/orca

Length of output: 9079


🏁 Script executed:

sed -n '125,235p' src/main/providers/agent-foreground-process-batch.ts
sed -n '140,190p' src/shared/process-table-snapshot.ts

Repository: stablyai/orca

Length of output: 2962


Publish process evidence only after both operations succeed.

If resolveAgentForegroundProcessesBatch rejects after getStrictProcessTableSnapshot() succeeds, the catch leaves evidenceRows populated and evidenceResults empty. The evidenceRows branch then skips getForegroundProcessName and uses only managed.pty.process, which loses the legacy process resolution. Keep both values local and publish them only after both operations succeed.

@brennanb2025

Copy link
Copy Markdown
Contributor Author

SSH/Electron validation update (HEAD bf758b955e):

  • Connected the real Electron build (Orca: brennanb2025/r1-build) to the real SSH host openclaw and remote repo /tmp/orca-pr17525-1788204100/demo-project.
  • Through the visible terminal UI, ran ps -axo pid=,ppid=,pgid=,tpgid=,stat=,command=, which returned live Linux process rows with PGID/TPGID, plus ORCA_REMOTE_OK.
  • Safe remote agent smoke checks passed: Claude 2.1.233 (Claude Code) and Codex codex-cli 0.151.0.
  • Launched a bounded foreground probe (exec -a orca-inventory-probe sleep 90), verified it remotely in the process table, then interrupted it and removed the temporary remote repo.
  • Visual proof: ssh-terminal.png

Readiness remains clean: focused 48-test suite, pnpm tc, changed-file lint, and git diff --check pass. No new P0/P1/P2 issues found. Remaining risk: Docker-backed relay/reconnect and network-failure drills were unavailable, so those paths remain unverified.

@brennanb2025
brennanb2025 merged commit 9477b5f into main Aug 31, 2026
30 of 33 checks passed
nwparker added a commit that referenced this pull request Aug 31, 2026
main is red on `static analysis`: oxlint's code-quality pass runs with
--deny-warnings, and agent-foreground-process-batch.test.ts imports
'../../shared/process-table-snapshot' twice (lines 5 and 13), tripping
"Modules should not be imported multiple times in the same file".

Introduced by #17525. It blocks every open PR, none of which can go green
until this lands.
nwparker added a commit that referenced this pull request Sep 1, 2026
…ntory path (#17763)

Follow-up defect fixes for the batched PTY-inventory evidence path (#17525),
now on main.

- One memoized `ps` capture serves both the lenient and strict views. The two
  readers ran byte-identical argv behind separate caches, so a relay serving
  both forked `ps` twice per 500ms window — the doubling issue #6288 removed.
- Drop the `byPgid`/`byTpgid` indexes no resolver reads, plus the zero-caller
  `parseProcessTableRowsStrict` and `getFreshStrictProcessTableSnapshot`; the
  batch resolver now reuses the shared index lookup and candidate score instead
  of private copies.
- Restore `getForegroundProcessName`'s ladder contract: the extracted table scan
  answers null again, so an unconfirmed wrapper fallback publishes the
  recognized (normalized) name rather than node-pty's raw one.
- Pin the SHIPPED `pty.listProcesses` path: one capture and one linear row pass
  for N panes, and node-pty's own name (never "shell") when the capture cannot
  disambiguate a `node`/`python` wrapper.
- Pin the hidden-pane cadence gate in the production option shape, and move the
  strict-parser coverage next to the parser it tests.
enrick-dev pushed a commit to enrick-dev/orca that referenced this pull request Oct 15, 2026
* feat(ssh): batch process evidence in PTY inventory

* fix(ssh): accept Linux kernel process rows and make no-evidence polling push-driven

* fix(ssh): preserve process evidence polling semantics

---------

Co-authored-by: Merge Sim <sim@local>
enrick-dev pushed a commit to enrick-dev/orca that referenced this pull request Oct 15, 2026
…7724)

main is red on `static analysis`: oxlint's code-quality pass runs with
--deny-warnings, and agent-foreground-process-batch.test.ts imports
'../../shared/process-table-snapshot' twice (lines 5 and 13), tripping
"Modules should not be imported multiple times in the same file".

Introduced by stablyai#17525. It blocks every open PR, none of which can go green
until this lands.
enrick-dev pushed a commit to enrick-dev/orca that referenced this pull request Oct 15, 2026
…ntory path (stablyai#17763)

Follow-up defect fixes for the batched PTY-inventory evidence path (stablyai#17525),
now on main.

- One memoized `ps` capture serves both the lenient and strict views. The two
  readers ran byte-identical argv behind separate caches, so a relay serving
  both forked `ps` twice per 500ms window — the doubling issue stablyai#6288 removed.
- Drop the `byPgid`/`byTpgid` indexes no resolver reads, plus the zero-caller
  `parseProcessTableRowsStrict` and `getFreshStrictProcessTableSnapshot`; the
  batch resolver now reuses the shared index lookup and candidate score instead
  of private copies.
- Restore `getForegroundProcessName`'s ladder contract: the extracted table scan
  answers null again, so an unconfirmed wrapper fallback publishes the
  recognized (normalized) name rather than node-pty's raw one.
- Pin the SHIPPED `pty.listProcesses` path: one capture and one linear row pass
  for N panes, and node-pty's own name (never "shell") when the capture cannot
  disambiguate a `node`/`python` wrapper.
- Pin the hidden-pane cadence gate in the production option shape, and move the
  strict-parser coverage next to the parser it tests.
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