instar 1.3.389 → 1.3.391

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "instar",
3
- "version": "1.3.389",
3
+ "version": "1.3.391",
4
4
  "description": "Coherence infrastructure for self-evolving AI agents — on the Claude Code or Codex subscription you already have.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$schema": "./builtin-manifest.schema.json",
3
3
  "schemaVersion": 1,
4
- "generatedAt": "2026-06-07T00:51:44.855Z",
5
- "instarVersion": "1.3.389",
4
+ "generatedAt": "2026-06-07T04:05:00.344Z",
5
+ "instarVersion": "1.3.391",
6
6
  "entryCount": 199,
7
7
  "entries": {
8
8
  "hook:session-start": {
@@ -11,7 +11,7 @@
11
11
  "domain": "identity",
12
12
  "sourcePath": "src/core/PostUpdateMigrator.ts",
13
13
  "installedPath": ".instar/hooks/instar/session-start.sh",
14
- "contentHash": "8d2952d0097dacb8077f2cf4dc3e48ee95de7aacf3517ca1d36aad156a3a4a7b",
14
+ "contentHash": "3e0828b523c2cece3ea4c3c73e77867c2d6884b7493c93e523318e63f5c09e30",
15
15
  "since": "2025-01-01"
16
16
  },
17
17
  "hook:dangerous-command-guard": {
@@ -20,7 +20,7 @@
20
20
  "domain": "safety",
21
21
  "sourcePath": "src/core/PostUpdateMigrator.ts",
22
22
  "installedPath": ".instar/hooks/instar/dangerous-command-guard.sh",
23
- "contentHash": "8d2952d0097dacb8077f2cf4dc3e48ee95de7aacf3517ca1d36aad156a3a4a7b",
23
+ "contentHash": "3e0828b523c2cece3ea4c3c73e77867c2d6884b7493c93e523318e63f5c09e30",
24
24
  "since": "2025-01-01"
25
25
  },
26
26
  "hook:grounding-before-messaging": {
@@ -29,7 +29,7 @@
29
29
  "domain": "safety",
30
30
  "sourcePath": "src/core/PostUpdateMigrator.ts",
31
31
  "installedPath": ".instar/hooks/instar/grounding-before-messaging.sh",
32
- "contentHash": "8d2952d0097dacb8077f2cf4dc3e48ee95de7aacf3517ca1d36aad156a3a4a7b",
32
+ "contentHash": "3e0828b523c2cece3ea4c3c73e77867c2d6884b7493c93e523318e63f5c09e30",
33
33
  "since": "2025-01-01"
34
34
  },
35
35
  "hook:compaction-recovery": {
@@ -38,7 +38,7 @@
38
38
  "domain": "identity",
39
39
  "sourcePath": "src/core/PostUpdateMigrator.ts",
40
40
  "installedPath": ".instar/hooks/instar/compaction-recovery.sh",
41
- "contentHash": "8d2952d0097dacb8077f2cf4dc3e48ee95de7aacf3517ca1d36aad156a3a4a7b",
41
+ "contentHash": "3e0828b523c2cece3ea4c3c73e77867c2d6884b7493c93e523318e63f5c09e30",
42
42
  "since": "2025-01-01"
43
43
  },
44
44
  "hook:external-operation-gate": {
@@ -47,7 +47,7 @@
47
47
  "domain": "safety",
48
48
  "sourcePath": "src/core/PostUpdateMigrator.ts",
49
49
  "installedPath": ".instar/hooks/instar/external-operation-gate.js",
50
- "contentHash": "8d2952d0097dacb8077f2cf4dc3e48ee95de7aacf3517ca1d36aad156a3a4a7b",
50
+ "contentHash": "3e0828b523c2cece3ea4c3c73e77867c2d6884b7493c93e523318e63f5c09e30",
51
51
  "since": "2025-01-01"
52
52
  },
53
53
  "hook:deferral-detector": {
@@ -56,7 +56,7 @@
56
56
  "domain": "safety",
57
57
  "sourcePath": "src/core/PostUpdateMigrator.ts",
58
58
  "installedPath": ".instar/hooks/instar/deferral-detector.js",
59
- "contentHash": "8d2952d0097dacb8077f2cf4dc3e48ee95de7aacf3517ca1d36aad156a3a4a7b",
59
+ "contentHash": "3e0828b523c2cece3ea4c3c73e77867c2d6884b7493c93e523318e63f5c09e30",
60
60
  "since": "2025-01-01"
61
61
  },
62
62
  "hook:self-stop-guard": {
@@ -65,7 +65,7 @@
65
65
  "domain": "coherence",
66
66
  "sourcePath": "src/core/PostUpdateMigrator.ts",
67
67
  "installedPath": ".instar/hooks/instar/self-stop-guard.js",
68
- "contentHash": "8d2952d0097dacb8077f2cf4dc3e48ee95de7aacf3517ca1d36aad156a3a4a7b",
68
+ "contentHash": "3e0828b523c2cece3ea4c3c73e77867c2d6884b7493c93e523318e63f5c09e30",
69
69
  "since": "2025-01-01"
70
70
  },
71
71
  "hook:post-action-reflection": {
@@ -74,7 +74,7 @@
74
74
  "domain": "evolution",
75
75
  "sourcePath": "src/core/PostUpdateMigrator.ts",
76
76
  "installedPath": ".instar/hooks/instar/post-action-reflection.js",
77
- "contentHash": "8d2952d0097dacb8077f2cf4dc3e48ee95de7aacf3517ca1d36aad156a3a4a7b",
77
+ "contentHash": "3e0828b523c2cece3ea4c3c73e77867c2d6884b7493c93e523318e63f5c09e30",
78
78
  "since": "2025-01-01"
79
79
  },
80
80
  "hook:external-communication-guard": {
@@ -83,7 +83,7 @@
83
83
  "domain": "safety",
84
84
  "sourcePath": "src/core/PostUpdateMigrator.ts",
85
85
  "installedPath": ".instar/hooks/instar/external-communication-guard.js",
86
- "contentHash": "8d2952d0097dacb8077f2cf4dc3e48ee95de7aacf3517ca1d36aad156a3a4a7b",
86
+ "contentHash": "3e0828b523c2cece3ea4c3c73e77867c2d6884b7493c93e523318e63f5c09e30",
87
87
  "since": "2025-01-01"
88
88
  },
89
89
  "hook:scope-coherence-collector": {
@@ -92,7 +92,7 @@
92
92
  "domain": "coherence",
93
93
  "sourcePath": "src/core/PostUpdateMigrator.ts",
94
94
  "installedPath": ".instar/hooks/instar/scope-coherence-collector.js",
95
- "contentHash": "8d2952d0097dacb8077f2cf4dc3e48ee95de7aacf3517ca1d36aad156a3a4a7b",
95
+ "contentHash": "3e0828b523c2cece3ea4c3c73e77867c2d6884b7493c93e523318e63f5c09e30",
96
96
  "since": "2025-01-01"
97
97
  },
98
98
  "hook:scope-coherence-checkpoint": {
@@ -101,7 +101,7 @@
101
101
  "domain": "coherence",
102
102
  "sourcePath": "src/core/PostUpdateMigrator.ts",
103
103
  "installedPath": ".instar/hooks/instar/scope-coherence-checkpoint.js",
104
- "contentHash": "8d2952d0097dacb8077f2cf4dc3e48ee95de7aacf3517ca1d36aad156a3a4a7b",
104
+ "contentHash": "3e0828b523c2cece3ea4c3c73e77867c2d6884b7493c93e523318e63f5c09e30",
105
105
  "since": "2025-01-01"
106
106
  },
107
107
  "hook:free-text-guard": {
@@ -110,7 +110,7 @@
110
110
  "domain": "safety",
111
111
  "sourcePath": "src/core/PostUpdateMigrator.ts",
112
112
  "installedPath": ".instar/hooks/instar/free-text-guard.sh",
113
- "contentHash": "8d2952d0097dacb8077f2cf4dc3e48ee95de7aacf3517ca1d36aad156a3a4a7b",
113
+ "contentHash": "3e0828b523c2cece3ea4c3c73e77867c2d6884b7493c93e523318e63f5c09e30",
114
114
  "since": "2025-01-01"
115
115
  },
116
116
  "hook:claim-intercept": {
@@ -119,7 +119,7 @@
119
119
  "domain": "coherence",
120
120
  "sourcePath": "src/core/PostUpdateMigrator.ts",
121
121
  "installedPath": ".instar/hooks/instar/claim-intercept.js",
122
- "contentHash": "8d2952d0097dacb8077f2cf4dc3e48ee95de7aacf3517ca1d36aad156a3a4a7b",
122
+ "contentHash": "3e0828b523c2cece3ea4c3c73e77867c2d6884b7493c93e523318e63f5c09e30",
123
123
  "since": "2025-01-01"
124
124
  },
125
125
  "hook:claim-intercept-response": {
@@ -128,7 +128,7 @@
128
128
  "domain": "coherence",
129
129
  "sourcePath": "src/core/PostUpdateMigrator.ts",
130
130
  "installedPath": ".instar/hooks/instar/claim-intercept-response.js",
131
- "contentHash": "8d2952d0097dacb8077f2cf4dc3e48ee95de7aacf3517ca1d36aad156a3a4a7b",
131
+ "contentHash": "3e0828b523c2cece3ea4c3c73e77867c2d6884b7493c93e523318e63f5c09e30",
132
132
  "since": "2025-01-01"
133
133
  },
134
134
  "hook:stop-gate-router": {
@@ -137,7 +137,7 @@
137
137
  "domain": "safety",
138
138
  "sourcePath": "src/core/PostUpdateMigrator.ts",
139
139
  "installedPath": ".instar/hooks/instar/stop-gate-router.js",
140
- "contentHash": "8d2952d0097dacb8077f2cf4dc3e48ee95de7aacf3517ca1d36aad156a3a4a7b",
140
+ "contentHash": "3e0828b523c2cece3ea4c3c73e77867c2d6884b7493c93e523318e63f5c09e30",
141
141
  "since": "2025-01-01"
142
142
  },
143
143
  "hook:auto-approve-permissions": {
@@ -146,7 +146,7 @@
146
146
  "domain": "safety",
147
147
  "sourcePath": "src/core/PostUpdateMigrator.ts",
148
148
  "installedPath": ".instar/hooks/instar/auto-approve-permissions.js",
149
- "contentHash": "8d2952d0097dacb8077f2cf4dc3e48ee95de7aacf3517ca1d36aad156a3a4a7b",
149
+ "contentHash": "3e0828b523c2cece3ea4c3c73e77867c2d6884b7493c93e523318e63f5c09e30",
150
150
  "since": "2025-01-01"
151
151
  },
152
152
  "job:health-check": {
@@ -1538,7 +1538,7 @@
1538
1538
  "type": "subsystem",
1539
1539
  "domain": "updates",
1540
1540
  "sourcePath": "src/core/PostUpdateMigrator.ts",
1541
- "contentHash": "8d2952d0097dacb8077f2cf4dc3e48ee95de7aacf3517ca1d36aad156a3a4a7b",
1541
+ "contentHash": "3e0828b523c2cece3ea4c3c73e77867c2d6884b7493c93e523318e63f5c09e30",
1542
1542
  "since": "2025-01-01"
1543
1543
  },
1544
1544
  "subsystem:scheduler": {
@@ -0,0 +1,50 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ macOS `mediaanalysisd` (~72-78% of a core) and Spotlight `mds_stores` (~28-48%)
9
+ were top constant CPU consumers on a busy fleet box — pinning it at load average
10
+ 30 — because the agent's OWN runtime data dir (`<agentHome>/.instar/`) was never
11
+ excluded from indexing. It holds `telegram-images/` (every user photo, vision-
12
+ analyzed by mediaanalysisd), `server-data/` (SQLite DBs rewritten continuously),
13
+ `logs/`, and `state/`. Instar already excluded `.worktrees/` (#588),
14
+ `node_modules/` (#606), and Claude transcripts (#903); this closes the last gap.
15
+
16
+ New `ensureAgentDataSpotlightExclusion()` helper drops the standard
17
+ `.metadata_never_index` marker in each high-churn subdir + a `PostUpdateMigrator`
18
+ backfill so existing agents get the relief on their next update.
19
+ `.instar/telegram-images/` and `.instar/server-data/` are also gitignored.
20
+
21
+ ## What to Tell Your User
22
+
23
+ Nothing required — silent OS-level resource hygiene. If their Mac was running
24
+ hot, part of the cause was macOS endlessly indexing and photo-analyzing the
25
+ agent's own chat images and databases; this stops that going forward.
26
+
27
+ ## Summary of New Capabilities
28
+
29
+ - `ensureAgentDataSpotlightExclusion(stateDir)` — drops `.metadata_never_index`
30
+ in the agent's `.instar/{telegram-images,server-data,logs,state}` so macOS
31
+ Spotlight + mediaanalysisd stop indexing the agent's own churning runtime data.
32
+ - `PostUpdateMigrator` backfill — existing agents get the exclusion on their next
33
+ update. Internal OS hygiene; no agent-facing API or config surface.
34
+
35
+ ## Evidence
36
+
37
+ Unit + migration tests (both sides of every boundary: marker dropped in each
38
+ existing subdir, only-existing subdirs marked, `[]` for a new agent, idempotent;
39
+ migration backfills/skips/idempotent). 22/22 green in the spotlight-exclusion
40
+ suite. `tsc --noEmit` clean. Mirrors the existing node_modules/worktree/transcript
41
+ exclusion pattern exactly.
42
+
43
+ ## Scope (honest)
44
+
45
+ This prevents FUTURE indexing/analysis. It does not instantly drop
46
+ `mediaanalysisd`/`mds_stores` — macOS releases already-indexed content on its own
47
+ schedule; forcing immediate eviction needs a one-time `sudo mdutil -E` the
48
+ operator runs. One of several resource-efficiency fixes (2026-06-06). Does not
49
+ address the ~300 accumulated worktrees (~100GB) — that is the AgentWorktreeReaper,
50
+ gated separately on operator approval.
@@ -0,0 +1,49 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ The idle-session reaper's "never reap a session with an open commitment" safety
9
+ guard is now activity-aware. An open commitment protects a session only while a
10
+ user message arrived within a staleness window (default 24h); past that the
11
+ commitment is treated as abandoned and no longer blocks reaping. Found 2026-06-06
12
+ during a load-avg-30 overload: a reaper dry-run would have reaped NOTHING because
13
+ 19 of 26 sessions were pinned by `open-commitment`, many on sessions untouched for
14
+ 26h. The unconditional veto was the dominant blocker to idle-session cleanup.
15
+
16
+ New `staleCommitmentWindowMs` on `ReapGuard` (default 24h; `Infinity` = old
17
+ always-protect) + `monitoring.sessionReaper.staleCommitmentWindowMinutes`
18
+ (default 1440), threaded through to the terminate-time authority guard too.
19
+
20
+ ## What to Tell Your User
21
+
22
+ Nothing required — internal reaper policy, and the reaper itself remains opt-in.
23
+ For operators turning the reaper on: idle sessions that have an open commitment
24
+ but no user message for 24h+ will now become reap-eligible (they previously stayed
25
+ alive forever). Active sessions and recently-touched sessions are unaffected.
26
+
27
+ ## Summary of New Capabilities
28
+
29
+ - `ReapGuard.staleCommitmentWindowMs` — bounds the open-commitment KEEP-guard so a
30
+ stale commitment stops pinning an inactive session. Default 24h; `Infinity`
31
+ restores always-protect.
32
+ - `sessionReaper.staleCommitmentWindowMinutes` config (default 1440). Internal
33
+ reaper policy; no agent-facing API/CLI surface.
34
+
35
+ ## Evidence
36
+
37
+ `tests/unit/reap-guard.test.ts` + `tests/unit/session-reaper.test.ts`: both sides
38
+ of the boundary (stale commitment ⇒ falls through to reap-eligible; fresh
39
+ commitment within window ⇒ still keeps; custom window honored; `Infinity` restores
40
+ always-protect; existing open-commitment cases updated to window-aware mocks).
41
+ 49/49 green. `tsc --noEmit` clean.
42
+
43
+ ## Scope (honest)
44
+
45
+ UNBLOCKS the reaper — it changes which sessions are eligible, it does not by itself
46
+ kill anything (the reaper is opt-in + dry-run-first). Pairs with enabling
47
+ sessionReaper + mcpProcessReaper + SleepController (which ship opt-in and were off
48
+ fleet-wide). Does NOT auto-expire the commitments themselves (separate follow-up);
49
+ it only stops a stale commitment from vetoing a reap.
@@ -0,0 +1,46 @@
1
+ # Side-Effects Review - Agent runtime-data Spotlight exclusion
2
+
3
+ **Version / slug:** `agent-data-spotlight-exclusion`
4
+ **Date:** `2026-06-06`
5
+ **Author:** `echo`
6
+ **Second-pass reviewer:** `not required (Tier 1)`
7
+
8
+ ## Summary of the change
9
+
10
+ Extends Instar's existing macOS Spotlight exclusion (currently covers `.worktrees/` #588, `node_modules/` #606, and Claude transcripts #903) to the agent's OWN runtime data dir (`<agentHome>/.instar/`). On a box pinned at load average 30 (2026-06-06, Justin's resource investigation), grounding showed the top CPU consumers were `mediaanalysisd` (~72-78% — analyzing the agent's `telegram-images/`) and `mds_stores`/Spotlight (~28-48% — re-indexing the constantly-rewritten `server-data/` SQLite dbs, `logs/`, `state/`). These were the remaining unexcluded churn source. Adds `ensureAgentDataSpotlightExclusion()` (reuses the generic marker-dropper) + a `PostUpdateMigrator` backfill, and gitignores the two runtime dirs that weren't already ignored.
11
+
12
+ ## Decision-point inventory
13
+
14
+ - `ensureAgentDataSpotlightExclusion(stateDir)` (new, exported) — drops `.metadata_never_index` in each existing high-churn subdir (`telegram-images`, `server-data`, `logs`, `state`); returns the list created. Reuses `ensureWorktreeSpotlightExclusion` (the dir-agnostic dropper).
15
+ - `PostUpdateMigrator.migrateAgentDataSpotlightExclusion` (new, private) — runs the helper on every update, pushes an `upgraded`/`errors` entry.
16
+ - Wired into the migrate() sequence right after `migrateClaudeTranscriptSpotlightExclusion`.
17
+ - `.gitignore` — adds `.instar/telegram-images/` and `.instar/server-data/` (per-machine runtime data; `logs/`, `state/`, `telegram-inbound/` were already ignored).
18
+
19
+ ## 1. Behavior change / gating
20
+
21
+ NONE that affects message flow, sessions, or any gate. The only effect is writing empty marker files into the agent's own `.instar/` data subdirs, telling macOS Spotlight + mediaanalysisd to stop indexing them. No runtime behavior of the agent changes; instar's own reads of these dirs (TokenLedger, server-data DBs, log tailing) are filesystem reads, unaffected by Spotlight indexing.
22
+
23
+ ## 2. Over/under-signal
24
+
25
+ N/A — not a signal/gate. The only "decision" is whether each subdir exists (drop the marker) or not (skip). Both branches are covered by tests.
26
+
27
+ ## 3. Blast radius
28
+
29
+ Filesystem only, additive, and scoped ENTIRELY INSIDE the agent's own `<agentHome>/.instar/` — unlike #903 it never reaches outside the agent home. Writes up to four empty marker files. No state mutation, no data migration, no config change. On a non-macOS host the markers are inert. The `.gitignore` additions only prevent committing per-machine runtime data (which was never intended to be committed).
30
+
31
+ ## 4. Failure modes
32
+
33
+ The underlying `ensureWorktreeSpotlightExclusion` swallows write errors (`@silent-fallback-ok`) and returns false — a failed marker write just means Spotlight keeps indexing (status quo), and can never block the migration or an update. `existsSync` guards each absent subdir (brand-new agent with no data yet → returns `[]`). No throw path.
34
+
35
+ ## 5. Migration parity
36
+
37
+ Covered: the `PostUpdateMigrator` backfill means existing agents get the markers on their next update (fast release cadence drops them within minutes). New agents get them once the subdirs exist. No agent-installed config/hooks/skills/CLAUDE.md change — this is internal OS hygiene with no agent-facing surface, consistent with the precedent (#588/#606/#903 also have no CLAUDE.md template line; they are not capabilities the agent surfaces to a user). No init-path call is needed because the data subdirs don't exist at init time — it would no-op; the migration is the correct single mechanism.
38
+
39
+ ## 6. Scope honesty (what this is NOT)
40
+
41
+ - One fix in the resource-efficiency initiative (Justin, 2026-06-06). The marker prevents FUTURE indexing/analysis; it does NOT instantly drop `mediaanalysisd`/`mds_stores` — macOS releases already-indexed content on its own schedule, and an immediate purge needs a one-time `sudo mdutil -E` the operator runs (instar cannot run sudo). The durable guarantee is that no agent keeps feeding the churn.
42
+ - Does NOT address the ~300 accumulated worktrees (~100GB) — that is the AgentWorktreeReaper's job, gated separately on operator approval because it deletes checkouts.
43
+
44
+ ## 7. Causal autopsy
45
+
46
+ Origin: **latent** (not a prior-PR regression). The agent's `.instar/` runtime data (images, DBs, logs, state) has been indexed by macOS since agents began writing it. The prior Spotlight-exclusion PRs (#588 worktrees, #606 node_modules, #903 transcripts) progressively closed the largest known trees but never extended to the agent's own data dir — which 2026-06-06 grounding (`ps`/`uptime` census during the load-30 incident) showed was the live `mediaanalysisd` + `mds_stores` fuel via `telegram-images/` and `server-data/`. This PR closes that latent gap by reusing the same marker mechanism. No behavior was broken by a prior change; an existing cost was simply never excluded.
@@ -0,0 +1,46 @@
1
+ # Side-Effects Review - Reaper stale-commitment override
2
+
3
+ **Version / slug:** `reaper-stale-commitment-override`
4
+ **Date:** `2026-06-06`
5
+ **Author:** `echo`
6
+ **Second-pass reviewer:** `not required (Tier 1)`
7
+
8
+ ## Summary of the change
9
+
10
+ The `ReapGuard` open-commitment KEEP-guard now protects a session only while a user message arrived within a staleness window (`staleCommitmentWindowMs`, default 24h). Past that window the open commitment is treated as abandoned and no longer vetoes reaping. Surfaced because a 2026-06-06 dry-run (during a load-avg-30 overload investigation) showed the idle-session reaper would reap NOTHING — 19 of 26 sessions were pinned by `open-commitment`, many on sessions the user hadn't touched in 26h. Adds `staleCommitmentWindowMs` to `ReapGuardOptions` (+ `DEFAULT_REAP_GUARD_OPTIONS`), `staleCommitmentWindowMinutes` to `SessionReaperConfig` + `ConfigDefaults` + the `InstarConfig` type, threaded `SessionReaper`→`ReapGuard`.
11
+
12
+ ## Decision-point inventory
13
+
14
+ - `ReapGuard.evaluate()` guard J (open-commitment): now gated on `recentUserMessage(topicId, staleCommitmentWindowMs)`. Fresh ⇒ keep('open-commitment'); stale ⇒ fall through to the activeness guards (unchanged).
15
+ - `ReapGuardOptions.staleCommitmentWindowMs` (new; default 24h; `Infinity` = old always-protect).
16
+ - `SessionReaperConfig.staleCommitmentWindowMinutes` (new; default 1440) → mapped to ms in the `SessionReaper` constructor's `new ReapGuard(...)`.
17
+ - `ConfigDefaults` + `types.ts` `sessionReaper` block gain `staleCommitmentWindowMinutes`.
18
+
19
+ ## 1. Behavior change / gating
20
+
21
+ This is a guard-loosening, in ONE direction only: it makes MORE sessions reap-ELIGIBLE, and only those that are BOTH commitment-pinned AND have had no user message for ≥24h. It never makes a session that was reapable into kept. Every other KEEP-guard (protected, spawn-grace, recovery, pending-injection, relay-lease, recent-user-message, active-subagent, structural-long-work, active-process, main-process) is unchanged and still fires in the same order. A session must STILL clear all remaining activeness guards (and, in the reaper, transcript-growth + positive-idle + confirmObservations) before it is actually reaped — this only removes the stale-commitment veto.
22
+
23
+ ## 2. Over/under-signal
24
+
25
+ The risk direction is OVER-reaping a session whose commitment is genuinely active but whose user simply hasn't messaged in 24h. Mitigations: (a) 24h is a long, conservative horizon — Justin's explicit "no message today" intent; (b) the session must additionally have NO active processes, NO active subagent, NO recent transcript growth, and be positively idle to actually reap; (c) `Infinity` disables entirely; (d) the terminate-time authority guard uses the same default so a single chokepoint enforces it. UNDER-signal (failing to reap) is the prior behavior being fixed.
26
+
27
+ ## 3. Blast radius
28
+
29
+ Pure in-memory guard logic; no I/O, no new deps (reuses the existing `recentUserMessage` dep with a longer window). Affects only the reap-eligibility decision for commitment-pinned, 24h-silent sessions. Ships behind the sessionReaper (which is itself opt-in + dry-run-first). No API route, no persistent state, no migration of data.
30
+
31
+ ## 4. Failure modes
32
+
33
+ `recentUserMessage` throwing is already caught by `blockedReason()`'s try/catch → KEEP ('guard-error'), so a signal failure fails SAFE (never reaps). `staleCommitmentWindowMs` defaults are always present (DEFAULT_REAP_GUARD_OPTIONS / DEFAULT_SESSION_REAPER_CONFIG), so an old config missing the field gets 24h, not 0. `Infinity` is honored (any finite withinMs < Infinity ⇒ a correct mock keeps).
34
+
35
+ ## 5. Migration parity
36
+
37
+ `staleCommitmentWindowMinutes` is an OPTIONAL config field with a code default (1440) in both `DEFAULT_SESSION_REAPER_CONFIG` and `ConfigDefaults`, so existing agents whose config omits it get the 24h behavior automatically — no `PostUpdateMigrator` entry needed (absence ⇒ default, the established pattern for sessionReaper sub-fields). No agent-installed file (hooks/skills/CLAUDE.md) changes; this is internal reaper policy with no agent-facing surface. The reaper remains opt-in (enabled:false default), so this changes nothing until an operator enables it.
38
+
39
+ ## 6. Scope honesty (what this is NOT)
40
+
41
+ - This UNBLOCKS the reaper; it does not by itself reduce a live process count. It changes which sessions are eligible; the reaper (dry-run first, then live) acts on them. It's paired with enabling sessionReaper + mcpProcessReaper + SleepController (which ship opt-in and were off fleet-wide — the 2026-06-06 finding).
42
+ - It does NOT touch the commitments themselves (no auto-expiry of stale commitments — that's a separate follow-up). It only stops a stale commitment from VETOING a reap.
43
+
44
+ ## 7. Causal autopsy
45
+
46
+ Origin: **latent**. The open-commitment guard has unconditionally protected commitment-bearing sessions since it was added; that was correct when sessions were short-lived and commitments closed promptly. As the fleet grew to dozens of multi-day sessions with commitments left open, the unconditional veto became the dominant blocker to idle-session reaping (grounded 2026-06-06: 19/26 keeps were open-commitment, many 26h-idle). No prior PR regressed it; an always-on protection simply never had a staleness bound. This adds the bound.