Docket Crew — local multi-agent orchestration (MVP) - #2
Open
pasichDev wants to merge 1 commit into
Open
Conversation
Adds @pasichdev/docket-crew, a separate package layered on Docket Core: a loopback daemon that launches real coding-agent CLIs, assigns them work, routes messages between them, isolates coding work in git worktrees, and serves a live Office UI. Docket Core is untouched — Crew depends on it, not the other way round. Real runtimes from the first slice, never mocked outside tests: claude 2.1.259, codex-cli 0.151.0, opencode 1.18.26 (incl. OpenRouter models). Every CLI contract in docs/RUNTIME-CONTRACTS.md was probed against the real binary, including the traps that break naive implementations: codex hangs unless stdin is closed, opencode interleaves terminal OSC escapes into its JSON stream, and a prompt starting with "-" is parsed as a flag. Proven end to end: a real Claude manager delegates to a real Codex worker in its own worktree, the worker reports, and the manager wakes automatically — no prompt copying. Branch is the deliverable; nothing is merged or pushed. Layers - adapters/ one AgentRuntimeAdapter per CLI, normalising to AgentEvent - supervisor process lifecycle, cancellation, idle-timeout watchdog - orchestrator manager loop, auto-wake, assignments, autonomous-loop guard - mcp/ the crew_* tool surface real agents call back through - office/ pixel-art Office + chat, live over SSE - skills/ manager/worker/reviewer behaviour as SKILL.md, not TypeScript Safety properties, each with tests - A worker only runs in the human's checkout when a human authorised it; the decision lives where turns start, so a new caller cannot add a door. - Uncommitted changes refuse isolated work rather than handing a worker a different tree than the human is looking at. - Observed Docket sessions are look-don't-touch: no controls, 409 on every mutation, no RPC access, and their self-reported names are sanitised before they reach a manager's context. - `stop` leaves zero Crew-owned processes; interrupted runs are never marked successful. Known limits are documented rather than papered over — see docs/OPERATIONS.md. Agents run as the same uid as the user, so "human-only" raises the bar but is not a boundary; that is stated plainly instead of claimed as solved. 448 tests, 444 passing, 4 live-gated (they spend real model quota).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this is
@pasichdev/docket-crew— a separate package layered on Docket Core. A loopback daemon that launches real coding-agent CLIs, assigns them work, routes messages between them, isolates coding work in git worktrees, and serves a live Office UI.Docket Core is untouched. Crew depends on it; nothing in
src/changed. Process supervision, model routing, CLI adapters and orchestration loops stay out of Core by design.Real runtimes, not mocks
Mocks exist only inside tests. From the first vertical slice this drives the actual binaries installed on the machine:
-p --output-format stream-json, resume bysession_idexec --json --sandbox workspace-write, resume bythread_idrun --format json -m openrouter/…, resume bysessionIDEvery contract in
crew/docs/RUNTIME-CONTRACTS.mdwas probed against the real binary, including three traps that break naive implementations:Reading additional input from stdin...unless the prompt is on argv and stdin is closed.-is parsed as a flag. SKILL.md frontmatter made every prompt begin---, so every turn failed until frontmatter was stripped.codex exec resumealso accepts neither--sandboxnor-Cand filters sessions by cwd — so a worker's worktree must outlive its turns. Sessions are keyed by the directory that created them.Proven end to end
A real Claude manager delegates to a real Codex worker in its own worktree; the worker reports; the manager wakes automatically. No prompt copying.
mainuntouched, work oncrew/<id>-codex, nothing merged or pushed. The manager's session id is identical across both turns — resume works.Architecture
adapters/AgentRuntimeAdapterper CLI, normalising to a singleAgentEventunionsupervisororchestratormcp/crew_*tools real agents call back through, role-scopedoffice/skills/SKILL.md, not hardcoded in TypeScriptDocket stays the canonical task store — Crew references todos, it does not copy them.
Safety properties (each with tests)
409on every mutation, no RPC access — and their self-reported names are sanitised before they can reach a manager's context.stopleaves zero Crew-owned processes. Interrupted runs are never marked successful.Honest limits
Written down in
crew/docs/OPERATIONS.mdrather than papered over. The one worth reading before merging:Also not done: worktrees and
crew/*branches accumulate (made visible, not auto-deleted — Crew cannot know which unmerged branch you still want);state.json's message ledger is unbounded; the reviewer path and opencode-as-worker are implemented and unit-tested but have never been watched end to end with a real model.Review notes
Three adversarial review passes (concurrency, security, data-loss) ran against this before it was opened, and their findings were fixed in four waves — including several silent-data-loss bugs of the shape this codebase keeps producing: a finished worker's result dropped when the manager was
failed, a message queued behind a busy worker that nothing would ever open, two queued assignments sharing one worktree so work landed on the wrong branch and was reported "done" with an empty diff, and agent replies truncated to 200 characters at emit time so the full text existed nowhere.448 tests, 444 passing, 4 live-gated (they spend real model quota; run with
DOCKET_CREW_LIVE=1).