Skip to content

fix: set APScheduler misfire_grace_time=None for reliable job execution - #178

Merged
RichardAtCT merged 1 commit into
overwirehq:mainfrom
sakhnenkoff:patch/scheduler-resilience
Sep 11, 2026
Merged

RichardAtCT merged 1 commit into
overwirehq:mainfrom
sakhnenkoff:patch/scheduler-resilience

Conversation

@sakhnenkoff

Copy link
Copy Markdown

Summary

Fixes #175.

The AsyncIOScheduler in JobScheduler.__init__ is created without explicit job_defaults, meaning APScheduler uses its default misfire_grace_time=1 second. 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:

  • Set misfire_grace_time=None — guarantees every job fires exactly once, regardless of how late
  • Set coalesce=True — merges multiple missed runs into a single execution, preventing duplicate firing

The 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 value
  • test_coalesce_is_enabled — verifies coalesce is on

All existing tests continue to pass.

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.
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
RichardAtCT merged commit 206a8f8 into overwirehq:main Sep 11, 2026
RichardAtCT added a commit that referenced this pull request Sep 11, 2026
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

APScheduler default misfire_grace_time is too strict for long-running Claude commands

2 participants