Skip to content

feat: generic scheduling and reposition OpenClaw cron as optional#41

Merged
WellDunDun merged 5 commits intodevfrom
WellDunDun/generic-scheduling
Mar 12, 2026
Merged

feat: generic scheduling and reposition OpenClaw cron as optional#41
WellDunDun merged 5 commits intodevfrom
WellDunDun/generic-scheduling

Conversation

@WellDunDun
Copy link
Collaborator

Summary

Make selftune's automation story generic and agent-agnostic. The primary path is now selftune schedule, which generates ready-to-use snippets for system cron, macOS launchd, and Linux systemd timers. selftune cron is repositioned as an optional OpenClaw integration rather than the main automation path.

Changes

  • New selftune schedule command: Generates scheduling snippets for cron, launchd, and systemd with --format filtering
  • CLI routing: Added schedule command to index.ts with proper help text
  • Documentation: Added Automation section to integration guide with generic scheduling as primary, OpenClaw as optional
  • Workflow docs: Created Workflows/Schedule.md for the new command; updated Cron.md to clearly mark it as OpenClaw-specific
  • Help text updates: Repositioned cron as "OpenClaw cron integration" throughout the codebase
  • Tests: 16 comprehensive tests for schedule command covering all formats and error handling

The core automation loop (sync → status → evolve --sync-first → watch --sync-first) is now runnable on any machine with standard system tools.

…optional

The primary automation story is now agent-agnostic. `selftune schedule`
generates ready-to-use snippets for system cron, macOS launchd, and Linux
systemd timers. `selftune cron` is repositioned as an optional OpenClaw
integration rather than the main automation path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Mar 12, 2026

Warning

Rate limit exceeded

@WellDunDun has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 1 minutes and 36 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: d9f91012-4ec1-4b5d-b84b-d86892dc9289

📥 Commits

Reviewing files that changed from the base of the PR and between 6770c47 and d59a483.

📒 Files selected for processing (2)
  • cli/selftune/schedule.ts
  • tests/schedule/schedule.test.ts
📝 Walkthrough

Walkthrough

Adds a new selftune schedule CLI command that generates platform-specific scheduling snippets (cron, launchd, systemd), registers the command in the CLI router, updates the OpenClaw-related cron help text, adds docs describing the unattended automation loop and platform setup, and includes unit tests for generation and format handling.

Changes

Cohort / File(s) Summary
Schedule Command
cli/selftune/schedule.ts
New Bun/TypeScript CLI implementing ScheduleEntry and SCHEDULE_ENTRIES; generators generateCrontab(), generateLaunchd(), generateSystemd(); formatOutput() and cliMain() with --format/-f parsing.
CLI Router
cli/selftune/index.ts
Added schedule top-level subcommand with dynamic import (./schedule.js) and help listing update.
Cron Setup Help
cli/selftune/cron/setup.ts
Reworded header/help to "OpenClaw cron integration" and added a multi-line note advising generic scheduling alternatives.
Documentation
docs/integration-guide.md, skill/Workflows/Cron.md, skill/Workflows/Schedule.md
Reorganized Integration Guide: added Automation section, platform-specific scheduling examples (cron, launchd, systemd), OpenClaw integration notes; updated Cron.md and added Schedule.md describing the automation loop and scheduling formats.
Tests
tests/schedule/schedule.test.ts
New tests validating SCHEDULE_ENTRIES contents, crontab/launchd/systemd output structure and unit names, formatOutput() variants and error handling.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title follows the conventional commits format with 'feat:' prefix and accurately describes the main changes: introducing generic scheduling and repositioning OpenClaw cron as optional.
Description check ✅ Passed The description is well-related to the changeset, clearly explaining the motivation, changes made, and technical implementation across command routing, documentation, and tests.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch WellDunDun/generic-scheduling
📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@cli/selftune/schedule.ts`:
- Around line 27-52: SCHEDULE_ENTRIES duplicates the same job set already
defined as DEFAULT_CRON_JOBS in cron/setup.ts; to fix, remove the hard-coded
SCHEDULE_ENTRIES array and instead import the single source of truth
(DEFAULT_CRON_JOBS) and map/transform it into any format-specific shape required
by the schedule command (e.g., add CLI-only fields like command or render
descriptions) so both cron/setup and schedule.ts use the same underlying job
metadata; update any references to SCHEDULE_ENTRIES to use the imported
DEFAULT_CRON_JOBS (or a small adapter function) and ensure
descriptions/semantics are preserved by deriving them from that single constant.
- Around line 152-175: The file is failing the repo formatter (Biome) around the
formatOutput function; run the project's formatter or reformat this function to
match project style (e.g., consistent quotes, spacing, and blank-line rules) and
re-commit the formatted result. Specifically ensure the formatOutput
implementation (references: formatOutput, isValidFormat, VALID_FORMATS,
sections, generateCrontab, generateLaunchd, generateSystemd) is formatted by the
repo's formatter so CI no longer rejects the file.
- Around line 74-107: The current generateLaunchd output only installs a single
"sync" job; update the generator to either (A) produce one launchd plist per
scheduled task by iterating SCHEDULE_ENTRIES and emitting a plist with the
proper Label and ProgramArguments for each entry (use the SCHEDULE_ENTRIES
symbol and generateLaunchd as the location to change), or (B) make the output
and docs explicitly say "sync-only example" by renaming labels/strings and
comments in generateLaunchd; apply the same change to the systemd generator (the
corresponding function that emits unit files referenced around lines 109-139) so
systemd and launchd behave consistently. Ensure each generated plist/unit uses
the entry's command/name for Label and ProgramArguments and maps timing to
StartInterval (or the unit's timer) accordingly.

In `@docs/integration-guide.md`:
- Around line 393-395: The fenced code block containing the sequence "sync →
status → evolve --sync-first → watch --sync-first" needs a language tag to
satisfy markdownlint; edit the opening fence from ``` to ```text so the block is
labeled as plain text (i.e., change the fence that contains "sync → status →
evolve --sync-first → watch --sync-first" to start with ```text).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 60b7692e-5d02-4c18-8793-0a144eb271a4

