# Changelog

## Unreleased

## 0.24.2: Context Compression Hotfix

- `Project Context`: Consolidated the `0.24.1` release narrative into final domain outcomes, reduced the backlog to concrete open work, and made minimum-Node Ubuntu/macOS/Windows CI a durable engineering contract. Impact: future agents receive a smaller, current project model without losing release behavior or platform-validation requirements.

## 0.24.1: Persistence I/O And Cross-Platform Validation Hotfix

- `Cross-Platform Validation`: Added minimum-Node Ubuntu, macOS, and Windows CI for typecheck, tests, and package shape, with audit once on Ubuntu. Awaited timers remain live on Node 22, Windows uses native pipes and paths, and long macOS socket endpoints map idempotently to short private hashes. Impact: every PR now exercises the supported OS transport and filesystem boundaries.
- `Test Cooling`: Added test-only transaction timing controls, one bounded Node-eval fixture for config/lock/log races, and a table-driven voice registry contract. Removed 19 unreachable exports after package/composition/docs proof. Impact: duplicated process plumbing shrinks and the lock suite falls from roughly nine seconds to three without changing production retries, compatibility, or recovery coverage.
- `Release History`: Consolidated noisy chronology across all 85 historical sections while preserving every version, shipped behavior, migration, limitation, compatibility boundary, and material operator result. Impact: the changelog becomes substantially smaller without rewriting already concise releases.
- `Global Config Concurrency`: Recursive transactional deltas preserve unrelated global/profile writes, keep polling offsets monotonic, and resolve same-leaf conflicts by serialized commit order. Semantically unchanged merges adopt the latest disk snapshot without replacing `telegram.json`. Impact: concurrent polling and Settings updates no longer erase each other or create no-op file churn.
- `Diagnostics Log I/O`: Batch same-turn `logs.jsonl` events per captured profile inside one transaction, preserving order and failure isolation without a timer. Authorized writers rotate between records at the 5 MiB threshold; one-record/reset-metadata overshoot stays explicit and non-owners defer rotation. Impact: bursts avoid per-event guard churn without weakening bounded diagnostics behavior.
- `State Snapshot I/O`: Coalesce diagnostics snapshots over 100 ms and skip `state.json` replacement when only observational `writtenAtMs` differs. Exact-owner commit fencing and stale-view disk reload remain intact. Impact: equivalent runtime state no longer creates temporary files or atomic full-snapshot renames.
- `Ownership Lease I/O`: Preserve one-second exact-owner checks and serialized expected-owner transactions while refreshing durable heartbeats every two seconds with an eight-second stale boundary. Concurrent recovery treats a vanished observed guard as a lost race and still admits one fenced winner. Impact: steady-state `owners.json` rewrites are halved without weakening singleton, leader/follower, Unix-socket, or Windows-pipe authority.

## 0.24.0: Canonical Profiles And Extension-Local Ownership

- `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.
- `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.

## 0.23.3: Thread-Scoped Settings Hotfix

- `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.

## 0.23.2: Voice Policy And Turn Delivery Hotfix

- `Settings Persistence Race`: Rebuilt expired Settings callback state from the live model-menu context before applying mutations. Polling now persists only its monotonic `lastUpdateId` into the current config-store snapshot instead of later submitting the detached full config object captured when polling started. Impact: a subsequent Telegram update can no longer erase freshly persisted `voice.replyMode`, `assistant.proactivePush`, or other Settings values and return the menu to stale defaults.
- `Compact Error Status`: Reduced pi-telegram's TUI error projection to the single `error` state while retaining detailed failures in runtime diagnostics and logs. Impact: provider and transport messages no longer consume the status line or displace the surrounding model/session indicators.
- `Forward Annotation Pairing`: Extended the bounded one-second coalescer so one optional owner-authored annotation and adjacent forward join in either transport order, including photo-only forwards without their own source caption. Prompt construction keeps the layers distinct: owner annotation first, then `[forward|from:...]` with the forward's own source text/caption, then source-attributed media; same-kind messages and existing command/sender/target/id-gap exclusions remain separate. Impact: Telegram forwarding gestures no longer split the user's explanation from the forwarded source or conflate it with the forward's own content.
- `Voice Reply Policy`: Collapsed the redundant explicit `manual` mode into the silent `hidden` default, kept `mirror` automatic only for voice/audio input, and kept `always` automatic for every Telegram turn. Active automatic turns now carry exactly `[voice] delivery: automatic voice`; the per-turn system suffix only points to `telegram_help`, explicit `telegram_voice` remains an agent-authored override, and legacy `manual` config resolves to `hidden`. Impact: models receive one effective delivery fact instead of a noisy mode matrix, while providers remain responsible for synthesis rather than text/voice composition.
- `Provider Retry Delivery`: Retained an active Telegram turn across low-level `agent_end` errors until Pi either produced a successful retry result or emitted `agent_settled`. Retry recovery now delivers the eventual semantic result once to the original target, while an exhausted retry finalizes the retained error once and releases queue state; redacted diagnostics distinguish retention, recovery, and settled failure. Impact: transient provider transport failures can no longer orphan a later successful reply from its originating Telegram turn.

## 0.23.1: Context Budget And Runtime Simplification

- `Bus Runtime Simplification`: Removed the no-op follower-binding recovery timer and grace configuration, the unused disconnected-announcement helper, and the duplicate follower-prune callback. Heartbeat pruning now emits one accurate diagnostic while preserving durable thread bindings. Impact: leader/follower recovery carries less dormant state and cannot imply offline cleanup that never occurs.
- `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.
- `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.
- `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.

## 0.23.0: Telegram Bot API 10.2 Rich Output And Proactive Projection

- `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.
- `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.
- `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.
- `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.
- `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.
- `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.
- `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.
- `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.

## 0.22.1: Termux-Compatible Filesystem Transactions

- `Filesystem Transactions`: Replaced hard-link guard publication with private staged directories containing complete exact-owner metadata, atomically published each non-empty guard by same-parent rename, and atomically renamed exact-owned guards away before recursive cleanup. Bound each owner generation into a unique filename so delayed stale observations cannot claim replacement metadata, retained exact stale recovery through recoverable internal claimant markers, retried reclaim and rollback moves without peer-visible stalls, released newly recovered ownership when secondary cleanup fails, kept fail-closed malformed-state handling, and bounded legacy regular-file guard recovery. Impact: shared Telegram state no longer requires the hard-link operation rejected by Android/Termux, while exactly-one cross-process ownership remains locally enforced; subsequent reporter confirmation established that the released path works on Termux.
- `Diagnostics`: Contained synchronous and queued JSONL persistence failures inside the diagnostics boundary while preserving later queued records after a failed append or rotation. Impact: an unavailable diagnostics path cannot terminate Pi through an unhandled rejection or permanently poison subsequent runtime evidence.

## 0.22.0: Concurrency And Runtime Ownership Hardening

- `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.
- `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.
- `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.
- `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.
- `Bus Endpoint Generations`: Bound each Unix bus server to a private generation socket and atomically published the stable profile endpoint as a relative symlink. Stop removes only its private path, replacement links remain intact, and startup waits for live legacy direct-socket servers before migration. Impact: delayed old-server teardown cannot unlink the replacement leader endpoint.
- `Configuration, Profiles, And Shared State`: Transactional `telegram.json` writers merge recursive deltas onto the latest snapshot, preserve monotonic profile offsets, and quarantine malformed config only behind identity-checked guards. Profile switching keeps the selected identity stable, stops old transport before exposing the new profile, and stamps queued/Activity/Delivery work with immutable profile generations. Revisioned thread snapshots, serialized JSONL rotation, owner-only destructive log reset, and process-birth follower identity protect secondary state. Impact: concurrent writers, delayed callbacks, profile replacement, and PID reuse cannot regress offsets, erase newer state, or reinterpret stale ownership.
- `Session, Target, And Message Ownership`: Added one generation registry across lifecycle, compaction, preview, final delivery, control dispatch, and shutdown so stale callbacks drop before touching replacement sessions. Model-switch continuations retain immutable targets; Delivery handles remain deeply frozen and privately bound; message ownership includes bot profile and exact follower registration generation. Impact: old sessions and sibling/replaced followers cannot retarget work, clear replacement state, or edit/delete messages they no longer own.
- `Idempotent Inbound Admission`: Retained handled update ids until polling-offset commit and preserved exact deferred album/split-text message sets across admission failure and session replacement. Suspended groups rebind to the replacement context and retry until dispatch succeeds. Impact: config retries and transient queue failures do not duplicate accepted prompts or silently lose grouped input.
- `Method-Aware Retry Safety`: Classified retry-safe Bot API methods separately from non-idempotent sends, uploads, and topic creation. The local bus memoizes request results, rejects id collisions, preserves ambiguity, maps missing non-idempotent acknowledgements to `TelegramApiCommitUnknownError`, and exposes `commit-unknown` with recoverable partial handles. Impact: response loss cannot authorize blind replay of messages, media, registrations, forwarded updates, or topic creation.
- `Live Runtime Evidence`: After a clean restart, local `/reload` retained the assigned leader thread, restored Telegram automatically, and accepted the next message without reconnect, follower fallback, or takeover. A private Guest Mode exchange preserved guest attribution and delivered generated voice plus a requested attachment through the one-result path. Impact: live evidence confirmed generation recovery, thread identity, Guest routing, voice, and artifact delivery after the hardening refactor.

## 0.21.1: Runtime And Session Semantics Hotfix

- `Runtime Semantics`: Clarified that Telegram destinations follow running Pi instances and route prompts into each instance's currently active session rather than binding permanently to one session file or session identity. Impact: session replacement and Threaded Mode behavior now match the documented operator mental model without mischaracterizing the bridge as a remote terminal or session browser.
- `Session Control`: Documented the exact mobile boundary: Telegram can compact the current session but cannot create, resume, fork, browse, or switch sessions until Pi exposes safe public extension APIs. Impact: operators can distinguish active-session continuation from unavailable session lifecycle/navigation control.
- `Context Cost`: Documented that Telegram prompts are normal Pi model turns and inherit the active post-compaction session context just like TUI prompts; pi-telegram does not promise context isolation or cost proportional only to the new mobile message. Impact: token usage expectations no longer conflate transport metadata with model-context economics.
- `Prompt Guidance`: Documented the current small transient system note plus on-demand `telegram_help` design and the historical risk from older releases that persisted large guidance suffixes in every user turn. Impact: operators investigating long-lived sessions can separate current behavior from legacy context growth already stored in old session history.
- `Diagnostics Identity`: Distinguished Pi session JSONL from shared profile-scoped pi-telegram `logs*.jsonl`, and clarified that `/telegram-connect` never launches hidden Pi processes while explicitly launched long-lived instances remain subject to normal lock ownership. Impact: shared bridge diagnostics can no longer be mistaken for merged Pi session history or hidden process creation.

## 0.21.0: Activity And Delivery Extension Platform

- `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.
- `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.
- `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.
- `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.
- `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.
- `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.
- `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.

## 0.20.6: Guest Attribution And Voice Action Hotfix

- `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.
- `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.

## 0.20.5: Guest Media And Runtime Recovery Hotfix

- `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.
- `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.
- `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.
- `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.
- `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.
- `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.

## 0.20.4: Thread State Ownership Hotfix

- `State Ownership`: Made the active transport lock owner the only process allowed to persist the profile-shared `state.json`; followers remain readers and acquire write authority only after promotion. Status-only persistence now refreshes disk-backed bindings before serialization. Impact: a stale follower diagnostics snapshot cannot erase newer leader-owned bindings, produce duplicate slot occupancy, or make a live follower disappear from current thread state.
- `Follower Recovery`: Followers now carry target, slot, and thread name during re-registration. When an authenticated live follower carries an exact target missing from persisted bindings, the leader recovers that target without creating another Telegram thread and restores its slot only when unoccupied; a matching previous live-roster observation can recover the name for an older follower runtime. Impact: damaged local state converges around the surviving Telegram tab instead of replacing it or preserving a duplicate letter.
- `Thread Identity`: Unified terminal status and `[telegram|thread:name]`: behind one target-aware current-instance identity resolver. Registered follower/leader metadata takes precedence over a stale shared record for the same target, with persisted state used only as fallback. Impact: when the prompt tag correctly identifies the assigned thread, terminal status can no longer regress to a previous thread name from stale state.
- `Live Linux`: A clean same-directory bootstrap produced one leader and two followers with three exact unique slot/thread bindings; the live roster and persisted targets agreed without duplicate slots. Impact: multiple processes launched from the same cwd no longer expose the state-writer collision that originally duplicated a slot.
- `Validation`: Added deterministic coverage for stale status writers, denied follower writes, promotion-time write authority, carried identity metadata, exact live-target recovery, collision-safe slot recovery, and status/prompt identity convergence. The full release validation passes with one platform-only named-pipe skip. Impact: the original corruption and cross-surface mismatch scenarios are release-gated.

## 0.20.3: Persistent Threads And Activity

- `Follower Sessions`: Registered followers now snapshot their target, slot, and thread name before same-process Pi session replacement, stop the old receiver/heartbeat context, and automatically re-register the new session through the live leader. Impact: `/new` and `/reload` no longer intentionally leave a healthy follower disconnected or require another manual `/telegram-connect`.
- `Thread Identity`: Follower re-registration transfers an exact requested target from the previous runtime instance through the stable manual-follower identity, and every reuse refreshes the binding's recovery timestamp. Post-leader-reload compaction preserves recently refreshed bindings across a brief follower registry gap, while still removing genuinely historical records. Impact: follower or leader reload does not rotate baked names or create duplicate same-slot Telegram tabs merely because runtime instance ids changed or the follower reload overlaps the leader's compaction deadline.
- `Native Activity`: Telegram's native `…typing` indicator now starts for every connected instance agent run, including local/TUI prompts and autonomous continuations such as Grow Loop, using the active Telegram turn target when present and otherwise the instance's assigned target. Impact: Telegram shows that an instance is working even when a new Telegram prompt is queued behind local work, while terminal `Active` remains scoped to Telegram-owned turns.
- `Live Linux`: Leader reload triggered bounded follower election/re-registration without replacing follower threads; subsequent follower `/reload` and `/new` both automatically restored follower role on the same assigned thread. Impact: leader reload and both Pi session-replacement paths have direct evidence for exact follower thread preservation without manual reconnect or duplicate tabs.
- `Validation`: Relaxed the process-shutdown child harness timeout from 2 to 5 seconds after full-suite concurrency exceeded the old wall-clock bound while the isolated shutdown suite remained green. Impact: process ownership regressions still fail on leaked handles but no longer flake solely from parallel test-runner load.

## 0.20.2: Live Thread Reality

- `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.
- `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.
- `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.
- `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.
- `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.
- `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.
- `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.

## 0.20.1: Profile IPC Isolation Hotfix

- `Runtime Isolation`: Profile-scoped Threaded Mode leader and follower IPC endpoints on Unix and Windows while preserving the default profile's legacy socket and named-pipe paths. Impact: parallel named-profile runtimes no longer contend for, unlink, or connect to another bot profile's local bus transport.
- `Profile Switching`: Resolved leader and follower endpoints from the active profile when servers start, follower calls are sent, diagnostics render, and follower registration publishes its receiver address. Impact: changing profiles after process start cannot retain stale IPC identity from the previously active profile.
- `Validation`: Added Unix and Windows endpoint-isolation regressions plus runtime restart coverage, and documented global, profile-scoped, and session-local runtime surfaces. Impact: profile reality boundaries are explicit and deterministic without making scratch attachments or extension registries routing authority.

## 0.20.0: Pi-Compatible Multi-Profile Runtime

- `Profiles`: Added named Telegram bot/session profiles under `telegram.json` `profiles` while preserving the top-level default profile and legacy default paths. Profile activation is session-local, bot/session fields are profile-scoped, shared bridge settings remain global, and setup/connect accept explicit profile names. Impact: separate bots can run from the same agent directory without `telegram-bots.json`, persisted active-profile drift, or default-profile migration risk.
- `Runtime Isolation`: Scoped Telegram lock ownership, Threaded Mode owner keys, runtime logs, previous logs, and Threaded Mode state by selected profile. Impact: named profiles keep independent polling ownership and observable bot realities, while the default profile remains backward-compatible.
- `Pi Compatibility`: Centralized agent-dir/path resolution with `PI_CODING_AGENT_DIR` support and moved queued Telegram prompt dispatch back under pi-telegram's scheduler as normal `sendUserMessage(content)` turns. Impact: Pi-compatible runtimes such as OMP can share the bridge without stranded follow-up work or duplicated path contracts.
- `Prompt Context`: Normalized Telegram prompt metadata for forwards, replies, source attachments, and guest surfaces. Impact: `[telegram...]`: identifies only the inbound surface, while `[reply|from:...]`, `[forward|from:...]`, and `[attachments|from:...]`: carry source provenance without conflating owner-authored prompts with quoted or forwarded evidence.
- `Threaded Mode`: Hardened manual follower lifecycle around reloads, reconnects, disconnects, and registration races. Followers now disconnect cleanly on session replacement, reconnect only on explicit `Telegram Connect`, provision one fresh routable tab with monotonic slot allocation, and never show stale previous thread names while disconnected. Impact: follower churn is predictable across reload/election paths without duplicate-tab spam or unroutable preserved bindings.
- `Reliability`: Hardened Windows lock heartbeat writes for transient `EPERM` / `EBUSY` / `EACCES` failures, skipped virtual prompt-template commands without source paths, and treats `createForumTopic` as non-idempotent by avoiding retry on topic creation. Impact: common runtime and Telegram-client edge cases degrade to diagnosable state instead of crashes, menu failures, or duplicate visible topics.
- `Validation`: Added regressions for profile persistence/activation, setup/connect profile behavior, profile-scoped locks/state/logs, OMP-style dispatch, path resolution, prompt context, follower reconnect/provisioning, status projection, and Domain DAG invariants. Live Linux smoke confirmed independent named-profile setup/connect, hot Threaded Mode upgrade, parallel leaders for separate bots, explicit follower reconnect, monotonic follower slot allocation including Z→A wraparound, and single-topic provisioning.

## 0.19.2: Draft And Rendering Isolation Hotfix

