Skip to content

cron workflows #245

@marccampbell

Description

@marccampbell

Cron workflows

Goal

Elasticclaw should support workflows that run on a schedule. A scheduled workflow should be able to start an ephemeral claw, inject deterministic run context, let the claw perform a bounded task, and record the result.

This is for recurring work such as dependency updates, nightly audits, weekly reports, repository hygiene, release checks, and other maintenance tasks that should not require a person or an external scheduler to trigger each run.

Product shape

A user creates a workflow with a cron trigger:

name: dependency-updates

on:
  cron:
    schedule: "0 9 * * 1"
    timezone: "America/Chicago"

concurrency:
  group: dependency-updates
  policy: skip

timeout: 2h

steps:
  - uses: elasticclaw/dependency-updates
    with:
      ecosystems:
        - go
        - npm
      grouping: all
      include_major: false

  - run: make test

  - uses: elasticclaw/open-pr
    with:
      title: "Update dependencies"
      branch_prefix: "elasticclaw/dependency-updates"

The UI can present this as a scheduled workflow form:

  • Workflow name
  • Cron schedule, with a visual picker and raw cron expression
  • Timezone
  • Template or workflow definition
  • Concurrency group and overlap policy
  • Timeout
  • Enabled/paused state
  • Run now
  • Recent runs and next run

Runtime behavior

When the schedule fires, Elasticclaw creates a new workflow run and provisions a claw for that run.

The claw receives generated context such as:

trigger:
  type: cron
  schedule: "0 9 * * 1"
  timezone: "America/Chicago"
  triggered_at: "2026-06-15T14:00:00Z"
  run_id: "dependency-updates-2026-06-15T14-00-00Z"

workflow:
  name: dependency-updates
  timeout: 2h

repository:
  owner: elasticclaw
  name: elasticclaw

The workflow run should appear in the dashboard with:

  • Trigger type: cron
  • Workflow name
  • Current status
  • Started at / finished at
  • Claw link
  • Logs and final summary
  • Result: success, failed, skipped, timed out, or canceled

When the claw signals completion, the workflow run is marked complete and the claw can terminate. If the timeout is reached, the run is marked timed out and the claw is terminated.

Why workflows, not factories

Cron should be modeled as a workflow trigger, not as a new factory type.

Factories are useful for event-to-claw creation, but scheduled maintenance tasks need a stronger execution model:

  • A run record with status, logs, summary, and history
  • A workflow definition that can include reusable built-in steps
  • A clean trigger model that supports cron now and other triggers later
  • Consistent behavior for manual runs, retries, and scheduled runs
  • A natural place for step-level configuration, such as dependency update policy

The trigger should answer "when does this run?" The workflow should answer "what happens when it runs?"

Dependency updates as a built-in workflow step

Dependency updates are the motivating first workflow, but they should not be hard-coded into cron.

Elasticclaw should provide a built-in dependency update step that can be used by a cron workflow, manually run workflow, or future event-triggered workflow.

The step should:

  • Discover supported manifests, such as go.mod, package.json, lockfiles, Ruby, and Python manifests
  • Identify available updates using ecosystem-native tooling where possible
  • Classify updates as patch, minor, major, runtime, and security-related when that data is available
  • Apply selected updates
  • Produce structured output describing discovered manifests, candidate updates, applied updates, skipped updates, commands run, and files changed
  • Let later workflow steps run tests, fix failures, and open a PR

Initial support can be narrow:

  • Go modules
  • npm / package-lock or pnpm/yarn if detected
  • One PR per repo per scheduled run
  • Skip major updates by default
  • Require tests before opening a PR

Later support can add Ruby, Python, security-specific grouping, and more package managers.

PR grouping

The default should be one PR per repository per scheduled run for normal patch and minor updates.

That keeps the workflow quiet and useful. One PR per dependency creates too much noise for the common case.

The model should still support splitting updates when needed:

  • Major updates can be separate
  • Security updates can be separate
  • Runtime version updates can be separate
  • Failed grouped updates can be split by ecosystem or dependency to isolate the breaking change

Suggested grouping options:

grouping: all | ecosystem | dependency
separate_major: true
separate_security: true
separate_runtime: true

Default:

grouping: all
separate_major: true
separate_security: true
separate_runtime: true
include_major: false

Overlap and missed-run behavior

Cron workflows need explicit overlap behavior.

Suggested policies:

  • skip: if a previous run is still active, skip the new run
  • queue: enqueue the next run after the active run finishes
  • parallel: allow overlapping runs

Default should be skip for scheduled maintenance workflows.

For missed runs while the hub was down, default to running only the latest missed occurrence, not every missed occurrence. This avoids accidental bursts after downtime.

Manual run and retry

Every cron workflow should have:

  • Run now
  • Retry failed run
  • Pause / resume
  • View next run
  • View run history

Manual runs should use the same workflow definition and produce the same kind of run record. The trigger context should identify them as manual:

trigger:
  type: manual
  requested_by: "user"

Non-goals

  • Do not build a full DAG engine in the first version
  • Do not require users to configure external cron services
  • Do not keep long-running claws alive between schedules
  • Do not make dependency updates a special cron-only feature
  • Do not fan out into many PRs by default

Open questions

  • Should the first implementation store workflows as YAML, database records, or both?
  • Should cron workflows be scoped to a repository, workspace, or organization?
  • What is the exact completion signal from the claw: [DONE], explicit workflow-step result, or both?
  • Should "latest missed run only" be configurable, or just the default behavior?
  • How much of dependency update detection should be deterministic tooling versus agent reasoning in the first version?

First shippable version

Ship a small version that proves the model:

  • Cron-triggered workflows
  • Timezone-aware schedule
  • Run now
  • Pause / resume
  • Run history
  • Timeout
  • Overlap policy with skip
  • Context injection
  • Dashboard status
  • Built-in dependency update step for Go and npm
  • One grouped PR per repository per run
  • Major updates skipped by default
  • Tests required before PR creation

Metadata

Metadata

Assignees

No one assigned

    Labels

    doneThe issue is complete

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions