fix: set APScheduler misfire_grace_time=None for reliable job execution - #178
Merged
RichardAtCT merged 1 commit intoSep 11, 2026
Merged
Conversation
With misfire_grace_time=300, heartbeats were still missed when the bot was busy for >5 minutes (observed: 8m54s miss). Setting to None guarantees every job fires exactly once, combined with coalesce=True to prevent duplicate execution.
4 tasks
paulpwo
added a commit
to paulpwo/claude-code-telegram
that referenced
this pull request
Apr 11, 2026
…irehq#151, overwirehq#160 - overwirehq#178: APScheduler misfire_grace_time=None — jobs no se dropean silenciosamente - overwirehq#177: Jobs del scheduler en background tasks — no bloquean el event bus - overwirehq#151: Comando /schedule desde Telegram (list, add, pause, resume, remove) - overwirehq#160: Comando /model para switch de modelo y effort en runtime Conflicto resuelto: test_orchestrator.py actualizado a 8 comandos agentic (/model + /sdd).
RichardAtCT
pushed a commit
that referenced
this pull request
Sep 11, 2026
Integration fixes for the six PRs merged into this branch. Each change belongs to a specific PR that could not land as-is: #196 — removed an unused `patch` import from the new webhook test (flake8 F401 would have failed CI on main). #177, #178 — reformatted with black; both were submitted unformatted. #206 — dropped the .gitignore hunk, which added the contributor's personal .env.bak/.env.bak2/.env.kai entries (the trailing-newline fix on config/mcp.json is kept). Rewrote the rationale comment: the claimed "'NoneType' object is not iterable" crash does not reproduce on the pinned claude-agent-sdk 0.1.39, which guards with a truthiness check. The change is still worth taking — ClaudeAgentOptions declares these as list[str] with default_factory=list, so None violates the dataclass contract and the project floats on ^0.1.39 — but as hardening rather than as the crash fix it claimed to be. Added explicit Optional[List[str]] annotations so mypy does not infer list[Any] from the [] branch. #206 x #220 — reconciled the escape-hatch assertion in test_disable_tool_validation_restores_permissive_behavior, which #220 added asserting `allowed_tools is None`. Both values are falsy, so the CLI omits --allowedTools either way and DISABLE_TOOL_VALIDATION=true remains unrestricted; only the sentinel changes. Verification: 559 passed; black, isort and flake8 clean. mypy gains 3 errors, all from #196's use of self.app in webhook mode — the same Optional-narrowing pattern that already produces ten identical errors in that file, and mypy is not run in CI. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tk9xKUdrarDX5KmUuwcjN8
RichardAtCT
pushed a commit
that referenced
this pull request
Sep 11, 2026
Patch release covering the security fix in #220 and the six bug fixes merged via #223 (#214, #212, #196, #177, #178, #206). Carries an upgrade note: #220 means tool calls targeting paths outside APPROVED_DIRECTORY are now denied where they previously succeeded. That restores the documented behaviour, but it is a real change for any deployment that relied on the gap. Also records the known limitation tracked in #221 — CLAUDE_ALLOWED_TOOLS does not block tools left off the list. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tk9xKUdrarDX5KmUuwcjN8
RichardAtCT
pushed a commit
that referenced
this pull request
Sep 11, 2026
Drop the out-of-scope rows for PRs merged in 1.6.2 (#214, #212, #196, #177, #178, #206), note #220, point the AskUserQuestion and ExitPlanMode items at the GUARDED_TOOLS set that 1.6.2 introduced, and remove the docs/tools.md item that 1.6.2 already fixed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019LaezV767Pguhpat9zVyEs
RichardAtCT
added a commit
that referenced
this pull request
Sep 11, 2026
* docs: add v2 roadmap Plan the 2.0 release in docs/ROADMAP-v2.md: SDK 0.2 migration, interactive question/plan/permission UX over inline keyboards, file-checkpoint undo, per-conversation concurrency, a session browser, token-based usage reporting, classic-mode removal, and container/PyPI distribution. Work already covered by open pull requests is listed as out of scope so contributors do not duplicate it. Link it from the docs index and changelog. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019LaezV767Pguhpat9zVyEs * chore: add community health files and first-pass review automation Add the files a contributor-driven project needs that were missing: issue forms (bug, feature, question) that ask for version, mode and logs up front; a pull request template with a hand-testing section; CODEOWNERS; MAINTAINERS.md with roles, a one-week response promise, the label set, and the path to maintainership; and a Contributor Covenant 2.1 code of conduct. Rewrite CONTRIBUTING.md, which still described the project as mid-way through "TODO-7", to cover PR scope rules, the AI-assisted contribution policy, the current source layout, and the review flow. Add Dependabot (weekly for the Claude SDK and Telegram library, monthly grouped otherwise) and restore a Claude Code Review workflow as a read-only first-pass reviewer that also covers fork PRs. Link the new files from the README, docs index and changelog. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019LaezV767Pguhpat9zVyEs * fix: point project URLs at the RichardAtCT repository The Homepage, Repository and Documentation entries in pyproject.toml referenced github.com/richardatkinson/claude-code-telegram, a handle that is not the project's. These URLs surface in `pip show` and would become the links on a PyPI listing. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019LaezV767Pguhpat9zVyEs * docs: rebase v2 roadmap on the 1.6.2 baseline Drop the out-of-scope rows for PRs merged in 1.6.2 (#214, #212, #196, #177, #178, #206), note #220, point the AskUserQuestion and ExitPlanMode items at the GUARDED_TOOLS set that 1.6.2 introduced, and remove the docs/tools.md item that 1.6.2 already fixed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019LaezV767Pguhpat9zVyEs --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #175.
The
AsyncIOSchedulerinJobScheduler.__init__is created without explicitjob_defaults, meaning APScheduler uses its defaultmisfire_grace_time=1second. This is too strict for a bot where Claude command execution routinely takes minutes — any job that can't start within 1 second of its scheduled time is silently skipped.Changes:
misfire_grace_time=None— guarantees every job fires exactly once, regardless of how latecoalesce=True— merges multiple missed runs into a single execution, preventing duplicate firingThe worst case with this configuration is one late run, never a skipped one.
Tests
2 new tests in
tests/unit/test_scheduler/test_misfire_config.py:test_misfire_grace_time_is_none— verifies the config valuetest_coalesce_is_enabled— verifies coalesce is onAll existing tests continue to pass.