From ddf554d7acd93902867f1670ed4d24c00033c429 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 28 Apr 2026 11:57:38 +0000 Subject: [PATCH 1/3] Initial plan From 1752dc8552184b9e6556421e3d2313fbd711dd58 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 28 Apr 2026 12:13:50 +0000 Subject: [PATCH 2/3] fix: handle 'every day [at HH:MM]' in ParseSchedule and fix testifylint warning Agent-Logs-Url: https://github.com/github/gh-aw/sessions/4b5c36c0-f14f-4a41-9c45-ff879964d705 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/parser/schedule_parser.go | 25 +++++++++++++++++++++++++ pkg/parser/spec_test.go | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/pkg/parser/schedule_parser.go b/pkg/parser/schedule_parser.go index cb999ac3c88..4e948be58c1 100644 --- a/pkg/parser/schedule_parser.go +++ b/pkg/parser/schedule_parser.go @@ -188,6 +188,31 @@ func (p *ScheduleParser) parseInterval() (string, error) { } } + // Handle "every day [at HH:MM]" as an alias for a daily schedule. + // Examples: "every day" (2 tokens), "every day on weekdays" (4 tokens), + // or "every day at 9am" (4+ tokens with "at" at index 2). + if p.tokens[1] == "day" || p.tokens[1] == "days" { + // len == 2: "every day"; len == 4 with weekdays suffix: "every day on weekdays" + if len(p.tokens) == 2 || (len(p.tokens) == 4 && hasWeekdaysSuffix) { + // "every day" or "every day on weekdays" — fuzzy daily schedule + if hasWeekdaysSuffix { + return "FUZZY:DAILY_WEEKDAYS * * *", nil + } + return "FUZZY:DAILY * * *", nil + } + // tokens[2] == "at": "every day at HH:MM" — token layout is [every, day, at, time...] + if len(p.tokens) > 2 && p.tokens[2] == "at" { + // extractTime handles the "at" keyword at index 2 and reads the time token(s) after it + timeStr, err := p.extractTime(2) + if err != nil { + return "", err + } + min, hr := parseTime(timeStr) + return fmt.Sprintf("%s %s * * *", min, hr), nil + } + return "", errors.New("invalid 'every day' format, use 'every day' or 'every day at HH:MM'") + } + // Fall back to original parsing for "every N minutes" format minTokens := 3 if hasWeekdaysSuffix { diff --git a/pkg/parser/spec_test.go b/pkg/parser/spec_test.go index cb8786f74b7..75c5f1e67a6 100644 --- a/pkg/parser/spec_test.go +++ b/pkg/parser/spec_test.go @@ -545,7 +545,7 @@ func TestSpec_PublicAPI_NewFormattedParserError(t *testing.T) { t.Run("empty message is preserved", func(t *testing.T) { err := NewFormattedParserError("") require.NotNil(t, err, "NewFormattedParserError should return non-nil for empty message") - assert.Equal(t, "", err.Error(), + assert.Empty(t, err.Error(), "NewFormattedParserError should preserve empty message") }) } From f59795e399776e81e7fac821b3e3a7b6e6e7e315 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 28 Apr 2026 14:32:55 +0000 Subject: [PATCH 3/3] test: add tests for 'every day [at HH:MM]' schedule variants Agent-Logs-Url: https://github.com/github/gh-aw/sessions/86921a24-21cb-49f3-9f94-145cbf6249e1 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/parser/schedule_parser_fuzz_test.go | 6 +++ pkg/parser/schedule_parser_test.go | 62 +++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/pkg/parser/schedule_parser_fuzz_test.go b/pkg/parser/schedule_parser_fuzz_test.go index 3dad0189b0b..9fb98980db8 100644 --- a/pkg/parser/schedule_parser_fuzz_test.go +++ b/pkg/parser/schedule_parser_fuzz_test.go @@ -126,6 +126,12 @@ func FuzzScheduleParser(f *testing.F) { f.Add("hourly on weekdays") f.Add("every 2h on weekdays") f.Add("every 2 hours on weekdays") + f.Add("every day") + f.Add("every day on weekdays") + f.Add("every day at 9am") + f.Add("every day at 14:30") + f.Add("every day at midnight") + f.Add("every day at noon") // UTC offset schedules f.Add("daily at 02:00 utc+9") diff --git a/pkg/parser/schedule_parser_test.go b/pkg/parser/schedule_parser_test.go index eddc39240b1..28c1e79de1b 100644 --- a/pkg/parser/schedule_parser_test.go +++ b/pkg/parser/schedule_parser_test.go @@ -831,6 +831,68 @@ func TestParseSchedule(t *testing.T) { expectedCron: "0 0 * * *", expectedOrig: "every 1 day", }, + + // "every day [at TIME]" — natural-language daily alias + { + name: "every day (fuzzy)", + input: "every day", + expectedCron: "FUZZY:DAILY * * *", + expectedOrig: "every day", + }, + { + name: "every days (plural, fuzzy)", + input: "every days", + expectedCron: "FUZZY:DAILY * * *", + expectedOrig: "every days", + }, + { + name: "every day on weekdays", + input: "every day on weekdays", + expectedCron: "FUZZY:DAILY_WEEKDAYS * * *", + expectedOrig: "every day on weekdays", + }, + { + name: "every day at 9am", + input: "every day at 9am", + expectedCron: "0 9 * * *", + expectedOrig: "every day at 9am", + }, + { + name: "every day at 09:00", + input: "every day at 09:00", + expectedCron: "0 9 * * *", + expectedOrig: "every day at 09:00", + }, + { + name: "every day at 14:30", + input: "every day at 14:30", + expectedCron: "30 14 * * *", + expectedOrig: "every day at 14:30", + }, + { + name: "every day at midnight", + input: "every day at midnight", + expectedCron: "0 0 * * *", + expectedOrig: "every day at midnight", + }, + { + name: "every day at noon", + input: "every day at noon", + expectedCron: "0 12 * * *", + expectedOrig: "every day at noon", + }, + { + name: "every day at 6pm", + input: "every day at 6pm", + expectedCron: "0 18 * * *", + expectedOrig: "every day at 6pm", + }, + { + name: "every day with unrecognised extra token", + input: "every day around 9am", + shouldError: true, + errorSubstring: "invalid 'every day' format", + }, { name: "weekly without on", input: "weekly monday",