instar 1.3.682 → 1.3.683

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,47 @@
1
+ # Process-footprint monitor — ELI16 overview
2
+
3
+ ## The problem in plain words
4
+
5
+ On 2026-06-26 the machine running this agent crashed hard — a kernel panic that forced
6
+ a reboot. The trigger was resource exhaustion: too many processes piled up on one
7
+ machine (several full agent stacks plus their heavy helper "MCP" servers — a whole
8
+ Chromium for the browser tool, an Electron app for another — most of them sitting idle).
9
+ The number of processes climbed slowly over time until the operating system hit an
10
+ internal limit and gave up.
11
+
12
+ The painful part: nobody SAW it coming. The agent already tracks CPU and memory, but it
13
+ never tracked the simplest, most relevant number for this kind of crash — *how many
14
+ processes are running on this machine right now, and is that number climbing?* That
15
+ measurement was missing, so the buildup was invisible until it was too late.
16
+
17
+ ## What this change does
18
+
19
+ This adds a small, observe-only monitor that fills exactly that gap. On an interval it
20
+ counts the agent-relevant processes on the machine and sorts them into buckets:
21
+
22
+ - **agent CLIs** — the per-session reasoning processes (claude / codex / gemini),
23
+ - **MCP servers** — the heavy, mostly-idle helper servers (Playwright's Chromium, etc.),
24
+ matched by the same precise signatures the cleanup sweep already uses,
25
+ - **other node** — the agent's servers, lifelines, and wrappers.
26
+
27
+ It keeps a rolling window of those readings so a TREND is visible — is the count rising,
28
+ stable, or falling? You can read it any time:
29
+
30
+ `GET /resources/footprint` → `{ enabled, latest: { total, byKind, rssBytes }, trend,
31
+ overThreshold, samples }`
32
+
33
+ ## What it deliberately does NOT do
34
+
35
+ It is **observe-only**. It never kills, throttles, or blocks anything — reclaiming
36
+ processes is the job of the existing reapers. This monitor only MEASURES, so it can't
37
+ cause harm. There is an optional heads-up that can fire when the count crosses a
38
+ threshold, but it's off by default ("measure first") — the goal of this first step is
39
+ just to make the climb visible.
40
+
41
+ It ships **dark** (off on the fleet, on for development agents) so it's exercised here
42
+ before any wider rollout, and every reading path fails safe: if the process scan fails,
43
+ the monitor keeps its last reading rather than crashing. The route returns a clear
44
+ "unavailable" (503) when the monitor is turned off.
45
+
46
+ The point: the next time the process footprint starts climbing toward danger, it will be
47
+ a number you can watch — not an invisible buildup that ends in a crash.
@@ -0,0 +1,69 @@
1
+ # Side-Effects Review — Process-footprint monitor
2
+
3
+ **Version / slug:** `process-footprint-monitor`
4
+ **Date:** `2026-06-27`
5
+ **Author:** `echo`
6
+ **Tier:** 1 — a NEW observe-only monitor + a read-only route. Ships DARK (developmentAgent
7
+ gate). No authority, no gate, no deletion, no mutation; it only READS process metadata
8
+ and exposes a status. The threshold heads-up is opt-in and its sink is unwired in this
9
+ increment (measure-first).
10
+
11
+ ## Summary of the change
12
+
13
+ Adds `ProcessFootprintMonitor` — the per-machine process-COUNT measurement missing before
14
+ the 2026-06-26 resource-exhaustion kernel panic (the ResourceLedger samples CPU%/RSS but
15
+ not process count). On an interval it counts agent-relevant processes (agent CLIs / MCP
16
+ servers via the shared `MCP_PROCESS_SIGNATURES` / other node), keeps a bounded rolling
17
+ window for a trend, and exposes `GET /resources/footprint`. Files:
18
+ `src/monitoring/ProcessFootprintMonitor.ts` (new — pure classifier + sampler + a
19
+ `ps`-backed scanner funneled through `withSyncOp`), `src/server/AgentServer.ts` (construct
20
+ + start, dev-gated; null when disabled), `src/server/routes.ts` (the read-only route +
21
+ ctx type), `src/core/types.ts` (config), `src/scaffold/templates.ts` +
22
+ `src/core/PostUpdateMigrator.ts` (awareness). Tests: 11 unit + 3 integration + 4 e2e.
23
+
24
+ ## 1. Over-block / 2. Under-block
25
+
26
+ **No block/allow surface — not applicable.** The monitor never gates, kills, or throttles.
27
+ The closest failure is a wrong reading: a throwing `ps` scan fails safe (keeps the last
28
+ sample, never crashes `sample()`); classification is best-effort (a miscount only changes
29
+ a number, never an action). Both sides of the classifier and the alert latch are unit-tested.
30
+
31
+ ## 3. Level-of-abstraction fit
32
+
33
+ Correct layer. It sits beside the ResourceLedger as read-only observability, constructed in
34
+ `AgentServer` like the other monitors and exposed via a `/resources/*` route. The pure core
35
+ (classifier, sample builder, trend, alert latch) is fully injectable/fake-testable; only the
36
+ production `ps` scanner touches the host.
37
+
38
+ ## 4. Signal vs authority compliance
39
+
40
+ Pure SIGNAL. The status is consumed by a human/dashboard, not by any gate. The optional
41
+ threshold heads-up only ever ADDS one de-duplicated attention item (per episode, with
42
+ hysteresis) — it carries zero blocking authority and is OFF by default.
43
+
44
+ ## 5. Interactions
45
+
46
+ - **Sampling cost:** one `ps` scan per multi-minute interval, funneled through `withSyncOp`
47
+ (the in-flight marker sees the bounded blocking spawn). Dark by default → zero fleet cost.
48
+ - **Alert latch:** one heads-up per threshold-crossing episode; re-arms only after the count
49
+ drops below 90% of the threshold (hysteresis) — no flapping. Tested both sides.
50
+ - **Disabled = null:** when the dev-gate/config resolves disabled, the monitor is not
51
+ constructed → the route 503s (matches the ResourceLedger contract; e2e-tested).
52
+
53
+ ## 6. External surfaces
54
+
55
+ - **New route** `GET /resources/footprint` (Bearer-gated, read-only; POST → 404). No new
56
+ external call beyond the local `ps` scan. No new credential.
57
+ - Config: `monitoring.processFootprintMonitor` (enabled/sampleIntervalMs/windowSamples/
58
+ alertThreshold/alertEnabled). `enabled` undefined rides the developmentAgent gate. No
59
+ config MIGRATION needed (absence resolves via the gate; `?? defaults` cover the rest).
60
+
61
+ ## 7. Rollback
62
+
63
+ Pure additive code + one config block + docs. Reverting the commit removes the monitor and
64
+ the route entirely. Dark default means no agent runs it until explicitly enabled.
65
+
66
+ ## Known follow-up (tracked, not in this increment)
67
+
68
+ The threshold heads-up's `emitAttention` sink is left unwired (the alert is opt-in and OFF
69
+ by default — measure-first). Wiring it to the aggregated attention surface is increment 2.