Skip to content

Releases: aleandros/powerqueue

powerqueue v0.18.1

Choose a tag to compare

@github-actions github-actions released this 16 Oct 19:57
645e884

Fixed

  • Preserve live session ownership when task controls run without a daemon:
    resume returns to the surviving session, and cancel/retry stay queued until
    the daemon can stop it. Select the latest session by start time, so resetting
    attempts on a terminal-task retry cannot hide the new session behind history
    in the scheduler or dashboard (including attachment and resource samples).

Added

  • Stateful scheduler coverage for conditional model preferences, policy and
    concurrency reloads, dated rolling-window spend, observed provider usage,
    historical sessions and offline CLI writers. Forced launch scenarios exercise
    draining a lowered concurrency limit, budget expiry and retry deadlines;
    minimized bug regressions and an opt-in larger stress run accompany the fixes.

powerqueue v0.18.0

Choose a tag to compare

@github-actions github-actions released this 15 Oct 23:06
47e4e0c

Fixed

  • Bound shared launch failures with persistent project/global backoff. Isolated
    setup failures allow other work; repeated setup failures defer that project,
    and shared runtime or storage failures stop launching globally. Failed starts
    reserve no capacity or predicted budget. Doctor and events expose the failure,
    retry deadline and recovery; Rust stateful properties, Quint simulations and
    daemon integration tests cover isolation, restart, bounded attempts and recovery.

  • Accept dead tmux panes whose process ID has been cleared after exit, so crash
    detection and retry continue to work on current macOS tmux versions.

  • Update the locked rustls dependency to 0.23.46 to resolve the security
    advisories reported by CI.

  • Recover abandoned starting tasks after launch persistence failures or daemon
    restarts using normal attempt limits and backoff. Recovery preserves work,
    rejects stale task/session observations, and waits for surviving setup processes
    or unrecorded agents. Doctor explains the hold and the saved tmux destination;
    doctor --fix no longer interrupts starting tasks.

Added

  • Quint simulation and event replay cover dependency blocking/unblocking and PR
    handoff, session release, review relaunch and merge, including per-round crash
    allowances and paused review watches. Synthetic rejection tests check invalid
    ordering; existing v0.14.0 event logs work without a daemon upgrade. Human
    blockers, containers, PR adoption, live-session retry release, and unsupported
    review/relay changes still end the affected prefix. Dependency holds reject
    live sessions and check the logged previous state against the model.

powerqueue v0.17.0

Choose a tag to compare

@github-actions github-actions released this 13 Oct 03:33
c549285

Added

  • Deterministic repository routing from source repository, Linear team/project
    metadata and labels, using typed conditions in config.toml. Matching rules
    override source fallbacks; conflicting, unmatched and invalid destinations hold
    future launches with persisted reasons. Sync previews, task show/explain and
    doctor expose routing decisions. Saved assignments and pinned checkouts survive
    metadata changes, retries and review; reassignment remains explicit.
  • Routing properties and integration coverage for conflicting labels, unknown
    projects, metadata changes, database restart, project isolation and stale
    sync/launch races. Quint trace replay models routing holds independently from
    source approval and validates the real daemon routing events.
  • Tune free-form Markdown intent into validated TOML proposals, with project
    selection, intent-change diagnostics, scoped queue simulation and reviewable
    working-copy changes for committed repository policies. Stale drafts refuse
    to overwrite newer input; applied snapshots remain available for undo.

Changed

  • Replace executable Markdown priority rules with strict versioned priority.toml.
    Structured conditions share the existing evaluator and budget behavior. Use
    priority migrate --from PRIORITY.md --to priority.toml and update policy paths;
    Markdown remains optional intent only. See migration.
  • Priority commands support execution projects; live simulation and explanation
    use each task's policy. Invalid reloads retain the last valid project policy.
    Initialization, doctor and tune use TOML and report legacy migration needs.
  • Rust API: PriorityRules::parse now accepts TOML; Markdown conversion is
    priority::migration::migrate. Priority show/edit/path command variants now
    carry PolicyArgs, and check/simulate arguments include an optional project.

