Skip to content

Commit 29f33b9

Browse files
committed
Merge remote-tracking branch 'origin/main' into feat/skilldoc-dedupe-response-shapes
2 parents 237e0ab + e8b8e77 commit 29f33b9

3 files changed

Lines changed: 28 additions & 24 deletions

File tree

internal/cli/automation.go

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313
)
1414

1515
const automationHTTPPostOnlyCron = "0 0 * * *"
16-
const automationUTCNote = "Convert local wall-clock requests to UTC before passing --at or --cron-expr."
16+
const automationTimezoneNote = "The rule's timezone defaults to the caller's member timezone, then the account timezone; pass the user's local wall-clock time here, do not convert it to UTC."
1717

1818
func newAutomationCmd() *cobra.Command {
1919
cmd := newGroupCmd("automation", "Manage AI SRE Automations")
@@ -60,9 +60,11 @@ By default the rule is enabled. Use --disabled only when the user explicitly
6060
asks to create it disabled. team_id=0 means personal scope; --team-id >0 creates
6161
the rule under that team. The scope is immutable after creation.
6262
63-
Schedule helpers build a 5-field UTC cron expression. --at and --cron-expr are
64-
interpreted in UTC, not the caller's local timezone. Convert local wall-clock
65-
requests to UTC before passing --at or --cron-expr.
63+
Schedule helpers build a 5-field cron expression evaluated in the rule's
64+
timezone, which defaults to the caller's member timezone, then the account
65+
timezone. Pass the user's local wall-clock time to --at or --cron-expr;
66+
do not convert it to UTC first. This command has no --timezone flag; use
67+
safari automation-rule-create --timezone to pin a different one.
6668
6769
For HTTP POST-only rules, pass --http-post-trigger without a schedule; the CLI
6870
sends a valid placeholder cron and disables the schedule trigger.`, "Automations", "RuleWriteCreate"),
@@ -111,10 +113,10 @@ the rule under that team. The scope is immutable after creation.
111113

112114
cmd.Flags().StringVar(&name, "name", "", "Automation name")
113115
cmd.Flags().Int64Var(&teamID, "team-id", 0, "Scope team ID; 0 means personal scope")
114-
cmd.Flags().StringVar(&schedule, "schedule", "", "UTC schedule helper: hourly, daily, weekly, or cron")
115-
cmd.Flags().StringVar(&at, "at", "", "UTC time in HH:MM; for hourly schedules, only the minute is used. "+automationUTCNote)
116+
cmd.Flags().StringVar(&schedule, "schedule", "", "Schedule helper: hourly, daily, weekly, or cron")
117+
cmd.Flags().StringVar(&at, "at", "", "Local time in HH:MM (rule's timezone); for hourly schedules, only the minute is used. "+automationTimezoneNote)
116118
cmd.Flags().StringVar(&weekday, "weekday", "", "Weekday for weekly schedules: sun, mon, tue, wed, thu, fri, sat, or 0-7")
117-
cmd.Flags().StringVar(&cronExpr, "cron-expr", "", "Exact 5-field UTC cron expression; overrides --schedule helpers. "+automationUTCNote)
119+
cmd.Flags().StringVar(&cronExpr, "cron-expr", "", "Exact 5-field cron expression in the rule's timezone; overrides --schedule helpers. "+automationTimezoneNote)
118120
cmd.Flags().BoolVar(&disabled, "disabled", false, "Create the Automation disabled")
119121
cmd.Flags().BoolVar(&scheduleEnabled, "schedule-enabled", true, "Whether the schedule trigger is enabled")
120122
cmd.Flags().BoolVar(&httpPostTrigger, "http-post-trigger", false, "Create and enable an HTTP POST trigger")
@@ -221,9 +223,11 @@ func newAutomationUpdateCmd() *cobra.Command {
221223
The personal/team scope is intentionally not exposed here. Scope is immutable
222224
after creation; create a new Automation if the target person/team scope needs to change.
223225
224-
Schedule helpers build a 5-field UTC cron expression. --at and --cron-expr are
225-
interpreted in UTC, not the caller's local timezone. Convert local wall-clock
226-
requests to UTC before passing --at or --cron-expr.`, "Automations", "RuleWriteUpdate"),
226+
Schedule helpers build a 5-field cron expression evaluated in the rule's
227+
timezone, set at creation from the caller's member timezone, then the account
228+
timezone. Pass the user's local wall-clock time to --at or --cron-expr;
229+
do not convert it to UTC first. This command has no --timezone flag; the
230+
rule's timezone cannot be changed after creation.`, "Automations", "RuleWriteUpdate"),
227231
Example: ` flashduty automation update auto_123 --name "Daily brief v2" --cron-expr "15 1 * * *"
228232
flashduty automation update auto_123 --disable
229233
flashduty automation update auto_123 --enable-http-post-trigger --rotate-http-post-token`,
@@ -315,10 +319,10 @@ func newAutomationUpdateCmd() *cobra.Command {
315319
}
316320

317321
cmd.Flags().StringVar(&name, "name", "", "New Automation name")
318-
cmd.Flags().StringVar(&schedule, "schedule", "", "UTC schedule helper: hourly, daily, weekly, or cron")
319-
cmd.Flags().StringVar(&at, "at", "", "UTC time in HH:MM; for hourly schedules, only the minute is used. "+automationUTCNote)
322+
cmd.Flags().StringVar(&schedule, "schedule", "", "Schedule helper: hourly, daily, weekly, or cron")
323+
cmd.Flags().StringVar(&at, "at", "", "Local time in HH:MM (rule's timezone); for hourly schedules, only the minute is used. "+automationTimezoneNote)
320324
cmd.Flags().StringVar(&weekday, "weekday", "", "Weekday for weekly schedules: sun, mon, tue, wed, thu, fri, sat, or 0-7")
321-
cmd.Flags().StringVar(&cronExpr, "cron-expr", "", "Exact 5-field UTC cron expression; overrides --schedule helpers. "+automationUTCNote)
325+
cmd.Flags().StringVar(&cronExpr, "cron-expr", "", "Exact 5-field cron expression in the rule's timezone; overrides --schedule helpers. "+automationTimezoneNote)
322326
cmd.Flags().BoolVar(&enableRule, "enable", false, "Enable the Automation")
323327
cmd.Flags().BoolVar(&disableRule, "disable", false, "Disable the Automation")
324328
cmd.Flags().BoolVar(&enableSchedule, "enable-schedule", false, "Enable the schedule trigger")

internal/cli/automation_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func TestAutomationCreateDailyDefaultsEnabled(t *testing.T) {
3434
assertBody(t, stub.lastBody, "prompt", "Summarize yesterday's incidents")
3535
}
3636

37-
func TestAutomationScheduleHelpDocumentsUTC(t *testing.T) {
37+
func TestAutomationScheduleHelpDocumentsTimezone(t *testing.T) {
3838
saveAndResetGlobals(t)
3939

4040
for _, args := range [][]string{
@@ -46,8 +46,8 @@ func TestAutomationScheduleHelpDocumentsUTC(t *testing.T) {
4646
t.Fatalf("%v unexpected error: %v", args, err)
4747
}
4848
for _, want := range []string{
49-
"UTC",
50-
"Convert local wall-clock requests to UTC before passing --at or --cron-expr.",
49+
"do not convert it to UTC",
50+
automationTimezoneNote,
5151
} {
5252
if !strings.Contains(out, want) {
5353
t.Fatalf("%v help missing %q\n%s", args, want, out)

skills/flashduty/reference/automation.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@ Prereq: `SKILL.md` read. Automations create AI SRE sessions on a schedule or thr
2929
## Scheduling
3030

3131
- Default create behavior: enabled immediately. Use `--disabled` only if the user asks for a disabled Automation.
32-
- No timezone flag is exposed by the current API. Automation schedules are stored and sent as UTC cron.
33-
- If the user asks for a local wall-clock schedule, first identify the intended timezone from the session context, runner `date`, or the user's wording. Convert that local time to UTC before calling the CLI. If the timezone is unclear, ask before creating or updating the schedule.
34-
- Helper schedules:
35-
- `--schedule hourly --at 00:15` -> minute 15 of every UTC hour.
36-
- `--schedule daily --at 01:30` -> every day at 01:30 UTC.
37-
- `--schedule weekly --weekday mon --at 02:00` -> every Monday at 02:00 UTC.
38-
- For exact minute-level control, use `--cron-expr '<minute> <hour> <day> <month> <weekday>'` in UTC.
39-
- Example: Asia/Shanghai 11:00 is UTC 03:00, so use `--schedule daily --at 03:00` or `--cron-expr "0 3 * * *"`.
32+
- `create`/`update` expose no `--timezone` flag. The cron expression runs in the rule's timezone, which the server resolves from the caller's member timezone, then the account timezone (a server-side default applies when neither is set).
33+
- Pass the user's local wall-clock time directly to `--at` or `--cron-expr` — do not convert it to UTC first. The rule already runs in the caller's own resolved timezone, so a manual UTC conversion shifts the schedule by the account's UTC offset.
34+
- Helper schedules (times are in the rule's resolved timezone, not UTC):
35+
- `--schedule hourly --at 00:15` -> minute 15 of every hour.
36+
- `--schedule daily --at 01:30` -> every day at 01:30.
37+
- `--schedule weekly --weekday mon --at 02:00` -> every Monday at 02:00.
38+
- For exact minute-level control, use `--cron-expr '<minute> <hour> <day> <month> <weekday>'` in that same local time.
39+
- To pin a rule to a specific timezone (e.g. UTC) regardless of the caller's default, use `safari automation-rule-create --timezone <IANA tz>` instead — the curated `create`/`update` commands cannot set it, and `update` cannot change it after creation.
4040
- HTTP POST-only rule: pass `--http-post-trigger` without schedule flags. The CLI sends a placeholder cron and disables the schedule trigger.
4141

4242
## Hot flow - create from chat

0 commit comments

Comments
 (0)