@llblab/pi-telegram 0.23.3 → 0.24.1

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/CHANGELOG.md CHANGED
@@ -1,9 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## Unreleased
4
+
5
+ ## 0.24.1: Persistence I/O And Cross-Platform Validation Hotfix
6
+
7
+ - `Cross-Platform CI`: Replaced Ubuntu-only validation with a fail-fast-disabled Ubuntu, macOS, and Windows matrix on minimum Node `22.19.0`; every runner performs typecheck, tests, and package dry-run, while audit remains a single Ubuntu gate. The first hosted run hardened awaited bounded timers for Node 22, maps filesystem-style endpoints onto native Windows pipes, bounds long macOS domain-socket paths through a private hashed fallback, scopes POSIX assertions to Unix, and uses native test paths. Impact: Unix socket/atomic-file behavior and Windows named-pipe/process behavior now receive preventive push/PR coverage rather than release-time assumptions.
8
+ - `Test Cooling`: Added test-only transaction timing controls, a shared bounded Node-eval fixture for config/lock/log races, and one table-driven synthesis/transcription registry contract while preserving each named behavior. Removed 19 declaration-only exports after composition/package/test/docs reachability proof; no single-reference exports remain. Impact: the lock suite drops from roughly nine seconds to three, repeated process plumbing shrinks, and production retries, failure assertions, compatibility, and recovery paths remain unchanged.
9
+ - `Release History`: Retrospectively reviewed all 85 changelog sections, consolidated only evidence-backed noisy releases, removed intermediate refactor/validation/backlog chronology, and preserved every version heading plus shipped behavior, breaking changes, migrations, limitations, compatibility boundaries, and material operator evidence. Impact: changelog source shrinks from 188,115 to about 135,000 characters while already compact historical sections remain intact.
10
+ - `Global Config Concurrency`: Added regressions for a two-store same-profile settings-versus-stale-polling race and for unrelated global/named-profile disk changes arriving after a store load. Documented recursive delta merge, monotonic offset, same-leaf commit-order, and non-transactional editor boundaries. Semantically unchanged merges now adopt the latest disk snapshot in memory without replacing `telegram.json`. Impact: the transaction delta merge now carries explicit coverage that polling progress remains monotonic without erasing global assistant or voice settings written by another live Pi instance.
11
+ - `Diagnostics Log I/O`: Batch same-turn `logs.jsonl` events by captured profile path into one transaction without adding a timer, preserve cross-process ordering/failure isolation, and rotate between batched records before an authorized writer crosses the 5 MiB threshold. Individual-record/reset-metadata overshoot remains explicit and non-owner writers defer rotation. Impact: ordinary diagnostic bursts avoid per-event guard churn without turning one large batch into an unbounded current log.
12
+ - `State Snapshot I/O`: Coalesce diagnostics snapshot requests across a bounded 100 ms window and compare `state.json` without its observational `writtenAtMs` timestamp before publishing a replacement, while retaining the exact-owner commit fence and the existing stale-view disk reload. Impact: unchanged domain state and repeated equivalent diagnostics projections no longer create temporary files or atomic full-snapshot renames.
13
+ - `Ownership Lease I/O`: Kept one-second exact ownership checks and the serialized expected-owner transaction while moving durable heartbeat refreshes to a separate two-second cadence and widening stale detection to eight seconds. Concurrent abandoned-guard recovery now treats disappearance after observation as a lost-candidate race instead of surfacing `ENOENT`; fake-clock and observed-owner regressions pin the stale boundary, single winner, losing candidates, and waking old leader. Impact: steady-state `owners.json` atomic rewrites are halved without weakening singleton/leader fencing or the Unix-socket and Windows-named-pipe ownership model.
14
+
15
+ ## 0.24.0: Canonical Profiles And Extension-Local Ownership
16
+
17
+ - `Canonical Default Profile`: Persisted bot/session identity under `profiles.default` and named siblings while keeping shared settings top-level. Legacy root identity migrates atomically when unambiguous and conflicts fail closed; bare and explicit `default` setup/connect commands now behave identically without changing default runtime paths. Live reload preserved token, pairing, offset, ownership, and Telegram delivery.
18
+ - `Extension-Local Transport Ownership`: Replaced shared agent-level `locks.json` ownership with private profile-scoped `tmp/telegram/owners.json`, serialized through `owners.json.transaction`; followers remain outside owner-slot writes. Breaking: `0.24.0` intentionally does not migrate legacy ownership, so upgrading resets the transport owner and may require `/telegram-connect`. Live reload confirmed isolated default ownership while leaving the legacy registry untouched.
19
+
3
20
  ## 0.23.3: Thread-Scoped Settings Hotfix
4
21
 
5
22
  - `Thread-Scoped Settings Rehydration`: Preserved `message_thread_id` when rebuilding full Settings menu state after session reload or TTL expiry. Impact: a stale Settings message in Threaded Mode retains its exact Telegram target when later callbacks reopen menus or cross into model/status controls.
6
- - `Composition Root Hygiene`: Sorted the local domain imports in `index.ts` and normalized adjacent wrapping without changing runtime composition. Impact: the entrypoint remains easier to scan and review while preserving the existing dependency graph and behavior.
7
23
 
8
24
  ## 0.23.2: Voice Policy And Turn Delivery Hotfix
9
25
 
@@ -19,30 +35,17 @@
19
35
  - `Thread Reconciliation Safety`: Removed unreachable reservation-probe/removal machinery and the uncalled heartbeat-prune destructive cleanup action. Explicit disconnect, replacement, previous-leader, and expired-provision cleanup retain their confirmation and leader-epoch fences. Impact: reconciliation matches the documented rule that heartbeat loss removes live routing authority without deleting a follower's recoverable Telegram thread.
20
36
  - `Destination Resolution`: Collapsed proactive chat-id and target selection onto the target resolver's active-turn → assigned-thread → paired-chat priority, retaining a scalar adapter only where an API requires a chat id. Impact: proactive projection, activity typing, and Guest attachment staging cannot drift between duplicate destination sources.
21
37
  - `Agent Context Budget`: Added compact successful-test output with an opt-in verbose reporter, bounded failure-log inspection, search-first large-artifact and Bot API lookup rules, scoped diff/review guidance, and stable-gate validation policy. Compressed repeated agent, architecture, and multi-instance contracts without weakening their safety meaning. Impact: ordinary validation and review consume substantially less model context while actionable diagnostics remain available in retained logs.
22
- - `Validation`: Full typecheck/tests/audit/package dry-run, strict Domain DAG, ABCd context validation, repository hygiene checks, and an independent regression review all passed after cleanup. Impact: the behavior-preserving hotfix is release-ready with no identified blockers.
23
38
 
24
39
  ## 0.23.0: Telegram Bot API 10.2 Rich Output And Proactive Projection
25
40
 
26
- - `Follower Visibility And Restoration`: Added one synchronous connected probe before cross-session target reuse or recovery of an exact target absent from current bindings. Success surfaces the existing tab; explicit stale-topic evidence provisions a monotonic replacement, while ambiguous failures preserve non-routable `probe-required` evidence and reject without replay or speculative replacement. Impact: followers cannot report invisible or deleted tabs as restored, and retries must resolve the exact target before activation.
27
- - `Explicit Thread Disconnect`: Authenticated registration and disconnect with present exact generations, serialized both mutations per durable follower profile across awaited cleanup, and required thread-named confirmation plus successful deletion or explicit already-gone evidence before removing routing authority. Incomplete cleanup preserves leader/follower state with retry guidance, and promoted leaders authorize inherited cleanup through their current epoch. Impact: `/telegram-disconnect` cannot let an old runtime delete a replacement registration or falsely report success while its tab remains.
28
- - `Follower Succession And Handoff`: Added the authenticated live slot roster to heartbeats so the lowest observed follower proceeds immediately on leader loss while higher slots defer for one bounded grace and then recheck exact atomic ownership. Promoted followers retain target, slot, thread name, profile ownership, and electing status through same-process session handoff; reload persists that identity under acquired leader authority before provisioning. Impact: failover prefers slot order without claiming consensus, dead lower candidates cannot block recovery indefinitely, and promoted reload reuses the existing tab instead of resetting identity.
29
- - `Threaded Topology Evidence`: Two- and three-instance live smokes confirmed usable follower tabs, repeated bidirectional promotion/disconnect/re-registration, promoted-leader reload reuse, and healthy convergence without manual takeover. Occasional timing-dependent promotion order remains compatible with bounded grace because exact atomic ownership—not timing—fences leadership. Impact: visibility, restoration, and multi-instance recovery have direct operator evidence without overstating succession guarantees.
30
- - `Composition Root Compression`: Reduced `index.ts` from 1,119 to 1,083 lines by moving assistant-output admission/authority/sender coordination into the existing Pi-binding orchestration domain, moving config-persist sync sequencing and stale-topic API recovery adapters into `sync`, and replacing local forwarding callbacks with direct live-port wiring where signatures already matched. Impact: the entrypoint retains visible runtime composition while low-level policy, failure projection, mutable sequencing, and reusable adapters stay with their owning domains.
31
- - `Forwarded Input`: Added a bounded one-second candidate window that joins ordinary short comments with an adjacent same-sender/chat/thread forward across polling responses, including Rich Message text and follower-routed updates. Nested forwarded photo, video, animation, audio, and voice-note media now render under source-attributed attachments immediately after the forward block. A post-reload live smoke confirmed comment → forward → attachment ordering with the image available as model input. Impact: comments and forwards form one correctly attributed Pi turn without relying on incidental polling batches or mislabeling forwarded media as current-user attachments.
32
- - `Follower Routing And Restart`: Propagated the exact live registration generation into every leader-forwarded envelope, recorded rejected acknowledgements, and preserved stable manual-follower bindings across process absence as restart hints only. Replacement registration reclaims the current recognizable thread and slot, while authenticated live registration remains mandatory routing authority and explicit stale/deleted/offline evidence invalidates reuse. Impact: follower prompts remain generation-fenced and diagnosable, and restarts avoid duplicate same-named tabs without routing to absent processes.
33
- - `Inbound Prompt Topology`: Kept attachment-derived `[outputs]`, including voice transcription, immediately after current-user `[attachments]`, with independent reply/source context following the complete current-user block. A live voice reply to an image confirmed the same current-user-first ordering. Impact: attachment meaning remains connected to the input that produced it instead of being split by quoted-message context.
34
- - `Portable Lock Standard`: Synchronized `docs/locks.md` bit-for-bit with the reusable cross-project standard and removed Telegram-specific runtime, bus, profile, and release-history policy from that portable artifact. Impact: the standard can be copied into another singleton-extension project as a complete implementation contract, while project-specific behavior remains owned by architecture documentation.
35
- - `Proactive Configuration And Documentation`: Moved local/autonomous projection policy under `assistant.proactivePush` beside assistant rendering and draft-preview settings, enabled it when absent, retained nested explicit `false` as the canonical opt-out, and intentionally omitted a compatibility alias for the removed top-level key. Settings explain `on` (default) and `off`, while README, Activity, Outbound, Public API, architecture, and durable contracts document ordered public-block projection, exclusions, rendering, authority, follower routing, and no-replay behavior. Impact: configuration, operator copy, and maintainer contracts describe one coherent default-enabled feature with an explicit disable path.
36
- - `Config Transactions`: Valid Telegram configuration snapshots now load directly from the atomically published file, while malformed-file recovery and every merge/write remain serialized by the cross-process transaction guard. Impact: ordinary `telegram.json` reads no longer create transaction-directory churn, without weakening concurrent persistence or destructive recovery safety.
37
- - `Release Preflight`: Ran the complete 0.23.0 validation suite after follower visibility, bounded succession preference, explicit cross-role thread disconnect, cross-batch grouping, and forwarded Rich media fixes: 1,292 tests passed with one platform-only skip, typecheck passed, npm audit reported zero vulnerabilities, package dry-run produced `@llblab/pi-telegram@0.23.0`, and `git diff --check` stayed clean. Impact: deterministic, packaging, dependency, and repository hygiene gates are green, and the final independent release review reported SHIP with no blockers.
38
- - `Proactive Projection`: Extended the existing Activity assistant-output path to project deduplicated completed public `text_end` segments from local and autonomous work through the configured Rich/HTML sender. Intermediate and final blocks share one ordered, non-blocking queue; Telegram-owned turns, hidden reasoning, tool traffic, empty text, disabled policy, and the removed final-only `agent_end` path remain excluded. Impact: public checkpoints and finals arrive once and in source order without a parallel projection domain or a Grow Loop dependency.
39
- - `Proactive Authority And Ordering`: Bound every admitted block to its target, profile/token transport stamp, session generation, and exact direct leader epoch or follower registration generation, then revalidated authority immediately before each non-idempotent send/edit mutation. Direct and follower barriers prove queued stale-generation work drops, follower IPC preserves order, replacement transport receives no old mutation, and ambiguous transport outcomes retain no-replay behavior. Impact: asynchronous handlers, ownership changes, follower re-registration, and session replacement cannot redirect or duplicate delayed projection.
40
- - `Proactive Projection Evidence`: Deterministic local-run, direct/follower ordering, privacy, and replacement-fence coverage plus a post-reload live smoke confirmed that one public commentary checkpoint and final arrived separately and in order in the assigned thread while internal tool traffic stayed silent. Impact: the normalized multi-block lifecycle has both regression and client evidence without duplicate output.
41
- - `Rich Attachment Results`: Added one deterministic outbound plan that combines exactly one probe-confirmed PNG/JPEG photo, MP4 video, or MP3 audio artifact with normalized final assistant Markdown, reply/thread targeting, and an optional inline keyboard in one configured-Rich multipart result. Known-safe rejection returns to text plus attachment; `commit-unknown` or malformed success stops without replay. HTML mode, multiple or unsupported artifacts, empty text, Guest Mode, voice-only output, explicit voice markup, and OGG/Opus retain their established paths. Impact: supported requested media can arrive as one reply-anchored result without weakening rendering choice, voice policy, or ambiguity safety.
42
- - `Rich Authority And Safety`: Recorded exact message ownership, authorized follower multipart upload only to its registered thread, and fenced scheduled or in-flight Rich finals across session replacement and ownership loss. Old generations cannot start multipart mutation or continue with preview cleanup, fallback delivery, or queue dispatch after authority changes. The outgoing Rich contract permits Markdown/HTML plus typed media but excludes Thinking blocks, with invariants across reply, preview, queue, and attachment paths. Impact: replacement sessions, cross-thread followers, and hidden reasoning cannot redirect or duplicate Rich delivery.
43
- - `Rich Transport And Rendering`: Added narrow Bot API 10.2 media and voice-note types plus direct/follower JSON, cached-file, HTTPS, and single-file `attach://` multipart transport coverage. Structured Markdown regressions preserve tables, inline/display mathematics, code, details, lists, and quotations through normalization and final request construction without a parallel block renderer. Impact: supported Rich content crosses both transport roles with its typed shape and native structure intact.
44
- - `Rich Client Evidence`: Post-reload direct-leader and follower Telegram-turn smokes confirmed one queued PNG plus final Markdown arrives as one reply-anchored composite result with no duplicate upload, attachment notice, or final. A separate live probe confirmed HTTPS photo/video/audio composites plus multipart and cached-`file_id` voice notes, with independently requested voice notes remaining separate messages. Impact: the bounded integration has deterministic transport coverage and direct client evidence across leader and follower paths.
45
- - `Rich Output Contracts And Reference`: Documented single-artifact behavior, ownership, targeting, compatibility fallbacks, ambiguity no-replay, and evidence boundaries across operator and maintainer docs. Synchronized the vendored Bot API reference with 10.2 Rich Message blocks/media, voice notes, Ephemeral Messages, Communities, subscription updates, and refreshed lookup indexes while preserving its full-reference structure. Impact: implementation and review can resolve current behavior and API fields locally without overstating broader Bot API possibilities.
41
+ - `Follower Restoration And Routing`: Required a synchronous visibility probe before cross-session target reuse, preserved ambiguous absence as non-routable `probe-required` evidence, carried exact registration generations through forwarded envelopes, and treated persisted bindings as restart hints rather than live authority. Impact: reconnects reuse recognizable threads without routing to absent followers, reporting deleted tabs as restored, replaying ambiguous work, or creating speculative replacements.
42
+ - `Disconnect And Succession`: Serialized registration/disconnect by durable follower identity, required confirmed deletion or explicit already-gone evidence before removing routing state, carried authenticated slot rosters in heartbeats, and let one bounded preferred follower attempt exact atomic promotion while promoted instances retain thread, slot, name, profile, and reload handoff. Impact: old runtimes cannot delete replacements, incomplete cleanup remains retryable, and leader recovery preserves instance identity without claiming timing-based consensus.
43
+ - `Inbound Attribution`: Joined one adjacent owner comment with a same-sender/chat/thread forward across polling batches, retained forwarded Rich media under source-attributed attachments, and kept current attachment-derived output—including voice transcription—before independent reply/forward context. Impact: forwarded gestures and attachment meaning enter Pi as one correctly ordered, attributable prompt through direct and follower routing.
44
+ - `Proactive Projection`: Moved default-enabled policy under `assistant.proactivePush`, projected deduplicated completed public local/autonomous assistant blocks through one ordered non-blocking Activity path, and excluded Telegram turns, reasoning, tools, token deltas, empty blocks, and disabled output. Every admitted block carries target, profile/token stamp, session generation, and direct leader epoch or follower generation, revalidated before mutation with ambiguous outcomes retaining no-replay. Impact: checkpoints and finals reach the authorized thread once and in source order without exposing internal activity or redirecting stale queued work after ownership, registration, or session replacement.
45
+ - `Rich Composite Results`: Added a bounded Bot API 10.2 path that combines final Markdown, reply/thread targeting, optional keyboard, and exactly one probe-confirmed PNG/JPEG photo, MP4 video, or MP3 audio artifact. Direct/follower transport supports JSON, HTTPS, cached `file_id`, and single-file `attach://`; known-safe rejection falls back to text plus attachment, while ambiguous commit stops without replay. Exact message/transport ownership fences scheduled and in-flight multipart work, and unsupported, multiple, Guest, HTML, voice-only, explicit-voice, and OGG/Opus cases retain their established paths. Impact: supported media and final text can arrive as one reply-anchored result without duplicate upload, hidden reasoning, cross-thread delivery, or stale-generation continuation.
46
+ - `Rich Rendering And Reference`: Preserved structured Markdown tables, math, code, details, lists, and quotations through Rich normalization and transport, documented composite ownership/fallback/evidence boundaries, and synchronized the vendored Bot API 10.2 Rich Message/media and voice-note reference plus lookup indexes. Impact: implementation and review share one local contract for the supported Rich surface without implying unsupported Bot API breadth.
47
+ - `Config And Architecture`: Let valid `telegram.json` snapshots load directly while keeping malformed recovery and every merge/write under the cross-process transaction, synchronized the portable lock standard without Telegram-specific policy, and moved projection/config/sync adapters out of the composition root into their owning domains. Impact: ordinary reads avoid transaction-directory churn, concurrent persistence remains guarded, and reusable standards stay separate from product policy.
48
+ - `Verification`: Deterministic direct/follower, stale-generation, multipart, ordering, privacy, and recovery regressions plus two-/three-instance and Telegram-client smokes confirmed follower restoration, bidirectional promotion/disconnect/re-registration, promoted reload reuse, ordered proactive blocks, forwarded media attribution, and one composite result without duplicate final or upload. Impact: the release records final operator evidence while omitting repeated preflight chronology.
46
49
 
