instar 1.3.532 → 1.3.533
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/dist/core/ReapGuard.d.ts.map +1 -1
- package/dist/core/ReapGuard.js +14 -1
- package/dist/core/ReapGuard.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +2 -2
- package/upgrades/1.3.533.md +25 -0
- package/upgrades/eli16/reapguard-stale-commitment-revival-loop.md +28 -0
- package/upgrades/side-effects/reapguard-stale-commitment-revival-loop.md +82 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReapGuard.d.ts","sourceRoot":"","sources":["../../src/core/ReapGuard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,KAAK,CAAC;AAE5C,+EAA+E;AAC/E,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,cAAc,CAAC;CAC5B;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,iBAAiB,EAAE,MAAM,MAAM,EAAE,CAAC;IAClC,gBAAgB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;IAChD,mBAAmB,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC;IACtD,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IACnD,YAAY,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACrD,iBAAiB,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;IAClE,wBAAwB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IACvD,mBAAmB,EAAE,CAAC,eAAe,EAAE,MAAM,GAAG,SAAS,KAAK,MAAM,CAAC;IACrE,uBAAuB,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,OAAO,CAAC;IAC7D,kBAAkB,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC;IACrD,kFAAkF;IAClF,iBAAiB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,GAAG,SAAS,CAAC;IACjE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,kBAAkB,EAAE,MAAM,CAAC;IAC3B,oEAAoE;IACpE,sBAAsB,EAAE,OAAO,CAAC;IAChC;;;;;;;;OAQG;IACH,uBAAuB,EAAE,MAAM,CAAC;CACjC;AAED,eAAO,MAAM,0BAA0B,EAAE,gBAKxC,CAAC;AAEF,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAmB;IACxC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;gBAEvB,IAAI,EAAE,aAAa,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC;IAMjE;;;;;;;;;OASG;IACH,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,cAAc,GAAG,IAAI;IAQtD,OAAO,CAAC,QAAQ;IA6DhB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,gBAAgB,EAAE;
|
|
1
|
+
{"version":3,"file":"ReapGuard.d.ts","sourceRoot":"","sources":["../../src/core/ReapGuard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,KAAK,CAAC;AAE5C,+EAA+E;AAC/E,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,cAAc,CAAC;CAC5B;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,iBAAiB,EAAE,MAAM,MAAM,EAAE,CAAC;IAClC,gBAAgB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;IAChD,mBAAmB,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC;IACtD,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IACnD,YAAY,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACrD,iBAAiB,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;IAClE,wBAAwB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IACvD,mBAAmB,EAAE,CAAC,eAAe,EAAE,MAAM,GAAG,SAAS,KAAK,MAAM,CAAC;IACrE,uBAAuB,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,OAAO,CAAC;IAC7D,kBAAkB,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC;IACrD,kFAAkF;IAClF,iBAAiB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,GAAG,SAAS,CAAC;IACjE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,kBAAkB,EAAE,MAAM,CAAC;IAC3B,oEAAoE;IACpE,sBAAsB,EAAE,OAAO,CAAC;IAChC;;;;;;;;OAQG;IACH,uBAAuB,EAAE,MAAM,CAAC;CACjC;AAED,eAAO,MAAM,0BAA0B,EAAE,gBAKxC,CAAC;AAEF,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAmB;IACxC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;gBAEvB,IAAI,EAAE,aAAa,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC;IAMjE;;;;;;;;;OASG;IACH,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,cAAc,GAAG,IAAI;IAQtD,OAAO,CAAC,QAAQ;IA6DhB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,gBAAgB,EAAE;CA8DxF"}
|
package/dist/core/ReapGuard.js
CHANGED
|
@@ -169,7 +169,20 @@ export class ReapGuard {
|
|
|
169
169
|
if (topicId != null) {
|
|
170
170
|
const boundTopicId = topicId;
|
|
171
171
|
probe(() => this.deps.recentUserMessage(boundTopicId, this.opts.recentUserWindowMs), 'recent-user-message');
|
|
172
|
-
|
|
172
|
+
// Open commitment — gated by the SAME staleness horizon evaluate()'s KEEP
|
|
173
|
+
// check uses (guard J above). A commitment counts as in-flight-work evidence
|
|
174
|
+
// ONLY while the topic has had a user message within staleCommitmentWindowMs;
|
|
175
|
+
// past that, evaluate() treats the commitment as abandoned and lets the
|
|
176
|
+
// session die — so workEvidence() must NOT re-assert it as work. Without this
|
|
177
|
+
// gate the two methods disagree on the same commitment: an idle session is
|
|
178
|
+
// killed (evaluate: stale ⇒ reap) then immediately revived (workEvidence:
|
|
179
|
+
// open-commitment ⇒ resume-eligible), forever. They MUST agree on what an
|
|
180
|
+
// open commitment means. (2026-06-13: 13 idle sessions across 6 topics were
|
|
181
|
+
// age-killed + revived in a loop, every one tagged solely [open-commitment]
|
|
182
|
+
// on a commitment the KEEP-guard had already judged stale.)
|
|
183
|
+
probe(() => this.opts.protectOpenCommitments &&
|
|
184
|
+
this.deps.activeCommitmentForTopic(boundTopicId) &&
|
|
185
|
+
this.deps.recentUserMessage(boundTopicId, this.opts.staleCommitmentWindowMs), 'open-commitment');
|
|
173
186
|
}
|
|
174
187
|
probe(() => this.deps.activeSubagentCount(session.claudeSessionId) > 0, 'active-subagent');
|
|
175
188
|
probe(() => this.deps.buildOrAutonomousActive(topicId), 'structural-long-work');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReapGuard.js","sourceRoot":"","sources":["../../src/core/ReapGuard.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ReapGuard.js","sourceRoot":"","sources":["../../src/core/ReapGuard.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./builtin-manifest.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"generatedAt": "2026-06-
|
|
5
|
-
"instarVersion": "1.3.
|
|
4
|
+
"generatedAt": "2026-06-13T18:27:49.685Z",
|
|
5
|
+
"instarVersion": "1.3.533",
|
|
6
6
|
"entryCount": 201,
|
|
7
7
|
"entries": {
|
|
8
8
|
"hook:session-start": {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: patch -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
The session reaper's shared guard (`ReapGuard`) had two halves that disagreed about a *stale* open commitment. The KILL decision (`evaluate()`) already treats a commitment as abandoned after 8h of topic silence and lets the idle session be reaped. But the RESUME-eligibility decision (`workEvidence()`) counted **any** open commitment as proof of interrupted work — with no staleness gate. So an idle session was killed (commitment stale ⇒ reap) and immediately revived (commitment exists ⇒ resume-eligible), in an endless loop.
|
|
9
|
+
|
|
10
|
+
This patch applies the **same 8h staleness gate** to the resume-eligibility probe that the kill decision already uses, so the two halves agree: a stale commitment neither keeps a session alive nor revives it, and a fresh one keeps the session alive so it never needs reviving. Strictly safer — it can only ever revive *less*, never more. Genuine interrupted work (a live build, an active sub-agent, a pending injection, a running process) is untouched.
|
|
11
|
+
|
|
12
|
+
## What to Tell Your User
|
|
13
|
+
|
|
14
|
+
Sessions that finished their work but still had an old, untouched promise on the books were being killed and revived over and over. That loop is fixed. You'll see fewer "🪦 your session was shut down — a restart is queued" notices on topics where nothing was actually unfinished. Promises still get followed up on by the commitment system — that part is unchanged.
|
|
15
|
+
|
|
16
|
+
## Summary of New Capabilities
|
|
17
|
+
|
|
18
|
+
No new capability — this is a bugfix. It removes a spurious session kill→revive loop driven by stale (long-untouched) open commitments by aligning the reaper guard's resume-eligibility decision with its existing kill-decision staleness rule.
|
|
19
|
+
|
|
20
|
+
## Evidence
|
|
21
|
+
|
|
22
|
+
- Live `logs/reap-log.jsonl` (2026-06-13): **13** age-limit reaps with `midWork=true`, every one carrying solely `workEvidence=[open-commitment]`, across 6 topics — and corresponding repeated `reason=age-limit` respawn entries in the resume queue (several doubled per topic). The loop, captured.
|
|
23
|
+
- Root cause confirmed in source: `ReapGuard.evaluate()` gates the open-commitment KEEP on `recentUserMessage(topicId, staleCommitmentWindowMs)`; `ReapGuard.workEvidence()` did not.
|
|
24
|
+
- New regression tests in `tests/unit/work-evidence.test.ts`: a stale commitment emits no `open-commitment` evidence (and `isMidWork`→false); a fresh one still does; an explicit `evaluate()`/`workEvidence()` consistency assertion; and the `protectOpenCommitments:false` boundary. All 22 work-evidence + 19 reap-guard unit tests green; 164 related reap/resume tests green; `tsc --noEmit` clean.
|
|
25
|
+
- Independent second-pass review (lifecycle change): **Concur** — confirmed the age-limit path uses the patched fallback, no legitimate revival is lost, downstream ResumeQueue / live-enqueue / boot-reconciliation re-enqueue (all `midWork`/`evidenceEligible`-gated) all behave correctly.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Stale-commitment kill→revive loop — Plain-English Overview
|
|
2
|
+
|
|
3
|
+
> The one-line version: a session that finished its work but had an old, untouched promise still on the books was being killed (correctly) and then revived (incorrectly) over and over, forever. This stops the revival half from firing on a stale promise.
|
|
4
|
+
|
|
5
|
+
## The problem in one breath
|
|
6
|
+
|
|
7
|
+
Today 13 idle sessions across 6 different topics were age-killed and then brought back to life, again and again, in a loop. Every single one was idle — its turn was finished, nothing was running — and the *only* reason the system revived it was that a commitment ("I'll keep you posted") was still registered on that topic. Many of those commitments were long-since done; they just were never marked delivered.
|
|
8
|
+
|
|
9
|
+
## What already exists
|
|
10
|
+
|
|
11
|
+
The reaper has one shared "is it safe to end this session?" guard with two halves:
|
|
12
|
+
|
|
13
|
+
- **The kill half** (`evaluate()`) already knows a commitment goes *stale*. If the topic has had no user message for 8 hours, the commitment is treated as abandoned and no longer keeps the session alive — so an idle session with only a stale promise is correctly reaped. (This staleness rule was added back on 2026-06-06.)
|
|
14
|
+
- **The revive half** (`workEvidence()`) decides whether a killed session had real interrupted *work* worth bringing back. It tags the session with evidence like "a build was running" or "a sub-agent was live" — and, until now, "an open commitment exists."
|
|
15
|
+
|
|
16
|
+
## What this changes
|
|
17
|
+
|
|
18
|
+
One line. The revive half now applies the **same 8-hour staleness gate** the kill half already uses. So an open commitment only counts as "interrupted work worth reviving" while the topic has had a user message within 8 hours.
|
|
19
|
+
|
|
20
|
+
The result: the two halves finally agree. A stale commitment neither keeps a session alive *nor* revives it. A *fresh* commitment keeps the session alive in the first place, so it never needs reviving. The loop's engine — kill (stale) then revive (commitment) — is gone.
|
|
21
|
+
|
|
22
|
+
## Why this is safe
|
|
23
|
+
|
|
24
|
+
It can only ever revive **less**, never more. A session that was genuinely doing work when it died still carries its real work signals (a live build, an active sub-agent, a pending message, a running process) — those are untouched, and a busy session is never age-killed in the first place. The only revivals removed are exactly the harmful ones: an idle session resurrected to "finish" a promise that was already done. Promises still get their own follow-through from the commitment system (the beacon and the overdue-commitment job) — that's the right owner for a promise, not a respawned session burning a fresh turn each time.
|
|
25
|
+
|
|
26
|
+
## What you'll notice
|
|
27
|
+
|
|
28
|
+
Fewer "🪦 your session was shut down — a restart is queued" messages on topics where nothing was actually unfinished. The looping topics (this one included) settle down. Nothing else changes.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Side-Effects Review — ReapGuard stale-commitment revival loop
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `reapguard-stale-commitment-revival-loop`
|
|
4
|
+
**Date:** `2026-06-13`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `general-purpose reviewer subagent (lifecycle change — required)`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
`ReapGuard` (the shared, stateless "is it safe to reap this session?" guard) has two methods that read an open commitment differently. `evaluate()` (the KILL decision) only keeps a session alive on an open commitment while the topic has had a user message within `staleCommitmentWindowMs` (default 8h); past that the commitment is "abandoned" and the idle session is reaped (staleness gate added 2026-06-06). `workEvidence()` (the RESUME-eligibility decision) emitted `open-commitment` evidence for **any** active commitment, with **no** staleness gate. So the same guard killed an idle session (commitment stale ⇒ reap) and immediately tagged it resume-eligible (commitment exists ⇒ revive), looping forever.
|
|
11
|
+
|
|
12
|
+
Evidence (live `logs/reap-log.jsonl`, 2026-06-13): 13 age-limit reaps with `midWork=true`, **all** carrying solely `workEvidence=[open-commitment]`, across 6 topics (multi-channel-support, Resource Limitation Mitigation, instar evolution, Subscription & Auth, instar-exo, Topic UX). The resume queue showed repeated `reason=age-limit` respawn entries, several doubled per topic.
|
|
13
|
+
|
|
14
|
+
The fix: one line in `ReapGuard.workEvidence()` — the `open-commitment` probe now applies the identical predicate `evaluate()` uses (`protectOpenCommitments && activeCommitmentForTopic && recentUserMessage(staleCommitmentWindowMs)`). Files touched: `src/core/ReapGuard.ts` (the probe + a comment), `tests/unit/work-evidence.test.ts` (a new regression `describe` block).
|
|
15
|
+
|
|
16
|
+
## Decision-point inventory
|
|
17
|
+
|
|
18
|
+
- `ReapGuard.workEvidence()` open-commitment probe (`src/core/ReapGuard.ts`) — **modify** — narrows when `open-commitment` is emitted as work evidence to match the KEEP guard's staleness horizon. This is a SIGNAL producer (work evidence consumed by the resume queue / reap-notify), not a blocking authority.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 1. Over-block
|
|
23
|
+
|
|
24
|
+
**What legitimate inputs does this change reject that it shouldn't?**
|
|
25
|
+
|
|
26
|
+
This change narrows a SIGNAL (work evidence), not a block/allow gate. The "over-block" analogue is: does it now suppress `open-commitment` evidence for a session that genuinely had interrupted work? No. To be age-killed at all, a session must be idle-at-prompt with no live processes (the age-gate's `ageGateTrulyIdle` check) — a genuinely-busy session is deferred, never killed. And by the time `workEvidence()` runs as the fallback, `blockedReason()` has already returned null, meaning the commitment was already judged stale (no user message in 8h). A session with real interrupted work carries OTHER evidence (`structural-long-work`, `active-subagent`, `pending-injection`, `active-process`, `main-process-active`) which are untouched. A commitment touched within 8h still emits `open-commitment` (covered by the "FRESH commitment" test). No legitimate revival is lost.
|
|
27
|
+
|
|
28
|
+
## 2. Under-block
|
|
29
|
+
|
|
30
|
+
**What failure modes does this still miss?**
|
|
31
|
+
|
|
32
|
+
The change does not, by itself, drain the 279 already-`pending` commitments that fuel the loop — but it makes them HARMLESS for revival (a stale one no longer revives). A separate, careful runtime hygiene pass to mark genuinely-delivered commitments is tracked: <!-- tracked: topic-18423 --> (operator-visible follow-up on the live machine; not a code deferral). It also does not change the age-limit reaper killing idle sessions — that is correct behavior and out of this fix's scope by design (the loop was the *revival* half, not the kill).
|
|
33
|
+
|
|
34
|
+
## 3. Level-of-abstraction fit
|
|
35
|
+
|
|
36
|
+
**Is this at the right layer?**
|
|
37
|
+
|
|
38
|
+
Yes. `ReapGuard` is the single shared guard both the reaper and the terminate authority consult; aligning its two methods at that one place fixes every killer that uses the `workEvidence()` fallback (the age-limit path does). Putting the staleness logic anywhere downstream (resume queue, reap-notify) would patch one consumer and leave the evidence itself wrong for the others. The correct owner of *promise* follow-through (the commitment beacon / overdue-commitment job) is a different subsystem and is intentionally left to do its job — this fix stops the resume queue from double-covering it on a stale signal.
|
|
39
|
+
|
|
40
|
+
## 4. Signal vs authority compliance
|
|
41
|
+
|
|
42
|
+
**Does this hold blocking authority with brittle logic, or produce a signal that feeds a smart gate?** (ref: `docs/signal-vs-authority.md`)
|
|
43
|
+
|
|
44
|
+
Compliant. `workEvidence()` is a pure SIGNAL producer — observe-only evidence collection. It holds no blocking authority (the KILL authority is `evaluate()`/`blockedReason()`, unchanged). This change makes the existing signal MORE accurate by removing a false-positive; it adds no new brittle check and no new authority.
|
|
45
|
+
|
|
46
|
+
## 5. Interactions
|
|
47
|
+
|
|
48
|
+
**Does it shadow another check, get shadowed, double-fire, race with cleanup?**
|
|
49
|
+
|
|
50
|
+
The two `ReapGuard` methods now use one identical predicate, removing the contradiction that WAS the bug. No race: `workEvidence()` is only collected after `blockedReason()` returned null (a non-null keep returns early at terminateSession before evidence is gathered), so the two never disagree on the same live state. Downstream consumers behave correctly: dropping the sole `open-commitment` signal flips `isMidWork`→false and `evidenceEligible`→false, which correctly prevents (a) `ResumeQueue` enqueue (gated on `evidenceEligible`), (b) the server's live enqueue (gated on `midWork===true`), and (c) boot-reconciliation re-enqueue from the reap-log (also `midWork===true`). The reaper's own idle path supplies authoritative `workEvidence:[]` and is unaffected (it was never the loop's source).
|
|
51
|
+
|
|
52
|
+
## 6. External surfaces
|
|
53
|
+
|
|
54
|
+
**Does it change anything visible to other agents/users/systems?**
|
|
55
|
+
|
|
56
|
+
User-visible: fewer "your session was shut down — a restart is queued" notices on topics with no genuinely-unfinished work; the looping topics settle. Reap-log entries for these reaps now record `midWork:false` (honest — they were idle reaps, not interrupted work). No agent-to-agent or cross-system surface. No new timing/runtime dependency — it reuses the same in-memory `recentUserMessage` dep `evaluate()` already calls.
|
|
57
|
+
|
|
58
|
+
## 7. Multi-machine posture (Cross-Machine Coherence)
|
|
59
|
+
|
|
60
|
+
**Machine-local BY DESIGN.** `ReapGuard` evaluates the LOCAL machine's sessions against that machine's local topic-state deps (topic binding, recent-message, active-commitment). Session reaping is inherently a per-machine operation — a machine reaps its own sessions — so there is no replication path to add and none is wanted. The commitment registry that backs `activeCommitmentForTopic` follows its own (separate) cross-machine story; this change reads it identically to how `evaluate()` already does, so it introduces no new multi-machine assumption. No user-facing notice voice, durable-state-on-transfer, or generated-URL concern applies.
|
|
61
|
+
|
|
62
|
+
## 8. Rollback cost
|
|
63
|
+
|
|
64
|
+
Cheap. Pure code change, no migration, no persisted-state shape change. Back-out = revert the one-line probe to its prior form (`upgrades/eli16/...` + git revert) and ship a patch. The reap-log entries already written are inert historical records. Config knob `staleCommitmentWindowMs: Infinity` independently restores the always-protect behavior for BOTH methods consistently (now that they share the predicate) without a code change, if a site wants the old revival behavior back immediately.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Second-pass review
|
|
69
|
+
|
|
70
|
+
**Reviewer:** independent general-purpose reviewer subagent (required: change touches session lifecycle kill/recovery + a "guard").
|
|
71
|
+
|
|
72
|
+
**VERDICT: Concur with the review.**
|
|
73
|
+
|
|
74
|
+
The reviewer independently audited `ReapGuard.evaluate()`/`workEvidence()`, the `SessionManager.terminateSession` evidence path (lines 825–925), and the new tests, pressure-testing all five risk dimensions:
|
|
75
|
+
|
|
76
|
+
- **A (over-block):** could not construct a genuinely-interrupted session left un-revived; busy sessions never reach the age-kill, and real work carries other evidence.
|
|
77
|
+
- **B (race/consistency):** the two methods now use the identical predicate triple; the benign `recent-user-message`/`open-commitment` independence in `workEvidence()` cannot resurrect the loop (for a stale session both windows are false; workEvidence is recomputed from the same live deps regardless of WHY evaluate cleared).
|
|
78
|
+
- **C (killer-supplied evidence):** grepped every killer supplying explicit `opts.workEvidence` — only the idle-reaper (authoritative `[]`), the operator force-resume (`['active-build-or-autonomous-run']`), and tests. The age-limit path supplies none → uses the patched fallback. The fix reaches the path that actually fired.
|
|
79
|
+
- **D (config edges):** `protectOpenCommitments:false` and `staleCommitmentWindowMs:Infinity` now behave consistently across both methods.
|
|
80
|
+
- **E (downstream):** correctly prevents ResumeQueue enqueue, server live enqueue, AND boot-reconciliation re-enqueue (all `midWork===true`/`evidenceEligible` gated); ReapNotifier reports the idle reap honestly.
|
|
81
|
+
|
|
82
|
+
No concern raised; no design iteration required.
|