- `Config`: Grouped assistant answer output under `assistant: { rendering, draftPreviews }`, while still reading and cleaning up legacy `assistantRendering`, `draftPreviews`, and `richDraftPreviews`. Impact: config vocabulary now matches the feature boundary; draft visibility and final rendering live together without implying that previews are inherently Rich Markdown.
- `Preview`: Hard-gated preview state creation behind the Draft previews setting. Impact: when Draft previews are off, `message_start` / `message_update` cannot create or flush draft frames; Telegram should show only native active status until the final answer.
- `Preview`: Aligned enabled draft previews with the selected final renderer: `assistant.rendering: "rich"` uses `sendRichMessageDraft`, while `assistant.rendering: "html"` uses legacy `sendMessageDraft` with HTML. Impact: the visible draft no longer morphs from Native Rich Markdown into legacy HTML at finalization.
- `Rendering`: Removed the thread-reply special case that forced anchored thread assistant replies through legacy Markdown-to-HTML. Impact: `assistant.rendering: "rich"` now uses native Rich Markdown for final assistant replies in Threaded Mode too, while `assistant.rendering: "html"` remains the only path that selects legacy HTML rendering.
- `Tests`: Updated reply regressions to assert native Rich Markdown delivery for anchored thread replies.

## 0.19.1: Settings Layer Hotfix

- `Settings`: Split the overloaded Rich Draft setting into two independent controls: `Draft previews` for live `sendRichMessageDraft` streaming and `Assistant rendering` for final-answer delivery mode. Impact: operators can hide/show in-progress drafts without changing how final Markdown is rendered.
- `Rendering`: Added persisted `assistantRendering: "rich" | "html"`, defaulting to Native Rich Markdown and allowing legacy Markdown-to-HTML final assistant replies when selected. Impact: renderer compatibility is explicit instead of being conflated with preview visibility.
- `Preview`: Kept `richDraftPreviews` as the stored draft-preview flag for compatibility, but renamed the Settings UI to `Draft previews`. Impact: existing configs keep working while the product vocabulary moves toward the preview feature boundary.
- `Validation`: Updated menu/settings/reply regressions for the two-axis configuration model.

## 0.19.0: Telegram Companion Hub

