Repository navigation
Description
Standalone analysis commissioned by Drew, 2026-11-01: full comparison of DeepSeek's dsh-superagent-prototype against our repo-health fleet — same-path check, concept mapping, adoptable ideas (fed into #3424 and #3418), and the deliberate differences we keep. Full text below; also sent to Aster for review.
DeepSeek dsh-superagent-prototype vs. our repo-health fleet — comparison & adoptable ideas
Date: 2026-11-01. Scope: whole system, not just code#3424.
Sources read: their docs/000-philosophy.md, 001-domain.md, 002-authorization.md,
003-execution.md, 004-prompts.md, 005-panel.md, 007-architecture.md
(006-deployment / 008-cookbook not read). Ours: goal GOAL.md, code#3424 + newest
comments, code#3418, opencode#1014 + directive comments, fleet instruction files,
standing Drew rules (merge authority, quota doctrine, decision surfacing).
Every claim about their system cites the doc it came from. Nothing posted to GitHub.
1. Their core concepts (compact)
Philosophy / operating stance
- Prime metric: take as little human attention as possible, give as much value as
possible; every message, notification, question, setting, and panel element must
earn its attention cost or be removed (000-philosophy). - Acts only when asked, or when a written rule allows it; unrequested work starts
in a record-only mode (000-philosophy, 002-authorization). - Speaks only when a person must act or can use a result; confirms a request once,
stays quiet while working (000-philosophy, 004-prompts). - One concrete question at a time, in structured form (000-philosophy; implemented
as the Report's structured question field, 001-domain / 003-execution). - Stops by impact, not effort: local change → reviewable result; a change needing
a design decision stops with a clear question (000-philosophy). - Honest reporting: drafts marked unfinished, failures reported as failures,
limits never bypassed to avoid asking (000-philosophy, 004-prompts).
Domain (001-domain)
- Source — an event stream (kind + instance config); holds its read position and
bot identity; drops the bot's own messages before they enter the domain. - Trigger — one immutable event; the unit of audit and idempotence (accepting it
twice creates one Ticket). - Thread — Triggers in time order; at most one Eval at a time; holds
Subscriptions and Decision history. - Eval — stateless judgement on a batch of Triggers in two layers: a deterministic
Gate, then model Assessment. Output is a Decision: accept / stop / ignore /
unavailable. - Mandate — what an accept grants: Policy version, scope, strength, matched
rules, sender identity. Immutable; wider scope = new Ticket; only a person's
stop withdraws it; revalidated against current Policy before an ended Ticket
resumes. - Ticket — the unit of authorized work; open → ended → resumable by a person's
message on its Threads; defines its own state, independent of the Executor. - Assignment — binding of a Ticket to one Executor instance; a Ticket has several
over time; pending → running → ended independently of the Ticket. - Subscription — many-to-many Ticket↔Thread relation; fan-out delivers Thread
messages to live Tickets as context with no authority check; context-only
subscriptions lend context but no authority and do not resume. - Correlation — relation between Threads sharing a Trigger; adds context, never
routes. - Channel — the write side of a Thread (acks, replies, PRs, review replies).
- Policy — versioned assessment rules + per-Source parts (allowed list, admission
table, bot list); a Policy change notifies affected live Tickets but does not
revoke their Mandates. - Attention — a structured question on a Ticket waiting for a person's answer.
- Disposition — the record of where each Trigger went (filtered / evaluated /
fanned out / handed back / answered). - Report — the Executor's structured state report to its Ticket: progress /
waiting / ready / blocked / failed / dropped, plus an optional question. - Explicitly rejected concepts (001-domain "Rejected concepts"): cross-Source
identity mapping, Eval scheduling its own delayed Triggers (waiting belongs to
Sources), waiting/revoked Eval states, one-live-Ticket-per-Thread, Ticket state
following the Executor session, an Executor declaring a person asked to stop,
cancelling running Tickets on Policy change, inferring "waiting on a person"
from free-text reports.
Authorization (002-authorization)
- Strength: explicit (allowed person addresses the agent, or follows up on a
Thread with a Ticket) vs inferred (bot on the bot list, unlisted follow-up,
admission-cell candidates). Bots can never make explicit requests or stop work. - Admission table per Source: rows = receiving scopes, cells decide
explicit / inferred / ignore by sender membership × addressed-or-not. - Accept mode per Policy:
off/observe(default; inferred accepts are
recorded as "would accept" and nothing starts) /auto. Explicit requests
work in every mode. Proactive accept requires ≥1 matching rule, and every
enabled rule is judged exactly once per assessment. - Follow-up ownership: a message on a Ticket's Thread is owned by that Ticket's
Executor (no Eval); the Executor handles it in-scope or hands it back once,
with a reason; only when no Ticket owns it does it go to fresh Eval. The main
Session may act on an owned follow-up only to stop work. - Revalidation before resume: an ended Ticket's Mandate is checked against
today's Policy (mode, rules still enabled, sender still listed, bot still
listed); failure = the Ticket stays ended and its waiting messages re-enter
the intake path as unowned. - Eval failure discipline: an expired Eval requeues twice, then records
unavailable; assessment failure also recordsunavailable; Policy change
mid-Eval recordsunavailableand requeues under the new version immediately.
Execution (003-execution)
- Ticket stages are derived, not stored: a precedence table (first match wins)
computes the stage from facts — input-undelivered, has-Attention, latest
Report ready / blocked / failed, queued, idle (waiting), working. Aperson/*
stage means the Ticket cannot continue without a human. - One Executor Session + one directory per Ticket (
worker-<ticket id>);
prepare command (typicallygit worktree) runs once before the first
Assignment; a PR belongs to the Ticket when its branch's last segment matches
the Ticket's short name. - Worker slots: a Ticket holds a slot through background work; background work
gets ≤30 min after turn end, then shell jobs are killed and the Ticket reports
waiting with which jobs were killed. One extra slot beyond the concurrency
limit is reserved for a person's message or a status request, and human wakes
take priority over new launches. - Blocked/failed hold: on a
blocked/failedReport the Ticket takes no
automatic Input (CI/bot messages are recorded, not delivered); transient
provider/network failures (408/429/5xx, refused/reset/timeout) retry 3× with
growing backoff before the hold; a person's message, a non-blocked Report, or
a manual Retry ends the hold. - Stored work: side effects are stored first, executed after (transactional
outbox); retries with doubling backoff; a kind of work surfaces as a system
problem only after 3 consecutive failures of an item. - Restart recovery: interrupted Assignments restart with a recovery note ("check
directory, git history and GitHub before repeating any outside action"),
oldest Ticket first; read/unread Input accounting survives restarts, and a
replacement Assignment re-receives exactly the Inputs the old one never took. - Pause processing: stops dispatch, Evals, deliveries and replies; Sources keep
recording Triggers; running turns are not interrupted; Eval deadlines shift
by the pause length. - Merge governance is prompt text ("Delivery requirements"), not host logic:
the agent account never enables auto-merge (attribution goes to whoever
enabled it); default rule allows auto-merge only for the Ticket's own PR,
ready, approvals covering the head commit, <200 changed lines. - A Ticket following PRs ends when none of the PRs it opened remain open (or all
followed PRs closed); outcome = the last relevant close; it keeps its
Subscriptions afterwards so a later human comment resumes it.
Panel (005-panel)
- The panel answers three questions in order: (1) does anything need me now?
(2) is the system healthy and doing the right things? (3) what is the history
of one piece of work, Trigger → Eval → Ticket? - Overview lists Tickets needing action first; a healthy state takes no space;
every count equals the length of the list it links to; a label says whom a
row waits for and what it needs, not an internal status code; problems must
be actionable (a one-off network error is not enough); rows needing a person
offer their action (Retry, stop, dismiss, evaluate-again) directly. - An
unavailableDecision asks for human attention only when <24h old, still
the latest on its Thread, undismissed, and the Thread is neither queued nor
evaluating.
Prompts (004-prompts)
- Prompt assembly has a fixed precedence ladder: (1) facts enforced by tools/
host, (2) built-in + generated sections as overridden, (3) a proactive
Ticket's matched-rule requirements for that Ticket only, (4) team sections
and skills, (5) outside text — data, never authorization. - The Policy section is regenerated from settings on every model request and
placed last, so a Policy change leaves the preceding prompt text unchanged. - Prompts and settings are immutable versions with base-revision optimistic
concurrency; a conflicting save is refused without discarding the draft;
Sessions read the latest version on every request, even mid-turn; an override
identical to the default is deleted so the part follows future defaults. - Role split: the main Session only routes (forwards the original Trigger +
routing facts, no technical decisions, routing note ≤30 words, one routing
call batches up to 20 decisions); Executors read original sources, judge
scope, implement and verify. The main Session never waits — a host guard
refusessleep, shell timeouts >30s, and job waits >5s. - Chat messages: one sentence by default, hard limit 100 words; main-Session
coordination notes to a Ticket ≤100 words and grant no authority.
Architecture (007-architecture)
- One Engine is the only writer of Triggers/Threads/Decisions/Tickets/
Assignments; every command mutates its aggregates in one transaction; ports
enqueue external work inside the transaction and adapters perform it after
commit (afterCommit). Callers get only their role'sPickof the Engine
(Sources / Main Session / People / Settings / Executor). - Effects: a durable side-effect queue (kind/key rows; re-enqueueing a waiting
key replaces its payload without changing queue order); per-kind handlers
with their own concurrency and backoff; throwingLaterdefers without
counting a failure. - Decisions record structured
reasons: a code + values (+ per-Trigger id),
rendered to text for agents and panel from one code table. - Persistence: one SQLite file; domain tables per aggregate plus a
dispositiontable, aneffecttable, anoutboxreceipt table (a message
id is never queued twice; dropped messages keep when/why), and typed KV.
Generated columns (open,active,subscribed) index exactly the working
set a pass must read. Schema version only increases; nothing deletes old
records yet (named as a known unbounded-growth gap). - Reasons, stages, and health have single definitions used by core, panel and
prompts alike ("one writer per state", "one place per concept").
2. Concept-by-concept mapping to our system
Legend: have = we do this today in substance · partial = shape exists,
weaker or by convention only · lack = no equivalent.
A. Intake, authorization, work acceptance
| Their concept (doc) | Ours | Verdict |
|---|---|---|
| Source with read position, own bot identity, self-messages dropped pre-domain (001) | Producers (sweeps, new-issue-creator, pr-diff-review, pr-comment-review, fleet monitor, conductor) write packets to per-repo Supabase queues; GitHub is the event surface; watermarks exist per producer (e.g. pr-review-state.json) | partial — positions/watermarks exist per producer, no single Source abstraction, no uniform "own output never re-enters" filter |
| Trigger as immutable unit of audit + idempotence (001) | repo-task/v1 packets with dedupe keys (fix/triage/pr families); enqueue revives on duplicate key (migration 0014) |
partial — dedupe gives idempotent enqueue, but the packet is a work order, not an immutable record of the originating event with its actor |
| Gate (deterministic) + Assessment (model) as two Eval layers (001, 002) | Label hard-stops at claim (held, user/owned, do-not-merge, do-not-auto-edit) + lane judgement during triage kinds | partial — the deterministic layer exists as label checks inside claim/revalidation; the judgement layer is the lane itself, not a separate recorded Decision |
| Decision as a recorded object with structured reasons (001, 007) | Triage outcomes recorded as issue comments (agent-note:v1) and queue status; reasons are free text in progress/last_error |
lack — no Decision record, no reason-code vocabulary; this is exactly what #3424 pieces 4–5 would build |
| Mandate: immutable grant w/ Policy version, scope, strength, matched rules (001, 002) | The packet is the closest analog: scope + timebox + payload, frozen at enqueue | partial — packet carries scope but no strength, no rule provenance, no version of the rule set it was admitted under |
| Strength explicit vs inferred (002) | Drew's direct directives vs fleet-inferred work (sweep findings, producer packets) — real distinction, nowhere recorded | lack as data; have as practice (Drew escalations short-circuit everything) |
| Admission table per Source (002) | Producer charters in job bodies (what new-issue-creator / pr-diff-review may file, caps per run) | partial — rules exist as prose in cron bodies, not as data consulted at intake |
| Accept modes off / observe / auto (002) | Pilot Phase 0 ran a 48h shadow before live cutover (GOAL.md); since then producers run auto permanently |
partial — we did observe-mode once, at system level, by hand; no per-rule or per-producer mode |
| Follow-up ownership + hand-back with reason (002, 003) | PR shepherd tasks and resume-briefs approximate it: a parked task's follow-up work returns to the same queue item; lanes hand off via handoff snapshots | partial — ownership is by queue item, not by conversation thread; hand-backs are prose in comments, not a routed object with a reason code |
| Revalidation of the grant before resume (002) | Lanes revalidate against fresh GitHub state (labels first) on every claim/resume — a strong, enforced habit (§ instruction) | partial — we revalidate the work's state rigorously; we do not revalidate the authority (e.g. a label Drew set since, a rule that changed) as a distinct check — in practice labels cover most of it |
Eval timeout → requeue ×2 → unavailable + health surfacing (002) |
Task attempts cap (max_attempts) + lease expiry returning tasks to queued; fleet monitor flags dead-in-queue | partial — caps exist; the "terminal undecidable" state and its dedicated surfacing do not (dead-in-queue repair is manual/operator) |
B. Queue data model (code#3424 / #3418 territory)
| Their concept (doc) | Ours | Verdict |
|---|---|---|
| Ticket defines its own state, independent of Executor (001) | Task row holds status; lanes are interchangeable claimers | have — this is already our shape, and #3424 keeps it |
| Assignment separate from Ticket, several over time (001) | Claim/lease + attempts on the task row; lane-execution ledger exists (migration-era) | partial — attempts counted, but no first-class assignment record with its own lifecycle; #3424 piece 6 (provenance) covers who, not the binding as an object |
| Derived stage from facts, precedence table, "whom does it wait for" (003, 005) | Stored status enum (queued/claimed/parked/blocked/done) + free-text reason | lack — #3424 piece 4 adds status_reason; a derived "waiting-on" classification (CI / review / person / budget / external) computed from facts is not in the design yet — adoptable (see §3.3) |
| Structured Report vocabulary: progress/waiting/ready/blocked/failed/dropped + structured question (001, 003) | Terminal verbs complete/park/block + checkpoint text; escalation to Drew is prose in chat | partial — verbs map roughly (park≈waiting, block≈blocked), but the question for a person is not a structured field anywhere; escalations are hand-written chat lines |
| Attention as a first-class object (001) | user/escalated label + backlog entries + chat lines |
lack — no queryable "questions waiting on Drew" set; the morning readout assembles it by hand each cycle |
| Disposition: every Trigger's fate recorded (001, 007) | Sweep logs, backlog files, lane handoff snapshots — per-producer, prose | lack — #3424 piece 5 (events) covers task changes, not intake fates (what a producer saw and skipped, and why) |
| Subscriptions / fan-out to live work (001) | Shepherd tasks poll their PRs on park-resume; fleet monitor watches in-progress items hourly | partial — polling by schedule instead of subscription; works, costs cycles |
| Correlation adds context, never routes (001) | #3424 links: related kind adds context; claim consumes only derived hard/soft block semantics |
have (in design) — the newest #3424 comments independently converged on this: kinds + provenance + derived blocking semantics, claim reads semantics only |
| Typed links with provenance, system-inferred links marked (their Disposition/hand-back reasons, 001/007) | #3424 amendment: kind × provenance (direct/inferred/related — explicitly not pinned) × derived effect; inference rules (issue-blocker ⇒ its queue item; PR closing a blocked-on issue joins the chain) | have (in design) — theirs is thinner here; our link model is already the more developed one |
| Append-only history, reconstruct any moment (their disposition + decision tables, 007) | #3424 piece 5: events table with before/after (JSONB diff pocket per storage ruling) | have (in design) |
| Actor provenance on every write (007's Mandate basis + Decision reasons) | #3424 piece 6: lane, runtime, session, host, pid, ip, originating system | have (in design) — ours is more detailed than theirs |
| Normal-form tables + generated working-set indexes (007 Persistence) | #3424 storage ruling: normal form default, JSONB in four sanctioned pockets, graduation rule | have (in design) — same instinct; their generated-column trick is the concrete mechanism worth copying (§3.8) |
| Budget-aware claiming: match work to claimer capacity (— they have worker slots instead, 003) | code#3418: required_budget_minutes on park/packet, claim takes claimer's remaining shift budget; external-wait vs capacity-wait split |
have (ours, in design) — they solve the adjacent problem (slot accounting + human-priority slot), not this one; #3418 is genuinely ours |
| Park revalidation on a cadence (—) | #3424 piece 3: daily re-verification of long parks writing last_checked_at + outcome |
have (ours, in design) — no analog in their docs; their nearest is Mandate revalidation at resume |
C. Execution, sessions, routing (lanes + conductor + router; opencode#1014)
| Their concept (doc) | Ours | Verdict |
|---|---|---|
| One session + one directory per work item, prepared by a prepare command (003) | Lane shifts claim many tasks sequentially in shared worktrees on the laptop; sessions are per-shift, not per-task | lack — deliberately different (§4), but their per-item directory discipline is what our worktree-per-task hygiene approximates by instruction |
| Worker slots with a reserved +1 human-priority slot (003) | Fixed lane counts per queue (code 6 lanes at peak design, opencode/openchamber/nix 1 each); Drew's messages don't preempt a lane mid-shift — they wait for a shift boundary or the main chat acts directly | lack — no priority lane for Drew-originated work inside the queue system; the main chat is the priority slot, informally |
| Background-work slot accounting: turn ending with jobs running keeps the slot, 30-min cap, kill + report (003) | Shift budget ~90 min; lanes park instead of waiting (CI, reviews); a task never just stops (§10 anti-evaporation) | partial — park-don't-wait is the same instinct; we bound by shift, they bound by per-item background window |
| Blocked/failed hold: no automatic input delivered while held; transient provider errors retry 3× backoff first (003) | Blocked tasks sit until operator/fleet-monitor action; provider-error handling lives in the router (#1014), not the queue | partial — split across two systems in ours; their rule "a hold is a state computed from stored Reports/Inputs, so a restart keeps it" is a property our blocked state has via the DB |
| Stored-work / transactional outbox: store first, execute after commit, per-kind backoff, surface after 3 consecutive failures (003, 007 Effects) | Supabase queue + cron/hook triggers + signal chaining; GitHub comments posted directly by lanes | partial — the queue itself is durable, but side effects (comments, enqueues, signals) are fire-and-forget from the lane; no outbox, no per-kind failure accounting |
| Restart recovery note + re-delivery of exactly the untaken inputs (003) | Lane handoff snapshots (per lane/queue JSON) + resume briefs on parked tasks; new shift re-derives state from GitHub + snapshot | partial — same goal, prose mechanism; theirs is exact because read/unread is tracked per Input; ours re-verifies fresh each claim (stronger against staleness, weaker on continuity) |
| Pause processing (dispatch/evals/deliveries stop; intake continues; deadlines shift) (003) | Individual cron jobs can be paused; quota walls stop dispatch by conductor gate (Meta read is the dispatch gate) | partial — no single fleet-wide pause that freezes clocks; our pauses are per-job and time keeps running on parks/leases |
| Merge governance as prompt text with attribution rule (003) | Merge authority is Drew's standing rule: Muse merges verified work itself; CI runs on main only; PRs don't wait for CI (2026-10-29/31 rules) | have, inverted — both keep merge policy out of the host's decision logic; the content of the policy deliberately differs (§4) |
| Router behavior under provider failure (their Executor retry classes, 003) | opencode#1014: any-error-class escalating bench, reset-aware holds, balance-shaped known-full, dynamic pull-out on quota error, nearest-first cascade that never kills a session while a candidate remains, pooled-seat launch rule (code#3325) | have (in flight, task 5256) — our router doctrine is considerably more developed than theirs; theirs contributes the classification discipline (transient class → retry 3× → hold) as a cross-check, not a replacement |
D. Surfacing: panel vs chat escalation + morning readout
| Their concept (doc) | Ours | Verdict |
|---|---|---|
| Panel: needs-me-first, health second, per-item history third; healthy = invisible (005) | Chat delivery discipline: one compact line for material outcomes only; everything else to logs/backlogs; morning readout + stewardship cycles name stalled/blocked items | have as discipline, lack as artifact — the ordering principle is identical (attention first, health second, history on demand); we render it as chat text assembled per cycle, they render it as a standing view over queryable state. #3424's notes/events/attention data is what would let ours be generated instead of written |
| Stage labels say whom a row waits for (005, 003) | Backlog/readout prose names blockers ("BLOCKED: <what's needed>") | partial — convention exists, not computable from data today |
| Actionable-only problems; one-off errors don't surface; counts == list lengths (005) | "A failed read never idles a pool"; routine exhaustion not surfaced, sole-door pools and anomalies are (quota doctrine) | have — same principle, independently arrived at |
| Dismissable, expiring attention requests (<24h, latest-only, not-while-queued) (002, 005) | Escalations persist until Drew rules or the condition clears; re-asking a recorded decision is banned | partial — we have the no-re-ask rule; we lack expiry/dismissal mechanics, so stale asks can linger in backlogs |
| One structured question at a time to the person (000, 004) | Decision surfacing carries substance + options + recommendation (Drew's 2026-10-28 rule); options widgets used for rulings | have — our version is richer in content; theirs adds the structured-field plumbing (question travels with the work item, answer returns to it) |
E. Prompts / instructions
| Their concept (doc) | Ours | Verdict |
|---|---|---|
| Precedence ladder: host-enforced facts > built-ins > matched-rule reqs > team text > outside text as data (004) | System rules > Drew directives > instruction files > issue/PR text; injection discipline in fleet instructions | have as practice — never written as one ladder our instruction files cite |
| Policy section regenerated per request, placed last so rule changes don't churn the prompt prefix (004) | Instruction files are static per cron definition; quota/router state injected per conductor cycle; cron definitions are truth, edits pushed via cron.update | partial — our "policy" (quota state, gates) does ride per-cycle; the placement/caching trick is OpenCode-session-specific but the principle (volatile state last, stable text first) applies to lane prompts |
| Versioned prompts/settings, base-revision saves, override==default auto-deleted (004, 007) | Cron definition files in git + cron.update; instruction files in hidden_files with git history | partial — versioned by git, no optimistic-concurrency on edits, no "instruction identical to template gets dropped" hygiene |
| Router/executor role split: router never decides technically, ≤30-word notes, batched routing calls (004) | Conductor dispatches and gates; lanes judge and implement; main chat routes Drew's intent | have in shape — our conductor already only dispatches/gates; the word-limit and batching disciplines are not formalized |
| Router never waits (no sleep / long job waits) (004) | Cron shifts are fresh-context and time-boxed; lanes park instead of polling | have by architecture — cron model gives us this for free |
| Few concepts, few settings; behaviour in words is prompt text, not a setting (000) | Fleet has accreted many job types and instruction files; label taxonomy 400+ labels | partial — worth an explicit audit pass (§3.10) |
3. Most adoptable ideas (ranked by value ÷ cost)
Each idea names its source doc, every plausible home, and a one-line cost note.
3.1 Structured question field on the work item ("Attention")
Their Executor asks through a structured field on its Report; the question
travels with the Ticket and the person's answer returns to the same Ticket
(001-domain glossary; 003-execution; 004-prompts "Ask through human_action").
Ours: escalations are chat prose + user/escalated labels; the substance rule
(what/options/recommendation/why) is enforced socially.
Homes: code#3424 (notes schema gains an attention note type with
question/options/recommendation/answer fields — fits the typed-notes piece
directly) · lane instructions (repo-queue-worker-instruction.md,
lane-shift-instruction.md: escalation = write the attention note, then the
chat line renders it) · escalation discipline / morning readout (readout
lists open attention notes instead of re-deriving them).
Cost: small — one note type + fields in a design already in flight; readout
generation is a follow-up, not a prerequisite.
3.2 Accept mode per producer: off / observe / auto
Inferred work starts in observe: positive assessments recorded as
"would accept", nothing starts; flip to auto after reviewing the recorded
Decisions (002-authorization). We ran observe once, system-wide, by hand
(pilot shadow); every new producer since went straight to auto.
Homes: code#3424 (a mode column on producer/queue config is schema-shaped)
· producer job bodies (new-issue-creator, pr-diff-review, pr-comment-review:
new filing rules/kinds start in observe for N runs) · fleet monitor (reports
would-accept counts so the flip decision has data).
Cost: small–medium — a config flag + producers honouring it; the win is a
safe on-ramp for every future producer rule change.
3.3 Derived "waiting-on" stage instead of (only) a stored status
Stage computed from facts by a precedence table — undelivered → person/answer →
person/review → person/blocked-failed → queued → idle → working — and the label
names whom it waits for (003-execution stage table; 005-panel principle 2).
Homes: code#3424 (add a derived waiting-class to the design: inputs are
status + blocker links + park kind + last note type; stored status_reason
stays as the human gloss) · code#3418 (capacity-wait vs external-wait is
exactly two rows of this table — fold them in rather than inventing parallel
vocabulary) · fleet monitor + morning readout (queue health reported in
waiting-on classes; "31 parked" becomes "12 on CI, 9 on review, 4 on Drew,
6 capacity").
Cost: small in the design phase (a view/function over #3424's tables);
medium if retrofitted after implementation — decide it inside #3424 now.
3.4 Decision/reason codes as a shared vocabulary
Decisions and transitions record a code + values from one table; agents,
panel and humans all render from the same codes (007-architecture Model;
001-domain disposition). Our reasons are free text (last_error, progress
blobs) — the failure #3424 exists to fix.
Homes: code#3424 (notes/events carry reason_code beside the free-text
body; seed the code list from our real vocabulary: ci_wait, codex_review,
quota_reset, capacity, blocked_on_task, drew_decision, upstream_pr, …) ·
lane instructions (terminal verbs require a code) · repo-queue.py (validate
codes at the verb, like packet schemas).
Cost: small — a controlled vocabulary list + one column; discipline cost
only if lanes must retrofit old rows (don't — codes apply going forward).
3.5 Follow-up ownership + hand-back, applied to PR shepherding
A follow-up on a work item's own thread is owned by that item's worker, which
either handles it in-scope or hands it back once with a reason; only unowned
messages become new intake (002-authorization; 003-execution). Our analog:
review comments and CI results on a PR with a live shepherd task should route
to that task (as a resume trigger with context), and a shepherd that judges a
comment out-of-scope hands it back as a new triage packet naming why — instead
of today's pattern where pr-comment-review files fresh issues that can collide
with the shepherd's own work.
Homes: lane instructions (shepherd resume protocol) · pr-comment-review
job body (check for a live shepherd/pr task before filing) · code#3424
(hand-back = a link + note with provenance inferred, reason code from 3.4).
Cost: medium — mostly instruction + one producer check; no schema beyond
what #3424 already plans.
3.6 Reserved human-priority capacity in claiming
Worker slots reserve +1 beyond the limit for a person's message or a status
request, and human wakes preempt new launches (003-execution Concurrency).
Our failure shape (2026-11-01): Drew-prioritized work waits behind whatever
the shift already claimed; there is no mechanism for a Drew directive to
preempt inside the queue system.
Homes: code#3418 (claim-side companion: expedite/Drew-originated tasks may
claim against a reserved budget slice — e.g. a lane may exceed its bundle cap
by one for a priority-90 task, or one lane slot per queue is reserved for
expedite until T-30 of the shift) · lane instructions (the reservation rule
lanes can actually execute) · conductor instruction (dispatch gate honours the
reservation when seating sessions).
Cost: small — a claim rule + instruction text; no schema beyond #3418's
required_budget_minutes conversation.
3.7 Stored-work discipline for side effects (mini-outbox)
Side effects are stored in the same transaction as the state change and
executed after commit with per-kind backoff; a kind surfaces as a system
problem only after 3 consecutive failures of one item (003-execution "Stored
work"; 007-architecture Effects). Our lanes post GitHub comments / enqueue
follow-ups / fire signals inline; a crash between the DB verb and the comment
is exactly the claim-evaporation class we repaired on 2026-10-26.
Homes: code#3424 (events table already stores the intent; add an
effects/outbox table for comment-mirroring — note piece 4 already promises
"the system comments notes back automatically", which is an outbox consumer)
· repo-queue.py (verbs enqueue effects; a small drainer in the fleet monitor
or a hook executes them) · fleet monitor (per-kind failure accounting replaces
ad-hoc divergence repair).
Cost: medium — one table + a drainer; but it mechanizes repairs the fleet
monitor currently does by hand every hour.
3.8 Generated working-set columns for queue reads
Their store computes open / active / subscribed as generated columns
with partial indexes so a pass reads only active work (007-architecture
Persistence). Our claim/health queries filter the full tasks table by status
and timestamps on every lane cycle.
Homes: code#3424 (schema design: generated columns or partial indexes for
claimable-now, parked-due, blocked-on-open-task working sets — pairs with the
normal-form ruling already recorded) · supabase migrations chain (lands as
part of the #3424 implementation migrations).
Cost: small — index design inside migrations already being written.
3.9 Prompt-precedence ladder + volatile-state-last, written into fleet instructions
One explicit ladder (host-enforced facts > standing rules > matched task
requirements > instruction text > repo/issue text as data), and prompts
assembled stable-first with volatile state (quota snapshot, gate state) last
(004-prompts). Our lanes already behave this way; writing it down once ends
per-instruction-file reinvention and gives the injection rule a citation.
Homes: lane-shift-instruction.md + repo-queue-worker-instruction.md
(one shared preamble section) · conductor instruction (same preamble) ·
opencode route/session prompts where the router assembles per-session context
(adjacent to #1014's surfaces, not inside its scope).
Cost: small — an editing pass over instruction files we control.
3.10 "Few concepts" audit of our own surface
Their design refuses new concepts: a business need becomes an attribute of an
existing concept or prompt text (000-philosophy; 001-domain rejected-concepts
table is the worked example). Our surface has grown by accretion: 400+ labels,
multiple overlapping job types, per-queue instruction variants.
Homes: goal-level review (label taxonomy file
files/label-taxonomy-2026-10-25.md — prune labels no query uses) ·
stewardship cycle (a standing "concept count" check when a new job/instruction
is proposed: attribute of an existing thing, or genuinely new?) · code#3424
(the design already applies this to links/notes — extend the same test to the
pieces' own vocabulary before implementation packets split).
Cost: small per pass, recurring; the cost of not doing it is the drift
that made tonight's routing incident hard to reason about.
4. What they do that we deliberately do differently — and should keep
-
Merge authority. Their default: the agent account never enables
auto-merge, people merge, policy lives in a "Delivery requirements" prompt
(003-execution). Ours (Drew, 2026-10-24/25, restated since): Muse merges
verified finished work itself — "if an issue or PR says it needs a human,
they mean you" — drafts and conflicted PRs included, fix forward. Keep
ours. It is the throughput decision the whole fleet is built on; their
model optimizes for a team of human colleagues whose attention and trust
are the scarce resource, ours for a single operator who has explicitly
delegated the merge call. (Borrow only their attribution awareness:
merges are attributable actions, which our provenance piece 6 now records.) -
Start narrow / observe-first as the permanent posture. Their
responsibility section: begin with a short allowed list and record-only
proactive work; widen only when the record looks right; never produce
volume (000-philosophy). We already passed that gate deliberately (pilot
shadow → Drew-approved cutovers, Phase 3 approved 2026-10-26) and Drew's
standing direction is the opposite failure-mode guard: "fix it means fix
it now", file the issue in the same pass, merge when verified. Keep our
posture; adopt observe-mode only as a per-producer on-ramp (3.2), not as a
fleet-wide temperament. -
One work item per session, session per item. Their Executor model is
one Session + directory per Ticket, resumed across days by subscription
fan-out (001/003). Our lanes are fresh-context cron shifts claiming bundles
— chosen 2026-10-26 precisely because long-lived worker contexts compact
and die mid-bundle ("cron jobs don't compact"). Keep the shift model. Our
continuity lives in the queue + GitHub + handoff snapshots, not in a
session's memory — which is also why design(queue): durable task data model — blocker links, park revalidation, status reasons + notes, full event history, actor provenance #3424's notes/events matter more for
us than their Session-history mechanics would. -
Panel as a separate UI artifact. Their panel is a standing view inside
the DeepSeek Harness (005-panel). Our surface is chat + GitHub + the
morning readout, and Drew works from his phone. Keep the surface; adopt
the panel's principles (needs-me-first ordering, waiting-on labels,
actionable-only problems, counts that equal their lists) as readout
requirements — 3.1/3.3 are what make them generatable from data instead of
assembled by hand. -
Waiting belongs to Sources; no park timers in the core. They reject
delayed-Trigger scheduling inside Eval: a condition that needs waiting is
a Source that checks again itself (001-domain rejected concepts). Our
park/not_before+ scheduled revalidation (design(queue): durable task data model — blocker links, park revalidation, status reasons + notes, full event history, actor provenance #3424 piece 3) puts waiting
inside the queue deliberately — because our "sources" are cron jobs and
GitHub state, and a park with a known external instant (quota reset, CI
completion) is more honest as data than as a poller. Keep ours; 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 split already encodes the part of their
objection that was right (a capacity wait is not a time wait). -
GitHub as the canonical work surface. Their Sources translate GitHub
into an internal domain and the Ticket state lives in their store
(001-domain "What is reusable"). Ours keeps GitHub issues/PRs canonical —
the queue is a control plane, the discussion and the audit trail people
read live on the issue — and design(queue): durable task data model — blocker links, park revalidation, status reasons + notes, full event history, actor provenance #3424 piece 4 mirrors notes out to GitHub
for exactly this reason. Keep ours; it's why a person can audit any fleet
action from the repo alone. -
Escalation content. Their questions are one concrete question, short
(000/004). Drew's rule requires the substance in the message itself —
what, options, ramifications, recommendation — because he rules from the
chat, not from a panel. Keep ours; 3.1 adds their plumbing (the question
as structured data on the item) underneath our content rule, not instead
of it.
Prepared for the repo-health fleet's design work (code#3424, code#3418,
opencode#1014, fleet instruction files). Reference only — no GitHub posts made.
Activity
developing-today commentedon Nov 1, 2026
CODE-1318
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.
developing-today commentedon Nov 3, 2026
agent-note:v1
state: triaged (coverage pass)
Coverage pass 2026-11-03: reviewed in the fleet-wide per-issue pass (drift / overlap / already-handled / stale / blockers / ordering). Verdict: still live; queued in repo-health-code-pilot as triage at priority 30 (priority/none). If this is already handled at current main, the triage closes it with evidence; if it needs splitting, the triage files the split.
Found via: coverage pass 2026-11-03
dezren39 commentedon Nov 3, 2026
🤖 Agent note · handed off
opencode; handed off to the laptop claimant (opencode-claimant), which launches the bound session that drives task 8619 to its terminal state.8 remaining items
dezren39 commentedon Nov 4, 2026
🤖 Agent note · handed off
dezren39 commentedon Nov 4, 2026
🤖 Agent note · handed off
dezren39 commentedon Nov 4, 2026
🤖 Agent note · handed off
dezren39 commentedon Nov 5, 2026
🤖 Agent note · handed off