Skip to content

design(queue): budget-aware claiming — parks carry a minimum required time budget, claim matches the claimer's remaining shift budget #3418

Open

Description

@dezren39

Proposal (Drew, 2026-11-01 ~02:26 CST)

Parks should be able to carry a minimum required time budget, and claiming should match tasks against the claimer's remaining shift budget. A task that needs a dedicated full shift should be claimable immediately by any worker that actually has the budget — instead of sitting out an arbitrary clock delay that no worker may override.

Why

The park mechanism conflates two different waits:

  1. External-wait — CI, a Codex review, a quota reset. Time is the readiness signal; not_before is correct here.
  2. Capacity-wait — the work is ready now; the claimer is what lacks room. Time is the wrong signal: a fresh shift starting 10 minutes later has the budget, and a shift ending in 10 minutes never will, no matter when the park expires.

Tonight's evidence: opencode task 5256 (issue opencode#1014, Drew-prioritized, expedite, effort/l, 120-min timebox) was claimed by a lane near the end of its shift, scoped, and parked 3600s purely so a future full shift would take it. During that hour no lane may claim it — the not_before gate is hard for every lane regardless of budget — and the opencode queue has a single lane anyway, so "another lane picks it up" does not exist there. The claim itself also had no budget check: the lane only discovered the mismatch by claiming first.

Design sketch

  • A park (and a packet) may declare required_budget_minutes — the minimum uninterrupted budget a claimer must have. Packet timebox_minutes is the natural default source.
  • claim_repo_task accepts the claimer's remaining budget (the lane/shift computes it from its own start time and budget cap) and only matches tasks whose requirement fits. Tasks with no requirement behave as today.
  • Lane/shift instructions pass their real remaining budget on every claim — including the first claim of a shift (full budget) and later ones (remainder), so an oversized task is never claimed just to be re-parked.
  • External-wait parks keep not_before unchanged; the two conditions compose (both must pass).

Acceptance

  • A capacity-parked task with required_budget_minutes: 120 is claimable immediately by a worker declaring >= 120 minutes remaining, and is skipped (not claimed, not re-parked) by one declaring less.
  • Lane instructions for all four queues pass remaining-budget on claim.
  • Existing external-wait parks behave exactly as before.
  • Worked example recorded on completion: a 5256-shaped task flowing to the first full-budget shift without a clock wait.

Cross-ref: opencode#1014 (the fix whose implementation task surfaced this).

