@aitne-sh/aitne 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +195 -829
- package/agent-assets/agent-profiles/_safety.md +49 -17
- package/agent-assets/agent-profiles/profile-importer.md +1 -1
- package/agent-assets/agent-profiles/routine.md +4 -3
- package/agent-assets/docs/concepts/agent-day.md +6 -1
- package/agent-assets/docs/concepts/auth-health.md +10 -1
- package/agent-assets/docs/concepts/backends-and-tiers.md +74 -40
- package/agent-assets/docs/concepts/costs-and-quotas.md +25 -5
- package/agent-assets/docs/concepts/delegated-mode.md +147 -68
- package/agent-assets/docs/concepts/memory-model.md +9 -4
- package/agent-assets/docs/concepts/observations.md +13 -1
- package/agent-assets/docs/concepts/process-keys.md +20 -5
- package/agent-assets/docs/concepts/routines.md +38 -20
- package/agent-assets/docs/concepts/safety-model.md +30 -13
- package/agent-assets/docs/concepts/skills.md +12 -7
- package/agent-assets/docs/features/integrations/calendar.md +1 -1
- package/agent-assets/docs/features/integrations/git.md +2 -2
- package/agent-assets/docs/features/integrations/github.md +9 -2
- package/agent-assets/docs/features/integrations/mail.md +1 -1
- package/agent-assets/docs/features/integrations/notion.md +34 -6
- package/agent-assets/docs/features/integrations/obsidian.md +7 -2
- package/agent-assets/docs/features/lifestyle/git.md +4 -7
- package/agent-assets/docs/features/lifestyle/receipts.md +17 -2
- package/agent-assets/docs/features/lifestyle/travel-bookings.md +15 -0
- package/agent-assets/docs/features/lifestyle/travel-time.md +7 -1
- package/agent-assets/docs/features/memory-files/agent-journal.md +2 -2
- package/agent-assets/docs/features/memory-files/projects.md +6 -0
- package/agent-assets/docs/features/memory-files/roadmap.md +5 -0
- package/agent-assets/docs/features/memory-files/today.md +1 -0
- package/agent-assets/docs/features/memory-files/user-profile.md +6 -0
- package/agent-assets/docs/features/messaging/bang-commands.md +20 -10
- package/agent-assets/docs/features/messaging/discord.md +12 -1
- package/agent-assets/docs/features/messaging/overview.md +10 -7
- package/agent-assets/docs/features/messaging/slack.md +13 -1
- package/agent-assets/docs/features/messaging/telegram.md +7 -1
- package/agent-assets/docs/features/messaging/whatsapp.md +12 -1
- package/agent-assets/docs/features/operations/activity-and-conversations.md +2 -2
- package/agent-assets/docs/features/operations/approvals.md +6 -0
- package/agent-assets/docs/features/operations/backend-routing.md +7 -0
- package/agent-assets/docs/features/operations/cost-tracking.md +6 -0
- package/agent-assets/docs/features/operations/notifications.md +6 -0
- package/agent-assets/docs/features/operations/schedule-approaching.md +22 -9
- package/agent-assets/docs/features/routines/custom-routines.md +10 -4
- package/agent-assets/docs/features/routines/evening-review.md +1 -1
- package/agent-assets/docs/features/routines/hourly-check.md +1 -1
- package/agent-assets/docs/features/routines/morning-routine.md +24 -15
- package/agent-assets/docs/features/routines/weekly-review.md +38 -12
- package/agent-assets/docs/features/wiki/commands.md +11 -0
- package/agent-assets/docs/features/wiki/overview.md +13 -3
- package/agent-assets/docs/getting-started/01-what-is-this.md +32 -11
- package/agent-assets/docs/getting-started/02-first-steps.md +17 -4
- package/agent-assets/docs/getting-started/03-what-can-this-do.md +21 -11
- package/agent-assets/docs/getting-started/04-first-day.md +14 -0
- package/agent-assets/docs/glossary.md +65 -12
- package/agent-assets/docs/guides/add-a-custom-routine.md +12 -0
- package/agent-assets/docs/guides/backup-and-restore.md +16 -2
- package/agent-assets/docs/guides/budget-and-cost-for-wiki.md +6 -0
- package/agent-assets/docs/guides/build-your-wiki.md +14 -0
- package/agent-assets/docs/guides/change-which-model-handles-x.md +7 -0
- package/agent-assets/docs/guides/connect-a-new-mail-account.md +16 -0
- package/agent-assets/docs/guides/explore-with-trace-and-connect.md +6 -0
- package/agent-assets/docs/guides/import-knowledge-file.md +11 -0
- package/agent-assets/docs/guides/install-and-run.md +20 -4
- package/agent-assets/docs/guides/maintain-wiki-health.md +6 -0
- package/agent-assets/docs/guides/migrate-machines.md +13 -1
- package/agent-assets/docs/guides/multiple-wikis-for-multiple-domains.md +9 -0
- package/agent-assets/docs/guides/pause-the-agent.md +12 -4
- package/agent-assets/docs/guides/reinstall-cleanly.md +19 -4
- package/agent-assets/docs/guides/setup-wizard.md +20 -9
- package/agent-assets/docs/guides/switch-default-backend.md +10 -1
- package/agent-assets/docs/guides/use-an-existing-obsidian-vault.md +5 -0
- package/agent-assets/docs/reference/api.md +29 -1
- package/agent-assets/docs/reference/cli-commands.md +22 -3
- package/agent-assets/docs/reference/config.md +37 -5
- package/agent-assets/docs/reference/disallowed-tools.md +13 -0
- package/agent-assets/docs/reference/keyboard-shortcuts.md +13 -0
- package/agent-assets/docs/reference/process-keys.md +70 -20
- package/agent-assets/docs/reference/skills.md +27 -9
- package/agent-assets/docs/troubleshooting/auth-failed.md +7 -2
- package/agent-assets/docs/troubleshooting/dashboard-shows-degraded.md +13 -1
- package/agent-assets/docs/troubleshooting/fallback-keeps-firing.md +10 -0
- package/agent-assets/docs/troubleshooting/messaging-not-pairing.md +11 -0
- package/agent-assets/docs/troubleshooting/morning-routine-didnt-run.md +9 -4
- package/agent-assets/docs/troubleshooting/observation-not-detected.md +12 -0
- package/agent-assets/docs/troubleshooting/quota-exhausted.md +7 -1
- package/agent-assets/docs/troubleshooting/wiki-ingest-full-blocked.md +5 -0
- package/agent-assets/docs/troubleshooting/wiki-write-failed.md +5 -0
- package/agent-assets/optimizer-skills/drift-analysis/SKILL.md +1 -1
- package/agent-assets/optimizer-skills/skill-curation/SKILL.md +2 -2
- package/agent-assets/skills/agent-actions/SKILL.md +122 -0
- package/agent-assets/skills/attach/SKILL.md +1 -2
- package/agent-assets/skills/context/SKILL.md +36 -454
- package/agent-assets/skills/context/references/api.md +220 -0
- package/agent-assets/skills/context/references/required-frontmatter.md +73 -0
- package/agent-assets/skills/context/references/snapshot-files.md +103 -0
- package/agent-assets/skills/context/seeds/file-responsibilities.seed.json +1 -1
- package/agent-assets/skills/docs-search/SKILL.md +13 -13
- package/agent-assets/skills/external-services/SKILL.delegated.claude.md +5 -7
- package/agent-assets/skills/external-services/SKILL.delegated.codex.md +5 -7
- package/agent-assets/skills/external-services/SKILL.delegated.gemini.md +5 -7
- package/agent-assets/skills/external-services/SKILL.md +6 -259
- package/agent-assets/skills/external-services/SKILL.native.claude.md +1 -2
- package/agent-assets/skills/external-services/SKILL.native.codex.md +1 -2
- package/agent-assets/skills/external-services/SKILL.native.gemini.md +1 -2
- package/agent-assets/skills/external-services/references/calendar-apple.md +97 -0
- package/agent-assets/skills/external-services/references/calendar-google.md +72 -0
- package/agent-assets/skills/external-services/references/calendar-outlook.md +36 -0
- package/agent-assets/skills/external-services/references/github.md +17 -0
- package/agent-assets/skills/external-services/references/obsidian.md +49 -0
- package/agent-assets/skills/external-services/references/skills-crud.md +27 -0
- package/agent-assets/skills/gmail-lifestyle/SKILL.md +224 -0
- package/agent-assets/skills/gmail-lifestyle/references/receipts-api.md +93 -0
- package/agent-assets/skills/gmail-lifestyle/references/travel-bookings-api.md +75 -0
- package/agent-assets/skills/gmail-lifestyle/references/travel-time-api.md +59 -0
- package/agent-assets/skills/mail/SKILL.delegated.claude.md +1 -1
- package/agent-assets/skills/mail/SKILL.delegated.codex.md +1 -1
- package/agent-assets/skills/mail/SKILL.delegated.gemini.md +1 -1
- package/agent-assets/skills/mail/SKILL.md +9 -114
- package/agent-assets/skills/mail/SKILL.native.claude.md +1 -1
- package/agent-assets/skills/mail/SKILL.native.codex.md +1 -1
- package/agent-assets/skills/mail/SKILL.native.gemini.md +1 -1
- package/agent-assets/skills/mail/references/api.md +108 -0
- package/agent-assets/skills/mail/references/examples.md +70 -0
- package/agent-assets/skills/mail/references/providers.md +8 -8
- package/agent-assets/skills/managed-tasks/SKILL.md +472 -0
- package/agent-assets/skills/managed-tasks/references/errors.md +70 -0
- package/agent-assets/skills/managed-tasks/references/output-path.md +75 -0
- package/agent-assets/skills/managed-tasks/references/recurrence-rule.md +86 -0
- package/agent-assets/skills/management-policy/SKILL.md +33 -105
- package/agent-assets/skills/management-policy/references/policy-workflow.md +101 -0
- package/agent-assets/skills/notify/SKILL.md +6 -78
- package/agent-assets/skills/notify/references/priority.md +60 -0
- package/agent-assets/skills/notion/SKILL.delegated.claude.md +1 -1
- package/agent-assets/skills/notion/SKILL.delegated.codex.md +1 -1
- package/agent-assets/skills/notion/SKILL.delegated.gemini.md +1 -1
- package/agent-assets/skills/notion/SKILL.md +6 -10
- package/agent-assets/skills/notion/SKILL.native.claude.md +1 -2
- package/agent-assets/skills/notion/SKILL.native.codex.md +1 -2
- package/agent-assets/skills/notion/SKILL.native.gemini.md +1 -2
- package/agent-assets/skills/observations/SKILL.md +1 -6
- package/agent-assets/skills/project-doc/SKILL.md +1 -5
- package/agent-assets/skills/reading/SKILL.md +2 -2
- package/agent-assets/skills/roadmap/SKILL.md +37 -135
- package/agent-assets/skills/roadmap/references/api.md +100 -0
- package/agent-assets/skills/roadmap/references/cross-check.md +73 -0
- package/agent-assets/skills/roadmap/references/migration.md +56 -0
- package/agent-assets/skills/roadmap/references/preparation-timeline.md +2 -2
- package/agent-assets/skills/schedule/SKILL.md +52 -88
- package/agent-assets/skills/schedule/references/batch.md +93 -0
- package/agent-assets/skills/schedule/references/errors.md +214 -0
- package/agent-assets/skills/schedule/references/model-selection.md +96 -0
- package/agent-assets/skills/schedule/references/recurrence-rule.md +86 -0
- package/agent-assets/skills/schedule/references/recurring.md +185 -0
- package/agent-assets/skills/scheduled-managed-task/SKILL.md +13 -15
- package/agent-assets/skills/today/SKILL.md +27 -57
- package/agent-assets/skills/today/references/agent-plan-lifecycle.md +113 -0
- package/agent-assets/skills/user-interview/SKILL.md +12 -59
- package/agent-assets/skills/user-interview/references/op-briefing.md +51 -0
- package/agent-assets/skills/user-interview/references/op-morning.md +59 -0
- package/agent-assets/skills/user-interview/references/sweep-and-fallback.md +1 -1
- package/agent-assets/skills/user-profile/SKILL.md +43 -63
- package/agent-assets/skills/user-profile/references/character-preferences.md +83 -0
- package/agent-assets/skills/user-profile/seeds/topic-files.seed.json +28 -0
- package/agent-assets/skills/wiki/wiki-ask/SKILL.md +0 -1
- package/agent-assets/skills/wiki/wiki-compile/SKILL.md +0 -1
- package/agent-assets/skills/wiki/wiki-connect/SKILL.md +0 -1
- package/agent-assets/skills/wiki/wiki-graduate/SKILL.md +0 -1
- package/agent-assets/skills/wiki/wiki-ingest/SKILL.md +0 -1
- package/agent-assets/skills/wiki/wiki-lint/SKILL.md +0 -1
- package/agent-assets/skills/wiki/wiki-trace/SKILL.md +0 -1
- package/agent-assets/skills/wiki/wiki-vault-rules/SKILL.md +0 -1
- package/agent-assets/system-prompts/routine-fetch-window.md +68 -0
- package/agent-assets/system-prompts/skill-index-instruction.md +26 -0
- package/agent-assets/task-flows/_partials/calendar-acquire.google_calendar.md +18 -11
- package/agent-assets/task-flows/_partials/calendar-acquire.outlook_calendar.md +16 -9
- package/agent-assets/task-flows/_partials/capture-user-info.md +24 -0
- package/agent-assets/task-flows/_partials/confirm-subflow.md +68 -0
- package/agent-assets/task-flows/_partials/dm-intent.long-horizon.md +35 -0
- package/agent-assets/task-flows/_partials/dm-intent.project.md +391 -0
- package/agent-assets/task-flows/_partials/mail-acquire.gmail.md +20 -11
- package/agent-assets/task-flows/_partials/mail-acquire.outlook_mail.md +17 -9
- package/agent-assets/task-flows/_partials/notion-acquire.notion.md +18 -12
- package/agent-assets/task-flows/knowledge.import.md +1 -1
- package/agent-assets/task-flows/message.received.dm.md +13 -15
- package/agent-assets/task-flows/message.received.dm_first.md +10 -14
- package/agent-assets/task-flows/routine.custom.md +3 -1
- package/agent-assets/task-flows/routine.evening_review.md +39 -163
- package/agent-assets/task-flows/routine.fetch_window.md +17 -12
- package/agent-assets/task-flows/routine.hourly_check.md +16 -8
- package/agent-assets/task-flows/routine.hourly_check.triage.md +1 -1
- package/agent-assets/task-flows/routine.monthly_review.md +46 -4
- package/agent-assets/task-flows/routine.morning_routine_journal.md +113 -0
- package/agent-assets/task-flows/routine.morning_routine_today.md +673 -0
- package/agent-assets/task-flows/routine.roadmap_refresh.md +60 -15
- package/agent-assets/task-flows/routine.user_profile_sweep.md +9 -10
- package/agent-assets/task-flows/routine.weekly_review.md +285 -70
- package/agent-assets/task-flows/scheduled.dm.md +8 -8
- package/agent-assets/task-flows/scheduled.task.md +5 -5
- package/agent-assets/task-flows/setup.initial.md +165 -245
- package/agent-assets/task-flows/wiki.ingest_url.md +1 -1
- package/agent-assets/templates/_manifest.json +7 -7
- package/agent-assets/templates/dossiers/_index.md +1 -1
- package/agent-assets/templates/rules/journal-format.md +145 -38
- package/agent-assets/templates/user/expertise.md +4 -2
- package/agent-assets/templates/user/goals.md +4 -2
- package/agent-assets/templates/user/people.md +8 -2
- package/agent-assets/templates/user/personal.md +4 -2
- package/agent-assets/templates/user/work.md +4 -2
- package/bin/aitne.mjs +8 -1
- package/package.json +4 -4
- package/scripts/commands/doctor.mjs +52 -0
- package/scripts/commands/run-now.mjs +202 -0
- package/scripts/commands/verify.mjs +264 -0
- package/agent-assets/docs/features/routines/monthly-review.md +0 -65
- package/agent-assets/skills/management-task-modify/SKILL.md +0 -203
- package/agent-assets/skills/management-task-register/SKILL.md +0 -330
- package/agent-assets/skills/management-task-stop/SKILL.md +0 -166
- package/agent-assets/skills/receipts/SKILL.md +0 -134
- package/agent-assets/skills/travel/SKILL.md +0 -132
- package/agent-assets/skills/travel-time/SKILL.md +0 -158
- package/agent-assets/task-flows/routine.morning_routine.md +0 -322
- package/agent-assets/task-flows/routine.morning_routine_initial.md +0 -204
|
@@ -7,14 +7,14 @@ Action line formats:
|
|
|
7
7
|
|
|
8
8
|
```
|
|
9
9
|
- YYYY-MM-DD [tag]: description
|
|
10
|
-
-
|
|
10
|
+
- completed YYYY-MM-DD: YYYY-MM-DD [tag]: description
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
The completed prefix date is the completion date; the second date is
|
|
14
14
|
the original planned date. Preserve completed rows byte-for-byte across
|
|
15
15
|
refreshes. Morning Routine marks an open row complete by rewriting:
|
|
16
16
|
`- YYYY-MM-DD [tag]: foo` →
|
|
17
|
-
`-
|
|
17
|
+
`- completed <today>: YYYY-MM-DD [tag]: foo`.
|
|
18
18
|
|
|
19
19
|
Tags: `[notify]`, `[today]`, `[check]`, `[schedule]`.
|
|
20
20
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: schedule
|
|
3
3
|
description: Load when scheduling a future agent wake-up, pre-composed DM, recurring task, or de-duping against existing pending schedules.
|
|
4
|
-
when_to_use: Owns `/api/schedule`, `/api/schedule/dm`, and `/api/recurring-schedules`. `external-services` defers here for all time-based work.
|
|
5
4
|
allowed-tools:
|
|
6
5
|
- Bash(curl *)
|
|
7
6
|
- Read
|
|
@@ -37,45 +36,12 @@ user but compound into duplicate DMs/notifications at fire time.
|
|
|
37
36
|
regenerate on its own.
|
|
38
37
|
4. **`confirm_dedup_key` check (mandatory for `confirm:` sub-flow rows
|
|
39
38
|
only).** When scheduling a `dm_session` row with
|
|
40
|
-
`taskContext.sub_flow="confirm"`,
|
|
41
|
-
|
|
42
|
-
`
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
check 1) both inherit the same dedup_key, so a successor or defer
|
|
47
|
-
row legitimately occupies the queue with the same key — a second
|
|
48
|
-
gate firing for the same topic MUST yield to it rather than
|
|
49
|
-
double-asking.
|
|
50
|
-
|
|
51
|
-
```bash
|
|
52
|
-
curl -s "http://localhost:8321/api/schedule?status=pending,running" \
|
|
53
|
-
| jq --arg k "<gate>:<stable-topic>" \
|
|
54
|
-
'[.items[] | select(.taskContext.confirm_dedup_key == $k)] | length'
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
If the count is `≥ 1`, log to `## Agent Log` and proceed without
|
|
58
|
-
scheduling:
|
|
59
|
-
```
|
|
60
|
-
- HH:MM [confirm] skipped <dedup_key>: row already pending
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
**`confirm_dedup_key` shape contract.** The key is
|
|
64
|
-
`<gate>:<stable-topic>` — for example
|
|
65
|
-
`create_project:la-pm-masters`,
|
|
66
|
-
`roadmap_ambiguous:tokyo-trip-date`,
|
|
67
|
-
`managed_task_dedup:<existing-task-id>`. The gate scope ensures
|
|
68
|
-
two unrelated gates can't collide on the same topic name; the
|
|
69
|
-
topic component MUST be deterministic from the topic itself
|
|
70
|
-
(no timestamps, no message IDs, no random nonces) so re-fires of
|
|
71
|
-
the same gate produce the same key and this pre-flight catches
|
|
72
|
-
them.
|
|
73
|
-
|
|
74
|
-
This rule layers on top of bullets 1-3, which catch the common
|
|
75
|
-
recurring / Agent-Plan duplicates. Bullet 4 catches the case
|
|
76
|
-
where two confirms target the same topic at different scheduled
|
|
77
|
-
times (e.g. one queued for the morning briefing, another the
|
|
78
|
-
gate would queue for `+4h`).
|
|
39
|
+
`taskContext.sub_flow="confirm"`, run the dedup pre-check + shape
|
|
40
|
+
contract documented in
|
|
41
|
+
`task-flows/_partials/confirm-subflow.md` (also included verbatim
|
|
42
|
+
by `scheduled.dm.md` and `message.received.dm{,_first}.md`). The
|
|
43
|
+
single source covers the `dedup_key` filter, the
|
|
44
|
+
`<gate>:<stable-topic>` shape, and cross-path cancellation.
|
|
79
45
|
|
|
80
46
|
Log the skip to `## Agent Log`:
|
|
81
47
|
`- HH:MM [schedule] skipped <subject>: duplicate of <planId|row>`.
|
|
@@ -144,9 +110,11 @@ month about ESTA for the LA trip"), either write/promote the roadmap
|
|
|
144
110
|
item via the roadmap skill and let AAP schedule the reminder, or call
|
|
145
111
|
`/api/schedule/dm` with `"importance":"strategic"`.
|
|
146
112
|
|
|
147
|
-
## Model selection
|
|
148
|
-
|
|
149
|
-
|
|
113
|
+
## Tier / Model selection
|
|
114
|
+
|
|
115
|
+
Pick `tier` (`lite` / `medium` / `high`) by default — backend-neutral cost knob. Pin `model` (registered id, alias, or `<backendId>/<modelId>`) only when the row must outlive a `/settings/models` re-route. Mutually exclusive — both set returns `schedule.tier_and_model_conflict`. Omit both to use the dispatcher's process-key default. Discovery, PATCH swap form, alias rewrite, and `/api/schedule/options` payload are in the reference below.
|
|
116
|
+
|
|
117
|
+
{{> ref:model-selection }}
|
|
150
118
|
|
|
151
119
|
## Time discipline
|
|
152
120
|
- **Absolute time required** — resolve relative expressions via `<current_time>` into ISO 8601 with offset. E.g. "in 1 hour" at 15:30 EDT → `2026-04-06T16:30:00-04:00`.
|
|
@@ -181,7 +149,7 @@ Response: `{ "status":"scheduled", "scheduleId":"123", "scheduledFor":"..." }`.
|
|
|
181
149
|
```bash
|
|
182
150
|
curl -s -X POST http://localhost:8321/api/schedule \
|
|
183
151
|
-H 'Content-Type: application/json' \
|
|
184
|
-
-d '{"time":"2026-04-06T16:00:00-04:00","taskType":"wake","description":"
|
|
152
|
+
-d '{"time":"2026-04-06T16:00:00-04:00","taskType":"wake","description":"Hourly docker health check: run `docker ps --format` and DM if any container is in restart loop.","tier":"lite","taskContext":{"scheduledBy":"docker_monitor"}}'
|
|
185
153
|
```
|
|
186
154
|
| Field | Required | Description |
|
|
187
155
|
|---|---|---|
|
|
@@ -189,7 +157,8 @@ curl -s -X POST http://localhost:8321/api/schedule \
|
|
|
189
157
|
| `taskType` | Yes | `wake` for scheduled tasks |
|
|
190
158
|
| `description` | Yes | Self-contained (min 20 chars). See format above. Doubles as the agent body unless `prompt` overrides it. |
|
|
191
159
|
| `prompt` | No | Optional override for the agent body (min 20 chars when set). When set, the dispatcher injects this — not `description` — into the task-flow template. Use when you want a short list-friendly `description` plus a longer, separate instruction for the agent. |
|
|
192
|
-
| `
|
|
160
|
+
| `tier` | No | `lite` / `medium` / `high`. Omit to use the dispatcher's process-key default (medium for `scheduled.task`). See "Tier / Model selection" above. Mutually exclusive with `model`. |
|
|
161
|
+
| `model` | No | Registered model id (`claude-opus-4-7`, `gpt-5.4`, …), legacy alias (`sonnet` / `opus`, auto-rewritten to `tier`), or composite `<backendId>/<modelId>`. See "Tier / Model selection" above. Mutually exclusive with `tier`. |
|
|
193
162
|
| `taskContext` | No | Structured metadata object |
|
|
194
163
|
|
|
195
164
|
Response: `{ "status":"scheduled", "scheduleId":"123", "scheduledFor":"YYYY-MM-DD HH:MM:SS" }`. `scheduledFor` is the normalized UTC SQLite timestamp the daemon actually stored — log this verbatim instead of re-formatting the input `time`. Rejects times in the past (> 1 min ago), same as `/api/schedule/dm`.
|
|
@@ -200,8 +169,7 @@ curl -s -X PATCH http://localhost:8321/api/schedule/42 \
|
|
|
200
169
|
-H 'Content-Type: application/json' \
|
|
201
170
|
-d '{"time":"2026-04-06T17:00:00-04:00"}'
|
|
202
171
|
```
|
|
203
|
-
Fields: `time` (ISO 8601), `description` (min 20 chars, non-dm only), `prompt` (min 20 chars OR `null` to clear; non-dm only), `message` (dm only), `model
|
|
204
|
-
Response: `{ "status":"updated", "id":42 }` / 404 / 409 (not pending).
|
|
172
|
+
Fields: `time` (ISO 8601), `description` (min 20 chars, non-dm only), `prompt` (min 20 chars OR `null` to clear; non-dm only), `message` (dm only), `tier` (`lite`/`medium`/`high` OR `null` to clear), `model` (registered id / alias / composite OR `null` to clear), `taskContext`. At least one required. Only `pending` items editable. `description`/`message` mutually exclusive; `prompt`/`message` mutually exclusive. Tier ↔ model swap form is in the model-selection reference above. Response: `{ "status":"updated", "id":42, "warnings":[] }` / 404 / 409 — surface `warnings[]` (e.g. `schedule.model_deprecated`) to the next turn.
|
|
205
173
|
|
|
206
174
|
### GET /api/schedule — List scheduled items
|
|
207
175
|
```bash
|
|
@@ -211,7 +179,7 @@ Param `status` (default `pending,running`): comma-separated `pending`, `running`
|
|
|
211
179
|
Param `roadmapEligible=true`: return only rows that may become
|
|
212
180
|
roadmap `Scheduled:` entries (`transient` / `low` excluded, `normal`
|
|
213
181
|
only beyond 7 days, `strategic` included).
|
|
214
|
-
Response: `{ "items":[{ "id","scheduledFor","taskType","description","prompt","status","model","taskContext","createdAt" }] }`
|
|
182
|
+
Response: `{ "items":[{ "id","scheduledFor","taskType","description","prompt","status","model","backendId","tier","taskContext","createdAt" }] }`. `prompt` / `tier` / `model` / `backendId` are `null` when no override is set. `model` is a registered id verbatim and travels with `backendId` when set — the row carries either the `(model, backendId)` pin or `tier`, never both. Legacy alias inputs (`sonnet` / `opus`) are normalized to `tier` at write time. `taskContext` is the parsed JSON (or `null`); filter with `jq` e.g. `'.items[] | select(.taskContext.confirm_dedup_key == "create_project:la-pm-masters")'`.
|
|
215
183
|
|
|
216
184
|
### DELETE /api/schedule/:id — Cancel a pending item
|
|
217
185
|
```bash
|
|
@@ -219,51 +187,47 @@ curl -s -X DELETE http://localhost:8321/api/schedule/42
|
|
|
219
187
|
```
|
|
220
188
|
Only cancels `pending` items. Response: `{ "status":"cancelled", "id":42 }` / 404 / 409.
|
|
221
189
|
|
|
190
|
+
### POST /api/schedule/batch — Bulk register rich-context schedules
|
|
191
|
+
|
|
192
|
+
Morning-routine Stage A only. Single-row callers use `POST /api/schedule`
|
|
193
|
+
above. The required `taskContext.background` + `expected_output`
|
|
194
|
+
fields, the 50-row cap, the atomic / per-row commit modes, and the
|
|
195
|
+
success payload are in the batch reference below.
|
|
196
|
+
|
|
197
|
+
{{> ref:batch }}
|
|
198
|
+
|
|
222
199
|
---
|
|
223
200
|
|
|
224
|
-
##
|
|
225
|
-
For tasks that repeat on a fixed pattern. Auto-regenerates the next occurrence after each execution.
|
|
201
|
+
## Errors
|
|
226
202
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
-d '{"taskType":"wake","description":"Morning inbox triage — check pending observations and update today.md.","recurrenceRule":{"frequency":"daily","time":"09:00"}}'
|
|
233
|
-
# Weekly Mon/Wed/Fri at 10:00
|
|
234
|
-
curl -s -X POST http://localhost:8321/api/recurring-schedules \
|
|
235
|
-
-H 'Content-Type: application/json' \
|
|
236
|
-
-d '{"taskType":"wake","description":"Standup prep — review PRs, calendar, and blockers.","recurrenceRule":{"frequency":"weekly","time":"10:00","daysOfWeek":[1,3,5]}}'
|
|
237
|
-
```
|
|
238
|
-
| Field | Required | Description |
|
|
239
|
-
|---|---|---|
|
|
240
|
-
| `taskType` | Yes | Task type for dispatch (e.g. `wake`) |
|
|
241
|
-
| `description` | Yes | Self-contained (min 20 chars). Same rules as one-shot. Doubles as the agent body unless `prompt` overrides it. |
|
|
242
|
-
| `prompt` | No | Optional override for the agent body (min 20 chars when set). Each materialized one-shot row inherits this from the recurring parent. |
|
|
243
|
-
| `recurrenceRule` | Yes | `{ frequency, time, timezone?, daysOfWeek?, daysOfMonth? }` |
|
|
244
|
-
| `model` | No | `sonnet` (default) or `opus` |
|
|
245
|
-
| `taskContext` | No | Structured metadata object |
|
|
203
|
+
Every endpoint in this skill emits errors in the **agent-consumable
|
|
204
|
+
envelope** — read `errors[].hint`, fix the value at `errors[].field`,
|
|
205
|
+
and resubmit the same body. The full envelope shape and every
|
|
206
|
+
`schedule.*` code (request-shape, time-bound, row-content, taskContext,
|
|
207
|
+
model, batch) are in the errors reference below.
|
|
246
208
|
|
|
247
|
-
|
|
209
|
+
{{> ref:errors }}
|
|
248
210
|
|
|
249
|
-
|
|
211
|
+
---
|
|
250
212
|
|
|
251
|
-
|
|
252
|
-
```bash
|
|
253
|
-
curl -s "http://localhost:8321/api/recurring-schedules?enabled=true"
|
|
254
|
-
```
|
|
255
|
-
Response: `{ "items":[{ "id","taskType","description","recurrenceRule","enabled","nextRunAt","recurrenceLabel" }] }`
|
|
213
|
+
## Recurring Schedules
|
|
256
214
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
```
|
|
263
|
-
Updatable: `recurrenceRule`, `description`, `prompt` (string sets an override, `null` clears), `model`, `taskContext`, `enabled`. Changing `recurrenceRule`/`enabled` auto-reschedules. Set `{"enabled":false}` to pause.
|
|
215
|
+
For tasks that repeat on a fixed pattern. The daemon auto-regenerates
|
|
216
|
+
the next one-shot occurrence after each execution. **Hourly / daily /
|
|
217
|
+
weekly / monthly** cadences are supported; the recurring reference
|
|
218
|
+
below documents the full shape, the hourly + monthly missing-day
|
|
219
|
+
recipes, pause-vs-delete trade-off, and PATCH / GET / DELETE surface.
|
|
264
220
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
221
|
+
{{> ref:recurring }}
|
|
222
|
+
|
|
223
|
+
### recurrenceRule grammar — engine vs consumer
|
|
224
|
+
|
|
225
|
+
The full engine grammar (mapping table, frequency-vs-field matrix,
|
|
226
|
+
cadence-string-must-match-recurrenceRule discipline) is shared with
|
|
227
|
+
the `managed-tasks` skill. The reference is byte-identical across
|
|
228
|
+
both skills — pinned by `skills-manifest.test.ts` so they cannot
|
|
229
|
+
drift. Schedule callers may use any of the four frequencies the
|
|
230
|
+
engine accepts; the `managed-tasks` consumer chooses to refuse
|
|
231
|
+
sub-daily for app-fetch correctness and that constraint lives there.
|
|
232
|
+
|
|
233
|
+
{{> ref:recurrence-rule }}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
kind: reference
|
|
3
|
+
name: batch
|
|
4
|
+
description: POST /api/schedule/batch — bulk register up to 50 rich-context schedules in one atomic transaction. Morning-routine Stage A is the primary caller.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# POST /api/schedule/batch — Bulk register rich-context schedules
|
|
8
|
+
|
|
9
|
+
Used by the morning-routine Stage A to register every same-day
|
|
10
|
+
schedule in one atomic transaction. Each row's `taskContext` MUST
|
|
11
|
+
carry the context a future `scheduled.task` / `scheduled.dm` session
|
|
12
|
+
needs to produce high-quality output hours later — the daemon cannot
|
|
13
|
+
reconstruct this from the user-facing description.
|
|
14
|
+
|
|
15
|
+
If you are not the morning routine, you almost certainly want
|
|
16
|
+
`POST /api/schedule` (single-row) instead — batch's required
|
|
17
|
+
`taskContext.background` + `expected_output` fields are overkill for
|
|
18
|
+
one-off DM-handler reminders.
|
|
19
|
+
|
|
20
|
+
## Example
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
curl -s -X POST http://localhost:8321/api/schedule/batch \
|
|
24
|
+
-H 'Content-Type: application/json' \
|
|
25
|
+
-d '{
|
|
26
|
+
"rows": [
|
|
27
|
+
{
|
|
28
|
+
"scheduledFor": "2026-05-15T14:30:00-04:00",
|
|
29
|
+
"taskType": "wake",
|
|
30
|
+
"taskDescription": "Pre-brief the 15:00 standup with the two open Q2 risks.",
|
|
31
|
+
"taskContext": {
|
|
32
|
+
"background": "User flagged Q2 roadmap risks in yesterdays DM; standup needs the two open items front-loaded so the team aligns before 15:30.",
|
|
33
|
+
"expected_output": "DM with two bullet items + one suggested mitigation each, sent 30min before standup.",
|
|
34
|
+
"references": ["projects/q2-roadmap.md#open-risks", "calendar:event:standup-2026-05-15"],
|
|
35
|
+
"tone": "concise"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
],
|
|
39
|
+
"atomic": true
|
|
40
|
+
}'
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Fields
|
|
44
|
+
|
|
45
|
+
| Field | Required | Description |
|
|
46
|
+
|---|---|---|
|
|
47
|
+
| `rows` | Yes | Array of row objects (max 50 per batch). Empty array is a documented no-op. |
|
|
48
|
+
| `rows[].scheduledFor` | Yes | ISO 8601 with timezone offset. Must be >= 1 minute in the future. |
|
|
49
|
+
| `rows[].taskType` | Yes | `wake` / `dm_session` / `check` / `dm`. |
|
|
50
|
+
| `rows[].taskDescription` | Yes | Self-contained (min 20 chars). Doubles as the agent body unless `taskPrompt` overrides. |
|
|
51
|
+
| `rows[].taskContext.background` | Yes | Why this task is being scheduled (min 30 chars). Anchor for the future session. |
|
|
52
|
+
| `rows[].taskContext.expected_output` | Yes | What the future session should produce (min 20 chars). |
|
|
53
|
+
| `rows[].taskContext.references` | No | Stable handles the future session can look up (project paths, calendar event ids). |
|
|
54
|
+
| `rows[].taskContext.tone` | No | Free-form tone hint for DM-shaped output. |
|
|
55
|
+
| `rows[].taskContext.tier_override` | No | `lite` / `medium` / `high` / `null`. **Legacy slot — prefer `rows[].tier` (top-level)**. When `tier` is omitted, this value is lifted into the row's `tier_override` column at insert time. |
|
|
56
|
+
| `rows[].tier` | No | `lite` / `medium` / `high`. Abstract cost knob — primary path. Wins over `taskContext.tier_override` when both are set. Mutually exclusive with `rows[].model` on the same row. |
|
|
57
|
+
| `rows[].taskContext.sub_flow` | No | Branches the task-flow rendering when the dispatcher needs a specialised sub-flow. |
|
|
58
|
+
| `rows[].taskPrompt` | No | Override for the agent body (min 20 chars when set). |
|
|
59
|
+
| `rows[].correlationId` | No | Defaults to the morning routine's correlation id when omitted. |
|
|
60
|
+
| `rows[].model` | No | Registered model id (`claude-opus-4-7`, `claude-sonnet-4-6`, `gpt-5.4`, `gemini-3.1-pro-preview`, …), legacy alias (`sonnet` / `opus` — auto-rewritten to `tier`), composite `<backendId>/<modelId>`, or `null`. Mutually exclusive with `rows[].tier`. Omit both to let `process_backend_config` decide. |
|
|
61
|
+
| `atomic` | No | `true` (default) wraps inserts in one transaction — any row error rolls back all. `false` commits successful rows individually. |
|
|
62
|
+
|
|
63
|
+
## Success
|
|
64
|
+
|
|
65
|
+
201:
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{ "ok": true, "rowsAttempted": 1, "rowsCommitted": 1, "ids": [101], "warnings": [] }
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
`warnings[]` carries non-blocking advisories (per-row issues like
|
|
72
|
+
`schedule.model_deprecated` keep the rowIndex so the agent can map
|
|
73
|
+
warnings back to the offending row). Rows are still committed —
|
|
74
|
+
surface the warnings to the next turn so the LLM can refine without
|
|
75
|
+
re-POSTing.
|
|
76
|
+
|
|
77
|
+
## Errors
|
|
78
|
+
|
|
79
|
+
Returns the standard agent-consumable envelope — see
|
|
80
|
+
`references/errors.md`. `rowsCommitted` tells you how much of the
|
|
81
|
+
batch landed; with `atomic:true` any error means `rowsCommitted === 0`.
|
|
82
|
+
Per-row `model_unknown` / `model_ambiguous` / `tier_and_model_conflict`
|
|
83
|
+
all reach this envelope with `rowIndex` set — fix the offending rows
|
|
84
|
+
and resubmit the same body.
|
|
85
|
+
|
|
86
|
+
## When NOT to use batch
|
|
87
|
+
|
|
88
|
+
- One-off DM-handler reminders → use `POST /api/schedule` (single
|
|
89
|
+
row, no required `taskContext.background`).
|
|
90
|
+
- DM-tone scheduled messages → use `POST /api/schedule/dm` (no agent
|
|
91
|
+
invoked at fire time).
|
|
92
|
+
- More than 50 rows in a single horizon → chunk into multiple
|
|
93
|
+
`atomic:true` batches; do not raise the cap.
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
---
|
|
2
|
+
kind: reference
|
|
3
|
+
name: errors
|
|
4
|
+
description: Agent-consumable error envelope shape + every `schedule.*` code emitted by /api/schedule and /api/schedule/batch.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Schedule error envelope + codes
|
|
8
|
+
|
|
9
|
+
Every endpoint in this skill emits errors in the
|
|
10
|
+
**agent-consumable envelope** so you can self-correct in the same
|
|
11
|
+
turn instead of retrying blindly:
|
|
12
|
+
|
|
13
|
+
```jsonc
|
|
14
|
+
{
|
|
15
|
+
"ok": false,
|
|
16
|
+
"summary": "1 validation error. Fix the listed errors and retry.",
|
|
17
|
+
"errors": [
|
|
18
|
+
{
|
|
19
|
+
"rowIndex": 2, // null when not a batch row
|
|
20
|
+
"code": "schedule.task_context_field_missing", // stable machine code
|
|
21
|
+
"field": "rows[2].taskContext.background", // JSON-pointer-ish path
|
|
22
|
+
"received": "<missing>",
|
|
23
|
+
"expected": "string with >= 30 characters explaining why this task is being scheduled",
|
|
24
|
+
"constraint": { "type": "string", "minLength": 30, "required": true },
|
|
25
|
+
"validValues": null, // runtime-derived set, when applicable (see "validValues vs constraint.enum")
|
|
26
|
+
"hint": "Stage A must populate taskContext.background so the future session can produce high-quality output without re-deriving context. Example: ...",
|
|
27
|
+
"skillAnchor": "schedule#taskContext-required-fields",
|
|
28
|
+
"docsUrl": "agent-assets/skills/schedule/references/errors.md#task_context_field_missing",
|
|
29
|
+
"severity": "error"
|
|
30
|
+
}
|
|
31
|
+
],
|
|
32
|
+
"warnings": [], // non-blocking advisories — see "Warnings channel"
|
|
33
|
+
"retryable": true,
|
|
34
|
+
"retryHint": "Fix the listed rows and POST the same body again. atomic=true (the default) means no rows were committed."
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
When you see an error: read `errors[].hint`, fix the value at
|
|
39
|
+
`errors[].field`, and resubmit the same body. The morning-routine
|
|
40
|
+
task-flow gates batch retries on `rowsCommitted === rows.length`; do
|
|
41
|
+
not retry a row-level fix on a different field path.
|
|
42
|
+
|
|
43
|
+
## Issue fields
|
|
44
|
+
|
|
45
|
+
| Field | Use |
|
|
46
|
+
|---|---|
|
|
47
|
+
| `code` | Stable namespaced identifier. Switch on this in skill prose, not on `expected` or `hint`. |
|
|
48
|
+
| `field` | JSON-pointer-ish path to the offending input (`rows[2].taskContext.background`). |
|
|
49
|
+
| `received` | Exact value the daemon saw. `'<missing>'` sentinel when the field was omitted. |
|
|
50
|
+
| `expected` | One-sentence summary of what would have been accepted. |
|
|
51
|
+
| `constraint` | Static, schema-level shape (`{type, minLength, enum: [...]}`). Fixed across deploys. |
|
|
52
|
+
| `validValues` | Runtime-derived list of acceptable values — populated when the answer is data the operator can change (model registry, IANA timezones, an integration's supported modes). Distinct from `constraint.enum`: never both on the same code. |
|
|
53
|
+
| `hint` | Concrete remediation guidance with an example. |
|
|
54
|
+
| `skillAnchor` | `<skill>#<slug>` reference for fuller context — `Read agent-assets/skills/<skill>/SKILL.md#<slug>`. |
|
|
55
|
+
| `docsUrl` | Repo-relative path to deeper "what to do" prose, including a fragment that lands on the code's heading in this file. |
|
|
56
|
+
| `severity` | `error` blocks the commit; `warning` is advisory only (also surfaced via `warnings[]` — see below). |
|
|
57
|
+
|
|
58
|
+
### validValues vs constraint.enum
|
|
59
|
+
|
|
60
|
+
These two fields look alike but answer different questions:
|
|
61
|
+
|
|
62
|
+
- **`constraint.enum`** — schema-level static list (`["lite","medium","high"]`, `["hourly","daily","weekly","monthly"]`). Same on every deploy.
|
|
63
|
+
- **`validValues`** — runtime-derived list (the model registry snapshot, which evolves as new models are registered; the IANA timezone set; an integration's `supportedModes`). Filled by the route at error-time.
|
|
64
|
+
|
|
65
|
+
Use `validValues` when present — it reflects what the daemon will accept on this run, including any newly added entries. `constraint.enum` is the
|
|
66
|
+
specification-time guarantee. The two never appear together on the same code.
|
|
67
|
+
|
|
68
|
+
## Warnings channel
|
|
69
|
+
|
|
70
|
+
Some inputs are syntactically valid but suspicious enough to flag —
|
|
71
|
+
deprecated model on a long-lived recurring rule, `daysOfMonth:[31]`
|
|
72
|
+
with the default `lastDayOfMonth` policy, etc. The daemon does **not**
|
|
73
|
+
reject these; the row is persisted and the response returns 200/201
|
|
74
|
+
with a `warnings: []` array using the same issue shape as `errors[]`:
|
|
75
|
+
|
|
76
|
+
```jsonc
|
|
77
|
+
{
|
|
78
|
+
"status": "created",
|
|
79
|
+
"item": { "id": 42, "recurrenceRule": { ... }, "nextRunAt": "2026-05-31T12:00:00Z" },
|
|
80
|
+
"warnings": [
|
|
81
|
+
{
|
|
82
|
+
"rowIndex": null,
|
|
83
|
+
"code": "schedule.on_missing_day_unused",
|
|
84
|
+
"field": "recurrenceRule.onMissingDay",
|
|
85
|
+
"received": "lastDayOfMonth",
|
|
86
|
+
"expected": "onMissingDay only matters when daysOfMonth contains 29, 30, or 31",
|
|
87
|
+
"hint": "Drop onMissingDay or add 29/30/31 to daysOfMonth.",
|
|
88
|
+
"skillAnchor": "schedule#monthly-missing-day",
|
|
89
|
+
"severity": "warning"
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Surface warnings to the next agent turn (e.g. include them in the
|
|
96
|
+
DM that confirms the schedule was created) so the LLM can refine on
|
|
97
|
+
the next call if the warning matters. **Don't treat warnings as
|
|
98
|
+
failures** — they are advisory, not blocking. `retryable` is computed
|
|
99
|
+
from `errors[]` only and ignores `warnings[]`.
|
|
100
|
+
|
|
101
|
+
When the same envelope contains both `errors` and `warnings`, the
|
|
102
|
+
errors path runs first: fix every entry in `errors[]`, then inspect
|
|
103
|
+
`warnings[]` on the retried response.
|
|
104
|
+
|
|
105
|
+
## Codes the schedule endpoints can emit
|
|
106
|
+
|
|
107
|
+
### Request-shape codes
|
|
108
|
+
|
|
109
|
+
Apply to `POST /api/schedule` and `POST /api/schedule/batch`.
|
|
110
|
+
|
|
111
|
+
<a id="request-shape"></a>
|
|
112
|
+
|
|
113
|
+
| Code | When | Fix |
|
|
114
|
+
|---|---|---|
|
|
115
|
+
| <a id="body_not_object"></a> `schedule.body_not_object` | Body is not a JSON object. | POST `{"rows":[…]}` for batch, or the row fields directly for single-row. |
|
|
116
|
+
| <a id="rows_field_missing"></a> `schedule.rows_field_missing` | Batch body is missing the `rows` array. | Wrap your row objects in a `rows` array. |
|
|
117
|
+
| <a id="rows_too_many"></a> `schedule.rows_too_many` | Batch contains > 50 rows. | Split into chunks of at most 50 rows. |
|
|
118
|
+
| <a id="batch_atomic_invalid"></a> `schedule.batch_atomic_invalid` | `atomic` is not a boolean. | Pass `true` / `false`, or omit (defaults to `true`). |
|
|
119
|
+
|
|
120
|
+
### Time-bound codes
|
|
121
|
+
|
|
122
|
+
<a id="scheduledFor-bounds"></a>
|
|
123
|
+
|
|
124
|
+
| Code | When | Fix |
|
|
125
|
+
|---|---|---|
|
|
126
|
+
| <a id="scheduled_for_invalid"></a> `schedule.scheduled_for_invalid` | `scheduledFor` / `time` is not parseable by `Date()`. | Use ISO 8601 with timezone offset. Resolve relative times via `<current_time>`. |
|
|
127
|
+
| <a id="scheduled_for_in_past"></a> `schedule.scheduled_for_in_past` | `scheduledFor` is earlier than now (with a 1-minute grace). | Pick a future time. Inspect `<current_time>` and pick now+1min minimum. |
|
|
128
|
+
|
|
129
|
+
### Row-content codes
|
|
130
|
+
|
|
131
|
+
<a id="taskType"></a>
|
|
132
|
+
<a id="description-shape"></a>
|
|
133
|
+
|
|
134
|
+
| Code | When | Fix |
|
|
135
|
+
|---|---|---|
|
|
136
|
+
| <a id="task_type_unknown"></a> `schedule.task_type_unknown` | `taskType` is not `wake` / `dm_session` / `check` / `dm`. | Pick the matching type. Use `/api/schedule/dm` for the precomposed-DM variant. |
|
|
137
|
+
| <a id="description_too_short"></a> `schedule.description_too_short` | `description` / `taskDescription` < 20 chars. | Expand the description so the wake-up agent has enough context to act. |
|
|
138
|
+
| <a id="prompt_too_short"></a> `schedule.prompt_too_short` | `prompt` / `taskPrompt` is set but < 20 chars. | Either remove it (description doubles as the body) or expand it. |
|
|
139
|
+
|
|
140
|
+
### taskContext required fields
|
|
141
|
+
|
|
142
|
+
<a id="taskContext-required-fields"></a>
|
|
143
|
+
|
|
144
|
+
For `POST /api/schedule/batch`, every row's `taskContext` must carry
|
|
145
|
+
`background` (>=30 chars) and `expected_output` (>=20 chars). The
|
|
146
|
+
future session firing at the scheduled time inherits these verbatim
|
|
147
|
+
— its output quality is bounded by the richness of what you write
|
|
148
|
+
here.
|
|
149
|
+
|
|
150
|
+
| Code | When | Fix |
|
|
151
|
+
|---|---|---|
|
|
152
|
+
| <a id="task_context_field_missing"></a> `schedule.task_context_field_missing` | `taskContext.background` or `taskContext.expected_output` is absent. | Populate both. `background` explains *why* this row exists; `expected_output` defines what "done" looks like. |
|
|
153
|
+
| <a id="task_context_field_too_short"></a> `schedule.task_context_field_too_short` | One of the required taskContext fields is below its min length. | Expand the string. Trivial values like "follow up" don't survive a 4-hour gap. |
|
|
154
|
+
| <a id="task_context_field_wrong_type"></a> `schedule.task_context_field_wrong_type` | A typed taskContext slot received the wrong type (e.g. `references` is a string instead of `string[]`). | Match the schema: references is `string[]`, tier_override is `null|"lite"|"medium"|"high"`, tone is a free string. |
|
|
155
|
+
|
|
156
|
+
### Model selection
|
|
157
|
+
|
|
158
|
+
<a id="model-selection"></a>
|
|
159
|
+
<a id="tier-selection"></a>
|
|
160
|
+
<a id="tier-vs-model"></a>
|
|
161
|
+
|
|
162
|
+
`model` accepts a free-form token after SCHEDULE_API_REDESIGN_PLAN
|
|
163
|
+
§4.3: legacy aliases (`sonnet` / `opus` — rewritten to `tier` at
|
|
164
|
+
the route), full registered model ids (e.g. `claude-opus-4-7`,
|
|
165
|
+
`gpt-5.4`), or the composite `<backendId>/<modelId>` form when an
|
|
166
|
+
id appears under multiple backends. `tier` (`lite` | `medium` |
|
|
167
|
+
`high`) is the abstract cost knob and is mutually exclusive with
|
|
168
|
+
`model`. Prefer `tier` for new schedules — the dispatcher picks the
|
|
169
|
+
latest non-deprecated model per resolved process key automatically.
|
|
170
|
+
|
|
171
|
+
| Code | When | Fix |
|
|
172
|
+
|---|---|---|
|
|
173
|
+
| <a id="model_unknown"></a> `schedule.model_unknown` | `model` is not a registered alias / model id. | Inspect `validValues.aliases` and `validValues.models` on the response — these list every value the daemon will accept right now. Omit `model` to let `process_backend_config` decide. |
|
|
174
|
+
| <a id="model_ambiguous"></a> `schedule.model_ambiguous` | `model` matches more than one backend in the registry. | Resubmit using the composite `<backendId>/<modelId>` form (see `validValues.matches`). |
|
|
175
|
+
| <a id="model_deprecated"></a> `schedule.model_deprecated` (warning) | `model` is registered but flagged deprecated. | The row was still created. Switch to a non-deprecated id from `validValues.availableModels`, or use `tier` instead. |
|
|
176
|
+
| <a id="backend_id_unknown"></a> `schedule.backend_id_unknown` | Backend portion of the composite token is not `claude` / `codex` / `gemini` / `opencode`. | Use one of the four BackendId values. |
|
|
177
|
+
| <a id="tier_unknown"></a> `schedule.tier_unknown` | `tier` is not `lite` / `medium` / `high`. | Pick one of the three tiers or omit entirely. |
|
|
178
|
+
| <a id="tier_and_model_conflict"></a> `schedule.tier_and_model_conflict` | Both `tier` AND `model` set on the same row. | Pick exactly one: `tier` (recommended) OR `model`. On PATCH you can clear one and set the other in the same request (pass `null` to clear). |
|
|
179
|
+
|
|
180
|
+
### Batch-shape codes
|
|
181
|
+
|
|
182
|
+
<a id="batch-shape"></a>
|
|
183
|
+
|
|
184
|
+
See the table under "Request-shape codes" above. `rowsAttempted` /
|
|
185
|
+
`rowsCommitted` in the envelope tell you how much of the batch
|
|
186
|
+
committed; with `atomic:true` (the default) every error means
|
|
187
|
+
`rowsCommitted === 0`.
|
|
188
|
+
|
|
189
|
+
### Recurring-schedules (`/api/recurring-schedules`)
|
|
190
|
+
|
|
191
|
+
<a id="recurring-shape"></a>
|
|
192
|
+
|
|
193
|
+
POST and PATCH `/api/recurring-schedules` route every Zod validation
|
|
194
|
+
failure through `translateZodError` so each offending field surfaces
|
|
195
|
+
as its own code instead of collapsing onto one
|
|
196
|
+
`recurring_schedules.validation_error` issue. The codes below mirror
|
|
197
|
+
the per-frequency rules in `recurrence-rule.md`.
|
|
198
|
+
|
|
199
|
+
| Code | When | Fix |
|
|
200
|
+
|---|---|---|
|
|
201
|
+
| <a id="frequency_unknown"></a> `schedule.frequency_unknown` | `recurrenceRule.frequency` not in the enum. | Pick `hourly` / `daily` / `weekly` / `monthly`. |
|
|
202
|
+
| <a id="frequency_field_mismatch"></a> `schedule.frequency_field_mismatch` | Wrong fields for the chosen frequency (e.g. `time` on `hourly`, `daysOfWeek` on `daily`). | See `validValues.requiredFor` / `forbiddenFor` for the exact matrix. |
|
|
203
|
+
| <a id="interval_hours_out_of_range"></a> `schedule.interval_hours_out_of_range` | `intervalHours` outside `[1, 23]`. | Use 1..23; for daily switch frequency. |
|
|
204
|
+
| <a id="minute_of_hour_out_of_range"></a> `schedule.minute_of_hour_out_of_range` | `minuteOfHour` outside `[0, 59]`. | Pick 0..59 (default 0). |
|
|
205
|
+
| <a id="time_format_invalid"></a> `schedule.time_format_invalid` | `time` not `HH:MM` 24h. | Use the exact form `09:00` / `21:30`. |
|
|
206
|
+
| <a id="days_of_week_invalid"></a> `schedule.days_of_week_invalid` | `daysOfWeek` empty, duplicate, or out of `[0, 6]`. | 0=Sun..6=Sat, distinct entries only. |
|
|
207
|
+
| <a id="days_of_month_invalid"></a> `schedule.days_of_month_invalid` | `daysOfMonth` empty, duplicate, or out of `[1, 31]`. | 1..31, distinct entries only — use `onMissingDay` to control 29-31 behavior. |
|
|
208
|
+
| <a id="on_missing_day_unknown"></a> `schedule.on_missing_day_unknown` | `onMissingDay` not `skip` / `lastDayOfMonth`. | Pick one (default `lastDayOfMonth`). |
|
|
209
|
+
| <a id="on_missing_day_unused"></a> `schedule.on_missing_day_unused` (warning) | `onMissingDay` set but `daysOfMonth` has no entry in `[29, 30, 31]`. | Advisory — row is created. Either drop `onMissingDay` (no effect on a 1..28 set) or extend `daysOfMonth` to include 29/30/31 if you meant a month-end rule. |
|
|
210
|
+
| <a id="timezone_unknown"></a> `schedule.timezone_unknown` | `timezone` is not a valid IANA zone. | Use a real zone (`Asia/Tokyo`, `America/New_York`, `UTC`). |
|
|
211
|
+
| <a id="recurrence_rule_invalid"></a> `schedule.recurrence_rule_invalid` | `recurrenceRule` is structurally invalid in a way the traversal could not localise. | Inspect the response `field` path and resubmit a well-formed object. |
|
|
212
|
+
| <a id="recurring_id_invalid"></a> `schedule.recurring_id_invalid` | id segment not a positive integer. | Use the `item.id` returned by POST. |
|
|
213
|
+
| <a id="recurring_not_found"></a> `schedule.recurring_not_found` | No row with this id. | List `/api/recurring-schedules` to see current rows. |
|
|
214
|
+
| <a id="recurring_no_changes"></a> `schedule.recurring_no_changes` | PATCH body is empty. | Supply at least one of `description` / `prompt` / `recurrenceRule` / `model` / `tier` / `taskContext` / `enabled`. |
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
---
|
|
2
|
+
kind: reference
|
|
3
|
+
name: model-selection
|
|
4
|
+
description: Tier vs model selection for schedule rows + `GET /api/schedule/options` discovery endpoint. Mutual-exclusion rules, legacy alias rewrite, composite-form disambiguator.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Tier / Model selection
|
|
8
|
+
|
|
9
|
+
`tier` is the backend-neutral cost knob — **prefer it**. `model` pins
|
|
10
|
+
a specific registered model id when the row must run against a
|
|
11
|
+
particular backend (e.g. a routine that depends on Opus reasoning
|
|
12
|
+
even after `/settings/models` re-routes the process key). The two are
|
|
13
|
+
**mutually exclusive on a single row** — passing both returns
|
|
14
|
+
`schedule.tier_and_model_conflict` (no "tier wins" precedence).
|
|
15
|
+
|
|
16
|
+
| `tier` | Class | When |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| `"lite"` | Haiku | hourly polling / health checks (e.g. docker `ps` summary) |
|
|
19
|
+
| `"medium"` | Sonnet | lock against future `/settings/models` re-routes |
|
|
20
|
+
| `"high"` | Opus | one-off generative work driving user-visible output |
|
|
21
|
+
|
|
22
|
+
`model` accepts:
|
|
23
|
+
|
|
24
|
+
- **Legacy aliases** — `"sonnet"` / `"opus"`. Auto-rewritten at the
|
|
25
|
+
route to `tier:"medium"` / `tier:"high"`; the alias is not stored
|
|
26
|
+
verbatim.
|
|
27
|
+
- **Registered model ids** — any id from `MODEL_REGISTRY` across the
|
|
28
|
+
four backends. Examples: `claude-opus-4-7`, `claude-sonnet-4-6`,
|
|
29
|
+
`claude-haiku-4-5-20251001`, `gpt-5.4`, `gemini-3.1-pro-preview`.
|
|
30
|
+
The row persists `(model, backend_id)` together so the dispatcher
|
|
31
|
+
honors the pin at fire time.
|
|
32
|
+
- **Composite `<backendId>/<modelId>`** — disambiguator for a future
|
|
33
|
+
registry that has the same model id under multiple backends (today
|
|
34
|
+
unreachable but accepted). The prefix MUST be one of `claude` /
|
|
35
|
+
`codex` / `gemini` / `opencode`; opencode model ids like
|
|
36
|
+
`anthropic/claude-opus-4-7` are NOT composites and fall through to
|
|
37
|
+
the cross-backend scan.
|
|
38
|
+
|
|
39
|
+
Unknown / ambiguous / deprecated model tokens surface through the
|
|
40
|
+
error envelope's `validValues` field — read it instead of guessing.
|
|
41
|
+
The full code list lives in `references/errors.md`.
|
|
42
|
+
|
|
43
|
+
## PATCH semantics — tier ↔ model swap
|
|
44
|
+
|
|
45
|
+
A row carries at most one pin at rest. On PATCH:
|
|
46
|
+
|
|
47
|
+
- Pass `null` to clear one and a concrete value to set the other in
|
|
48
|
+
the same request — that is the documented form for swapping a
|
|
49
|
+
tier-pinned row to a model-pinned row (and vice versa).
|
|
50
|
+
- Setting a registered `model` token also clears any prior
|
|
51
|
+
`tier_override` automatically; setting `tier` does not auto-clear
|
|
52
|
+
`model` — pair the change with `"model": null` when the intent is
|
|
53
|
+
to swap.
|
|
54
|
+
- Setting a legacy alias (`sonnet` / `opus`) on PATCH is rewritten to
|
|
55
|
+
`tier:"medium"` / `tier:"high"`; the alias is never stored verbatim.
|
|
56
|
+
|
|
57
|
+
## Discovery — `GET /api/schedule/options`
|
|
58
|
+
|
|
59
|
+
Read-only one-stop endpoint that returns every value the daemon will
|
|
60
|
+
accept right now: registered models per backend, model aliases,
|
|
61
|
+
allowed tiers, recurrence frequencies, `daysOfWeek` map, hourly /
|
|
62
|
+
monthly bounds (`intervalHours` 1..23, `minuteOfHour` 0..59,
|
|
63
|
+
`onMissingDay` default), and the operator's configured timezone.
|
|
64
|
+
Fetch once per cold session before composing tricky schedules; the
|
|
65
|
+
error envelope also cites this endpoint via `docsUrl` so you can
|
|
66
|
+
recover after a 400.
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
curl -s http://localhost:8321/api/schedule/options
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Response shape:
|
|
73
|
+
|
|
74
|
+
```jsonc
|
|
75
|
+
{
|
|
76
|
+
"tiers": ["lite", "medium", "high"],
|
|
77
|
+
"modelAliases": { "sonnet": "medium", "opus": "high" },
|
|
78
|
+
"models": {
|
|
79
|
+
"claude": [{ "id": "claude-opus-4-7", "tier": "high", "deprecated": false }, ...],
|
|
80
|
+
"codex": [...],
|
|
81
|
+
"gemini": [...],
|
|
82
|
+
"opencode": [...]
|
|
83
|
+
},
|
|
84
|
+
"frequencies": ["hourly", "daily", "weekly", "monthly"],
|
|
85
|
+
"daysOfWeek": { "0": "Sun", "1": "Mon", ..., "6": "Sat" },
|
|
86
|
+
"recurrence": {
|
|
87
|
+
"intervalHours": { "min": 1, "max": 23 },
|
|
88
|
+
"minuteOfHour": { "min": 0, "max": 59 },
|
|
89
|
+
"daysOfMonth": { "min": 1, "max": 31 },
|
|
90
|
+
"onMissingDay": { "values": ["skip", "lastDayOfMonth"], "default": "lastDayOfMonth" }
|
|
91
|
+
},
|
|
92
|
+
"timeFormat": "HH:MM (24h)",
|
|
93
|
+
"timezoneExample": "Asia/Tokyo",
|
|
94
|
+
"defaults": { "timezone": "<operator's configured primary timezone>" }
|
|
95
|
+
}
|
|
96
|
+
```
|