Skip to content

v0.6.4: Auth-aware cron rule files, DRY refactor, improved stop flow

Choose a tag to compare

@PleasePrompto PleasePrompto released this 26 Feb 16:39
· 319 commits to main since this release

ductor v0.6.4

Cross-platform process management overhaul, expanded auth detection, auth-aware cron task rule files, and DRY refactoring.

Cross-platform process tree management

New infra/process_tree.py module with unified terminate/force-kill helpers for POSIX and Windows.

  • Graceful signal handling: SIGTERM/SIGINT now triggers CancelledError for clean shutdown instead of abrupt exit.
  • Robust rmtree: Windows-safe directory removal with read-only flag clearing and retry logic for locked files.
  • kill_all_ductor_processes(): Scans for stale ductor processes on Windows (including pythonw.exe from pipx venv). POSIX no-op for safety.
  • All process kill logic (executor, gemini_provider, process_registry, pidlock, cron/execution) now uses shared process_tree helpers.
  • Cron execution uses CREATE_NO_WINDOW flag on Windows to prevent console popups.

Expanded Claude auth detection

check_claude_auth() now checks three sources (previously only credentials file):

  1. ~/.claude/.credentials.json (OAuth login)
  2. ANTHROPIC_API_KEY environment variable
  3. claude auth status CLI fallback (covers managed keys, OAuth tokens)

Improved stop flow

  • ductor stop now stops the system service first (prevents Task Scheduler / systemd / launchd respawn), then kills PID-file instance + all remaining processes.
  • Always kills all system-wide ductor processes (consistent behavior).
  • Brief file-lock wait on Windows after kill.

Auth-aware cron task rule files

Cron task folders now create only the rule files matching authenticated providers instead of always writing CLAUDE.md + AGENTS.md and never GEMINI.md.

  • New tasks: create_cron_task() detects which providers are authenticated from the parent cron_tasks/ directory and creates only the relevant rule files.
  • Existing tasks: New ensure_task_rule_files() backfills missing rule files when a provider gets authenticated later (e.g. adds GEMINI.md to old tasks). Only adds, never removes.
  • Periodic sync: Runs at bot start and every 10 seconds via the rule file watcher.
  • cron_add.py: Now supports --provider gemini alongside claude and codex.

Cron result sanitization

  • Strips transport confirmation lines ("Message sent successfully") from cron results before broadcasting to Telegram.
  • Skips broadcast entirely when result contains only transport acks.

Background task cleanup

  • BackgroundObserver.cancel_all() and shutdown() now properly await cancelled tasks instead of fire-and-forget cancel.

DRY platform refactoring

  • New shared infra.platform.is_windows() replaces duplicate _is_windows() helpers.
  • Inlined trivial wrappers (_force_kill, _find_ductor_binary, kill_process_tree).
  • Extracted print_file_service_logs() and print_journal_service_logs() to service_logs.py.
  • Dead code removed: strip_file_tags, perform_upgrade, cmd_stop, _sanitize_markers.

Test safety

  • Global autouse fixture in tests/conftest.py mocks all process signal functions — prevents tests from sending real SIGTERM/SIGKILL to system PIDs.

Upgrade

ductor upgrade
# or
pip install --upgrade ductor