Phase 4: queue scheduler in tick — drain the defer queue #8

Merged
ellen merged 1 commit from phase4-tick-queue into main 2026-07-21 11:29:42 +00:00
Member

Phase 4 — queue scheduler in tick (runbook §5)

Extends the tick job (schedule, every 15 min, one run per repo via its caller) to drain the defer queue:

  1. Lists this repo's open issues/PRs labelled blocked/usage or blocked/night.
  2. Keeps the ones whose gate has re-opened — usage: now > resume_after (from the <!-- agent-state --> comment; empty/unparseable ⇒ open, preflight re-checks); night: now inside NIGHT_WINDOW (Europe/Helsinki, same math as preflight).
  3. Sorts FIFO by the state comment's updated_at (deferral time) and takes the first QUEUE_BATCH (default 2).
  4. For each: removes blocked/* and re-applies origin_label with the PAT matching the route's identity, so the original label event re-fires (preflight runs again and may re-defer).

origin_label → apply mapping:

origin PAT applies
agent/plan claude-plan agent/plan
agent/test claude-plan agent/test (on the PR)
agent/dev claude-dev agent/dev
plan/approved claude-dev plan/approved then agent/dev

First-build carry-over gap (fixed here)

A night/usage-deferred first build has origin_label = plan/approved, but the implement route is APPROVER-only — a bot re-applying plan/approved can't re-fire it. Instead the queue restores plan/approved as the standing gate (a bot applying it does not trigger implement, which checks sender == APPROVER) and then applies agent/dev, which dev-bounce admits for a bot PAT when plan/approved is present. The dev route builds agent/issue-N from main on first run — exactly a first build. No guard relaxation; the human-approval invariant is preserved.

Notes

  • Only dispatch.yaml changes; the tick timeout goes 2 → 10 min (runbook §3).
  • Kill switch honoured: AGENTS_ENABLED != true ⇒ no-op.
  • Validated: js-yaml parse + bash -n of the tick script; live smoke-test of the candidate-gather + FIFO/batch logic against the API.

Part of the epic: valssi/ops#1. Merges are human-only.

🤖 Generated with Claude Code

## Phase 4 — queue scheduler in `tick` (runbook §5) Extends the `tick` job (schedule, every 15 min, one run per repo via its caller) to drain the defer queue: 1. Lists this repo's open issues/PRs labelled `blocked/usage` or `blocked/night`. 2. Keeps the ones whose gate has re-opened — usage: `now > resume_after` (from the `<!-- agent-state -->` comment; empty/unparseable ⇒ open, preflight re-checks); night: now inside `NIGHT_WINDOW` (Europe/Helsinki, same math as preflight). 3. Sorts FIFO by the state comment's `updated_at` (deferral time) and takes the first `QUEUE_BATCH` (default 2). 4. For each: removes `blocked/*` and re-applies `origin_label` with the PAT matching the route's identity, so the original label event re-fires (preflight runs again and may re-defer). `origin_label` → apply mapping: | origin | PAT | applies | |---|---|---| | `agent/plan` | claude-plan | `agent/plan` | | `agent/test` | claude-plan | `agent/test` (on the PR) | | `agent/dev` | claude-dev | `agent/dev` | | `plan/approved` | claude-dev | `plan/approved` then `agent/dev` | ### First-build carry-over gap (fixed here) A night/usage-deferred **first build** has `origin_label = plan/approved`, but the `implement` route is APPROVER-only — a bot re-applying `plan/approved` can't re-fire it. Instead the queue restores `plan/approved` as the standing gate (a bot applying it does **not** trigger `implement`, which checks `sender == APPROVER`) and then applies `agent/dev`, which `dev-bounce` admits for a bot PAT when `plan/approved` is present. The dev route builds `agent/issue-N` from `main` on first run — exactly a first build. No guard relaxation; the human-approval invariant is preserved. ### Notes - Only `dispatch.yaml` changes; the `tick` timeout goes 2 → 10 min (runbook §3). - Kill switch honoured: `AGENTS_ENABLED != true` ⇒ no-op. - Validated: `js-yaml` parse + `bash -n` of the tick script; live smoke-test of the candidate-gather + FIFO/batch logic against the API. Part of the epic: valssi/ops#1. Merges are human-only. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
ellen merged commit 386b713d48 into main 2026-07-21 11:29:42 +00:00
ellen deleted branch phase4-tick-queue 2026-07-21 11:29:42 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
valssi-public/agent-workflows!8
No description provided.