📥 Commits

Reviewing files that changed from the base of the PR and between 9ea8a5c and c4ba9d0.

📒 Files selected for processing (7)
  • cli/selftune/cron/setup.ts
  • cli/selftune/index.ts
  • cli/selftune/schedule.ts
  • docs/integration-guide.md
  • skill/Workflows/Cron.md
  • skill/Workflows/Schedule.md
  • tests/schedule/schedule.test.ts

WellDunDun and others added 2 commits March 12, 2026 19:32
…tors and formatting

Derive SCHEDULE_ENTRIES from DEFAULT_CRON_JOBS (single source of truth),
generate launchd/systemd configs for all 4 entries instead of sync-only,
fix biome formatting, and add markdown language tag.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@cli/selftune/schedule.ts`:
- Around line 106-147: The launchd generator currently drops chained commands by
taking only the last segment (in generateLaunchd) — change the ProgramArguments
creation to detect if entry.command contains shell operators like && (and
similarly update the systemd generator around the code that builds ExecStart)
and, when present, emit a shell wrapper (e.g., ProgramArguments:
["/bin/sh","-c","<full command>"] for generateLaunchd and ExecStart=/bin/sh -c
"<full command>" for systemd) instead of splitting by spaces and using .pop();
alternatively, if you intend to rely on a separate sync job, add a clear comment
in the generated plist output stating the dependency on the separate sync
schedule.
- Around line 56-84: cronToInterval currently returns a numeric StartInterval
for all cron patterns, which silently misrepresents fixed-time schedules; modify
cronToInterval to detect fixed-calendar crons (e.g. "0 8 * * *", "0 3 * * 0",
any expression with specific minute/hour/day fields) and return null (change
signature to number | null) to signal "not representable as StartInterval", and
adjust callers to use a launchd StartCalendarInterval instead when
cronToInterval returns null; also improve cronToOnCalendar mappings in
cronToOnCalendar for those fixed patterns (use full timestamp syntax like "*-*-*
08:00:00" and include weekday for weekly crons) so systemd OnCalendar and the
launchd StartCalendarInterval can be generated correctly rather than
approximating with an interval.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 460503e0-01e4-43bb-895c-d4292b22f724

📥 Commits

Reviewing files that changed from the base of the PR and between c4ba9d0 and 6770c47.

📒 Files selected for processing (4)
  • cli/selftune/index.ts
  • cli/selftune/schedule.ts
  • docs/integration-guide.md
  • tests/schedule/schedule.test.ts

WellDunDun and others added 2 commits March 12, 2026 20:15
…ers for chained commands

- launchd: use StartCalendarInterval (Hour/Minute/Weekday) for fixed-time
  schedules instead of approximating with StartInterval
- launchd/systemd: use /bin/sh -c wrapper for commands with && chains
  so prerequisite steps (like sync) are not silently dropped

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@WellDunDun WellDunDun merged commit 7d6c454 into dev Mar 12, 2026
5 checks passed
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.

1 participant