Repository navigation
Description
Direction (Drew, 2026-11-01 ~02:40 CST)
Make the repo-queue data model durable — "make this system to last." Six pieces, one design:
1. External waits take a real datetime
Today park accepts only --delay-seconds; the not_before column is a timestamp and enqueue already accepts an absolute datetime (helper example: 2026-10-25T12:00:00Z), but a mid-work park cannot name one. External events have known instants (a quota reset, a review window): park should accept an absolute not_before datetime as well as a relative delay.
2. Blockers are links, not text
A task's blockers are recorded as typed links — to other queue tasks (preferred: they are queryable, so claim can exclude a task whose blocker task is incomplete, and completing a blocker can surface its dependents), and to PRs and issues. Today block stores a free-text reason in progress/last_error; nothing can query it, so blocked-on relationships are invisible to the claim query.
3. Long parks get re-verified on a schedule
A maintenance check re-verifies every long park per item on a cadence (default daily): are the linked blockers still real, has anything changed around them that the time, the queue state, or the GitHub number doesn't capture? The check writes last_checked_at and its outcome onto the item; a park confirmed still-valid stays parked untouched; a stale park is flagged with a note (piece 4) for pickup or release.
4. Status reason column + a notes table, mirrored out
Every status transition records a status_reason, which automatically lands as a row in a notes/comments table (task, actor, kind — status_reason / finding / handoff — body, timestamp). Findings and notes from previous pickups, and insights from related items, accumulate there instead of evaporating between shifts. The system comments notes back automatically (to the linked GitHub issue) so the record lives where the work is discussed.
5. Full event history — resurrect any moment
An append-only events table records every change to a task (status, priority, park, claim, links, notes) with before/after values and the actor. Any past state of any task is reconstructable from the event stream.
6. Actor provenance on every write
Every create/update records who made it: lane, runtime (opencode / Muse / whichever system), session id, hostname, pid, ip address, task id and the task's start, and — at creation — which system found/filed the originating issue. Provenance rides on tasks, notes, and events alike.
Migrations question (part of the design's scope)
Schema changes for this system should land as proper versioned migrations, in order, in a repo — the design must first inventory how the muse-dev Supabase schema (agent schema: tasks, claim/park RPCs) is currently changed, and establish the migration discipline before adding pieces 1–6.
Acceptance
- Design record covering pieces 1–6: schemas for blocker links, notes, events; the park-datetime change; the revalidation check's cadence/config and where it runs; provenance field set.
- Migration discipline decided and the current schema state inventoried as the baseline migration.
- Implementation packets split per piece and enqueued, each independently landable.
Related: #3418 (budget-aware claiming — the claim-side companion; blocker links and budget requirements both belong in the claim query), opencode#1014 task 5256 (the capacity-wait park that started this line of design).
Activity
dezren39 commentedon Nov 1, 2026
Design amendment from Drew, 2026-11-01 ~03:04 CST — notes typing/tagging and a standard link classification with inference. Extends pieces 2 and 4 of this issue.
Notes and items carry types and tags
Links have three axes
Every link between items (queue tasks, issues, PRs) records:
direct(a human/agent added it),inferred(the system derived it, rules below), orrelated(system-suggested association, weakest).hard_block(claim must exclude the dependent),soft_block(ordering preference only — ideally after, never a stop), or none. The claim query consumes semantics, never raw kinds.Standard link classification (v1 vocabulary)
Start from the Jira link set (relates-to, blocks/is-blocked-by, duplicates/is-duplicated-by, clones, causes/is-caused-by) and extend:
blocks→ converts to hard_blockideally_after→ converts to soft_blockrelated→ no blockhandled_together— convergent/associated: would be good handled together or under one design (includes aneeds_design_togetherflavor)causes/caused_byduplicate/overlap— overlap is the partial case (shared scope, neither contains the other)xor/conflicts— either/or: doing one forecloses or collides with the otherSemantics of the soft kinds (handled_together, ideally_after, overlap) are deliberately NOT pinned yet — Drew: "can figure out what to make that mean later." The vocabulary, provenance, and conversion-to-blocking layer land now; the soft-kind behaviors are an explicit design TBD, not a blocker for the rest.
Inference rules (system-added links, always marked inferred)
dezren39 commentedon Nov 1, 2026
Clarification from Drew, 2026-11-01 ~03:09 CST, binding on how to read the link-classification amendment above: his examples are DIRECTION, not specification. The kind / derived-effect / provenance layering, the vocabulary names, and the inference examples sketch the kind of thing the model should have — where exactly the line sits between a link kind and a derived effect is itself an open design question for this issue to settle. What is firm: blockers must be queryable, blocking behavior must be derivable rather than hand-maintained, system-added links must be honestly distinguished from direct ones, and notes/items are typed and tagged. The design owns the final model; do not implement the sketch literally.
dezren39 commentedon Nov 1, 2026
Further clarification from Drew, 2026-11-01 ~03:10 CST: the direct / inferred / related provenance split is itself NOT fixed either. The design may choose different categories, restructure the axis, or add subfields — whatever fits the model best. Same status as the kind/effect line: illustrative, open to redesign; only the underlying intent (system-derived relationships must be honestly distinguishable from deliberately-added ones, in some form) is firm.
dezren39 commentedon Nov 1, 2026
Structural note from Drew, 2026-11-01 ~03:11 CST: links are mostly POINT-TO-POINT (pairwise between two items) — model them that way rather than inventing group/graph constructs the use cases don't need. And the schema should follow NORMAL FORM: break out into multiple proper tables as appropriate (links, notes, events, tags, link types as their own relations where that fits) instead of JSON blobs on the task row. Same status as the other notes: sound default structure, design may adjust where it can justify it.
dezren39 commentedon Nov 1, 2026
Storage-shape ruling (Drew asked for a judgment call, 2026-11-01 ~03:13 CST): NORMAL FORM is the default and is right for everything the system queries — links, notes, events, tags, blockers, provenance keys. JSONB is the most appropriate tool in exactly four pockets, and is sanctioned there: (1) the task PAYLOAD/packet — an opaque, versioned document (repo-task/v1) authored and consumed whole, never queried by field; (2) event DIFF/snapshot payloads — each event is a proper row (type, actor, timestamp as columns) carrying its before/after as JSONB, since normalizing arbitrary field changes makes reconstruction queries worse, not better; (3) a provenance EXTRAS bag alongside the fixed provenance columns, for the long tail of environment facts nobody filters on; (4) checkpoint/progress SCRATCH — write-heavy, read-whole, shape varies by kind. Graduation rule: any JSONB field that starts being queried graduates to a real column or table via migration. What must NOT happen is today's failure shape: queryable state (blockers, reasons, history) buried inside a progress blob.
dezren39 commentedon Nov 1, 2026
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's design:
attentiontype with those fields; lane escalations write the note and the chat line renders it; the morning readout lists open attention notes instead of re-deriving them.status_reasonstays the human gloss. Also absorbs design(queue): budget-aware claiming — parks carry a minimum required time budget, claim matches the claimer's remaining shift budget #3418's external-wait vs capacity-wait as two rows of the one table (§3.3 of analysis: dsh-superagent-prototype vs our fleet — findings and adoptable ideas #3450).reason_codefrom one controlled vocabulary (seed: ci_wait, codex_review, quota_reset, capacity, blocked_on_task, drew_decision, upstream_pr, …) beside the free-text body; terminal verbs validate the code. One vocabulary rendered for agents, humans, and views.developing-today commentedon Nov 1, 2026
CODE-1308
dezren39 commentedon Nov 1, 2026
Correction to this issue's migrations premise (2026-11-01 ~02:52 CST): proper migrations DO exist. The muse-dev chain lives at ~/workspace/supabase/muse-dev/migrations/ — but the live tree held only 0015-0019; links 0001-0014 (including 0008_repo_queue_pilot, 0009_cancel_repo_task, 0012_claim_park_resume_attempts, 0014_revive_on_enqueue) survived only in a trashed 2026-10-28 snapshot. Those files have now been restored into the live migrations directory (25 files, 0001-0019, verified by listing), so piece 0 of this design changes from "establish a migration discipline" to: verify the restored chain against the live schema (hand-applied changes since 2026-10-28, if any, are still unrecorded) and land all six pieces as new migrations in the existing chain. The ad-hoc SQL observation stands only for post-chain drift, which the design should inventory.
dezren39 commentedon Nov 1, 2026
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
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.
127 remaining items
dezren39 commentedon Nov 4, 2026
🤖 Agent note · handed off
dezren39 commentedon Nov 4, 2026
🤖 Agent note · picked up
dezren39 commentedon Nov 4, 2026
🤖 Agent note · parked
dezren39 commentedon Nov 5, 2026
🤖 Agent note · handed off