Fixed

  • Refuse legacy or stale tune undo operations before touching live files; policy
    mutation commands refuse unresolved repository overrides instead of editing
    the machine policy by mistake. Intent-only Markdown can seed a new TOML policy.
  • Preserve the legacy checkout's GitHub approver restrictions and Linear intake
    filters when adding execution projects, including daemon reloads.
  • Treat unreadable committed policy objects as errors, never absent files.
    Worktree ownership checks no longer require Git's --path-format option.
  • Persist failed project cleanup for retry after repair or daemon restart;
    doctor reports pending cleanup, finished session windows close independently,
    and superseded executions cannot be cleaned up.
  • Isolate GitHub issue collisions and verification failures so healthy issues
    still sync, launch and receive lifecycle updates. Source-wide authentication
    and rate-limit failures still pause the source, including GraphQL HTTP 200
    errors. Repeated issue warnings are deduplicated.
  • Keep cached project policies through temporary override errors and deduplicate
    repeated policy failure events.

powerqueue v0.16.0

Choose a tag to compare

@github-actions github-actions released this 12 Oct 21:58
738b8d0

Set up one local queue for multiple GitHub repositories with project registration,
explicit issue approval, shared provider budgets and concurrency, and separate
worktrees. See the multi-project setup guide.

Added

  • Focused project register/project list setup and reconfiguration, project
    columns and filters in status/dashboard, per-project doctor cleanup/isolation
    checks, and disposable three-project GitHub review lifecycle validation.
    Named-only registries work with Linear disabled. Quint now models three projects.
  • Multiple GitHub intake sources with explicit execution-project mappings,
    per-source credentials, filters, polling and lifecycle settings. Preserve legacy
    [github] configuration and task assignments; reject unknown or conflicting
    routes and report per-source failures in previews, admission and doctor.
  • Stateful routing checks across setup, retry, restart, review and active work,
    including mapping conflicts during a launch pass and shared resource accounting.
  • Explicit GitHub execution approval with configurable required_labels (default
    agent:ready) and optional trusted_approvers. Verify effective label actors and
    title/body edit history before starts and after setup; revocation holds future
    starts while preserving active work. Persist decisions and explain them in task
    inspection, sync previews, events and doctor.
  • Stateful daemon/SQLite and Quint admission checks, including revocation during
    setup, reapproval, restart, stale candidates and rejection of unapproved event
    traces. Advisory CI also replays a real GitHub approval/launch trace.

Changed

  • Explicit existing GitHub label settings remain unchanged. Omitted settings now
    use agent:ready; empty approval labels are invalid for enabled intake. Title or
    body edits require review and label reapplication. Approval verification requires
    GraphQL access; unavailable evidence blocks starts, including offline starts.
  • scheduler::launch::on_starting returns Option<Start> and refuses unapproved
    tasks without mutation.
  • CLI argument and dashboard structs include project fields; dashboard::Options
    remains Clone but is no longer Copy.

Fixed

  • GitHub review/retry launches now persist the attempt and worktree claim before
    rechecking approval, even when the checkout is already bound. Approval reloads
    no longer discard the recreated worktree or reset crash accounting.
  • Make the multi-project cleanup test wait for transcript usage collection,
    avoiding a timing race when cleanup finishes before usage is recorded.
  • Record crash retry deadlines for formal replay, so delayed event logging
    cannot make an on-time restart appear premature.

powerqueue v0.15.0

Choose a tag to compare

@github-actions github-actions released this 12 Oct 19:14
5ead835

Added

  • Execution projects: register multiple checkouts under [projects.<id>], enqueue
    with add --project, and reassign unstarted tasks with task project. One
    daemon shares slots and provider budgets while resolving setup, prompts,
    priority and cleanup per project. Existing tasks migrate to default; pinned
    checkouts and ownership checks protect retries, review and cleanup across
    restarts. doctor reports project configuration and binding problems.

Changed

  • Testing: extend the Rust daemon model with project reassignment, independent
    policies, unavailable/moved checkouts, and stale SQLite launch claims. Extend
    Quint with execution-project ownership invariants and a finite model of the
    reassignment/launch race, including both models in the simulation checks.
  • Testing: replace the Python Quint replay adapter with a Rust Cargo example,
    reusing application event types and preserving anonymized schedules, coverage
    reports, task-prefix cutoffs and invalid-schedule checks. Projection tests run
    in the Rust gate; advisory CI runs Quint checks and all three daemon traces.

