feat: v0.35.1rc4 — /at, hot-reload bridge, trigger visibility, restart Tier 1#292
Conversation
systemd user services inherit OOMScoreAdjust=200 + OOMPolicy=stop defaults, which made Untether's engine subprocesses preferred earlyoom/kernel OOM killer targets ahead of CLI claude (oom_score_adj=0) and orphaned grandchildren actually consuming the RAM. When lba-1 ran low on RAM, live Telegram chats died with rc=143 (SIGTERM) while the processes actually eating the RAM survived. Updates contrib/untether.service with: - OOMScoreAdjust=-100 — documents intent; kernel clamps to the parent baseline for unprivileged users (typically 100), but takes effect if the parent user@UID.service is ever overridden lower - OOMPolicy=continue — a single OOM-killed child no longer tears down the whole unit cgroup; previously every live chat died at once Also updates docs/reference/dev-instance.md with a new OOM section covering the asymmetry, the clamping caveat, and the optional sudo systemctl edit user@UID.service override for operators who want Untether's children to live longer than CLI processes. Existing installs need to copy the unit file and `systemctl --user daemon-reload`; staging picks up the change on the next `scripts/staging.sh install` cycle. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ibility, restart Tier 1 (#271, #286, #287, #288) Bundles four rc4 features plus a CHANGELOG entry for #283 (diff_preview gate, already on dev as 8c04904). Full details in CHANGELOG.md. #269/#285 hot-reload triggers: merged separately as PR #285 (squash-merged to dev); this commit extends TriggerManager with rc4 helpers (remove_cron, crons_for_chat, webhooks_for_chat, cron_ids, webhook_ids) for Features 4b and 5 below. #288 — /at command and run_once cron flag: - new telegram/at_scheduler.py — module-level task-group + run_job holder; schedule_delayed_run(), cancel_pending_for_chat(), active_count(); per-chat cap of 20 pending delays - new telegram/commands/at.py — AtCommand backend, /at <duration> <prompt> with Ns/Nm/Nh suffixes, 60s-24h range - /cancel integration via cancel_pending_for_chat() - drain integration via active_count() in _drain_and_exit - entry-point at = untether.telegram.commands.at:BACKEND - CronConfig.run_once: bool = False; scheduler removes cron after fire if run_once=True; re-enters on reload/restart #286 — unfreeze TelegramBridgeConfig: - drop frozen=True (slots preserved); add update_from(settings) method - route_update() reads cfg.allowed_user_ids live; handle_reload() calls update_from() and refreshes state.forward_coalesce_s / media_group_debounce_s - restart-only keys still warn (bot_token, chat_id, session_mode, topics, message_overflow); others hot-reload #271 — trigger visibility Tier 1: - new triggers/describe.py — describe_cron(schedule, timezone) utility - /ping shows per-chat trigger indicator when triggers target the chat - RunContext.trigger_source field; dispatcher sets it to cron:<id>/webhook:<id>; runner_bridge seeds progress_tracker.meta['trigger'] with icon + source; ProgressTracker.note_event merges engine meta over dispatcher meta - format_meta_line() appends 'trigger' to footer parts - CommandContext gains trigger_manager, default_chat_id fields (default None); populated by telegram/commands/dispatch.py from cfg #287 — graceful restart Tier 1: - new sdnotify.py — stdlib sd_notify client (READY=1 / STOPPING=1); poll_updates sends READY=1 after _send_startup succeeds; _drain_and_exit sends STOPPING=1 at drain start - new telegram/offset_persistence.py — DebouncedOffsetWriter; loads saved update_id on startup, persists via on_offset_advanced callback in poll_incoming; flushes in poll_updates finally block - contrib/untether.service: Type=notify, NotifyAccess=main, RestartSec=2 Tests: +224 tests added across 6 new test files and 6 extended files; 2164 total tests pass with 81.55% coverage. Context files (CLAUDE.md, .claude/rules/*) and human docs (README, triggers reference, dev-instance, integration-testing, webhooks-and-cron how-to, commands-and-directives) updated. rc4 integration test scenarios R1-R10 added to integration-testing.md. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
anyio.CancelScope.__exit__ swallows the Cancelled exception when the scope itself caused the cancellation. The fire/dispatch code outside the scope continued regardless. Added cancelled_caught check after the scope exits to prevent stale timers from dispatching. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
52-test plan covering all rc4 features: /at command, run_once, hot-reload (triggers + bridge config), trigger visibility, graceful restart Tier 1, plus standard Tier 1/6/7 regression. Includes correct dev bot chat IDs (Bot API + Telethon MCP mapping), pre-test trigger config, results template, and known caveats. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Integration Test Report — v0.35.1rc4Date: 2026-04-14 Results: 46/52 pass, 0 fail, 6 skip
Detailed results posted to individual issues
Non-Untether findings
Verdictrc4 is ready for staging. All new features work correctly in live Telegram. No Untether bugs found during testing. |
The old ut-dev-hf: chat IDs (5171122044 etc.) belong to a different bot (ID 8485467124). Updated both docs to the current @untether_dev_bot chats with both Telethon and Bot API ID forms. Added note about Telegram MCP PeerUser fallback for channel/supergroup IDs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
HIGH priority: - config.md: add run_once to cron table, fix watch_config description to list hot-reloadable vs restart-only settings - operations.md: fix hot-reload section (transport settings ARE now partially hot-reloadable), add /ping trigger format, update_id persistence, systemd section with Type=notify/OOM notes - schedule-tasks.md: add /at command section with examples, run_once mention MEDIUM priority: - triggers.md: remove duplicate hot-reload section, keep authoritative version with watch_config requirement and last_fired note - CLAUDE.md: add diff_preview plan bypass (#283) to features list - troubleshooting.md: add entries for config hot-reload issues and /at delay not firing LOW priority: - security.md: document untrusted-payload prefix for webhooks/cron - voice-notes.md: note that voice settings hot-reload - specification.md: bump version to v0.35.1 - tutorials: update version numbers from 0.35.0 to 0.35.1 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
Bundles six items for v0.35.1rc4:
8c04904)8e891a0remove_cron,crons_for_chat,webhooks_for_chat,cron_ids,webhook_idshelpers toTriggerManagerfor Features feat: one-shot delayed triggers — /at command and run_once cron flag #288 and feat: trigger visibility — indicators, discovery, and run history #271TelegramBridgeConfig—update_from()wired intohandle_reload(); voice, files,allowed_user_ids, timing settings now hot-reload/atcommand andrun_oncecron flag/pingindicator, trigger footer,describe_cron()update_id,Type=notifysd_notify,RestartSec=2Full details and CHANGELOG entries in
CHANGELOG.mdunder## v0.35.1.Test plan
uv run ruff format --check+ruff checkcleanuv lock --checkcleanscripts/validate_release.pypasses (skips rc per discipline)@untether_dev_bot— tier 7 command smoke, tier 1 all-engines, plus new rc4 scenarios R1-R10 (seedocs/reference/integration-testing.md)@hetz_lba1_botfor 1+ week before v0.35.1 stable tagNew files
src/untether/sdnotify.py— stdlib sd_notify clientsrc/untether/telegram/at_scheduler.py—/atmodule-level schedulersrc/untether/telegram/commands/at.py—/atbackendsrc/untether/telegram/offset_persistence.py— update_id persistencesrc/untether/triggers/describe.py—describe_cron()utilitytests/test_at_command.py,test_bridge_config_reload.py,test_describe_cron.py,test_offset_persistence.py,test_sdnotify.py,test_trigger_meta_line.pyDocs
CHANGELOG.mdv0.35.1 section: 6 new entriesCLAUDE.mdfeatures + key files + testsREADME.md—/atin commands table, trigger visibility in Scheduled tasks bulletdocs/reference/triggers/triggers.md— Hot-reload section, Trigger visibility section,run_onceflagdocs/reference/commands-and-directives.md—/atrowdocs/reference/dev-instance.md—Type=notify+RestartSec=2sectionsdocs/reference/integration-testing.md— Q14-Q16 + new rc4 scenarios R1-R10docs/how-to/webhooks-and-cron.md—run_once,/at, discovery sections.claude/rules/telegram-transport.md— hot-reload + sd_notify + /at sections.claude/rules/runner-development.md— RunContext.trigger_source🤖 Generated with Claude Code