- `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.
- `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.
- `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.
- `Guest Mode`: Added the standard denied-action marker to unauthorized guest-query replies. Impact: compact access denial is easier to recognize in Telegram.

## 0.18.6: Threaded Mode parity hotfix

- `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.
- `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.
- `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.
- `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.
- `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.
- `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.

## 0.18.5: Windows Threaded Mode stabilization hotfix

- `Bus Transport`: Introduced an explicit local bus transport boundary for endpoint derivation, socket-vs-pipe detection, operation-aware retry policy, timeout/transient IPC error classification, endpoint reachability probes, request-scoped server/client transport events, and handler-failure ACKs instead of silent client timeouts. Impact: Unix socket behavior remains the stable baseline while Windows named-pipe readiness and retry behavior are contained in the transport layer instead of leaking into routing.
- `Windows IPC`: Leader-side forwarding now tolerates a pruned follower registry entry by using the follower's deterministic receiver endpoint, the default follower prune window is more conservative, and `/telegram-status --debug` identifies local bus endpoints as pipes or sockets. Impact: follower threads that already connected are less likely to fall back to `not connected to the Telegram bus yet` during Windows named-pipe heartbeat jitter, and diagnostics expose the active transport contour directly.
- `Capability Switching`: Live Threaded Mode downgrade now blocks follower takeover while active thread bindings prove the bot is degrading from a live leader/follower organism, confirms disabled thread capability after two 2.5-second monitor probes, retries classic polling restore after transient failures, and clears the in-memory follower registry when bus leadership stops. Impact: when BotFather disables private-chat threads, the current bus leader keeps the classic singleton polling role and followers disconnect instead of stealing ownership or lingering as a live bus roster.
- `Diagnostics`: Runtime JSONL reset now preserves the previous session log as `logs.previous.jsonl` and records that path in the new reset line. Impact: `/reload` no longer destroys the best evidence for long-running `/start`, menu, polling, queue, or bus stalls immediately before restart.
- `Previews`: Native rich Markdown previews no longer send syntax-only prefixes such as a bare opening `**`, while keeping the native draft/final lifecycle otherwise unchanged and removing unused throttle/manual-clear branches. Impact: Telegram avoids malformed early preview fragments without extra delivery policy that can create duplicate, stalled, or placeholder draft artifacts.
- `Validation`: Native Windows smoke passed for classic mode, classic ownership handoff, hot upgrade to Threaded Mode, leader/follower registration and delivery, and hot downgrade back to classic with follower disconnect. Impact: the named-pipe and capability-switching fixes have live evidence across both directions, with classic restore/status convergence inside the intended 5–15 second fallback window.

## 0.18.4: Windows Threaded Mode hotfix

- `Windows IPC`: Follower registration now retries transient local bus connection failures while the leader named pipe/socket is still coming online. Impact: a same-directory Windows follower is less likely to fail `/telegram-connect` with `connect ENOENT \\.\\pipe\\...` during leader reload or hot Threaded Mode activation.
- `Queue`: A session-bound queue dispatch watchdog now retries dispatch while Telegram work remains queued. Impact: if a platform drops the one-shot deferred dispatch wakeup, queued Telegram messages can resume without waiting for a manual `/reload`.

## 0.18.3: Threaded Mode live hotfix

- `Threaded Mode`: Inbound Telegram prompts now request an immediate dispatch and a session-bound deferred retry. Impact: hosts where Pi is not yet dispatch-ready at update handling time no longer need a later `/reload` or command to process the queued prompt.
- `Thread Lifecycle`: Automatic leader reclaim/reconciliation paths no longer call `editForumTopic` just to restore internal thread identity, and an unknown unbound thread is no longer auto-claimed by the leader while another live thread target exists. Prompt thread labels now prefer the local live leader/follower target over stale shared thread-store records. Impact: ordinary prompts and voice messages should not produce duplicate Telegram service messages such as `renamed the thread to ...`, and a same-directory follower thread is less likely to be smeared onto the leader binding or mislabeled in prompts.
- `Threaded Mode`: Follower Bot API authorization now permits safe bot identity reads and chat-level typing/activity within the follower's assigned chat, while preserving thread-scoped write restrictions for messages/files/topic mutation. Impact: forwarded follower updates no longer fail just because native activity/capability paths use the aggregate chat surface.
- `Status`: Leader target assignment now carries the live thread name into status fallback state. Impact: the status bar is less likely to flicker from `Dune Leader/Active` to generic `Telegram Leader` when the current active turn or thread-store lookup changes.
- `Model Menu`: The Telegram model menu now hides one-page pagination controls and keeps scope tabs hidden unless scoped models exist. Impact: the minimal model menu shows only main-menu navigation and the available models.

## 0.18.2: Setup pairing start hotfix

- `Setup`: `/telegram-setup` now updates the live in-memory config immediately after persisting the validated bot token and before starting polling. Impact: first-time setup no longer shows `Send /start...` followed by `Telegram bot is not configured`, and `/start` can be received without restarting Pi.

## 0.18.1: Windows setup transport hotfix

- `Setup`: `/telegram-setup` token validation now uses the same fallback-aware Telegram transport as normal API calls. Impact: Windows/QEMU hosts that fail native `fetch` during bot-token validation can retry through IPv4 fallback instead of failing before config is saved.
- `Setup`: Token validation transport failures now report a setup error notification instead of escaping as a command failure. Impact: operators get a clear retryable setup failure when Telegram is unreachable.
- `Docs`: Normalized Threaded Mode language across README, architecture docs, prompt guidance, and changelog: `Threaded Mode` is the mode name, `thread` is the user-visible Telegram surface, and BotFather is only the bot configuration tool. Impact: release docs no longer imply BotFather owns runtime Threaded Mode behavior.

## 0.18.0: Threaded Mode

- `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.
- `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.
- `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.
- `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.
- `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.
- `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.
- `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.
- `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.

## 0.17.5: Screenshot Refresh

- `Docs`: Refreshed the package screenshot.

## 0.17.4: Native Rich Markdown Splitter Hotfix

- `Rich Markdown`: Rewrap oversized fenced code, display-math, and fully wrapped inline-formatting blocks when splitting native Rich Markdown at Telegram transport limits. Impact: very long structured Markdown blocks no longer produce invalid partial Rich Markdown chunks, so final assistant replies can stay native without losing long code/math/formatted output.
- `Tests`: Added regressions for oversized fenced code, display math, and inline formatting split behavior. Impact: future native splitter changes must preserve structurally valid chunks beyond Telegram's single-message size limit.

## 0.17.3: Native Draft Preview Hotfix

- `Rich Markdown`: Normalize multiline display-math blocks written as `$$` / content / `$$` into Telegram-supported `math` code fences before native Rich Markdown delivery, while preserving literal delimiters inside code fences. Impact: assistant replies following the Telegram prompt guidance for block formulas no longer risk making the whole Rich Markdown message render as raw Markdown.
- `Preview`: Removed assistant plain-message preview fallback paths; failed native draft frames are recorded and skipped because partial Markdown can be temporarily invalid while the final answer remains valid. Draft delivery now sends only structurally closed Markdown prefixes, holding back unclosed inline spans, links, fenced code, comments, and display-math blocks until a safe boundary exists. Impact: assistant previews stay on Telegram's native Rich Draft API and no longer create raw-Markdown fallback bubbles.
- `Validation`: Live Telegram smoke-tested native draft/final Rich Markdown delivery with sections, lists, code fences, links, `$$` display math, and inline buttons after reload. Impact: the `0.17.3` hotfix behavior is verified in the target Telegram client path, not only by local tests.

## 0.17.2: Indented List Rich Markdown Hotfix

- `Rich Markdown`: Neutralized indented list markers before native Rich Markdown delivery by replacing leading list indentation with non-breaking spaces while preserving top-level list markers. Impact: assistant replies with bold section headers followed by two-space-indented bullets containing slash/hyphen text, `with`, and inline code no longer render raw Markdown or truncate around the inline-code span.
- `Preview`: Pinned the same normalization path for native draft previews and editable/final Rich Markdown messages. Impact: risky replies use consistent Markdown safety behavior across draft, fallback edit, and final delivery paths.
- `Tests`: Added regression coverage for the discovered formatting-only and truncation-risk fixtures, including payload-tail preservation through native Markdown splitting and send delivery. Impact: future Rich Markdown parser changes are less likely to reintroduce partial Telegram messages.

## 0.17.1: Rich Markdown Parser Hotfix

- `Rich Markdown`: Normalize Bot-API-fragile source before native Rich Markdown delivery, including space-after-marker blockquotes and dollar-prefixed ticker atoms such as `$BLDR` / `$NTVE`, prefer Telegram `rich_message` blocks over raw `text`/`caption` when extracting quoted reply context for prompts, and keep Telegram copyability guidance generic by recommending inline code for short copyable literals. Impact: assistant replies are less likely to render as raw Markdown on Telegram Rich Message parser/client edges, replying to a native Rich Markdown bot message no longer injects raw Markdown source into `[reply]`, and prompts nudge copyable identifiers without ticker-specific bloat.

## 0.17.0: Native Rich Markdown Delivery

- `Rich Markdown`: Assistant and guest replies now use Telegram-native Rich Message APIs directly: final assistant Markdown goes through `sendRichMessage`, streaming drafts go through `sendRichMessageDraft`, editable fallback previews finalize through `editMessageText.rich_message`, and guest replies use `InputRichMessageContent`. Impact: model-authored Markdown reaches Telegram as native Rich Markdown instead of passing through the legacy Markdown-to-HTML assistant path.
- `Preview UX`: Streaming preview is now a thin Rich Draft lifecycle controller with serialized flushes, no default debounce, no assistant rendering dependency, and no post-final draft-clear call. Impact: live Telegram clients get smoother draft updates and avoid duplicate final messages, blank finalization gaps, or the transient animated three-dot block observed during draft clearing.
- `UI Boundary`: Bridge-owned commands, menus, status messages, queue controls, buttons, and sections remain explicit Telegram HTML/plain UI by default, while companion sections can opt into Markdown/HTML/plain per view. Impact: native Rich Markdown improves model-authored replies without making hand-authored bot UI harder to maintain.
- `API And Limits`: Added typed Rich Message send/draft helpers, disabled automatic entity detection for assistant/guest Rich Markdown, and split native Markdown at Telegram Rich Message character/block limits while keeping reply metadata on the first chunk and reply markup on the final chunk. Impact: technical output avoids accidental entities and long replies stay within Bot API limits.
- `Docs And Tests`: Added a local Bot API Rich Messages reference, updated README/outbound/public API/sections/architecture/prompt/AGENTS guidance, kept formula prompting compact around `$...$` / `$$...$$`, and added regressions for native delivery, guest replies, preview lifecycle, split replies, and the UI/compat rendering boundary. Impact: the release behavior is documented, covered, and easier to preserve.

## 0.16.6: Telegram Review Hardening Hotfix

- `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.
- `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.
- `Reply Identity`: Scoped transport reply deduplication by chat id. Impact: equal Telegram message ids in different chats retain independent reply metadata.
- `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.
- `Callback Diagnostics`: Recorded non-fatal `answerCallbackQuery` transport failures in runtime diagnostics. Impact: `/telegram-status` can explain acknowledgement failures without breaking callback handling.
- `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.

## 0.16.5: Context-Aware Prompt Guidance Hotfix

- `Prompt Guidance`: Made before-agent-start Telegram guidance context-aware: unconfigured sessions receive no bridge suffix, local/TUI prompts receive only explicit direct-delivery guidance, and Telegram-originated turns keep the full inbound, phone-width, voice, and button contract. Impact: ordinary local replies no longer get raw Telegram action-comment syntax unless the current turn actually comes from Telegram.
- `Docs`: Recorded the product boundary that `pi-telegram` is a mobile companion for a live Pi session, not a remote terminal, PTY supervisor, or process launcher. Telegram controls should stay within Pi's extension-facing APIs; true session replacement such as Telegram `/new` should wait for a public Pi hook that preserves interactive runtime and TUI semantics.

## 0.16.4: Follow-Up And Runtime Mode Hotfix

- `Runtime`: Feature-detect Pi `ctx.mode` and keep `print`/`json` runs passive by blocking polling start/resume in those modes. Impact: CLI/headless sessions can finish local work without inheriting Telegram polling, while `tui`/`rpc` and older Pi runtimes keep existing behavior.
- `Queue`: Forward queued Telegram prompts and unknown callback fallbacks to Pi with explicit `followUp` delivery semantics. Impact: Telegram input keeps the existing non-steering queue contract even when Pi's native streaming-message API requires an explicit busy-run policy.

## 0.16.3: Ownership And Shutdown Hotfix

- `Ownership`: Lock-gated proactive local/headless final-result push so only the current `/telegram-connect` owner can send non-Telegram agent-end replies to the paired chat, while accepted Telegram turns and queued work still finalize session-locally after polling ownership moves away. Impact: child/headless/non-owner instances no longer leak unrelated local results into Telegram.
- `Shutdown`: Made polling retry sleep abort-aware, `unref()`ed non-critical Telegram housekeeping timers, and routed registered session shutdown through the composed lifecycle runtime so session context cleanup runs with queue and polling cleanup. Impact: shutdown and print/headless runs are less likely to stay alive on retry/debounce/typing/preview timers, and direct-delivery ownership context is cleared at the session boundary.
- `Tests`: Added regressions for inherited child lock refusal, child-process no-poll ownership, child-process direct-tool non-owner refusal, proactive owner/non-owner/stale/off states, queued dispatch after lock movement, abort-during-retry polling sleep, process-level session shutdown, and real `pi -p` exit/no-leak paths with a local custom provider. Impact: the cross-instance ownership, queue, and shutdown contracts are pinned from unit coverage through CLI smoke coverage.
- `Status`: Changed `/telegram-status` bot identity fallback from `not configured` to `unknown` when a bot token exists but the bot username is absent. Impact: live sessions that are paired and polling no longer look unconfigured only because identity metadata is missing.
- `Docs`: Documented ownership, proactive-push, timer/shutdown, and multi-extension prompt-boundary contracts in README and `/docs`. Impact: companion extensions get clearer boundaries without adding a core question/prompt-mirroring API.

## 0.16.2: Screenshot Refresh Hotfix

- `Docs`: Refreshed the package screenshot. Impact: npm and repository previews show the current Telegram bridge UI without changing runtime behavior.

## 0.16.1: Disconnected Queue Status Hotfix

- `Status`: Keep showing the local Telegram queue count in the TUI status bar when polling ownership moves to another Pi instance and the bridge reads as disconnected. Impact: the singleton Telegram control lock can move without hiding pending session-local Telegram prompt work from the original agent.

## 0.16.0: Telegram Extension Commands

- `API`: Added `registerTelegramCommand()` on the public `/commands` subpath so companion extensions can explicitly provide Telegram-native slash commands without adding workflow-specific commands to core. Built-in bridge commands stay reserved, extension command names must be Bot API safe, duplicate extension names are rejected, commands stay hidden unless `showInMenu` is enabled, visible commands must provide an emoji used in `/start` help and Bot API descriptions, extension-command descriptions are shown in `/start`, visible extension commands are inserted after `/compact` before queue-control commands, prompt-template commands remain separated in `/start`, handler failures are isolated with runtime diagnostics, and routing precedence is built-ins → extension commands → prompt-template aliases. Impact: workflow-specific controls can live in companion extensions while `pi-telegram` remains a lightweight Telegram shell.

## 0.15.1: Typing Keepalive Cadence

- `Typing Status`: Pinned the default native Telegram typing keepalive interval at 2500 ms while preserving the 250 ms idle-drain cap. Impact: runtime behavior matches the intended conservative chat-action cadence.

## 0.15.0: Companion Status Lines

- `API`: Added `registerTelegramStatusLineProvider()` on the public `/status` subpath so companion extensions can append compact rows to the `/start` menu status text. Providers are synchronous, model-aware, isolated on failure, and rendered with Telegram-style capitalized labels. Impact: quota/status widgets can progressively enhance the Telegram operator menu without owning polling, transport, or core menu rendering.
- `Docs`: Documented the status-line provider with an abstract companion-extension example and listed `pi-codex-usage` as a companion extension. Impact: the public API docs stay implementation-neutral while the README still points operators to the concrete Codex quota widget.

## 0.14.0: Direct Telegram Delivery, Queue Semantics, And Section Diagnostics

- `Prompt Guidance`: Tightened agent context for Telegram buttons: use normal Markdown plus top-level hidden `telegram_button` comments, never JSON button specs or standalone button actions, and keep comments out of code/quotes/lists/indented examples. Impact: agents immediately know how to author visible Telegram text, inline buttons, and direct `telegram_message` payloads without transport hacks.
- `Command Templates`: Synced `lib/command-templates.ts` with the current `pi-actors` standard, including advisory risk labels, actor recipe context metadata, bundled short-flag detection, and fuller trusted-executable mitigation text. Impact: pi-telegram command-template tooling no longer lags the actor recipe/tooling implementation.
- `Tools`: Telegram is now a first-class local delivery target: `telegram_attach` sends files immediately to the paired/default chat when no Telegram turn is active, and new `telegram_message` supports explicit local/TUI requests to push Markdown text messages. `telegram_message` reuses the normal `telegram_button` comment planner, so direct buttons are authored exactly like ordinary Telegram replies and always attach to a real message. Direct local/TUI delivery is gated by `/telegram-connect` ownership, while active-turn reply delivery remains session-local. Impact: agents can deliver requested artifacts or notices to Telegram from terminal-originated work without bypassing singleton polling/control ownership.
- `Status`: TUI status now renders `compacting` with the same warning color used for `active`, while keeping the `telegram` domain label accented. Native typing cleanup now gives the last in-flight `sendChatAction` a short bounded drain before final reply delivery, and the typing keepalive interval is relaxed to 3s while staying below Telegram's typical chat-action TTL. Impact: manual or automatic context compaction reads as active model work, and Telegram typing is less likely to outlive a completed agent turn.
- `Queue`: Telegram queue and reply delivery now stay per Pi instance, independent from the singleton polling/control lock. `/abort` only enables abort-history preservation for Telegram-owned turns, and local/non-Telegram agent starts clear stale abort-history mode. Impact: moving `/telegram-connect` no longer silences an already accepted queue, and local prompts after abort no longer fold old queued turns into the next Telegram prompt.
- `Sections`: Section label, render, and callback failures now record source-scoped diagnostics and recover only when the matching surface succeeds. Section diagnostics expose only `active`/`error`, and settings-only callbacks keep Settings-level Back navigation. Impact: one broken companion section cannot break menu rendering or hide unrelated diagnostics.

## 0.13.2: Config Recovery And Inbound Output Bounds Hotfix

- `Config`: Invalid `telegram.json` now recovers on session startup by renaming the broken file to an `.invalid-*` recovery path, loading safe empty defaults, and recording a runtime diagnostic. Impact: a hand-edited or partially written config no longer bricks `/telegram-setup` or session startup.
- `Inbound`: Inbound handler, programmatic handler, voice transcription, and built-in text attachment outputs are now bounded before entering Telegram prompt context. Impact: large OCR, PDF, STT, or text-file outputs cannot silently explode prompt size.
- `Diagnostics`: Runtime event messages/details and inbound handler failure stdout/stderr are truncated before storage/rendering. Impact: `/telegram-status` remains useful after noisy provider or handler failures without hiding that truncation happened.

## 0.13.1: Rendering, Typing, And Continue Queue Hotfix

- `Rendering`: Fixed Telegram HTML rendering for Markdown bold/italic spans that cross soft line breaks, so assistant replies like `**first line\nsecond line**` render as bold text instead of showing raw asterisks. Added a regression for the guest-mode-style multiline bold reply shape.
- `Typing Status`: Hardened assistant message activity hooks so transient preview/provider transport failures are recorded but do not break the native Telegram `typing` keepalive while an active turn continues.
- `Continue Queue`: `/continue` now enqueues as a control-lane resume prompt and explicitly clears abort-history mode, so queued Telegram prompts stay separate and the continuation runs ahead of queued prompt work after abort or compaction recovery.

## 0.13.0: Command Template Standard, Voice Hardening, And Domain Cleanup

- `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.
- `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.
- `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.
- `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.
- `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.
- `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.
- `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.