47
50
  ## 0.22.1: Termux-Compatible Filesystem Transactions
48
51
 
@@ -51,7 +54,7 @@
51
54
 
52
55
  ## 0.22.0: Concurrency And Runtime Ownership Hardening
53
56
 
54
- - `Composition Root And Validation`: Reduced `index.ts` from 1,534 to 1,077 lines by moving transport generations, Threaded Mode orchestration, request/ownership identity, synchronization, provisioning, lifecycle, diagnostics, Delivery policy, inbound authority, follower forwarding, and retry policy into their owning flat domains. Domain regressions and structural guards prohibit local runtime adapters, direct Node imports, dependency cycles, and leaf-domain drift. The release gate passed 1,229 tests with one platform-only skip, typecheck, strict Domain DAG, ABCd, invariants, package dry-run, zero-vulnerability audit, and `git diff --check`. Impact: the entrypoint retains high-level composition while release-critical policy remains independently testable and structurally enforced.
57
+ - `Composition Root And Validation`: Reduced `index.ts` from 1,534 to 1,077 lines by moving transport generations, Threaded Mode orchestration, ownership identity, sync/provisioning, lifecycle, diagnostics, Delivery policy, inbound authority, follower forwarding, and retry policy into owning flat domains. Domain regressions and structural guards prohibit local runtime adapters, direct Node imports, cycles, and leaf drift. Impact: the entrypoint retains high-level composition while release-critical policy remains independently testable and structurally enforced.
55
58
  - `Lock Transactions And Fencing`: Serialized all `locks.json` acquisition, refresh, release, and dead-owner recovery through fail-closed cross-process transactions while preserving unrelated profile keys. Collision-resistant leader epochs, exact owner/profile retention, and time-monotonic same-process generations fence forced replacement, refresh, release, direct transport, state persistence, and reload handoff. Impact: concurrent or stale runtimes cannot both win ownership, reverse a replacement, mutate through replacement transport, or corrupt the shared registry.
56
59
  - `Leader Startup And Follower Election`: Started exact-owner heartbeat refresh immediately after lock acquisition and retained it through binding handoff, provisioning, server startup, and polling; startup failure cleans up and releases ownership. Followers remain in re-registration recovery while an exact live lease exists, promote only after atomic stale/no-owner acquisition, and losers re-register with the winner using their carried target. Impact: slow startup, transient IPC loss, simultaneous followers, and session handoff cannot create split-brain polling, strand a follower, or duplicate its thread.
57
60
  - `Reconciliation And Provisioning Fences`: Revalidated the stamped leader epoch before every destructive Bot API call, local deletion mutation, cleanup persistence, and provisioning boundary; missing ownership fails closed. Thread snapshots commit through exact lock transactions, pending creation intents survive displacement as serialized recovery evidence, and the next owner adopts successfully created targets without replaying creation. Impact: stale leaders cannot delete replacement-owned threads or publish authoritative bindings, while successful topic creation survives handoff without duplicates or deadlock.
@@ -72,41 +75,27 @@
72
75
 
73
76
  ## 0.21.0: Activity And Delivery Extension Platform
74
77
 
75
- - `Platform Documentation`: Completed 0.21 discoverability across the README, public API inventory/smoke checklist, Activity and Delivery contracts, architecture map, Sections reference, package contents, documented consumer policy examples, and the external demo-project reference. Removed the completed platform epic from `BACKLOG.md` while preserving deferred media/process boundaries and the concrete callback revisit trigger in docs. Impact: extension authors can find and validate the complete supported surface without `/lib` imports, and open-work context now contains only unfinished work.
76
- - `Platform Validation`: Added a full-runtime classic-mode regression proving public activity delivery reaches the assigned Telegram surface while `agent_start` remains independent from the consumer's pending Bot API send. Expanded scope coverage to distinguish active-turn, assigned-instance, and aggregate targets and verify autonomous activity can opt into aggregate delivery; existing leader/follower transport, authorization, stale-generation, ordering, chunk reconciliation, and cleanup regressions complete the platform matrix. Impact: the 0.21 extension contracts now carry focused domain, public-boundary, and runtime integration proof.
77
- - `Callback Boundary`: Confirmed that the issue #126 consumer shape needs no second managed callback registry: Sections already own interactive Settings namespacing, answers, edits, navigation, and cleanup, while delivered activity rows remain non-interactive and raw update handlers stay the low-level escape hatch. Impact: the platform avoids duplicate callback ownership and records the concrete trigger for revisiting the boundary.
78
- - `Activity API`: Added the public `@llblab/pi-telegram/activity` membrane and wired Pi input, agent, assistant text/reasoning, executed-tool, compaction, settlement, and shutdown lifecycle signals into evidence-based activity/source identities. Isolated asynchronous per-handler queues preserve semantic order, coalesce adjacent deltas, fence shutdown generations, report handler failures, and provide fresh target-aware delivery contexts without awaiting consumer work or duplicating bridge previews/finals. Impact: extension consumers can build lifecycle-adjacent Telegram surfaces without private Pi contexts, raw provider messages, or bridge transport ownership.
79
- - `Delivery API`: Added the public `@llblab/pi-telegram/delivery` membrane for ownership-gated operational views and chat actions across active-turn, current-instance, aggregate, and explicitly authorized targets. Logical handles reconcile chunked send/edit/delete operations, per-target queues preserve ordering, followers route through the leader transport, and reload/session replacement invalidates old generations without captured Pi contexts. Impact: companion extensions can now deliver lifecycle-adjacent Telegram UI through stable ports instead of importing bridge internals or owning another bot client.
80
- - `Public API`: Documented the complete capability inventory, intentional private boundaries, target policy, structured delivery failures, callback boundary decision, and deferred media/process controls; added public-boundary, classic/leader/follower policy, chunk reconciliation, ordering, and lifecycle regressions. Impact: extension authors can distinguish supported platform capabilities from deliberate safety boundaries and the completed 0.21 extension-platform surface.
81
- - `Pi Compatibility`: Set the Activity platform floor to Pi/core/AI `0.80.6`, registered the public typed `agent_settled` lifecycle event directly, and aligned Telegram model controls with Pi's `max` thinking level. Impact: activity identity now closes at a supported terminal boundary without unsafe event casts or silently merging unrelated runs on older Pi versions.
82
- - `Delivery Lifecycle`: Constructed a fresh Delivery runtime and generation for every session start, shut down displaced bindings, and fenced queued or multi-step in-flight work at every transport boundary. Impact: session replacement cannot revive old handles or let an old operation continue chunks, edits, deletes, or chat actions through a new session.
83
- - `Delivery Recovery`: Added recoverable partial handles to failed multi-chunk sends and edit growth, tracking every message id that remains visible after transport failure. Impact: callers can deterministically retry or clean up a partially materialized logical view instead of losing its only valid handle.
84
- - `Activity Compaction`: Added explicit abandonment for standalone compaction activities that never receive `session_compact`, triggered by the next run/compaction boundary or the bounded observer timeout, while preserving compaction inside an active agent identity and ignoring late completion. Impact: cancelled or failed compaction cannot leak its activity id or source into an unrelated run.
85
- - `Activity Diagnostics`: Reconciled the public contract with implemented diagnostics: handler failures carry redacted identity metadata through the bounded bridge recorder, while 0.21 intentionally exposes no queue phase/length/latency telemetry or drop policy beyond adjacent delta coalescing. Impact: consumers can reason from documented backpressure behavior without relying on diagnostics the runtime does not emit.
86
- - `Activity Lifecycle`: Recreated the Activity dispatcher with a fresh generation on every session start while stopping and clearing the retiring generation at shutdown, and bound handler contexts to their exact dispatcher generation and registration. Impact: same-process session replacement resumes normalized lifecycle delivery while blocked handlers from the retiring session fail closed instead of sending stale work through replacement Delivery.
87
- - `Guest Identity`: Kept private Guest Mode location identity anchored to the strongest remote-conversation evidence and excluded bot-authored replies from guest resolution, while retaining a non-bot replied peer as a final fallback when chat/caller identity is absent. Impact: replying to a Guest Mode bot response preserves `[telegram|guest:<remote-user>]`: alongside `[reply|from:<bot>]`: instead of replacing the conversation peer with the bot username.
78
+ - `Activity API`: Added the public `@llblab/pi-telegram/activity` membrane for normalized Pi input, agent, assistant text/reasoning, executed-tool, compaction, settlement, and shutdown signals with evidence-based activity/source identity. Per-handler asynchronous queues preserve semantic order, coalesce adjacent deltas, isolate failures with redacted identity diagnostics, and provide fresh target-aware Delivery contexts without blocking Pi or duplicating bridge previews/finals. Impact: extensions can build lifecycle-adjacent Telegram surfaces without private Pi contexts, raw provider messages, or transport ownership.
79
+ - `Activity Lifecycle`: Recreated dispatchers per session generation, fenced retiring registrations and blocked handlers, preserved compaction inside active run identity, and abandoned standalone compaction that never reaches `session_compact` at the next boundary or bounded timeout while ignoring late completion. The contract intentionally promises adjacent-delta coalescing but no queue phase/length/latency telemetry or broader drop policy. Impact: replacement and cancelled compaction cannot leak stale identity or work into another run.
80
+ - `Delivery API`: Added the public `@llblab/pi-telegram/delivery` membrane for ownership-gated operational views and chat actions across active-turn, instance, aggregate, and explicitly authorized targets. Per-target queues order logical chunked send/edit/delete handles, followers route through leader transport, session generations invalidate old operations at every transport boundary, and partial failures return handles for every still-visible message. Impact: extensions can deliver and recover Telegram UI through stable ports without bot clients, captured Pi contexts, or orphaned partial views.
81
+ - `Platform Boundary`: Kept Sections as the owner of managed Settings callbacks/navigation/cleanup, Activity rows non-interactive, and raw updates as the low-level escape hatch instead of adding a second callback registry. Documented capability inventory, target policy, structured failures, intentional private/deferred media/process boundaries, consumer policy, and the maintained external demo through public membranes only. Impact: extension authors can discover the complete supported platform without `/lib` imports or overlapping callback ownership.
82
+ - `Pi Compatibility`: Set the Activity/Delivery floor to Pi/core/AI `0.80.6`, consumed typed `agent_settled`, and aligned Telegram model controls with Pi's `max` thinking level. Impact: activity identities close on a supported terminal boundary without unsafe casts or accidental merging across runs.
83
+ - `Platform Verification`: Added focused public-boundary and full-runtime proof for classic, leader, follower, active-turn, instance, aggregate, autonomous, stale-generation, ordering, chunk reconciliation, partial recovery, authorization, cleanup, and non-blocking `agent_start` behavior. Impact: the platform contract is protected across its supported scopes and transport roles without preserving separate documentation/test chronology.
84
+ - `Guest Identity`: Anchored private Guest Mode identity to the strongest remote-conversation evidence, excluded bot-authored replies from peer resolution, and retained a non-bot replied peer as final fallback. Impact: replying to a Guest bot response keeps `[telegram|guest:<remote-user>]` alongside `[reply|from:<bot>]` instead of misidentifying the bot as the conversation peer.
88
85
 
89
86
  ## 0.20.6: Guest Attribution And Voice Action Hotfix
90
87
 
91
- - `Voice Action Syntax`: Hidden `telegram_voice` actions now accept the intuitive paired form `<!-- telegram_voice ... -->...<!-- /telegram_voice -->` alongside inline, attribute-text, and single-comment multiline forms. The parser captures a non-empty multiline body and preserves language/rate attributes while leaving surrounding prose visible. Impact: agents can use an explicit closing tag without leaking the intended TTS payload as ordinary text.
92
- - `Voice Investigation`: Removed the premature Guest Mode generate-before-answer experiment and unrelated voice-pipeline changes after live evidence identified unsupported paired markup as the confounder. After reload, voice-only paired actions delivered exactly one playable voice response with no visible fallback text in both an assigned thread and a correctly attributed private Guest Mode conversation; `telegram_attach` independently delivered the same format. Impact: standard Threaded Mode and private Guest Mode now have direct live proof on the established delivery architecture, while group Guest Mode confirmation remains explicit in `BACKLOG.md`.
93
- - `Guest Attribution`: Private Guest Mode now resolves `guest` as the remote conversation peer instead of the paired owner: a non-owner sender identifies itself, while an owner-authored turn prefers the replied peer, then the private-chat identity, then non-owner caller metadata. Username falls back to the remote display name and numeric id, and an unresolved payload records redacted field-presence diagnostics without leaking the owner's identity into `[telegram|guest:...]`. Group Guest Mode continues to use the group title. Impact: the agent sees the third party it is assisting in a direct conversation, not the bot owner who invoked it.
94
- - `Validation`: Added route and resolver regressions for owner-authored no-reply DMs, explicit replies, non-owner peers, username changes, missing usernames, numeric fallback, alternate paired profile ids, and owner-only unresolved input. Impact: private attribution and source-context provenance remain distinct while the paired owner can never become the guest label.
95
- - `Live Evidence`: After reloading the hotfix workspace, a real owner-authored private Guest Mode invocation identified the remote peer rather than the paired owner. Impact: the repaired remote-peer attribution now has direct Telegram evidence, so the completed P0 moved out of `BACKLOG.md` and the tree is ready for the next hotfix scope.
88
+ - `Voice Action Syntax`: Added paired `<!-- telegram_voice ... -->...<!-- /telegram_voice -->` markup beside inline, attribute-text, and single-comment multiline forms, preserving language/rate attributes and surrounding visible prose. Reloaded Threaded and private Guest turns delivered one playable voice result without fallback leakage, and `telegram_attach` independently accepted the format. Impact: explicit closing-tag TTS works through the established delivery architecture without a separate generation path.
89
+ - `Guest Attribution`: Private Guest Mode resolves the remote conversation peer rather than the paired owner: non-owner senders identify themselves, owner-authored turns prefer the replied peer then private-chat/non-owner caller evidence, and username falls back through display name to numeric id. Unresolved input records only redacted field presence; groups retain the group title. Route/resolver regressions and a live private invocation confirm the paired owner cannot become `[telegram|guest:...]`. Impact: the agent sees the third party it is assisting while reply-source attribution remains separate.
96
90
 
97
91
  ## 0.20.5: Guest Media And Runtime Recovery Hotfix
98
92
 
