instar 1.3.253 → 1.3.255

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,63 @@
1
+ # Side effects — quick-tunnel captures cloudflared stderr (429 detection)
2
+
3
+ ## What was broken
4
+
5
+ `CloudflareQuickProvider` (the Tier-1 zero-config quick tunnel) classified
6
+ failures via `classifyError(msg, stderr)`, whose rate-limit branch checks the
7
+ text for `429` / `1015` / "rate limit" / "too many requests". But the provider
8
+ listened only to the cloudflared wrapper's `url` / `error` / `exit` events — it
9
+ **never listened to the wrapper's `stderr` event**, which is the only place
10
+ cloudflared's real stderr (including the `429 Too Many Requests` / `error code
11
+ 1015` rate-limit line) is delivered. So `stderrTail` stayed empty, `exit` logged
12
+ the opaque `process-exit code 1: no stderr captured`, and the 429 branch was
13
+ **dead code on the exit path** — the manager could never recognize (or back off
14
+ on / surface) a Cloudflare rate-limit.
15
+
16
+ Found live (2026-05-31): a quick-tunnel start hit Cloudflare 429, but instar
17
+ surfaced only "process-exit code 1: no stderr captured"; the 429 was visible
18
+ only by running `cloudflared tunnel --url` directly.
19
+
20
+ ## The fix
21
+
22
+ 1. `CloudflareQuickProvider.startInner` now registers
23
+ `tunnel.on('stderr', (data) => { stderrTail = (stderrTail + ' ' + data).slice(-2000); })`,
24
+ capturing cloudflared's real stderr (bounded to the last 2000 chars). The
25
+ existing `error`/`exit` handlers already feed `stderrTail` into the
26
+ classifier, so the 429/1015 text now reaches it.
27
+ 2. The classification logic is extracted to a pure, exported
28
+ `classifyQuickTunnelError(msg, stderr)` (unchanged behavior), so the
29
+ decision boundary is unit-testable.
30
+
31
+ ## Who is affected
32
+
33
+ - **Any agent with a quick tunnel that hits Cloudflare 429** (the free
34
+ trycloudflare service rate-limits under load): the failure is now classified
35
+ `rate-limited:` instead of opaque `process-exit`, so the TunnelManager's
36
+ failure handling (per the tunnel-failure-resilience spec) acts on the correct
37
+ reason. No behavior change on the success path or for non-rate-limited
38
+ failures (those classify exactly as before).
39
+
40
+ ## Blast radius
41
+
42
+ - 1 source file: `src/tunnel/CloudflareQuickProvider.ts` (one added event
43
+ listener + a pure-function extraction). No config, no schema, no migration —
44
+ picked up by existing agents on the normal dist update. The TunnelManager,
45
+ other providers, and the success path are untouched.
46
+
47
+ ## Failure modes considered
48
+
49
+ - **Listener fires after resolution?** Harmless — it only appends to a bounded
50
+ buffer; once `url` resolves, the buffer is unused.
51
+ - **stderr never arrives (true silent exit)?** Behavior is exactly as before:
52
+ `stderrTail` empty → `exit` logs "no stderr captured" → classified generic.
53
+ The fix can only ADD signal, never remove it.
54
+ - **Buffer growth?** Bounded to the last 2000 chars via `.slice(-2000)`.
55
+
56
+ ## Tests
57
+
58
+ `tests/unit/CloudflareQuickProvider.test.ts` (6): `classifyQuickTunnelError`
59
+ across 429/1015/"too many requests"/"rate limit", ENOENT→binary-missing,
60
+ DNS/ECONNREFUSED→network, and unrecognized→preserved; plus a mock-`cloudflared`
61
+ test proving the new `stderr` listener feeds a 429 stderr line into the
62
+ classifier so `start()` rejects `rate-limited` (rather than the opaque
63
+ `process-exit`). `tsc --noEmit` clean.
@@ -0,0 +1,147 @@
1
+ # Side-Effects Review — Telegram inbound files under project dir
2
+
3
+ **Version / slug:** `telegram-inbound-project-dir`
4
+ **Date:** `2026-06-04`
5
+ **Author:** `instar-codey`
6
+ **Second-pass reviewer:** `not run — sub-agent tool requires an explicit delegation request in this session`
7
+
8
+ ## Summary of the change
9
+
10
+ Long Telegram inbound payload files and Telegram auto-spawn context files move
11
+ from `/tmp/instar-telegram` to `<projectDir>/.instar/telegram-inbound` through a
12
+ single helper, `getTelegramInboundDir(projectDir)`. Runtime callsites updated:
13
+ `src/core/SessionManager.ts`, `src/commands/server.ts`, and
14
+ `src/server/routes.ts`. The cleanup function now targets the same project-local
15
+ directory, `.gitignore` excludes it, and focused tests assert that long-message
16
+ files land under the configured project directory and that injected references
17
+ point there.
18
+
19
+ ## Decision-point inventory
20
+
21
+ - Telegram long-message file redirect in `SessionManager.injectTelegramMessage`
22
+ — modify — same threshold and same injected reference shape, but the backing
23
+ file path is project-local.
24
+ - Telegram bootstrap/context side-file creation in `src/commands/server.ts` and
25
+ `src/server/routes.ts` — modify — same session spawn behavior, but side files
26
+ are readable from sandboxed project workspaces.
27
+ - `cleanupTelegramTempFiles` — modify — same 7-day file-only cleanup policy, but
28
+ applied to the new project-local inbound directory.
29
+ - No new block/allow authority is added.
30
+
31
+ ---
32
+
33
+ ## 1. Over-block
34
+
35
+ No block/allow surface — over-block not applicable. This change does not reject
36
+ messages, users, topics, sessions, or actions.
37
+
38
+ ---
39
+
40
+ ## 2. Under-block
41
+
42
+ No block/allow surface — under-block not applicable. Remaining failure modes:
43
+ if the configured `projectDir` is wrong, inbound files will consistently be
44
+ written under that wrong project. That is not newly introduced by this change;
45
+ the same config value already controls session startup, state paths, and other
46
+ project-local behavior. If a sandbox denies `.instar/telegram-inbound` despite
47
+ allowing the project root, the agent would still receive an unreadable reference,
48
+ but that would indicate a broader sandbox/config mismatch.
49
+
50
+ ---
51
+
52
+ ## 3. Level-of-abstraction fit
53
+
54
+ The helper belongs in the shared messaging layer because the path is a Telegram
55
+ messaging primitive used by both core session injection and server-side
56
+ Telegram auto-spawn routes. It is not a policy gate and should not live in
57
+ `SessionManager` alone, because route code also writes context side files. It is
58
+ also not a config migration: this is transient runtime storage derived from the
59
+ already-required project directory.
60
+
61
+ ---
62
+
63
+ ## 4. Signal vs authority compliance
64
+
65
+ **Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
66
+
67
+ **Does this change hold blocking authority with brittle logic?**
68
+
69
+ - [ ] No — this change produces a signal consumed by an existing smart gate.
70
+ - [x] No — this change has no block/allow surface.
71
+ - [ ] Yes — but the logic is a smart gate with full conversational context (LLM-backed with recent history or equivalent).
72
+ - [ ] Yes, with brittle logic — STOP. Reshape the design. Brittle detectors must not own block authority.
73
+
74
+ This is a storage-location change for already accepted Telegram payloads. It
75
+ does not inspect message meaning, classify user intent, block delivery, or
76
+ filter content.
77
+
78
+ ---
79
+
80
+ ## 5. Interactions
81
+
82
+ - **Shadowing:** no gate is shadowed. Existing InputGuard and topic/session
83
+ routing still run before message injection and are untouched.
84
+ - **Double-fire:** no new writer is added; existing writers now call the shared
85
+ helper. The same message creates the same one payload file as before.
86
+ - **Races:** cleanup still removes only files older than 7 days. It now shares
87
+ the same directory helper as the writers, reducing drift. The cleanup window
88
+ is far longer than any active read window, so it should not race fresh
89
+ inbound messages.
90
+ - **Feedback loops:** the injected path is read by the receiving agent. Moving
91
+ the file under `.instar/telegram-inbound` changes the path text the agent
92
+ sees, but does not feed back into routing, dedup, or gate decisions.
93
+
94
+ ---
95
+
96
+ ## 6. External surfaces
97
+
98
+ This is visible to agents receiving long Telegram messages: the injected file
99
+ reference now points under `.instar/telegram-inbound` in the project instead of
100
+ `/tmp/instar-telegram`. That is intentional so Gemini CLI can read the file
101
+ inside its workspace sandbox. Users should not see a conversational difference
102
+ except that long Telegram messages are readable by sandboxed agents. No
103
+ Telegram API behavior changes, no Slack behavior changes, no database schema
104
+ changes, and no persistent committed state is introduced. The new directory is
105
+ ignored by git because payloads may include private user message content.
106
+
107
+ ---
108
+
109
+ ## 7. Rollback cost
110
+
111
+ Pure code rollback. Reverting the helper use would put future files back under
112
+ `/tmp/instar-telegram`; no database migration or state repair is required.
113
+ Existing transient files under `.instar/telegram-inbound` can be left in place
114
+ or removed by cleanup if the rollback keeps that cleaner. User-visible risk
115
+ during rollback is limited to sandboxed agents losing readability of long
116
+ Telegram inbound payloads again.
117
+
118
+ ---
119
+
120
+ ## Conclusion
121
+
122
+ The review found the key risk is path drift across the multiple Telegram
123
+ writers and cleanup, so the implementation uses one shared helper and updates
124
+ tests that previously encoded `/tmp/instar-telegram`. The change is clear to
125
+ ship with focused regression coverage on the relay-sensitive file reference
126
+ path.
127
+
128
+ ---
129
+
130
+ ## Second-pass review (if required)
131
+
132
+ **Reviewer:** `not run`
133
+ **Independent read of the artifact:** `not available`
134
+
135
+ Inbound messaging is relay-sensitive, but the multi-agent tool exposed in this
136
+ session is restricted to explicit user-requested delegation. I did not spawn a
137
+ reviewer under that constraint. The PR should receive human review on the
138
+ runtime callsites and tests before merge.
139
+
140
+ ---
141
+
142
+ ## Evidence pointers
143
+
144
+ - `npm test -- --run tests/unit/session-telegram-inject.test.ts tests/e2e/input-guard-e2e.test.ts tests/unit/server-temp-cleanup.test.ts tests/unit/bootstrap-file-threshold.test.ts tests/unit/telegram-message-injection.test.ts`
145
+ - `rg` check found no remaining runtime `/tmp/instar-telegram` use in
146
+ `src/core/SessionManager.ts`, `src/commands/server.ts`, or
147
+ `src/server/routes.ts`.