## 0.12.0: Public API Membranes, Telegram UX Safety, And Extension Interop

- `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.
- `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.
- `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.
- `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.
- `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.
- `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`.

## 0.11.2: Queue Continuation, Compaction Safety, And Settings Polish

- `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.
- `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.
- `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.
- `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.
- `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.
- `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.

## 0.11.1: Time Context And Settings Polish

- `Time Context`: Added optional `telegram.json` `time` prompt context for Telegram-originated turns. `time.injectionMode` values are `off`, `always`, and per-chat `interval`; `time.interval` is stored in milliseconds and timezone comes from the system. The `[time]` line renders last after attachments, handler outputs, and voice context, and Settings exposes a `🕒 Time` mode selector.
- `Settings UI`: The proactive push row now uses `📌 Proactive push: on|off`, and proactive push, time, and voice reply submenus use matching emoji headings.

## 0.11.0: Voice Provider Platform

- `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.
- `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.
- `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.
- `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.
- `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.
- `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.
- `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.

## 0.10.8: Compact Typing Timing Hotfix

- `Compaction`: Telegram `/compact` now starts the native `typing` chat-action keepalive after the "Compaction started" notice is sent, then stops it on completion or failure. Impact: operators see the same Telegram activity indicator during context compression that they already see during normal agent/tool work, without showing `typing` before the explicit start confirmation arrives.

## 0.10.7: Stale Context Hardening Hotfix

- `Session Reloads`: Context-sensitive command, pairing, queue, session-start, and update-dispatch paths now ignore only stale-session/stale-context failures instead of swallowing broad runtime errors. Impact: the bridge survives ctx replacement/fork/reload races while real bugs still surface for diagnostics.
- `Runtime Status`: Restored status update error propagation so existing polling/dispatch safety wrappers can record stale status failures as structured runtime events instead of losing diagnostics inside the status domain.
- `Release`: Added a tag-triggered GitHub Actions release workflow that verifies the `vX.Y.Z` tag matches `package.json`, extracts the matching `CHANGELOG.md` section, and publishes a GitHub Release automatically.
- `Tests`: Added focused regressions proving the newly guarded call sites tolerate stale context errors and still rethrow unrelated failures.

## 0.10.6: Native Typing Keepalive Hotfix

- `Typing`: Telegram native `typing` chat actions now refresh every 2.5s instead of every 4s. Impact: the bot's Telegram-side typing animation has more headroom to stay visible during model retries, transient model/API errors, and other long-running agent work.
- `Queue Menu`: Empty queue refresh now rotates through a wider set of small status phrases. Impact: repeatedly refreshing an empty queue feels less repetitive while preserving the same callbacks and menu layout.
- `Tests`: Added coverage for the default native typing keepalive cadence.

## 0.10.5: Queue Continuity And Input Resilience Hotfix

- `Compaction`: `/compact` completion and failure callbacks now request deferred queue dispatch instead of dispatching immediately. Impact: queued Telegram turns resume after compaction state and Pi idle/pending-message state have a chance to settle.
- `Text Groups`: Long-text split recovery is more aggressive where Telegram chunking actually drifts: the debounce is rounded to 1s, the conservative 3600-character start threshold is preserved, and continuation messages can span a much wider message-id gap while staying scoped to the same chat/user and non-command text. Impact: very large pasted prompts are more likely to arrive as one agent turn instead of several fragmented turns.
- `Runtime Status`: Typing-loop and prompt-dispatch status updates are now best-effort and record stale-context failures as structured runtime events. Impact: status/Running indicators remain resilient after error paths without hiding diagnostics.
- `Tests`: Added regressions for deferred compact dispatch, stale status failures in typing/dispatch paths, and many-part split-text grouping.

## 0.10.4: Polling Status Resilience Hotfix

- `Polling`: Status-bar updates from the polling loop are now best-effort and no longer crash the extension when a captured session context becomes stale after session reload. Failures are recorded as structured polling runtime events with `phase: "status-update"`. Impact: polling cleanup and retry status updates stay resilient without changing the Telegram API, config, or operator workflow.
- `Tests`: Added stale-context polling regressions for startup, cleanup, and retry status updates. Impact: the external PR #43 fix is now covered by maintainer-side tests and kept aligned with local style.

## 0.10.3: Dependency Audit Hotfix

- `Dependencies`: Refreshed the lockfile transitive dependency set to resolve current `protobufjs` / `@protobufjs/utf8` npm audit advisories inherited through development peer installs. Impact: `npm run validate` is green again without changing runtime API or bridge behavior.

## 0.10.2: Delete Message Port Hotfix

- `ctx.deleteMessage()`: Added `deleteMessage()` to `TelegramSectionContext` and `TelegramSectionCallbackContext`. Extensions can now delete the message that triggered a callback — useful for cleaning up confirmation dialogs after the user makes a choice.
- `API`: Added `deleteMessage` to `TelegramBridgeApiRuntime`, backed by Telegram's `deleteMessage` Bot API method with error recording.
- `Demo`: Confirmation dialog in `pi-telegram-extension-demo` now deletes itself on answer (`ctx.deleteMessage()`) and posts a follow-up result message (`ctx.open()`).
- `Docs`: Updated context port listings and interactive-messages section in `extension-sections.md` with `deleteMessage()`.

## 0.10.1: Navigation Abstraction Hotfix