99
- - `Setup Persistence`: The setup prompt now applies the validated bot identity to its config store before invoking persistence, so adapters that serialize current store state cannot write an empty or stale `telegram.json` on first run. Persistence failure rolls the in-memory candidate back and remains ahead of success notifications and polling startup. Impact: setup from a missing file or `{}` durably writes `botToken`, `botId`, and `botUsername` on the first successful command for default and named profiles without reporting an unsaved connection.
100
- - `Validation`: Added file-backed setup regressions for missing and empty config files, environment-provided tokens, named-profile isolation, and persistence-failure rollback while preserving existing cancellation, validation, polling-failure, and atomic config-write coverage. Full validation passes with 1,098 tests and one platform-only skip; typecheck and npm audit remain clean.
101
- - `Guest Attachments`: `telegram_attach` now admits exactly one local file during an active Guest Mode turn and rejects a second before file inspection or queue mutation. Agent-end stages that file through the paired-owner chat, sends one cached-media guest result with final text as its caption, cleans up the staging message, and never follows an ambiguous media-answer failure with a second guest answer. Impact: a requested local file is no longer silently discarded, while Telegram's one-result constraint remains explicit.
102
- - `Guest Media Transport`: `answerGuestQuery` now accepts a typed cached document/photo/audio/voice result in addition to text and Rich Markdown articles, and the bus-aware API preserves that exact result when a follower routes it through the leader. Impact: guest delivery no longer hard-codes article construction at the direct or IPC boundary, providing the minimal one-shot transport needed for staged local media without widening the follower API allowlist.
103
- - `Guest Media Staging`: Added a bounded local-media staging primitive that selects document/photo/audio/voice multipart transport, extracts the returned Telegram `file_id`, emits one matching cached guest result, truncates captions safely to 1,024 code points, and deletes the staging message in `finally`. Extraction and answer failures still clean up; cleanup failures record diagnostics without retrying the one-shot guest answer. Impact: local Guest Mode artifacts have deterministic cleanup and no duplicate-answer path.
104
- - `Guest Voice`: Guest agent-end now routes one explicit or policy-intercepted voice reply through the existing synthesis/handler chain, captures the generated OGG/OPUS artifact instead of sending it to sentinel chat `0`, stages it through the leader-owned multipart transport, and answers with one cached voice result. Visible answer text becomes the media caption, and multiple voice blocks reduce to the first result under Telegram's one-query/one-result contract. Impact: ordinary Guest Mode responses can include synthesized audio without bypassing ownership or emitting a separate text answer.
105
- - `Leader Endpoint Recovery`: The active Threaded Mode leader now checks its Unix socket during the existing follower-health cadence. If an external cleanup unlinks the endpoint while the server and polling owner remain alive, it closes only the orphaned local server, recreates the socket and parent directory, and resumes follower reachability without restarting polling, changing leader epoch, or touching thread bindings. Named pipes and classic mode remain unchanged because they do not expose the same filesystem-loss condition. Impact: a live owner can self-heal the observed `ENOENT bus.sock` split between polling health and follower connectivity without unsafe lock takeover.
106
- - `Follower Diagnostics`: When bounded registration retries fail with `ENOENT`, `ECONNREFUSED`, or `ETIMEDOUT` behind a still-live lock owner, the connection result now identifies `live owner / unreachable bus endpoint`, asks the operator to wait briefly and retry `/telegram-connect`, and explicitly rejects force takeover while the owner remains live. Impact: transient endpoint recovery no longer looks like a generic registration failure or invite split-brain remediation.
107
- - `Profile Diagnostics`: Current logs use `logs.jsonl` for default and `logs.<profile>.jsonl` for named profiles; preserved logs use `logs._prev.jsonl` and `logs.<profile>._prev.jsonl`. Status and `telegram_help` resolve paths through the shared helper, old logs remain untouched as ephemeral evidence, and profile names allow only lowercase ASCII letters and digits. Impact: `_prev` remains an unmistakable lifecycle suffix because underscores and dots cannot occur in profile identifiers, while compact dotted profile filenames remain readable.
108
- - `Compaction Status`: Removed pi-telegram's terminal and status-summary `compacting` projection while retaining the compaction flag in explicit bridge diagnostics and dispatch safety. A Telegram-owned active turn continues to render `active`; unrelated compaction leaves the stable connected/leader/follower role visible. Impact: Pi remains the sole owner of compaction lifecycle UI, and pi-telegram reports Telegram ownership rather than duplicating generic session state.
109
- - `Compaction Activity`: Compaction now starts the same connected-instance native typing path used by agent activity instead of suppressing typing when no Telegram turn is active. Active Telegram compaction targets its thread plus `All`; local/autonomous compaction targets the instance's assigned thread plus `All`, with completion, timeout, and shutdown stopping the keyed loop. Impact: compaction remains visible in Telegram without taking ownership of Pi's terminal lifecycle label.
93
+ - `Setup Persistence`: Applied validated bot identity to the config store before persistence and rolled back the in-memory candidate on failure before success notification or polling startup. File-backed regressions cover missing/empty files, environment tokens, named-profile isolation, cancellation, validation, polling failure, and atomic writes. Impact: first setup durably stores bot token/id/username without reporting an unsaved connection.
94
+ - `Guest Media`: Allowed exactly one local Guest turn attachment, added typed cached document/photo/audio/voice `answerGuestQuery` results through direct and follower transport, staged bounded multipart media through the paired-owner chat, extracted `file_id`, truncated captions to 1,024 code points, and always attempted staging cleanup. Safe failures clean up and ambiguous one-shot answers never replay. Impact: requested Guest artifacts can arrive with final caption text without silent discard, duplicate answers, or a wider follower allowlist.
95
+ - `Guest Voice`: Routed one explicit or policy-intercepted Guest voice action through the existing synthesis/handler chain, captured the generated OGG/Opus artifact, staged it through leader-owned media transport, and returned one cached voice result with visible text as caption. Impact: Guest Mode can synthesize audio without sentinel destinations, separate fallback text, or bypassed ownership.
96
+ - `Leader Endpoint Recovery`: Probed the live leader's Unix socket during follower-health checks and recreated an externally unlinked endpoint without restarting polling, changing leader epoch, or touching bindings. Registration exhaustion behind a live owner now reports `live owner / unreachable bus endpoint`, recommends retry, and rejects force takeover; named pipes and classic mode remain outside this filesystem-loss path. Impact: `ENOENT bus.sock` can self-heal without split-brain remediation.
97
+ - `Profile Diagnostics`: Standardized current and preserved diagnostic paths as `logs[.<profile>].jsonl` and `logs[.<profile>]._prev.jsonl`, shared path resolution across status/help, and restricted profile names to lowercase ASCII letters and digits. Impact: profile logs stay isolated and `_prev` remains an unambiguous lifecycle suffix.
98
+ - `Compaction Presence`: Removed pi-telegram's duplicate terminal/status-summary `compacting` label while retaining diagnostic and dispatch-safety state, and reused connected-instance native typing for active Telegram, local, and autonomous compaction in the assigned thread plus aggregate `All`. Completion, timeout, and shutdown stop the keyed loop. Impact: Telegram shows compaction activity while Pi remains the owner of terminal lifecycle status.
110
99
 
111
100
  ## 0.20.4: Thread State Ownership Hotfix
112
101
 
@@ -126,19 +115,13 @@
126
115
 
127
116
  ## 0.20.2: Live Thread Reality
128
117
 
129
- - `Profiles`: Named `/telegram-connect <profile>` now verifies the persisted profile before stopping polling or changing session-local profile activation. Impact: a mistyped or missing profile leaves the current bot, transport ownership, and polling runtime untouched instead of disconnecting a healthy session.
130
- - `Profiles`: Follower target replacement now resolves its fallback binding key from the active profile at replacement time instead of capturing the default-profile key during extension construction. Impact: named-profile thread restore cannot write a missing-record fallback into another bot profile's identity namespace.
131
- - `Profiles`: Setup now returns explicit success, cancellation, unavailable/busy, validation-failure, and polling-failure outcomes. Named-profile setup validates in an isolated temporary config and commits/stops the previous runtime only after token validation; `saved and connected` appears only after polling startup succeeds. Impact: cancellation and invalid tokens leave the active profile and transport untouched, while polling failures cannot produce false success copy.
132
- - `Diagnostics`: Compact status and `telegram_help` now render the active profile's real `state.<profile>.json` and `logs.<profile>.jsonl` filenames while retaining the legacy unsuffixed paths for the default profile. Impact: named-profile debugging no longer points operators and agents at another bot runtime's evidence.
133
- - `Validation`: Removed stale turn-helper imports and enabled TypeScript's `noUnusedLocals` and `noUnusedParameters` checks in the standard typecheck gate. Impact: abandoned imports and adapters now fail local and CI validation instead of silently accumulating.
134
- - `Composition`: Moved profile-scoped bus process identity and live endpoint resolution into the existing `bus` domain; moved manual-follower key resolution, promoted-binding transfer, and receiver/recovery/registration assembly into `bus-follower`; and consolidated provisioner, reconciliation, API-proxy, and server runtime assembly inside `bus-leader`. Impact: hotfix-sensitive profile isolation and bus lifecycle wiring stay with established owners instead of repeated construction-time closures and circular initialization in the composition root, reducing `index.ts` from 1,398 to 1,314 lines without adding another domain.
135
- - `Validation`: Added direct follower and leader assembly regressions, kept entrypoint/import architecture invariants green, and passed the full test suite (1 platform skip). Impact: composition compression is behavior-preserving and the remaining entrypoint surface stays explicit cross-domain wiring rather than being hidden behind a generic runtime bag.
136
- - `Live Linux`: A short leader `/reload` smoke auto-started from the retained lock in 652 ms, reused Dawn at the same thread target and slot `D`, restored the local bus server, and removed 17 historical follower bindings after recovery grace. Impact: lock-driven leader reload, same-thread preservation, and delayed non-destructive roster compaction are confirmed live; the smoke also exposed a surviving historical `lastSlot: "Z"` cursor that is corrected below.
137
- - `Thread Slots`: When follower-binding reality reconciliation removes stale records, it now realigns a cursor owned by those removed records to the newest-created remaining live binding in the same persisted compaction. It preserves a cursor that still belongs to live state, leaves pending/reserved slots as allocation guards, and does not reinterpret orphaned cursors from ordinary thread deletion. Impact: current-version compaction cannot recreate the observed historical `Z` cursor beside Dawn-only `D`; the next fresh follower starts from `E`.
138
- - `Thread Slots`: Converted `bot.lastSlot` from a max-letter watermark into a true ring cursor that advances through `Z → A`, starts allocation from the latest fresh slot, and ignores higher occupied letters when the cursor points earlier in the ring. Impact: wrapped histories no longer pin allocation at `Z`, and a live `D` cursor can assign the next free follower slot from `E`.
139
- - `Thread Identity`: Limited cursor updates to fresh/new-target records while preserving same-target binding reuse without cursor drift. Impact: reconciliation and reload upserts cannot silently rewrite the fresh-allocation sequence.
140
- - `Live State`: Replaced historical follower-registry restoration with a bounded leader-reload grace window followed by non-destructive reconciliation against the live bus roster. Followers now carry their last known target while re-registering so live processes reuse the same thread, while dead current-state records and identities leave `state.json` without deleting Telegram tabs. Impact: runtime truth compacts stale slot occupancy after recovery has had time to converge.
141
- - `Validation`: Added ring-wrap, cursor-priority, dead-follower reality, delayed reconciliation, and same-target follower re-registration regressions while keeping the existing slot reuse, pending provision, reservation, and alphabet-cap coverage green.
118
+ - `Profile Activation`: Validated named profiles before stopping polling or changing active identity, resolved follower replacement keys from the profile active at replacement time, and made setup return explicit success/cancelled/busy/validation/polling outcomes. Named setup validates in isolation and commits the switch only after token validation and successful polling startup. Impact: missing profiles, cancellation, bad tokens, and startup failure leave the healthy bot/transport untouched and cannot write restoration state into another profile.
119
+ - `Profile Diagnostics`: Status and `telegram_help` now show the selected profile's actual `state[.<profile>].json` and `logs[.<profile>].jsonl` paths while retaining unsuffixed default paths. Impact: named-profile debugging points at the correct bot evidence.
120
+ - `Bus Composition`: Moved profile process/endpoint identity into `bus`, follower identity/handoff/receiver/recovery/registration into `bus-follower`, and provisioning/reconciliation/API proxy/server assembly into `bus-leader`; direct assembly regressions and import guards protect the boundary. Impact: profile isolation and bus lifecycle policy stay with cohesive owners instead of construction-time entrypoint closures.
121
+ - `Slot Ring`: Replaced the max-letter watermark with a true `A…Z → A` cursor, advanced from the latest fresh slot, ignored unrelated higher occupied letters, updated the cursor only for fresh targets, and preserved reuse without drift. Impact: wrapped histories no longer pin allocation at `Z`, and ordinary reconciliation cannot silently rewrite fresh allocation order.
122
+ - `Reality Reconciliation`: After a bounded leader-reload grace, reconciled persisted follower state against the live roster, let re-registering followers carry/reuse their exact target, removed dead local records/identities without deleting Telegram tabs, and realigned a removed cursor to the newest remaining live binding while preserving live, pending, and reserved guards. Impact: stale slot occupancy compacts only after recovery has had time to converge.
123
+ - `Live Verification`: A leader reload reused the same named thread/target/slot, restored the bus automatically, and compacted historical follower records; ring-wrap, cursor priority, dead-follower, delayed reconciliation, and same-target re-registration regressions preserve the resulting contract. Impact: lock-driven reload and live-state convergence have direct evidence without retaining incidental timing or environment-specific thread names.
124
+ - `Validation Hygiene`: Enabled `noUnusedLocals` and `noUnusedParameters` in the standard typecheck gate. Impact: abandoned imports and adapters fail locally and in CI instead of accumulating silently.
142
125
 
143
126
  ## 0.20.1: Profile IPC Isolation Hotfix
144
127
 
@@ -173,26 +156,19 @@
173
156
 
174
157
  ## 0.19.0: Telegram Companion Hub
175
158
 
176
- - `Context`: Defined Rich Markdown as the model-answer membrane: complete assistant/guest model replies use native Rich Message delivery, while tool rows, reasoning/thinking blocks, menus, status, queue controls, settings, diagnostics, and other harness-owned surfaces stay on explicit Telegram HTML/plain rendering.
177
- - `Settings`: Added an opt-in `richDraftPreviews` setting, exposed it in Telegram Settings, and gated `sendRichMessageDraft` preview frames behind it while preserving final native Rich Markdown replies. Impact: fresh installs default to final-only Rich Markdown plus native active status, and operators can explicitly enable progressive draft drawing when desired.
178
- - `Backlog`: Opened 0.19.0 release preparation and closed the rich draft preview setting task, making final-only Rich Markdown replies the intended baseline and draft previews an opt-in progressive enhancement.
179
- - `Context`: Clarified the README standard: keep the root entrypoint balanced between product positioning and a compact practical feature showcase, avoiding both over-abstract marketing copy and duplicated implementation docs. Impact: future README changes preserve the feature-catalogue value while keeping the surface coherent.
180
- - `Docs`: Reworked the root README as a product-oriented RhythmE entrypoint with clearer hero positioning, install/connect flow, operating model, expanded feature showcase, classic-vs-Threaded Mode comparison, safety boundaries, extension platform summary, and documentation map. Impact: the public entrypoint now explains `pi-telegram` as a Telegram companion console while preserving a practical catalogue of user-facing capabilities.
181
- - `Guest Mode`: Unauthorized guest-query replies now include the standard denied-action emoji. Impact: the compact `Access denied` message is easier to recognize in Telegram.
159
+ - `Rendering Boundary`: Defined Rich Markdown as the complete assistant/guest answer membrane while tool rows, reasoning/thinking, menus, status, queue controls, Settings, diagnostics, and other harness-owned surfaces retain explicit HTML/plain rendering. Impact: model-authored content and operator UI use formats suited to their different ownership and compatibility needs.
160
+ - `Draft Preview Setting`: Added opt-in `richDraftPreviews` while keeping final native Rich Markdown and native activity as the fresh-install baseline. Impact: operators can enable progressive draft drawing without changing final answer delivery.
161
+ - `Product Entrypoint`: Reworked README around companion positioning, install/connect, operating model, feature catalogue, classic-versus-Threaded comparison, safety boundary, extension platform, and docs map, with a durable balance between positioning and practical capability. Impact: readers can understand the product without an abstract landing page or duplicated implementation manual.
162
+ - `Guest Mode`: Added the standard denied-action marker to unauthorized guest-query replies. Impact: compact access denial is easier to recognize in Telegram.
182
163
 
183
164
  ## 0.18.6: Threaded Mode parity hotfix
184
165
 
185
- - `Threaded Mode`: Follower-routed prompts now record message ownership when the leader forwards them by thread target, and edited messages can route by stored message ownership when Telegram omits thread identity. Impact: later queue-control reactions and queued-prompt edits on the original Telegram message route back to the owning follower instead of being handled by the leader.
186
- - `Native Activity Status`: Follower typing/activity startup now sends one thread-scoped action plus one aggregate action, and the default keepalive cadence is back to 2.5 seconds. Impact: follower `...active` status avoids duplicate chat-action bursts that can hit Telegram rate limits.
187
- - `Threaded Mode`: Follower `/start` can now register the visible bot command menu through the leader bus without a warning before opening the local menu, follower-sent Bot API messages are recorded in the leader's ownership map, and follower message edit/delete calls used by menu surfaces are allowed as validated same-chat message operations. Impact: follower menu callbacks and interactive cleanup route back to the owning follower even when Telegram callback payloads omit thread identity, without false bus-allowlist failures.
188
- - `Threaded Mode`: Follower promotion now snapshots the current follower thread binding before clearing registration state and converts that binding into the leader profile before forced lock acquisition. Impact: an elected follower keeps its existing thread identity across promotion and later reload instead of becoming disconnected or provisioning a fresh leader thread.
189
- - `Threaded Mode`: Follower registration now probes a reused same-profile thread with the connected notice before reporting it as reusable, and recreates the thread when Telegram reports the old target as stale. Impact: reconnecting a follower after its Telegram tab was closed no longer leaves the terminal showing a follower thread name while no matching Telegram thread is visible.
190
- - `Threaded Mode`: Unbound-thread reroute controls now expose replace/restore for the current live bus roster instead of requiring prior leader reroute confirmation. Impact: when a new unbound Telegram thread appears, the operator can choose any currently live leader/follower instance to route to or replace/restore into that source thread.
191
- - `Status`: Follower terminal status now gives active/compacting processing labels precedence over the stable follower role, matching leader behavior. Impact: a follower shows its thread name plus `active` while processing a Telegram-originated prompt, then returns to `follower` when idle.
192
- - `Threaded Mode`: Reload-time target ownership now classifies only follower-owned records as follower targets and replaces stale same-profile/same-target follower registry entries on registration. Impact: after leader or follower reload, Telegram prompts and reroutes no longer get forwarded to dead instance ids or report a live thread as unavailable.
193
- - `Validation`: Live Linux Threaded Mode smoke now passes for post-reload leader/follower prompt routing, unbound reroute/restore, and leader/follower terminal Active status. Impact: the hotfix candidate has Telegram-client evidence for the regressions fixed after `0.18.5`.
194
- - `Docs`: Added a leader/follower capability parity matrix covering prompts, queue reactions, edits, callbacks, replies, previews, attachments, native activity, command/menu bootstrap, and diagnostics. Impact: follower behavior now has an explicit parity checklist instead of being inferred from leader behavior.
195
- - `Engineering`: Formalized an `AGENTS.md` compliance pass for non-trivial work and cleaned unused runtime/lifecycle test surfaces surfaced by strict no-unused diagnostics. Impact: future changes have an explicit project-rule audit step, and dead-code diagnostics stay actionable.
166
+ - `Follower Message Ownership`: Recorded leader-forwarded prompt and follower-sent Bot API message ownership by target, then used that evidence when edits, reactions, or callbacks omit thread identity. Allowed validated same-chat follower edit/delete operations and routed menu cleanup back to the owner. Impact: queued edits, queue controls, callbacks, and interactive surfaces no longer fall through to the leader or fail the bus allowlist.
167
+ - `Follower Menu And Activity`: Let follower `/start` register bot commands through leader transport, sent one thread plus one aggregate activity action at a 2.5-second cadence, and gave active/compacting status precedence over the stable follower role. Impact: follower controls and presence match leader behavior without duplicate chat-action bursts or misleading idle labels during work.
168
+ - `Promotion And Reload`: Snapshotted the follower binding before promotion, converted it to the leader profile before forced acquisition, classified only true follower-owned reload records as follower targets, and replaced stale same-profile/same-target registrations. Impact: elected or reloaded instances retain their visible thread and stop forwarding to dead runtime ids.
169
+ - `Follower Restoration`: Probed reused same-profile threads with the connected notice before reporting success and recreated targets only on explicit stale evidence. Impact: reconnect cannot claim a thread name when no usable Telegram tab exists.
170
+ - `Unbound Reroute`: Exposed replace/restore choices from the current live leader/follower roster without requiring prior leader reroute confirmation. Impact: operators can route a new unbound thread to any live instance through one current-state chooser.
171
+ - `Parity Evidence`: Added the leader/follower capability matrix and live Linux proof for post-reload routing, unbound restore, and active status; formalized project-rule compliance and removed dead test surfaces. Impact: prompts, reactions, edits, callbacks, replies, previews, attachments, activity, menu bootstrap, and diagnostics have explicit parity evidence without separate validation/docs chronology.
196
172
 
197
173
  ## 0.18.5: Windows Threaded Mode stabilization hotfix
198
174
 
@@ -228,24 +204,14 @@
228
204
 
229
205
  ## 0.18.0: Threaded Mode
230
206
 
231
- - `Threaded Mode`: Added Telegram private-chat Threaded Mode while keeping classic private DM as the base mode. Threaded Mode is now the bus switch: in ordinary private-DM mode, one Pi session owns the bot; when Telegram exposes threads for the bot, one live leader owns polling/Bot API transport and visible follower Pi processes join explicitly with `/telegram-connect`. Impact: operators can choose either a simple single-instance bot or a multi-thread development workspace without competing pollers or hidden process spawning.
232
- - `Capability Switching`: Reworked Threaded Mode availability around private-bot evidence: `getMe.has_topics_enabled`, incoming `message_thread_id`, and private-thread operation success/failure. A 5-second monitor can hot-upgrade classic mode to Threaded Mode and hot-downgrade back to classic without `/reload`. Impact: Threaded Mode behaves as a progressive enhancement instead of a startup-only assumption.
233
- - `Thread Routing`: Preserved per-instance ownership for queues, active turns, model/tool state, previews, menus, lifecycle hooks, replies, files, voice, buttons, reactions, and command/control replies. Impact: leader and follower threads behave like scoped Telegram workspaces rather than views over one shared queue.
234
- - `Thread Lifecycle`: Added durable current-state thread bindings with explicit owners, stable slots, compact baked thread names, reservations, and proof-before-delete cleanup through `thread-reconciler`. Impact: reloads, reconnects, stale tabs, restores, and cleanup avoid duplicate live threads and avoid deleting uncertain targets.
235
- - `Leader/Follower Recovery`: Added recovery for reloads, reconnects, follower heartbeat loss, promotion, explicit disconnect, stale thread cleanup, and same-profile follower resume. Impact: Threaded Mode degrades forward across local process churn while preserving the intended thread binding where possible.
236
- - `Native Activity Status`: Kept Telegram work indication native-only through Bot API `sendChatAction(typing)` / Telegram client `...active` status. Custom progress/activity/thinking message surfaces are not part of the release path. Impact: long-running work uses the Telegram-native affordance instead of adding extra chat noise.
237
- - `Compaction Activity`: Scoped typing to real work: active Telegram turns, tool/reasoning/message activity during those turns, confirmed manual `/compact`, and automatic compaction only when it belongs to an active Telegram turn. Thread-scoped typing preserves the concrete thread target and mirrors to `All` as aggregate activity. Impact: compaction shows native activity when it should, without reviving startup/connect/reload typing.
238
- - `Thread-Scoped Delivery`: Propagated `{ chatId, threadId? }` across inbound routing, replies, previews/drafts, typing, voice, attachments, menus, sections, callbacks, reactions, media groups, slash commands, and follower-routed Bot API calls. Impact: classic DM delivery and thread delivery share one target-scoped transport contract.
239
- - `Replies And Drafts`: Anchored the first assistant reply block to the prompting message in Threaded Mode and kept later chunks sequential; preview rollover preserves the active turn's source reply metadata. Telegram Desktop may still omit the visual reply header despite the same correct payload that mobile renders. Impact: thread conversations keep local reply context without stacking headers on every chunk.
240
- - `Thread UX`: Improved unbound-thread reroute/restore flows, cleanup of temporary chooser surfaces, connected/offline notices, status/menu role indicators, and routing controls. Impact: operator-facing Threaded Mode surfaces are more recognizable and less likely to leave stale controls behind.
241
- - `Proactive Push`: Allowed Threaded Mode followers to send successful local non-Telegram final replies through the leader transport when `proactivePush` is enabled. Impact: follower-owned local results can reach the assigned thread without granting unrelated non-owner processes Telegram delivery.
242
- - `Agent Responsiveness`: Moved successful Telegram turn follow-up delivery work into extension-owned background tasks. Impact: Pi can leave the working state sooner after producing the final answer while preserving Telegram delivery ordering.
243
- - `Telegram API Transport`: Added `PI_TELEGRAM_NETWORK_FAMILY=auto|ipv4|ipv6|ipv4-fallback`; the default `ipv4-fallback` retries transport-level dual-stack failures through Node's IPv4-only HTTPS path after native `fetch`. JSON calls, multipart uploads, and file downloads now share one transport helper with richer redacted diagnostics. Impact: hosts with broken IPv6 can keep polling, typing, drafts, downloads, uploads, and direct tools working without global DNS changes.
244
- - `Security`: Hardened local bus authorization with leader-minted secrets, derived private endpoints, allowed-user checks, target-scoped follower Bot API allowlists, and liveness refreshes around forwarded updates/API calls. Impact: followers can use their assigned thread without gaining arbitrary bot control.
245
- - `Windows IPC`: Added native Windows named-pipe path selection for the local leader/follower bus alongside Unix socket support. Impact: Threaded Mode has an intended native Windows transport path, with live Windows smoke still tracked separately in the backlog.
246
- - `Diagnostics`: Expanded `/telegram-status`, `tmp/telegram/state.json`, and redacted `tmp/telegram/logs.jsonl` around runtime role, roster, capability state, reservations, thread reconciliation, and transport health, without making diagnostics files routing authority. Impact: operators and agents can inspect Threaded Mode health without depending on stale history.
247
- - `Validation`: Split Threaded Mode coverage across focused bus, leader, follower, runtime, integration, routing, lifecycle, and delivery tests. Impact: the release behavior is pinned by domain-owned regressions rather than one oversized integration bucket.
248
- - `Architecture`: Moved Threaded Mode logic out of `index.ts` into focused domains for bus protocol, leader runtime, follower runtime, thread bindings, synchronization, polling/capability switching, and reconciliation. The separate public `telegram.json` bus switch was removed from the product model and implementation. Impact: the public surface stays small, classic mode remains the base mode, Telegram private-chat Threaded Mode is the multi-instance switch, and product language consistently says thread while Bot API topics remain implementation details.
207
+ - `Threaded Mode`: Added Telegram private-chat threads as the automatic multi-instance switch while retaining classic private DM as the base singleton mode. One visible Pi leader owns polling/Bot API transport and operator-started followers join explicitly through `/telegram-connect`; Telegram never spawns hidden Pi processes. Impact: one bot can host scoped live Pi workspaces without competing pollers or a separate public bus setting.
208
+ - `Capability And Recovery`: Detects support from private-bot evidence (`getMe.has_topics_enabled`, incoming thread ids, and thread-operation results), monitors hot upgrade/downgrade without reload, and recovers across leader/follower reload, reconnect, heartbeat loss, promotion, explicit disconnect, stale cleanup, and same-profile resume. Impact: classic and Threaded modes converge through local process churn while preserving the intended binding where evidence permits.
209
+ - `Thread State And UX`: Added current-state bindings with explicit owners, stable slots, compact baked names, reservations, unbound reroute/restore, role/status controls, notices, and proof-before-delete reconciliation. Impact: reconnect and cleanup avoid duplicate live tabs, stale chooser surfaces, and destructive action against uncertain targets.
210
+ - `Target-Scoped Runtime`: Propagated `{ chatId, threadId? }` through inbound routing, per-instance queue/model/tool/lifecycle state, replies, previews, typing, voice, attachments, menus, sections, callbacks, reactions, media groups, commands, and follower Bot API calls. Impact: classic DM and each leader/follower thread share one transport contract without collapsing into a shared queue or cross-thread output.
211
+ - `Activity, Replies, And Responsiveness`: Kept activity native through `sendChatAction(typing)`, scoped it to real turns and applicable compaction while mirroring thread work to aggregate `All`, anchored only the first assistant block to the source message, preserved reply metadata through preview rollover, and moved ordered post-result Telegram side effects off Pi's critical completion path. Telegram Desktop may omit a reply header that mobile renders from the same valid payload. Impact: work stays visible and locally contextual without extra progress messages, stacked reply headers, or prolonged Pi busy state.
212
+ - `Proactive Follower Delivery`: Allowed an authenticated follower's successful local non-Telegram result to traverse leader transport into its assigned thread when proactive push is enabled. Impact: follower-owned work reaches mobile without granting unrelated processes arbitrary bot delivery.
213
+ - `Transport And Security`: Unified JSON, multipart, and download transport with redacted diagnostics and `PI_TELEGRAM_NETWORK_FAMILY=auto|ipv4|ipv6|ipv4-fallback`, defaulting to IPv4 fallback after dual-stack transport failures. Added leader secrets, private derived endpoints, owner checks, target-scoped follower allowlists, liveness refresh, Unix sockets, and native Windows named pipes; live Windows smoke remained an explicit follow-up. Impact: broken IPv6 hosts and both desktop transport families can participate without weakening local authorization.
214
+ - `Diagnostics And Architecture`: Added role, roster, capability, reservation, reconciliation, and transport-health projections to `/telegram-status`, observational `state.json`, and redacted `logs.jsonl`; diagnostics never become routing authority. Split bus protocol, leader/follower runtimes, thread state, sync, capability switching, and reconciliation into focused domains with matching regressions. Impact: operators can inspect Threaded Mode health while the public surface and composition root remain bounded.
249
215
 
250
216
  ## 0.17.5: Screenshot Refresh
251
217
 
@@ -282,16 +248,12 @@
282
248
 
283
249
  ## 0.16.6: Telegram Review Hardening Hotfix
284
250
 
285
- - `Guest Mode`: Deny `guest_message` updates until the bridge already has a paired Telegram user. Impact: guest mode can no longer become the first pairing surface or trigger guest file/handler processing before explicit DM pairing.
286
- - `Lifecycle`: Unref the compaction observer fallback timer when the host timer supports it. Impact: headless or shutdown paths are less likely to linger until the 5-minute safety timeout.
287
- - `Shutdown`: Stop polling before clearing active-turn/abort state, keep the abort controller visible until the polling promise settles, and record typing-cleanup failures without skipping polling abort. Impact: session shutdown and polling cleanup ordering is more deterministic.
288
- - `Replies`: Scope transport-level reply deduplication by chat id. Impact: equal Telegram message ids in different chats no longer suppress valid reply metadata for each other.
289
- - `Buttons`: Consume one-shot `telegram_button` callback actions after the first successful resolve. Impact: repeated taps on an old assistant-authored button no longer enqueue duplicate prompts.
290
- - `Buttons`: Centralized Telegram `callback_data` byte-limit guards for generated inline keyboards outside the section helper path. Impact: oversized generated button callbacks fail locally before Telegram rejects the message.
291
- - `Diagnostics`: Record `answerCallbackQuery` transport failures in runtime API diagnostics while keeping callback handling non-fatal. Impact: `/telegram-status` can explain failed Telegram callback acknowledgements instead of losing the signal silently.
292
- - `Tests`: Added regressions for shutdown during pending control, long-text, and media-group dispatch, for settings menu callbacks persisting voice/time changes to `telegram.json`, for malformed/boundary Markdown rendering, and for runtime outbound delivery retrying a transient Telegram API failure. Impact: high-risk queue/timer/settings/rendering/API paths are pinned at the bridge boundary.
293
- - `Docs`: Documented which environment-driven transport defaults should be set before launch because module-load constants intentionally capture them.
294
- - `Backlog`: Captured and narrowed the non-blocking 2026-06 review-swarm follow-ups for lifecycle shutdown hardening, reply/callback/button state cleanup, validation coverage, and bindings maintainability.
251
+ - `Guest Pairing`: Rejected `guest_message` updates until a Telegram owner has paired through DM. Impact: Guest Mode cannot become the first pairing surface or trigger file/handler processing before explicit authorization.
252
+ - `Lifecycle And Shutdown`: Unrefed the five-minute compaction fallback timer, stopped polling before clearing turn/abort state, retained the abort controller until the polling promise settled, and contained typing-cleanup failures without skipping polling abort. Impact: headless exit and session shutdown no longer linger or reorder transport cleanup unpredictably.
253
+ - `Reply Identity`: Scoped transport reply deduplication by chat id. Impact: equal Telegram message ids in different chats retain independent reply metadata.
254
+ - `Button Safety`: Consumed one-shot assistant button actions after first successful resolution and centralized callback-data byte-limit checks for generated keyboards. Impact: stale repeated taps cannot duplicate prompts and oversized callbacks fail locally before Telegram rejection.
255
+ - `Callback Diagnostics`: Recorded non-fatal `answerCallbackQuery` transport failures in runtime diagnostics. Impact: `/telegram-status` can explain acknowledgement failures without breaking callback handling.
256
+ - `Boundary Verification`: Added regressions for shutdown during pending control/long-text/media-group work, Settings voice/time persistence, malformed/boundary Markdown, and transient outbound API retry; documented environment-driven transport defaults that must exist before module load. Impact: the reviewed queue, timer, config, renderer, and API boundaries remain explicit without preserving review/backlog chronology.
295
257
 
296
258
  ## 0.16.5: Context-Aware Prompt Guidance Hotfix
