@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
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
---
|
|
2
|
+
kind: reference
|
|
3
|
+
name: recurrence-rule
|
|
4
|
+
description: recurrenceRule grammar — hourly / daily / weekly / monthly. Engine accepts all four; the managed-tasks consumer specifically refuses sub-daily for app-fetch correctness (template below).
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# recurrenceRule grammar
|
|
8
|
+
|
|
9
|
+
The daemon's recurrence engine accepts four frequencies: `hourly`,
|
|
10
|
+
`daily`, `weekly`, `monthly`. Each frequency requires its own set of
|
|
11
|
+
fields and rejects fields that don't apply — the daemon's Zod
|
|
12
|
+
refinements return a `schedule.frequency_field_mismatch` issue (with
|
|
13
|
+
the offending field path) when the shape disagrees with the chosen
|
|
14
|
+
frequency. Pre-validate to save a round-trip.
|
|
15
|
+
|
|
16
|
+
Times are `HH:MM` 24-hour local; `timezone` is IANA (auto-fills from
|
|
17
|
+
daemon config when omitted, but explicit is safer so a roaming laptop
|
|
18
|
+
does not surprise the user).
|
|
19
|
+
|
|
20
|
+
## Engine — per-frequency field rules
|
|
21
|
+
|
|
22
|
+
| `frequency` | Required | Allowed | Forbidden |
|
|
23
|
+
|---|---|---|---|
|
|
24
|
+
| `hourly` | — | `intervalHours` (1..23, default 1), `minuteOfHour` (0..59, default 0), `timezone` | `time`, `daysOfWeek`, `daysOfMonth`, `onMissingDay` |
|
|
25
|
+
| `daily` | `time` | `timezone` | `intervalHours`, `minuteOfHour`, `daysOfWeek`, `daysOfMonth`, `onMissingDay` |
|
|
26
|
+
| `weekly` | `time`, `daysOfWeek` | `timezone` | `intervalHours`, `minuteOfHour`, `daysOfMonth`, `onMissingDay` |
|
|
27
|
+
| `monthly` | `time`, `daysOfMonth` | `timezone`, `onMissingDay` (default `lastDayOfMonth`) | `intervalHours`, `minuteOfHour`, `daysOfWeek` |
|
|
28
|
+
|
|
29
|
+
- `daysOfWeek` is `0=Sun..6=Sat`; 1..7 distinct entries, dupes rejected.
|
|
30
|
+
- `daysOfMonth` is `1..31`; 1..31 distinct entries, dupes rejected.
|
|
31
|
+
Days 29-31 may not exist in a given month — see `onMissingDay`.
|
|
32
|
+
- `onMissingDay`: `"skip"` (don't fire that month) or
|
|
33
|
+
`"lastDayOfMonth"` (fire on the actual last day, preserving the
|
|
34
|
+
pre-redesign clamp behavior). Default `"lastDayOfMonth"` for
|
|
35
|
+
back-compat. The engine also de-duplicates calendar dates that
|
|
36
|
+
collapse to the same fire (e.g. `[28,31]` in non-leap Feb with
|
|
37
|
+
`"lastDayOfMonth"` fires Feb 28 once, not twice).
|
|
38
|
+
- `intervalHours=N` fires when `(localHour % N) == 0` at
|
|
39
|
+
`minuteOfHour` local, anchored at midnight in the rule's
|
|
40
|
+
`timezone`.
|
|
41
|
+
|
|
42
|
+
## Mapping table
|
|
43
|
+
|
|
44
|
+
| User said | `cadence` | `recurrenceRule` |
|
|
45
|
+
|---|---|---|
|
|
46
|
+
| every hour | `hourly :00 (UTC)` | `{frequency:"hourly"}` |
|
|
47
|
+
| every 2 hours at :30 | `hourly /2 :30 (UTC)` | `{frequency:"hourly", intervalHours:2, minuteOfHour:30}` |
|
|
48
|
+
| every day at 10am (Asia/Tokyo) | `daily 10:00 (Asia/Tokyo)` | `{frequency:"daily", time:"10:00", timezone:"Asia/Tokyo"}` |
|
|
49
|
+
| every Monday 9am | `weekly Mon 09:00` | `{frequency:"weekly", time:"09:00", timezone:<user tz>, daysOfWeek:[1]}` |
|
|
50
|
+
| every weekday at 8am | `weekdays 08:00` | `{frequency:"weekly", time:"08:00", timezone:<user tz>, daysOfWeek:[1,2,3,4,5]}` |
|
|
51
|
+
| 1st of every month at noon | `monthly day 1 12:00` | `{frequency:"monthly", time:"12:00", timezone:<user tz>, daysOfMonth:[1]}` |
|
|
52
|
+
| 25th of every month at 21:00 | `monthly day 25 21:00` | `{frequency:"monthly", time:"21:00", timezone:<user tz>, daysOfMonth:[25]}` |
|
|
53
|
+
| last day of every month at 21:00 | `monthly last 21:00` | `{frequency:"monthly", time:"21:00", timezone:<user tz>, daysOfMonth:[31], onMissingDay:"lastDayOfMonth"}` |
|
|
54
|
+
| every 5 minutes | _not representable_ | _refuse — sub-hour cadences are not supported_ |
|
|
55
|
+
|
|
56
|
+
## Consumer-specific refusal — managed-tasks only
|
|
57
|
+
|
|
58
|
+
The managed-tasks skill (`mt_<n>` rows) refuses sub-daily cadences
|
|
59
|
+
because app-fetch correctness requires a daily-or-coarser window to
|
|
60
|
+
amortise rate limits and to map cleanly onto the entity-mirror's
|
|
61
|
+
daily granularity. Schedule callers (`/api/schedule`,
|
|
62
|
+
`/api/recurring-schedules`) have no such constraint and may use any
|
|
63
|
+
of the four frequencies the engine accepts.
|
|
64
|
+
|
|
65
|
+
### managed-tasks sub-daily refusal — DM template
|
|
66
|
+
|
|
67
|
+
> Managed tasks only support daily, weekly, or monthly cadences.
|
|
68
|
+
> "every hour" / "every 5 minutes" is too tight for a recurring app
|
|
69
|
+
> fetch — pick `daily` or coarser. (If you want a daemon-internal
|
|
70
|
+
> hourly check, use `/api/recurring-schedules` via the `schedule`
|
|
71
|
+
> skill.)
|
|
72
|
+
|
|
73
|
+
Same template applies to "every 5 minutes", "every 30 minutes",
|
|
74
|
+
"every 2 hours", etc. when the registering surface is managed-tasks.
|
|
75
|
+
|
|
76
|
+
## Cadence string vs structured rule
|
|
77
|
+
|
|
78
|
+
Always send both `cadence` (human-readable, rendered in
|
|
79
|
+
`rules/management.md` §B) and `recurrenceRule` (structured, what the
|
|
80
|
+
scheduler executes). They must agree — if they drift, the rendered
|
|
81
|
+
file misleads the user about what the scheduler will actually do.
|
|
82
|
+
|
|
83
|
+
When the user modifies just the time (`"9am instead of 10am"`),
|
|
84
|
+
send the new `cadence` and new `recurrenceRule` together in the same
|
|
85
|
+
PATCH so the §B label matches the executable schedule in one
|
|
86
|
+
transition.
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
---
|
|
2
|
+
kind: reference
|
|
3
|
+
name: recurring
|
|
4
|
+
description: /api/recurring-schedules — hourly / daily / weekly / monthly cadences auto-regenerating one-shot rows. Includes hourly anchor semantics, monthly missing-day recipes, and the tier ↔ model swap on PATCH.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Recurring schedules
|
|
8
|
+
|
|
9
|
+
For tasks that repeat on a fixed pattern. The daemon auto-regenerates
|
|
10
|
+
the next one-shot occurrence after each execution; you never have to
|
|
11
|
+
re-POST a daily reminder.
|
|
12
|
+
|
|
13
|
+
Use a recurring schedule when the cadence is all that matters and
|
|
14
|
+
there is no need to record *why* the rule exists. If the user wants
|
|
15
|
+
the WHY captured alongside the cadence (so the rule survives a
|
|
16
|
+
context reset), use the `management-policy` skill — it produces a
|
|
17
|
+
`rules/policies/<slug>.md` linked to a `routines/custom/<slug>.md`
|
|
18
|
+
custom routine.
|
|
19
|
+
|
|
20
|
+
## POST /api/recurring-schedules — Create
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# Hourly at :00 (every hour)
|
|
24
|
+
curl -s -X POST http://localhost:8321/api/recurring-schedules \
|
|
25
|
+
-H 'Content-Type: application/json' \
|
|
26
|
+
-d '{"taskType":"wake","description":"Hourly docker container health check.","recurrenceRule":{"frequency":"hourly"},"tier":"lite"}'
|
|
27
|
+
|
|
28
|
+
# Every 2 hours at :30 (00:30, 02:30, …, 22:30 local)
|
|
29
|
+
curl -s -X POST http://localhost:8321/api/recurring-schedules \
|
|
30
|
+
-H 'Content-Type: application/json' \
|
|
31
|
+
-d '{"taskType":"wake","description":"Sync inbox triage signals.","recurrenceRule":{"frequency":"hourly","intervalHours":2,"minuteOfHour":30},"tier":"lite"}'
|
|
32
|
+
|
|
33
|
+
# Daily at 09:00
|
|
34
|
+
curl -s -X POST http://localhost:8321/api/recurring-schedules \
|
|
35
|
+
-H 'Content-Type: application/json' \
|
|
36
|
+
-d '{"taskType":"wake","description":"Morning inbox triage — check pending observations and update today.md.","recurrenceRule":{"frequency":"daily","time":"09:00"}}'
|
|
37
|
+
|
|
38
|
+
# Weekly Mon/Wed/Fri at 10:00
|
|
39
|
+
curl -s -X POST http://localhost:8321/api/recurring-schedules \
|
|
40
|
+
-H 'Content-Type: application/json' \
|
|
41
|
+
-d '{"taskType":"wake","description":"Standup prep — review PRs, calendar, and blockers.","recurrenceRule":{"frequency":"weekly","time":"10:00","daysOfWeek":[1,3,5]}}'
|
|
42
|
+
|
|
43
|
+
# Monthly on the 25th at 21:00 (billing reconciliation)
|
|
44
|
+
curl -s -X POST http://localhost:8321/api/recurring-schedules \
|
|
45
|
+
-H 'Content-Type: application/json' \
|
|
46
|
+
-d '{"taskType":"wake","description":"Monthly card reconciliation — pull statement, log balance to finance dossier.","recurrenceRule":{"frequency":"monthly","time":"21:00","daysOfMonth":[25]},"tier":"medium"}'
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
| Field | Required | Description |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| `taskType` | Yes | Task type for dispatch (e.g. `wake`) |
|
|
52
|
+
| `description` | Yes | Self-contained (min 20 chars). Same rules as one-shot. Doubles as the agent body unless `prompt` overrides it. |
|
|
53
|
+
| `prompt` | No | Optional override for the agent body (min 20 chars when set). Each materialized one-shot row inherits this from the recurring parent. |
|
|
54
|
+
| `recurrenceRule` | Yes | `{ frequency, time?, timezone?, intervalHours?, minuteOfHour?, daysOfWeek?, daysOfMonth?, onMissingDay? }` — fields gated by `frequency`; see grammar below. |
|
|
55
|
+
| `tier` | No | `lite` / `medium` / `high`. Mutually exclusive with `model`. |
|
|
56
|
+
| `model` | No | Registered model id (`claude-opus-4-7`, `gpt-5.4`, `gemini-3.1-pro-preview`, …), legacy alias (`sonnet` / `opus` — auto-rewritten to `tier`), or composite `<backendId>/<modelId>` for future disambiguation. Mutually exclusive with `tier`. The row stores `(model, backend_id)` together so the dispatcher honors the pin at fire time. |
|
|
57
|
+
| `taskContext` | No | Structured metadata object |
|
|
58
|
+
|
|
59
|
+
### Recurrence rule grammar (engine)
|
|
60
|
+
|
|
61
|
+
The recurrence engine accepts four frequencies. Each frequency
|
|
62
|
+
requires its own set of fields and rejects fields that don't apply.
|
|
63
|
+
|
|
64
|
+
| `frequency` | Required | Allowed | Forbidden |
|
|
65
|
+
|---|---|---|---|
|
|
66
|
+
| `"hourly"` | — | `intervalHours` (1..23, default 1), `minuteOfHour` (0..59, default 0), `timezone` | `time`, `daysOfWeek`, `daysOfMonth`, `onMissingDay` |
|
|
67
|
+
| `"daily"` | `time` | `timezone` | `intervalHours`, `minuteOfHour`, `daysOfWeek`, `daysOfMonth`, `onMissingDay` |
|
|
68
|
+
| `"weekly"` | `time`, `daysOfWeek` (1..7 distinct entries, 0=Sun..6=Sat) | `timezone` | `intervalHours`, `minuteOfHour`, `daysOfMonth`, `onMissingDay` |
|
|
69
|
+
| `"monthly"` | `time`, `daysOfMonth` (1..31 distinct entries) | `timezone`, `onMissingDay` (default `"lastDayOfMonth"`) | `intervalHours`, `minuteOfHour`, `daysOfWeek` |
|
|
70
|
+
|
|
71
|
+
`time` is `HH:MM` 24-hour local. `timezone` is an IANA zone
|
|
72
|
+
(`Asia/Tokyo`, `America/New_York`, `UTC`); auto-filled from daemon
|
|
73
|
+
config when omitted, but explicit is safer so a roaming laptop does
|
|
74
|
+
not surprise the user. The error envelope cites `validValues` on
|
|
75
|
+
every range / format failure — read it and resubmit instead of
|
|
76
|
+
guessing.
|
|
77
|
+
|
|
78
|
+
### Hourly anchor semantics
|
|
79
|
+
|
|
80
|
+
`intervalHours=N` fires when `(localHour % N) == 0` at
|
|
81
|
+
`minuteOfHour` local. The anchor is **local midnight** in the rule's
|
|
82
|
+
`timezone`, so `intervalHours:2, minuteOfHour:30` fires at 00:30,
|
|
83
|
+
02:30, …, 22:30 local — predictable for the user's mental model.
|
|
84
|
+
|
|
85
|
+
| Intent | `recurrenceRule` |
|
|
86
|
+
|---|---|
|
|
87
|
+
| Every hour at :00 | `{frequency:"hourly"}` |
|
|
88
|
+
| Every hour at :15 | `{frequency:"hourly", minuteOfHour:15}` |
|
|
89
|
+
| Every 2 hours at :30 | `{frequency:"hourly", intervalHours:2, minuteOfHour:30}` |
|
|
90
|
+
| Every 6 hours at :00 (Asia/Tokyo) | `{frequency:"hourly", intervalHours:6, timezone:"Asia/Tokyo"}` |
|
|
91
|
+
|
|
92
|
+
DST: in zones that observe it, a skipped local hour drops one fire;
|
|
93
|
+
a doubled local hour fires once. Accepted edge case — do not try to
|
|
94
|
+
compensate from the caller.
|
|
95
|
+
|
|
96
|
+
Use hourly sparingly. Sub-hour cadences are not representable (the
|
|
97
|
+
minimum is 1 hour); pick a coarser cadence or move the work into a
|
|
98
|
+
daemon-internal poller instead.
|
|
99
|
+
|
|
100
|
+
### Monthly missing-day semantics
|
|
101
|
+
|
|
102
|
+
Some months don't contain the day the user asked for (Feb 30, Apr
|
|
103
|
+
31). `onMissingDay` controls what happens that month:
|
|
104
|
+
|
|
105
|
+
- `"skip"` — don't fire that month for the missing day.
|
|
106
|
+
- `"lastDayOfMonth"` (default) — fire on the actual last day of the
|
|
107
|
+
month. Preserves the pre-redesign clamp behavior, so existing
|
|
108
|
+
recurring rules created before this redesign keep firing
|
|
109
|
+
bit-identically.
|
|
110
|
+
|
|
111
|
+
The engine de-duplicates calendar dates that collapse to the same
|
|
112
|
+
fire (e.g. `daysOfMonth:[28,31]` in non-leap Feb with
|
|
113
|
+
`"lastDayOfMonth"` lands on Feb 28 once, not twice).
|
|
114
|
+
|
|
115
|
+
| Recipe | `recurrenceRule` |
|
|
116
|
+
|---|---|
|
|
117
|
+
| 25th of every month at 21:00 | `{frequency:"monthly", time:"21:00", daysOfMonth:[25]}` |
|
|
118
|
+
| 31st at 21:00, skip Feb/Apr/Jun/Sep/Nov | `{frequency:"monthly", time:"21:00", daysOfMonth:[31], onMissingDay:"skip"}` |
|
|
119
|
+
| 31st at 21:00, fall back to last day | `{frequency:"monthly", time:"21:00", daysOfMonth:[31], onMissingDay:"lastDayOfMonth"}` |
|
|
120
|
+
| **Last day of every month at 21:00** | same as above — `daysOfMonth:[31] + onMissingDay:"lastDayOfMonth"` clamps Feb/Apr/Jun/Sep/Nov to their last day; the 31st of every other month is already that month's last day |
|
|
121
|
+
| 29th at 21:00, skip non-leap Feb | `{frequency:"monthly", time:"21:00", daysOfMonth:[29], onMissingDay:"skip"}` |
|
|
122
|
+
| 1st AND 15th at 10:00 | `{frequency:"monthly", time:"10:00", daysOfMonth:[1,15]}` |
|
|
123
|
+
|
|
124
|
+
When `daysOfMonth` contains 29/30/31 and `onMissingDay` is omitted,
|
|
125
|
+
the daemon returns a `warnings[]` entry nudging you to be explicit.
|
|
126
|
+
Persistence still happens — the warning is advisory.
|
|
127
|
+
|
|
128
|
+
Response: `{ "status":"created", "item":{ "id","recurrenceRule","recurrenceLabel","nextRunAt",...}, "warnings":[] }`. `nextRunAt` is the UTC timestamp the engine has materialized as the first one-shot row's `scheduled_for`. `recurrenceLabel` is the human-readable form rendered into `rules/management.md` §B (e.g. `"Every 2 hours at :30 (UTC)"`, `"Monthly on the 31st at 21:00 (Asia/Tokyo); falls back to last day of month"`).
|
|
129
|
+
|
|
130
|
+
## GET /api/recurring-schedules — List
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
curl -s "http://localhost:8321/api/recurring-schedules?enabled=true"
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Response: `{ "items":[{ "id","taskType","description","recurrenceRule","enabled","nextRunAt","recurrenceLabel","model","backendId","tier","taskContext" }] }`. `model` / `backendId` are populated together when the row pins a registered id; otherwise `model:null, backendId:null` and `tier` carries the pin (or all three are null and the row inherits the dispatcher's process-key default).
|
|
137
|
+
|
|
138
|
+
## PATCH /api/recurring-schedules/:id — Update
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
# Swap a daily rule to hourly + change model to Opus in one PATCH
|
|
142
|
+
curl -s -X PATCH http://localhost:8321/api/recurring-schedules/1 \
|
|
143
|
+
-H 'Content-Type: application/json' \
|
|
144
|
+
-d '{"recurrenceRule":{"frequency":"hourly","intervalHours":2,"minuteOfHour":0},"tier":null,"model":"claude-opus-4-7"}'
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Updatable: `recurrenceRule`, `description`, `prompt` (string sets an
|
|
148
|
+
override, `null` clears), `tier` (set / `null` to clear), `model`
|
|
149
|
+
(set / `null` to clear), `taskContext`, `enabled`. Changing
|
|
150
|
+
`recurrenceRule` / `enabled` auto-reschedules — the pending one-shot
|
|
151
|
+
row tied to the old rule is cancelled and a fresh row is materialized
|
|
152
|
+
from the new `recurrenceRule` value, preserving the parent's
|
|
153
|
+
`(model, backend_id)` or `tier` pin.
|
|
154
|
+
|
|
155
|
+
**Tier ↔ model swap.** Pass `null` to clear one and a concrete value
|
|
156
|
+
to set the other in the same request — the row carries at most one
|
|
157
|
+
pin at rest. Setting a registered `model` token also clears any
|
|
158
|
+
prior `tier_override`. Setting a legacy alias (`sonnet` / `opus`) on
|
|
159
|
+
PATCH is rewritten to `tier:"medium"` / `tier:"high"`; the alias is
|
|
160
|
+
never stored verbatim.
|
|
161
|
+
|
|
162
|
+
**Re-materialization scope.** Changing `model` / `tier` alone does
|
|
163
|
+
**not** re-point the already-materialized pending one-shot row — only
|
|
164
|
+
`recurrenceRule` / `enabled` re-materialize. Delete the pending row
|
|
165
|
+
(`DELETE /api/schedule/:id`) and let the next reconcile pass pick up
|
|
166
|
+
the new pin, or PATCH `/api/schedule/:id` directly if you need the
|
|
167
|
+
pending row repointed now.
|
|
168
|
+
|
|
169
|
+
Set `{"enabled":false}` to pause without deleting. Surface
|
|
170
|
+
`warnings[]` (e.g. `schedule.model_deprecated`,
|
|
171
|
+
`schedule.on_missing_day_unused`) to the next turn — the PATCH still
|
|
172
|
+
succeeds but the warning carries replacement guidance.
|
|
173
|
+
|
|
174
|
+
## DELETE /api/recurring-schedules/:id — Delete
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
curl -s -X DELETE http://localhost:8321/api/recurring-schedules/1
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Deletes the rule and cancels every materialized pending instance.
|
|
181
|
+
Response: `{ "status":"deleted", "id":1 }`.
|
|
182
|
+
|
|
183
|
+
Use pause (`PATCH ... {"enabled":false}`) instead when the user might
|
|
184
|
+
want to resume the same cadence later — DELETE loses the
|
|
185
|
+
`recurrenceRule` shape and the `taskContext` payload.
|
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: scheduled-managed-task
|
|
3
|
-
description:
|
|
4
|
-
when_to_use: A `scheduled.task` session with `task_context.mt_id` matching `mt_<n>`; `task_context.adhoc === true` marks on-demand pulls. SKIP for regular scheduled tasks, DM-tone scheduled sessions (`scheduled.dm`), or one-off reminder delivery.
|
|
3
|
+
description: A `scheduled.task` session with `task_context.mt_id` matching `mt_<n>`; `task_context.adhoc === true` marks on-demand pulls. SKIP for regular scheduled tasks, DM-tone scheduled sessions (`scheduled.dm`), or one-off reminder delivery.
|
|
5
4
|
allowed-tools:
|
|
6
5
|
- Bash(curl *)
|
|
7
|
-
- Bash(jq *)
|
|
8
6
|
- Read
|
|
9
7
|
---
|
|
10
8
|
|
|
11
9
|
# Scheduled Managed-Task Run
|
|
12
10
|
|
|
13
11
|
This skill is the **scheduled execution** half of the management
|
|
14
|
-
registry. The DM-side
|
|
15
|
-
`
|
|
16
|
-
lifecycle. This skill is what fires every cron slot to actually
|
|
17
|
-
the work.
|
|
12
|
+
registry. The DM-side counterpart — the `managed-tasks` skill
|
|
13
|
+
(`## Register` / `## Modify` / `## Stop` / `## Run once`) — owns the
|
|
14
|
+
row's lifecycle. This skill is what fires every cron slot to actually
|
|
15
|
+
do the work.
|
|
18
16
|
|
|
19
17
|
## When this skill activates
|
|
20
18
|
|
|
@@ -72,8 +70,8 @@ records the orphan firing.
|
|
|
72
70
|
|
|
73
71
|
### Step 2 — Select tool (LLM judgment, fresh each run)
|
|
74
72
|
|
|
75
|
-
Same rule as `
|
|
76
|
-
tools available to this session and pick by capability for
|
|
73
|
+
Same rule as the `managed-tasks` skill's `## Register` Step 3:
|
|
74
|
+
enumerate the tools available to this session and pick by capability for
|
|
77
75
|
`item.app`. The user's prior choice (when surfaced as a hint in
|
|
78
76
|
`task_context.lastToolChoice` by an earlier run) is a **hint**, not
|
|
79
77
|
a binding — if it no longer exists in this session (the user
|
|
@@ -146,9 +144,9 @@ output_path = "finance/receipts/" → domain=finance, type=receipt
|
|
|
146
144
|
```
|
|
147
145
|
|
|
148
146
|
If `output_path` is null (first run), pick the best `(domain, type)`
|
|
149
|
-
from the data shape using the same prior table from
|
|
150
|
-
`
|
|
151
|
-
|
|
147
|
+
from the data shape using the same prior table from the `managed-tasks`
|
|
148
|
+
skill `## Register` Step 4a. After this run, write the chosen path back
|
|
149
|
+
to the row (Step 5b) so subsequent runs converge.
|
|
152
150
|
|
|
153
151
|
Slug: `<YYYY-MM-DD>-<sanitized-title>`. Sanitization rules:
|
|
154
152
|
lowercase, ASCII-fold, replace `[^a-z0-9-]+` with `-`, collapse
|
|
@@ -256,8 +254,8 @@ audit shape.
|
|
|
256
254
|
If the run produced a mix of domains/types (e.g. Drive PDFs that were
|
|
257
255
|
half receipts and half random docs), leave `output_path` null — let
|
|
258
256
|
the next run try again. The renderer marks null-path rows in §B with
|
|
259
|
-
an em-dash; the user can also set the path explicitly via
|
|
260
|
-
`
|
|
257
|
+
an em-dash; the user can also set the path explicitly via the
|
|
258
|
+
`managed-tasks` skill `## Modify` flow.
|
|
261
259
|
|
|
262
260
|
### Step 6 — Three-strikes notify
|
|
263
261
|
|
|
@@ -359,7 +357,7 @@ appended `## <App> Notes` body, not as a separate DM.
|
|
|
359
357
|
daemon owns the threshold notify, the agent emits one DM at the
|
|
360
358
|
3rd consecutive failure, then stays silent until success or stop.
|
|
361
359
|
- Does NOT touch the §B row's `app` or `cadence` — those are
|
|
362
|
-
user-mutable only via `
|
|
360
|
+
user-mutable only via the `managed-tasks` skill `## Modify` flow.
|
|
363
361
|
- Does NOT INSERT `agent_schedule` rows. The cron scheduler does.
|
|
364
362
|
- Does NOT delete entity files when a tool returns "this item was
|
|
365
363
|
removed upstream". Removal-from-source is recorded as a
|
|
@@ -8,10 +8,7 @@ allowed-tools:
|
|
|
8
8
|
|
|
9
9
|
# today.md Guide
|
|
10
10
|
|
|
11
|
-
Output language:
|
|
12
|
-
Policy B — the **skeleton lines listed below stay English verbatim**;
|
|
13
|
-
bullets, narrative, and free-text fields under each H2 are written in
|
|
14
|
-
`<settings primary_language>`. Preserve user-customized headers verbatim.
|
|
11
|
+
Output language: today.md is Policy B — see `<output_language_policy>`. The skeleton lines listed below stay English verbatim; bullets and narrative under each H2 are in `<settings primary_language>`.
|
|
15
12
|
|
|
16
13
|
**Skeleton (do NOT translate — exact-regex-validated on PUT):**
|
|
17
14
|
|
|
@@ -143,28 +140,16 @@ Violations: row without schedule → silently never fires. Schedule without row
|
|
|
143
140
|
|
|
144
141
|
## Agent Plan lifecycle — close the loop
|
|
145
142
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
-H 'Content-Type: application/json' \
|
|
157
|
-
-d '{"section": "agent_plan", "mode": "replace", "content": "- [x] 08:55 ..."}'
|
|
158
|
-
```
|
|
159
|
-
**Read-before-write is mandatory** — PATCH replace replaces the entire section.
|
|
160
|
-
4. If the Agent Plan row is missing (user hand-edited), log and skip.
|
|
161
|
-
5. Always flip to `[x]`, even for skips/failures — annotate non-success:
|
|
162
|
-
- Success: no annotation
|
|
163
|
-
- Skip: `⚠ skipped: <reason>`
|
|
164
|
-
- Failure: `⚠ failed: <reason>`
|
|
165
|
-
6. If PATCH returns 409 (Morning Routine lock), retry after 30s up to 3 times. If still locked, log `loop-closeout deferred`.
|
|
166
|
-
|
|
167
|
-
**Why flip inside the scheduled task, not later?** The user may DM at 09:00 asking "did you send the reminder?" — if the row is still `[ ]`, the DM handler can't tell whether it was sent.
|
|
143
|
+
`scheduled.task` and `scheduled.dm` (and any other event that flips an
|
|
144
|
+
Agent Plan row) follow the close-the-loop lifecycle in the reference
|
|
145
|
+
below: execute, append Agent Log entry, read-then-flip the row to
|
|
146
|
+
`[x]` with annotation, retry on `today.md` lock, surface missing-row
|
|
147
|
+
state.
|
|
148
|
+
|
|
149
|
+
DM handlers and hourly checks do not flip Agent Plan rows — read the
|
|
150
|
+
reference only if your event type is in its applicability list.
|
|
151
|
+
|
|
152
|
+
{{> ref:agent-plan-lifecycle }}
|
|
168
153
|
|
|
169
154
|
## Agent Log format
|
|
170
155
|
|
|
@@ -193,7 +178,7 @@ so the LLM never sees this format-using event with a wider lookahead.
|
|
|
193
178
|
No additional gate is restated here.
|
|
194
179
|
|
|
195
180
|
**Agent Notes**:
|
|
196
|
-
`-
|
|
181
|
+
`- event_title starts at HH:MM [— blocks/relates to: <task>]`
|
|
197
182
|
|
|
198
183
|
**Agent Log** (always):
|
|
199
184
|
`- HH:MM [cal] event_title — action`
|
|
@@ -204,36 +189,21 @@ Morning Routine acquires exclusive lock. Other sessions get 409 on PUT/PATCH (GE
|
|
|
204
189
|
|
|
205
190
|
PUT today.md must contain the H1 date line, day-type header quote, and all six sections in order.
|
|
206
191
|
|
|
207
|
-
## today.md API
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
submission
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
-
|
|
222
|
-
-H 'X-Lock-Id: <today_write_lock_id>' \
|
|
223
|
-
-d @- <<'JSON'
|
|
224
|
-
{"content":"# 2026-04-02 (Thursday)\n> Day type: Weekday | Work focus: on | Study focus: on | Personal focus: on\n\n## User Schedule\n- 14:00–15:00 Design review [work]\n\n## User Tasks\n- [ ] 11:00 Finalize Q2 draft [work]\n\n## Agent Plan\n- [ ] 08:55 DM reminder: standup [work] →DM\n\n## Agent Notes\n\n## Agent Log\n- 04:00 Morning Routine completed (day-type: Weekday)\n\n## Handoff\n- (none)\n"}
|
|
225
|
-
JSON
|
|
226
|
-
|
|
227
|
-
# Section operation — small body, inline `-d` is fine.
|
|
228
|
-
curl -s -X PATCH http://localhost:8321/api/context/today \
|
|
229
|
-
-H 'Content-Type: application/json' \
|
|
230
|
-
-H 'X-Lock-Id: <today_write_lock_id>' \
|
|
231
|
-
-d '{"section":"agent_log","mode":"append","content":"- 09:35 ..."}'
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
The H1 date and the `> Day type:` quote line are validated by exact
|
|
235
|
-
regex on PUT — keep both English-shaped exactly as the template. See
|
|
236
|
-
context skill for the full endpoint reference.
|
|
192
|
+
## today.md API
|
|
193
|
+
|
|
194
|
+
The generic GET / PUT / PATCH / DELETE surface — modes, fields, error
|
|
195
|
+
envelopes, body-submission shape — is documented in the **context**
|
|
196
|
+
skill `references/api.md`. today.md-specific rules layered on top:
|
|
197
|
+
|
|
198
|
+
- **Lock.** `today.md` is locked by the Morning Routine. Include
|
|
199
|
+
`X-Lock-Id: <today_write_lock_id>` on every PUT / PATCH when the
|
|
200
|
+
tag is in your context; other sessions get `409
|
|
201
|
+
today_write_lock_held` while the lock is held.
|
|
202
|
+
- **Skeleton validators.** PUT is rejected (400) if line 1 fails the
|
|
203
|
+
H1 date regex or line 2 fails the day-type quote regex (see §"Line 1
|
|
204
|
+
— which date?" and §"Header line — day-type filter" above). PUT is
|
|
205
|
+
rejected (422) if line 1's date disagrees with the daemon's current
|
|
206
|
+
agent-day — the error echoes both values.
|
|
237
207
|
|
|
238
208
|
## Knowledge map — section shape (auto-curated)
|
|
239
209
|
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
---
|
|
2
|
+
kind: reference
|
|
3
|
+
name: agent-plan-lifecycle
|
|
4
|
+
description: Agent Plan close-the-loop lifecycle for scheduled.task / scheduled.dm sessions — execute, log, flip [x], handle missing rows / failures / lock retries.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Agent Plan lifecycle — close the loop
|
|
8
|
+
|
|
9
|
+
This reference is consumed by `scheduled.task`, `scheduled.dm`,
|
|
10
|
+
`routine.morning_routine`, and `routine.evening_review` — every event
|
|
11
|
+
that may flip an Agent Plan row. DM handlers and hourly checks never
|
|
12
|
+
flip Agent Plan rows; if you are not one of the listed events, the
|
|
13
|
+
lifecycle below does not apply to your turn.
|
|
14
|
+
|
|
15
|
+
## Why flip inside the scheduled task, not later?
|
|
16
|
+
|
|
17
|
+
The user may DM at 09:00 asking "did you send the reminder?" — if the
|
|
18
|
+
matching Agent Plan row is still `[ ]`, the DM handler cannot tell
|
|
19
|
+
whether the reminder was sent. The flip must land in the same turn as
|
|
20
|
+
the action it represents, before the session exits.
|
|
21
|
+
|
|
22
|
+
## Steps (when spawned by `scheduled.task` for an Agent Plan row)
|
|
23
|
+
|
|
24
|
+
1. **Execute the task.** Send the DM, fire the notification, run the
|
|
25
|
+
check-in — whatever the row's action text describes. The row's
|
|
26
|
+
trigger tag (`→DM`, `→notify`, `→check-in`, `→wake`) selects the
|
|
27
|
+
API surface (see `today` skill §"Entry formats").
|
|
28
|
+
|
|
29
|
+
2. **Append an Agent Log entry** describing the outcome:
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
- HH:MM [agent_plan] <action> — <outcome>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Outcomes (use exactly one, lowercase):
|
|
36
|
+
- `DM sent`
|
|
37
|
+
- `notify sent`
|
|
38
|
+
- `check-in done`
|
|
39
|
+
- `wake fired`
|
|
40
|
+
- `skipped (<reason>)` — e.g. `skipped (user in meeting)`,
|
|
41
|
+
`skipped (focus off)`, `skipped (deduped)`
|
|
42
|
+
- `failed: <reason>` — short, single-line, no stack trace
|
|
43
|
+
|
|
44
|
+
Agent Log entries are mandatory before the flip, not after. If the
|
|
45
|
+
PATCH that flips the row to `[x]` fails, the log entry is the only
|
|
46
|
+
record that the action ran.
|
|
47
|
+
|
|
48
|
+
3. **Read today.md, locate the matching Agent Plan row** (match HH:MM
|
|
49
|
+
+ action text), and flip `[ ]` → `[x]`:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
curl -s http://localhost:8321/api/context/today
|
|
53
|
+
# Find the agent_plan section. Edit the matching row's checkbox.
|
|
54
|
+
# Then PATCH the full updated section body:
|
|
55
|
+
curl -s -X PATCH http://localhost:8321/api/context/today \
|
|
56
|
+
-H 'Content-Type: application/json' \
|
|
57
|
+
-H 'X-Lock-Id: <today_write_lock_id>' \
|
|
58
|
+
-d '{"section": "agent_plan", "mode": "replace", "content": "<full merged section>"}'
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Read-before-write is mandatory** — `PATCH mode: "replace"` replaces
|
|
62
|
+
the entire section body. Send only the flipped row and you erase
|
|
63
|
+
every other Agent Plan row.
|
|
64
|
+
|
|
65
|
+
4. **If the Agent Plan row is missing** (user hand-edited, row was
|
|
66
|
+
pruned by Evening Review, race with a concurrent rewrite), log
|
|
67
|
+
`skipped (row_missing)` to Agent Log and exit. Do not append a
|
|
68
|
+
new row to back-fill — the row's absence is informative state.
|
|
69
|
+
|
|
70
|
+
## Flip-to-[x] cardinality rule
|
|
71
|
+
|
|
72
|
+
**Always flip to `[x]`, even for skips and failures.** The cardinality
|
|
73
|
+
rule is: every Agent Plan row reaches exactly one terminal state per
|
|
74
|
+
agent-day, and that state is `[x]`. Annotate the non-success cases in
|
|
75
|
+
parentheses appended to the action text:
|
|
76
|
+
|
|
77
|
+
| Outcome | Row content after flip |
|
|
78
|
+
|---|---|
|
|
79
|
+
| Success | `- [x] HH:MM <action> [category] →<trigger>` (no annotation) |
|
|
80
|
+
| Skip | `- [x] HH:MM <action> [category] →<trigger> (skipped: <reason>)` |
|
|
81
|
+
| Failure | `- [x] HH:MM <action> [category] →<trigger> (failed: <reason>)` |
|
|
82
|
+
|
|
83
|
+
Leaving rows as `[ ]` is a bug: Morning Routine's reconciliation
|
|
84
|
+
treats unflipped past rows as "scheduler dropped the wake", which
|
|
85
|
+
triggers self-recovery and inflates the agent-actions audit.
|
|
86
|
+
|
|
87
|
+
## Lock retry rules
|
|
88
|
+
|
|
89
|
+
The Morning Routine holds the `today.md` write lock. Other sessions
|
|
90
|
+
get `409 today_write_lock_held` on PUT / PATCH while the lock is held.
|
|
91
|
+
|
|
92
|
+
- Detect by the response body `{"error":"lock_held"}` or by the
|
|
93
|
+
status code 409 alone.
|
|
94
|
+
- Retry policy: 30 s back-off, max 3 attempts. If the third attempt
|
|
95
|
+
also returns 409, log `loop-closeout deferred (lock_held)` to Agent
|
|
96
|
+
Log and exit. The next Evening Review reconciliation will catch the
|
|
97
|
+
un-flipped row.
|
|
98
|
+
- Do NOT retry without the `X-Lock-Id` header when the tag is in
|
|
99
|
+
context. Sending a PATCH without the header during a held-lock
|
|
100
|
+
window returns 409 even though you would have been allowed in
|
|
101
|
+
during a no-lock window.
|
|
102
|
+
|
|
103
|
+
## What this lifecycle does NOT cover
|
|
104
|
+
|
|
105
|
+
- Agent Notes flavors and their flips (`Profile question (latent)` ↔
|
|
106
|
+
`Profile question (asked HH:MM)`) — those live in the
|
|
107
|
+
`user-interview` skill, not in this lifecycle.
|
|
108
|
+
- The schedule.approaching → Agent Notes / Agent Log format — that
|
|
109
|
+
is in the `today` skill body (§"schedule.approaching → Agent Notes
|
|
110
|
+
+ Agent Log"), not here. The 15-minute firing gate is the daemon's,
|
|
111
|
+
not the skill's.
|
|
112
|
+
- The Morning Routine's initial population of Agent Plan rows — see
|
|
113
|
+
the morning routine task-flow.
|