instar 1.3.383 → 1.3.385

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,32 @@
1
+ # ELI16 — Duplicate-Message Suppression
2
+
3
+ ## The problem
4
+
5
+ You flagged it and the logs proved it: the same status message went out to you
6
+ THREE times — two of them byte-for-byte identical, 13.5 minutes apart. That's me
7
+ sending the same thing twice, which is exactly as annoying as it sounds.
8
+
9
+ Why did the existing safeguards miss it? There was a guard that catches "the
10
+ exact same send retried" — but these were two SEPARATE sends with the same
11
+ words, 13 minutes apart, so it didn't count them as the same. And the smarter
12
+ content-check was being skipped on the very paths these went through (status
13
+ relays, cross-machine).
14
+
15
+ ## What this fixes
16
+
17
+ I added a dead-simple, reliable check right where messages go out: if I'm about
18
+ to send you the SAME message text in the SAME topic that I already sent in the
19
+ last ~15 minutes, the repeat is dropped — you just don't get pinged twice. The
20
+ first one still goes through normally.
21
+
22
+ It's deliberately careful so it never over-corrects:
23
+ - **Short acks are exempt.** If you send me two things and I reply "Got it" to
24
+ both, you still see both — only longer, substantial messages get deduped.
25
+ - **Per-conversation.** The same text in a different topic still sends.
26
+ - **I can force a repeat** when I genuinely mean to (rare) with an explicit flag.
27
+ - **A failed send isn't remembered**, so a real retry of something that didn't
28
+ go through is never swallowed.
29
+
30
+ Tested both ways: identical status 13 min apart → second one dropped; two
31
+ different messages → both sent; two short acks → both sent; cross-topic → sent.
32
+ Run through the real send path, not just in isolation.
@@ -0,0 +1,79 @@
1
+ # Side-Effects Review — Outbound Content-Dedup
2
+
3
+ **Version / slug:** `outbound-content-dedup`
4
+ **Date:** `2026-06-06`
5
+ **Author:** `Echo (instar-dev agent — Justin: "We really need to work on not sending duplicate messages. Let's make this much more robust.")`
6
+ **Second-pass reviewer:** `self-adversarial pass over the one real risk — suppressing a message the user actually needed`
7
+
8
+ ## Summary of the change
9
+
10
+ A pure `OutboundContentDedup` (per-topic, windowed, length-gated content
11
+ fingerprint) wired at the `/telegram/reply` route, after the delivery-id LRU and
12
+ before the tone gate. An identical long message to the same topic within ~15min
13
+ is suppressed (200, not re-sent); the first send still goes. Files:
14
+ `OutboundContentDedup.ts` (new), `routes.ts` (instance + check/record),
15
+ `PostUpdateMigrator.ts` (CLAUDE.md note), 3 test files.
16
+
17
+ ## Decision-point inventory
18
+
19
+ - content-dedup check — **add (suppress)** — before the send.
20
+ - length floor (minLength 40) — **add** — brief acks always pass.
21
+ - `allowDuplicate` bypass — **reuse (existing metadata)** — caller can force a repeat.
22
+ - record-after-success — **deliberate** — a failed send's retry isn't lost.
23
+
24
+ ## 1. Over-block (the real risk — suppressing a wanted message)
25
+
26
+ The danger is dropping a message the user needed. Defenses, each tested:
27
+ - **Length floor:** brief acks (the most common legitimate repeat — two "Got it"
28
+ for two user messages) are exempt (test: "brief acks never suppressed").
29
+ - **Per-topic:** the same text to a different topic sends (tested).
30
+ - **`allowDuplicate` escape hatch:** a caller that means to repeat bypasses it
31
+ (tested).
32
+ - **Record-after-success:** a send that throws is never recorded, so its
33
+ legitimate retry (same content, new id) is not suppressed.
34
+ - **Scope = `/telegram/reply` only:** command responses (bot command handler) and
35
+ sentinel/standby sends go through other paths and are untouched, so a user
36
+ re-running a command still gets fresh output.
37
+ Residual: a caller that legitimately re-sends the EXACT same ≥40-char text to the
38
+ SAME topic within 15min without `allowDuplicate` is suppressed — which is exactly
39
+ the reported bug, and the escape hatch covers the rare intentional case.
40
+
41
+ ## 2. Under-block
42
+
43
+ Near-duplicates (reworded status, e.g. the 21:15 variant in the incident) are
44
+ NOT caught — only byte-identical (whitespace-normalized) text. Catching
45
+ semantic near-dups would require an LLM and risks false suppression; the
46
+ deterministic exact-match is the safe, robust core. The reworded-variant case is
47
+ a separate, lower-frequency concern.
48
+
49
+ ## 3. Level-of-abstraction fit
50
+
51
+ The dedup is a pure module in `messaging/`, instantiated once per route
52
+ construction beside the existing delivery-id LRU (same lifecycle, same
53
+ chokepoint). It reuses the route's existing `allowDuplicate` metadata contract.
54
+
55
+ ## 4. Signal vs authority compliance
56
+
57
+ **Required reference:** `docs/signal-vs-authority.md`
58
+
59
+ - [x] Deterministic guard, no LLM. It removes a redundant send; it never alters
60
+ content and never blocks a non-duplicate. The `allowDuplicate` hatch preserves
61
+ caller authority for intentional repeats. Strictly subtractive on exact dups.
62
+
63
+ ## 5. Interactions
64
+
65
+ - **Delivery-id LRU:** complementary — id-dedup catches a re-POST of the same id;
66
+ content-dedup catches a fresh-id re-send of the same text. Runs after it.
67
+ - **Tone gate:** the content-dedup runs BEFORE it (so a duplicate skips the LLM
68
+ call entirely) and independent of it (covers the proxy/relay paths the gate
69
+ skips).
70
+ - **Tokenless-standby relay:** unaffected — the dedup decides before the send;
71
+ the relay still carries the real messageId on a non-duplicate.
72
+
73
+ ## 6. External surfaces / 7. Rollback
74
+
75
+ New response field `suppressedDuplicate: true` on a suppressed `/telegram/reply`
76
+ (additive; callers `.catch`/ignore the body today). Optional config
77
+ `outboundContentDedup` (window/minLength/maxPerTopic/enabled) with safe
78
+ defaults; absent ⇒ defaults. One idempotent CLAUDE.md note. Rollback = revert;
79
+ duplicates flow again.
@@ -0,0 +1,58 @@
1
+ # Side-Effects Review — Peer quota propagation (finding A2)
2
+
3
+ **Version / slug:** `peer-quota-propagation`
4
+ **Date:** `2026-06-06`
5
+ **Author:** `echo`
6
+ **Second-pass reviewer:** `not required`
7
+
8
+ ## Summary of the change
9
+
10
+ The peer's `quotaState` (already in its session-status response via
11
+ getCapacity(self)) was parsed away on the receive side — same narrowing bug as
12
+ the #931 commitmentsAdvert drop. Now carried through `fetchPeerCapacity` ->
13
+ `PeerCapacity` -> `PeerPresencePuller.recordHeartbeat` -> pool registry, so the
14
+ router sees a peer's quota and quota-aware placement (#804) can avoid a
15
+ rate-limited peer (the original EXO failure).
16
+
17
+ ## Decision-point inventory
18
+
19
+ One: carry the field or not. Carried, additively, with absent = not blocked.
20
+
21
+ ## 1. Over-block
22
+
23
+ A correctly-reported `blocked:true` peer is now AVOIDED by placement where
24
+ before it was silently chosen. That is the intended behavior, not over-block:
25
+ the data is the peer's own self-report (the gemini quota-conflation lesson —
26
+ never another machine's file; this is the peer asserting its OWN state).
27
+
28
+ ## 2. Under-block
29
+
30
+ An old peer that omits quotaState still reads as not-blocked (fail-open,
31
+ unchanged) — no regression, just no improvement for un-upgraded peers.
32
+
33
+ ## 3. Level-of-abstraction fit
34
+
35
+ The field travels the SAME path the commitmentsAdvert/journalAdvert already
36
+ travel (session-status -> fetchPeerCapacity -> puller). No new transport, no
37
+ new endpoint. The serving side already emitted it (getCapacity spread).
38
+
39
+ ## 4. Signal vs authority compliance
40
+
41
+ **Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
42
+
43
+ Placement remains advisory + fail-open: a hard pin still wins
44
+ (pinned-machine-quota-blocked), all-blocked proceeds least-loaded. This change
45
+ only feeds the existing decision real peer data.
46
+
47
+ ## 5. Interactions
48
+
49
+ - #804 quota-aware placement: the consumer — now has peer data.
50
+ - A1 (collector hoist): the producer — together they make placement real.
51
+ - gemini quota-conflation lesson: respected — this is the peer's OWN
52
+ self-report carried verbatim, never this machine reading another's file.
53
+ - Old peers: forward/backward compatible (optional field).
54
+
55
+ ## 6. External surfaces
56
+
57
+ `GET /pool` now populates a peer's `quotaState` (was always null for peers).
58
+ No new routes/config/notifications.