instar 1.3.301 → 1.3.303

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,41 @@
1
+ # Side-Effects Review — Lifeline replay drop budget: down-server exemption
2
+
3
+ **Version / slug:** `lifeline-replay-down-server-guard`
4
+ **Date:** `2026-06-05`
5
+ **Author:** `instar-echo`
6
+
7
+ ## Summary
8
+
9
+ In `TelegramLifeline.replayQueue()`, the failure branch's strike increment becomes healthy-gated: `msg.replayFailures = this.supervisor.healthy ? failures + 1 : failures`. A forward that fails while the supervisor reports the server DOWN re-queues the message with its strike count untouched. The drop decision itself (3 strikes → record + degradation report + sender notice) is unchanged.
10
+
11
+ ## Decision-point inventory
12
+
13
+ - Replay strike increment — modified — gated on `this.supervisor.healthy` (the same flag the loop's own stop-replaying branch already consults three lines below; no new state).
14
+ - Drop decision, versionSkewActive exemption, dropped-message notification, queue ordering — untouched.
15
+
16
+ ## Direction of failure
17
+
18
+ - Old failure: systemic down-server failures burned the poison-message budget; head-of-queue messages dropped in ~90s of a multi-minute restart window (39 live records on codey).
19
+ - New behavior: down-window failures are free; messages wait out the outage. Strikes only accrue against a healthy server.
20
+ - Conservative failure direction: messages are KEPT longer. A genuinely poisonous message still accumulates strikes the moment the server is healthy (its delivery failure against a healthy server is precisely the poison signal) and is dropped with the existing loud path.
21
+
22
+ ## Side-effects checklist
23
+
24
+ 1. **Over-keep (message retained that should drop):** a poison message during an outage survives the outage — correct: it then fails 3x against the HEALTHY server and drops via the existing path. Worst case it delays its own drop by the outage length.
25
+ 2. **Under-keep:** none introduced — no path drops earlier than before.
26
+ 3. **Stale-healthy edge:** the supervisor may not yet have noticed a fresh crash, so the first failure after a crash can still increment. Acceptable: the budget is 3 and the guard's job is stopping the systematic burn across a known-down window; the loop's own `!supervisor.healthy` break uses the same flag with the same staleness, keeping the two behaviors consistent.
27
+ 4. **Queue growth:** an extended outage retains messages it previously shredded. Bounded by the queue's existing capacity controls; the alternative (dropping user messages) is the bug.
28
+ 5. **Level-of-abstraction fit:** policy stays inside `replayQueue()` next to the drop decision and the sibling versionSkewActive exemption — one drop policy, one place. No new flags, fields, or config.
29
+ 6. **Signal vs authority:** no LLM; the drop path's loud notification chain is preserved verbatim.
30
+ 7. **Rollback cost:** revert the one-line gate (plus comment + tests). No state migration; dropped-messages.json shape unchanged.
31
+
32
+ ## Scope not taken
33
+
34
+ - No change to MAX_REPLAY_FAILURES (3 remains right for the poison case).
35
+ - No fix for the separate `telegram-forward sentinel pause` limbo (held-not-dropped message on an idle session; ledger issue 38edd8f0, distinct mechanism on the SERVER side — this fix is the LIFELINE side).
36
+ - No retroactive redelivery of already-dropped messages (the ledger + sender notices already cover them).
37
+ - SlackLifeline has its own replay path — audit as a follow-up, not blind-patched here.
38
+
39
+ ## Rollback
40
+
41
+ Revert the commit. Behavior returns to unconditional strike increments.
@@ -0,0 +1,44 @@
1
+ # Side-Effects Review — Mentor tick observability (durable lastResult + tick logging)
2
+
3
+ **Version / slug:** `mentor-tick-observability`
4
+ **Date:** `2026-06-05`
5
+ **Author:** `instar-echo`
6
+
7
+ ## Summary
8
+
9
+ `MentorRunnerServices` gains optional `loadLastResult`/`saveLastResult`; the runner hydrates `lastResult` once at construction and routes all three write paths (disabled short-circuit, success, failure) through one `setLastResult` funnel that persists best-effort. The host (`AgentServer.buildMentorRunner`) wires both to `<stateDir>/mentor-last-result.json` (atomic tmp+rename write; shape-checked, corrupt-tolerant load). `startTick` logs one line on acceptance and one on outcome.
10
+
11
+ ## Decision-point inventory
12
+
13
+ - `MentorRunnerServices.loadLastResult` / `saveLastResult` — added — optional; absent ⇒ byte-for-byte old behavior (in-memory only).
14
+ - `MentorOnboardingRunner.setLastResult` — added — single write funnel; persist failures contained (in-memory value already set).
15
+ - Constructor hydration — added — try/catch contained; corrupt/missing ⇒ null (old start state).
16
+ - `startTick` logging — added — two `console.log` lines per accepted tick; no logging change on the disabled/in-flight short-circuits (they stay quiet — they fire every 15 min when dark and would be log spam).
17
+ - `AgentServer.buildMentorRunner` — modified — wires the two services only when `stateDir` exists; the persist file lives beside the existing `mentor-sent.jsonl` precedent.
18
+
19
+ ## Direction of failure
20
+
21
+ - Old failure: the loop's only outcome record was wiped by every restart; success was silent in logs — "is the mentor alive?" was unanswerable from its own surfaces.
22
+ - New behavior: outcome survives restarts; the log carries the loop's pulse.
23
+ - Conservative failure direction: ALL new I/O is best-effort and contained — a missing stateDir, unreadable file, corrupt JSON, or full disk degrades to exactly the old in-memory behavior, never a crash, never a blocked tick.
24
+
25
+ ## Side-effects checklist
26
+
27
+ 1. **Over-block:** none possible — the change never gates or refuses anything; it records and logs only.
28
+ 2. **Under-block:** none — no authority added. A stale persisted lastResult after config flip-off is possible (file shows an old outcome while disabled writes overwrite it on the next tick POST) — acceptable: the disabled short-circuit itself writes `reason: disabled`, refreshing the file on the very next heartbeat.
29
+ 3. **Level-of-abstraction fit:** the runner owns WHEN to persist (its write funnel); the host owns WHERE/HOW (state-dir path + atomic write) — mirrors the existing `capture`/`deliverToMentee` service split and the `mentor-sent.jsonl` persistence precedent.
30
+ 4. **Signal vs authority compliance:** observability-only; no LLM, no gate. Log lines are signals.
31
+ 5. **Interactions:** the persisted shape is exactly the in-memory `MentorRunResult & { at }` — the status route serializes it identically whether hydrated or fresh. The hydrated value can briefly present a PRIOR generation's outcome after a restart until the next tick overwrites it — that is the feature (it is timestamped via `at`, so staleness is readable).
32
+ 6. **External surfaces:** GET /mentor/status semantics unchanged (same field, now durable). One new state file in the agent state dir. Two new log line shapes (`[mentor] tick accepted…` / `[mentor] tick result…`).
33
+ 7. **Rollback cost:** revert the commit; the state file is ignored by old code (no reader), safe to leave or delete.
34
+
35
+ ## Scope not taken
36
+
37
+ - No fix for the job-session 1-min age-limit race (`expectedDurationMinutes: 1` vs heavy boot) — that is task #14's lean loop-worker territory; this slice makes the symptom DIAGNOSABLE first.
38
+ - No X-Instar-AgentId header fix in the job template (auth deprecation warning) — separate small follow-up.
39
+ - No grounding-config addition for the mentor job (JobLoader audit warning) — separate.
40
+ - No change to tick cadence, gating, budget, or Stage-A/B behavior.
41
+
42
+ ## Rollback
43
+
44
+ Revert the single commit. The runner returns to in-memory-only lastResult and silent successful ticks.