instar 1.3.129 → 1.3.130

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,122 @@
1
+ # Side-Effects Review — SessionReaper CPU-aware pressure + decision audit
2
+
3
+ **Version / slug:** `sessionreaper-cpu-aware-and-decision-audit`
4
+ **Date:** `2026-05-30`
5
+ **Author:** `echo`
6
+ **Second-pass reviewer:** `not required`
7
+
8
+ ## Summary of the change
9
+
10
+ The idle-session reaper's pressure tier was computed from free memory only. This
11
+ change makes it the WORST of memory (free %) and CPU (1-min load ÷ cores) via a
12
+ new pure `computePressure()` classifier, with two tunable thresholds
13
+ (`cpuModerateLoadPerCore` 1.0 / `cpuCriticalLoadPerCore` 1.5) auto-migrated to
14
+ existing agents. It also adds a silent decision audit: every keep/kill decision
15
+ *change* + the reap-path events land in `logs/reaper-audit.jsonl`, served
16
+ read-only at `GET /sessions/reaper/audit`.
17
+
18
+ ## Decision-point inventory
19
+
20
+ - **Pressure tier computation** (existing decision, widened): now also keys on CPU
21
+ load. Gates *when* the reaper may consider acting.
22
+ - **Decision audit emission** (new, zero-authority signal): writes an observability
23
+ row on `(verdict, keptBy)` transitions. No control-flow effect.
24
+
25
+ ## 1. Over-block
26
+
27
+ **What legitimate inputs does this change reject that it shouldn't?**
28
+
29
+ CPU-awareness can raise the tier from `normal` to `moderate`/`critical` during a
30
+ load spike, making genuinely-idle sessions eligible sooner. It cannot cause a
31
+ *working* session to be reaped: the kill path still requires the full positive-idle
32
+ proof, transcript-stasis, render-stasis, 3-observation hysteresis over the
33
+ confirmation window, the two-phase reap, and the per-tick/per-hour budget — all
34
+ unchanged. A transient build spike is smoothed by the multi-observation
35
+ requirement. Default thresholds (1.0/1.5 load-per-core) are deliberately at/above
36
+ full subscription so "moderate" means genuinely oversubscribed.
37
+
38
+ ## 2. Under-block
39
+
40
+ **What failure modes does this still miss?**
41
+
42
+ `os.loadavg()` is a trailing 1-minute average, so a very brief CPU famine may not
43
+ register, and a famine caused by non-session processes still only lets the reaper
44
+ trim *idle* sessions (it cannot reduce the load of the busy processes themselves).
45
+ This is acceptable — the reaper is one lever among several (load-shed, hosting
46
+ migration, tool/agent sleep); it is not meant to be a complete CPU governor.
47
+
48
+ ## 3. Level-of-abstraction fit
49
+
50
+ **Is this at the right layer?**
51
+
52
+ Yes. Pressure sensing belongs in the reaper's injected `pressure()` provider; the
53
+ pure classifier lives next to the reaper and is unit-tested without `os`. The audit
54
+ is a sink/reader pair beside the existing `fileAuditSink`, mirroring the
55
+ `/sessions/reap-log` read-surface pattern. No business logic leaks into routes.
56
+
57
+ ## 4. Signal vs authority compliance
58
+
59
+ **Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
60
+
61
+ **Does this change hold blocking authority with brittle logic?**
62
+
63
+ No new blocking authority. The reaper remains the authority it already was; this
64
+ change does not add a brittle check that gates behavior — it widens an existing,
65
+ heavily-confirmed kill path's *eligibility window*, and every safety gate still has
66
+ to clear independently. The decision audit is a pure signal producer (write-only
67
+ observability) with zero authority. `computePressure` is total: unknown/non-finite
68
+ CPU input degrades to the prior memory-only behavior rather than failing.
69
+
70
+ ## 5. Interactions
71
+
72
+ **Does this interact with existing checks, recovery paths, or infrastructure?**
73
+
74
+ - Reads the same `monitoring.sessionReaper` config block; two additive fields.
75
+ - `reapNotify`, the reap-log (`/sessions/reap-log`), and the silently-stopped
76
+ sentinels are untouched; the new audit writes a SEPARATE file
77
+ (`reaper-audit.jsonl`), so nothing reading `sentinel-events.jsonl` is affected.
78
+ (Reaper events previously co-mingled there now route to the dedicated file —
79
+ reviewed: no consumer filters `sentinel-events.jsonl` for `kind:'session-reaper'`.)
80
+ - Migration: canonical config defaults (`applyDefaults` deep-merge) + a
81
+ content-sniffed `migrateClaudeMd` section; both idempotent.
82
+
83
+ ## 6. External surfaces
84
+
85
+ **Does this change anything visible outside the immediate code path?**
86
+
87
+ One new read-only HTTP route (`GET /sessions/reaper/audit`, Bearer-auth, classified
88
+ in the capabilities-discoverability lint). `GET /sessions/reaper`'s `pressure.inputs`
89
+ gains `loadPerCore`/`memTier`/`cpuTier` fields (additive). One new on-disk file
90
+ (`logs/reaper-audit.jsonl`). No Telegram, no attention items, no notifications.
91
+
92
+ ## 7. Rollback cost
93
+
94
+ **If this turns out wrong in production, what's the back-out?**
95
+
96
+ Cheap and layered. (a) Operationally, set the CPU thresholds absurdly high to
97
+ neutralize CPU-awareness with no deploy; the audit is write-only and harmless to
98
+ ignore. (b) A full revert of the PR restores the prior behavior exactly (the change
99
+ is additive). No data migration, no schema change, no irreversible state.
100
+
101
+ ## Conclusion
102
+
103
+ Low-risk, additive, reversible. The safety-critical "never reap a working session"
104
+ contract is untouched; the change only widens *when* the existing gated path may
105
+ act and adds zero-authority observability. Ships behind the reaper's existing
106
+ OFF + dry-run default.
107
+
108
+ ## Second-pass review (if required)
109
+
110
+ Not required — additive change, no new blocking authority, safety classifier
111
+ untouched.
112
+
113
+ ## Evidence pointers
114
+
115
+ - `tests/unit/session-reaper-pressure-audit.test.ts` — `computePressure` matrix,
116
+ transition-only decision audit, sink/reader round-trip.
117
+ - `tests/integration/session-reaper-routes.test.ts` — `GET /sessions/reaper/audit`.
118
+ - `tests/e2e/session-reaper-lifecycle.test.ts` — Phase-1 feature-alive for the
119
+ audit route through the real AgentServer.
120
+ - `tests/unit/feature-delivery-completeness.test.ts` + capabilities-discoverability
121
+ lint — migration + route-classification parity.
122
+ - `upgrades/NEXT.md` — upgrade guide.