297
259
 
@@ -355,58 +317,31 @@
355
317
 
356
318
  ## 0.13.0: Command Template Standard, Voice Hardening, And Domain Cleanup
357
319
 
358
- - `Architecture`: Extracted outbound assistant-action markup parsing into `lib/outbound-markup.ts` and removed the temporary Voice/Outbound/Queue import-cycle allowance. Impact: project source imports are fully acyclic again while preserving existing voice and outbound helper exports.
359
- - `Tests`: Updated the Pi SDK centralization invariant to guard the current `@earendil-works/*` package scope as well as the legacy scope. Impact: new direct SDK imports outside `lib/pi.ts` are caught again.
360
- - `Voice Providers`: Generated compatibility ids for STT/TTS providers now use monotonic counters with registry probing, and provider disposers now remove only their own registered instance. Impact: anonymous ids stay collision-safe across stale registry entries/module reloads, and stale disposers cannot delete replacement providers.
361
- - `Security`: Telegram temp directories, downloaded inbound files, and `locks.json` writes now use explicit private filesystem modes. Impact: private attachments and local polling ownership metadata are less exposed on permissive-umask or shared hosts.
362
- - `Docs`: Clarified that `voice.sendTranscript` is the bridge-owned transcript preference and updated provider examples to gate `transcriptText` with `getTelegramVoiceSendTranscript(config)`. Impact: companion voice providers no longer need to invent duplicate transcript/reply-policy UI.
363
- - `Tests`: Added a long-session runtime regression that preserves queued work across `/abort`, explicit `/next`, and in-flight model switching. Impact: the high-risk queue/dispatch path now has coverage for an operator session that chains abort recovery into model-switch continuation.
364
- - `Naming`: Renamed the concrete Bot API transport domain from `lib/api.ts` / `tests/api.test.ts` to `lib/telegram-api.ts` / `tests/telegram-api.test.ts`. Impact: the transport owner is clearer and no longer competes conceptually with the public `/api/*.ts` package membranes.
365
- - `Status`: `/telegram-status` recent runtime events now include a category summary before the detailed event list. Impact: provider, handler, and transport failure categories are easier to scan during companion-extension diagnostics.
366
- - `Tests`: Added a combined `telegram_voice` + `telegram_button` outbound planner smoke regression and corrected the text-group non-contiguous-tail fixture to reflect the widened split-message id gap. Impact: the rendering/markup watchlist now has direct coverage for mixed assistant action markup without changing runtime behavior.
367
- - `Audit`: Added fixture lifecycle coverage for STT/TTS provider re-registration across session-start/resume/reload-style boundaries, and scanned the local workspace for removed `@llblab/pi-telegram/lib/*` companion imports. Impact: the remaining hotfix lifecycle and migration audit items are now closed in this environment.
368
- - `Refactor`: Split assistant-authored button planning, callback storage, callback handling, and button prompt-turn construction from `lib/outbound.ts` into `lib/outbound-buttons.ts`, with symmetric `tests/outbound-buttons.test.ts` coverage. Impact: the outbound domain is smaller and button behavior now has a direct module-level test peer while existing `lib/outbound.ts` exports remain compatible.
369
- - `Tests`: Added symmetric `tests/outbound-markup.test.ts` coverage for `lib/outbound-markup.ts`, including top-level comment collection, fenced-code exclusion, partial-comment stripping, attribute parsing, and multi-voice planning. Impact: assistant action markup has direct module-level regression coverage instead of relying only on umbrella outbound tests.
370
- - `Tests`: Added symmetric `tests/menu-status.test.ts` coverage for `lib/menu-status.ts`, including status reply markup rows, voice-active thinking suppression, callback routing, and status message send/update helpers. Impact: status-menu behavior now has a direct module-level regression peer.
371
- - `Tests`: Added symmetric `tests/menu-thinking.test.ts` coverage for `lib/menu-thinking.ts`, including reply markup, thinking-level callbacks, invalid/voice/non-reasoning guards, and menu send/update helpers. Impact: thinking-menu behavior now has direct module-level regression coverage.
372
- - `Tests`: Added symmetric `tests/setup.test.ts` coverage for `lib/setup.ts`, including token defaults, prompt mode selection, setup success/failure, and prompt-runtime guard cleanup after errors. Impact: `/telegram-setup` prompt behavior now has direct module-level regression coverage.
373
- - `Tests`: Added symmetric `tests/menu-settings.test.ts` coverage for `lib/menu-settings.ts`, including built-in settings markup, detail menu active states, settings mutations, and stale-message fallback toggles. Impact: settings-menu behavior now has direct module-level regression coverage.
374
- - `Context`: Cleared the completed backlog down to `No open work` and tightened the `lib/outbound.ts` domain header after button/markup extraction. Impact: historical completion notes stay in the changelog, while backlog and domain ownership now reflect current reality.
375
- - `Refactor`: Split native Telegram voice delivery from `lib/outbound.ts` into `lib/outbound-voice.ts`, with symmetric `tests/outbound-voice.test.ts` coverage. Impact: outbound voice upload/provider orchestration now has a direct domain owner and `lib/outbound.ts` is reduced to the outbound surface, command handlers, text transforms, artifact composition, and compatibility re-exports.
376
- - `Command Templates`: Replaced `pi-telegram`'s command-template implementation with the current `pi-actors` standard as a deliberate breaking 0.x minor change. Impact: templates now use `parallel` and `when`, support string `timeout`/`delay`/`retry`, inherited default references, `{value??fallback}`, `{flag?yes:no}`, and empty-arg filtering; old local `mode`, `critical`, and `pipe` shapes were removed/migrated to `parallel`, `failure`, and `template: [...]`.
377
- - `Docs`: Removed real companion-extension identities from abstract voice-provider examples and README guidance, keeping concrete names only in the explicit Companion Extensions list. Impact: pi-telegram documentation now keeps bridge responsibilities separate from third-party companion-extension ownership.
378
- - `Docs`: Integrated public API smoke examples for Extension Sections, raw updates, inbound handlers, outbound handlers, and voice providers into `docs/public-api.md` using only stable public membranes. Impact: companion-extension authors get copyable patterns in the canonical public API guide and avoid removed `@llblab/pi-telegram/lib/*` imports.
379
- - `Docs`: Updated README release positioning and corrected Extension Sections docs so `ctx.edit()` owns automatic Back-row insertion, `ctx.open()` is documented as a standalone chat-message sender, and section callbacks appear before built-in menu callbacks. Impact: companion extension authors get an accurate public contract.
380
- - `Backlog`: Restored concrete near-term follow-up slices for public API migration, provider lifecycle, smoke examples, diagnostics, voice-domain DAG cleanup, section examples, and voice transcript config clarity. Impact: README's open-work link points to actionable development priorities again.
320
+ - `Command Templates`: Adopted the current shared command-template standard as a deliberate breaking 0.x minor change: `parallel` and `when`, string `timeout`/`delay`/`retry`, inherited default references, `{value??fallback}`, `{flag?yes:no}`, and empty-argument filtering replace the old local `mode`, `critical`, and `pipe` shapes through `parallel`, `failure`, and `template: [...]`. Impact: pi-telegram handler commands use the same portable execution contract as the wider Pi extension ecosystem.
321
+ - `Voice Providers`: Made generated STT/TTS compatibility ids monotonic and registry-probed, fenced disposers to their exact provider instance, and verified re-registration across session-start/resume/reload-style lifecycles. Clarified `voice.sendTranscript` as the bridge-owned transcript preference. Impact: anonymous providers avoid collisions, stale cleanup cannot remove replacements, and companion providers do not need duplicate transcript policy.
322
+ - `Outbound Actions`: Split assistant voice markup, button planning/callback prompt construction, and native voice delivery into acyclic `outbound-markup`, `outbound-buttons`, and `outbound-voice` owners with direct mirrored coverage while preserving supported outbound exports. Impact: voice/button composition remains compatible without the temporary Voice/Outbound/Queue cycle allowance or one oversized outbound domain.
323
+ - `Menus, Setup, And Diagnostics`: Added direct domain coverage for status, thinking, settings, and setup behavior—including callback guards, active states, stale-message fallback, token defaults, prompt cleanup, and mixed voice/button planning—and added category summaries before detailed `/telegram-status` runtime events. Impact: operator controls and failure categories are easier to verify and scan without relying on umbrella tests.
324
+ - `Architecture And Security`: Renamed the concrete Bot API domain to `telegram-api` to distinguish it from public package membranes, restored fully acyclic imports, guarded both current and legacy Pi SDK scopes through the central adapter invariant, and applied private modes to Telegram temp directories, inbound files, and ownership writes. Impact: domain ownership is clearer and local private data remains protected on permissive-umask or shared hosts.
325
+ - `Public Extension Guidance`: Moved Section, update, inbound/outbound handler, and voice-provider examples onto stable public membranes; documented `ctx.edit()` automatic Back navigation, standalone `ctx.open()`, callback order, neutral provider identities, and explicit companion lists. Impact: extension authors receive accurate copyable contracts without depending on removed `@llblab/pi-telegram/lib/*` paths or conflating bridge and provider ownership.
326
+ - `Runtime Verification`: Added focused long-session coverage across abort, explicit next, and in-flight model switching, plus markup, split-text, provider lifecycle, menu, setup, and migration audits. Impact: the release protects its high-risk queue and extension boundaries while omitting per-suite test chronology.
381
327
 
382
328
  ## 0.12.0: Public API Membranes, Telegram UX Safety, And Extension Interop
383
329
 
384
- - `Typing Status`: Auto-compaction now starts and stops the native Telegram `typing` keepalive like manual `/compact`, including timeout and shutdown cleanup. Active Telegram turns also re-arm typing on assistant message start/update events so transient provider/model errors cannot permanently leave a continuing run without Telegram activity feedback.
385
- - `Compaction Safety`: Telegram `/compact` now opens an inline confirmation dialog before manual compaction starts, protecting the operator from accidental taps near `/start`. The dialog follows the dedicated UI style guide: a bold text-only question with emoji only on the explicit `Yes, compact` and `No` buttons. Confirming edits the dialog directly to `Compaction started.` instead of showing a separate `Compaction confirmed.` step.
386
- - `Docs`: Added `docs/ui-style.md` as the focused style guide for inline buttons, toggles, tabs, option lists, cards, and dialogs.
387
- - `Docs`: Restructured `docs/architecture.md` into a clearer architectural map with runtime topology, domain ownership, core flows, extension surfaces, and operational behavior while pushing detailed UI/callback rules toward focused standards.
388
- - `Breaking API`: Renamed the public implementation domains to `lib/sections.ts`, `lib/updates.ts`, `lib/inbound.ts`, and `lib/outbound.ts`. Package exports now expose only the stable public API domains (`/sections`, `/updates`, `/inbound`, `/outbound`, `/voice`, `/keyboard`) and no longer expose the compatibility `./lib/*.ts` wildcard.
389
- - `Architecture`: Folded the public update-handler interop surface into `updates` and renamed the internal long-poll loop module back to `polling`, giving the pair concise one-word domains: `updates` for update contracts/classification/handler registry and `polling` for the `getUpdates` runtime. Entrypoint extraction now lives in `bindings`, a concrete pi-facing command/tool/lifecycle wiring boundary rather than a new product domain.
390
- - `Tests`: Added an architecture invariant and package self-import regressions that pin the `0.12.0` package exports to stable `/api` membranes with exact runtime export shapes and prevent accidental restoration of the removed `./lib/*.ts` wildcard.
391
- - `Docs`: Added `docs/public-api.md` as the public API map for commands, config, assistant markup, extension APIs, callback ownership, and public/internal stability boundaries.
392
- - `API`: Hardened Telegram Extension Sections by rejecting duplicate section ids and validating `ctx.callbackData()` against Telegram's 64-byte callback-data limit.
393
- - `API`: Added `registerTelegramUpdateHandler()` as the matrix-aligned low-level update bus name.
394
- - `API`: Documented the public low/high-level registration matrix: low-level buses (`updates`, `inbound`, `outbound`) intentionally have no ids, while high-level sections and voice providers use stable ids in new integrations.
395
- - `Settings UI`: Refined control conventions: boolean toggles use Capitalized horizontal `On`/`Off` with green active `On`, yellow active `Off`, and black inactive markers; state/navigation rows use Capitalized status values; horizontal tabs use capitalized labels with purple default-state and yellow elevated-state active markers; vertical option lists keep only the current value marked green; submenu navigation distinguishes `⬆️ Main menu` from deeper `⬆️ Back` rows; confirmation actions use explicit `Yes, ...` labels such as `🗜 Yes, compact`; added State & Navigation Buttons section to the style guide for buttons that show state and lead to a submenu.
396
- - `Config`: Time Injection Hidden mode now removes `time.injectionMode` from `telegram.json` instead of persisting `"hidden"`, matching Voice Reply Hidden semantics: missing key = default hidden state.
330
+ - `Breaking Public API`: Replaced the published `./lib/*.ts` wildcard with stable `/sections`, `/updates`, `/inbound`, `/outbound`, `/voice`, and `/keyboard` membranes backed by focused API entrypoints. Package self-import and architecture invariants pin exact runtime shapes and prevent accidental restoration of internal paths. Impact: extension consumers gain explicit stability boundaries through a deliberate breaking 0.x migration.
331
+ - `Interop Contracts`: Named the low-level update bus `registerTelegramUpdateHandler()`, documented low-level id-less update/inbound/outbound buses versus stable-id Sections/voice providers, rejected duplicate section ids, and enforced Telegram's 64-byte callback-data limit. Impact: extension identity and callback ownership remain predictable across platform surfaces.
332
+ - `Runtime Architecture`: Separated `updates` contracts/classification/handler registry from the `polling` long-poll runtime and placed Pi-facing command/tool/lifecycle composition in `bindings`. Added a public API map and restructured architecture docs around topology, ownership, flows, extension surfaces, and operational behavior. Impact: public and internal runtime boundaries are discoverable without introducing another product domain.
333
+ - `Compaction And Typing`: Added confirmation before manual `/compact`, edited the confirmed dialog directly to started state, and ran native typing for manual/automatic compaction with timeout/shutdown cleanup; active turns re-arm typing after assistant activity. Impact: accidental compaction is harder and continuing work does not remain visually silent after transient provider/model errors.
334
+ - `Telegram UI Standard`: Added the focused UI style guide and standardized toggle, tab, option, state/navigation, Back/Main-menu, and explicit confirmation labels/markers. Impact: Settings and inline controls share one readable interaction language instead of per-feature conventions.
335
+ - `Config Defaults`: Hidden Time Injection now removes `time.injectionMode` rather than persisting `"hidden"`, matching absent-key Voice Reply defaults. Impact: default-off prompt context stays represented consistently and minimally in `telegram.json`.
397
336
 
398
337
  ## 0.11.2: Queue Continuation, Compaction Safety, And Settings Polish
399
338
 
400
- - `Time Context`: Renamed the disabled time injection mode from `off` to `hidden` in Settings and config defaults, matching voice reply mode semantics where no prompt-context line is injected. Legacy `off` callbacks/config values are still treated as hidden.
401
- - `Settings UI`: Settings detail headings now show the current value immediately after the bold label in monospace style, making each submenu title double as the active setting summary.
402
- - `Entrypoint`: Removed root-level API re-exports from `index.ts`; public extension APIs remain available from their owning `lib/*` modules while the root file stays a default-only composition root.
403
- - `Continue Queue`: `/continue` now enqueues a standalone priority prompt without preserving already queued prompts as history. Impact: queued prompts stay iterative queue items instead of being folded into one combined `continue` prompt.
404
- - `Auto Compaction`: Observes native `session_before_compact` / `session_compact` events and blocks queued Telegram prompt dispatch while compaction is running, then resumes the queue after compaction settles. Impact: queued Telegram turns no longer race Pi auto-compaction and trigger `Cannot read properties of undefined (reading 'signal')` after compaction.
405
- - `Command Templates`: Updated the command-template helper library and regressions with typed placeholders, array-index placeholder resolution, repeat fanout from array length, unbounded default timeout semantics, and trusted-command warnings.
406
- - `Docs`: Updated the command-template standard with typed args, array placeholders, failure propagation, recover cleanup, and trust-boundary guidance.
407
- - `Docs`: Decomposed oversized architecture documentation blocks into focused sections for runtime ownership, queue validation, application menu shape, outbound actions, and interactive controls. Impact: the architecture entry point is easier to scan without changing runtime behavior.
408
- - `README`: Split queue reaction shortcuts into priority and removal lists, added `pi-xai-voice` as a companion extension, and kept the time-injection row label compact while preserving the full detail-heading label. Impact: operator-facing docs match the current Telegram menu language.
409
- - `Context`: Recorded the convention that extension-local standards should stay self-contained and avoid naming sibling extension implementations as authorities. Impact: shared standards can evolve independently without creating false extension dependencies.
339
+ - `Time And Settings`: Renamed disabled time injection from `off` to absent-key `hidden` while accepting legacy values/callbacks, and showed each Settings detail's current value beside its heading. Impact: time and voice defaults share one vocabulary and submenus expose active state immediately.
340
+ - `Continue Queue`: Made `/continue` enqueue one standalone priority prompt without folding existing queued prompts into history. Impact: waiting prompts remain iterative queue items rather than becoming hidden context inside a synthetic continuation.
341
+ - `Compaction Safety`: Observed native `session_before_compact` / `session_compact`, blocked Telegram dispatch during compaction, and resumed after settlement. Impact: queued turns no longer race automatic compaction or enter Pi through an invalidated signal.
342
+ - `Command Templates`: Added typed and array-index placeholders, repeat fanout from array length, unbounded default timeout semantics, failure/recover behavior, and trusted-command warnings with matching self-contained standard documentation. Impact: handler templates gained richer portable composition without treating sibling extensions as authorities.
343
+ - `Public Boundary`: Removed root-level API re-exports so `index.ts` remains a default-only composition root and extension APIs stay with owning modules. Impact: runtime composition and reusable contracts no longer share an accidental package surface.
344
+ - `Documentation`: Split oversized architecture material into focused ownership, queue, menu, outbound-action, and interactive-control sections; aligned README reaction groups, companion listing, and time labels with the UI. Impact: operator and maintainer entrypoints became easier to scan without runtime change.
410
345
 
