outfitter-dispatch 0.2.1__tar.gz → 0.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/.gitignore +2 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/AGENTS.md +9 -2
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/PKG-INFO +41 -11
- outfitter_dispatch-0.7.0/README.md +103 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/justfile +9 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/plugins/dispatch/README.md +13 -4
- outfitter_dispatch-0.7.0/plugins/dispatch/skills/dispatch/SKILL.md +452 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/plugins/dispatch/skills/dm/SKILL.md +16 -14
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/pyproject.toml +2 -1
- outfitter_dispatch-0.7.0/scripts/check_package_contents.py +49 -0
- outfitter_dispatch-0.7.0/scripts/check_pypi_smoke.py +163 -0
- outfitter_dispatch-0.7.0/scripts/run_scenario.py +355 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/client/client.py +90 -5
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/client/models.py +117 -3
- outfitter_dispatch-0.7.0/src/outfitter/dispatch/config.py +112 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/contracts/context.py +47 -3
- outfitter_dispatch-0.7.0/src/outfitter/dispatch/contracts/derive_cli.py +650 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/contracts/derive_mcp.py +15 -9
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/contracts/errors.py +9 -1
- outfitter_dispatch-0.7.0/src/outfitter/dispatch/contracts/schema.py +26 -0
- outfitter_dispatch-0.7.0/src/outfitter/dispatch/core/handlers.py +1712 -0
- outfitter_dispatch-0.7.0/src/outfitter/dispatch/core/history.py +281 -0
- outfitter_dispatch-0.7.0/src/outfitter/dispatch/core/launch.py +325 -0
- outfitter_dispatch-0.7.0/src/outfitter/dispatch/core/model_registry.py +177 -0
- outfitter_dispatch-0.7.0/src/outfitter/dispatch/core/models.py +837 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/core/new_config.py +61 -1
- outfitter_dispatch-0.7.0/src/outfitter/dispatch/core/ops.py +756 -0
- outfitter_dispatch-0.7.0/src/outfitter/dispatch/core/packet.py +172 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/core/queue.py +18 -4
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/core/reactor.py +4 -8
- outfitter_dispatch-0.7.0/src/outfitter/dispatch/core/selectors.py +113 -0
- outfitter_dispatch-0.7.0/src/outfitter/dispatch/core/staging.py +238 -0
- outfitter_dispatch-0.7.0/src/outfitter/dispatch/core/sync.py +263 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/core/triggers.py +7 -6
- outfitter_dispatch-0.7.0/src/outfitter/dispatch/core/turn_settings.py +86 -0
- outfitter_dispatch-0.7.0/src/outfitter/dispatch/core/workspace.py +554 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/daemon/host.py +8 -1
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/daemon/supervisor.py +16 -8
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/doctor.py +41 -5
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/registry/models.py +98 -0
- outfitter_dispatch-0.7.0/src/outfitter/dispatch/registry/refs.py +29 -0
- outfitter_dispatch-0.7.0/src/outfitter/dispatch/registry/store.py +1135 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/surfaces/cli.py +154 -4
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/surfaces/mcp.py +3 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/client/test_client.py +122 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/client/test_events.py +8 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/client/test_models.py +128 -6
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/core/test_examples.py +6 -0
- outfitter_dispatch-0.7.0/tests/core/test_handlers.py +1914 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/core/test_new_config.py +40 -0
- outfitter_dispatch-0.7.0/tests/core/test_packet.py +219 -0
- outfitter_dispatch-0.7.0/tests/core/test_selectors.py +81 -0
- outfitter_dispatch-0.7.0/tests/core/test_staging.py +147 -0
- outfitter_dispatch-0.7.0/tests/core/test_sync.py +128 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/core/test_triggers.py +18 -0
- outfitter_dispatch-0.7.0/tests/core/test_workspace.py +391 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/daemon/test_control.py +1 -1
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/daemon/test_supervisor.py +15 -7
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/fakes.py +129 -7
- outfitter_dispatch-0.7.0/tests/fixtures/README.md +21 -0
- outfitter_dispatch-0.7.0/tests/fixtures/__init__.py +45 -0
- outfitter_dispatch-0.7.0/tests/fixtures/app_server/config_read/current.json +9 -0
- outfitter_dispatch-0.7.0/tests/fixtures/app_server/events/turn_failure_unsupported_model.jsonl +4 -0
- outfitter_dispatch-0.7.0/tests/fixtures/app_server/model_list/current.json +69 -0
- outfitter_dispatch-0.7.0/tests/fixtures/app_server/model_list/legacy_additional_speed_tiers.json +18 -0
- outfitter_dispatch-0.7.0/tests/fixtures/app_server/thread_list/basic.json +26 -0
- outfitter_dispatch-0.7.0/tests/fixtures/app_server/thread_read/with_turns.json +31 -0
- outfitter_dispatch-0.7.0/tests/fixtures/cli_smoke/README.md +10 -0
- outfitter_dispatch-0.7.0/tests/fixtures/registry/builders.py +95 -0
- outfitter_dispatch-0.7.0/tests/fixtures/test_corpus.py +115 -0
- outfitter_dispatch-0.7.0/tests/fixtures/transcripts/long_history_top_and_tail.jsonl +6 -0
- outfitter_dispatch-0.7.0/tests/fixtures/transcripts/malformed_lines.jsonl +6 -0
- outfitter_dispatch-0.7.0/tests/fixtures/transcripts/minimal.jsonl +3 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/integration/test_app_server.py +30 -1
- outfitter_dispatch-0.7.0/tests/registry/test_store.py +578 -0
- outfitter_dispatch-0.7.0/tests/scenarios/README.md +25 -0
- outfitter_dispatch-0.7.0/tests/scenarios/basic_coordination.toml +21 -0
- outfitter_dispatch-0.7.0/tests/surfaces/test_derive_cli.py +656 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/surfaces/test_derive_mcp.py +25 -8
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/surfaces/test_mcp_routing.py +51 -11
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/surfaces/test_parity.py +123 -19
- outfitter_dispatch-0.7.0/tests/test_config.py +35 -0
- outfitter_dispatch-0.7.0/tests/test_doctor.py +294 -0
- outfitter_dispatch-0.7.0/tests/test_scenarios.py +26 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/uv.lock +1 -1
- outfitter_dispatch-0.2.1/README.md +0 -73
- outfitter_dispatch-0.2.1/plugins/dispatch/skills/dispatch/SKILL.md +0 -252
- outfitter_dispatch-0.2.1/src/outfitter/dispatch/config.py +0 -34
- outfitter_dispatch-0.2.1/src/outfitter/dispatch/contracts/derive_cli.py +0 -388
- outfitter_dispatch-0.2.1/src/outfitter/dispatch/core/handlers.py +0 -641
- outfitter_dispatch-0.2.1/src/outfitter/dispatch/core/models.py +0 -331
- outfitter_dispatch-0.2.1/src/outfitter/dispatch/core/ops.py +0 -403
- outfitter_dispatch-0.2.1/src/outfitter/dispatch/registry/store.py +0 -392
- outfitter_dispatch-0.2.1/tests/core/test_handlers.py +0 -662
- outfitter_dispatch-0.2.1/tests/registry/test_store.py +0 -89
- outfitter_dispatch-0.2.1/tests/surfaces/test_derive_cli.py +0 -234
- outfitter_dispatch-0.2.1/tests/test_doctor.py +0 -112
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/plugins/dispatch/.codex-plugin/plugin.json +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/plugins/dispatch/.mcp.json +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/plugins/dispatch/assets/dispatch.svg +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/plugins/dispatch/skills/README.md +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/__init__.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/cli.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/client/__init__.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/client/errors.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/client/events.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/client/router.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/client/transport.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/contracts/__init__.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/contracts/examples.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/contracts/execute.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/contracts/op.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/contracts/registry.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/core/__init__.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/core/scheduler.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/core/trigger_handlers.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/daemon/__init__.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/daemon/__main__.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/daemon/control.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/daemon/lifecycle.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/registry/__init__.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/surfaces/__init__.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/src/outfitter/dispatch/version.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/__init__.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/client/__init__.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/client/conftest.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/client/test_router.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/client/test_transport.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/conftest.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/contracts/__init__.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/contracts/test_contracts.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/core/__init__.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/core/test_trigger_handlers.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/daemon/__init__.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/daemon/test_lifecycle.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/integration/__init__.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/integration/_drive.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/integration/conftest.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/integration/test_daemon_e2e.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/integration/test_lifecycle_e2e.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/registry/__init__.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/registry/test_triggers_store.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/surfaces/__init__.py +0 -0
- {outfitter_dispatch-0.2.1 → outfitter_dispatch-0.7.0}/tests/test_smoke.py +0 -0
|
@@ -14,6 +14,7 @@ just test # pytest
|
|
|
14
14
|
just lint # ruff check
|
|
15
15
|
just fmt # ruff format
|
|
16
16
|
just typecheck # mypy --strict
|
|
17
|
+
just scenario -- tests/scenarios/basic_coordination.toml
|
|
17
18
|
just run -- ... # run the dispatch CLI in-tree
|
|
18
19
|
uv run dispatch --help
|
|
19
20
|
uv run dispatchd --help
|
|
@@ -33,6 +34,8 @@ dispatch owns one `codex app-server` subprocess (stdio JSONL, shared `~/.codex`)
|
|
|
33
34
|
- `docs/usage/` — operator docs for the CLI, MCP, triggers, and plugin setup.
|
|
34
35
|
- `.agents/plans/v0/` — phased plan (`PLAN.md`) + references (`REFS.md`); tracked.
|
|
35
36
|
- `spikes/` — App Server probe scripts; seed of the integration suite.
|
|
37
|
+
- `tests/fixtures/` — small named App Server, JSONL, CLI-smoke, and registry fixtures.
|
|
38
|
+
- `tests/scenarios/` — live agent workflow fixtures run intentionally with `just scenario`.
|
|
36
39
|
- `.agents/notes/` — working notes, session recaps, learnings; **gitignored, local only**.
|
|
37
40
|
- `skills/` — first-party Codex skills for operating dispatch (`dispatch`) and dispatch-backed direct messages (`dm`).
|
|
38
41
|
- `plugins/dispatch/` — workspace-local Codex plugin bundle exposing the skills and MCP server.
|
|
@@ -43,12 +46,14 @@ Read `docs/development/design.md` and `.agents/plans/v0/PLAN.md` before implemen
|
|
|
43
46
|
|
|
44
47
|
Use the project language consistently:
|
|
45
48
|
|
|
46
|
-
- **lane** — a managed Codex thread (own or attached)
|
|
49
|
+
- **lane** — internal term for a managed Codex thread (own or attached) with registry state.
|
|
50
|
+
- **thread** — user-facing Codex conversation/session. Public CLI/help/docs should prefer "thread" unless the managed-lane authority distinction matters.
|
|
51
|
+
- **ref** — dispatch-local short stable selector for a managed lane. Full Codex thread ids are always accepted; titles and `@handles` are mutable labels.
|
|
47
52
|
- **op** — one authored operation (input/output/intent/examples/handler). The contract unit. Not "command" or "tool" (those are surface projections of an op).
|
|
48
53
|
- **surface** — a derived rendering of the op registry: CLI, MCP, remote. Surfaces are projected, never hand-written per-op.
|
|
49
54
|
- **trigger** — an automated when→action→lane binding (time or event). Not "rule" (collides with agent rules), "automation", or "job".
|
|
50
55
|
- **daemon** (`dispatchd`) — the long-lived host owning the app-server and core; the CLI is a thin client to it.
|
|
51
|
-
- **register/registry** — the durable store of lanes and triggers.
|
|
56
|
+
- **register/registry** — the durable store of lanes, refs, sync state, and triggers.
|
|
52
57
|
|
|
53
58
|
## Core rules (summary; full detail in `.claude/rules/`)
|
|
54
59
|
|
|
@@ -62,6 +67,8 @@ Use the project language consistently:
|
|
|
62
67
|
- **App Server access only via `client/`.** Never spawn or speak to `codex app-server` outside the client layer. See [client rules](.claude/rules/client.md).
|
|
63
68
|
- **Async core, sync CLI.** The daemon is asyncio end-to-end; the CLI is a thin sync client over the control socket. No blocking calls in the loop (use `aiosqlite`, asyncio subprocess, `run_in_executor`). See [python-conventions](.claude/rules/python-conventions.md).
|
|
64
69
|
- **Never touch the user's live state in tests.** Integration tests use a real ephemeral app-server with an isolated `CODEX_HOME` and `ephemeral:true` lanes.
|
|
70
|
+
- **Fixtures should be exercised.** Add checked-in cases under `tests/fixtures/` only when a test loads them; prefer Python builders over binary SQLite fixtures.
|
|
71
|
+
- **Live scenarios are opt-in.** Scenario fixtures start real isolated Dispatch/Codex daemons and make model calls; keep them small, synthetic, low-effort, and outside `just check`.
|
|
65
72
|
|
|
66
73
|
## Source control
|
|
67
74
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: outfitter-dispatch
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Local control plane for orchestrating Codex agent lanes over the Codex App Server.
|
|
5
5
|
Project-URL: Homepage, https://github.com/outfitter-dev/dispatch
|
|
6
6
|
Project-URL: Repository, https://github.com/outfitter-dev/dispatch
|
|
@@ -32,6 +32,8 @@ uv tool install outfitter-dispatch
|
|
|
32
32
|
dispatch --help
|
|
33
33
|
dispatchd --help
|
|
34
34
|
dispatch doctor
|
|
35
|
+
dispatch up --json
|
|
36
|
+
dispatch down --json
|
|
35
37
|
```
|
|
36
38
|
|
|
37
39
|
From a source checkout:
|
|
@@ -40,34 +42,62 @@ From a source checkout:
|
|
|
40
42
|
uv sync
|
|
41
43
|
uv run dispatch --help
|
|
42
44
|
uv run dispatch doctor --no-app-server
|
|
43
|
-
uv run dispatch
|
|
45
|
+
uv run dispatch models --no-refresh
|
|
46
|
+
uv run dispatch up --json
|
|
44
47
|
uv run dispatch daemon status
|
|
45
48
|
```
|
|
46
49
|
|
|
47
|
-
|
|
50
|
+
Create an owned managed thread, send it work, and inspect the daemon:
|
|
48
51
|
|
|
49
52
|
```bash
|
|
50
53
|
uv run dispatch new \
|
|
51
54
|
--name docs \
|
|
52
55
|
--cwd /path/to/dispatch \
|
|
56
|
+
--goal "Finish the docs review." \
|
|
53
57
|
--text "Please summarize the current stack state."
|
|
54
|
-
uv run dispatch
|
|
55
|
-
uv run dispatch
|
|
58
|
+
uv run dispatch list
|
|
59
|
+
uv run dispatch get <dispatch-ref>
|
|
60
|
+
uv run dispatch tail <dispatch-ref> --limit 20
|
|
56
61
|
uv run dispatch daemon log --limit 10
|
|
57
|
-
uv run dispatch down
|
|
62
|
+
uv run dispatch down --json
|
|
58
63
|
```
|
|
59
64
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
65
|
+
For durable or parallel launches, point `new` at a launch packet directory and
|
|
66
|
+
preview it without side effects: `dispatch new --name lane-a --cwd /repo --packet
|
|
67
|
+
./packet --dry-run --json`, then `--stage all` to write durable session files under
|
|
68
|
+
`.agents/sessions/<ref>/`. See [`docs/usage/README.md`](docs/usage/README.md) for
|
|
69
|
+
packet layout, file/stdin inputs, and staging.
|
|
70
|
+
|
|
71
|
+
Use owned managed threads for turn-writing work. Existing desktop Codex threads can be attached as
|
|
72
|
+
managed threads, but ADR-0005 blocks turn-writing and history-mutating commands such
|
|
73
|
+
as `send`, `stop`, `goal set`, and `goal clear` on attached lanes by default. A
|
|
74
|
+
local operator can explicitly opt in with `[policy] allow_attached_writes = true`
|
|
75
|
+
in `~/.dispatch/config.toml`; `list --json` and `get --json` expose
|
|
76
|
+
`writable`, `capabilities`, and `write_locked_reason` so scripts can tell which
|
|
77
|
+
lanes can receive writes. Every managed thread has a dispatch-local `ref`; full
|
|
78
|
+
Codex thread UUIDs remain accepted everywhere.
|
|
79
|
+
Titles and `@handles` are mutable convenience labels, not stable identity. Metadata
|
|
80
|
+
lifecycle actions (`rename`, `archive`, `restore`) can target managed refs or raw
|
|
81
|
+
unmanaged Codex thread ids, and `search` can span both. Attach is metadata-only by
|
|
82
|
+
default; use `dispatch sync <selector>` when you want dispatch to refresh its local
|
|
83
|
+
indexed view of an attached thread.
|
|
84
|
+
|
|
85
|
+
`new` reports whether the first message was accepted by the App Server, not whether
|
|
86
|
+
assistant work completed. Use `get` to inspect the latest turn state and persisted
|
|
87
|
+
App Server errors, or `watch` for a bounded live event sample. Slash commands in
|
|
88
|
+
`--text` are plain text; use `--goal` when creating a native App Server goal.
|
|
89
|
+
Use `dispatch models` before pinning model or service-tier presets; Dispatch
|
|
90
|
+
resolves aliases such as `fast` from the live App Server model catalog and keeps
|
|
91
|
+
omitted model/tier values on Codex defaults.
|
|
64
92
|
|
|
65
93
|
For the operator guide, CLI/MCP examples, triggers, and plugin setup, start at
|
|
66
94
|
[`docs/usage/README.md`](docs/usage/README.md).
|
|
67
95
|
|
|
68
96
|
Start troubleshooting with `dispatch doctor`. It checks PATH visibility, the Codex CLI
|
|
69
97
|
and auth footprint, daemon socket/pidfile state, registry schema/integrity, packaged
|
|
70
|
-
skills/plugin assets, and a low-risk Codex App Server initialize smoke.
|
|
98
|
+
skills/plugin assets, and a low-risk Codex App Server initialize smoke. If doctor reports
|
|
99
|
+
an old registry schema, stop the daemon and run `dispatch registry migrate` before
|
|
100
|
+
starting it again.
|
|
71
101
|
|
|
72
102
|
## Agent And Plugin Support
|
|
73
103
|
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# dispatch
|
|
2
|
+
|
|
3
|
+
Local control plane for orchestrating Codex agent lanes over the Codex App Server.
|
|
4
|
+
One authored contract per operation, projected to CLI + MCP (+ remote later) with no drift.
|
|
5
|
+
|
|
6
|
+
## Quick Start
|
|
7
|
+
|
|
8
|
+
Install the CLI from PyPI:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
uv tool install outfitter-dispatch
|
|
12
|
+
dispatch --help
|
|
13
|
+
dispatchd --help
|
|
14
|
+
dispatch doctor
|
|
15
|
+
dispatch up --json
|
|
16
|
+
dispatch down --json
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
From a source checkout:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
uv sync
|
|
23
|
+
uv run dispatch --help
|
|
24
|
+
uv run dispatch doctor --no-app-server
|
|
25
|
+
uv run dispatch models --no-refresh
|
|
26
|
+
uv run dispatch up --json
|
|
27
|
+
uv run dispatch daemon status
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Create an owned managed thread, send it work, and inspect the daemon:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
uv run dispatch new \
|
|
34
|
+
--name docs \
|
|
35
|
+
--cwd /path/to/dispatch \
|
|
36
|
+
--goal "Finish the docs review." \
|
|
37
|
+
--text "Please summarize the current stack state."
|
|
38
|
+
uv run dispatch list
|
|
39
|
+
uv run dispatch get <dispatch-ref>
|
|
40
|
+
uv run dispatch tail <dispatch-ref> --limit 20
|
|
41
|
+
uv run dispatch daemon log --limit 10
|
|
42
|
+
uv run dispatch down --json
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
For durable or parallel launches, point `new` at a launch packet directory and
|
|
46
|
+
preview it without side effects: `dispatch new --name lane-a --cwd /repo --packet
|
|
47
|
+
./packet --dry-run --json`, then `--stage all` to write durable session files under
|
|
48
|
+
`.agents/sessions/<ref>/`. See [`docs/usage/README.md`](docs/usage/README.md) for
|
|
49
|
+
packet layout, file/stdin inputs, and staging.
|
|
50
|
+
|
|
51
|
+
Use owned managed threads for turn-writing work. Existing desktop Codex threads can be attached as
|
|
52
|
+
managed threads, but ADR-0005 blocks turn-writing and history-mutating commands such
|
|
53
|
+
as `send`, `stop`, `goal set`, and `goal clear` on attached lanes by default. A
|
|
54
|
+
local operator can explicitly opt in with `[policy] allow_attached_writes = true`
|
|
55
|
+
in `~/.dispatch/config.toml`; `list --json` and `get --json` expose
|
|
56
|
+
`writable`, `capabilities`, and `write_locked_reason` so scripts can tell which
|
|
57
|
+
lanes can receive writes. Every managed thread has a dispatch-local `ref`; full
|
|
58
|
+
Codex thread UUIDs remain accepted everywhere.
|
|
59
|
+
Titles and `@handles` are mutable convenience labels, not stable identity. Metadata
|
|
60
|
+
lifecycle actions (`rename`, `archive`, `restore`) can target managed refs or raw
|
|
61
|
+
unmanaged Codex thread ids, and `search` can span both. Attach is metadata-only by
|
|
62
|
+
default; use `dispatch sync <selector>` when you want dispatch to refresh its local
|
|
63
|
+
indexed view of an attached thread.
|
|
64
|
+
|
|
65
|
+
`new` reports whether the first message was accepted by the App Server, not whether
|
|
66
|
+
assistant work completed. Use `get` to inspect the latest turn state and persisted
|
|
67
|
+
App Server errors, or `watch` for a bounded live event sample. Slash commands in
|
|
68
|
+
`--text` are plain text; use `--goal` when creating a native App Server goal.
|
|
69
|
+
Use `dispatch models` before pinning model or service-tier presets; Dispatch
|
|
70
|
+
resolves aliases such as `fast` from the live App Server model catalog and keeps
|
|
71
|
+
omitted model/tier values on Codex defaults.
|
|
72
|
+
|
|
73
|
+
For the operator guide, CLI/MCP examples, triggers, and plugin setup, start at
|
|
74
|
+
[`docs/usage/README.md`](docs/usage/README.md).
|
|
75
|
+
|
|
76
|
+
Start troubleshooting with `dispatch doctor`. It checks PATH visibility, the Codex CLI
|
|
77
|
+
and auth footprint, daemon socket/pidfile state, registry schema/integrity, packaged
|
|
78
|
+
skills/plugin assets, and a low-risk Codex App Server initialize smoke. If doctor reports
|
|
79
|
+
an old registry schema, stop the daemon and run `dispatch registry migrate` before
|
|
80
|
+
starting it again.
|
|
81
|
+
|
|
82
|
+
## Agent And Plugin Support
|
|
83
|
+
|
|
84
|
+
This repo ships first-party skills in [`skills/`](skills/):
|
|
85
|
+
|
|
86
|
+
- [`skills/dispatch/SKILL.md`](skills/dispatch/SKILL.md) teaches agents how to operate
|
|
87
|
+
dispatch safely.
|
|
88
|
+
- [`skills/dm/SKILL.md`](skills/dm/SKILL.md) is the dispatch-backed "dispatch message"
|
|
89
|
+
workflow for short inter-lane messages.
|
|
90
|
+
|
|
91
|
+
The workspace-local Codex plugin bundle lives at [`plugins/dispatch/`](plugins/dispatch/),
|
|
92
|
+
with a marketplace entry in [`.agents/plugins/marketplace.json`](.agents/plugins/marketplace.json).
|
|
93
|
+
Restart Codex if the plugin does not appear immediately.
|
|
94
|
+
|
|
95
|
+
## Project Docs
|
|
96
|
+
|
|
97
|
+
- [`docs/development/design.md`](docs/development/design.md) - architecture and design notes.
|
|
98
|
+
- [`docs/adrs/`](docs/adrs/) - accepted architecture decisions.
|
|
99
|
+
- [`docs/research/`](docs/research/) - verified Codex App Server findings.
|
|
100
|
+
- [`.agents/plans/v0/RETRO.md`](.agents/plans/v0/RETRO.md) - v0 execution ledger and
|
|
101
|
+
verification record.
|
|
102
|
+
|
|
103
|
+
For contributors, [`AGENTS.md`](AGENTS.md) is the canonical fieldguide.
|
|
@@ -6,6 +6,7 @@ check:
|
|
|
6
6
|
uv run ruff format --check .
|
|
7
7
|
uv run mypy src tests
|
|
8
8
|
uv run pytest
|
|
9
|
+
rm -f dist/*.whl dist/*.tar.gz
|
|
9
10
|
uv build
|
|
10
11
|
uv run python scripts/check_package_contents.py
|
|
11
12
|
|
|
@@ -17,6 +18,14 @@ test *args:
|
|
|
17
18
|
test-int *args:
|
|
18
19
|
uv run pytest -m integration {{args}}
|
|
19
20
|
|
|
21
|
+
# Smoke-test the published PyPI package from a clean temporary DISPATCH_HOME.
|
|
22
|
+
pypi-smoke *args:
|
|
23
|
+
uv run python scripts/check_pypi_smoke.py {{args}}
|
|
24
|
+
|
|
25
|
+
# Run a live agent scenario against an isolated DISPATCH_HOME/CODEX_HOME.
|
|
26
|
+
scenario *args:
|
|
27
|
+
uv run python scripts/run_scenario.py {{args}}
|
|
28
|
+
|
|
20
29
|
# Lint with ruff.
|
|
21
30
|
lint:
|
|
22
31
|
uv run ruff check .
|
|
@@ -8,16 +8,25 @@ This workspace-local plugin exposes:
|
|
|
8
8
|
`dispatch mcp`.
|
|
9
9
|
|
|
10
10
|
The MCP server and skills expose the same derived operation registry as the CLI,
|
|
11
|
-
including
|
|
12
|
-
triggers, schemas,
|
|
11
|
+
including managed-thread creation/messaging, dispatch refs, persisted `tail`,
|
|
12
|
+
bounded live `watch`, native goals, triggers, schemas, model catalog reads, and
|
|
13
|
+
daemon status/log reads.
|
|
14
|
+
`new --goal` creates native App Server goal state; `/goal ...` in message text is
|
|
15
|
+
plain text and should not be used as a goal substitute. `new` also accepts launch
|
|
16
|
+
packets (`--packet DIR`), file/stdin inputs (`--goal-file`/`--input-file`/
|
|
17
|
+
`--output-schema-file`, `-` for stdin), a mutation-free `--dry-run`, and durable
|
|
18
|
+
staging (`--stage all|<parts>` → `.agents/sessions/<ref>/`).
|
|
19
|
+
Use `dispatch models` or the MCP daemon-read `models` op before pinning explicit
|
|
20
|
+
model/service-tier presets.
|
|
13
21
|
|
|
14
22
|
Run `dispatch doctor` after installing or upgrading dispatch. It verifies the CLI
|
|
15
23
|
entrypoints, Codex CLI/auth footprint, daemon socket/pidfile state, registry
|
|
16
24
|
schema/integrity, packaged skills/plugin assets, and a low-risk App Server
|
|
17
25
|
initialize smoke. Use `dispatch doctor --no-app-server` when you only want local
|
|
18
|
-
install checks.
|
|
26
|
+
install checks. If doctor reports an old registry schema, run `dispatch down`,
|
|
27
|
+
`dispatch registry migrate`, then `dispatch up`.
|
|
19
28
|
|
|
20
|
-
Run `dispatch up` before MCP tool calls that need the daemon. `dispatch mcp`
|
|
29
|
+
Run `dispatch up --json` before MCP tool calls that need the daemon. `dispatch mcp`
|
|
21
30
|
serves the derived tools over stdio; the daemon remains the executor.
|
|
22
31
|
|
|
23
32
|
`skills` is a symlink to the repo-root [`../../skills`](../../skills) tree so the plugin
|