- `ctx.open()`: Removed automatic Back-row prepend from `ctx.open()`. `ctx.open()` sends a new message into the chat — a Back button makes no sense outside the menu. `ctx.edit()` still auto-prepends the correct navigation row for in-menu views.
- `Platform Docs`: Extended `docs/extension-sections.md` with a dedicated section on sending interactive messages into chat via `ctx.open()`: confirmation dialogs, approve/deny gates, and extension-driven button flows that live outside the menu hierarchy.

## 0.10.0: Extension Sections Platform

- `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.
- `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.
- `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.
- `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.
- `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.
- `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.

## 0.9.9: Guest Mode HTML Rendering

- `Guest Mode`: Guest replies now render through the same `renderTelegramMessage` pipeline as direct messages: Markdown → HTML → `answerGuestQuery` with `parse_mode: "HTML"`. Bold, italic, code, links, lists, and tables render identically in guest and DM replies.
- `Replies`: Added `createGuestMarkdownReplySender` in the replies domain — guest rendering stays encapsulated within `replies.ts` and `index.ts` no longer imports from `rendering.ts` directly.
- `API`: Simplified `answerGuestQuery` title to a fixed `"Response"` string (the `InlineQueryResultArticle` title is hidden in guest mode and was previously generated by stripping HTML/Markdown from the message text).
- `API`: Removed `replyMarkup` parameter from `answerGuestQuery` — inline keyboards are not supported in guest mode because `callback_query` from inline results carries `inline_message_id` instead of `chat_id`/`message_id`, which the existing callback routing cannot handle.

## 0.9.8: Guest Mode Context

- `Guest Mode`: Extended the [telegram] prefix with |from:user (sender) and |guest:GroupName (source chat for group guest messages) so the agent sees who sent the message and where from. Private guest chats omit the guest: suffix.
- `Guest Mode`: Added |from:user to the [reply] block so the agent knows the original author of a replied-to message in guest mode.
- `Guest Mode`: Formatted guest prompt text identically to regular DMs through buildTelegramTurnPrompt, including [attachments] and [outputs] sections with file downloads and inbound handler processing.
- `Prompts`: Added compact agent guidance explaining guest-mode prefix suffixes (|from:, |guest:) and reply-from context.

## 0.9.7: Bot API 10.0 Alignment

- `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.
- `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.
- `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.
- `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.

## 0.9.6: Runtime Adapter Positioning

- `Package`: Repositioned the package description from "Better Telegram DM bridge extension for Pi" to "Telegram runtime adapter for Pi". Impact: package metadata now reflects the runtime adapter/operator-console role rather than a narrow pipe metaphor.
- `Telegram API`: Introduced `TELEGRAM_API_BASE` for the Bot API endpoint and documented native HTTP/HTTPS proxy operation through `HTTP_PROXY`, `HTTPS_PROXY`, `NO_PROXY`, and explicit `NODE_USE_ENV_PROXY=1` / `--use-env-proxy` enablement. Impact: users behind corporate proxies, local HTTP tunnels, or restricted networks get a zero-runtime-dependency proxy path without replacing native `fetch`; SOCKS5 remains outside the zero-dependency core.
- `Dependencies`: Refreshed the lockfile transitive dependency set so `npm audit` clears current `fast-uri` and `fast-xml-builder` advisories inherited through development peer installs. Impact: the full `npm run validate` pipeline passes without changing runtime dependencies.
- `README`: Restructured the user entrypoint around install → connect → use → core features → docs, then consolidated examples, terminology, proxy setup, `PI_CODING_AGENT_DIR`, and other environment-only configuration around the runtime-adapter/operator-console model. Impact: first-time users get a clearer path from installation to operation, while vivid examples and non-UI runtime knobs stay discoverable.
- `Context`: Promoted the runtime-adapter/operator-console README rhythm, `/start` menu emphasis, and environment-only configuration rule into `AGENTS.md`. Impact: future documentation edits preserve the same positioning and env-knob coverage instead of drifting back toward a narrow bridge metaphor.

## 0.9.5: Telegram Delivery Resilience Hotfix

- `Preview Delivery`: Preview flush failures from Telegram transport errors such as `fetch failed` / `ECONNRESET` are now caught and recorded as runtime diagnostics instead of escaping from the preview pipeline. Impact: transient Telegram connectivity failures no longer crash the extension during streamed preview edits.
- `Final Delivery`: Final Markdown preview replacement now catches Telegram transport failures and returns a normal fallback signal; the agent-end delivery path records final-text delivery failures and continues cleanup, attachment handling, and queue dispatch. Impact: a failed `editMessageText` at `agent_end` no longer breaks the bridge lifecycle or blocks the next queued Telegram turn.
- `Diagnostics`: Preview and final delivery failures now flow through the runtime event recorder with compact phase metadata. Impact: `/telegram-status` can show recent transport failures without dumping noisy stack traces into the extension runner.
- `Tests`: Added preview and queue regressions for non-fatal Telegram transport failures during preview flush and final delivery.
- `Extension Sections Draft`: Added a draft design note for pi-native Telegram extension sections, reserved the future `section:` callback prefix, linked the draft from docs, and recorded the project philosophy that `pi-telegram` should inherit Pi's extensibility model as a shared Telegram shell for loaded extensions. Impact: the future 0.10.0 extension platform direction is documented without exposing a stable API yet.
- `Docs Formatting`: Normalized project Markdown so prose paragraphs stay as single logical lines and Markdown tables remain narrow instead of using artificial hard wraps. Impact: editors and viewers can handle visual wrapping naturally while fixed-width structures stay readable.
- `Settings Copy`: Tightened the proactive-push settings text by removing redundant persistence/default wording.

## 0.9.4: Temp Dir And Command Template Hotfix

- `Telegram Temp Dir`: Default Telegram API temp files now respect `PI_CODING_AGENT_DIR`, falling back to `~/.pi/agent` when the env var is unset. Impact: sandboxed or relocated agent dirs no longer force Telegram downloads through the default home-directory path.
- `Command Templates`: Updated the local Command Template Standard: command-template nodes now document `mode`, `label`, `delay`, `repeat`, parallel fanout semantics, zero-based repeat placeholders, padding, and limited arithmetic expressions such as `{_(index+1)}`. Impact: inbound/outbound Telegram handler docs and helpers share the current portable automation contract without depending on another extension's documentation.
- `Queue Menu`: Empty queue refresh clicks now rotate through compact alternate empty-state headings while preserving the default first-open `⌛ Queue is empty.` state, and the Refresh button now stays directly under Back for both empty and populated queue lists. Impact: manual queue polling feels alive and the primary refresh control stays in a stable location without changing queue semantics.

## 0.9.3: External Handlers Rename

- `External Handlers`: Renamed the external update handlers domain to `external-handlers` across source, tests, and docs. Impact: the interop domain now has a cleaner name aligned with inbound/outbound handler naming.
- `Breaking`: Removed the old `external-update-handlers` module/doc path and old exported update/interceptor aliases. Impact: layered extensions should import from `@llblab/pi-telegram/lib/external-handlers.ts` and use the `TelegramExternalHandler*` names.

## 0.9.2: External Update Interceptors

- `External Update Interceptors`: Added a versioned `globalThis` registry that lets layered pi extensions observe and optionally consume Telegram updates before pi-telegram's default routing. Impact: approval gates and other same-process extensions can react synchronously to Telegram callbacks without owning a second bot poller.
- `External Update Interceptors`: Validated the full v1 registry shape (`version`, `add`, and `dispatch`) before reusing a pre-existing global registry and documented the zero-coupling bootstrap contract. Impact: install-order interop stays safe even when another extension initializes the registry first.
- `Queue Menu`: Non-empty queue lists now keep the `🌀 Refresh` row below queued items, matching the empty-queue surface. Impact: users can manually refresh the queue screen while waiting for changes without navigating away.
- `Security`: Refreshed the lockfile to resolve the transitive `basic-ftp` audit advisory. Impact: release validation returns to a clean npm audit state.

## 0.9.1: Model Detail Hotfix

- `Model Menu`: Detail-mode activation now preserves scoped `thinkingLevel` by resolving the selected scoped entry before falling back to the unscoped model list. Impact: scoped model shortcuts opened through the detail submenu keep their reasoning/thinking level.
- `Model Menu`: Activating an already active model from the detail submenu now still runs the refresh path that applies scoped thinking changes while returning to the model list. Impact: tapping Active can still correct the thinking level instead of becoming a no-op.
- `Proactive Push`: Removed the unused proactive reply-target store and always sends proactive local-result pushes without `reply_to_message_id`. Impact: the runtime no longer carries dead state for a target-capture behavior that does not exist yet.
- `Queue Reactions`: Added `🔥` as a priority reaction and `🗑` as a queue-removal reaction. Impact: the intuitive fire/removal gestures now work alongside the existing reaction controls.
- `Docs`: Updated the status-bar example to match the compact active/queued display.

## 0.9.0: Hidden Settings And Proactive Push

