instar 1.3.265 → 1.3.267

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
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ `SessionManager.isMarkerStuckAtPrompt()` now recognizes Gemini CLI's input box. It checked the pane line for `❯` (Claude) or `›` (codex) to find the prompt; Gemini has neither — its active input is a `│ * <text>` box line — so a Telegram message injected into a Gemini session was never detected as stuck, and `verifyInjection`'s Enter-recovery never fired for Gemini. Forwarded prompts stalled unsubmitted in the box (the recurring mentee-layer auto-submit friction; it stalled a message to Codey live this session until manually nudged). The fix adds `│ *` to the prompt-indicator set. The downstream gate is unchanged — a line only counts as stuck if it also contains the exact injected marker, so `│ *` alone (or Gemini's empty-box placeholder) never false-fires, and Claude/codex detection is untouched. Sibling of the earlier codex `›` fix; all three CLIs now get the same stuck-input auto-recovery.
9
+
10
+ Adds an anti-clobber safety guard to cross-machine secret-sync: outbound push is now opt-in and
11
+ **off by default**.
12
+
13
+ - `multiMachine.secretSync.enabled` now activates the RECEIVE path only.
14
+ - Outbound push (the boot best-effort push + `POST /secrets/sync-now`) requires
15
+ `multiMachine.secretSync.pushEnabled: true`, set only on the machine whose secret store is
16
+ authoritative.
17
+ - A receive-only machine refuses `POST /secrets/sync-now` with `409`; `GET /secrets/sync-status`
18
+ now reports `pushEnabled` and `mode` (`full` | `receive-only`).
19
+ - Reason (earned live): a machine whose local secret store is stale/divergent — e.g. recovered from
20
+ a master-key drift — would otherwise auto-push its stale secrets on boot and overwrite peers'
21
+ good ones. Receive-only-by-default removes that foot-gun and makes "authoritative machine pushes,
22
+ stale machine only receives" the safe default.
23
+
24
+ ## What to Tell Your User
25
+
26
+ - Your saved credentials are safer across machines now. When I sync a secret between your machines,
27
+ only the machine you've designated as the source can send — a machine with an out-of-date copy can
28
+ receive an update but can never overwrite the good copy on your other machines.
29
+
30
+ ## Summary of New Capabilities
31
+
32
+ - Receive-only mode for secret-sync (the safe default): a machine can accept synced secrets without
33
+ ever pushing its own.
34
+ - Per-machine push opt-in via `multiMachine.secretSync.pushEnabled`.
35
+ - `GET /secrets/sync-status` now reports the machine's sync mode.
36
+
37
+ ## Evidence
38
+
39
+ - `vitest run tests/unit/codex-stranded-draft-recovery.test.ts tests/unit/session-multishot-recovery.test.ts` → **27/27 green** (Gemini box-detect + empty-box placeholder immunity + Claude/codex no-regression + no false-fire on a markerless `│ *` line).
40
+ - `tsc --noEmit` clean.
41
+ - Fixture mirrors a real Gemini idle pane captured live (`│ * [telegram:1] [Long message saved to …]`).
42
+
43
+ 16 tests across all three tiers (8 unit / 5 integration / 3 e2e), including a guard test proving a
44
+ receive-only machine returns 409 on `sync-now` and leaves the peer store untouched. tsc + lint clean.
45
+ Spec: docs/specs/cross-machine-secret-sync-spec.md (Guarantees → "Push is opt-in; receive-only by default").
@@ -0,0 +1,25 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ `telegram-reply.sh` now supports `--stdin-base64`, an additive mode for sending replies whose text may contain shell metacharacters or a literal heredoc delimiter line. The script decodes the base64 payload before using the existing JSON request path, so ordinary replies and server behavior are unchanged.
9
+
10
+ Existing unmodified relay scripts are upgraded through the SHA-based migrator. Customized relay scripts are preserved and receive a `.new` candidate as before.
11
+
12
+ ## What to Tell Your User
13
+
14
+ Telegram replies are more robust when an agent needs to send text that looks like shell syntax or contains a heredoc-closing line. Normal replies work the same way; the safer mode is only used when needed.
15
+
16
+ ## Summary of New Capabilities
17
+
18
+ - `telegram-reply.sh --stdin-base64 TOPIC_ID` decodes base64 input and sends the original text.
19
+ - Generated agent instructions mention the safer fallback for delimiter-sensitive content.
20
+ - Post-update migration upgrades the v1.3.266 shipped relay script to the new version without overwriting local customizations.
21
+
22
+ ## Evidence
23
+
24
+ - Focused unit run passed: `telegram-reply-port-resolution`, `PostUpdateMigrator-telegramReply`, `migration-relay-script-hash`, `IdentityRenderer`, and `telegramRelayPrompt`.
25
+ - The new relay test sends shell-looking content plus a literal `EOF` line through `--stdin-base64` and asserts the server receives the exact original text.
@@ -0,0 +1,91 @@
1
+ # Side-Effects Review — Secret-Sync push opt-in (receive-only default)
2
+
3
+ **Version / slug:** `secret-sync-push-guard`
4
+ **Date:** `2026-06-04`
5
+ **Author:** `echo`
6
+ **Second-pass reviewer:** `not required` (Tier 2; single-author, safety-tightening change)
7
+
8
+ ## Summary of the change
9
+
10
+ Adds an anti-clobber safety guard to cross-machine secret-sync (PR #771 / v1.3.258). Previously
11
+ `multiMachine.secretSync.enabled` activated BOTH receive and push, and a boot best-effort
12
+ push fired unconditionally — so a machine whose local secret store is stale/divergent would
13
+ auto-push its stale set to peers and overwrite their good secrets. This change splits push out
14
+ behind `multiMachine.secretSync.pushEnabled` (default **false**): `enabled` alone is now
15
+ RECEIVE-ONLY; outbound (boot push + `POST /secrets/sync-now`) requires `pushEnabled: true`,
16
+ set only on the machine whose store is authoritative. Files: `src/commands/server.ts` (gate +
17
+ handle field + boot-push guard), `src/core/SecretSync.ts` (`SecretSyncHandle.pushEnabled`),
18
+ `src/core/types.ts` (config field), `src/server/routes.ts` (sync-status reports `mode`;
19
+ sync-now 409s when receive-only), `src/scaffold/templates.ts` + `PostUpdateMigrator.ts`
20
+ (agent awareness, incl. a migration for agents that already have the section).
21
+
22
+ Earned live: 2026-06-04 the mini's store drifted (keychain↔file master-key); enabling the
23
+ original (push-on) secret-sync there would have clobbered the laptop's authoritative secrets.
24
+
25
+ ## Decision-point inventory
26
+
27
+ - `multiMachine.secretSync.pushEnabled` gate (server.ts) — **add** — splits outbound from inbound.
28
+ - Boot best-effort `provisionAll()` (server.ts) — **modify** — now gated on pushEnabled.
29
+ - `POST /secrets/sync-now` (routes.ts) — **modify** — returns 409 when receive-only.
30
+ - `GET /secrets/sync-status` (routes.ts) — **modify** — now reports `pushEnabled` + `mode`.
31
+
32
+ ## 1. Over-block
33
+
34
+ The guard "blocks" outbound push when `pushEnabled` is false — that is the intended behavior, not
35
+ over-block. A user who genuinely wants push must set `pushEnabled: true` (one config line). No
36
+ legitimate RECEIVE is blocked. The 409 response names the exact remedy.
37
+
38
+ ## 2. Under-block
39
+
40
+ The guard does not validate that the push-enabled machine's store is ACTUALLY authoritative — it
41
+ trusts the operator's `pushEnabled: true`. A misconfiguration (pushEnabled on a stale machine)
42
+ could still clobber. Mitigated by: default-off (you must deliberately opt in) + the doc guidance
43
+ ("set only on the machine whose store is authoritative"). A value-hash reconciliation (only push
44
+ keys the peer is missing/older) is a sound follow-up but out of scope here.
45
+
46
+ ## 3. Level-of-abstraction fit
47
+
48
+ Right layer: a config flag + a wiring gate, consistent with the rest of secret-sync. It reuses the
49
+ existing provisioner/handle; no new primitive. The default-off posture matches the project's
50
+ "dark by default" rollout discipline for risky features.
51
+
52
+ ## 4. Signal vs authority compliance
53
+
54
+ - [x] No — this change has no block/allow surface over user messages. (It gates an internal
55
+ outbound sync action behind an explicit config flag — deterministic, not a heuristic gate.)
56
+
57
+ ## 5. Interactions
58
+
59
+ - **Shadowing:** none — `pushEnabled` only narrows when the existing push path runs.
60
+ - **Double-fire:** reduces it — the boot push no longer fires on receive-only machines.
61
+ - **Races:** unchanged — same SecretStore read-modify-write as before; receive path untouched.
62
+ - **Feedback loops:** none. A receive-only machine that gets corrected by an authoritative push
63
+ does NOT re-push (it can't), so no ping-pong.
64
+
65
+ ## 6. External surfaces
66
+
67
+ - **Peers:** strictly safer — a receive-only machine no longer sends to peers at all.
68
+ - **Config:** new optional field `multiMachine.secretSync.pushEnabled` (absent ⇒ false ⇒ no push).
69
+ No migrateConfig default needed (absence = safe default).
70
+ - **API:** `/secrets/sync-status` gains `pushEnabled` + `mode` fields (additive); `/secrets/sync-now`
71
+ can now return 409 (receive-only) in addition to its prior 200/503/500.
72
+ - **Persistent state:** none changed.
73
+
74
+ ## 7. Rollback cost
75
+
76
+ Pure code change. Revert = secret-sync returns to push-on-enable (the less-safe prior behavior).
77
+ No persistent state to unwind. Because push was never enabled on any real machine between #771 and
78
+ this change (the mini incident is exactly why), there is no in-the-wild push to reconcile.
79
+
80
+ ## Conclusion
81
+
82
+ A small, safety-tightening change with a default-off posture; it closes the divergent-store clobber
83
+ risk that the 2026-06-04 mini incident exposed and makes laptop→mini the safe reconciliation
84
+ direction for the live verification. The one residual (operator opts pushEnabled on a non-authoritative
85
+ machine) is documented and a value-hash reconciliation is the natural follow-up. Clear to ship.
86
+
87
+ ## Evidence pointers
88
+
89
+ 16 tests green: 8 unit, 5 integration (incl. the new receive-only guard test: sync-now 409s + peer
90
+ vault untouched), 3 e2e. tsc + lint clean. Spec updated (Guarantees → "Push is opt-in"). Related: the
91
+ SecretStore keychain-drift repair that surfaced this (re-key file→keychain).
@@ -0,0 +1,31 @@
1
+ # Side-effects review — telegram reply robust content mode
2
+
3
+ ## What changed
4
+
5
+ `telegram-reply.sh` now accepts `--stdin-base64` / `--base64-stdin`. In that mode, the script decodes the provided base64 payload before building the existing JSON request body. This gives agents a transport-safe path when the reply text itself contains shell metacharacters, quotes, JSON-looking text, or a literal heredoc delimiter line.
6
+
7
+ The normal heredoc path remains unchanged. The new mode is additive and only activates when the flag is present.
8
+
9
+ ## Why
10
+
11
+ The standard relay instruction uses a single-quoted heredoc. That protects most shell-sensitive text, but it still fails when the response body contains a line that exactly matches the heredoc delimiter. During Gemini mentoring, Gemi hit this class directly: its heredoc relay attempt ended in a shell syntax error, then it recovered by squeezing the response into a quoted argument. That workaround is fragile for long or structured replies.
12
+
13
+ Base64 stdin moves the fragile bytes out of shell syntax entirely. The shell only carries base64 characters; the canonical reply script restores the original text before sending.
14
+
15
+ ## Migration footprint
16
+
17
+ Existing unmodified `telegram-reply.sh` copies are SHA-migrated by `PostUpdateMigrator`. This PR registers the v1.3.266 template SHA as a prior shipped version so deployed agents receive the new script on update. Locally modified scripts are still preserved: the migrator writes a `.new` candidate and reports the existing relay-script-modified-locally degradation instead of overwriting custom content.
18
+
19
+ Generated identity/scaffold guidance now keeps the familiar heredoc example and adds the base64 fallback for delimiter-sensitive content.
20
+
21
+ ## Risk
22
+
23
+ Low. The default send path, HTTP route, auth headers, port resolution, tone-gate handling, 408 ambiguous handling, recoverable relay queue, and JSON body shape are unchanged. The new branch only decodes input before the existing JSON builder.
24
+
25
+ The main operational risk is invalid base64 input; the script exits before contacting the server and prints a clear error.
26
+
27
+ ## Tests
28
+
29
+ - Unit: `tests/unit/telegram-reply-port-resolution.test.ts` now proves `--stdin-base64` sends shell-sensitive text and a literal `EOF` line as exact message text.
30
+ - Unit: existing `PostUpdateMigrator-telegramReply`, `migration-relay-script-hash`, `IdentityRenderer`, and `telegramRelayPrompt` tests cover migration and generated guidance.
31
+ - Focused run: 58 tests passed across those five files.
@@ -0,0 +1,11 @@
1
+ # ELI16 — Telegram Reply Robust Content Mode
2
+
3
+ Agents usually send Telegram replies by pasting the reply into a shell heredoc. That is fine for normal text, but it can break if the reply itself contains the heredoc closing word on its own line.
4
+
5
+ This change adds a safer backup path. The reply script can now accept base64 text, decode it, and send the original message. That means the shell only sees safe base64 characters, while Telegram receives the real reply text.
6
+
7
+ Nothing changes for ordinary replies. The normal heredoc command still works, the server route is the same, and the script still builds the same JSON body after it has the final text. The new flag only changes how the text gets into the script.
8
+
9
+ Existing agents with the standard reply script are upgraded automatically. The migrator recognizes the last shipped script by its hash, backs it up, and installs the new version. If an operator edited the script locally, Instar does not overwrite it. Instead it writes the new version next to it as a review candidate, preserving the local customization.
10
+
11
+ This matters for agents because reply failures are easy to miss: the user sees silence, while the agent may only see a shell error in its pane. The safer path gives agents a reliable escape hatch for long reports, code examples, JSON snippets, or any text that accidentally contains the heredoc closing line.
@@ -1,22 +0,0 @@
1
- # Upgrade Guide — vNEXT
2
-
3
- <!-- assembled-by: assemble-next-md -->
4
- <!-- bump: patch -->
5
-
6
- ## What Changed
7
-
8
- `SessionManager.isMarkerStuckAtPrompt()` now recognizes Gemini CLI's input box. It checked the pane line for `❯` (Claude) or `›` (codex) to find the prompt; Gemini has neither — its active input is a `│ * <text>` box line — so a Telegram message injected into a Gemini session was never detected as stuck, and `verifyInjection`'s Enter-recovery never fired for Gemini. Forwarded prompts stalled unsubmitted in the box (the recurring mentee-layer auto-submit friction; it stalled a message to Codey live this session until manually nudged). The fix adds `│ *` to the prompt-indicator set. The downstream gate is unchanged — a line only counts as stuck if it also contains the exact injected marker, so `│ *` alone (or Gemini's empty-box placeholder) never false-fires, and Claude/codex detection is untouched. Sibling of the earlier codex `›` fix; all three CLIs now get the same stuck-input auto-recovery.
9
-
10
- ## What to Tell Your User
11
-
12
- None — internal change (no user-facing surface).
13
-
14
- ## Summary of New Capabilities
15
-
16
- None — internal change (no user-facing surface).
17
-
18
- ## Evidence
19
-
20
- - `vitest run tests/unit/codex-stranded-draft-recovery.test.ts tests/unit/session-multishot-recovery.test.ts` → **27/27 green** (Gemini box-detect + empty-box placeholder immunity + Claude/codex no-regression + no false-fire on a markerless `│ *` line).
21
- - `tsc --noEmit` clean.
22
- - Fixture mirrors a real Gemini idle pane captured live (`│ * [telegram:1] [Long message saved to …]`).