# Reduce idle work and disk churn with native resource diagnostics · PR \#2679 · pingdotgg/t3code

[View on GitCafe](https://git.cafe/pingdotgg/t3code/pull/2679)

Repository: [pingdotgg/t3code](https://git.cafe/pingdotgg/t3code)

Visibility: public

State: merged

Source repository: pingdotgg/t3code

Source branch: t3code/a55b49df

Target branch: main

Head commit: 6b8a5163be9bac7c3b8b73d8b59a0d7f4dc6ad48

[Discussion and reviews](https://git.cafe/pingdotgg/t3code/pull/2679)

[Commits](https://git.cafe/pingdotgg/t3code/pull/2679/commits?format=markdown)

[Files changed](https://git.cafe/pingdotgg/t3code/pull/2679/diffs?format=markdown)

## Description

---

## Intent

Reduce T3 Code's steady-state resource usage, bound local observability disk churn, **and** make CPU, memory, power-state, and I/O regressions observable enough to debug.

Before this PR:

- provider status refreshes, VCS remote refreshes, and other background work followed fixed schedules even when nobody needed the result;
- process diagnostics repeatedly spawned `ps` or PowerShell, adding process churn while still missing short-lived work between samples;
- macOS power state came from recurring shell probes;
- the diagnostics page could show sampled CPU and memory, but had no process I/O counters, collector health, Electron overhead, or application-level write attribution;
- native and canonical provider events used independent rotators against the same thread files, retained duplicate streaming deltas, and had no aggregate age or byte budget;
- high-frequency provider-log and preview debugger operations generated their own Effect trace records.

This PR replaces those paths with a demand-aware background policy plus a persistent, cross-platform telemetry pipeline.

## Runtime architecture

```text
Electron main
  ├─ powerMonitor events and state
  ├─ app.getAppMetrics()
  └─ NDJSON over inherited fd 4
                         ┐
                         ▼
Node server ── NDJSON stdio ── persistent Rust resource monitor
     │
     ├─ ResourceTelemetry Effect service
     ├─ bounded in-memory history and I/O attribution
     ├─ HostPowerMonitor → BackgroundPolicy
     └─ typed RPC/subscription → diagnostics UI
```

The native monitor is intentionally a **standalone executable**, not an N-API or FFI module. One persistent child process gives the server a supervised crash boundary, avoids Node/Electron ABI coupling, and eliminates recurring process-table subprocesses. The same protocol and binary layout work for desktop and the published CLI.

## What changed

### Demand-aware background work

- Adds an Effect `BackgroundPolicy` service that combines:
  - active client leases and requested scopes;
  - visibility, focus, recent interaction, app state, battery, and low-power hints;
  - host lock, suspend, battery, low-power, and thermal constraints;
  - balanced, performance, and battery-saver profiles with interval overrides.
- Clients retain scopes for the data they currently need, such as a repository's VCS status or a provider instance's status.
- Provider refreshes and VCS remote polling consult the policy instead of blindly running on fixed cadences.
- Settings and reporting flows expose the policy without coupling individual background services to renderer state.

### Native and Electron telemetry

- Adds `native/resource-monitor`, a Rust sidecar backed by OS APIs through `sysinfo`.
- Samples the server, all descendants, provider-spawned grandchildren such as `node`, `tsgo`, language servers and shells, Electron roots, Electron descendants, and the monitor itself.
- Reports process identity `(pid, startTimeMs)`, parent/child relationships, command line, CPU, cumulative CPU time, resident/virtual memory, cumulative I/O counters, and collection cost.
- Disables Linux task/thread enumeration and avoids repeatedly reloading command lines.
- Uses Electron `powerMonitor` and `app.getAppMetrics()` for battery/AC state, lock/idle, suspend/resume, thermal state, CPU speed limits, Electron CPU/memory, and idle wakeups.
- Sends Electron-main data directly to the server over fd 4. It does not route telemetry through the renderer WebSocket.

### Diagnostics, history, and safety

- Adds a schema-backed `ResourceTelemetry` service that merges native and Electron samples, computes rates from cumulative counters, classifies process groups, and publishes live snapshots.
- Adds bounded, in-memory history for CPU, memory, I/O, process lifecycle, and collector health. Telemetry is not persisted to disk.
- Expands diagnostics with:
  - backend, Electron, monitor, and total resource groups;
  - live process tree and process lifecycle counters;
  - CPU, memory, and I/O history;
  - power and thermal state;
  - collector status, restart count, scan duration, and explicit retry;
  - logical write attribution for provider event logs and local trace output.
- Reuses this service for the legacy process diagnostics RPCs, removing the old `ps`/PowerShell implementations entirely.
- Validates process signals against both PID and start time and only permits signalable backend descendants; Electron and monitor processes remain visible but protected.

### Bounded local observability

- Replaces the competing native and canonical provider rotators with one shared, thread-aware log store.
- Keeps full provider-native diagnostics while dropping duplicate transient canonical events such as content, item, task, hook, tool, proposal, and realtime audio deltas before serialization. Final states, warnings, and errors remain available.
- Flushes provider records in demand-driven 1-second batches with byte and record thresholds; there is no permanent polling timer.
- Enforces a 512 MiB aggregate provider-log budget and 14-day age limit, pruning oldest files at startup and during sustained writes.
- Removes trace spans from provider-log writes and per-message Electron preview debugger handlers, which were dominant trace hot paths.
- Closes adapter-owned log stores consistently, including the Claude adapter path.

### Reliability and packaging

- Models monitor resolution, protocol, transport, and refresh failures as schema-backed tagged error unions with descriptive messages.
- Supervises the sidecar with version negotiation, bounded restart backoff, a failure circuit, health transitions, and manual retry.
- Handles sidecar sequence resets across restarts and preserves native rates during Electron-only updates.
- Builds and packages platform executables in desktop resources and CLI releases for supported macOS, Linux, and Windows targets.
- Adds CI coverage for Rust formatting/tests and release wiring for per-platform artifacts.

## Metric semantics and limits

- Sampling is once per second, not syscall or process-lifecycle tracing. A process that starts and exits entirely between samples can still be missed.
- Unix-like and Windows process I/O counters have different OS semantics, and filesystem caches mean they are not guaranteed to equal physical SSD traffic. The UI therefore labels them as **I/O reads/writes**, not disk reads/writes.
- Application attribution reports known logical writes from instrumented T3 Code components; it complements rather than replaces process-level OS counters.
- Headless/web servers still receive native process telemetry. Electron-specific power fields degrade to `unknown` instead of falling back to shell probes.
- Collector failures degrade telemetry without taking down the server.

## Validation

- `vp check`
- `vp run typecheck`
- full server suite: 1,243 passed, 7 skipped
- focused provider-log regression suite: 9 passed
- 11 VCS/background-policy merge-integration tests
- `cargo fmt --manifest-path native/resource-monitor/Cargo.toml -- --check`
- `cargo test --locked --manifest-path native/resource-monitor/Cargo.toml` (6 tests)
- `cargo clippy --manifest-path native/resource-monitor/Cargo.toml -- -D warnings`
- `vp run build:desktop`
- Live sidecar smoke test against the local process table, including full command-line and I/O output

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **High Risk**
> Large cross-cutting change to desktop backend spawn/teardown, release packaging, and new native binaries; incorrect fd/protocol handling or restart races could break backend startup or diagnostics, though coverage is extensive in tests.
> 
> **Overview**
> Adds a **Rust `t3-resource-monitor` sidecar** with CI formatting/tests and release artifacts per platform (mac/linux/win), bundled into the CLI and resolved from packaged resources or dev `target/release` for the desktop primary backend. WSL backends intentionally omit the monitor path.
> 
> **Electron main** now publishes NDJSON host telemetry (`DesktopTelemetryPublisher` + `ElectronPowerMonitor`) over inherited fds **4/5** alongside the fd **3** bootstrap; the backend manager wires control messages, demand-gated `app.getAppMetrics()`, and cleans up telemetry sources on stop/restart.
> 
> **Backend child logging** no longer writes stdout/stderr continuously: output is buffered (1 MiB / chunk limits) and flushed to `server-child.log` only on failure or readiness-timeout snapshots; normal shutdown discards the session. Trace batching widens to 1 s and per-chunk output tracing is removed.
> 
> **Desktop backend process management** gains structured tagged errors, post-exit output draining, readiness-timeout context, and safer stop/start/restart behavior (including restart during teardown and timed-out stop).
> 
> **Mobile** reports client activity leases and retains background scopes (e.g. VCS, diagnostics) while subscriptions are active.
> 
> **Server** adds a compile-time **`RPC_REQUIRED_SCOPES`** map so every WebSocket RPC (including background policy and resource telemetry) has an explicit auth scope.
> 
> **Preview** forwards debugger screencast frames to recording listeners only while recording is active.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 6b8a5163be9bac7c3b8b73d8b59a0d7f4dc6ad48. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- Macroscope's pull request summary starts here -->
<!-- Macroscope will only edit the content between these invisible markers, and the markers themselves will not be visible in the GitHub rendered markdown. -->
<!-- If you delete either of the start / end markers from your PR's description, Macroscope will append its summary at the bottom of the description. -->
> [!NOTE]
> ### Add native resource monitor sidecar and background activity policy to reduce idle work and disk churn
> - Introduces a Rust native sidecar ([main.rs](https://github.com/pingdotgg/t3code/pull/2679/files#diff-7a0bf30dcecc5bf8b959e01d81ac251dc193225d35ce851e6e0f59c9773888cf)) that samples system/process metrics via a JSON protocol; the server spawns and communicates with it through `NativeTelemetryClient` and `ResourceMonitorBinary`.
> - Adds a `BackgroundPolicy` service that tracks client activity leases, host power state, and per-scope demand to gate whether periodic background work (provider health refreshes, VCS remote polling) actually runs.
> - Adds `ResourceTelemetry` pipeline (`NativeTelemetryClient` → `DesktopTelemetryReceiver` → `ResourceAttribution` → `ResourceTelemetry`) and exposes history, retry, and live-subscription RPCs to clients.
> - Desktop backend now wires `ElectronPowerMonitor` and `DesktopTelemetryPublisher` to stream Electron process metrics and power state to the server over dedicated FDs (4/5).
> - Web and mobile clients gain background activity reporters that retain scope leases while subscriptions are active and periodically report visibility/focus/app-state to the server.
> - Provider health refresh loop and VCS remote refresh loop skip work when `BackgroundPolicy` reports no foreground demand, and the refresh interval is now driven by `ServerSettingsService` with a new structured `backgroundActivity` settings model.
> - `EventNdjsonLogger` is refactored into a shared log store with batched writes, size-bounded rotation, transient-event filtering, and periodic retention enforcement to reduce disk churn.
> - `RotatingFileSink` no longer triggers an immediate rotation after a write; rotation is deferred to the next write cycle.
> - Risk: `LocalApi` browser facade no longer exposes `server.*` methods or `shell.openInEditor`; callers that previously received a rejected Promise will now see `undefined` properties.
>
> <!-- Macroscope's review summary starts here -->
>
> <sup><a href="https://app.macroscope.com">Macroscope</a> summarized 6b8a516.</sup>
> <!-- Macroscope's review summary ends here -->
>
<!-- macroscope-ui-refresh -->
<!-- Macroscope's pull request summary ends here -->