Activity

  1. added
    priority/highImportant and time-sensitive
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 1, 2026
  2. developing-today commented on Nov 1, 2026

    @developing-today
    Contributor
  3. dezren39 commented on Nov 1, 2026

    @dezren39
    MemberAuthor

    Design input from the dsh-superagent comparison (full standalone analysis: #3450; Drew directed posting the adoptable set here, 2026-11-01). Items for THIS issue:

  4. added
    expediteImportant - do this very soon, before anything not expedited
    on Nov 1, 2026
  5. dezren39 commented on Nov 1, 2026

    @dezren39
    MemberAuthor

    Transferred from Slack #alignment at Drew's direction (2026-11-01). Aster (@drewrypope-aster) reviewed the dsh-superagent design package (#3450 / #3424 / #3418) in the thread on Muse's 03:29 CST pass; her replies are below verbatim (formatting converted from Slack mrkdwn to GitHub markdown; wording unchanged). The identical text is posted on all three issues so each record is self-contained.


    Aster's acknowledgment (03:29 CST):

    I’ll review the package against the original dsh docs, focusing on genuine weaknesses, the deliberate differences worth challenging, and possible misreadings. I’ll treat Drew’s sketches as design direction and keep this to review, with findings returned here.


    Aster's review (03:33 CST):

    Reviewed #3450, #3424 and #3418, including their comments, against dsh docs 000–008. My conclusion: the shared architecture is real, but “same path, mostly plumbing to borrow” understates their strongest advantage. Their docs specify ownership and recovery across transitions more precisely. Our proposed schema is richer in some areas, but records alone do not establish those guarantees.

    This is a documentary design review, not a runtime audit of either system. I would distinguish “implemented,” “proposed,” and “verified” rather than count “have (in design)” alongside shipped capabilities.

    Where I would correct the comparison

    • Merge authority: dsh does not categorically require humans to merge. Its Executor can enable auto-merge through another explicitly named account’s CLI. Human merge is the fallback. The real comparison is attribution and readiness safeguards: their defaults require an own-Ticket PR, approvals covering the head, fewer than 200 changed lines, and withdrawing auto-merge before a new revision. Keep delegated merge authority, but compare its safeguards rather than calling it an inversion. 003: Merging
    • Observe-first: they explicitly permit graduating to auto. Our mature-auto posture plus observation for new or materially changed producers is compatible. Their mode is Policy-level; per-producer modes are our adaptation. Explicit requests work in every mode, which matters when defining what “off” means. 002: Accept modes
    • Reserved capacity: their extra slot lets a human message/status request continue an existing Ticket and precedes new launches. It does not interrupt active work or give a newly queued expedited task a full shift. #3418’s proposal is a new scheduling policy, not direct adoption. Raising a bundle cap cannot give a worker with ten minutes left the 120 minutes a task needs. 003: Concurrency
    • Expiration: the 24-hour/latest/undismissed rule applies to unavailable Eval Decisions shown for attention, not all unanswered Attention questions. Do not age out Drew’s pending decision by importing it. 002: Unavailable Decisions
    • Storage and reconstruction: dsh describes aggregate JSON rows with generated working-set columns, not normal-form consensus. Retained Decisions/dispositions also do not establish full historical state reconstruction. #3424’s “resurrect any moment” is a stronger proposed contract with its own proof burden. 007: Persistence
    • Waiting and escalation: they reject Eval scheduling delayed Triggers, not all persisted timers in the core. Queue-native not_before is compatible with that separation. Likewise, one concrete question can include options, consequences and a recommendation. Their questions return through chat too; this is not “panel questions versus substantive chat.” 001: Rejected concepts, 004: Prompts
    Where our design needs stronger contracts

    1. Authorization, execution identity and relationship provenance are different things. Runtime/session/host/pid/IP explains who wrote. A grant reference explains who authorized what scope under which rule/version. A derivation basis explains why a link exists. None substitutes for the others. Add claim-generation/fencing semantics so an expired worker cannot write after its replacement claims the task. Context and inferred links must never silently expand authority.
    2. Durable input ownership and external-effect reconciliation come before more vocabulary. dsh specifies stable source-event IDs, cursor advancement after storage, follow-up ownership/hand-back, consumed-input accounting, and replacement Assignment recovery. Its cookbook also addresses remote success followed by local failure using outbound idempotency. An outbox must handle “GitHub accepted the comment; the drainer crashed before recording success.” Task mutation, event and effect intent should commit together; delivery needs a stable identity and reconciliation, not blind retry. Renewable task dedupe is not immutable event identity. 003: Restart, 008: Cookbook
    3. Attention needs a lifecycle, even if stored as a note type. Give each question identity, an answer binding, and open/resolved/superseded state. Deriving waiting-on from “last note type” is unsafe: a later finding must not hide an unanswered question. Keep all underlying blockers even if one precedence rule chooses the displayed stage. That is what makes a chat readout trustworthy without requiring another UI.
    4. Inferred blockers need satisfaction and retraction rules. An issue, its queue task and a PR claiming to close it are not interchangeable proof of completion. Cancelling the task or closing the PR unmerged must not unblock its dependent. Track the assertions supporting an inference so withdrawing one basis removes only its unsupported consequences, not an independently deliberate link. Pairwise links can support this; no general graph framework is required.
    5. Budget fit needs a starvation story. A maximum timebox is not necessarily the minimum uninterrupted budget. If a task requires 120 minutes but no lane can ever offer that, repeated skipping is not successful scheduling. Preserve the fit predicate under priority overrides, identify impossible fits, and specify whether human-priority work gets a fresh eligible worker, reserved start capacity or checkpointed yielding. Keep external-condition readiness separate from a recheck time: elapsed CI wait does not prove CI passed.
      Pushback on the deliberate differences

    Keep fresh shifts, phone-friendly chat/GitHub, and queue-native waits. But fresh context does not itself guarantee no compaction or no waiting; those require actual runtime bounds. Per-task workspace isolation also does not require a long-lived session.

    I would narrow “GitHub-canonical” to human discussion and code artifacts, then state authority per field. Queue leases, admission decisions, skipped inputs and pending effects are not automatically auditable from the repo because notes are mirrored. Define reconciliation and avoid two competing sources of truth.

    Do not copy dsh’s trust model wholesale: its workers run as the operator OS user, and the docs explicitly say wrappers/directories are not a security boundary. Its live Mandates also survive Policy changes, with notifications rather than automatic revocation. Those are tradeoffs to examine, not safety guarantees to inherit. 006: Isolation

    Five acceptance cases I would put ahead of implementation splitting

    • Cancel the task representing a blocking issue and close its resolving PR unmerged: the dependent remains blocked.
    • Open Q1, append a finding, supersede it with Q2, then receive Q1’s late/duplicate answer: Q2 remains correctly unanswered and work does not resume twice.
    • Present an expedited 120-minute task to a worker with ten minutes left: no cap override claims it; a fresh eligible worker can.
    • Crash after GitHub accepts an effect, then resume the old worker after lease reassignment: reconcile delivery and reject stale ownership writes.
    • Evaluate inferred work in auto, switch to observe before acceptance, then replay the event: no stale acceptance or duplicate execution.
    My recommendation is to retain the overall direction and revise the comparison before using it as design justification. Prioritize authority/ownership, atomic transitions and recovery, then structured attention and blocker semantics. The detailed link model and budget matching remain promising fleet-specific contributions; their value needs to be demonstrated by those failure cases. No implementation or issue changes made.

  6. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  7. added
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 3, 2026
  8. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · parked

  9. 193 remaining items

  10. dezren39 commented on Nov 6, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

  11. dezren39 commented on Nov 6, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

  12. added
    queue/claimedQueue worker lifecycle state
    and removed
    status/parkedDeliberately paused with a recorded resume condition
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Nov 6, 2026
  13. dezren39 commented on Nov 6, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    task: 9570
    lane: c29174f1-48e0-4b13-b4ff-9b73ab67e9ab
    state: picked-up
    issue: #3418
    at: 2026-11-06T10:42Z

    Claimed task 9570 for fresh triage. Current GitHub check: #3418 is OPEN with no hard-stop labels. The packet appears internally inconsistent: its issue field/title identify #3418, while scope, evidence, and context refs identify #3205; I am verifying the packet defect before any task work.

  14. added
    queue/blockedQueue or user escalation state
    status/blockedQueue or user escalation state
    and removed
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    on Nov 6, 2026
  15. dezren39 commented on Nov 6, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    task: 9570
    lane: c29174f1-48e0-4b13-b4ff-9b73ab67e9ab
    state: blocked
    issue: #3418
    at: 2026-11-06T10:47:54Z
    reason: packet_defect

    Task 9570 is blocked because the packet conflicts about its target: task/title/issue identify #3418 (budget-aware claiming), while scope.include, evidence, context_refs, and the problem narrative identify #3205 (per-repo hygiene census). Fresh GitHub checks confirm #3418 and #3205 are different OPEN issues. No safe way to infer intended work; please correct the packet target and retry/re-enqueue. No code changes or follow-up task created.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

expediteImportant - do this very soon, before anything not expeditedpriority/highImportant and time-sensitivesource/creatorFiled by the new-issue-creator jobtask/triageQueue packet kind: verify, reproduce, and route this item

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions