instar 1.3.164 → 1.3.165

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.164",
3
+ "version": "1.3.165",
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-05-31T11:18:35.637Z",
5
- "instarVersion": "1.3.164",
4
+ "generatedAt": "2026-05-31T11:39:31.391Z",
5
+ "instarVersion": "1.3.165",
6
6
  "entryCount": 193,
7
7
  "entries": {
8
8
  "hook:session-start": {
@@ -0,0 +1,47 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What to Tell Your User
7
+
8
+ If you run your agent across more than one machine and move a conversation to another
9
+ one, that conversation can now reply to you — its replies are relayed through the
10
+ machine that owns your messaging bot, so you hear back without any risk of the two
11
+ machines clashing over the bot. Only relevant when the multi-machine session pool is
12
+ on; single-machine agents are unaffected. Nothing to configure.
13
+
14
+ ## Summary of New Capabilities
15
+
16
+ - `TelegramAdapter` gains an `outboundRelay` hook. When the adapter has no bot token,
17
+ `sendToTopic` routes the send through it (the server wires it to POST the
18
+ Telegram-owning lease holder's `/telegram/reply`), instead of failing silently. A
19
+ token-holding adapter sends directly as before; a relay that can't deliver throws
20
+ rather than dropping the message.
21
+
22
+ ## Evidence
23
+
24
+ - Found live: the backup machine's Telegram adapter had no bot token, so a moved
25
+ session's reply was sent with no token and silently vanished.
26
+ - Unit, `tests/unit/TelegramAdapter.test.ts`: a tokenless adapter routes the send
27
+ through the relay (the Telegram API is not hit, the relayed id is returned); a
28
+ token-holding adapter sends directly and never consults the relay; a relay that
29
+ returns nothing throws instead of silently dropping the reply.
30
+ - 19 TelegramAdapter tests pass; tsc --noEmit clean.
31
+ - Spec, `docs/specs/standby-telegram-outbound-relay.md` plus the .eli16.md sibling.
32
+ - Side-effects, `upgrades/side-effects/standby-telegram-outbound-relay.md`.
33
+
34
+ ## What Changed — a conversation moved to your other machine can now reply to you
35
+
36
+ The final piece of the multi-machine "move this conversation to my other machine"
37
+ feature. Telegram only allows one program to use a given bot at a time, so in a
38
+ two-machine setup only the main machine holds the bot, and the backup deliberately
39
+ holds none (to avoid two programs fighting over the same bot — a real failure we fixed
40
+ earlier). That meant a conversation moved to the backup machine could run there but
41
+ couldn't actually send a reply — it came out silent.
42
+
43
+ This release adds a relay: when the backup machine wants to reply but has no bot, it
44
+ hands the message to the machine that does hold the bot, which sends it normally. So
45
+ your reply comes through, and there's still only ever one program using the bot — no
46
+ fighting, no duplicate messages. A machine that holds its own bot is completely
47
+ unaffected.
@@ -0,0 +1,100 @@
1
+ # Side-Effects Review — Tokenless standby Telegram outbound relay (bug #7)
2
+
3
+ **Version / slug:** `standby-telegram-outbound-relay`
4
+ **Date:** `2026-05-31`
5
+ **Author:** `echo`
6
+ **Second-pass reviewer:** `not required`
7
+
8
+ ## Summary of the change
9
+
10
+ `TelegramAdapter` gains a settable `outboundRelay` callback. In `sendToTopic`, when
11
+ the adapter has NO bot token AND a relay is wired, the send routes through the relay
12
+ instead of the Telegram API (the relayed id feeds the same log/stall/promise
13
+ bookkeeping); a relay returning null throws. `server.ts` wires the relay to POST the
14
+ lease holder's `/telegram/reply/:topicId` (Bearer authToken + the holder's peer URL),
15
+ refusing to relay to self/unknown. Closes bug #7 (a session moved to a tokenless
16
+ standby was mute).
17
+
18
+ ## Decision-point inventory
19
+
20
+ - **sendToTopic branch** — `!this.config.token && this.outboundRelay` → relay; else →
21
+ the unchanged API path. Both covered by tests.
22
+ - **relay closure** — `holder` is self or unknown, or no URL → return null (no
23
+ relay); else POST and return the id (or null on non-ok / throw). Self-relay guard
24
+ + null-on-failure tested via the adapter-level null case.
25
+
26
+ ## 1. Over-block
27
+
28
+ **What legitimate inputs does this reject?** Nothing for a token-holding machine — its
29
+ send path is byte-identical (the relay branch is skipped). For a tokenless standby, a
30
+ send that previously failed silently (no token) now either relays successfully or
31
+ throws a clear error (better than the silent mute). No legitimate send is dropped.
32
+
33
+ ## 2. Under-block
34
+
35
+ **What does this still miss?** It does not sync conversation CONTEXT to the moved
36
+ session (audit #2 — the reply may lack prior history). It relays to the current lease
37
+ holder only (correct for the single-Telegram-owner model); if the holder is
38
+ unreachable it returns null → `sendToTopic` throws (surfaced, not silent). It does not
39
+ retry/queue a failed relay (the caller/​session sees the throw); a durable relay queue
40
+ is possible later but out of scope.
41
+
42
+ ## 3. Level-of-abstraction fit
43
+
44
+ **Right layer?** Yes. The send decision lives in `TelegramAdapter.sendToTopic` (the
45
+ one outbound chokepoint), expressed as an injected callback (same pattern as the
46
+ adapter's other `on*` hooks). The cross-machine resolution (holder → URL → POST) lives
47
+ in `server.ts` where the mesh/coordinator/authToken are already in scope. The relay
48
+ reuses the existing `/telegram/reply` route rather than a new mesh command.
49
+
50
+ ## 4. Signal vs authority compliance
51
+
52
+ **Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
53
+
54
+ No new blocking authority. It changes HOW a tokenless adapter sends (relay vs direct),
55
+ not WHETHER. It preserves the single-Telegram-owner safety invariant (the standby
56
+ never sends on the bot directly), which is the 409-conflict guard — strengthening, not
57
+ weakening, a safety property.
58
+
59
+ ## 5. Interactions
60
+
61
+ The relay POSTs the holder's `/telegram/reply` — the same route used for normal
62
+ replies — so the message goes out the one bot the holder owns; no second poller/sender
63
+ (no 409). Pairs with the lease coordinator (`getSyncStatus().leaseHolder` picks the
64
+ target) and peer presence (`peerUrl`). On a token-holding router the callback is wired
65
+ but never invoked. Idempotent per call; a failed relay throws (the session's reply
66
+ attempt errors rather than silently vanishing).
67
+
68
+ ## 6. External surfaces
69
+
70
+ One cross-machine HTTP POST from a tokenless standby to the holder's existing
71
+ `/telegram/reply` (Bearer-authed). No new route, config, or notification. The visible
72
+ effect: a moved session's replies reach the user (via the holder's bot).
73
+
74
+ ## 7. Rollback cost
75
+
76
+ Low. Remove the `outboundRelay` callback + the `sendToTopic` branch + the wiring; a
77
+ tokenless standby's sends revert to silent failure (bug #7). No schema, no state, no
78
+ migration (the callback is in-memory, default null).
79
+
80
+ ## Conclusion
81
+
82
+ Minimal, injected-callback change scoped to the tokenless-send path, reusing the
83
+ existing reply route, preserving the single-owner 409-guard, both branches + the
84
+ null-failure case unit-tested, no change for token-holding machines, cheap revert.
85
+ The completion gate for the live transfer — a moved session can now reply.
86
+
87
+ ## Second-pass review (if required)
88
+
89
+ Not required — scoped to the no-token send path, reuses a battle-tested route,
90
+ strengthens (not weakens) the single-owner invariant, both branches + failure tested,
91
+ reversible. The live two-machine re-test (a reply landing) is the Tier-3 gate.
92
+
93
+ ## Evidence pointers
94
+
95
+ - `tests/unit/TelegramAdapter.test.ts` — tokenless adapter relays (API not hit, relayed
96
+ id returned); token-holding adapter sends directly (relay not consulted); relay→null
97
+ throws (no silent mute).
98
+ - 19 TelegramAdapter tests green; `tsc --noEmit` clean.
99
+ - Found live: mini telegram adapter `botToken=MISSING` → a moved session's reply muted.
100
+ - Spec: `docs/specs/standby-telegram-outbound-relay.md` (+ `.eli16.md`).