411
346
  ## 0.11.1: Time Context And Settings Polish
412
347
 
@@ -415,24 +350,13 @@
415
350
 
416
351
  ## 0.11.0: Voice Provider Platform
417
352
 
418
- - `Voice Synthesis Provider API`: Added a first-class voice synthesis provider surface for Telegram voice replies. Providers register with `registerTelegramVoiceSynthesisProvider()` from `@llblab/pi-telegram/lib/voice.ts`, synthesize text into `.ogg`/`.opus`, may return `{ audioPath, transcriptText }`, and can contribute voice-specific prompt guidance through `getVoicePromptContribution(view)`.
419
- - `Voice Prompt Context`: Replaced the redundant `[The user sent a voice message.]`: prompt marker with compact voice context owned by pi-telegram: `[voice] reply mode: manual`, `[voice] reply mode: mirror`, or `[voice] reply mode: always`. The marker is placed after handler `[outputs]`: when present, otherwise after `[attachments]`, and can expand to a `[voice]`: list when more fields are added.
420
- - `Voice Reply Policy`: Missing or invalid `telegram.json` `voice.replyMode` now resolves to `manual` regardless of provider defaults. Provider UIs can still change policy by writing `voice.replyMode` to the same config file pi-telegram reads.
421
- - `Voice Reply Policy`: Added `voice.replyMode` with `manual`, `mirror`, and `always` modes. The bridge tags voice turns, suppresses previews for voice-tagged replies, and transparently converts implicit assistant text to voice when policy asks for it while explicit `<!-- telegram_voice -->` markup still wins.
422
- - `Status UI`: Removed extension-section diagnostics from the Telegram status text. Section state belongs on dynamic section button labels and submenus, while `/telegram-status` keeps runtime/transport diagnostics focused.
423
- - `Extension Sections`: Main-menu section rows now support a dynamic `getLabel()` function, matching Settings rows, so extensions can surface live state directly on their button labels.
424
- - `Prompt Guidance`: Clarified `[voice`: turn context in the Telegram system prompt: `manual` means normal agent-authored output with optional explicit `telegram_voice` markup, `mirror` means voice input prefers voice output, and `always` means replies should stay TTS-friendly for automatic conversion.
425
- - `Config Interop`: Added a narrow live config runtime so companion voice sections can update `telegram.json` voice policy and the active pi-telegram config store in one step.
426
- - `Voice Delivery`: Restored outbound `type: "voice"` command handlers as the explicit first leg of voice delivery, followed by programmatic handlers and registered voice synthesis providers as zero-config fallbacks, so operator-configured `telegram.json` TTS handlers are never overridden by provider extensions.
427
- - `Inbound Handler API`: Added `registerTelegramInboundHandler(kind, handler)` as the generic programmatic counterpart to configured `inboundHandlers`, completing the handler/provider matrix beside `registerTelegramOutboundHandler`, `registerTelegramVoiceTranscriptionProvider`, and `registerTelegramVoiceSynthesisProvider`.
428
- - `Voice Transcription Provider API`: Added `registerTelegramVoiceTranscriptionProvider()` for provider-owned STT. Explicit inbound handlers and programmatic inbound handlers still run first; registered STT providers are fallback for voice/audio files without handler output.
429
- - `Settings UI`: Added built-in voice reply mode controls to pi-telegram Settings and removed the need for provider extensions to own duplicate reply-policy UI; the selector persists `voice.replyMode` to `telegram.json` even from stale visible menu messages and uses the `👄 Voice reply: hidden|manual|mirror|always` row with lowercase model-style active dots.
430
- - `Voice Prompt Context`: Missing or invalid `voice.replyMode` is now surfaced in Settings as `hidden`: it behaves like `manual`, emits no `[voice] reply mode: manual` prompt-context block, and stores no `voice.replyMode`; explicit `manual` keeps the same behavior but renders context. `mirror` mode text-originated turns stay on the manual text path, including support for explicit `telegram_voice` markup.
431
- - `Voice Delivery`: Voice delivery now uses Telegram `sendVoice` plus the native `record_voice` chat action. Providers own speech rewriting, TTS, and OGG/Opus conversion; non-OGG provider output fails voice delivery and falls back to the planned text reply.
432
- - `Voice Fallbacks`: Voice artifact failures now throw to the queue runtime, which records diagnostics and sends the planned text fallback with outbound markup stripped and reply markup preserved when no text was already delivered.
433
- - `Voice Platform Cleanup`: Collapsed merged prototype-only domains: removed shared `globals`, `global-augmentations`, and broad `shutdown` cleanup modules. Voice, section, external-handler, and outbound-handler global registry keys are now owned by their respective domains, and session shutdown no longer clears every extension registry globally.
434
- - `Docs`: Added `docs/voice.md` and README coverage for voice modes, provider registration, STT provider fallbacks, caption-style transcripts, native voice format requirements, fallback behavior, and provider-owned settings.
435
- - `Tests`: Added voice policy, provider registry, preview suppression, artifact delivery, fallback, OGG/Opus validation, prompt contribution, and entrypoint/invariant regressions. Full validation passes with 575 tests.
353
+ - `Voice Provider APIs`: Added provider-owned STT and TTS registration with optional prompt contribution and `{ audioPath, transcriptText }` synthesis results. Configured/programmatic inbound handlers remain ahead of STT fallback; configured outbound `type: "voice"` handlers remain ahead of programmatic handlers and TTS providers. Impact: extensions can supply zero-config transcription/synthesis without overriding operator pipelines.
354
+ - `Voice Policy And Context`: Added bridge-owned `voice.replyMode` (`manual`, `mirror`, `always`) plus the silent `hidden` Settings default for absent/invalid config. Voice turns carry compact `[voice]` context after outputs/attachments, implicit text converts only when policy requests it, explicit `telegram_voice` wins, and mirror leaves text-originated turns on the text path. Impact: one persisted policy coordinates model guidance, preview suppression, and automatic conversion without provider defaults silently changing behavior.
355
+ - `Voice Settings And Interop`: Added built-in Settings controls with stale-message persistence, a narrow live config runtime for companion sections, dynamic section labels, and focused section state outside Telegram status text. Impact: pi-telegram owns reply policy while providers can reflect and update it without duplicate UI or polluting runtime diagnostics.
356
+ - `Native Delivery And Fallback`: Sent voice through `sendVoice` with `record_voice`, required OGG/Opus provider output, and routed synthesis/artifact failures through queue diagnostics to a markup-stripped text fallback with preserved reply keyboard when text had not already landed. Impact: voice delivery uses Telegram-native format and activity without losing the planned answer on provider failure.
357
+ - `Handler Matrix`: Added generic programmatic inbound registration beside outbound handlers and STT/TTS providers. Impact: configured commands, programmatic handlers, and provider fallbacks form one explicit precedence model for inbound and outbound voice work.
358
+ - `Platform Cleanup`: Removed prototype shared globals/global augmentations and broad shutdown registry clearing; each voice, section, inbound, and outbound registry owns its key and lifecycle. Impact: session shutdown cannot erase unrelated extension registrations, and voice integration no longer requires shared-bucket domains.
359
+ - `Documentation And Verification`: Added the voice guide and focused coverage for policy, registries, prompt context, preview suppression, artifact delivery, OGG/Opus validation, fallback, prompt contribution, and runtime invariants. Impact: provider authors receive one documented native-format and failure contract without test-count chronology.
436
360
 
437
361
  ## 0.10.8: Compact Typing Timing Hotfix
438
362
 
@@ -481,21 +405,12 @@
481
405
 
482
406
  ## 0.10.0: Extension Sections Platform
483
407
 
484
- - `Extension Sections`: Implemented the Telegram Extension Sections platform: extensions can register structured UI sections that appear in the main Telegram application menu and Settings submenu without owning a second bot poller.
485
- - `Registry`: Added `lib/extension-sections.ts` with a section registry (`createTelegramExtensionSectionRegistry`), token-based callback routing (`section:<token>:<action>:<payload>`), main-menu row injection, settings submenu row injection, `registerTelegramSection()` globalThis bridge for ordinary pi extensions, and diagnostics.
486
- - `API`: Exported `registerTelegramSection(section)` / `getTelegramSectionDiagnostics()` from `@llblab/pi-telegram/lib/extension-sections.ts`. Extensions receive narrow typed context ports (`TelegramSectionContext` / `TelegramSectionCallbackContext`) with `answerCallback`, `edit`, `open`, and `enqueuePrompt`.
487
- - `Main Menu`: Section rows are injected before the built-in **Settings** row in the status/application menu. Sections render their own inline-keyboard views with an automatic `⬆️ Main menu` back button.
488
- - `Settings Submenu`: Extension settings rows appear before built-in settings controls. Each section can expose an optional `settings` block with its own `open` and `handleCallback`.
489
- - `Callback Routing`: `section:` is now a pi-telegram-owned callback prefix. Section callbacks are dispatched before built-in menu handling. Stale tokens receive a graceful "no longer available" answer. Unknown section callbacks fall through to the existing callback namespace fallback.
490
- - `Menu Integration`: Updated `menu-status.ts` to accept a `sectionRegistry` and inject section rows before Settings. Updated `menu-settings.ts` to accept a `sectionRegistry` and inject extension settings rows before built-in controls. Updated `menu.ts` to parse and dispatch `section:` callbacks through the registry.
491
- - `Demo`: Added `@llblab/pi-telegram-extension-demo` — a companion pi extension demonstrating section registration, a read-only Explorer UI with prompt enqueue, and a settings toggle. The demo lives in `extensions/pi-telegram-extension-demo/`.
492
- - `Model Labels`: Model button labels now use compact `provider/ModelId` format (e.g., `anthropic/claude-sonnet-4-5`) instead of `ModelId [provider]`. Models are sorted by provider for predictable grouping. The status row and detail view already used this canonical format.
493
- - `Navigation`: Section `ctx.edit()` and `ctx.open()` automatically prepend the correct Back button: `⬆️ Main menu` → `menu:back` at root level, `⬆️ Back` → `section:<token>:open` from section callbacks, `⬆️ Back` → `settings:list` from settings callbacks. Back buttons are deduplicated when already present.
494
- - `Settings Status`: Settings rows now support a dynamic `getLabel()` function for live status indicators (e.g., `🟢`/`⚫️` based on internal state). Called on every Settings list render, no polling needed.
495
- - `Context`: Added `callbackData(action, payload?)` to section context types — section authors never hand-roll `section:` callback strings. Tokens are filled in automatically.
496
- - `CLI`: Removed `/telegram-settings` from pi CLI commands. Telegram settings remain available through the Telegram `/settings` inline menu. Keeps the pi TUI simple.
497
- - `Demo`: Renamed `@llblab/pi-telegram-demo` → `@llblab/pi-telegram-extension-demo` with a standalone `package.json` depending on `@llblab/pi-telegram` ^0.10.0, a comprehensive `README.md`, and a GitHub repository reference. Proves third-party devs can extend the pi-telegram interface as an ordinary npm package.
498
- - `Tests`: Added 26 regression tests in `tests/extension-sections.test.ts` covering registry lifecycle, main-menu and settings row ordering, callback parsing, section open/callback/settings-open dispatch, stale token handling, handler fallback, and back-button dedup.
408
+ - `Extension Sections`: Added a registry and extension-facing API for structured main-menu and Settings views without another bot poller. Stable tokens map `section:<token>:<action>:<payload>` callbacks to narrow contexts with answer, edit, open, prompt enqueue, generated callback data, and diagnostics. Impact: ordinary Pi extensions can add Telegram-native UI without raw bot access or hand-built callback namespaces.
409
+ - `Menu And Settings Integration`: Injected extension rows before built-in Settings/controls, supported optional section settings and dynamic status labels, and dispatched owned section callbacks before built-in menu handling. Stale tokens fail gracefully and unclaimed actions retain the existing namespace fallback. Impact: extension state and controls compose with the application menu without polling or callback ownership conflicts.
410
+ - `Navigation`: Automatically added and deduplicated context-correct Main menu/Back rows for root, section callback, and settings callback edits/opens. Impact: section authors receive consistent navigation without manually constructing token-bearing return buttons.
411
+ - `Companion Demo`: Published the standalone `@llblab/pi-telegram-extension-demo` package/repository with section registration, read-only Explorer prompt enqueueing, settings toggle, and documentation. Impact: the platform had an installable third-party example rather than an in-repository-only concept.
412
+ - `Operator UI`: Standardized model labels and sorting as compact `provider/ModelId`, and removed the redundant Pi-side `/telegram-settings` command while retaining Telegram `/settings`. Impact: model lists group predictably and Settings remain on their owning mobile surface.
413
+ - `Verification`: Added direct coverage for registry lifecycle, row ordering, callback parsing/dispatch/fallback, section and settings opens, stale tokens, and Back-button deduplication. Impact: the initial Sections platform contract is protected without per-file integration chronology.
499
414
 
500
415
  ## 0.9.9: Guest Mode HTML Rendering
501
416
 
@@ -513,15 +428,10 @@
513
428
 
514
429
  ## 0.9.7: Bot API 10.0 Alignment
515
430
 
516
- - `Dependencies`: Migrated peer dependencies and imports from `@mariozechner/*` to `@earendil-works/*` (`pi-agent-core`, `pi-ai`, `pi-coding-agent`). Impact: the extension now tracks the new `@earendil-works` package scope; transitive `@mariozechner` packages remain in the lockfile until their upstreams migrate.
517
- - `Package`: Added `engines: { "node": ">=22.0.0" }` to document the supported Node expectation while keeping dev dependencies on `latest` for early-stage iteration. Impact: users know the minimum Node version without constraining the development dependency matrix prematurely.
518
- - `Polling`: Added `"guest_message"` to `TELEGRAM_ALLOWED_UPDATES` so the bot receives guest-mode updates. Impact: without this, guest mentions are silently ignored by Telegram.
519
- - `Telegram API`: Updated `sendMessageDraft` wrapper for Bot API 10.0 semantics: removed the empty-text guard, made `text` optional, and added optional `parse_mode`, `entities`, and `message_thread_id` parameters. Impact: preview can now show a "Thinking…" placeholder with empty text, and callers can pass rich formatting through `parse_mode` or `entities`.
520
- - `Telegram API`: Added `answerGuestQuery` to the API runtime for Bot API 10.0 Guest Mode support. Impact: callers can reply to guest queries in chats where the bot is not a member. Uses `InlineQueryResultArticle` as the result payload per Bot API 10.0 contract.
521
- - `Updates`: Extended inbound update routing to recognize `guest_message` updates. Added `getAuthorizedTelegramGuestMessage`, guest flow action, execution plan, runtime handler, and prompt enqueue support. Unauthorized guest queries receive an "Access denied." reply via `answerGuestQuery`. Guest turns customize the agent-end delivery to use `answerGuestQuery` instead of normal reply transport. Impact: the bridge can now receive and route guest-mode mentions in group chats while preserving the existing private-message authorization model.
522
- - `Runtime`: Added typing-loop skip for guest turns (`chatId === 0`) to avoid spurious `sendChatAction` errors in the status bar.
523
- - `Tests`: Added regression tests for empty-text draft delivery, undefined-text draft delivery, rich preview with `parse_mode` and `entities`, guest query answers, guest extraction, guest flow classification, guest execution plan, guest deny reply, and guest message routing through the runtime.
524
- - `Preview`: Updated `sendDraft` interface in `lib/preview.ts` to accept optional text and formatting options, keeping the preview pipeline aligned with the new API wrapper.
431
+ - `Runtime Baseline`: Migrated Pi peer imports to `@earendil-works/*` and declared Node `>=22.0.0`, while historical transitive `@mariozechner` packages remained until upstream migration. Impact: the extension tracks the maintained Pi package scope and states its runtime floor without pinning development dependencies.
432
+ - `Guest Mode`: Admitted `guest_message` updates, added authorized extraction/planning/runtime prompt flow, denied unauthorized queries, and delivered Guest finals through Bot API 10.0 `answerGuestQuery` article results instead of normal chat replies. Impact: the bridge can answer mentions where the bot is not a member while preserving private-owner authorization.
433
+ - `Draft API`: Aligned `sendMessageDraft` and preview contracts with Bot API 10.0 by allowing absent/empty text plus optional parse mode, entities, and thread id. Impact: previews can carry rich formatting and empty-text thinking placeholders through one typed path.
434
+ - `Guest Presence And Verification`: Suppressed chat-action typing for guest sentinel targets and added focused coverage for drafts, formatting, guest answers/extraction/classification/planning/denial, and runtime routing. Impact: Guest Mode avoids spurious status errors and its new API/update boundaries remain protected without separate test chronology.
525
435
 
