Skip to content

[Phase 1] Move all scheduled workflows off the top of the hour #723

Closed

Description

@github-actions

Story

As a maintainer of petry-projects/.github-private's scheduled automation,
I want change every schedule.cron that fires at minute 0 to a staggered off-peak minute, touching only the minute field,
so that scheduled runs land outside GitHub's most congested slot (the top of the hour), directly targeting the #1 documented cause of dropped/delayed cron runs.

Acceptance Criteria

  1. No schedule.cron entry in .github/workflows/.yml or in agentic .github/workflows/.md sources uses minute 0 (i.e. the leading cron field is no longer 0).
  2. Only the minute (first) field of each cron is changed; the hour, day-of-month, month, and day-of-week fields are preserved exactly so every workflow's cadence and any date guards remain unchanged (e.g. standards-sync.yml must still fire on Mondays so its first-Monday guard still works; idea-triage must still be Monday 13:xx UTC).
  3. Minutes are staggered across the edited workflows (not all set to one shared minute) and avoid :00 and its immediate neighborhood, so the change does not create a new self-inflicted burst at a single minute.
  4. agent-shield.yml is not modified at all, and thin-caller stubs are not changed beyond their cron minute; no behavior other than the cron minute is altered in any file.
  5. shellcheck/lint passes and gh aw compile succeeds for any edited agentic .md source (e.g. stale-manager.md).

Tasks / Subtasks