powerqueue v0.14.0

Choose a tag to compare

@github-actions github-actions released this 10 Oct 15:47
8e3698f

The stateful model now covers the whole daemon: several tasks sharing
slots, ledgers and rate limits through the real launch pass. It found one
scheduling bug, fixed here: a start that fails before the launch no longer
keeps its slot and its predicted budget for the rest of the pass.

Changed

  • Testing: a whole-daemon model (scheduler/model.rs) runs random
    interleavings of launch passes, per-task calls, recorded usage, the
    scheduling pause and time against several tasks sharing slots, ledgers
    and rate-limit marks. Launches go through the real LaunchPlanner as
    launch_tasks drives it; the checks cover slots (never beyond
    max_concurrent), one hand-out per ready task per pass, the retry time
    of a throttled candidate, budget (every ledger a pass reserved on stays
    within the safety margin), bounded progress (no ready task left
    unconsidered while a slot is free) and independence from the order the
    store lists the tasks in.

Fixed

  • A start that fails before the launch (worktree setup, repo.setup, the
    launcher) no longer uses up its slot and its predicted budget for the
    rest of the launch pass: the next candidate is tried in the same tick,
    as the planner documents. Found by the whole-daemon model. (A failure
    that hits every task, such as a missing repository, now crashes every
    ready task in one pass rather than one per tick; each still gets its
    backoff and max_attempts.)

powerqueue v0.13.0

Choose a tag to compare

@github-actions github-actions released this 10 Oct 14:21
059d025

The pure core is now checked by property-based tests and a stateful
model of the daemon's calls, and the bugs they found are fixed: relayed
answers no longer revive finished tasks, stale retry times are cleared,
and a done marker that arrives after the probe still completes the task.
task complete and task block refuse a task the daemon is launching.

Changed

  • Testing: the pure core is checked by property-based tests (proptest)
    besides the example tests. Shared generators in src/strategies.rs
    produce tasks, sessions, configs, ledgers, hook outcomes and PR statuses
    the daemon could hold; every pure module in scheduler and budget has
    properties (legal moves, inert terminal states, idempotent commands,
    justified effects, backoff arithmetic, review rounds, planner passes,
    policy eligibility, period arithmetic, observation history), and a
    stateful model test runs random sequences of the daemon's calls against
    one task, checking the cross-cutting invariants after each step.
    TaskState::can_transition_to now lists every move the daemon makes
    (a starting task may land in any session state; paused and throttled
    tasks keep their session and may complete, crash or ask for a human; a
    crashed or failed task completes when the done marker of its last
    attempt arrives after the probe; a paused task unskipped while waiting
    on a blocker goes blocked).
  • task complete, task complete --pr and task block are pure
    transitions (scheduler::commands::{on_complete, on_hand_off, on_block})
    that the CLI persists, so the stateful model runs the real ones. They
    refuse a starting task: the daemon is launching it and would persist
    running over the change. The daemon also re-reads the row after a
    launch and keeps whatever was written to it meanwhile (a command applied
    offline during a long repo.setup), logging launch.superseded.

Fixed

Found by the new property tests:

  • A reply relayed from Linear to a completed, failed or cancelled task no
    longer re-queues it; only task retry revives a finished task.
  • A Stop with the done marker or a SessionEnd drained after the
    session was already closed no longer completes a cancelled task or one
    re-queued since, nor counts a second crash against a re-queued one. A
    done marker drained after the probe already crashed or failed the
    session still completes the task (the pane died right after printing
    it), instead of relaunching the finished work or leaving it failed.
  • A throttled task whose agent then reports a blocker, hits a permission
    prompt or an authentication failure, or finishes, no longer keeps the
    stale retry time; neither does a task that starts out of a throttle or
    is completed by task complete or blocked by task block.
  • A throttled or paused task whose agent is still in its session (waiting
    for a usage reset, finishing its turn) is no longer re-scored, so an
    unsatisfied blocker cannot move it to blocked under the live session,
    where nothing would probe the window.
  • A task parked because its PR URL is unusable is marked parked on its
    watch (created when the row had none), so task resume watches the PR
    again instead of running a pending review round or re-queuing it.
  • Policy::eligibility agrees with decide for a provider disabled in
    config that still has a ledger: its models are not eligible.

powerqueue v0.12.0

Choose a tag to compare

@github-actions github-actions released this 09 Oct 15:20
af155a8

The scheduler is now a functional core with an imperative shell, the
groundwork for stronger testing of the queue's decisions, and the
default-branch policy reading introduced in 0.11.0 no longer locks the
CLI out or stalls the daemon when the branch cannot be read.

Changed

  • The scheduler is a functional core with an imperative shell: every task
    and session state change is a pure function returning Effects
    (scheduler::{transitions,commands,launch,review}), and the daemon only
    loads rows, persists what changed and carries the effects out. The
    budget core (Ledger::build, resolve_clock, the observation history
    rules) takes plain rows; store access lives in budget::io. budget plan runs the daemon's LaunchPlanner; priority simulate shares its
    preferred-model helper. Events logged from a cancel or retry now carry
    the session they ended (a refused retry names none). task pause|resume| cancel|retry applied offline (no daemon) use the daemon's own
    transitions: an offline retry of a finished task starts over (attempts,
    error and summary reset) and an offline resume clears a PRIORITY.md
    skip, as they do with the daemon running.

Fixed

  • task retry of a task with a live session no longer keeps the ended
    session in the daemon's nudge list.
  • A task parked because its PR URL is unusable has its retry time
    cleared like every other parked task.
  • A status-line usage payload without readings no longer reads the
    observation history before being dropped.
  • A .powerqueue.toml that cannot be read from the default branch no longer
    locks every command out: status, doctor, config show, stop, pause
    and the rest run with config.toml alone and say so (status --json and
    config show --json carry the error); only run refuses to start.
  • doctor, tune and config validate read .powerqueue.toml from the
    commit the daemon loaded it from, even when that file sets
    default_branch itself.
  • Whether .powerqueue.toml exists on a branch is now an exit-status probe
    (git cat-file -e), and git runs with LC_ALL=C: a localized git no
    longer turns a missing file into a hard error.
  • The daemon retries a reload that failed (a half-written config.toml, a
    git lock) every check instead of waiting for the next change, logs it once,
    and doctor reports a daemon still running the configuration from before
    such a change ("config reload").
  • A git failure while checking .powerqueue.toml for changes keeps the last
    known fingerprint and is logged once (daemon.overrides_check_failed)
    instead of causing a spurious reload (which also reset the GitHub
    rate-limit backoff) once git recovered.
  • A reload asked for by config set moves the change baseline, so the next
    check no longer reloads the same change a second time.
  • The periodic git fetch runs on a blocking thread; an unreachable remote
    no longer stalls hook processing and stop / pause for the duration of
    the network timeout. A fetch before a task start counts as the periodic one.
  • repo.fetch_interval_secs is capped at a week by config validate; an
    absurd value no longer panics the daemon's first tick.
  • priority simulate --json prints one JSON document when the rules file is
    missing (rules_missing: true) instead of two; the priority commands'
    missing-file hint names the branch when the rules are committed.
  • A relative priority_file in .powerqueue.toml is normalised (./,
    doubled slashes) and one that leaves the repository (../x) is rejected
    when the file is applied, instead of making the rules permanently
    unreadable.
  • config show marks values from .powerqueue.toml by editing the parsed
    TOML (toml_edit) rather than scanning lines, and a repository
    instructions value is attributed to claude.append_system_prompt, the
    key it changes.

powerqueue v0.11.0

Choose a tag to compare

@github-actions github-actions released this 08 Oct 23:38
d91103f

The queue's policy can live in the repository: .powerqueue.toml now carries
[linear], [github], [scheduler] and the rules file, and the daemon can
read it from the default branch instead of the working tree.

Added

  • .powerqueue.toml accepts [linear] (everything but endpoint),
    [github] (everything but endpoint), [scheduler] (everything but
    gh_binary) and priority_file (the rules file, relative to the repo
    root). Precedence is repo over global, key by key; lists replace. Secrets,
    [budget] and host settings stay global.
  • repo.overrides_from = "default-branch" reads .powerqueue.toml and a
    relative priority_file as committed on origin/<default_branch> (the
    local branch without a remote), so a git checkout in the main checkout
    cannot change what the daemon runs; repo.fetch_interval_secs (300) makes
    the daemon fetch while idle so a merged change arrives on its own. The
    default stays "working-tree".
  • The daemon reloads its configuration when .powerqueue.toml changes
    (working tree: mtime and size; branch: blob ids), without config set or a
    restart: events daemon.reloaded (with the keys taken and the commit) and
    daemon.reload_failed (the previous configuration is kept). Committed
    rules reload the same way; rules.loaded names the commit.
  • config show marks every key that came from the repository
    (# .powerqueue.toml) and names the file and branch; --json adds
    repo_overrides. config validate validates the merged configuration and
    reports what the repo sets. config path lists repo_config.
  • doctor: the .powerqueue.toml check reports the source and the keys set
    and fails when the branch cannot be read; a new overrides source check
    warns when the main checkout is not on the default branch (working-tree
    mode), when default-branch mode has no remote branch to read, or when the
    daemon never fetches. The PRIORITY.md check reads the committed copy when
    that is what the daemon reads.
  • priority show|check|explain|simulate read the committed rules when the
    daemon does and say so; priority edit reminds you to commit and push;
    tune refuses to rewrite a rules file the repository owns.

Changed

  • Shorten the README to an overview and quick start with a Mermaid workflow;
    move detailed guides and references into docs/. The tuning assistant now
    embeds the dedicated configuration reference.

powerqueue v0.10.0

Choose a tag to compare

@github-actions github-actions released this 08 Oct 22:12
3251f2f

Sessions can run inside containers (or anywhere the daemon's powerqueue
binary cannot run); see docs/containers.md.

Added

  • claude.binary, codex.binary and gemini.binary are command templates:
    a command line split like a shell would, with per-task placeholders
    ({key}, {slug}, {task_id}, {session_id}, {worktree},
    {task_dir}, {repo}, {attempt}, {model}), e.g. docker exec -it --env-file {task_dir}/env -w {worktree} pq-{slug} claude. A plain
    program still works as before. config validate reports unbalanced
    quotes and unknown placeholders; doctor, service status and the
    usage probes use the template's program, and skip the login check with a
    note when the command is per-task.
  • <provider>.shim = true: the launcher writes a POSIX shell shim to
    <task dir>/bin/powerqueue and points the hooks, Claude Code's status
    line, Codex's notify and the prompt's completion protocol at it. The
    shim writes one file per call into <task dir>/inbox/; the daemon drains
    it every tick (new inbox phase before the hooks) and applies the
    messages as powerqueue hook / task complete / task block would
    (events inbox.complete, inbox.block, inbox.error, inbox.rejected;
    doctor reports parked unreadable messages). Claude sessions get
    Bash(<shim> task *) in --allowedTools; prompt templates can use
    {{powerqueue}}.
  • POWERQUEUE_BIN in the session environment names the powerqueue
    command the session should run (the host binary, or the shim) unless the
    provider's env sets it.
  • repo.setup gets POWERQUEUE_TASK_SLUG, POWERQUEUE_TASK_DIR,
    POWERQUEUE_DATA_DIR and POWERQUEUE_STATE_DIR; cleanup.run gets
    POWERQUEUE_TASK_SLUG.
  • claude.env.CLAUDE_CONFIG_DIR is also where the daemon reads transcripts
    and seeds workspace trust (like codex.env.CODEX_HOME for rollouts), so a
    config directory mounted into a container at the same path works on both
    sides.
  • docs/containers.md, docs/examples/Dockerfile.agent (Claude Code + Codex
    on Node 22) and docs/examples/agent-container.sh (up / down / exec
    for a per-task container); end-to-end tests of the shim on the host and,
    with POWERQUEUE_E2E_DOCKER=1, of Claude and Codex sessions through
    docker exec.

Fixed

  • A task completed by powerqueue task complete whose session exited
    between the hook and probe phases of one tick was released without
    cleanup (no push, no cleanup.run, no source-issue update): the probe
    marked the session exited and finalize_terminal never saw it. The
    session is now left live for finalize_terminal (event
    session.pane_gone).