You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+8Lines changed: 8 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,6 +2,14 @@
2
2
3
3
## Unreleased
4
4
5
+
## v0.2.5 - 2026-05-06
6
+
7
+
- Added the Telegram notification contract: `New run` is configurable, `[Plan]` and `[Final]` notify, while live progress, direct responses, menus, callbacks, exports, and errors are sent silently.
8
+
- Changed Final rendering to send a new `[Final]` message and best-effort delete transient live cards, preserving Details routing on the new Final Card.
9
+
- Fixed tool-only runs so live current tools are not erased by stale polling snapshots and completed tool-only commands remain visible in Details and Tools file.
10
+
- Added explicit Default Mode escape hatches through `/default` and `/reply --default` for threads that remain in App Server Plan Mode.
11
+
- Added ADR-015, contract/regression documentation, release validation notes, Telegram transport tests for `disable_notification`, and live E2E coverage for notification and tool-only Details behavior.
12
+
5
13
## v0.2.4 - 2026-05-05
6
14
7
15
- Changed `/newchat <prompt>` to create a real Codex UI Chat folder under `CTR_GO_CODEX_CHATS_ROOT` before starting the new thread.
Copy file name to clipboardExpand all lines: README.md
+9-5Lines changed: 9 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,7 @@ Codex Telegram bot and remote UI for local OpenAI Codex App Server, built in Go.
4
4
5
5
`codex-tg` turns a Telegram bot into a mobile control surface for local Codex threads: it watches Codex GUI/CLI activity, keeps thread identity visible, routes replies back to the right thread, and exposes high-signal controls such as Plan Mode prompts, Stop, Steer, Details, Tools file, and Get full log.
6
6
7
-
Current release: `v0.2.4`.
7
+
Current release: `v0.2.5`.
8
8
9
9