526
436
  ## 0.9.6: Runtime Adapter Positioning
527
437
 
@@ -617,23 +527,13 @@
617
527
 
618
528
  ## 0.7.0: Unified App Menu & Command Template Hardening
619
529
 
620
- - `Commands`: Visible Telegram bot command menu now exposes `/start`, `/compact`, `/next`, `/continue`, `/abort`, and `/stop`; `/help`, `/status`, `/model`, `/thinking`, and `/queue` remain hidden compatibility shortcuts. `/start`, `/help`, and `/status` open one unified app menu containing command help, status rows, and inline controls. Command emoji are centralized as fixed adornments in the commands domain and reused by matching menu buttons (`🤖` model, `🧠` thinking); `/next` uses `⏩` and `/continue` uses `▶️`. `/continue` enqueues a priority Telegram-owned `continue` prompt instead of forcing the next queued item or requiring Pi to be idle. Impact: the visible command surface is cleaner while existing operator muscle memory still works and skills can react to queued `continue` prompts.
621
- - `Application Menu`: `/start` opens command help plus status rows and the inline application menu; `/queue` opens the queue section directly, the status menu Queue button shows the current queued-item count, all submenus keep Back/Main menu navigation in the top row, and queued items are listed in dispatch order with numeric labels plus `⚡`/`📎` markers. Queue menu message text uses the same HTML heading style as the other inline menus; empty queue menus render bold message text with only the Main menu navigation button instead of a disabled empty-state button. Item submenus support Back, Priority/Normal tabs, and Cancel, and stale item clicks refresh the live list. Impact: queued Telegram work is inspectable and mutable from the menu control surface without relying only on reactions.
622
- - `Prompt Templates`: `/start` now shows a separate block for Pi prompt-template commands, and the Telegram bot command menu registers Telegram-safe prompt-template aliases such as `fix-tests` → `/fix_tests` when they do not conflict with built-in bridge commands or hidden shortcuts. Sending `/template_name args` from Telegram expands the matching Pi prompt-template file before queueing the turn. Impact: reusable Pi workflows are available from Telegram without duplicating prompt text manually.
623
- - `Keyboard`: Shared Telegram inline-keyboard reply-markup structure was extracted to `keyboard`, while `menu` owns application-control button semantics and `outbound-handlers` owns assistant-authored button semantics. Impact: inline UI domains share one Bot API shape without centralizing feature behavior.
624
- - `Domain DAG`: Source-module opening comments now include `Zones:` tags for cross-cutting responsibility areas such as Telegram transport, Pi agent lifecycle, TUI, and shared utilities. Impact: flat files keep folder-like orientation without adding directory nesting.
625
- - `Menu Refactor`: Queue-menu UI moved from `menu.ts` into the flat `menu-queue` domain while core queue mechanics remain in `queue`; model-menu state, scoped model pages, callback planning, and model-menu rendering moved into the flat `menu-model` domain while core model semantics remain in `model`; thinking-menu text, markup, callbacks, and rendering moved into the flat `menu-thinking` domain; status-menu payloads, callbacks, and rendering moved into the flat `menu-status` domain. Impact: `menu.ts` is smaller and queue/model/thinking/status control surfaces have dedicated UI boundaries without adding folders or changing Telegram behavior.
626
- - `Menu`: Busy-state messages now mention `/abort`, `/next`, and `/stop`; submenu main navigation uses top-row `⬆️ Main menu`; thinking-menu text is a compact bold heading because the selected level is already marked in the buttons; model-menu scope and pagination controls now sit at the top under Main menu, and the pagination indicator opens a compact `<b>Choose a page:</b>` picker with numbered page buttons.
627
- - `Queue Reactions`: Priority reactions now accept `👍`, `⚡️`, `❤️`, and `🕊`; removal reactions now accept `👎`, `👻`, `💔`, and `💩`. Impact: users can use more default Telegram reactions for queue control while keeping the same priority/removal semantics.
628
- - `Config`: `telegram.json` persistence now writes through a private temp file and atomic rename before restoring `0600` permissions. Impact: concurrent setup/status reload paths and interrupted writes no longer expose readers to a truncated JSON file.
629
- - `Status`: Main-menu status output now renders `Status: idle|active|pending|unknown` as a normal status row instead of a standalone heading; TUI status-bar `active` uses the `warning` color token.
630
- - `Reply Dedup`: Only the first agent message in a turn replies to the triggering prompt; subsequent messages skip `reply_to_message_id`. Impact: stacked reply headers no longer waste vertical viewport space—the first message anchors the thread and the rest deliver as independent messages. Implemented at the transport level in `buildTelegramReplyParameters` so preview delivery, voice upload, and all text paths are caught uniformly. Reset on `agent_start` via `lifecycle.ts`.
631
- - `Command Template`: Default timeout of 30s (`DEFAULT_COMMAND_TIMEOUT_MS`) is now exported and enforced; handler invocations may omit explicit `timeout` where the default is sufficient.
632
- - `Command Template`: `critical` field standardised: when `true`, leaf failure aborts the entire root composition. `attachment-handlers.ts` and `outbound-handlers.ts` composition loops implement fail-open default (continue on non-critical failure) with critical re-throw gating. Impact: the TTS pipeline (edge-tts → ffmpeg) can mark ffmpeg as critical and abort cleanly.
633
- - `Docs`: Handler documentation and README examples now rely on default command timeouts and keep config examples minimal; critical-step guidance remains where needed.
634
- - `Typing Safety`: Typing-loop send failures now update the live status through the prompt-dispatch context and still record diagnostics. Impact: transient typing failures are visible without relying only on `/telegram-status`.
635
- - `Type Safety`: Preview reply markup now flows through generic preview controller/runtime and agent-end finalization contracts instead of `any`. Impact: assistant-authored buttons keep their concrete inline-keyboard type through preview finalization without narrowing future preview transports.
636
- - `Tests`: 416 passing (was 402 before prompt-template command coverage): reply dedup, critical composition gating, queue controls, queued `/continue`, unified app menu/status rows, menu-domain splits, queue-menu navigation order, preview reply-markup typing, prompt-template command expansion, and transport-level reply-parameter dedup are all covered.
530
+ - `Unified Commands`: Reduced the visible bot menu to `/start`, `/compact`, `/next`, `/continue`, `/abort`, and `/stop` while retaining help/status/model/thinking/queue compatibility shortcuts. Start/help/status open one command-help, status, and inline-control surface; `/continue` queues a priority Telegram-owned continuation instead of forcing normal queue dispatch. Impact: the primary mobile command surface became smaller without breaking existing operator shortcuts.
531
+ - `Queue Menu And Reactions`: Added queue count, dispatch-order item lists, priority/attachment markers, item detail with Priority/Normal/Cancel actions, stale-list refresh, consistent top-row navigation, and direct `/queue` entry. Expanded default Telegram reactions for priority and removal. Impact: operators can inspect, reprioritize, normalize, or cancel waiting work from menus or reactions.
532
+ - `Prompt Templates`: Discovered Pi prompt-template commands, generated conflict-safe Telegram aliases such as `/fix_tests`, displayed them separately in `/start`, and expanded template files plus arguments before queueing. Impact: reusable Pi workflows became phone-accessible without duplicating prompts or exposing arbitrary commands.
533
+ - `Menu Domains And UI`: Split queue, model, thinking, and status views into flat owning domains over one shared keyboard shape, added `Zones:` responsibility tags, and standardized busy guidance, status rows, top navigation, compact thinking state, model scope/page controls, and page picker behavior. Impact: inline controls gained consistent operator UX and dedicated testable boundaries without centralizing feature semantics.
534
+ - `Runtime Safety`: Published `telegram.json` through private atomic replacement, anchored only the first assistant message to the triggering Telegram prompt, surfaced typing-loop failures in live status plus diagnostics, and carried concrete reply-markup types through preview finalization. Impact: interrupted config writes, stacked reply headers, hidden typing failures, and untyped button finalization no longer degrade the mobile session.
535
+ - `Command Templates`: Enforced and exported a 30-second default timeout and standardized fail-open composition with an optional `critical` leaf that aborts the root pipeline; handler docs and examples use the default unless a critical step needs explicit guidance. Impact: ordinary handler failures can fall through while required pipeline steps such as media conversion fail cleanly.
536
+ - `Regression Coverage`: Added focused coverage for unified menus/status, queue mutation and reactions, queued continuation, prompt-template expansion, reply dedup, critical composition, menu-domain navigation, and preview keyboard typing. Impact: the final 0.7.0 operator and handler contracts are protected without retaining test-count chronology.
637
537
 
638
538
  ## 0.6.3: Outbound Action Syntax & Prompt Guidance
639
539
 
@@ -693,65 +593,22 @@
693
593
 
694
594
  ## 0.3.0: Modular Runtime, Queue Controls, Diagnostics
695
595
 
696
- ### Runtime Architecture
697
-
698
- - `Flat Domain DAG`: The extension now uses `index.ts` as the single composition root over flat, acyclic `/lib` domains. API transport, persisted config/pairing, model control, queue/lifecycle, runtime state, commands, menu UI, polling, previews, replies, rendering, media, turns, attachments, updates, setup, status, pi SDK adapters, and registration each have explicit ownership. Impact: bridge behavior is easier to locate without introducing a second entrypoint or shared bucket modules.
699
- - `Composition Root`: `index.ts` now focuses on live pi/Telegram ports, session-local state, and cross-domain wiring. Stable defaults and local adapters for rendering, preview limits, preview reply metadata, attachment limits, Telegram prompt prefixes, prompt suffixes, command control items, bot command registration, API runtime construction, polling controllers, prompt dispatch, reply delivery, setup prompts, queue/session lifecycle, agent hooks, and tool hooks live in their owning domains. Impact: the entrypoint is smaller and reads as orchestration instead of carrying domain behavior.
700
- - `Type Boundaries`: Concrete Bot API transport shapes live in `api`, queued/active turn contracts live in `queue`, persisted session state lives in `config`, media download metadata lives in `media`, model selection contracts live in `model`, and domain constants stay with their owners. Narrow structural view contracts are used where a domain only needs a projection. Impact: public module interfaces are cleaner and accidental cross-domain coupling is reduced.
701
- - `Runtime State`: `runtime` owns only session-local coordination primitives: queue/control/priority counters, lifecycle flags, setup guards, abort handler storage, typing-loop timers, prompt-dispatch lifecycle binding, and agent-end reset sequencing. Preview state, queue planning, command behavior, rendering, and API transport stay outside `runtime`. Impact: mutable bridge state is centralized without becoming a general-purpose behavior bucket.
702
-
703
- ### Queue, Lifecycle, And Controls
704
-
705
- - `Queue Core`: `queue` owns prompt/control item contracts, explicit control/priority/default lane admission rules, queue stores, active-turn state, queue mutation, dispatch readiness, prompt enqueueing, control enqueueing, session start/shutdown sequencing, and agent/tool lifecycle hooks. Impact: scheduling rules, active-turn binding, abort preservation, compaction guards, and dispatch safety are enforced in one place.
706
- - `Command Admission`: `/stop`, `/compact`, `/help`, and `/start` execute immediately, while `/status`, `/model`, and model-switch continuation prompts enter the control lane ahead of normal prompts. Priority reactions promote waiting prompts into the priority lane without bypassing control actions. Asynchronous control-item execution is serialized so new prompts or controls cannot dispatch while a queued `/status` or `/model` action is still settling. Impact: Telegram controls stay responsive while normal messages remain predictably ordered.
707
- - `Model Control`: `model` owns model identity, thinking levels, scoped model pattern parsing/resolution/sorting, current-model state, in-flight model-switch state, restart eligibility, delayed abort decisions, continuation prompt construction, and model-switch controller runtime binding. Impact: model selection, scoped menus, and in-flight restart behavior have one cohesive home.
708
- - `Commands And Menus`: `commands` owns slash-command parsing, command metadata, command-message targets, command execution modes, control-queue adapters, bot command registration, and stop/compact/status/model/help side effects. The Telegram bot command menu no longer exposes `/debug`; diagnostics live in pi-side `/telegram-status` and the pi TUI. `menu` owns inline status/model/thinking UI state, model-menu caching, callback routing, callback planning, render payloads, and menu message updates. Impact: Telegram controls can be tested without reading the full runtime composition.
709
-
710
- ### Telegram Delivery, Rendering, And Files
711
-
712
- - `Rendering`: `rendering` owns Telegram HTML Markdown scanning, escaping, preview snapshots, raw HTML chunking, long-message splitting, table/list formatting, grapheme/display-width-aware table padding for emoji and wide Unicode text, nested quote flattening, link safety, task-list handling, and literal code preservation. Impact: Telegram output stays readable on narrow clients while avoiding malformed HTML and broken code blocks.
713
- - `Registration`: The Telegram before-agent prompt suffix now reminds the assistant to prefer narrow table columns because Telegram is often read on phone-width screens where wide monospace tables become unreadable. Impact: Telegram-originated tabular answers are more likely to fit mobile chats before renderer-level formatting is applied.
714
- - `Preview And Replies`: `preview` owns streaming preview lifecycle, draft/editable-message transport choices, flush scheduling, preview finalization, and assistant-message hooks, while defaulting preview reply metadata through the `replies` helper instead of threading it through `index.ts`. `replies` owns final rendered-message delivery, reply parameters, assistant-message extraction, plain/Markdown replies, interactive message delivery, and split-message reply metadata. Impact: rich previews, final replies, errors, attachment notices, and uploads are tied to the source Telegram prompt when possible and degrade safely when Telegram cannot attach the reply.
715
- - `Files And Attachments`: `api` owns Bot API calls, retries, runtime error recording, temp-dir cleanup, inbound file limits, lazy bot-token clients, chat actions, and file downloads. `media` owns inbound text/media extraction, file-info normalization, media-group debounce, and download assembly. `attachments` owns outbound attachment queueing, atomic multi-file staging, stat checks, outbound limits, photo/document classification, and queued attachment sending. Impact: inbound downloads and outbound uploads are size-limited by default, large files fail predictably without leaving partial attachment batches staged, and outbound artifacts flow through `telegram_attach`.
716
- - `Config And Setup`: `config` owns `telegram.json`, bot-token/allowed-user state, single-user authorization, and first-user pairing. `setup` owns token prompting, stored-token/env fallback selection, validation, and guarded setup orchestration. Impact: pairing and setup behavior stays consistent across `/telegram-setup`, `/telegram-connect`, `/start`, and update routing.
717
-
718
- ### Observability, Packaging, And Validation
719
-
720
- - `Status And Diagnostics`: `/telegram-status` now reports bridge diagnostics as grouped line-by-line pi notification sections separated by blank lines, ending with the redacted recent runtime/API event ring after connection, polling, execution, and queue state such as active turn, queue depth, queue lanes, compaction, active tool count, and pending model-switch state. Transport/API failures, polling/update failures, prompt dispatch failures, control action failures, typing failures, compaction failures, setup failures, session lifecycle failures, and attachment queue/delivery failures are recorded in the ring, while benign unchanged edit responses and empty draft-clear attempts do not pollute it. Impact: operators can diagnose bridge stalls and transport/runtime failures after the fact without exposing a Telegram-side debug command.
721
- - `Package Contents`: The npm package uses an explicit allowlist and keeps the tracked lockfile. Impact: published tarballs exclude tests and internal context files while preserving predictable release contents.
722
- - `Validation`: The project now ships typecheck, test, audit, package dry-run, and combined `validate` scripts plus GitHub Actions validation. Regression coverage spans rendering fixtures, queue/runtime/session behavior, command admission, lane contracts, invalid-lane rejection, setup, registration, replies, polling, updates, attachments, media, config, model resolution, preview timers, and extension-runtime flows. Impact: release checks catch type errors, dependency issues, package-content drift, rendering regressions, queue/lifecycle races, and architecture-boundary drift before publishing.
723
- - `Architecture Guards`: Invariant tests enforce an acyclic local import graph, ban `lib/constants.ts` and `lib/types.ts`, keep empty interface-extension shells collapsed into clearer type aliases, centralize direct pi SDK imports, keep `index.ts` source code free of direct Node runtime imports, local helper declarations, local arrow adapters, direct `process.env`, and direct `pi.*` receiver access, keep `runtime` and structural leaf domains isolated, guard menu/model, API/config, media/update/API, and attachment/queue/media/API boundaries, and require project TypeScript files to keep responsibility headers. Impact: the Flat Domain DAG shape and file-boundary documentation stay protected as domains continue to evolve.
724
- - `Refactor`: Reopened compression/decomposition/refactor/consistency passes tightened menu-domain message render/send plumbing, compressed repeated menu/media/attachment/runtime/API/model/queue test harness shapes, extracted shared runtime context, model-context, dispatch-event, Telegram config, deferred-response, API-response, rich-response, prompt-block, fetch-method, API response/client/fetch-restore, runtime fetch/model, model-test, queue-model, queue prompt/control/item-type, registration active-turn, menu-model, and pi API test fixtures, migrated runtime integration tests onto those fixtures, replaced ad hoc structural casts with owning-domain or test-local helpers where practical, and removed avoidable test casts from attachment, polling, update, model, reply, menu, pi-adapter, and registration suites. Impact: the codebase stays easier to extend without changing Telegram runtime behavior.
596
+ - `Flat Domain DAG`: Established `index.ts` as the single composition root over flat acyclic domains for Telegram transport, config/pairing, queue/lifecycle, model control, commands/menus, polling/updates, preview/replies/rendering, media/attachments, setup/status, Pi adapters, and registration. Types, constants, mutable state, and narrow view contracts stay with their owners; `runtime` contains session-local coordination rather than domain behavior. Impact: bridge behavior became easier to locate and test without adding shared buckets or a second runtime entrypoint.
597
+ - `Queue And Lifecycle`: Centralized prompt/control item contracts, control/priority/default lane admission, active-turn state, mutation, readiness, enqueueing, abort preservation, compaction guards, session start/shutdown, and agent/tool lifecycle. Immediate stop/compact/help/start actions remain responsive; status/model and model-switch continuations serialize in the control lane ahead of normal prompts, while reactions can promote prompts without bypassing controls. Impact: dispatch and active-turn binding remain predictable while asynchronous controls settle.
598
+ - `Model, Commands, And Menus`: Unified model identity, thinking levels, scoped-model resolution, in-flight restart/delayed-abort policy, slash-command planning, bot command registration, inline status/model/thinking state, callback routing, render payloads, and bounded menu caching. Removed Telegram `/debug` in favor of Pi-side `/telegram-status` and TUI diagnostics. Impact: operators receive immediate, testable control feedback without scattering model and menu policy through the composition root.
599
+ - `Rendering And Delivery`: Consolidated safe Telegram HTML/Markdown scanning, escaping, long-message splitting, raw-HTML tag balancing, display-width-aware tables, lists, quotes, links, tasks, literal code, and phone-width guidance. Preview owns draft/editable streaming and finalization; replies owns final/plain/interactive delivery and reply metadata. Impact: previews and finals stay tied to the triggering prompt where Telegram permits, remain readable on narrow clients, and degrade without malformed HTML or broken code.
600
+ - `Files, Config, And Setup`: Separated Bot API retries/downloads/temp cleanup, media extraction and album debounce, atomic outbound attachment staging/limits/classification, global config/pairing/authorization, and guarded stored-token/env setup. Impact: inbound and outbound files fail predictably within limits, `telegram_attach` owns artifact delivery, and setup/pairing behavior stays consistent across commands and update routing.
601
+ - `Diagnostics`: Expanded `/telegram-status` with grouped connection, polling, execution, queue/lane, compaction, tool, and model-switch state followed by a redacted runtime/API event ring. Transport, polling/update, dispatch, control, typing, compaction, setup, lifecycle, and attachment failures enter the ring, while benign unchanged edits and empty draft clears do not. Impact: operators can diagnose bridge stalls after the fact without a Telegram-side debug surface.
602
+ - `Packaging And Guards`: Added an explicit npm allowlist, tracked lockfile, typecheck/test/audit/package/combined validation scripts, GitHub Actions, broad domain/integration regressions, and architecture invariants for acyclic imports, composition-root hygiene, Pi SDK centralization, structural leaves, domain boundaries, responsibility headers, and shared-bucket bans. Impact: package drift, runtime regressions, and Domain DAG erosion fail before publication.
603
+ - `Maintenance Compression`: Consolidated repeated runtime/menu/media/attachment/API/model/queue test fixtures and tightened owning-domain contracts without changing Telegram behavior. Impact: the modular baseline remained extensible while the release history records the resulting boundaries rather than every intermediate extraction and cast cleanup.
725
604
 
