Skip to content

feat(cli): orca serve stats [--json] — live headless-serve runtime stats - #24

Open
LesleyMurfin wants to merge 24 commits into
mainfrom
ai/serve-stats-json-10608
Open

LesleyMurfin wants to merge 24 commits into
mainfrom
ai/serve-stats-json-10608

Conversation

@LesleyMurfin

@LesleyMurfin LesleyMurfin commented Jul 25, 2026 •

Copy link
Copy Markdown
Owner
Files Added Deleted Net
Test 327 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​27301 $\color{#cf222e}{\Huge{\mathbf{−}}}$​5942 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​21359
Prod 485 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​21003 $\color{#cf222e}{\Huge{\mathbf{−}}}$​6627 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​14376

Summary

Adds orca serve stats [--json] — a first-class CLI command and serve.stats RPC that returns live factory occupancy from a running headless orca serve (agents, tasks, terminals, worktrees, version, uptime, post-bind WebSocket port), plus host load/memory pressure and event-loop health. Scripts and agents can query the runtime without scraping the UI or opening orchestration.db.

Closes stablyai#10608

Updates since this draft was last reviewed

Since the "Testing"/"AI Review Report" sections below were written (commit 348f368), three feature commits and two fix-ups landed — full detail in stablyai/orca#10612 (the upstream PR this fork branch feeds):

  • 50a836f9 — adds host.* (load average, CPU cores, memory total/available + source, swap) and health.eventLoopDelayP99Ms. This supersedes the "Host CPU/RAM metrics" non-goal below — it's now in scope and shipped.
  • 82bfc0ff — splits proven pty exits (terminalsExited) from unverifiable ones, and separates headless browser pages from client-hosted ones.
  • 2817d68e — keeps a proven pty exit recorded across inventory refresh.
  • a53803ba (current head) — clears servePort when a WebSocket-widen recovery also fails (open CodeRabbit finding on feat(cli): orca serve stats [--json] — live headless-serve runtime stats stablyai/orca#10612), plus an unrelated i18n catalog resync that fixes CI (en-runtime-required.json had drifted from en.json on an unrelated key, unrelated to this feature).

The JSON contract, non-goals, diff size, and commit reference further down are historical for 348f368; see stablyai/orca#10612 for the current contract and CI status.

Screenshots

No visual change.

User-visible change

orca serve stats
orca serve stats --json
orca serve stats --environment <name> --json   # honors remote/serve selection

Stable JSON contract:

{
  "version": "1.4.x",
  "uptimeSeconds": 1234,
  "port": 6768,
  "counts": {
    "agents": 0,
    "tasks": 0,
    "terminals": 0,
    "worktrees": 0
  }
}
  • port is the post-bind WebSocket port, or null when no WS listener is active.
  • counts.agents is currently live agents (StatsCollector), not lifetime spawned totals.
  • Human output mirrors other status-style CLI formatters.

Related

Implementation notes

  • CLI: serve stats registered under SERVE_COMMAND_SPECS next to bare serve; handler mirrors status (client.call + printResult).
  • Remote selection: only bare ['serve'] ignores remote env; serve stats honors --environment / pairing.
  • Runtime: getServeStats() aggregator; setServePort set from the RPC server after WS bind (optional-chained for remote runtime proxies, same pattern as activateRecentPtyPathCandidateTracking?.()).
  • RPC: serve.stats registered in the method registry with dispatch coverage.

Explicit non-goals

Testing

  • Targeted lint: oxlint on all touched files (0 warnings / 0 errors); pre-commit oxlint + oxfmt on commit
  • Targeted typecheck: tsc --noEmit for config/tsconfig.tc.cli.json and config/tsconfig.node.json
  • Targeted tests (would catch regressions for this surface):
    • src/main/runtime/serve-stats.test.ts
    • src/main/runtime/rpc/methods/serve-stats.test.ts
    • full src/main/runtime/runtime-rpc.test.ts (includes port-bind regression + runtime-proxy optional-chain path)
    • 63 tests passed on mtl-02 and on Lesleys-PC (WSL), Node 24
  • Full-repo pnpm lint / pnpm typecheck / pnpm test / pnpm build not run as a single gate in this session (scope limited to the serve-stats surface + registry suite above)
  • Added high-quality unit/RPC tests for aggregator counts, RPC dispatch, and post-bind port propagation

Live headless serve (PC factory — correct surface)

Target runtime (already running; not a desktop client):

Field Value
Host Lesleys-PC (WSL)
Unit orca-serve@factory.service
User svc_orca
Prefix /data/opt/revive/orca_serve
Port 6768 (default factory serve)
AppImage /data/opt/revive/orca_serve/share/orca-linux.AppImage → versioned store
User data /data/opt/revive/orca_serve/state/factory/config/orca

What we verified against that live factory:

  • Factory serve is up on :6768 (orca-serve@factory, AppImage serve --port 6768 …)
  • CLI as the factory identity reaches the live runtime (status → reachable)
  • Feature-branch CLI against the stock factory binary returns method_not_found: serve.stats (expected until the serve process runs a build that includes this PR)
  • Stock AppImage CLI reports Unknown command: serve stats (feature not in deployed binary yet)
  • End-to-end green path: deploy this build into factory (or canary) AppImage/serve-root, restart orca-serve@factory (or canary on 6771), then as svc_orca run orca serve stats --json against the live headless serve and confirm the JSON contract above

Not part of the plan: starting a second Electron “client” process, or asking upstream maintainers to run a manual smoke for us.

Commands run

pnpm exec vitest run --config config/vitest.config.ts \
  src/main/runtime/serve-stats.test.ts \
  src/main/runtime/rpc/methods/serve-stats.test.ts \
  src/main/runtime/runtime-rpc.test.ts
# → 3 files, 63 tests passed (mtl-02 + Lesleys-PC WSL)

pnpm exec oxlint <touched paths>
pnpm exec tsc --noEmit -p config/tsconfig.tc.cli.json
pnpm exec tsc --noEmit -p config/tsconfig.node.json

AI Review Report

Review focused on the serve-stats surface (CLI, RPC, runtime aggregator, remote-selection guard, port lifecycle).

Risk area What was checked Outcome
Cross-platform (macOS / Linux / Windows) CLI + main process only; no UI, shortcuts, or path hardcoding. Port/null covers unix-only and WS bind failure. OK for this surface
SSH / remote / local serve stats honors --environment / pairing; bare serve still ignores remote selection. setServePort?.() safe for partial remote runtime proxies. OK
Agents / integrations Read-only stats; no spawn or lifecycle side effects. JSON is a stable parseable contract for agents/MOPs. OK
Performance One-shot aggregator (in-memory leaves/agents + managed worktree list + in-process task list); no polling loop. OK
UI No visual change. N/A
Security See Security Audit below. OK

Changes from review: optional-chain setServePort for runtime proxies (matches existing activateRecentPtyPathCandidateTracking?.()); register CLI under SERVE_COMMAND_SPECS; keep port sourced from post-bind resolvedPort.

Security Audit

Topic Assessment
Auth / RPC Uses existing RuntimeClient + serve auth path; no new auth mechanism.
Input handling No free-form path/command input; --json only changes output encoding.
Secrets Read-only counts/version/uptime/port; does not return tokens, pairing secrets, or settings blobs.
Privilege Does not mutate settings, spawn processes, or open network listeners.
Command execution None.
Follow-up None required for this PR. (Related stablyai#10609 will need a separate allowlist/privilege review if it exposes PTY ownership/cleanup.)

Notes

  • Single topic: factory live-stats CLI/RPC only.
  • Deploy note for live e2e: factory and canary on Lesleys-PC run system units as svc_orca under /data/opt/revive/orca_serve (factory :6768, canary :6771). CLI extract noise from AppImage is expected when invoking orca under that prefix. Live green e2e requires swapping the serve AppImage/serve-root to a build that includes this PR, then restarting the unit — not replacing a user desktop client.
  • Diff size: 13 files, +257 / −4.

X handle

@LesleyMurfin

Provenance

  • Orca workspace: none — worktree created with git worktree from external/orca/fork (not via /orca launch)
  • Host (authoring): mtl-02-dev-001
  • Host (live factory serve checks): Lesleys-PC (WSL), orca-serve@factory as svc_orca
  • Worktree path: /data/projects/external/orca-wt/ai-serve-stats-json-10608
  • Branch: ai/serve-stats-json-10608
  • Commit: 348f368297455490141c1dc96ede28e5234a0d34

@coderabbitai

coderabbitai Bot commented Sep 7, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 53231997-8933-4dbd-ac09-2328ed1792de
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

LesleyMurfin and others added 16 commits September 11, 2026 00:28
Add a read-only CLI + serve.stats RPC that returns live factory occupancy
from a running runtime (agents, tasks, terminals, worktrees) plus version,
uptime, and the post-bind WebSocket port (or null).

- Register under SERVE_COMMAND_SPECS next to bare `serve`
- Honor --environment / pairing (only bare serve ignores remote selection)
- Wire setServePort from RPC server; optional-chain for runtime proxies
- Tests: aggregator, RPC registry dispatch, port-bind regression

Closes stablyai#10608
Add handler unit tests for serve.stats RPC dispatch, factory count
fields, null port rendered as "none", and JSON mode shape.
… ptys

Adds runtimeId plus counts.browserPages, counts.browserPagesRetained and
counts.terminalsUnverifiable to the (unshipped) serve.stats result.

Retained pages hold one of the runtime's 256 page slots with no TTL and no
reaper (stablyai#14552); the disconnected-pty count makes leaked ptys visible (stablyai#9819,
stablyai#9479) without claiming they exited; runtimeId distinguishes a same-generation
runtime from one that restarted underneath the caller (stablyai#9585).
serve.stats documents live current-state counts, but countTasks() counted
every row in the tasks table. Settled tasks persist until an explicit
orchestration reset, so the advertised task count grew monotonically.
Exclude completed/failed; keep blocked, which is resumable work.
stop() empties activeTransports/transports before stopping them, then
rethrew the first rejected stop before clearing the advertised port, so
serve stats kept reporting a dead port after a failed shutdown. Clear the
port unconditionally, then rethrow.
`serve stats` reported only scalars, so the histograms operators actually
needed were hand-tabulated from worker-list and task-list output (stablyai#13047,
stablyai#19388, stablyai#18737). Adds three fixed-key breakdowns to the same single walk:

- counts.tasksByStatus: one grouped scan (countTasksByStatus), every
  TaskStatus always present. Includes completed/failed, which counts.tasks
  excludes, so it deliberately does not sum to counts.tasks.
- counts.agentsByState: working/permission/idle/unknown. PTY-backed agents
  are bucketed from their own current-incarnation evidence (retained hook
  status, prompt lifecycle, live-observed title); structured sessions and
  ptys with no current evidence report `unknown`, because identity and
  liveness prove presence, not turn state (stablyai#19548).
- counts.workersByTerminalState: countWorkerTerminalInventory keyed by all
  six WorkerTerminalListState values, so reclaimable/release_unknown
  pileups are visible without worker-list.

TaskStatus and WorkerTerminalListState move to shared leaf modules so the
wire contract keys on the same unions the DB derives (shared cannot import
main); FleetTerminalState now aliases the latter instead of repeating it.
…tract change

Upstream createTask now requires a runId, and the serve-stats agent-state read is a new hook-row consumer the census has to pin.
…lay p99

serve stats could show every Orca-side count while the host itself was saturated: stablyai#14552 and stablyai#19312 both read as 'Reconnecting to remote runtime' network faults for days (loadavg 105-112, systemd reporting the unit healthy), and stablyai#12588's 60 GiB terminal child degraded SSH with no visible signal.

Adds host.{loadAverage1m,cpuCoreCount,memoryTotalBytes,memoryAvailableBytes,memoryAvailableSource,swapUsedBytes} under its own key (never inside counts, since these are host-wide and not Orca-attributed) and health.eventLoopDelayP99Ms. Unmeasurable fields are null and render n/a, never 0, so Windows' meaningless os.loadavg() zeros cannot read as an idle host. Linux prefers /proc/meminfo MemAvailable over os.freemem() and labels the source; every procfs read is guarded so a container without it yields null instead of failing the command.

The delay histogram is one long-lived monitorEventLoopDelay enabled with the RPC listener and reset on read, so each read reports the window since the previous one rather than a multi-day percentile that goes stale-flat.
`counts.browserPages` counted only RuntimeBrowserPageRegistry, which
`browserTabCreate` populates on the client-hosted branch alone. A headless
serve has no renderer, so `tab create` takes the offscreen branch and the page
was never published there — the field reported 0 for a live, listable,
agent-opened tab, which is exactly the population stablyai#14552 asked for. Count the
WebContents registration map the bridge reads as well, de-duplicated by page
id, and read it via `getRegisteredTabs` rather than `tabList` so a stats read
deregisters nothing. `browserPagesRetained` stays scoped to client-hosted
pages and now says so: an offscreen page has no separate host to lose.

`counts.terminalsUnverifiable` incremented on `connected === false`, but
`onPtyExit` clears `connected` while recording an `exited` liveness verdict
from a host-delivered exit code. Confirmed-dead ptys therefore landed in the
one field documented as carrying no evidence of exit and as not authorizing
cleanup. Split the bucket on that verdict: `terminalsExited` for a positive
death certificate, `terminalsUnverifiable` for absence of contact only, with
anything ambiguous staying on the conservative side.

`terminalsUnverifiable` narrows in meaning; `serve.stats` has not shipped in a
release, so no consumer contract breaks.
The liveness register documented an invariant it did not enforce: an earned
death certificate is kept, and nothing weaker than a host-delivered exit frame
may reach it. Both doubt writers ignored that. The controller-inventory sweep
deleted the entry for any id an answering provider disowned, and recorded
`unverifiable` for any id no provider could be asked about — so a host-delivered
exit only held between `onPtyExit` and the next `terminal list` / `worktree ps` /
`worktree rm`, after which `serve stats` reported the proven death as
`terminalsUnverifiable`, the field whose whole meaning is that cleanup is NOT
authorized.

Enforce it in the register rather than at the sweep's call sites: three writers
in that one sweep shared the bug, plus the stop-error path, and loss of contact
is never a retraction of positive evidence anywhere
(docs/reference/ssh-execution-boundary.md). Doubt stays exactly as clearable as
before.

Disposal is unaffected: retiring a pty or reusing its id deletes the entry
directly (onPtySpawned, registerPty, dropDisconnectedPtyRecord), `getServeStats`
counts from `ptysById` so a disposed pty contributes to neither counter, and the
register's orphan ratchet still bounds retained verdicts at 256.
If current.stop() rejects in widenWebSocketBind(), the servePort clear
on the next line never runs. When the loopback recovery in
recoverWebSocketBindAfterFailedWiden then also fails, wsBoundHost and
the transport are torn down but servePort stays stale, so serve stats
can report a port with nothing listening on it.

Also resyncs en-runtime-required.json: TerminalPane.minimumContrast.*
text had drifted from en.json after an unrelated upstream change,
failing the runtime-required-catalog test and static-analysis CI
checks. Regenerated via sync:localization-runtime-catalog; unrelated
to serve-stats itself.
…roup pids

Three resource-exhaustion signals `serve stats` could not answer, each null (never
0) wherever the platform cannot measure it:

- counts.browserPageMemoryTotalBytes / browserPageMemoryMaxBytes: resident set of
  the renderers behind counts.browserPages, de-duplicated by pid because Electron
  may back several pages with one renderer. stablyai#14552 was one 1.3 GB page among six,
  which a total alone hides, so the max ships beside it. One /proc/<pid>/status
  VmRSS read per pid — no subprocess, no `ps` sweep. Page counting moves into the
  same collector, since the bridge's page-id map is both the page population and
  the only handle a footprint read can start from.

- health.longPolls: active vs cap for the total, ask, browser-host and specialized
  admission pools. stablyai#19342 hit `runtime_busy` at loadavg 4.8 with 44 GB free and
  could only find the cap by unpacking app.asar. The counters and caps live on the
  RPC server, so it registers a reader with the runtime where it already sets the
  serve port — a pull, so nothing pushes on the long-poll hot path and the snapshot
  cannot lag the counters. Null when no listener is serving.

- host.pids: cgroup v2 pids.current / pids.max, resolved through /proc/self/cgroup
  and walked to the nearest enclosing cgroup with the pid controller enabled. A
  fixed /sys/fs/cgroup read only works inside a container: the kernel omits
  controller files from the root cgroup, and stablyai#18789's pids.max=4096 was a systemd
  unit limit. The literal `max` maps to null (unlimited), never to a number.

Verified live on a built headless serve: three offscreen pages reported
total=259588096 max=88240128, matching an independent /proc read of the three
renderer pids exactly; two held terminal.wait calls moved total.active 0 -> 2 -> 0
against caps 16/8/8/12; host.pids.max matched the unit cgroup's 16384 exactly,
with current tracking pids.current to within the measuring process's own tasks.
@svc-orca
svc-orca Bot force-pushed the ai/serve-stats-json-10608 branch from 52c0038 to 2776ecd Compare September 11, 2026 06:29
nwparker and others added 3 commits September 11, 2026 23:13
- Route webContents OS process ID lookup through RuntimeDesktopSurface to keep electron out of runtime modules.
- Extract serve stats collection logic to serve-stats-aggregation.ts, removing the max-lines bypass.
- Install fake AppEnvironment in serve-stats-lifecycle.test.ts.
@svc-orca

svc-orca Bot commented Oct 9, 2026

Copy link
Copy Markdown

Merge order: land after #21, and before #19

This is a merge-ordering note, not a review blocker. The coupling below is file adjacency and rebase churn only — it is not a functional dependency. This PR is correct and self-contained on its own: merging out of the suggested order produces a merge conflict someone has to resolve, not a broken build or a missing symbol.

Shared with #21 — 1 file:

Shared with #19 — 3 files:

  • src/main/runtime/rpc/methods/index.ts (both register new RPC methods in the same method table)
  • src/main/runtime/orca-runtime-pty-foreground-process-reads.ts
  • src/shared/rpc-contract/rpc-params-catalog.generated.ts

Correction to any earlier summary that listed only rpc/methods/index.ts: the overlap with #19 is three files, including the generated catalog.

⚠️ rpc-params-catalog.generated.ts is generated output — do not hand-edit

This PR regenerates src/shared/rpc-contract/rpc-params-catalog.generated.ts. #19 regenerates it too, and so will any future RPC-touching PR.

After any later RPC-touching merge, re-run the generator and commit its output. Do not hand-resolve or hand-edit the conflict in the generated file. Hand-editing it will silently drift the catalog away from the actual RPC method definitions, and the next regeneration will overwrite the manual fix anyway.

Suggested sequence: #21 → #24 → #19, regenerating the catalog on the merge that follows.

@svc-orca

svc-orca Bot commented Oct 14, 2026

Copy link
Copy Markdown

ACO structural triage (prompt_version=1.2-quick)

Workspace: factory fork feat-cli-orca-serve-stats-json-live-headless-ser
Local HEAD: f2dbea24b54 (ai/serve-stats-json-10608)
PR head: 0be235d0411 — diverged (local ahead 21 / behind 1173 vs origin/ai/serve-stats-json-10608)
Draft: yes
Graph: missing (.aco/graph.db absent) — non-AST / rg heuristic only
riley_kg: unavailable (no RILEY_KG_ROOT)

Scope (≤15 production targets)

Feature slice c8b3f2084fd...HEAD (serve-stats topic), not full status noise.

# File Role
1 src/cli/specs/serve.ts CLI contract notes
2 src/cli/handlers/core.ts serve stats handler
3 src/cli/format.ts human + JSON print path
4 src/main/runtime/rpc/methods/serve-stats.ts RPC serve.stats
5 src/main/runtime/serve-stats-aggregation.ts collector
6 src/main/runtime/serve-stats-host.ts host metrics
7 src/main/runtime/serve-stats-browser-pages.ts page/RSS
8 src/main/runtime/serve-stats-event-loop-delay.ts ELD p99
9 src/shared/runtime-session-contracts.ts RuntimeServeStatsResult
10 src/main/runtime/runtime-rpc/runtime-rpc-lifecycle.ts enable ELD + longPoll provider
11 src/main/runtime/runtime-rpc/runtime-rpc-request-admission.ts readLongPollStats
12 src/main/runtime/runtime-rpc/runtime-rpc-shutdown.ts / network-exposure port/provider clear
13 src/main/runtime/orchestration/db/tasks/task-store.ts countTasks*
14 src/main/runtime/orca-runtime-pty-foreground-process-reads.ts getServeStats surface
15 src/main/host/electron-runtime-desktop-surface.ts getWebContentsOSProcessId

Blast radius (rg, non-AST)

Symbol Direct callers (prod) Risk
collectRuntimeServeStats orca-runtime-pty-foreground-process-reads.getServeStats low fan-in
serve.stats / SERVE_STATS_METHODS RPC method index new wire method
formatServeStats CORE_HANDLERS['serve stats'] CLI only
enableServeStatsEventLoopDelayMonitor RuntimeRpcLifecycle.start process-wide timer
countTasks / countTasksByStatus aggregation + task-store stats-oriented semantics
setServePort / setLongPollStatsProvider lifecycle, shutdown, widen recovery stale-null correctness
getWebContentsOSProcessId browser-pages via desktop surface optional; inert → null

serve.stats is a short RPC (not in classifyRuntimeLongPoll) — does not consume long-poll slots. Auth still required (authToken).


Findings (sev-ordered)

P1 — Lifecycle unit test fails (structured native-chat fixture)

  • Evidence: pnpm test src/main/runtime/serve-stats-lifecycle.test.ts -t 'counts native live'
  • Error: TypeError: undefined is not an object (evaluating 'location.executionHostId')
  • Path: collectRuntimeServeStats → observeStructuredWorker → resolveLineageRunningSession → structuredWorkerHostScope(record.location)
  • Cause: test mock deps.store.getRecord returns partial lease without location (required on AgentSessionRecord). Fixture not fully updated after native-chat upstream.
  • Requested change: rebuild fixture with real location (+ lease fields the lineage path needs), matching HOST_TEST_LOCATION / origin-era richer mocks.

P1 — Local tip ≠ PR tip

  • Workspace f2dbea24b54 is not GitHub head 0be235d0411.
  • Requested change: rebase/push so PR head matches the tip under review before merge; do not merge draft on divergent local-only commits.

P1 — CLI help implies bare JSON; runtime emits RPC envelope

  • Notes (src/cli/specs/serve.ts): “JSON shape is a stable contract: version, runtimeId, …”
  • Code: printResult → JSON.stringify(prepareComputerCliJsonResult(response)) → top-level { id, ok, result, ... }; payload under result
  • Tests assert parsed.result.port (correct).
  • Requested change: rewrite notes to document envelope (jq '.result') so MOPs/scripts do not parse top-level fields and silently fail.

P2 — ELD monitor never disabled on RPC stop

  • Enabled in RuntimeRpcLifecycle.start; disable only via test helper.
  • Idempotent; 20ms standing timer for process life — acceptable if intentional; document residual for long-lived desktop after serve stop.

P2 — eventLoopDelayP99Ms reset-on-read

  • Concurrent readers split one window (documented). OK for operator CLI; bad if turned into multi-scrape target without changing semantics.

P2 — as unknown as runtime cast in aggregation → browser pages

  • serve-stats-aggregation.ts casts ServeStatsRuntime for collectServeStatsBrowserPages. Prefer a narrow shared pick-type.

Non-findings (checked)

  • No tokens/secrets in stats payload (counts/host/health only).
  • Headless: inert desktop surface returns null OS pid; no new show()/app.focus on stats path (Notification.show pre-existing).
  • servePort / longPollStatsProvider cleared on socket start fail, transport teardown, widen fail, shutdown.
  • null vs 0 discipline is consistent and documented.
  • Mixed-version: old runtime lacks serve.stats → standard method-missing (acceptable; notes say queries running runtime).

Verification run (this workspace)

PASS  serve-stats.test.ts, serve-stats-host.test.ts, serve-stats-browser-pages.test.ts
PASS  rpc/methods/serve-stats.test.ts + core.test.ts serve-stats cases (8)
FAIL  serve-stats-lifecycle.test.ts — 1 fail (native live sessions) / 33 other pass in batch

Requested-change checklist (P0/P1)

  • P1 Fix serve-stats-lifecycle structured-session fixture (location + valid lease) so suite is green
  • P1 Align PR head with reviewed tip (rebase/push; leave draft until green)
  • P1 Correct serve stats JSON contract notes to RPC envelope / .result
  • (optional P2) Null-guard structuredWorkerHostScope for corrupt records → unverifiable not throw
  • (optional P2) ELD disable-on-stop or document process-lifetime cost

Changes made by triage

None (review-only).

Residual risk

PR tip not identical to local evidence; graph absent; full monorepo behind-main noise ignored by design.

@svc-orca

svc-orca Bot commented Oct 14, 2026

Copy link
Copy Markdown

ACO triage follow-up — fixes applied (local workspace)

Applied on local tip f2dbea24b54 + uncommitted fix diffs (still diverged from PR head 0be235d0411 — push/rebase still required before merge).

Checklist from triage

Item Status
P1 lifecycle fixture + location null-guard Fixed
P1 JSON contract notes (.result envelope) Fixed
P1 PR tip alignment Open — needs rebase/push of this tip
P2 ELD disable on RPC stop Fixed
P2 drop as unknown as browser-pages cast Fixed
(extra) serve.stats missing permission → tsc fail Fixed (permission: 'workspace', same as stats.summary)

Files touched

  • src/main/runtime/serve-stats-lifecycle.test.ts — full agentSessionRecordFixture + location
  • src/main/runtime/structured-worker-identity.ts — structuredWorkerHostScope accepts nullish location
  • src/cli/specs/serve.ts — JSON notes document RPC envelope / .result
  • src/main/runtime/serve-stats-event-loop-delay.ts — prod disableServeStatsEventLoopDelayMonitor
  • src/main/runtime/runtime-rpc/runtime-rpc-shutdown.ts + runtime-rpc-lifecycle.ts — disable on stop/fail
  • src/main/runtime/serve-stats-host.test.ts — import rename
  • src/main/runtime/serve-stats-browser-pages.ts + serve-stats-aggregation.ts — narrow runtime type, no cast
  • src/main/runtime/rpc/methods/serve-stats.ts — permission: 'workspace'

Verification

pnpm tc:node                          # PASS
pnpm test serve-stats* + core + rpc-shutdown + long-poll-transport
  → 8 files / 64 tests PASS
pnpm test structured-worker*.test.ts  → 10 files / 122 tests PASS

Residual

  • Draft PR head still 0be235d; local has feature + these fixes unpushed.
  • Reset-on-read ELD concurrent-reader split left intentional (documented).

Disable the process-wide ELD histogram when RPC start fails or stop runs,
document the CLI --json RPC envelope/.result contract, require workspace
permission on serve.stats, drop the browser-pages unknown cast, and null-guard
structured worker host scope when location is missing.
selectFreshExplicitAgentStatus accepts a nullable handle after the main merge,
but the join API is Iterable<string>. Mirror the paneKey guard so a missing
handle becomes an empty list instead of a type error.
@svc-orca
svc-orca Bot marked this pull request as ready for review October 14, 2026 09:09
@svc-orca

svc-orca Bot commented Oct 14, 2026

Copy link
Copy Markdown

Recovery + ACO close-out

Local worktree had diverged (merge wreckage + unpushed ACO fixes). Reset to PR tip 0be235d, then landed three commits:

  1. dc3b85f — casting safety + lifecycle fixture for upstream native chat
  2. 79207df — ACO triage: ELD disable on stop/fail, --json envelope/.result notes, serve.stats permission: 'workspace', drop browser-pages as unknown as, null-guard structured worker location
  3. c39621c — nullable handle join filter (tsc after main merge)

Verification

  • pnpm tc:node PASS
  • pnpm tc:cli PASS
  • pnpm test serve-stats* + core + rpc-shutdown + row-selection + structured-worker + long-poll → 20 files / 202 tests PASS

PR tip now includes the ACO fixes; draft cleared.

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.

[Feature]: orca serve stats [--json] — live headless-serve runtime stats

2 participants