Scheduler
Cron-style job scheduler. Add, remove, list, and run jobs against a JSON-backed registry.
- License 许可
- MIT
- 最近更新
- 2026-11-07
- Stars
- ★ 1
- Forks
- 0
01 前言 Front Matter
- name
- Scheduler
- description
- Cron-style job scheduler. Add, remove, list, and run jobs against a JSON-backed registry.
03 SKILL.md 正文
Scheduler
Time-anchored work — calendar sync, reminders, end-of-day rollups. For loop-style "every N minutes" polling with no calendar component, use the Heartbeat Faculty instead.
Setup
Resolved by the runner from Fitting config:
GARRISON_SCHEDULER_JOBS=... # default: data/scheduler-jobs.json
GARRISON_SCHEDULER_LOG=... # default: data/scheduler.log
Both paths are relative to the composition directory.
CLI
The scheduler.mjs CLI runs from the Fitting's installed
directory (apm_modules/_local/scheduler/).
node scripts/scheduler.mjs --probe # health check
node scripts/scheduler.mjs list # JSON list of jobs
node scripts/scheduler.mjs add <id> <cron> <command> # add or replace
node scripts/scheduler.mjs remove <id> # remove a job
node scripts/scheduler.mjs run-now <id> # run once now
node scripts/scheduler.mjs tick # process current-minute due jobs
node scripts/scheduler.mjs daemon # tick every minute until killed
Cron grammar
5 fields: minute hour day-of-month month day-of-week. Supported:
*— any value*/N— every N units (modulo arithmetic from field min)M— single valueM,N,...— comma-separated listA-B— inclusive range
No @yearly/@daily aliases, no seconds, no named months/days.
That covers Phase 2's intended patterns:
*/5 * * * *— every 5 minutes (calendar sync)0 8 * * 1-5— 8am weekdays (morning briefing)0 18 * * *— 6pm daily (end-of-day rollup)
Tick semantics
A tick runs at most once per minute per job. Each job records
last_run_minute (e.g. 2026-5-7T8:0) so a second tick within
the same minute is a no-op for that job. Cron matching is against
the local time of the tick, not UTC.
Operating principles
- Time-anchored vs loop-driven. Use Scheduler for "at H:M
every weekday." Use Heartbeat for "every 40 minutes,
regardless of clock." A heartbeat tick can call
scheduler.mjs tickto drive due jobs as a side effect. - Job idempotency is the consumer's responsibility. The scheduler doesn't dedupe across daemon restarts; if a job must not fire twice, the job's command must check its own state.
- Log file grows unbounded. Rotate it externally if retention matters. v1 doesn't ship rotation.
Persistence
jobs.json is a flat array of objects:
[
{
"id": "morning-briefing",
"cron": "0 8 * * 1-5",
"command": "curl -X POST http://127.0.0.1:24777/jobs -d ...",
"enabled": true,
"last_run": "2026-05-07T07:00:00.000Z",
"last_run_minute": "2026-5-7T8:0"
}
]
Survives Garrison restart — the scheduler reads jobs.json on
every tick. last_run_minute is written before the job is
spawned, so a crash mid-run doesn't double-fire on restart.
Cookbook: morning briefing
The daily morning briefing now ships as its own Fitting —
fittings/seed/morning-briefing/. Add it to your composition's
selections.automations block and garrison up registers the
scheduler job for you. See that Fitting's instructions.md for
configuration knobs (briefing_time, weekdays_only,
GARRISON_BRIEFING_TIME / GARRISON_BRIEFING_WEEKDAYS_ONLY env
overrides).
If you want a different scheduled-prompt recipe (e.g. an end-of-day
rollup), follow the morning-briefing Fitting's setup.sh as a
template — POST {kind, instructions} to
http://$GARRISON_GATEWAY_HOST:$GARRISON_GATEWAY_PORT/jobs and the
gateway will dispatch it to the session as a synthetic prompt.
How the daemon mode is wired
In Phase 2, the runner does not auto-spawn the scheduler daemon. Three integration paths the consumer can pick from:
- Manual:
node apm_modules/_local/scheduler/scripts/scheduler.mjs daemonin a tmux pane or underlaunchctl asuser. - Heartbeat-driven: Phase 2's heartbeat (T4) can run
tickonce per heartbeat as part of its periodic work. Coarser cadence (40 min vs 1 min) but no separate process. - Host cron:
* * * * * cd <composition> && node apm_modules/_local/scheduler/scripts/scheduler.mjs tickincrontab.
A future runtime-SDK milestone may add an explicit
x-garrison.daemon declaration so the runner spawns the
scheduler daemon at Up time.
04 同仓库更多 Skills
pinned-helper
An owned skill the human has pinned so the Improver must not touch it.
legacy-helper
A rarely used helper kept around from an earlier workflow.
human-notes
A human-authored skill not deployed by APM (loose, not in the lock).
garrison-helper
Helps compose and station Garrison Fittings into Faculty role slots.
walkthrough
Record a short, narrated, captioned video walkthrough that proves a finished coding task and shows how it behaves, then self-verify the video via vision on extracted frames and publish it as one scrubbable Tailscale link. Use after completing a change/fix/feature on a web project (Next.js/React etc.) when the user wants visual proof of work, a demo of a user flow, or to avoid manually retesting and watching a long raw screen recording. Triggers on requests like "record a walkthrough", "show me it working", "make a demo video of this", "prove the feature", or finishing a UI/route/form/API change worth demonstrating. Not for walking through a full from-scratch project build.
Trello
Manage tasks via Trello REST API.