726
605
  ## 0.2.x: Fork Genesis
727
606
 
728
- - `Turns`: Preserved existing attachment-path blocks and aborted-turn history context when a still-queued Telegram message is edited. Impact: caption edits no longer make queued prompts lose their downloaded file references or prior-message context.
729
- - `Polling`: Persisted Telegram long-poll offsets only after each update is handled successfully. Impact: a handler failure no longer marks an unprocessed Telegram update as consumed, reducing the chance of silently dropping inbound messages.
730
- - `Telegram API`: Added HTTP-status-aware Bot API response parsing, malformed-success handling, retry/backoff for 429 and 5xx Bot API responses, streaming Telegram downloads with size-limit checks, file-backed multipart upload blobs, partial-download cleanup on limit failures, startup cleanup for stale Telegram temp files, and UUID-based sanitized temp filenames. Impact: Telegram transport failures now report clearer status/description details, transient Telegram throttling/server failures get retried automatically, oversized inbound files are rejected before or during download, outbound multipart sends avoid preloading files into memory, partial and stale temp files are removed, and downloaded files are less prone to timestamp collisions or unsafe local names.
731
- - `Rendering`: Escaped generated HTML attributes separately, sanitized code-fence language classes, and chunked raw HTML-mode output below Telegram length limits with balanced tag reopening across raw HTML chunks. Impact: generated Telegram HTML is harder to malformed through link or fence metadata and long raw-HTML replies no longer exceed Telegram's message size limit or break active tags across chunk boundaries.
732
- - `Preview`: Serialized overlapping preview flushes through a single in-flight flush chain. Impact: rapid streaming updates no longer allow concurrent Telegram edit calls to overwrite newer preview text with stale snapshots.
733
- - `Polling`: Added a bounded poisoned-update policy for repeatedly failing Telegram updates. Impact: one malformed or consistently failing update can no longer stall the long-poll loop forever; after the retry threshold, the bridge records and advances past it.
734
- - `Menu`: Added short-lived model-menu input caching plus TTL/LRU cleanup for stored inline menu state. Impact: repeated `/status` and `/model` interactions do less settings/model-registry work, while old Telegram inline keyboards expire predictably instead of accumulating for the whole session.
735
- - `Updates`: Routed Telegram `edited_message` updates separately from new messages and applied edits to matching queued turns. Impact: editing a still-queued Telegram message updates the pending prompt instead of enqueueing a duplicate turn.
736
- - `Refactor`: Moved shared Telegram Bot API transport shapes out of `index.ts` into `lib/types.ts`. Impact: the entrypoint is smaller and future runtime extraction can reuse one type boundary instead of keeping local duplicate interfaces.
737
- - `Refactor`: Moved Telegram media-group debounce and pending-group removal into the existing media domain with mirrored tests. Impact: album coalescing and reaction/delete cleanup are easier to validate without reading the full extension entrypoint, while avoiding an unnecessary extra domain file.
738
- - `Refactor`: Extracted Telegram slash-command parsing and command-action routing into `lib/commands.ts` with mirrored tests, and moved queued-turn text replacement for edited messages into the turn domain. Impact: command normalization/execution planning and queued edit mutations are reusable, while the entrypoint keeps less local runtime state logic.
739
- - `Rendering`: Hardened link rendering so absolute links stay clickable, markdown-heavy link labels reduce to plain clickable labels, tooltip titles are ignored safely, balanced-parenthesis URLs stay intact, and unsupported link forms degrade without broken anchors. Impact: Telegram replies now keep more links usable while avoiding malformed output for relative, reference-style, or footnote-like link syntax.
740
- - `Preview`: Evolved rich streaming from first-chunk snapshots to stable-block previews with a conservative plain tail fallback, while preserving original blank-line spacing between rendered blocks and keeping headings visually separated from following blocks. Impact: closed top-level Markdown blocks now stream as rich Telegram HTML before finalization, incomplete fences, quotes, lists, and other trailing work remain readable without producing broken rich formatting, preview/final block spacing no longer collapses extra empty lines, and headings no longer visually merge into following code blocks when source Markdown omits a blank line.
741
- - `Refactor`: Split preview concerns so runtime transport and finalization live in the preview domain while preview snapshot derivation lives in the rendering domain. Impact: rich streaming can evolve independently from final reply delivery while keeping preview appearance decisions closer to the Telegram renderer.
742
- - `Streaming`: Switched Telegram previews from plain draft-first text to rich first-chunk message editing, so formatting appears during generation instead of only after finalization. Impact: users now see richer streamed output earlier, while final replies still replace the preview with fully rendered Telegram HTML.
743
- - `Rendering`: Preserved leading indentation on the first Markdown line, kept numeric markers for ordered task lists in both preview and final Telegram rendering, and stopped reinterpreting standalone `[x]`: or `[ ]`: prose as inline checkboxes. Impact: nested content no longer flattens when a message starts with indentation, numbered checklists keep their ordered semantics, and literal checklist-like prose stays literal.
744
- - `Queue UI`: Marked liked high-priority queued Telegram turns with `⬆` in the pi status-bar queue preview. Impact: operators can now distinguish reaction-promoted turns from normal queued prompts at a glance.
745
- - `Docs`: Added short responsibility header comments to every project `.ts` file. Impact: file boundaries are easier to understand while navigating the growing `/lib` split.
746
- - `Naming`: Renamed extracted domain modules and mirrored regression suites to use repo-scoped bare domain filenames such as `api.ts`, `queue.ts`, and `queue.test.ts` instead of repeating `telegram-*` in every path. Impact: the internal topology is easier to scan and stays aligned with the repository-level Telegram scope.
747
- - `Controls`: Expanded Telegram session controls with a richer `/status` view, inline model selection, and thinking-level controls, and fixed the callback-selection path so idle model and thinking picks apply immediately instead of only becoming visible after a later Telegram interaction. Impact: more bridge configuration can be managed directly from Telegram with more predictable immediate feedback.
748
- - `Queue`: Upgraded Telegram turn queueing with previews, reaction-driven prioritization/removal, media-group handling, aborted-turn history preservation, and safer dispatch gating. Impact: follow-up handling is more transparent and less prone to lifecycle races.
749
- - `Rendering`: Added Telegram-oriented Markdown rendering and hardened reply streaming/chunking behavior, including narrower monospace Markdown table output without outer side borders, monospace list markers for unordered and ordered lists, and flattened nested quote indentation inside a single Telegram blockquote. Impact: formatted replies render more reliably while preserving literal code blocks and using width more efficiently on narrow Telegram clients.
750
- - `Runtime`: Hardened attachment delivery, polling/runtime behavior, Telegram session integration, preview-finalization and reply-transport routing into the replies domain, lazy Telegram API client routing into the Telegram API domain, turn-building extraction into its own domain, menu/model-resolution plus menu-state, pure menu-page derivation, pure menu render-payload builders, menu-message runtime, callback parsing, callback entry handling, callback mutation helpers, full model-callback planning and execution, and interface-polished callback effect ports into the menu domain, direct execute-from-update routing into the updates domain, model-switch restart glue extraction into the model-switch domain, and tool/command/lifecycle-hook registration extraction into a dedicated registration domain. Impact: the bridge is more robust as a daily Telegram frontend for pi.
751
- - `Metadata`: Updated package repository metadata to point at the `llblab/pi-telegram` fork and renamed the npm package to `@llblab/pi-telegram` with public scoped publish settings. Impact: published package links no longer send users to stale upstream coordinates and the package can be published under the fork-owned npm scope.
752
- - `Validation`: Added lightweight regression tests for Telegram Markdown rendering, queue/runtime/agent-loop/session/control/dispatch, replies, polling, updates, attachments, registration, turns, menu, and Telegram API/media/config helpers, including quote/list, table, link/code, mixed-link/code chunking, mixed-block chunk transitions, long multi-block, long-quote, long inline-formatting chunk boundaries, list-code-quote-prose chunk transitions, narrower monospace table rendering without outer side borders, monospace unordered and ordered list markers, flattened nested quote indentation inside one Telegram blockquote, inbound poll/pair/dispatch runtime cases, preview finalization, aborted-turn history carry-over, queued-status/model-after-agent-end sequencing, compaction gating, media-group debounce dispatch, direct menu callback planning and execution, pure menu-page derivation, pure menu render-payload builders, reaction-driven reprioritization/removal, immediate in-flight model-switch continuation, delayed abort-after-tool-completion, lazy Telegram API client routing, turn-building, and scoped-model resolution. Impact: key renderer and queue invariants now have repeatable automated coverage across the known high-risk bridge paths.
753
- - `Model Switching`: Enabled `/model` during an active Telegram-owned run by applying the new model and continuing on the new model automatically, delaying the abort until the current tool finishes when needed. Impact: Telegram can now approximate pi's manual stop-switch-continue workflow with fewer mid-tool aborts.
754
- - `Queue Core`: Introduced queued item kinds and explicit queue-lane ordering semantics so prompt turns and synthetic control actions share one ordering model, then regrouped the extracted helpers into flatter domain-oriented `/lib` modules such as queue, replies, polling, updates, attachments, turns, menu, Telegram API, and registration while keeping `index.ts` as the entrypoint. Prompt items now stay queued until `agent_start` consumes the dispatched turn, which restores correct active-turn binding for previews and final delivery. Impact: the bridge now has a clearer foundation for scheduling async extension operations alongside Telegram prompts without losing a single obvious runtime entry file.
755
- - `Registration`: Moved extension tool, command, and lifecycle-hook binding into the registration domain and added registration-focused regression coverage. Impact: extension wiring is easier to reason about and test without dragging full runtime state into every registration change.
756
- - `Control Queue`: Moved `/status` and `/model` command handling onto high-priority control queue items. Impact: control actions can wait safely behind the current run while still jumping ahead of normal queued prompts.
757
- - `Setup`: `/telegram-setup` now shows the stored bot token first, otherwise prefills from common Telegram bot environment variables before falling back to the placeholder, using an actual prefilled editor when a real default exists. Impact: repeat setup respects local saved state while first-run and secret-managed setup stay fast.
607
+ - `Fork Identity And Setup`: Established the maintained `@llblab/pi-telegram` fork with correct repository/package metadata and a setup flow that prefers the saved bot token, then supported environment variables, then an editable placeholder. Impact: installation and repeated setup point at the maintained package and reuse operator state predictably.
608
+ - `Domain Runtime`: Split the monolithic entrypoint into flat queue, replies, polling, updates, media/attachments, turns, commands, menu/model, Telegram API, setup, status, registration, and model-switch domains with mirrored responsibility headers and regression suites. Impact: the bridge retained one visible composition root while runtime policies became independently understandable and testable.
609
+ - `Queue And Lifecycle`: Introduced explicit queued item kinds and lane ordering, kept dispatched prompts queued until `agent_start`, added reaction-driven priority/removal, media-group admission, aborted-turn history, attachment preservation across queued edits, safer compaction/dispatch gates, high-priority `/status` and `/model` controls, and a visible promoted-turn marker. Impact: queued work, controls, previews, and final delivery stay bound to the correct Telegram turn through busy-session lifecycle changes.
610
+ - `Polling And Updates`: Persisted offsets only after successful handling, bounded repeatedly poisoned updates before advancing, routed edited messages into matching queued turns, and separated update execution from polling transport. Impact: failures no longer silently consume work or stall polling forever, and Telegram edits update pending prompts instead of creating duplicates.
611
+ - `Telegram Transport`: Added HTTP-aware Bot API errors, malformed-success handling, 429/5xx retry and backoff, streaming size-limited downloads, file-backed multipart uploads, sanitized UUID temp names, partial-download cleanup, and stale temp cleanup. Impact: transient API failures recover more reliably, file transfers use bounded memory, and unsafe or incomplete local artifacts do not accumulate.
612
+ - `Rendering And Preview`: Delivered Telegram-oriented Markdown/HTML rendering with safe attributes and fence classes, robust links, literal code, compact monospace tables/lists, flattened nested quotes, preserved indentation/checklist semantics, balanced long-message chunking, and serialized stable-block rich previews with readable incomplete tails. Impact: streaming and final replies remain readable on narrow clients without stale preview overwrites, malformed HTML, broken active tags, or transport-limit failures.
613
+ - `Telegram Controls`: Added richer status, model, thinking, menu state, immediate idle selection feedback, scoped model handling, TTL/LRU menu cleanup, and in-flight model switching that delays abort until an active tool finishes before continuing on the new model. Impact: operators can supervise and reconfigure a live Pi run from Telegram without unsafe mid-tool interruption or stale inline-menu state.
614
+ - `Regression Foundation`: Added focused domain and integration coverage for rendering/chunking, queue and control ordering, polling/update admission, edited turns, media groups, attachments, previews/finals, compaction, model switching, registration, setup, and Telegram API behavior. Impact: the fork's initial architecture and high-risk mobile-runtime flows gained repeatable protection without preserving intermediate refactor chronology.