[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M71RSBAQB2KSBD7BPDX4YSD8":3,"skill-same:01M71RSBAQB2KSBD7BPDX4YSD8":56},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":29,"linkOnly":30,"markdownContent":31,"markdownBody":32,"frontMatter":33,"refName":34,"commitSha":35,"skillDirectory":36,"forksCount":37,"repositoryHtmlUrl":38,"repositoryHomepageUrl":39,"ownerHtmlUrl":40,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":41,"install":42,"resources":55},"01M71RSBAQB2KSBD7BPDX4YSD8","Scheduler",null,"Cron-style job scheduler. Add, remove, list, and run jobs against a JSON-backed registry.","gongiskhan\u002Fagent-garrison","gongiskhan","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F1997392?v=4","01M71RKMFR53TKXE308C22QTNZ","01M71RKMJA57KZHNDCBNKTWZRR",1,"MIT","https:\u002F\u002Fgithub.com\u002Fgongiskhan\u002Fagent-garrison\u002Fblob\u002Fmain\u002Ffittings\u002Fseed\u002Fscheduler\u002F.apm\u002Fskills\u002Fscheduler\u002FSKILL.md",[],[18,19,20,21,22,23,24,25,26,27,28],"scheduler","run","registry","cron","json","list","remove","jobs","style","job scheduler","add","2026-11-10 13:02:02",false,"---\nname: Scheduler\ndescription: Cron-style job scheduler. Add, remove, list, and run jobs against a JSON-backed registry.\n---\n\n# Scheduler\n\nTime-anchored work — calendar sync, reminders, end-of-day rollups.\nFor loop-style \"every N minutes\" polling with no calendar\ncomponent, use the **Heartbeat** Faculty instead.\n\n## Setup\n\nResolved by the runner from Fitting config:\n\n```\nGARRISON_SCHEDULER_JOBS=...   # default: data\u002Fscheduler-jobs.json\nGARRISON_SCHEDULER_LOG=...    # default: data\u002Fscheduler.log\n```\n\nBoth paths are relative to the composition directory.\n\n## CLI\n\nThe `scheduler.mjs` CLI runs from the Fitting's installed\ndirectory (`apm_modules\u002F_local\u002Fscheduler\u002F`).\n\n```bash\nnode scripts\u002Fscheduler.mjs --probe                    # health check\nnode scripts\u002Fscheduler.mjs list                       # JSON list of jobs\nnode scripts\u002Fscheduler.mjs add \u003Cid> \u003Ccron> \u003Ccommand>  # add or replace\nnode scripts\u002Fscheduler.mjs remove \u003Cid>                # remove a job\nnode scripts\u002Fscheduler.mjs run-now \u003Cid>               # run once now\nnode scripts\u002Fscheduler.mjs tick                       # process current-minute due jobs\nnode scripts\u002Fscheduler.mjs daemon                     # tick every minute until killed\n```\n\n## Cron grammar\n\n5 fields: `minute hour day-of-month month day-of-week`. Supported:\n\n- `*` — any value\n- `*\u002FN` — every N units (modulo arithmetic from field min)\n- `M` — single value\n- `M,N,...` — comma-separated list\n- `A-B` — inclusive range\n\nNo `@yearly`\u002F`@daily` aliases, no seconds, no named months\u002Fdays.\nThat covers Phase 2's intended patterns:\n\n- `*\u002F5 * * * *` — every 5 minutes (calendar sync)\n- `0 8 * * 1-5` — 8am weekdays (morning briefing)\n- `0 18 * * *` — 6pm daily (end-of-day rollup)\n\n## Tick semantics\n\nA tick runs at most once per minute per job. Each job records\n`last_run_minute` (e.g. `2026-5-7T8:0`) so a second tick within\nthe same minute is a no-op for that job. Cron matching is against\nthe local time of the tick, not UTC.\n\n## Operating principles\n\n- **Time-anchored vs loop-driven.** Use Scheduler for \"at H:M\n  every weekday.\" Use Heartbeat for \"every 40 minutes,\n  regardless of clock.\" A heartbeat tick can call\n  `scheduler.mjs tick` to drive due jobs as a side effect.\n- **Job idempotency is the consumer's responsibility.** The\n  scheduler doesn't dedupe across daemon restarts; if a job\n  must not fire twice, the job's command must check its own\n  state.\n- **Log file grows unbounded.** Rotate it externally if\n  retention matters. v1 doesn't ship rotation.\n\n## Persistence\n\n`jobs.json` is a flat array of objects:\n\n```json\n[\n  {\n    \"id\": \"morning-briefing\",\n    \"cron\": \"0 8 * * 1-5\",\n    \"command\": \"curl -X POST http:\u002F\u002F127.0.0.1:24777\u002Fjobs -d ...\",\n    \"enabled\": true,\n    \"last_run\": \"2026-05-07T07:00:00.000Z\",\n    \"last_run_minute\": \"2026-5-7T8:0\"\n  }\n]\n```\n\nSurvives Garrison restart — the scheduler reads jobs.json on\nevery tick. `last_run_minute` is written before the job is\nspawned, so a crash mid-run doesn't double-fire on restart.\n\n## Cookbook: morning briefing\n\nThe daily morning briefing now ships as its own Fitting —\n`fittings\u002Fseed\u002Fmorning-briefing\u002F`. Add it to your composition's\n`selections.automations` block and `garrison up` registers the\nscheduler job for you. See that Fitting's `instructions.md` for\nconfiguration knobs (`briefing_time`, `weekdays_only`,\n`GARRISON_BRIEFING_TIME` \u002F `GARRISON_BRIEFING_WEEKDAYS_ONLY` env\noverrides).\n\nIf you want a different scheduled-prompt recipe (e.g. an end-of-day\nrollup), follow the morning-briefing Fitting's setup.sh as a\ntemplate — POST `{kind, instructions}` to\n`http:\u002F\u002F$GARRISON_GATEWAY_HOST:$GARRISON_GATEWAY_PORT\u002Fjobs` and the\ngateway will dispatch it to the session as a synthetic prompt.\n\n## How the daemon mode is wired\n\nIn Phase 2, the runner does not auto-spawn the scheduler daemon.\nThree integration paths the consumer can pick from:\n\n1. **Manual:** `node apm_modules\u002F_local\u002Fscheduler\u002Fscripts\u002Fscheduler.mjs daemon`\n   in a tmux pane or under `launchctl asuser`.\n2. **Heartbeat-driven:** Phase 2's heartbeat (T4) can run\n   `tick` once per heartbeat as part of its periodic work.\n   Coarser cadence (40 min vs 1 min) but no separate process.\n3. **Host cron:** `* * * * * cd \u003Ccomposition> && node apm_modules\u002F_local\u002Fscheduler\u002Fscripts\u002Fscheduler.mjs tick`\n   in `crontab`.\n\nA future runtime-SDK milestone may add an explicit\n`x-garrison.daemon` declaration so the runner spawns the\nscheduler daemon at Up time.\n","# Scheduler\n\nTime-anchored work — calendar sync, reminders, end-of-day rollups.\nFor loop-style \"every N minutes\" polling with no calendar\ncomponent, use the **Heartbeat** Faculty instead.\n\n## Setup\n\nResolved by the runner from Fitting config:\n\n```\nGARRISON_SCHEDULER_JOBS=...   # default: data\u002Fscheduler-jobs.json\nGARRISON_SCHEDULER_LOG=...    # default: data\u002Fscheduler.log\n```\n\nBoth paths are relative to the composition directory.\n\n## CLI\n\nThe `scheduler.mjs` CLI runs from the Fitting's installed\ndirectory (`apm_modules\u002F_local\u002Fscheduler\u002F`).\n\n```bash\nnode scripts\u002Fscheduler.mjs --probe                    # health check\nnode scripts\u002Fscheduler.mjs list                       # JSON list of jobs\nnode scripts\u002Fscheduler.mjs add \u003Cid> \u003Ccron> \u003Ccommand>  # add or replace\nnode scripts\u002Fscheduler.mjs remove \u003Cid>                # remove a job\nnode scripts\u002Fscheduler.mjs run-now \u003Cid>               # run once now\nnode scripts\u002Fscheduler.mjs tick                       # process current-minute due jobs\nnode scripts\u002Fscheduler.mjs daemon                     # tick every minute until killed\n```\n\n## Cron grammar\n\n5 fields: `minute hour day-of-month month day-of-week`. Supported:\n\n- `*` — any value\n- `*\u002FN` — every N units (modulo arithmetic from field min)\n- `M` — single value\n- `M,N,...` — comma-separated list\n- `A-B` — inclusive range\n\nNo `@yearly`\u002F`@daily` aliases, no seconds, no named months\u002Fdays.\nThat covers Phase 2's intended patterns:\n\n- `*\u002F5 * * * *` — every 5 minutes (calendar sync)\n- `0 8 * * 1-5` — 8am weekdays (morning briefing)\n- `0 18 * * *` — 6pm daily (end-of-day rollup)\n\n## Tick semantics\n\nA tick runs at most once per minute per job. Each job records\n`last_run_minute` (e.g. `2026-5-7T8:0`) so a second tick within\nthe same minute is a no-op for that job. Cron matching is against\nthe local time of the tick, not UTC.\n\n## Operating principles\n\n- **Time-anchored vs loop-driven.** Use Scheduler for \"at H:M\n  every weekday.\" Use Heartbeat for \"every 40 minutes,\n  regardless of clock.\" A heartbeat tick can call\n  `scheduler.mjs tick` to drive due jobs as a side effect.\n- **Job idempotency is the consumer's responsibility.** The\n  scheduler doesn't dedupe across daemon restarts; if a job\n  must not fire twice, the job's command must check its own\n  state.\n- **Log file grows unbounded.** Rotate it externally if\n  retention matters. v1 doesn't ship rotation.\n\n## Persistence\n\n`jobs.json` is a flat array of objects:\n\n```json\n[\n  {\n    \"id\": \"morning-briefing\",\n    \"cron\": \"0 8 * * 1-5\",\n    \"command\": \"curl -X POST http:\u002F\u002F127.0.0.1:24777\u002Fjobs -d ...\",\n    \"enabled\": true,\n    \"last_run\": \"2026-05-07T07:00:00.000Z\",\n    \"last_run_minute\": \"2026-5-7T8:0\"\n  }\n]\n```\n\nSurvives Garrison restart — the scheduler reads jobs.json on\nevery tick. `last_run_minute` is written before the job is\nspawned, so a crash mid-run doesn't double-fire on restart.\n\n## Cookbook: morning briefing\n\nThe daily morning briefing now ships as its own Fitting —\n`fittings\u002Fseed\u002Fmorning-briefing\u002F`. Add it to your composition's\n`selections.automations` block and `garrison up` registers the\nscheduler job for you. See that Fitting's `instructions.md` for\nconfiguration knobs (`briefing_time`, `weekdays_only`,\n`GARRISON_BRIEFING_TIME` \u002F `GARRISON_BRIEFING_WEEKDAYS_ONLY` env\noverrides).\n\nIf you want a different scheduled-prompt recipe (e.g. an end-of-day\nrollup), follow the morning-briefing Fitting's setup.sh as a\ntemplate — POST `{kind, instructions}` to\n`http:\u002F\u002F$GARRISON_GATEWAY_HOST:$GARRISON_GATEWAY_PORT\u002Fjobs` and the\ngateway will dispatch it to the session as a synthetic prompt.\n\n## How the daemon mode is wired\n\nIn Phase 2, the runner does not auto-spawn the scheduler daemon.\nThree integration paths the consumer can pick from:\n\n1. **Manual:** `node apm_modules\u002F_local\u002Fscheduler\u002Fscripts\u002Fscheduler.mjs daemon`\n   in a tmux pane or under `launchctl asuser`.\n2. **Heartbeat-driven:** Phase 2's heartbeat (T4) can run\n   `tick` once per heartbeat as part of its periodic work.\n   Coarser cadence (40 min vs 1 min) but no separate process.\n3. **Host cron:** `* * * * * cd \u003Ccomposition> && node apm_modules\u002F_local\u002Fscheduler\u002Fscripts\u002Fscheduler.mjs tick`\n   in `crontab`.\n\nA future runtime-SDK milestone may add an explicit\n`x-garrison.daemon` declaration so the runner spawns the\nscheduler daemon at Up time.\n",{"name":5,"description":7},"main","31458d7e0e08a7b3494c27bf2b912ed41c87a138","fittings\u002Fseed\u002Fscheduler\u002F.apm\u002Fskills\u002Fscheduler",0,"https:\u002F\u002Fgithub.com\u002Fgongiskhan\u002Fagent-garrison","https:\u002F\u002Fgongiskhan.github.io\u002Fagent-garrison\u002F","https:\u002F\u002Fgithub.com\u002Fgongiskhan","2026-11-07 05:27:23",{"source":8,"skillName":5,"commands":43,"prompt":53,"zipAvailable":54},[44,47,50],{"tool":45,"command":46},"npx","npx skills add gongiskhan\u002Fagent-garrison --skill Scheduler",{"tool":48,"command":49},"bunx","bunx skills add gongiskhan\u002Fagent-garrison --skill Scheduler",{"tool":51,"command":52},"pnpm","pnpm dlx skills add gongiskhan\u002Fagent-garrison --skill Scheduler","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fgongiskhan\u002Fagent-garrison\u002Fblob\u002Fmain\u002Ffittings\u002Fseed\u002Fscheduler\u002F.apm\u002Fskills\u002Fscheduler\u002FSKILL.md",true,[],[57,69,79,90,102,133],{"skillNo":58,"name":59,"nameZh":6,"description":60,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":61,"categories":62,"keywords":63,"publishedAt":29},"01M71RTFA0HD83YBE1TE7DCE6B","pinned-helper","An owned skill the human has pinned so the Improver must not touch it.","https:\u002F\u002Fgithub.com\u002Fgongiskhan\u002Fagent-garrison\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fimprover\u002Fskills\u002Fpinned-helper\u002FSKILL.md",[],[64,65,66,67,68],"pinned helper","helper","human","touch","it",{"skillNo":70,"name":71,"nameZh":6,"description":72,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":73,"categories":74,"keywords":75,"publishedAt":29},"01M71RTDKBG0WQHPHKFZKFWDHF","legacy-helper","A rarely used helper kept around from an earlier workflow.","https:\u002F\u002Fgithub.com\u002Fgongiskhan\u002Fagent-garrison\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fimprover\u002Fskills\u002Flegacy-helper\u002FSKILL.md",[],[76,65,77,78],"Legacy","legacy helper","workflow",{"skillNo":80,"name":81,"nameZh":6,"description":82,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":83,"categories":84,"keywords":85,"publishedAt":29},"01M71RTCC6ZVVJ9MHHESXPHWA6","human-notes","A human-authored skill not deployed by APM (loose, not in the lock).","https:\u002F\u002Fgithub.com\u002Fgongiskhan\u002Fagent-garrison\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fimprover\u002Fskills\u002Fhuman-notes\u002FSKILL.md",[],[86,66,87,88,89],"notes","human notes","lock","apm",{"skillNo":91,"name":92,"nameZh":6,"description":93,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":94,"categories":95,"keywords":96,"publishedAt":29},"01M71RTB83ZP6VK6XH19Z93FAC","garrison-helper","Helps compose and station Garrison Fittings into Faculty role slots.","https:\u002F\u002Fgithub.com\u002Fgongiskhan\u002Fagent-garrison\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fimprover\u002Fskills\u002Fgarrison-helper\u002FSKILL.md",[],[65,97,98,99,100,101],"garrison","garrison helper","slots","role","compose",{"skillNo":103,"name":104,"nameZh":6,"description":105,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":106,"categories":107,"keywords":113,"publishedAt":29},"01M71RT6MBGJC4QQZBGHF4H1M8","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\u002Ffix\u002Ffeature on a web project (Next.js\u002FReact 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\u002Froute\u002Fform\u002FAPI change worth demonstrating. Not for walking through a full from-scratch project build.","https:\u002F\u002Fgithub.com\u002Fgongiskhan\u002Fagent-garrison\u002Fblob\u002Fmain\u002Ffittings\u002Fseed\u002Fwalkthrough\u002F.apm\u002Fskills\u002Fwalkthrough\u002FSKILL.md",[108],{"categoryNo":109,"categoryName":110,"taxonomyType":111,"taxonomyTypeDesc":112},"01JBSEEDCAT000000000000016","图像与多媒体","SCENARIO","使用场景",[104,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132],"when","project","project build","api","react","change","demo video","publish","recording","Video","show me","work","short","fix","show","route","me","next","self",{"skillNo":134,"name":135,"nameZh":6,"description":136,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":137,"categories":138,"keywords":139,"publishedAt":29},"01M71RT54T0SQS42XEP5FVQ28K","Trello","Manage tasks via Trello REST API.","https:\u002F\u002Fgithub.com\u002Fgongiskhan\u002Fagent-garrison\u002Fblob\u002Fmain\u002Ffittings\u002Fseed\u002Ftrello\u002F.apm\u002Fskills\u002Ftrello\u002FSKILL.md",[],[140,141,142,117,143,144,145],"trello","tasks","REST","manage","rest api","via"]