scheduled prompts: refresh stale docs for target edits (#478)

This commit is contained in:
damocles 2026-05-26 16:21:57 +02:00 committed by Mara
commit 2bf90c9db2
2 changed files with 25 additions and 12 deletions

View file

@ -1368,9 +1368,12 @@ impl ManagerServer {
description = "Edit an existing scheduled prompt's mutable fields (#474). Pass only \
the fields you want to change anything omitted keeps its current value. Editable: \
`body`, `description`, `interval_seconds` (positive only via this tool; flipping \
recurringone-shot is operator-only via the dashboard), `next_fire_at_unix`. \
Targets are immutable: per-target last-result history is keyed on them. To change \
the recipient list, cancel and submit a new schedule. \n\n\
recurringone-shot is operator-only via the dashboard), `next_fire_at_unix`, and \
the target set via `targets_add` / `targets_remove` (#478). Both target lists are \
applied in the same transaction with removes-before-adds, so a single edit can \
swap a target atomically. Re-adding a previously-removed target starts a fresh \
per-target history (drops the tombstone). Draining all targets auto-cancels the \
parent schedule. \n\n\
Authorization mirrors `cancel_schedule` / `fire_schedule_now`: you can edit your \
own schedules + any owned by a sub-agent in your subtree per topology.json. \
Refuses cancelled schedules (the row's terminal submit a fresh one)."

View file

@ -360,15 +360,25 @@ impl ScheduledPrompts {
}
/// Partial-update an existing schedule's mutable fields (#474).
/// Every field is `Option<_>`; `None` means "leave the existing
/// value alone", `Some(_)` means "set it to this." Refuses
/// cancelled rows (no point editing a tombstone — operator can
/// just submit a new schedule). Refuses `interval_seconds = Some(0)`
/// — same rule as submit-time validation. Targets stay
/// immutable: per-target last-result history is keyed on
/// (schedule_id, target); changing the target set would orphan
/// or duplicate history rows. Operator workaround for "I want
/// different targets" is cancel-target + submit a new schedule.
/// Every scalar field is `Option<_>`; `None` means "leave the
/// existing value alone", `Some(_)` means "set it to this."
/// Refuses cancelled rows (no point editing a tombstone —
/// operator can just submit a new schedule). Refuses
/// `interval_seconds = Some(0)` — same rule as submit-time
/// validation.
///
/// Targets are mutable via `targets_remove` + `targets_add`
/// (#478 fast-follow). Both are processed in the same
/// transaction, with **removes before adds** so a single PATCH
/// can swap a target without ever leaving the schedule
/// target-less mid-tx. Remove writes a tombstone via
/// `COALESCE(cancelled_at_unix, ?1)` so it's idempotent. Add
/// uses `INSERT OR REPLACE` so re-adding a previously-removed
/// target drops the tombstone and resets per-target history
/// (fresh start — option C from the iris design thread). If
/// the post-tx active-target count is zero the parent schedule
/// is auto-cancelled — the worker would otherwise spin forever
/// firing nothing.
pub fn update(&self, id: i64, patch: UpdateSchedule) -> Result<()> {
// Pre-flight: row must exist and not be cancelled.
let mut conn = self.conn.lock().unwrap();