- `Settings Menu`: Added hidden Telegram `/settings` with a proactive push checkbox detail submenu plus `/telegram-settings` in the terminal. Impact: operators can see green/black binary flag state, use green/black/yellow on/off checkbox controls from Telegram, and toggle the same proactive push flag locally without adding a visible bot-command entry.
- `Proactive Push`: `telegram.json` now supports `proactivePush`; when enabled, successful local non-Telegram Pi final replies are sent to the paired Telegram chat if no Telegram turn is active and the current session still owns the Telegram lock. Local prompt text stays private because the bot does not own or mirror terminal user messages. Impact: long local tasks can notify the phone with result context without leaking from stale bridge owners or failed/aborted turns.
- `Queue UI`: Empty queue states now use the bottom-filled `⌛` hourglass while non-empty queue states keep `⏳`. Queue item details now show the selected queue position above the raw prompt preview, preserve reaction-specific priority emoji in the heading, and use side-by-side Priority/Normal tabs that refresh the heading marker immediately. The terminal status bar now stays yellow active while Telegram-owned work still has running tools even if a queued prompt is removed by reaction. Impact: queue emptiness has a small visual easter egg, item submenus stay oriented without changing queue semantics, and queue-removal reactions no longer visually degrade active work to connected.
- `Model Menu`: Model rows now open a detail submenu with Back, ☑️ Activate/🟢 Active selection, and yellow/black-marked Scoped/All membership tabs. Impact: model selection remains one tap away while scoped model membership can be managed from Telegram.
- `Status Menu`: The main Telegram menu status row now shows `compacting` while a Telegram `/compact` run is active. Impact: the phone UI reflects the same compaction state that already blocks dispatch and appears in terminal status.
- `Prompt Guidance`: Telegram prompt injection now asks agents to target 37 visible cells for tables, dense list items, and compact text blocks. Impact: replies better fit narrow mobile Telegram screens, especially when emoji or wide glyphs are present.

## 0.8.2: Lock-Safe Delivery

- `Lock Safety`: Active Telegram turns now re-check singleton ownership before preview flushes and final agent-end delivery. Impact: an old Pi instance stays silent after another instance takes the Telegram bridge lock, even if the old instance finishes a long-running prompt later.
- `Inbound Handlers`: The first step of an inbound composition now receives the full configured handler timeout before elapsed-time accounting starts on later steps. Impact: composition timeout behavior is deterministic and avoids one-millisecond test/runtime drift at pipeline start.
- `Menu UI`: Model and Thinking submenu headers now include their matching command icons (`🤖` and `🧠`). Impact: submenu headings match the Queue menu's icon-led style.

## 0.8.1: Outbound Voice Translation Hotfix

- `Outbound Voice`: Composed voice handlers now pass the original `telegram_voice` text to the first pipeline step through stdin, then continue piping each step's stdout into the next step. Impact: translate-from-stdin voice pipelines can translate hidden voice text before TTS instead of failing with an empty first-step input.
- `Queue Menu`: Queue item detail previews now render prompt text inside a bounded raw `<pre>` block, and generic queue navigation/headings use the `⏳` waiting icon. Impact: absolute file paths and attachment references remain readable without Telegram interpreting slash-prefixed paths as commands, long previews are truncated below Telegram's message limit, and the queue surface has a clearer generic icon distinct from ordered-list or priority markers.
- `Queue Delete`: Queue item removal now uses explicit `🗑 Delete` wording and opens a two-button confirmation (`🗑 Yes, delete` / `❌ No`) before mutating the queue. Impact: accidental queue-item deletion is harder while the item detail flow remains compact.
- `Queue Priority`: Priority reactions now preserve the exact normalized promotion emoji and render it in both queue-menu rows and the Pi status-bar queued preview. Reaction metadata is grouped into semantic id ranges (`10..13` for priority, `20..23` for removal). Impact: `👍`, `⚡`, `❤️`, and `🕊️` keep the same priority semantics while making the user's chosen reaction visible across Telegram and TUI surfaces.
- `Configuration Docs`: Documented the configuration philosophy that rich visual/TUI setup stays minimal for now while agents can read README/docs and update `telegram.json` for advanced workflows. Impact: configuration guidance matches the extension's agent-assisted operator model without adding premature TUI surfaces.
- `Outbound Docs`: Tightened voice-handler critical-step wording around transform → TTS → conversion pipelines and handler-level fallbacks. Impact: docs now match translated voice pipelines without implying provider-specific TTS fallbacks.
- `Command Template Docs`: Updated `docs/command-templates.md` to the current portable standard. Impact: the documented standard now includes retry, fail-open composition, critical-step abort semantics, and the 30s default timeout without requiring cross-extension references.
- `Lock Docs`: Synchronized `docs/locks.md` bit-for-bit with the extension-neutral Locks Standard shared by `pi-wakeup`. Impact: singleton ownership documentation no longer carries project-specific examples that prevent exact reuse across extensions.

## 0.8.0: Handler Bus

- `Inbound Handlers`: Added `inboundHandlers` as the provider-neutral Telegram → Pi transformation bus. Raw Telegram text can match `type: "text"`, `mime: "text/plain"`, or `mime: "text/*"`, receives text on stdin and `{text}`, and non-empty stdout replaces the prompt text before queueing; media/file handlers keep the existing `{file}`/`{mime}`/`{type}` behavior with optional independent selectors. Impact: translation, normalization, STT, OCR, and file extraction can share one command-template integration model.
- `Text Attachments`: Attached `text/plain`/`text/*` files now have a built-in fail-open reader that injects UTF-8 content into `[outputs]`: when no configured handler produced output. Impact: ordinary `.txt` and other text documents become readable to Pi without custom extraction config.
- `Inbound Domain`: Renamed the implementation module and mirrored regression suite from `attachment-handlers` to `inbound-handlers`. Impact: file names now match the unified text/media preprocessing domain while legacy `attachmentHandlers` config remains supported.
- `Outbound Attachment Domain`: Renamed the outbound file-delivery module and mirrored regression suite from `attachments` to `outbound-attachments`. Impact: `telegram_attach` ownership now reads as an outbound domain beside `outbound-handlers` while behavior stays unchanged.
- `Inbound Docs`: Consolidated the deprecated `docs/attachment-handlers.md` page into `docs/inbound-handlers.md` and removed the old page. Impact: the inbound bus docs are now the canonical home for legacy `attachmentHandlers`, placeholders, ordered fallbacks, and prompt-output behavior without split documentation.
- `Attachment Handlers`: `attachmentHandlers` is now deprecated but remains supported as a compatibility alias appended after `inboundHandlers`. Impact: existing voice/file preprocessing configs keep working while new configs can move to the unified inbound bus.
- `Outbound Handlers`: Added `outboundHandlers` support for `type: "text"`; final text/Markdown replies can be transformed before Telegram rendering and delivery. Impact: translation-back or other outbound text normalization can be configured without hard-coded providers.
- `Outbound Text Preview`: Finalized rich preview messages now pass through outbound `type: "text"` handlers before Telegram edit/delivery, with expanded README/docs examples for machine translation, final text rewrites, composed translated voice-over, and inline-button compatibility. Impact: outbound text transforms apply even when the final answer reuses an existing preview instead of falling back to a separate send path, while inline buttons remain attached and visible labels are transformed without changing callback prompts.

## 0.7.2: Split Text Coalescing Hotfix

- `Text Coalescing`: Telegram text messages that look like automatic splits of one near-limit human message are now short-debounced and forwarded to Pi as one prompt, using a conservative 3600-character near-limit threshold. Commands, bot messages, media groups, captions, non-contiguous messages, and normal short follow-ups bypass coalescing. Impact: long pasted logs/prompts are less likely to arrive as separate Pi turns when Telegram chunks them.
- `Runtime Tests`: The media-group runtime regression now waits for the real debounce instead of mixing fake timers with the polling loop, and the reaction-priority runtime test flushes pending microtasks before ending the active turn. Impact: CI should stop failing on timing-only races around delayed dispatch and queued reaction mutations.
- `Callback Namespaces`: Current status-screen navigation callbacks now use the canonical `menu:` namespace (`menu:model`, `menu:thinking`, `menu:queue`). `status:` remains reserved as an owned legacy prefix but is no longer emitted by current UI. Impact: new inline menu callbacks align with the unified app-menu model while old `status:` payloads still cannot leak to external fallback handlers.

## 0.7.1: Layered Callback Interop

- `Callback Interop`: Unknown Telegram inline-button callback data that does not belong to pi-telegram-owned prefixes (`tgbtn:`, `menu:`, `model:`, `thinking:`, `status:`, `queue:`) is now forwarded to Pi as `[callback] <data>` after assistant-button, queue-menu, and app-menu handlers decline it. `docs/callback-namespaces.md` defines the shared callback namespace standard for layered extensions. Impact: layered Pi extensions can namespace and handle their own Telegram inline buttons without polling the same bot or forking pi-telegram.
- `Prompt Templates`: Prompt-template aliases stay visible only inside `/start` and are no longer registered in the Telegram bot command menu. Impact: reusable Pi workflows remain discoverable without making Telegram's global command menu noisy.

## 0.7.0: Unified App Menu & Command Template Hardening

- `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.
- `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.
- `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.
- `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.
- `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.
- `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.
- `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.

## 0.6.3: Outbound Action Syntax & Prompt Guidance

- `Outbound Buttons`: `telegram_button: Label` now creates a label-only button whose callback prompt equals the label. Impact: button shorthand now matches the `telegram_voice: Text` inline style and leaves one canonical label-only syntax.
- `Outbound Actions`: `telegram_voice text="..."` and `telegram_button label=... prompt="..."` now provide explicit one-line action forms. Impact: agents can keep short voice and button actions on one line without relying on body blocks.
- `Outbound Parsing`: Hidden action bodies now stay attached to their action heads within the parser recovery window. Impact: hidden prompt and TTS bodies stay out of Telegram-visible messages.
- `Prompt Guidance`: Telegram prompt injection is now organized by inbound context, visible output, and native outbound actions, with explicit one-line vs body `telegram_button` syntax. Impact: agents get the same operational rules with less duplicated guidance and more consistent action markup.
- `Architecture`: Entrypoint wiring now names inbound routing, queue session lifecycle, agent lifecycle hooks, outbound reply collaborators, and repeated pi context ports before registration. Impact: `index.ts` remains the composition root while the final hook/polling registration blocks are easier to scan.
- `Config`: Missing `telegram.json` is now handled with an explicit existence check before reading. Impact: first-run config loading keeps the empty-config fallback without using read failures as control flow.

## 0.6.2: Reload-Stale Queue Dispatch Hotfix

- `Queue Dispatch`: Deferred post-agent-end queue dispatch is now session-bound and canceled on session shutdown. Impact: `/reload` and session replacement can no longer leave old queue timers calling stale `ExtensionContext` methods such as `ctx.isIdle()`.
- `Typing Safety`: Typing-loop transport failures now go only to runtime diagnostics instead of updating status through an interval-captured context. Impact: typing errors remain visible in diagnostics without retaining live `ExtensionContext` in timer error paths.
- `Lock Watcher Safety`: Ownership-loss watchers now retain only the snapshotted lock identity and stop polling without a captured live context. Impact: singleton takeover cleanup no longer needs stale-prone status refreshes from watcher callbacks.
- `Media Group Safety`: Media-group debounce timers now flush through controller state instead of closure-capturing the inbound context. Impact: album coalescing keeps the same behavior while reducing stale-context retention in timer callbacks.

## 0.6.1: Outbound Action & Command Timeout Hardening

- `Command Template Runtime`: Timed-out command templates now escalate from `SIGTERM` to `SIGKILL` when the child process does not exit. Impact: attachment and outbound-handler pipelines no longer hang forever on commands that ignore graceful termination.
- `Outbound Buttons`: `telegram_button` blocks may now omit the body when the callback prompt should equal the label. Impact: concise buttons such as `<!-- telegram_button label="OK" -->` work without duplicating the prompt text.
- `Outbound Comment Parsing`: Top-level outbound comments are now recognized again after fenced code blocks closed by Markdown-valid indented or longer fences. Impact: code examples stay literal while later `telegram_voice` and `telegram_button` blocks still execute correctly.
- `Command Template Docs`: The command-template contract now explicitly documents the strict 0.6.x shape: use `timeout`, and keep `args` as a string array of placeholder declarations. Impact: legacy `timeoutMs` and string-form `args` are not presented as supported compatibility paths.

## 0.6.0: Command Templates & Assistant-Authored Outbound Actions

- `Outbound Actions`: Assistant replies now use hidden `telegram_voice` and `telegram_button` blocks as Telegram-native action markup. Impact: text stays in the normal Markdown answer, voice block bodies become native OGG/Opus `sendVoice` messages, and button bodies become normal queued Telegram prompt turns without agent-side transport tool calls.
- `Outbound Semantics`: Outbound behavior is now owned by the unified `outbound-handlers` domain. Impact: voice artifacts, per-block language/rate attributes, independent multi-voice delivery, singular one-block-one-button callbacks, top-level-only comment stripping, artifact upload, and prompt reply metadata are planned and delivered as one post-`agent_end` response surface while code examples stay literal.
- `Command Template Standard`: Command-backed handlers now share a compact shell-free template contract: no `command` field, `template` as string or `template: [...]`, `args` as declarations only, defaults via `defaults` or `{name=default}`, top-level `timeout` wrapping composed sequences, stdout-to-stdin composition piping, and `output` defaulting to `"stdout"` while allowing artifact selectors such as `"ogg"`. Impact: inbound attachment preprocessing and outbound artifact generation use the same portable automation model without provider-specific fields or shell evaluation.
- `Handler Boundaries`: Inbound preprocessing now lives in `attachment-handlers`, outbound generated actions live in `outbound-handlers`, and reusable template mechanics live in `command-templates`. Impact: file names, mirrored tests, and docs match the actual domains instead of broad `handlers`, standalone voice, or grouped button mini-DSL boundaries.
- `Docs`: Handler examples now use portable `/path/to/stt`, `/path/to/tts`, and `/path/to/tool` placeholders and dense command-template documentation. Impact: release docs describe what operators configure without leaking host-local skill paths or repeating the same template rules across documents.

## 0.5.2: Telegram Reply Context

- `Telegram Replies`: Normal Telegram prompts now include quoted Telegram `reply_to_message` text/caption as a bounded `[reply]`: context block. Impact: replying to an earlier Telegram message gives the agent the quoted context instead of only the new message text. Inspired by external PR #4 from @maphim.
- `Command Safety`: Slash-command parsing still uses only the new message text/caption, and reply context is injected only while building or editing queued prompt turns. Impact: replying with `/status`, `/model`, `/stop`, and other commands still executes the command instead of becoming a normal prompt.
- `Docs & Tests`: Updated README, architecture/context notes, package metadata, and media/turn regressions for reply-context forwarding, truncation, queued edits, and command-safe raw text extraction. Impact: the feature is documented and covered without weakening the existing queue/command split.

## 0.5.1: Stop Queue Reset Hotfix

- `Queue Safety`: Telegram `/stop` now clears all waiting Telegram queue items, resets pending model-switch/abort-history preservation state, and then aborts the active run when possible. Impact: queued priority/default/control turns can no longer leave the bridge stopped after an abort; the next Telegram message starts from a clean queue like a fresh TUI prompt.
- `Docs & Tests`: Updated README, architecture notes, agent context, and queue/runtime/command regressions for the new stop/reset contract. Impact: the hotfix behavior is documented and covered by the high-risk stop plus queue path.

## 0.5.0: Command Templates, Domain Boundaries & Queue UX

- `Queue UX`: Telegram `/status` and `/model` now execute immediately, post-agent-end queue dispatch retries after pi settles idle state, and the status bar shows specific busy labels (`active`, `dispatching`, `queued`, `tool running`, `model`). Reaction priority remains local and applies to text, voice, file, image, and media-group turns without introducing pi steering semantics. Impact: controls do not get stuck behind generation, queued work no longer needs a later Telegram update to unstick, and attachment turns keep predictable ordering.
- `Attachment Handlers`: Inbound preprocessing now uses portable `template` configs with `args`/`defaults` and ordered fallback chains, documented in `docs/command-templates.md` and current inbound handler docs. Impact: voice/STT primary-fallback setups work from `telegram.json` without coupling pi-telegram to private auto-tool registry internals.
- `Domain Boundaries`: Removed the broad `registration` domain and moved registration surfaces to owners: attachments register `telegram_attach`, commands register pi `/telegram-*` commands, lifecycle registers hooks, and prompts own Telegram-specific system prompt injection. Impact: entrypoint wiring is clearer and each registration surface has focused tests.
- `telegram_attach`: The outbound attachment tool now lives in the attachments domain with outbound limits, queueing failure events, and pi-friendly tool-result formatting. Impact: outbound file delivery behavior is owned by the same domain that queues and sends Telegram attachments.
- `Docs & Validation`: Updated README, docs, architecture/context maps, backlog, focused coverage, and removed vendored repository-local agent skills in favor of global validation tooling. Impact: user-facing docs, validation, and package-adjacent repo contents match the 0.5.0 code shape without stale skill copies.

## 0.4.0: Singleton Locks & Attachment Handlers

- `Locks`: Added the shared `locks.json` singleton ownership standard and documented it in `docs/locks.md`. Telegram polling ownership now lives under `@llblab/pi-telegram` in `~/.pi/agent/locks.json`, while `telegram.json` remains pure bot/user configuration. `/telegram-connect` acquires the lock, replaces stale locks, or moves live external owners here through an interactive confirmation; `/telegram-disconnect` releases it. Session initialization reads ownership state, active owners stop local polling when `locks.json` no longer points at their own `pid`/`cwd`, session replacement via `/new` suspends polling/watchers without touching explicit ownership before resuming in the new session, and a reopened pi process resumes a stale same-`cwd` lock automatically. Impact: runtime locks can be reset or moved without deleting Telegram configuration, finding the previous pi instance, or crashing on stale extension contexts.
- `Attachment Handlers`: Added `telegram.json` inbound attachment handlers with MIME/type matching, safe command placeholder substitution, compact `[attachments] <directory>` plus `[outputs]`: prompt sections, and quiet omission of empty or failed handler output. Impact: common flows such as Telegram voice transcription can happen before the agent sees the turn while keeping source attachment paths visible.
- `Refactor`: Extracted inbound route composition from `index.ts` into `/lib/routing.ts`, keeping paired update execution, callback menus, command-or-prompt dispatch, media grouping, prompt enqueueing, queued edits, and attachment-handler turn building behind one cohesive route wiring boundary. Impact: the entrypoint stays smaller while high-risk Telegram update flow remains covered by runtime and invariant tests.

## 0.3.0: Modular Runtime, Queue Controls, Diagnostics

- `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.
- `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.
- `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.
- `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.
- `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.
- `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.
- `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.
- `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.

## 0.2.x: Fork Genesis

- `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.
- `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.
- `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.
- `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.
- `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.
- `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.
- `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.
- `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.
