polygram 0.10.0-rc.31 → 0.10.0-rc.32

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://anthropic.com/claude-code/plugin.schema.json",
3
3
  "name": "polygram",
4
- "version": "0.10.0-rc.31",
4
+ "version": "0.10.0-rc.32",
5
5
  "description": "Telegram integration for Claude Code that preserves the OpenClaw per-chat session model. Migration target for OpenClaw users. Multi-bot, multi-chat, per-topic isolation; SQLite transcripts; inline-keyboard approvals. Bundles /polygram:status|logs|pair-code|approvals admin commands plus history (transcript queries) and polygram-send (out-of-turn IPC sends with file-upload validation) skills.",
6
6
  "keywords": [
7
7
  "telegram",
@@ -98,16 +98,33 @@ function getClaudeSessionId(db, sessionKey) {
98
98
  // ─── S2: session-config drift ────────────────────────────────────────
99
99
  //
100
100
  // A stored `sessions` row records the config the claude session was
101
- // SPAWNED under (agent / cwd / pm_backend). Those three are
102
- // spawn-identity: they are baked into the process at spawn time —
103
- // `--agent`, the tmux/SDK working dir, the backend class and cannot
104
- // be changed on a live session. If the chat/topic config has drifted
105
- // from the stored row, `--resume`-ing the old session forces claude
106
- // to run under a config it was never built for. shumorobot
107
- // 2026-05-17 22:03, topic :3: the row was agent=shumabit / cwd=$HOME
108
- // / sdk (created before the Music topic got its per-topic override);
109
- // resuming it under agent=music-curation:music-curator /
110
- // cwd=.../Music/rekordbox / tmux left the TUI never signalling ready.
101
+ // SPAWNED under. Two of the recorded fields are spawn-identity:
102
+ // - agent `--agent <name>` is baked into the spawned process;
103
+ // resuming a session spawned under agent X under agent Y forces
104
+ // claude to use Y's system prompt + tool whitelist against
105
+ // conversation history built under X's. Incoherent.
106
+ // - cwd `--cwd <path>` (SDK) / tmux session cwd; claude resolves
107
+ // project-local config (.claude/settings.json, agent files,
108
+ // plugins) relative to it. Mid-conversation cwd drift means
109
+ // half the messages are answered with one project's allowlist
110
+ // and the other half with another's.
111
+ //
112
+ // pm_backend was REMOVED from spawn-identity (rc.32, 2026-05-21).
113
+ // Both backends spawn the same pinned claude binary and write the
114
+ // same on-disk JSONL (~/.claude/projects/<cwd-enc>/<sid>.jsonl) —
115
+ // claude itself doesn't know or care which Node-side wrapper invoked
116
+ // it. Treating a backend flip as drift was destructively dropping
117
+ // context across the SDK→tmux migration window, costing every chat
118
+ // its conversation history on its first turn under the new backend.
119
+ // shumorobot 2026-05-20 18:51 incident: the Music topic flipped
120
+ // tmux→sdk→tmux during runtime and lost its agent's prior context
121
+ // at each flip. The orphan-tmux problem that the flip ALSO triggered
122
+ // is solved by rc.31's spawn-time reconcile (TmuxProcess.start) —
123
+ // independently, so a backend flip is now a no-op for session-state.
124
+ //
125
+ // shumorobot 2026-05-17 22:03, topic :3 (the original drift incident)
126
+ // remains correctly handled: that row had agent+cwd drift in
127
+ // addition to backend, so the agent+cwd drift alone still drops it.
111
128
  //
112
129
  // model + effort are deliberately EXCLUDED from the invalidating set.
113
130
  // They are NOT spawn-identity: a live `/model` or `/effort` change is
@@ -118,7 +135,7 @@ function getClaudeSessionId(db, sessionKey) {
118
135
  // every model switch, double-handling what the live-apply path
119
136
  // already covers cleanly. The stored model/effort columns are
120
137
  // informational, not identity.
121
- const SPAWN_IDENTITY_FIELDS = ['agent', 'cwd', 'pm_backend'];
138
+ const SPAWN_IDENTITY_FIELDS = ['agent', 'cwd'];
122
139
 
123
140
  /**
124
141
  * Decide whether a stored session can be resumed for the next spawn,
@@ -499,9 +499,12 @@ class TmuxProcess extends Process {
499
499
  // Spawn-time reconcile (shumorobot 2026-05-20 18:51 incident).
500
500
  // A tmux session with our name may already exist on the host
501
501
  // BEFORE we spawn — sources:
502
- // - pm_backend drift: chat config flipped tmux → sdk → tmux;
503
- // polygram dropped its in-memory handle but the previous
504
- // daemon's tmux session is still running headless.
502
+ // - pm_backend flip: chat config flipped tmux → sdk → tmux;
503
+ // polygram dropped its in-memory handle on the flip away
504
+ // from tmux but the previous daemon's tmux session is still
505
+ // running headless. (rc.32 makes the flip context-preserving
506
+ // on the session-id side; this reconcile keeps the
507
+ // tmux-pane side safe.)
505
508
  // - Boot-sweep raced a concurrent operator (already noted in
506
509
  // lib/tmux/orphan-sweep.js header).
507
510
  // - Crash mid-spawn: the spawn() call landed but the sessionCreated
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polygram",
3
- "version": "0.10.0-rc.31",
3
+ "version": "0.10.0-rc.32",
4
4
  "description": "Telegram daemon for Claude Code that preserves the OpenClaw per-chat session model. Migration path for OpenClaw users moving to Claude Code.",
5
5
  "main": "lib/ipc/client.js",
6
6
  "bin": {
package/polygram.js CHANGED
@@ -400,18 +400,21 @@ function buildSpawnContext(sessionKey) {
400
400
  const threadId = sessionKey.includes(':') ? sessionKey.split(':')[1] : null;
401
401
 
402
402
  // S2: a stored session is valid ONLY for the config it was spawned
403
- // under. agent / cwd / pm_backend are spawn-identity — baked into
404
- // the process at spawn time, never mutable on a live session.
405
- // Resolve them the same way the backends do (topic override merged
406
- // over chat-level) and compare to the stored `sessions` row. On
407
- // drift, resolveSessionForSpawn drops the stale row and returns
403
+ // under. agent / cwd are spawn-identity — baked into the process at
404
+ // spawn time, never mutable on a live session. Resolve them the
405
+ // same way the backends do (topic override merged over chat-level)
406
+ // and compare to the stored `sessions` row. On drift,
407
+ // resolveSessionForSpawn drops the stale row and returns
408
408
  // existingSessionId:null → the spawn starts fresh under the correct
409
409
  // config instead of `--resume`-ing a stale one. This self-heals the
410
410
  // pre-per-topic-config rows (e.g. shumorobot's Music topic :3,
411
- // stored agent=shumabit / cwd=$HOME / sdk vs the current
412
- // music-curation:music-curator / .../Music/rekordbox / tmux).
411
+ // stored agent=shumabit / cwd=$HOME vs the current
412
+ // music-curation:music-curator / .../Music/rekordbox).
413
413
  // model/effort are NOT compared — they apply live via setModel /
414
- // applyFlagSettings with no respawn.
414
+ // applyFlagSettings with no respawn. pm_backend is also NOT
415
+ // compared (rc.32): both backends spawn the same pinned claude
416
+ // binary against the same on-disk JSONL, so a backend flip
417
+ // preserves context. See lib/db/sessions.js for full reasoning.
415
418
  //
416
419
  // The drift check runs only at COLD spawn (no warm process). A warm
417
420
  // process already runs under its spawn-time config; getOrSpawn