Dev Notes

  • Per GitHub docs (quoted in Improving reliability of scheduled GitHub Actions runs (cron is best-effort) #656): the schedule event is delayed during high load, and 'high load times include the start of every hour' -- moving off 0 * * * * is the lowest-cost, highest-leverage mitigation. Scheduled workflows run only on the default branch's latest commit (already satisfied here).
  • Changing only the minute keeps each workflow's intended time-of-day/day-of-week, which several workflows depend on: standards-sync.yml has a 'first Monday of month only' guard that re-derives the day from the run date, so the cron must still be a Monday; idea-triage is meant to land after Friday ideation; token-report is the weekly Monday report.
  • Do NOT touch agent-shield.yml (exempt from agent modification per AGENTS.md / standards/agent-standards.md). Thin-caller stubs noted in CLAUDE.md/AGENTS.md (claude.yml, agent-shield.yml, auto-rebase.yml, dependabot-automerge.yml) have no minute-0 schedule, so none are in the target set -- but if any cron is edited in a thin caller, limit the change to the minute field only.
  • This is a mechanical, low-risk edit. The complementary CI guard that prevents regressions and the standard that documents the convention are Story 2, which depends on this one landing first.

Project Structure Notes

All edits are confined to existing .github/workflows/*.yml and the stale-manager.md agentic source; no new files, scripts, or jobs. No script behavior changes.

References

  • .github/workflows/feature-ideation.yml
  • .github/workflows/standards-sync.yml#first-monday-guard
  • .github/workflows/daily-pr-review-health.yml
  • .github/workflows/content-twin-audit.yml
  • .github/workflows/docs-health-check.yml
  • .github/workflows/actions-fleet-monitor.yml
  • .github/workflows/stale-manager.yml
  • .github/workflows/stale-manager.md
  • .github/workflows/token-report.yml
  • .github/workflows/idea-enhancer.yml
  • .github/workflows/idea-triage.yml
  • AGENTS.md#workflow-files
  • CLAUDE.md#key-guidelines

Likely target surface

  • .github/workflows/feature-ideation.yml
  • .github/workflows/standards-sync.yml
  • .github/workflows/daily-pr-review-health.yml
  • .github/workflows/content-twin-audit.yml
  • .github/workflows/docs-health-check.yml
  • .github/workflows/actions-fleet-monitor.yml
  • .github/workflows/stale-manager.yml
  • .github/workflows/stale-manager.md
  • .github/workflows/token-report.yml
  • .github/workflows/idea-enhancer.yml
  • .github/workflows/idea-triage.yml

Story prepared by the BMAD Scrum Master (Bob) for epic #722. Status: ready-for-dev.

Activity

  1. don-petry commented on Jul 14, 2026

    @don-petry
    Collaborator

    Dev-Lead Implementation Plan

    Issue: #723 — [Phase 1] Move all scheduled workflows off the top of the hour

    Scope

    Change the minute (first) field of every schedule.cron that fires at minute 0 to a distinct, staggered off-peak minute, preserving each cron's hour/day-of-month/month/day-of-week exactly so cadence and date guards are unchanged.

    Enumeration note (target set differs from the story's list)

    The story's task list predates repo changes. Verified against current main:

    • idea-enhancer.yml no longer exists — dropped from the set.
    • Four additional minute-0 workflows exist that the story did not list but AC#1 requires: readme-refresh.yml, auto-rebase-health.yml, premature-closure-audit.yml, skill-eval-report.yml.
    • Only agentic .md source with a cron is stale-manager.md (spec doc). The real gh aw sources (ci-failure-analyst.md, issue-triage.md, release-notes.md) have no schedule.
    • agent-shield.yml is exempt and untouched. No thin-caller stub other than feature-ideation.yml (minute-field-only edit) is in the set.

    Minute assignments (only the first field changes)

    File Old New
    feature-ideation.yml 0 7 * * 5 7 7 * * 5
    standards-sync.yml 0 9 * * 1 11 9 * * 1
    daily-pr-review-health.yml 0 6 * * * 13 6 * * *
    content-twin-audit.yml 0 7 * * * 19 7 * * *
    docs-health-check.yml 0 0 * * 0 21 0 * * 0
    actions-fleet-monitor.yml 0 6 * * * 27 6 * * *
    stale-manager.yml 0 9 * * 1 29 9 * * 1
    token-report.yml 0 8 * * 1 34 8 * * 1
    idea-triage.yml 0 13 * * 1 37 13 * * 1
    readme-refresh.yml 0 9 * * 1 41 9 * * 1
    auto-rebase-health.yml 0 7 * * * 43 7 * * *
    premature-closure-audit.yml 0 8 * * 1 49 8 * * 1
    skill-eval-report.yml 0 7 * * * 51 7 * * *
    stale-manager.md (spec, sync w/ yml) 0 9 * * 1 29 9 * * 1

    All 13 minutes are distinct; none collide at a shared hour, none collide with the already-off-peak crons (pr-review-sweep 2/17/32/47, dev-lead-retry :15, initiative-driver :23, initiative-planner-canary :30, initiative-driver-canary :40); all avoid the :00 neighborhood.

    Documentation consistency (illustrative crons in docs/aw mirrors)

    • docs/aw/standards-sync.md 0 9 1-7 * 1 → 11 9 1-7 * 1
    • docs/aw/docs-health-check.md 0 0 * * 0 → 21 0 * * 0
    • docs/aw/content-twin-audit.md 0 7 * * * → 19 7 * * *

    Adjacent human-readable time comments (e.g. # Every Monday at 09:00 UTC) are updated to the new minute so they stay accurate; no other content changes.

    Tests

    No test asserts a specific cron minute (verified: test_skill_eval_report.bats only checks a cron exists). This is a behavior-preserving configuration change, so per the dev-lead Phase-2 exception no new test is added; verification is by lint + a repo-wide check that no - cron: '0 ...' remains.

    Test / Verify Command

    bash .dev-lead/scripts/dev-lead-lint.sh plus bats tests/ and a grep guard for residual minute-0 crons.

  2. don-petry commented on Jul 14, 2026

    @don-petry
    Collaborator

    Dev-Lead: Implementation Complete

    Plan Execution

    • Enumerated every minute-0 cron in the repo (found the story's list was stale — see notes)
    • Assigned each a distinct, staggered off-peak minute; edited only the first (minute) cron field
    • Kept stale-manager.md (spec doc) in sync with stale-manager.yml
    • Updated docs/aw illustrative-cron mirrors for documentation consistency
    • Left already-off-peak crons (pr-review-sweep 2/17/32/47, dev-lead-retry :15, initiative-driver :23, initiative-planner-canary :30, initiative-driver-canary :40) untouched — no collisions introduced
    • agent-shield.yml not modified
    • Lint + YAML/cron validation pass; verified zero residual minute-0 crons

    Acceptance Criteria

    • AC#1 No schedule.cron at minute 0 in .github/workflows/*.yml or .md: verified by grep + parse (0 matches).
    • AC#2 Only the minute field changed; hour/day-of-month/month/day-of-week preserved exactly — standards-sync stays Monday (first-Monday guard intact), idea-triage stays Mon 13:xx.
    • AC#3 13 distinct minutes {7,11,13,19,21,27,29,34,37,41,43,49,51}, all clear of the :00 neighborhood and of the existing off-peak minutes; no two edited workflows (and none at a shared hour) collide.
    • AC#4 agent-shield.yml untouched; thin-caller feature-ideation.yml changed in the minute field only; no non-cron behavior altered in any file.
    • AC#5 dev-lead-lint.sh (shellcheck + profile validation) passes. gh aw compile: the only cron-bearing agentic .md is stale-manager.md, a spec document — not a compilable gh aw source (real sources ci-failure-analyst.md / issue-triage.md / release-notes.md carry no schedule and are unchanged), so no compile output changes.

    Enumeration note (story list was out of date vs. main)

    • idea-enhancer.yml no longer exists — dropped.
    • Four minute-0 workflows the story omitted but AC#1 requires were included: readme-refresh.yml, auto-rebase-health.yml, premature-closure-audit.yml, skill-eval-report.yml.

    Minute assignments

    File Old → New
    feature-ideation.yml 0 7 * * 5 → 7 7 * * 5
    standards-sync.yml 0 9 * * 1 → 11 9 * * 1
    daily-pr-review-health.yml 0 6 * * * → 13 6 * * *
    content-twin-audit.yml 0 7 * * * → 19 7 * * *
    docs-health-check.yml 0 0 * * 0 → 21 0 * * 0
    actions-fleet-monitor.yml 0 6 * * * → 27 6 * * *
    stale-manager.yml (+ .md) 0 9 * * 1 → 29 9 * * 1
    token-report.yml 0 8 * * 1 → 34 8 * * 1
    idea-triage.yml 0 13 * * 1 → 37 13 * * 1
    readme-refresh.yml 0 9 * * 1 → 41 9 * * 1
    auto-rebase-health.yml 0 7 * * * → 43 7 * * *
    premature-closure-audit.yml 0 8 * * 1 → 49 8 * * 1
    skill-eval-report.yml 0 7 * * * → 51 7 * * *
    docs/aw/standards-sync.md 0 9 1-7 * 1 → 11 9 1-7 * 1
    docs/aw/docs-health-check.md 0 0 * * 0 → 21 0 * * 0
    docs/aw/content-twin-audit.md 0 7 * * * → 19 7 * * *

    Verification output

    [lint] shellcheck on 80 file(s)...
    [lint] validating 4 agent profile(s)... OK (x4)
    [lint] validating .github/CODEOWNERS... OK
    [lint] all checks passed   (exit 0)
    
    cron/YAML validation: 13 workflows parse; all minutes distinct, none == 0,
    hours/days preserved. residual minute-0 crons in .github/workflows + docs/aw: 0
    

    Note: bats is not installed in this environment, so the tests/ suite runs in CI. No test asserts a specific cron minute (test_skill_eval_report.bats only checks that a cron exists), so this behavior-preserving config change does not affect any assertion.

    Files Changed

    16 files (14 minute edits + stale-manager.md sync + 3 docs/aw mirrors → 17 lines total). Each is a single-line change touching only the cron minute field.

    Notes

    • Phase 2 (TDD) exception: this is a behavior-preserving configuration change with no cron-minute test harness (the regression guard is Story 2, per the epic). Verification is by lint + parse checks.
    • Comments were intentionally left unchanged; they denote the hour slot (e.g. "09:00 UTC"), which is preserved, and several cross-reference other workflows' hour slots — rewriting them to minute precision would add churn beyond "only the minute field."
    • No commits/PRs created — leaving git operations to the CI workflow.
  3. added a commit that references this issue on Jul 14, 2026
  4. added 18 commits that reference this issue on Aug 2, 2026
  5. added a commit that references this issue on Aug 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    dev-leadFor dev-lead agent pickupinitiativeEpic / initiative tracking issue

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions