{"_id":"@async/dispatch","_rev":"6-d01f7db9bb63af68f2d8f8feadd99c38","name":"@async/dispatch","dist-tags":{"latest":"0.0.6"},"versions":{"0.0.2":{"name":"@async/dispatch","version":"0.0.2","license":"MIT","_id":"@async/dispatch@0.0.2","maintainers":[{"name":"async-npm","email":"async.npm@gdi2290.com"},{"name":"patrickjs","email":"npm.patrickjs@gdi2290.com"}],"homepage":"https://github.com/async/dispatch#readme","bugs":{"url":"https://github.com/async/dispatch/issues"},"bin":{"async-dispatch":"src/cli.js"},"dist":{"shasum":"c79530708ca5e113ecd899c47d26810fa869b332","tarball":"https://registry.npmjs.org/@async/dispatch/-/dispatch-0.0.2.tgz","fileCount":22,"integrity":"sha512-Cn0qS+ruXK8ygrVP/j/HdYdLS2SoZhApQS/nLvY22Cw9P5fiLR0elhNAkakGLSYC7kP9VlLyCW/8nNk2LdmYGQ==","signatures":[{"sig":"MEYCIQCl/AIrSMAZd5cOvFQxgfALaDCzZrO+W0rjQ9lSf+QWtgIhAPgEIliUj+9RbNBUaNfQOhF/S9o2doOoU+SEad3x1094","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@async%2fdispatch@0.0.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":220202},"type":"module","engines":{"node":">=24"},"exports":{"./package.json":"./package.json"},"gitHead":"c9eac11a284e79fe723812aab7613b053e3cf7ca","scripts":{"test":"node --test","console":"node src/cli.js console","api:check":"api-contract check --manifest api-contract.json && api-contract ledger --manifest api-contract.json --check API_SURFACE.md","pack:check":"npm pack --dry-run --registry=https://registry.npmjs.org","api:surface":"api-contract ledger --manifest api-contract.json --out API_SURFACE.md","claims:check":"async-claims check --registry test/claims.json --test-files test/**/*.test.js","skills:check":"node src/cli.js skills check","release:check":"pnpm run pipeline:verify","pipeline:verify":"async-pipeline run verify --force"},"_npmUser":{"name":"patrickjs","email":"npm.patrickjs@gdi2290.com"},"repository":{"url":"git+https://github.com/async/dispatch.git","type":"git"},"_npmVersion":"11.16.0","description":"Installable CLI and bundled Codex skills for coordinating async chats, plans, workers, and receipts.","directories":{},"_nodeVersion":"24.16.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.20.0","devDependencies":{"@async/claims":"0.1.0","@async/pipeline":"0.4.3","@async/api-contract":"0.1.1"},"_npmOperationalInternal":{"tmp":"tmp/dispatch_0.0.2_1781456984324_0.8828565840343261","host":"s3://npm-registry-packages-npm-production"}},"0.0.3":{"name":"@async/dispatch","version":"0.0.3","license":"MIT","_id":"@async/dispatch@0.0.3","maintainers":[{"name":"async-npm","email":"async.npm@gdi2290.com"},{"name":"patrickjs","email":"npm.patrickjs@gdi2290.com"}],"homepage":"https://github.com/async/dispatch#readme","bugs":{"url":"https://github.com/async/dispatch/issues"},"bin":{"async-dispatch":"src/cli.js"},"dist":{"shasum":"2971d57a58636be1d0f13f44ded8eb93699a14bf","tarball":"https://registry.npmjs.org/@async/dispatch/-/dispatch-0.0.3.tgz","fileCount":22,"integrity":"sha512-G1ijYJZl2IuGyeRgPrEF8x27WIQYy4sFtuquZN5lz+wObrkXZyZMRQqzp3ej3fZyqnizxlTXHiM9oxVmWe1SMQ==","signatures":[{"sig":"MEYCIQDsOtM7Fj2w6guvXSXdgGA7j3Z2VCbh5IdM3ZA9ACbicAIhAJT/ljeW5dnMUWG+IHkxGwwj6hTlhZsxJY0L+G7uBpaO","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@async%2fdispatch@0.0.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":220219},"type":"module","engines":{"node":">=24"},"exports":{"./package.json":"./package.json"},"gitHead":"5b4461a702d374dd2448f597474b876f36364b54","scripts":{"test":"node --test","console":"node src/cli.js console","api:check":"api-contract check --manifest api-contract.json && api-contract ledger --manifest api-contract.json --check API_SURFACE.md","pack:check":"npm publish --dry-run --access public --registry=https://registry.npmjs.org","api:surface":"api-contract ledger --manifest api-contract.json --out API_SURFACE.md","claims:check":"async-claims check --registry test/claims.json --test-files test/**/*.test.js","skills:check":"node src/cli.js skills check","release:check":"pnpm run pipeline:verify","pipeline:verify":"async-pipeline run verify --force"},"_npmUser":{"name":"patrickjs","email":"npm.patrickjs@gdi2290.com"},"repository":{"url":"git+https://github.com/async/dispatch.git","type":"git"},"_npmVersion":"11.16.0","description":"Installable CLI and bundled Codex skills for coordinating async chats, plans, workers, and receipts.","directories":{},"_nodeVersion":"24.16.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.20.0","devDependencies":{"@async/claims":"0.1.0","@async/pipeline":"0.4.3","@async/api-contract":"0.1.1"},"_npmOperationalInternal":{"tmp":"tmp/dispatch_0.0.3_1781457138697_0.13363650269897742","host":"s3://npm-registry-packages-npm-production"}},"0.0.4":{"name":"@async/dispatch","version":"0.0.4","license":"MIT","_id":"@async/dispatch@0.0.4","maintainers":[{"name":"async-npm","email":"async.npm@gdi2290.com"},{"name":"patrickjs","email":"npm.patrickjs@gdi2290.com"}],"homepage":"https://github.com/async/dispatch#readme","bugs":{"url":"https://github.com/async/dispatch/issues"},"bin":{"async-dispatch":"src/cli.js"},"dist":{"shasum":"8802885fb25bd5d09f48f99ae6959c3117cb859d","tarball":"https://registry.npmjs.org/@async/dispatch/-/dispatch-0.0.4.tgz","fileCount":22,"integrity":"sha512-BaMoE1VXNtWHIO87vA4jOPXEr+SDqFIy5fWFOkDl3z4SpPo54/j07B8TaF4073ft2hjHrYWhfMoPv/ehP5qCcQ==","signatures":[{"sig":"MEUCIQDjlHvCojBbd58L/QKsNy8JVjNk2uOCnSWDgLMh3SZGxAIgPOpY0FOOSOoBJ0D1pLIOERwqglA00lfUNb2HDltkGWk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@async%2fdispatch@0.0.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":220219},"type":"module","engines":{"node":">=24"},"exports":{"./package.json":"./package.json"},"gitHead":"73dcdd76efc65e75ed7146a42a56f839d0e18a56","scripts":{"test":"node --test","console":"node src/cli.js console","api:check":"api-contract check --manifest api-contract.json && api-contract ledger --manifest api-contract.json --check API_SURFACE.md","pack:check":"npm publish --dry-run --access public --registry=https://registry.npmjs.org","api:surface":"api-contract ledger --manifest api-contract.json --out API_SURFACE.md","claims:check":"async-claims check --registry test/claims.json --test-files test/**/*.test.js","skills:check":"node src/cli.js skills check","release:check":"pnpm run pipeline:verify","pipeline:verify":"async-pipeline run verify --force"},"_npmUser":{"name":"patrickjs","email":"npm.patrickjs@gdi2290.com"},"repository":{"url":"git+https://github.com/async/dispatch.git","type":"git"},"_npmVersion":"11.16.0","description":"Installable CLI and bundled Codex skills for coordinating async chats, plans, workers, and receipts.","directories":{},"_nodeVersion":"24.16.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.20.0","devDependencies":{"@async/claims":"0.1.0","@async/pipeline":"0.4.3","@async/api-contract":"0.1.1"},"_npmOperationalInternal":{"tmp":"tmp/dispatch_0.0.4_1781457221368_0.5085896329738966","host":"s3://npm-registry-packages-npm-production"}},"0.0.5":{"name":"@async/dispatch","version":"0.0.5","license":"MIT","_id":"@async/dispatch@0.0.5","maintainers":[{"name":"async-npm","email":"async.npm@gdi2290.com"},{"name":"patrickjs","email":"npm.patrickjs@gdi2290.com"}],"homepage":"https://github.com/async/dispatch#readme","bugs":{"url":"https://github.com/async/dispatch/issues"},"bin":{"async-dispatch":"src/cli.js"},"dist":{"shasum":"aa3d6f4c3bc6ea3eb9c302b1999ac467716045a1","tarball":"https://registry.npmjs.org/@async/dispatch/-/dispatch-0.0.5.tgz","fileCount":22,"integrity":"sha512-NA/fQXtn3DDOhBl8sx9TelyWieOMTKCJrfiDM4BM26LReSoUawiNE51e9xKB6UhdQFQDh4lA7b3vsmn80mU8XQ==","signatures":[{"sig":"MEYCIQDtVu99s6zag1hYmqEJpi5JiGLu+WxfkuTX3J9Ow/VrVgIhAIjFb9a3CK3eld4PGAbX9gUYbXSvh1HMbAtkP02/0pTe","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@async%2fdispatch@0.0.5","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":220503},"type":"module","engines":{"node":">=24"},"exports":{"./package.json":"./package.json"},"gitHead":"3d9efc0856f10eb16dfe79110a5439771bbdf2cd","scripts":{"test":"node --test","console":"node src/cli.js console","api:check":"api-contract check --manifest api-contract.json && api-contract ledger --manifest api-contract.json --check API_SURFACE.md","pack:check":"npm publish --dry-run --access public --registry=https://registry.npmjs.org","api:surface":"api-contract ledger --manifest api-contract.json --out API_SURFACE.md","claims:check":"async-claims check --registry test/claims.json --test-files test/**/*.test.js","skills:check":"node src/cli.js skills check","release:check":"pnpm run pipeline:verify","pipeline:verify":"async-pipeline run verify --force"},"_npmUser":{"name":"patrickjs","email":"npm.patrickjs@gdi2290.com"},"repository":{"url":"git+https://github.com/async/dispatch.git","type":"git"},"_npmVersion":"11.16.0","description":"Installable CLI and bundled Codex skills for coordinating async chats, plans, workers, and receipts.","directories":{},"_nodeVersion":"24.16.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.20.0","devDependencies":{"@async/claims":"0.1.0","@async/pipeline":"0.4.3","@async/api-contract":"0.1.1"},"_npmOperationalInternal":{"tmp":"tmp/dispatch_0.0.5_1781457453777_0.29424636518894154","host":"s3://npm-registry-packages-npm-production"}},"0.0.6":{"name":"@async/dispatch","version":"0.0.6","license":"MIT","_id":"@async/dispatch@0.0.6","maintainers":[{"name":"async-npm","email":"async.npm@gdi2290.com"},{"name":"patrickjs","email":"npm.patrickjs@gdi2290.com"}],"homepage":"https://github.com/async/dispatch#readme","bugs":{"url":"https://github.com/async/dispatch/issues"},"bin":{"async-dispatch":"dist/cli.js"},"dist":{"shasum":"cc59935de2b350dddc07ec921f500c483d898289","tarball":"https://registry.npmjs.org/@async/dispatch/-/dispatch-0.0.6.tgz","fileCount":25,"integrity":"sha512-efZ3Q3zqr+sIAJmsfM5ECwJZfZcpwGAEZbRo5R5DkMIHZdpJCxOux0seRfb5XJT5mNNMEHyk3WZBHLouB5EXzA==","signatures":[{"sig":"MEUCIFFozvKQmBRg9DaI18taNIimwGjKltYEvK6oR4+sEwfyAiEA/vKEncqKWOBQa9NySQb0W/8TXlEni9Fca328MTqQtVI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@async%2fdispatch@0.0.6","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":236531},"type":"module","engines":{"node":">=24"},"exports":{"./package.json":"./package.json"},"gitHead":"027c2d5017606d2e75e38797d6b77b7a5623fb07","scripts":{"console":"node src/cli.js console","pipeline:pages":"async-pipeline run pages","pipeline:verify":"async-pipeline run verify","pipeline:preview":"async-pipeline run preview","pipeline:publish":"async-pipeline run publish","pipeline:snapshot":"async-pipeline run snapshot","pipeline:api:check":"async-pipeline run-task api.check","pipeline:task:test":"async-pipeline run-task test","pipeline:pack:check":"async-pipeline run-task pack.check","pipeline:sync:check":"async-pipeline sync check","pipeline:task:build":"async-pipeline run-task build","pipeline:api:surface":"async-pipeline run-task api.surface","pipeline:publish:npm":"async-pipeline publish npm --package .","pipeline:task:claims":"async-pipeline run-task claims","pipeline:task:verify":"async-pipeline run-task verify","pipeline:github:check":"async-pipeline github check","pipeline:skills:check":"async-pipeline run-task skills.check","pipeline:verify:force":"async-pipeline run verify --force","pipeline:sync:generate":"async-pipeline sync generate","pipeline:release-doctor":"async-pipeline run release-doctor","pipeline:release:doctor":"async-pipeline release doctor --package .","pipeline:release:ensure":"async-pipeline release ensure --package .","pipeline:task:api.check":"async-pipeline run-task api.check","pipeline:task:docs.site":"async-pipeline run-task docs.site","pipeline:github:generate":"async-pipeline github generate","pipeline:task:pack.check":"async-pipeline run-task pack.check","pipeline:task:sync.check":"async-pipeline run-task sync.check","pipeline:task:api.surface":"async-pipeline run-task api.surface","pipeline:publish:github:pr":"async-pipeline publish github pr --package .","pipeline:task:github.check":"async-pipeline run-task github.check","pipeline:task:skills.check":"async-pipeline run-task skills.check","pipeline:task:claims.report":"async-pipeline run-task claims.report","pipeline:publish:github:main":"async-pipeline publish github main --package .","pipeline:task:publish.stable":"async-pipeline run-task publish.stable","pipeline:task:release.doctor":"async-pipeline run-task release.doctor","pipeline:task:release.ensure":"async-pipeline run-task release.ensure","pipeline:task:publish.preview":"async-pipeline run-task publish.preview","pipeline:task:publish.snapshot":"async-pipeline run-task publish.snapshot","pipeline:publish:github:release":"async-pipeline publish github release --package .","pipeline:task:publish.stable.github":"async-pipeline run-task publish.stable.github"},"_npmUser":{"name":"patrickjs","email":"npm.patrickjs@gdi2290.com"},"repository":{"url":"git+https://github.com/async/dispatch.git","type":"git"},"_npmVersion":"11.16.0","description":"Installable CLI and bundled Codex skills for coordinating async chats, plans, workers, and receipts.","directories":{},"_nodeVersion":"24.16.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.20.0","devDependencies":{"@async/claims":"0.1.0","@async/pipeline":"0.4.3","@async/api-contract":"0.1.1"},"_npmOperationalInternal":{"tmp":"tmp/dispatch_0.0.6_1781458419132_0.7709996497246168","host":"s3://npm-registry-packages-npm-production"}}},"time":{"created":"2026-06-14T17:09:44.138Z","modified":"2026-06-17T04:41:59.856Z","0.0.2":"2026-06-14T17:09:44.490Z","0.0.3":"2026-06-14T17:12:18.866Z","0.0.4":"2026-06-14T17:13:41.557Z","0.0.5":"2026-06-14T17:17:33.912Z","0.0.6":"2026-06-14T17:33:39.262Z"},"bugs":{"url":"https://github.com/async/dispatch/issues"},"license":"MIT","homepage":"https://github.com/async/dispatch#readme","repository":{"url":"git+https://github.com/async/dispatch.git","type":"git"},"description":"Installable CLI and bundled Codex skills for coordinating async chats, plans, workers, and receipts.","maintainers":[{"email":"me@jackshelton.com","name":"jackshelton"},{"email":"async.npm@gdi2290.com","name":"async-npm"},{"email":"npm.patrickjs@gdi2290.com","name":"patrickjs"}],"readme":"# @async/dispatch\n\nInstallable local coordination CLI for goal-first async chat work.\n\nDispatch keeps the coordination engine outside individual skills:\n\n```text\nGoal Seed -> Context Discovery -> Refined Goal Charter -> Human Draft -> Review Loop -> Reference Map Enrichment -> Board -> Runtime Ledger -> Workers/Receipts\n```\n\nThe CLI owns IDs, storage, validation, plan compilation, and the local console.\nBundled Codex skills stay thin and call into Dispatch instead of duplicating\nruntime state in prompts.\n\n## Install\n\nDispatch is distributed as the public npm package `@async/dispatch`. Install the\nCLI first, then install the bundled skills that teach Codex how to use that CLI\nfor async root chats, domain chats, workers, receipts, idle/wake handling, and\ncode-routing decisions. A normal user should not need a source checkout.\n\nRequirements:\n\n- Node.js 24 or newer\n\nInstall the CLI from the public npm registry:\n\n```bash\npnpm add --global @async/dispatch\nasync-dispatch help\n```\n\nUse `corepack` only if you want pnpm to manage global installs on a fresh\nmachine:\n\n```bash\ncorepack enable\npnpm add --global @async/dispatch\nasync-dispatch help\n```\n\nFor an unpublished local build or release candidate, install the checkout as a\nglobal tarball instead of running source files directly:\n\n```bash\ncorepack enable\npnpm install\nPACK_DIR=\"$(mktemp -d)\"\npnpm pack --pack-destination \"$PACK_DIR\"\npnpm add --global \"$PACK_DIR\"/async-dispatch-*.tgz\nasync-dispatch help\n```\n\nInstall the bundled Codex skills:\n\n```bash\nasync-dispatch skills install\nasync-dispatch skills status\n```\n\nAfter this, start a fresh Codex session so the newly installed Dispatch skills\nare discoverable. The installed skills call `async-dispatch`; they should not\nduplicate runtime state in prompts or local skill files.\n\nBy default that writes to `~/.codex/skills`. Installed Dispatch-managed skills\ninclude metadata with the package version and source hash so `skills status` can\nreport `missing`, `current`, `stale`, `modified`, or `unmanaged`.\n\nExisting skill folders are skipped unless they are missing or you explicitly ask\nfor replacement. To update Dispatch-managed skills from a newer package, use:\n\n```bash\nasync-dispatch skills install --force\n```\n\nUnmanaged folders are not replaced by `--force`; use `--replace-unmanaged` only\nafter deciding the existing folder should be backed up and replaced.\n\nUse `--skill` to install one bundled skill:\n\n```bash\nasync-dispatch skills install --skill dispatch-root-runtime\n```\n\n## Development From Checkout\n\nSource development still works from a checkout. Use this when changing Dispatch\nitself, validating a release, or editing the bundled skills before publishing an\nupdated package.\n\nDevelopment requires pnpm 10.20 or newer.\n\n```bash\ngit clone <dispatch-repo-url> dispatch\ncd dispatch\ncorepack enable\npnpm install\npnpm link --global\nasync-dispatch help\nasync-dispatch skills install\nasync-dispatch skills status\n```\n\nFull local verification dogfoods adjacent Async helper packages. The expected\ndevelopment layout is:\n\n```text\nasync/\n  api-contract/\n  claims/\n  dispatch/\n  pipeline/\n```\n\nBuild or verify the helper repos first if their `dist/` folders are missing,\nthen run Dispatch verification:\n\n```bash\ncd ../pipeline\npnpm install\npnpm run pipeline:task:build\n\ncd ../api-contract\npnpm install\npnpm run pipeline:task:build\n\ncd ../claims\npnpm install\npnpm run pipeline:task:build\n\ncd ../dispatch\npnpm run pipeline:verify\n```\n\nIf you only need the Dispatch CLI and do not have the helper repos yet, use the\nstandalone gate:\n\n```bash\npnpm run pipeline:task:test\n```\n\n`pnpm run pipeline:verify` creates ignored `.async/` run and cache artifacts.\nRuntime ledger state does not live there; it defaults to `~/.async/dispatch`.\n\nGitHub Actions and package scripts are generated from `pipeline.js` with\n`pnpm run pipeline:sync:generate`. The committed workflow checks generated\nstate, verifies pull requests, publishes PR previews and main snapshots to\nGitHub Packages, deploys GitHub Pages from `main`, and publishes stable releases\nthrough `@async/pipeline`.\n\n## Quick Start\n\nUse a temporary home for demos so you do not touch your real Dispatch ledger:\n\n```bash\nexport ASYNC_DISPATCH_HOME=\"$(mktemp -d)\"\ndispatch() { async-dispatch \"$@\"; }\n```\n\nCreate and start a small runtime:\n\n```bash\nGOAL=$(dispatch goal init --seed \"Coordinate a local release\" | awk '/goalId:/ {print $2}')\nPLAN=$(dispatch plan draft \"$GOAL\" | awk '/planId:/ {print $2}')\ndispatch plan ready \"$PLAN\" --note \"ready\"\nBOARD=$(dispatch plan compile \"$PLAN\" | awk '/boardId:/ {print $2}')\ndispatch board approve \"$BOARD\" --note \"approved\"\nLEDGER=$(dispatch runtime start \"$BOARD\" | awk '/ledgerId:/ {print $2}')\ndispatch node add \"$LEDGER\" --kind phase --title \"Discovery\"\ndispatch node tree \"$LEDGER\"\n```\n\nOpen the local console:\n\n```bash\ndispatch console --port 8787\n```\n\nThe console renders a Work Discovery board. It finds every absolute root runtime\nand shows the board tasks, workers, domain tasks, nodes, dispatch plans, waits,\ninbox events, receipts, child ledgers, and linked threads that depend on that root. A\nwatcher can read the same projection from `/api/work`.\n\n## Conceptual Model\n\nDispatch is a small local state-machine and queue runtime for Codex work.\n\n- State machines describe what each durable thing is doing: the root runtime,\n  domain owners, workers, code-dispatch lanes, external waits, and future gates.\n- Queues and inboxes describe what needs attention next: ready work, status\n  events, blocked work, and due waits.\n- Receipts and events describe what happened and why root can safely move\n  forward.\n\nThe goal is not a distributed job system. The goal is to keep root-chat\ncoordination explicit: runnable work stays `active`, known human blockers become\n`paused-human`, real timers become `waiting-external`, and no useful work\nbecomes `idle`.\n\n## Dispatch Control Discipline\n\nDispatch makes root-chat coordination first-class:\n\n- Start with an oracle: record the observable success proof before runtime work\n  starts, then keep checking receipts against it.\n- Treat state as truth: the Dispatch ledger, not chat prose, decides what is\n  active, blocked, done, waiting, or idle.\n- Use role-shaped work: scout and judge work should be read-only, worker work\n  should be bounded, and root owns PM decisions.\n- Bound every write lane: record ownership or allowed files, verification, and\n  stop conditions before dispatching a worker.\n- Require receipts for done, blocked, and escalated work.\n- Block the exact task, not the whole runtime, when safe adjacent work can\n  continue.\n- Finish with an audit that maps current receipts back to the original goal and\n  success proof.\n\nDispatch's source of truth is its CLI-managed board and runtime ledger, not a\ngenerated repo artifact. The console is the live UI: it discovers each absolute\nroot runtime, then shows the board tasks, workers, domain tasks, nodes,\ndispatch plans, waits, inbox events, receipts, child ledgers, and linked threads\nthat depend on that root. Keep one active writer per owned scope; run parallel\nlanes only when ownership is disjoint and root has an integration point.\n\n## Workflow Improvement Loop\n\nDispatch should learn from its own runs. The root closeout should inspect\nreceipts, blockers, reroutes, failed verification, external waits, idle\ntransitions, and any place the agent wanted to add an untracked sleep. If that\nteaches a reusable rule, capture it as a lesson:\n\n```text\ntrigger\nobserved\nrule\nevidence\nfollowUp\nstatus\n```\n\nADR-style records are useful when the lesson becomes a durable design decision:\nwhy a scheduler state exists, why a gate is required, why a release train table\nis the source of truth, or why a skill workflow changed. The live Dispatch\nledger still decides current state; lessons and ADRs explain how the workflow\nshould improve next time.\n\nLessons should move through a small lifecycle:\n\n```text\nobserved -> candidate-rule -> applied-to-repo -> validated -> promoted-to-skill\n```\n\nDo not promote every one-off annoyance. Promote lessons that have concrete\nevidence, prevent repeated failure, or clarify root/domain/worker boundaries.\n\n## Recursive Runtime Nodes\n\nV1 nodes are the workflow-structure overlay for recursive phases, loops,\ncheckpoints, milestones, tasks, lanes, gates, and lessons. They do not replace\nexecution records. Workers, code dispatch plans, external waits, and JSONL\nreceipts remain the execution source of truth and link back with `nodeId` or\nreceipt IDs.\n\nContainment is intentionally narrow for v1:\n\n```text\nroot -> phase\nphase -> loop | checkpoint | milestone | task | lane | gate | lesson\nloop -> checkpoint | gate | task | lane\ncheckpoint | milestone -> task | lane | gate\ntask | lane | gate | lesson -> leaf\n```\n\nParent status is derived from children unless the parent is already terminal.\nRunnable or reviewable children make the parent `active`; all actionable\nchildren waiting on humans make it `waiting-human`; only external waits make it\n`waiting-external`; complete children plus required receipt references make it\n`gate-ready`; `node pass` makes it `passed`.\n\nHuman direction and human blockers use separate shapes. Direction gates store a\nquestion, 2-3 options, a recommended option, and the final decision. Human\nblockers store the blocked thing, why it is blocked, what was attempted, options\nwhen useful, the recommended path, and what resumes after the answer.\n\n## Storage\n\nBy default Dispatch stores data under:\n\n```text\n$HOME/.async/dispatch\n```\n\nFor tests or demos, set:\n\n```bash\nASYNC_DISPATCH_HOME=/tmp/async-dispatch-demo\n```\n\nUse persistent storage for real work and a temporary `ASYNC_DISPATCH_HOME` for\ntests, demos, and README smoke runs. Do not put runtime ledger state in the repo.\n\n`.async/` is reserved for Async Pipeline run/cache artifacts. `.async-dispatch/`\nis only an ignored legacy/reserved local scratch name; current Dispatch runtime\nstate is `~/.async/dispatch` unless `ASYNC_DISPATCH_HOME` is set.\n\n## Codex Setup\n\nCodex should normally use the installed Dispatch skills plus the installed\n`async-dispatch` command. The checkout is only required when the task is to\nchange Dispatch itself.\n\nChecklist for a new Codex thread:\n\n1. Confirm the CLI and installed skills:\n\n   ```bash\n   async-dispatch help\n   async-dispatch skills status\n   ```\n\n2. Install or refresh the bundled skills if they are missing or stale:\n\n   ```bash\n   async-dispatch skills install\n   ```\n\n   Use `async-dispatch skills install --force` only when intentionally updating\n   Dispatch-managed installed skill copies from the current package.\n\n3. Choose storage:\n   - Real ongoing work: leave `ASYNC_DISPATCH_HOME` unset so state goes to\n     `~/.async/dispatch`.\n   - Demo or test work: set `ASYNC_DISPATCH_HOME=\"$(mktemp -d)\"`.\n\n4. Smoke-test the selected storage:\n\n   ```bash\n   async-dispatch snapshot\n   ```\n\n5. In a fresh Codex session, use the installed skills when their triggers match:\n   - `$dispatch-root-runtime` for broad root-chat coordination.\n   - `$dispatch-code-routing` before code edits that might split into lanes,\n     worktrees, child chats, or domain-owner chats.\n   - `$dispatch-skill-evolution` when changing the bundled Dispatch skills or\n     promoting workflow lessons into them.\n\n6. For a new user goal, move through the hard boundaries:\n   - `goal init`\n   - `context add` for discovered facts\n   - `plan draft` or `plan template human-draft`\n   - review loop with `plan decision`, `plan enrich`, and `plan resolve`\n   - `plan ready`\n   - `plan compile`\n   - `board approve`\n   - `runtime start`\n\n7. Once a runtime exists, treat the ledger as source of truth:\n   - Use `node add`, `node gate`, `node tree`, and `node show` for recursive\n     phases, loops, checkpoints, tasks, lanes, gates, and lessons.\n   - Before writing code, record routing with `runtime plan-code`.\n   - Keep worker/domain state current with `worker status`, `worker task`,\n     receipts, and `worker close-domain`.\n   - Use `runtime wait` only for a real timer or external event.\n   - Use `runtime human-response` only for a known blocker that was waiting on\n     a specific human answer.\n   - Use `runtime wake` when the runtime is idle and the human says something\n     new.\n\n8. Before claiming the repo is healthy, run the strongest available local gate\n   from the Dispatch checkout:\n\n   ```bash\n   pnpm run pipeline:verify\n   ```\n\n   If the helper repos or their `dist/` folders are not present, run the narrow\n   smoke path instead:\n\n   ```bash\n   async-dispatch help\n   async-dispatch snapshot\n   ```\n\nCodex should not invent sleeps or private scratch state. If there is runnable\nwork, dispatch it. If the only valid action is a timer or external event, record\nan external wait. If nothing is actionable, let the scheduler become `idle` and\nwait for `runtime wake`.\n\n## Bundled Codex Skills\n\nThe `skills/` directory is part of the package. These skills ship with\n`@async/dispatch` and are installed into Codex with\n`async-dispatch skills install`.\n\n- `dispatch-root-runtime`: goal, draft, board, runtime, worker, receipt, idle,\n  and wake coordination.\n- `dispatch-code-routing`: quick code-routing decisions before edits, including\n  root work, scouts, worktrees, child chats, and domain-owner chats.\n- `dispatch-skill-evolution`: evolving bundled Dispatch skills before publishing\n  or installing updated copies.\n\nThe skills should stay thin. They tell Codex when to call `async-dispatch`; they\nshould not duplicate ledger state in long prompts.\n\nDuring Dispatch development, edit bundled skills in `skills/<skill-name>/`, then\nvalidate the source copy:\n\n```bash\npnpm run pipeline:task:skills.check\n```\n\nAfter validation, install them for local Codex use:\n\n```bash\nasync-dispatch skills install --force\nasync-dispatch skills status\n```\n\nPublishing the package and installing skills are separate actions. A fresh Codex\nsession only sees the workflow after the skills are installed into the Codex\nskills directory.\n\n## Commands\n\n```bash\nasync-dispatch goal init --seed \"Align async repo release workflows\"\nasync-dispatch context add <goalId> --note \"Found six target repos\"\nasync-dispatch goal refine <goalId> --statement \"...\" --success-proof \"...\" --why \"After repo scan\"\nasync-dispatch plan template human-draft --seed \"Align async repo release workflows\" > draft.md\nasync-dispatch plan draft <goalId> --from release-preview-alignment-draft.md\nasync-dispatch plan decision <planId> --section-id S018 --note \"GITHUB_TOKEN is automatic in Actions\"\nasync-dispatch plan template reference-map --seed \"Align async repo release workflows\"\nasync-dispatch plan enrich <planId> --note \"Added reference map and phase IDs\"\nasync-dispatch plan resolve <planId> --decision-id D001 --resolution \"Clarified token rules in the draft\"\nasync-dispatch plan ready <planId> --note \"Human says the draft loop is ready\"\nasync-dispatch plan compile <planId>\nasync-dispatch board approve <boardId> --note \"Human reviewed the plan board\"\nasync-dispatch runtime start <boardId>\nasync-dispatch worker assign <ledgerId> --domain \"pipeline\" --owns-domain true --worker-type nested-root --task \"Release pipeline first\"\nasync-dispatch worker task <ledgerId> --worker-id W001 --objective \"Refresh consumer repos after pipeline release\"\nasync-dispatch worker status <ledgerId> --worker-id W001 --state ready-for-review --message \"Initial slice is ready\"\nasync-dispatch worker status <ledgerId> --worker-id W001 --state blocked --blocked-by human --message \"Need release owner decision\"\nasync-dispatch runtime human-response <ledgerId> --note \"Owner approved option A\"\nasync-dispatch worker status <ledgerId> --worker-id W001 --state idle\nasync-dispatch runtime wake <ledgerId> --note \"Human asked for the next dispatch\"\nasync-dispatch runtime plan-code <ledgerId> --objective \"Patch release scheduler\" --route domain-owner-chat --domain pipeline --ownership \"packages/pipeline/src\" --verify \"pnpm run pipeline:verify\"\nasync-dispatch runtime wait <ledgerId> --next-check-at \"2026-06-14T18:00:00.000Z\" --reason \"Wait for npm propagation\"\nasync-dispatch runtime clear-wait <ledgerId> --wait-id EW001 --note \"Propagation checked\"\nasync-dispatch node add <ledgerId> --kind phase --title \"Discovery\" --objective \"Map the repo before implementation\"\nasync-dispatch node add <ledgerId> --parent-id N001 --kind loop --title \"Planning loop\"\nasync-dispatch node gate <ledgerId> --parent-id N002 --question \"Which direction?\" --option \"Recursive nodes\" --option \"Separate tables\" --recommended 1\nasync-dispatch node block-human <ledgerId> --node-id N003 --blocked-thing \"Release permissions\" --why-blocked \"Need owner decision\" --attempted \"Checked workflow requirements\" --option \"Use trusted publishing\" --option \"Keep doctor-only\" --recommended 1 --resume-after-answer \"Update release checklist\"\nasync-dispatch node receipt <ledgerId> --node-id N001 --requirement research --summary \"Repo map complete\" --verification \"reviewed files\"\nasync-dispatch node pass <ledgerId> --node-id N001 --receipt R001\nasync-dispatch node tree <ledgerId>\nasync-dispatch node show <ledgerId> --node-id N001\nasync-dispatch worker complete-task <ledgerId> --worker-id W001 --task-id DT001 --summary \"Reviewed\" --verification \"root receipt\"\nasync-dispatch worker close-domain <ledgerId> --worker-id W001 --note \"Domain backlog drained\"\nasync-dispatch skills list\nasync-dispatch skills status\nasync-dispatch skills check\nasync-dispatch skills install --force\nasync-dispatch console\n```\n\n`plan compile` creates a draft/plan board only. It does not create chats, code\nwork, worker threads, or runtime ledgers. Use `runtime start` only after the plan\nboard is approved.\n\n## Replacement Flow\n\nThe v0 target is to replace the manual workflow:\n\n```text\nraw goal -> human-readable draft -> review comments -> reference-map enrichment -> pre-runtime board -> root runtime\n```\n\nUse `plan decision` for every human correction or review comment that changes\nthe draft. Decisions are append-only and may reference a section such as `S018`.\nAfter the draft is edited, use `plan enrich` to refresh the parsed structure and\n`plan resolve` to close the original review comment with a resolution event.\n\nThe initial human draft intentionally starts without stable IDs. Add IDs such as\n`G-2` or `DB-4` during the reference-map enrichment pass, after the human agrees\nthe broad shape is right.\n\nUse `plan ready` as the hard boundary before compiling a board. `plan compile`\nrefuses to run while the draft is not ready or while open review decisions\nremain.\n\nUse `board approve` as the hard boundary before chats, code work, threads, or\nruntime ledgers. `runtime start` refuses to run until the board is approved.\n\n## Domain Owners\n\nDispatch distinguishes one-shot child chats from domain owners.\n\nA worker with `ownsDomain: true` is long-lived. It stays in the runtime waiting\nset while it has open work. When the domain has no open task, no blocker, and no\nroot action needed, it can sit at `domain-idle` without being closed. A domain\nowner reporting `done` only means the current slice is done; it does not close\nthe domain while open domain tasks remain.\n\nUse this for repo/domain roots such as `pipeline`, `db`, or `web`, where the\nchild needs to keep context across multiple related tasks. Use a short\n`child-chat` without `ownsDomain` only for bounded one-off work.\n\nThis is the rule that keeps the root chat useful after the first child run: the\nroot polls long-lived domain owners only while there is actual work, adds domain\ntasks when new work appears, and uses `worker close-domain` only for final\narchival/finalization.\n\n## Event-Driven Idle\n\nDispatch stops runtime polling when the root has no active call stack item, no\nready queue items, no actionable inbox events, no active domain tasks, and no\nexternal wait that is due or pending. The ledger records:\n\n```text\nscheduler.polling.status: \"idle\"\n```\n\nThat means there is nothing useful to poll. The root should not loop or invent a\nsleep. When the human says something new, record it as a wake event:\n\n```bash\nasync-dispatch runtime wake <ledgerId> --note \"Human asked for the next dispatch\"\n```\n\nThat appends a `human-wake` event to the status inbox, sets polling back to\n`active`, and lets the root decide what to dispatch next.\n\nIf the only valid action is to wait for a real timer or external event, record\nthat explicitly instead of hiding it in a root-chat sleep:\n\n```bash\nasync-dispatch runtime wait <ledgerId> --next-check-at \"2026-06-14T18:00:00.000Z\" --reason \"Wait for npm propagation\"\n```\n\nThe console shows this as `waiting-external` with the next check time. Clear the\nwait after checking the external condition:\n\n```bash\nasync-dispatch runtime clear-wait <ledgerId> --wait-id EW001 --note \"Propagation checked\"\n```\n\n## Code Dispatch Planning\n\nBefore the root chat starts writing code, it should quickly route the work. The\nruntime can record that decision so the root does not accidentally do broad work\nthat belongs in a bounded worker, worktree, or long-lived domain chat.\n\n```bash\nasync-dispatch runtime plan-code <ledgerId> --objective \"Patch release scheduler\" --route domain-owner-chat --domain pipeline --ownership \"packages/pipeline/src\" --verify \"pnpm run pipeline:verify\"\n```\n\nSupported routes:\n\n- `root`: small edits, unclear design, overlapping files, review/integration,\n  architecture, merge, push, release, or completion decisions.\n- `subagent`: short same-turn read-only scout/judge checks.\n- `subagent-worktree`: write-capable parallel work with exact ownership, a\n  worktree, and verification.\n- `domain-owner-chat`: durable work that belongs with an existing domain owner.\n- `child-chat`: durable bounded work that needs its own receipt but does not\n  belong to a long-lived domain owner.\n\nDelegated routes are marked `needs-boundary` until they include ownership and\nverification. `domain-owner-chat` also needs a domain or worker ID, and\n`subagent-worktree` needs a worktree target. Recording a plan appends a\n`code-dispatch-planned` event to the status inbox so the root can review the\nroute before dispatching or editing.\n\nTests and implementation are a good parallel case when their ownership is clean.\nRecord a test lane and a code lane separately:\n\n```bash\nasync-dispatch runtime plan-code <ledgerId> --objective \"Add failing tests for scheduler idle/wake\" --route subagent-worktree --worktree \"../dispatch-tests\" --ownership \"test/goal-first.test.js\" --verify \"pnpm run pipeline:task:test\"\nasync-dispatch runtime plan-code <ledgerId> --objective \"Implement scheduler idle/wake support\" --route subagent-worktree --worktree \"../dispatch-code\" --ownership \"src/model.js src/cli.js src/console-server.js\" --verify \"pnpm run pipeline:task:test\"\n```\n\nWhen the test lane has a runnable red test, root can run it against the code\nlane as soon as the code lane reaches the relevant interface. If the test fails\nbecause implementation is missing, keep the code lane active. If the test fails\nbecause the contract is wrong, route back to root for an interface decision. If\nboth lanes have nothing runnable, let the scheduler become `idle`,\n`paused-human`, or `waiting-external` instead of adding an untracked sleep loop.\n\n## Human-Blocked Polling\n\nDispatch pauses runtime polling when the root has no active call stack item, no\nready queue items, no non-human actionable inbox events, and every waiting\nworker is blocked on a human response.\n\nWorkers can signal this with:\n\n```bash\nasync-dispatch worker status <ledgerId> --worker-id W001 --state blocked --blocked-by human --message \"Need owner approval\"\n```\n\nThe ledger then records `scheduler.polling.status: \"paused-human\"` with a\nblocker list. The console shows the pause reason so the root chat can stop\nwasting turns polling child chats that cannot progress.\n\nWhen the human replies, record that response:\n\n```bash\nasync-dispatch runtime human-response <ledgerId> --note \"Approved option A\"\n```\n\nThat resumes polling, clears the human-block marker on affected workers, marks\nthem `needs-root`, and puts a `human-response` event into the status inbox for\nthe root to process.\n\n## Development\n\n```bash\npnpm run pipeline:task:test\npnpm run pipeline:task:claims\npnpm run pipeline:task:api.check\npnpm run pipeline:verify\n```\n","readmeFilename":"README.md"}