10
10
@@ -38,7 +38,8 @@ The demo flow is documented in [docs/demo/telegram-plan-mode-demo.md](docs/demo/
38
38
- Telegram-origin live current tool rendering from App Server `item/*` events, while foreign GUI/CLI panels stay completed-tool only.
39
39
- Stable visual identity per thread: emoji marker plus project/thread/run chips.
40
40
- Explicit `New run -> [User] -> [commentary] -> [Tool] -> [Output] -> [Final]` chronology with status on the live commentary/final card.
41
-
- Plan Mode starts from Telegram via `/plan` or `/reply --plan`, then renders `[Plan]` prompt-cards with reply-first routing and structured buttons when Codex provides choices.
41
+
- Low-noise Telegram notifications: only `New run` (configurable), `[Plan]`, and `[Final]` are audible; live progress and exports are sent silently.
42
+
- Plan Mode starts from Telegram via `/plan` or `/reply --plan`, and Default Mode can be forced with `/default` or `/reply --default` if a thread needs to leave Plan Mode; `[Plan]` prompt-cards keep reply-first routing and structured buttons when Codex provides choices.
42
43
- Final Card with Details pagination and on-demand Tools file export.
43
44
- On-demand full log archive from Codex session JSONL.
44
45
- SQLite-backed durable state for bindings, routes, callbacks, observer target, panels, and delivery metadata.
@@ -47,7 +48,7 @@ The demo flow is documented in [docs/demo/telegram-plan-mode-demo.md](docs/demo/
47
48
## Platform Status
48
49
49
50
- Windows: actively tested with the local Codex App Server, Telegram Bot API, observer flows, and live E2E demo.
50
-
- macOS: `v0.2.4` is verified stable on macOS 26.3.1 arm64 with Go 1.26.2, LaunchAgent daemon startup, local build, Details binding validation, Telegram command-menu readback, real Chat folder creation, and live Telegram readback E2E.
51
+
- macOS: `v0.2.5` is verified stable on macOS 26.3.1 arm64 with Go 1.26.2, LaunchAgent daemon startup, local build, Details binding validation, Telegram command-menu readback, real Chat folder creation, low-noise notification validation, and live Telegram readback E2E.
51
52
- Linux: CI runs tests/builds on Ubuntu; full local daemon/runtime validation is still pending.
52
53
53
54
## Quickstart
@@ -79,7 +80,9 @@ In Telegram:
79
80
/context
80
81
```
81
82
82
-
Start or continue a Codex thread from Codex GUI/CLI. `codex-tg` should create a `New run` card, a `[User]` card, live progress cards, and then collapse the completed run into a final answer card with Details.
83
+
Start or continue a Codex thread from Codex GUI/CLI. `codex-tg` should create a `New run` card, a `[User]` card, live progress cards, and then send a final answer card with Details while cleaning up transient live cards.
84
+
85
+
Set `CTR_GO_NOTIFY_NEW_RUN=off` to keep `New run` visible but silent. `[Plan]` prompts and `[Final]` cards still use normal Telegram notifications.
Copy file name to clipboardExpand all lines: docs/adr/ADR-004-final-card-details-ux.md
+5-4Lines changed: 5 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,23 +2,24 @@
2
2
3
3
- Status: accepted
4
4
- Decision: active runs keep trio live visibility, while completed runs collapse into one Final Card with a Details view.
5
+
- Amended by: ADR-015 for Final Card notification delivery.
5
6
6
7
## Decisions
7
8
8
9
- An active run remains live-visible through the trio of Telegram surfaces used for current execution state, tool activity, and output activity.
9
-
- After the final answer is available, the completed run collapses into one Final Card.
10
+
- After the final answer is available, the completed run collapses into one newly sent Final Card.
10
11
-`Details` is view-state of that one Telegram message, not a stream of new detail messages.
11
12
- Details mode may page through final text, tool calls, and output without creating a replacement message stream.
12
13
- Tool and output content remains available on demand in Details tool mode.
13
14
- Full tool and output content is also available as a `.txt` file when message-sized rendering is not practical.
14
-
- Deletion of old live tool/output messages after finalization is best-effort.
15
+
- Deletion of old live commentary/tool/output messages after finalization is best-effort.
15
16
- Details callbacks are bound to the completed run panel/card that created them. Missing, stale, or mismatched panel metadata must fail closed instead of falling back to the current panel for the thread.
16
17
17
18
## Consequences
18
19
19
-
- The completed-run operator surface is one stable message with Final and Details states.
20
+
- The completed-run operator surface is one stable message with Final and Details states. That stable message is the new Final card, not the earlier live commentary message.
20
21
- Callback handlers must edit the existing card whenever Telegram permits it instead of emitting a new stream of messages.
21
22
- Pagination state belongs to the card view and must be recoverable from callback payloads or persisted card metadata.
22
23
- Callback handlers must verify the panel, thread, turn, chat/topic, and message id before editing a Details/Final card or exporting Details tools.
23
24
- Tool/output live messages must not be treated as durable final history; the final card and on-demand `.txt` export are the durable review surface.
24
-
- Cleanup failures for old live tool/output messages must not fail final delivery.
25
+
- Cleanup failures for old live commentary/tool/output messages must not fail final delivery.
Copy file name to clipboardExpand all lines: docs/adr/ADR-006-plan-prompt-mode.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,6 +8,7 @@
8
8
- A waiting Plan Mode prompt is rendered as a separate `[Plan]` prompt-card, not as a Final Card state and not as a passive tool/output message.
9
9
- Telegram-originated Plan Mode runs must be started with App Server `turn/start``collaborationMode.mode = plan`; prompt wording alone is not treated as Plan Mode.
10
10
- Telegram exposes Plan start commands through `/plan <text>`, `/plan_mode <text>`, `/plan <thread> <text>`, `/plan_mode <thread> <text>`, and `/reply --plan <thread> <text>`.
11
+
- Telegram exposes Default Mode reset commands through `/default <text>`, `/default <thread> <text>`, and `/reply --default <thread> <text>`, which pass App Server `turn/start``collaborationMode.mode = default`.
11
12
-`/plan <text>` and `/plan_mode <text>` use normal routing precedence after the command: reply-to route, armed state, then bound thread.
12
13
-`/plan <thread> <text>` and `/plan_mode <thread> <text>` are treated as explicit-thread commands only when the first token is a known thread id or UUID-like Codex thread id. Unknown plain words remain part of the prompt text for the implicit route.
13
14
-`/reply --plan <thread> <text>` stays strict and requires an explicit thread id.
Copy file name to clipboardExpand all lines: docs/adr/ADR-010-run-chronology-and-user-notice.md
+2-1Lines changed: 2 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,6 +2,7 @@
2
2
3
3
- Status: accepted
4
4
- Supersedes: ADR-009
5
+
- Amended by: ADR-015 for notification policy and Final Card delivery mechanics.
5
6
6
7
## Context
7
8
@@ -16,7 +17,7 @@ The Telegram observer is also a security surface: if a local GUI/CLI or another
16
17
-`New run` is an orientation card with source metadata only. It does not own run status.
17
18
-`[User]` is delivered once as request context. It does not show run status and is not updated for status-only changes.
18
19
- The live `[commentary]` card owns run status while the run is active.
19
-
- At terminal finalization, `New run`, `[Tool]`, and `[Output]`are deleted best-effort. `[User]` remains as historical request context, and `[commentary]` is edited into `[Final]`.
20
+
- At terminal finalization, the bridge sends a new `[Final]` card, then deletes `New run`, `[commentary]`, `[Tool]`, and `[Output]` best-effort. `[User]` remains as historical request context.
20
21
-`[Final]` shows final-answer text and status only; completed commentary/tool/output history is available through Details.
21
22
- DB message routes and callback tokens remain the routing source of truth.
- Supersedes: the terminal finalization message-edit detail in ADR-004 and ADR-010.
5
+
6
+
## Context
7
+
8
+
Telegram notification volume can become noisy when every observer card is sent as a normal message. The operator still needs audible attention for genuinely important events: a new run, a final answer, and a Plan Mode question that needs a choice or reply.
9
+
10
+
Telegram edits do not provide a reliable per-edit notification contract. Therefore a `[Final]` that is produced by editing the live `[commentary]` card cannot be made audible without also making the earlier commentary message audible.
11
+
12
+
## Decision
13
+
14
+
- New messages are silent by default through Telegram Bot API `disable_notification=true`.
15
+
- Audible messages are limited to:
16
+
-`New run`, controlled by `CTR_GO_NOTIFY_NEW_RUN` and enabled by default;
17
+
- a newly sent `[Final]` card;
18
+
- a routeable `[Plan]` prompt-card for user input or structured choices.
19
+
-`[commentary]`, `[Tool]`, `[Output]`, `[User]`, command/menu responses, explicit exports, and fallback/error messages are silent.
20
+
- Finalization sends a new `[Final]` card, records its message route, moves the panel summary message id to that new card, and then best-effort deletes the old `[commentary]`, `New run`, `[Tool]`, and `[Output]` messages.
21
+
-`[User]` remains as historical request context.
22
+
- Details and Back callbacks remain bound to the completed run panel/card. After finalization, the panel's summary message id is the new `[Final]` message id.
23
+
24
+
## Consequences
25
+
26
+
- The operator receives fewer notifications while preserving alerts for run start, required Plan input, and run completion.
27
+
- The completed-run surface is still one stable Final/Details message, but it is no longer the same Telegram message that previously held live commentary.
28
+
- Old routes for deleted live commentary messages may remain in SQLite, but active callback routing uses the new Final card message id.
29
+
- Cleanup failures for old live messages must not fail Final delivery.
30
+
31
+
## Non-goals
32
+
33
+
- This does not add per-chat notification profiles.
34
+
- This does not make Telegram edits audible.
35
+
- This does not change App Server protocol or Plan Mode routing.
- Telegram notification noise is reduced: only `New run` (configurable), `[Plan]`, and `[Final]` use normal Telegram notifications.
6
+
-`[Final]` is delivered as a new message and transient live cards are cleaned up best-effort after finalization.
7
+
- Tool-only runs, such as a single long shell command with empty output, keep their current tool visible while running and expose the completed command in Details and Tools file.
8
+
-`/default` and `/reply --default` can force the next Telegram-origin turn into App Server Default Mode when a thread remains in Plan Mode.
9
+
- ADR-015 records the notification contract.
10
+
11
+
## Validation
12
+
13
+
-`go test ./internal/appserver ./internal/daemon ./internal/telegram`
14
+
-`go test ./internal/telegram ./internal/config ./internal/daemon ./internal/storage ./tests`
15
+
-`go test ./...`
16
+
-`go build -buildvcs=false ./...`
17
+
-`git diff --check`
18
+
- Python compile for the live E2E harness
19
+
- targeted secret/local scan
20
+
- macOS LaunchAgent rebuild/restart
21
+
- checked-in live Telegram E2E cases: `tool_only_sleep_details` and `notification_contract`
22
+
23
+
## Notes
24
+
25
+
- No App Server protocol changes were required.
26
+
- No database migration is required.
27
+
-`CTR_GO_NOTIFY_NEW_RUN=false` keeps the `New run` card visible but silent.
Copy file name to clipboardExpand all lines: docs/research/contract-matrix.md
+11-1Lines changed: 11 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -15,7 +15,9 @@ This file now serves two purposes:
15
15
-`/projects`
16
16
-`/show <thread>`
17
17
-`/bind <thread>`
18
-
-`/reply [--plan] <thread> <text>`
18
+
-`/reply [--plan|--default] <thread> <text>`
19
+
-`/default <thread> <text>`
20
+
-`/default <text>`
19
21
-`/plan <thread> <text>`
20
22
-`/plan <text>`
21
23
-`/plan_mode <thread> <text>`
@@ -53,9 +55,11 @@ This file now serves two purposes:
53
55
- The summary panel owns `Stop` and `Steer`.
54
56
- Tool/output stream messages do not carry buttons.
55
57
- Final answers are delivered separately and expose `Получить полный лог`.
58
+
- Telegram sends normal notifications only for `New run` (configurable through `CTR_GO_NOTIFY_NEW_RUN`), `[Plan]` prompt-cards, and `[Final]`; other bot messages are silent.
56
59
- Plan Mode / waiting-input states create a separate routeable `[Plan]` prompt-card.
57
60
-`[Plan]` buttons are structured-only: they come from Codex `choices/options/suggestions/responses`, never from bridge heuristics.
58
61
- Telegram-originated Plan Mode starts use App Server `turn/start` with `collaborationMode.mode = plan`; prompt wording alone is not Plan Mode.
62
+
- Telegram-originated Default Mode starts through `/default` and `/reply --default` use App Server `turn/start` with `collaborationMode.mode = default`, which is the operator escape hatch when a thread remains in Plan Mode.
59
63
-`/model` and `/effort` are button menus backed by SQLite daemon state for Telegram-started collaboration-mode model settings.
60
64
- After a model or reasoning-effort selection, the edited settings message removes inline choice buttons.
61
65
-`/projects` groups cached non-Chat projects by normalized `cwd`, sorts projects by latest cached thread activity, shows latest Codex UI Chat previews, opens full Chats pagination through `Open Chats`, and never accepts arbitrary filesystem paths from Telegram.
@@ -135,6 +139,7 @@ Additional route rules:
135
139
- reply-to `[Plan]` routes before binding and carries `thread_id`, `turn_id`, and `request_id` when available
136
140
- real `request_id` Plan answers use App Server server-request response; synthetic Plan answers use `turn/steer`
137
141
-`/reply --plan`, `/plan`, and `/plan_mode` carry an explicit Plan Mode start intent when they create a new turn
142
+
-`/reply --default` and `/default` carry an explicit Default Mode start intent when they create a new turn
0 commit comments