instar 1.3.335 → 1.3.337

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,45 @@
1
+ # ELI16 — AUP-Rejection Wedge Signature + Fresh-Respawn API
2
+
3
+ ## What happened
4
+
5
+ Last night one of my sessions died in a new way. Justin and the session had
6
+ been designing security test scenarios (deliberately-sneaky "try to trick the
7
+ agent" prompts, for the EXO 3.0 test harness). Enough of that content piled up
8
+ in the conversation that the AI provider's safety filter started refusing the
9
+ ENTIRE conversation — every single reply came back "this request appears to
10
+ violate our Usage Policy." Since each reply re-sends the whole conversation,
11
+ every reply failed, forever. From Justin's side it looked like me ignoring him
12
+ for an hour: "✓ Delivered" receipts, no answers.
13
+
14
+ The watchdog that's supposed to catch dead-but-still-printing sessions (the
15
+ ContextWedgeSentinel) only knew ONE death signature — the "thinking block"
16
+ error from May. This new one sailed right past it. And the only repair lever —
17
+ "restart fresh, do NOT reload the poisoned conversation" — existed solely
18
+ inside the watchdog's own wiring, so fixing it by hand meant editing a state
19
+ file directly.
20
+
21
+ ## What this change does
22
+
23
+ 1. **Teaches the watchdog the second signature.** It now recognizes the
24
+ policy-rejection loop too, and the audit log says WHICH kind of wedge it
25
+ caught. Safety detail: one single policy rejection is NOT treated as a
26
+ wedge — sometimes one message just gets refused and the next works fine,
27
+ and killing the conversation for that would destroy real state. The loop
28
+ version always repeats, so we require seeing it more than once.
29
+
30
+ 2. **Adds the repair lever to the API.** `POST /sessions/refresh` now accepts
31
+ `"fresh": true` — restart this session WITHOUT reloading its conversation.
32
+ That's the right move whenever a transcript itself is poisoned.
33
+
34
+ 3. **Tells every deployed agent about it.** The CLAUDE.md migration adds the
35
+ new signature, the API lever, and the prevention rule: keep literal attack
36
+ payloads in files on disk and reference them by path — never paste them
37
+ into the conversation itself.
38
+
39
+ ## Why it's safe
40
+
41
+ Detection alone never kills anything (auto-recovery stays opt-in, unchanged).
42
+ The one-off-vs-loop distinction is tested on both sides with the real pane
43
+ text from the incident. The API param is validated, rate-guarded by the same
44
+ limiter every refresh uses, and reuses the exact internal mode the sentinel
45
+ already exercised in production twice this week.
@@ -0,0 +1,83 @@
1
+ # Side-Effects Review — AUP-Rejection Wedge Signature + Fresh-Respawn API
2
+
3
+ **Version / slug:** `aup-wedge-fresh-api`
4
+ **Date:** `2026-06-06`
5
+ **Author:** `Echo (instar-dev agent, session-robustness topic per Justin's "work on more robust ways to handle these scenarios")`
6
+ **Second-pass reviewer:** `self-adversarial pass over the one-off-vs-loop boundary (the only place this change could destroy user state)`
7
+
8
+ ## Summary of the change
9
+
10
+ ContextWedgeSentinel learns a second wedge-signature family — the AUP-rejection
11
+ loop (2026-06-05 EXO incident) — via `classifyWedgeTail()`, which returns the
12
+ matching family for the live tail and tags every event/escalation with `kind`.
13
+ The AUP family requires the signature on >1 line of the capture (the loop
14
+ repeats every turn; a benign one-off rejection appears once). `POST
15
+ /sessions/refresh` forwards a validated `fresh` boolean to
16
+ `SessionRefresh.refreshSession` — the previously-internal-only fresh-mode.
17
+ CLAUDE.md migrator patch teaches deployed agents both additions. Files:
18
+ `ContextWedgeSentinel.ts`, `server.ts` (wiring detail strings), `routes.ts`,
19
+ `PostUpdateMigrator.ts`, spec doc, three test files.
20
+
21
+ ## Decision-point inventory
22
+
23
+ - AUP tail classification — **add (detector)** — new signal only; same confirm
24
+ window + same opt-in recovery policy as the existing family.
25
+ - One-line AUP occurrence — **deliberate non-detection** — a benign one-off
26
+ rejection must never cost a session its conversation; the wedge always
27
+ repeats, so the second occurrence arrives within one failed turn.
28
+ - `fresh` route param — **add (lever, validated)** — exposes an existing
29
+ internal mode; same spawnLimiter + SessionRefresh rate-guard as every
30
+ refresh.
31
+
32
+ ## 1. Over-block
33
+
34
+ None added. Detection alone never kills anything (autoRecovery ships dark,
35
+ unchanged). The worst over-detection case — a session DISCUSSING the AUP error
36
+ with two quoted copies in its tail — is covered by the same two defenses as the
37
+ thinking-block family (tail gate + 45s no-progress confirm window): a working
38
+ session scrolls the signature out before confirm.
39
+
40
+ ## 2. Under-block
41
+
42
+ (a) A genuinely-wedged session whose FIRST rejection is the only one on screen
43
+ is not detected until the next inbound message produces the second copy —
44
+ bounded by one message turn; accepted to protect one-off conversations.
45
+ (b) A wedge whose error text the provider rewords escapes both families —
46
+ inherent to signature-based detection; the turn-receipt structural close is
47
+ tracked separately (CMT-1115 follow-up design).
48
+
49
+ ## 3. Level-of-abstraction fit
50
+
51
+ The family lives inside the existing sentinel (same lifecycle, confirm window,
52
+ recovery, veto integration) rather than a 5th sentinel — the failure shape is
53
+ identical; only the signature differs. `kind` is data on existing events, not
54
+ a new event vocabulary. The route param reuses `RefreshOptions.fresh` which
55
+ SessionRefresh already owned; the route stays a thin validated entry point.
56
+
57
+ ## 4. Signal vs authority compliance
58
+
59
+ **Required reference:** `docs/signal-vs-authority.md`
60
+
61
+ - [x] No new authority. The detector is a signal; recovery policy (detect-only
62
+ / dry-run / live) is unchanged and opt-in. The `fresh` param is operator/agent
63
+ initiative through an already-rate-guarded lever; the route grants no new
64
+ capability that the sentinel wiring didn't already exercise.
65
+
66
+ ## 5. Interactions
67
+
68
+ - **SessionReaper veto:** `isRecoveryActive` covers AUP wedges identically
69
+ (state machine is shared) — the reaper can't kill a session mid-recovery.
70
+ - **Sentinel audit:** `kind` lands in `logs/sentinel-events.jsonl` detail
71
+ strings; existing consumers parse free-text detail, no schema break.
72
+ - **`fresh` + followUpPrompt:** unchanged interaction — fresh clears the resume
73
+ entry after the kill persists it; respawner then spawns clean (SessionRefresh
74
+ ordering, already tested).
75
+ - **Back-compat:** `signatureIsTail()` boolean wrapper preserved — all existing
76
+ callers/tests pass unmodified (81 green pre-existing + new).
77
+
78
+ ## 6. External surfaces / 7. Rollback
79
+
80
+ One new accepted body field on an existing authed route (400 on non-boolean);
81
+ response gains `fresh` echo. No schema/config/persistent state; migrator patch
82
+ is append-only + idempotent (marker: 'AUP-rejection wedge'). Rollback = revert;
83
+ the second family goes blind again and fresh-respawn returns to internal-only.
@@ -0,0 +1,43 @@
1
+ # Side-Effects Review — Sibling-Transport Brakes
2
+
3
+ **Version / slug:** `sibling-transport-brakes`
4
+ **Date:** `2026-06-06`
5
+ **Author:** `Echo (instar-dev agent, autonomous session per Justin's direction)`
6
+ **Second-pass reviewer:** `focused adversarial reviewer subagent — CONCUR on all four probes (the #874 pattern itself carries tonight's line-level CONCUR)`
7
+
8
+ ## Summary of the change
9
+
10
+ The #874 brake pattern applied verbatim to the two remaining mesh transports: `HttpLiveTailTransport` and `ReplyMarkerTransport` get `AbortSignal.timeout` (30s default, the #874-corrected sizing above the fleet's 5–40s receiver-stall envelope) on their fetches, and `PeerFailureLogGate` state-change failure logging (live-tail N=360; reply-marker N=50 for reply cadence) replacing per-attempt lines, with non-ok responses now gated-logged. Files: both transports, one test file.
11
+
12
+ ## Decision-point inventory
13
+
14
+ - Both transports' `broadcast()` — **modify (bounded)** — same requests, same return semantics; failures abort at the timeout instead of hanging; logging gated.
15
+
16
+ ## 1. Over-block / 2. Under-block
17
+
18
+ (a) A 30s abort can drop a reply-marker a slower wait might have delivered — widening the marker's documented Two-Generals residual. Reviewer-traced: `broadcast()`'s return is void-discarded at its ONLY callsite (fire-and-forget by design); provider redelivery + the dedup gate + git-committed ledger state are the explicit backstops. Pre-accepted, not new risk. (b) Perfectly alternating ok/fail logs one transition pair per cycle — at reply cadence this is bounded and is diagnostic signal for a genuinely unstable peer (reviewer: not a blocker; an across-resets suppressor would mask real instability). (c) A local `encryptFor` throw logs under the peer's key — imprecise label, but the error detail (the real exception message) disambiguates and the operational meaning ("this peer's flush did not deliver") is identical. (d) Remaining audit item is the SessionRouter design <!-- tracked: CMT-1109 -->.
19
+
20
+ ## 3. Level-of-abstraction fit / 4. Signal vs authority
21
+
22
+ Brakes in the transports that generate the cost; cadence stays with callers; reuses the canonical gate class rather than re-implementing. **Signal-only** per `docs/signal-vs-authority.md`: log shaping + failure-timing bounds. Critically verified: neither transport feeds lease renewal/suspend (`.isReachable()`'s only src consumer is `LeaseCoordinator` via the LEASE transport) — the #874 reviewer's false-self-suspend concern structurally cannot apply here.
23
+
24
+ ## 5. Interactions
25
+
26
+ - **Exactly-once (the marker's job):** unchanged — the timeout affects only the best-effort fast path; the dedup gate and ledger sync carry correctness (reviewer probe 1).
27
+ - **#867's per-topic backoff:** composes — backoff bounds live-tail attempt RATE per topic; the gate bounds LOG volume per peer across topics.
28
+ - **Old format pins:** none — pre-existing transport suites pass untouched.
29
+ - **Node engines / AbortSignal-vs-test-clocks:** identical to #874 (verified there; same package.json).
30
+
31
+ ## 6. External surfaces / 7. Rollback
32
+
33
+ Logs only; no API/schema/config/persistent state; no migration (in-code defaults). Rollback = revert; the hang exposure and per-attempt logging return.
34
+
35
+ ## Conclusion
36
+
37
+ Completes the mesh-transport brake set: all four cross-machine wires (lease #874, heartbeat #881, live-tail and reply-marker here) now carry P19's brakes. Mechanical extension of a twice-validated pattern, with the one novel risk (marker-drop under timeout) traced to a documented, backstopped design acceptance.
38
+
39
+ ---
40
+
41
+ ## Phase 5 — Second-pass review (cross-machine exactly-once adjacency → performed)
42
+
43
+ A focused adversarial pass probed only what is novel beyond #874's reviewed pattern: (1) the Two-Generals widening from a 30s marker abort — traced `broadcast()`'s only callsite (void-discarded, fire-and-forget, comment-documented backstops): pre-accepted by design; (2) gate key granularity + alternating ok/fail behavior — peer-bounded memory, transition chatter acceptable-and-diagnostic at reply cadence; (3) local `encryptFor` throws misattributed to the peer — disambiguated by the error detail, operationally equivalent; (4) ran the new + pre-existing transport suites (15/15) and tsc (clean). **Verdict: CONCUR.**