outfitter-dispatch 0.1.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.1.0/.agents/plans/PLANNING.md +35 -0
- outfitter_dispatch-0.1.0/.agents/plans/cli-mcp-ergonomics/GOAL.md +25 -0
- outfitter_dispatch-0.1.0/.agents/plans/cli-mcp-ergonomics/PLAN.md +125 -0
- outfitter_dispatch-0.1.0/.agents/plans/cli-mcp-ergonomics/REFS.md +62 -0
- outfitter_dispatch-0.1.0/.agents/plans/cli-mcp-ergonomics/RETRO.md +351 -0
- outfitter_dispatch-0.1.0/.agents/plans/v0/GOAL.md +27 -0
- outfitter_dispatch-0.1.0/.agents/plans/v0/PLAN.md +81 -0
- outfitter_dispatch-0.1.0/.agents/plans/v0/REFS.md +32 -0
- outfitter_dispatch-0.1.0/.agents/plans/v0/RETRO.md +108 -0
- outfitter_dispatch-0.1.0/.agents/plugins/marketplace.json +20 -0
- outfitter_dispatch-0.1.0/.claude/rules/agent-docs.md +28 -0
- outfitter_dispatch-0.1.0/.claude/rules/client.md +29 -0
- outfitter_dispatch-0.1.0/.claude/rules/contracts.md +54 -0
- outfitter_dispatch-0.1.0/.claude/rules/python-conventions.md +12 -0
- outfitter_dispatch-0.1.0/.claude/rules/surfaces.md +24 -0
- outfitter_dispatch-0.1.0/.github/workflows/ci.yml +32 -0
- outfitter_dispatch-0.1.0/.github/workflows/publish.yml +27 -0
- outfitter_dispatch-0.1.0/.gitignore +29 -0
- outfitter_dispatch-0.1.0/.python-version +1 -0
- outfitter_dispatch-0.1.0/AGENTS.md +68 -0
- outfitter_dispatch-0.1.0/CLAUDE.md +17 -0
- outfitter_dispatch-0.1.0/PKG-INFO +87 -0
- outfitter_dispatch-0.1.0/README.md +67 -0
- outfitter_dispatch-0.1.0/docs/adrs/0000-contract-first-surface-derived.md +44 -0
- outfitter_dispatch-0.1.0/docs/adrs/0001-typed-exceptions-over-result.md +42 -0
- outfitter_dispatch-0.1.0/docs/adrs/0002-single-daemon-over-one-app-server.md +43 -0
- outfitter_dispatch-0.1.0/docs/adrs/0003-own-scheduler-not-codex-automations.md +42 -0
- outfitter_dispatch-0.1.0/docs/adrs/0005-lane-authority-capability-ladder.md +56 -0
- outfitter_dispatch-0.1.0/docs/adrs/0006-handler-context-and-di.md +45 -0
- outfitter_dispatch-0.1.0/docs/adrs/0007-normalized-internal-lane-events.md +45 -0
- outfitter_dispatch-0.1.0/docs/adrs/0008-control-socket-protocol.md +47 -0
- outfitter_dispatch-0.1.0/docs/adrs/0009-mcp-daemon-lifecycle.md +57 -0
- outfitter_dispatch-0.1.0/docs/adrs/0010-surface-projections-are-ergonomic-not-isomorphic.md +65 -0
- outfitter_dispatch-0.1.0/docs/adrs/0011-codex-session-registration-is-explicit.md +56 -0
- outfitter_dispatch-0.1.0/docs/adrs/0012-conditional-triggers-and-event-sinks.md +60 -0
- outfitter_dispatch-0.1.0/docs/adrs/0013-dispatch-mesh-is-daemon-federation.md +60 -0
- outfitter_dispatch-0.1.0/docs/adrs/0014-mesh-auth-discovery-and-durable-queues.md +70 -0
- outfitter_dispatch-0.1.0/docs/adrs/0015-new-command-config-presets-and-name-prefixes.md +141 -0
- outfitter_dispatch-0.1.0/docs/adrs/0016-history-goals-and-bounded-watch.md +69 -0
- outfitter_dispatch-0.1.0/docs/adrs/README.md +27 -0
- outfitter_dispatch-0.1.0/docs/adrs/template.md +37 -0
- outfitter_dispatch-0.1.0/docs/development/design.md +182 -0
- outfitter_dispatch-0.1.0/docs/research/app-server-verification.md +132 -0
- outfitter_dispatch-0.1.0/docs/research/orchestration-thesis.md +61 -0
- outfitter_dispatch-0.1.0/docs/usage/README.md +367 -0
- outfitter_dispatch-0.1.0/justfile +32 -0
- outfitter_dispatch-0.1.0/lefthook.yml +17 -0
- outfitter_dispatch-0.1.0/plugins/dispatch/.codex-plugin/plugin.json +46 -0
- outfitter_dispatch-0.1.0/plugins/dispatch/.mcp.json +9 -0
- outfitter_dispatch-0.1.0/plugins/dispatch/README.md +19 -0
- outfitter_dispatch-0.1.0/plugins/dispatch/assets/dispatch.svg +7 -0
- outfitter_dispatch-0.1.0/plugins/dispatch/skills/README.md +10 -0
- outfitter_dispatch-0.1.0/plugins/dispatch/skills/dispatch/SKILL.md +238 -0
- outfitter_dispatch-0.1.0/plugins/dispatch/skills/dm/SKILL.md +114 -0
- outfitter_dispatch-0.1.0/pyproject.toml +95 -0
- outfitter_dispatch-0.1.0/spikes/01_stdio_grammar.py +87 -0
- outfitter_dispatch-0.1.0/spikes/02_messaging.py +101 -0
- outfitter_dispatch-0.1.0/spikes/03_approvals_guardian.py +64 -0
- outfitter_dispatch-0.1.0/spikes/04_resume_fanout.py +105 -0
- outfitter_dispatch-0.1.0/spikes/05_ws_multiclient.py +106 -0
- outfitter_dispatch-0.1.0/spikes/README.md +22 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/__init__.py +6 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/cli.py +16 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/client/AGENTS.md +1 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/client/__init__.py +47 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/client/client.py +360 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/client/errors.py +33 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/client/events.py +163 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/client/models.py +247 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/client/router.py +148 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/client/transport.py +123 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/config.py +34 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/contracts/AGENTS.md +1 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/contracts/__init__.py +43 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/contracts/context.py +144 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/contracts/derive_cli.py +388 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/contracts/derive_mcp.py +191 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/contracts/errors.py +101 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/contracts/examples.py +51 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/contracts/execute.py +27 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/contracts/op.py +75 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/contracts/registry.py +38 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/core/__init__.py +2 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/core/handlers.py +631 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/core/models.py +331 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/core/new_config.py +255 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/core/ops.py +403 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/core/queue.py +59 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/core/reactor.py +93 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/core/scheduler.py +79 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/core/trigger_handlers.py +118 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/core/triggers.py +102 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/daemon/__init__.py +6 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/daemon/__main__.py +61 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/daemon/control.py +94 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/daemon/host.py +79 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/daemon/lifecycle.py +103 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/daemon/supervisor.py +94 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/registry/__init__.py +2 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/registry/models.py +121 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/registry/store.py +380 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/surfaces/AGENTS.md +1 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/surfaces/__init__.py +5 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/surfaces/cli.py +122 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/surfaces/mcp.py +137 -0
- outfitter_dispatch-0.1.0/src/outfitter/dispatch/version.py +15 -0
- outfitter_dispatch-0.1.0/tests/__init__.py +1 -0
- outfitter_dispatch-0.1.0/tests/client/__init__.py +1 -0
- outfitter_dispatch-0.1.0/tests/client/conftest.py +57 -0
- outfitter_dispatch-0.1.0/tests/client/test_client.py +207 -0
- outfitter_dispatch-0.1.0/tests/client/test_events.py +76 -0
- outfitter_dispatch-0.1.0/tests/client/test_models.py +169 -0
- outfitter_dispatch-0.1.0/tests/client/test_router.py +60 -0
- outfitter_dispatch-0.1.0/tests/conftest.py +46 -0
- outfitter_dispatch-0.1.0/tests/contracts/__init__.py +1 -0
- outfitter_dispatch-0.1.0/tests/contracts/test_contracts.py +127 -0
- outfitter_dispatch-0.1.0/tests/core/__init__.py +1 -0
- outfitter_dispatch-0.1.0/tests/core/test_examples.py +57 -0
- outfitter_dispatch-0.1.0/tests/core/test_handlers.py +641 -0
- outfitter_dispatch-0.1.0/tests/core/test_new_config.py +78 -0
- outfitter_dispatch-0.1.0/tests/core/test_trigger_handlers.py +81 -0
- outfitter_dispatch-0.1.0/tests/core/test_triggers.py +267 -0
- outfitter_dispatch-0.1.0/tests/daemon/__init__.py +1 -0
- outfitter_dispatch-0.1.0/tests/daemon/test_control.py +94 -0
- outfitter_dispatch-0.1.0/tests/daemon/test_lifecycle.py +56 -0
- outfitter_dispatch-0.1.0/tests/daemon/test_supervisor.py +90 -0
- outfitter_dispatch-0.1.0/tests/fakes.py +275 -0
- outfitter_dispatch-0.1.0/tests/integration/__init__.py +1 -0
- outfitter_dispatch-0.1.0/tests/integration/_drive.py +97 -0
- outfitter_dispatch-0.1.0/tests/integration/conftest.py +78 -0
- outfitter_dispatch-0.1.0/tests/integration/test_app_server.py +144 -0
- outfitter_dispatch-0.1.0/tests/integration/test_daemon_e2e.py +74 -0
- outfitter_dispatch-0.1.0/tests/integration/test_lifecycle_e2e.py +67 -0
- outfitter_dispatch-0.1.0/tests/registry/__init__.py +1 -0
- outfitter_dispatch-0.1.0/tests/registry/test_store.py +89 -0
- outfitter_dispatch-0.1.0/tests/registry/test_triggers_store.py +78 -0
- outfitter_dispatch-0.1.0/tests/surfaces/__init__.py +1 -0
- outfitter_dispatch-0.1.0/tests/surfaces/test_derive_cli.py +214 -0
- outfitter_dispatch-0.1.0/tests/surfaces/test_derive_mcp.py +61 -0
- outfitter_dispatch-0.1.0/tests/surfaces/test_mcp_routing.py +104 -0
- outfitter_dispatch-0.1.0/tests/surfaces/test_parity.py +143 -0
- outfitter_dispatch-0.1.0/tests/test_smoke.py +38 -0
- outfitter_dispatch-0.1.0/uv.lock +970 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Planning conventions (dispatch)
|
|
2
|
+
|
|
3
|
+
How goal packets and phased execution work in this repo. Read before planning or executing a goal. (Authority: repo `AGENTS.md` > this file > tool defaults.)
|
|
4
|
+
|
|
5
|
+
## Packet layout
|
|
6
|
+
- Active packets: `.agents/plans/{slug}/` with `PLAN.md` (phases + gates), `GOAL.md` (pasteable `/goal` + loop), `RETRO.md` (durable ledger), `REFS.md` (pointers). The current packet is `v0/`.
|
|
7
|
+
- `.agents/plans` is tracked; `.agents/notes/` is local-only (gitignored) for scratch/session notes.
|
|
8
|
+
- On completion, move the whole packet to `.agents/plans/archive/`.
|
|
9
|
+
|
|
10
|
+
## Phased execution = Graphite stack
|
|
11
|
+
- One phase = one Graphite branch, stacked in order on `main`. PRs stay **draft** until their review gate passes. `gt submit --stack --draft` once the repo is synced to Graphite (else open draft PRs via `gh`).
|
|
12
|
+
- Phases must be small and independently reviewable.
|
|
13
|
+
|
|
14
|
+
## Verification ladder (every phase, green before review)
|
|
15
|
+
1. `just check` = `ruff check` + `ruff format --check` + `mypy --strict` + `pytest`
|
|
16
|
+
2. examples-as-tests (`test_examples(registry)`) once the contract layer exists
|
|
17
|
+
3. integration vs a **real ephemeral `codex app-server`** (isolated `CODEX_HOME`, `ephemeral:true` lanes) — never the user's `~/.codex` or live daemon
|
|
18
|
+
|
|
19
|
+
## Local review gate (between phases)
|
|
20
|
+
After a phase is green + self-reviewed, request a **local review** before starting the next phase. Output contract:
|
|
21
|
+
```
|
|
22
|
+
Overall score: n/5
|
|
23
|
+
Summary: <one line>
|
|
24
|
+
Findings:
|
|
25
|
+
- P0|P1|P2|P3 — <file:line> — <finding>
|
|
26
|
+
Prompt To Fix With AI: <concise fix prompt>
|
|
27
|
+
No-findings statement: <inspected, residual risk>
|
|
28
|
+
```
|
|
29
|
+
Severity: P0 cannot-proceed · P1 correctness/contract regression · P2 quality/docs/coverage (docs correctness is P2) · P3 style. Fix P0–P2; P3 fix-if-cheap or record deferred. Advance only at ≥4/5 with no open P0/P1/P2, or explicit user OK. Record every round in `RETRO.md`.
|
|
30
|
+
|
|
31
|
+
## Retro discipline
|
|
32
|
+
`RETRO.md` is the source of truth for what happened. Update it before every handoff/ready/merge/pause; keep execution, verification, review, and forbidden-action logs current; finalize it before claiming completion. A transcript-only report is never sufficient.
|
|
33
|
+
|
|
34
|
+
## Constraints
|
|
35
|
+
Honor the repo's ADRs (`docs/adrs/`). Subagents do no source-control writes. No merge / non-draft submit / publish without explicit user OK.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# CLI/MCP Ergonomics — quality loop goal
|
|
2
|
+
|
|
3
|
+
Pasteable `/goal` for a deceptively simple quality loop. The executor should
|
|
4
|
+
read the queued issues in [`RETRO.md`](./RETRO.md), then loop until the branch
|
|
5
|
+
is actually good.
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
/goal From `/path/to/dispatch`, run the CLI/MCP ergonomics quality loop on branch `feat/cli-mcp-ergonomics`.
|
|
9
|
+
|
|
10
|
+
Read first: `AGENTS.md`, `.agents/plans/cli-mcp-ergonomics/RETRO.md`, and the touched CLI/MCP/handler tests.
|
|
11
|
+
|
|
12
|
+
Start with the queued quality findings in `RETRO.md`. Then repeat up to 5 loops:
|
|
13
|
+
1. Find the highest-value bug, debt, missing test, stale doc, or less-than-good code in this branch.
|
|
14
|
+
2. Fix one coherent slice.
|
|
15
|
+
3. Run focused tests, then `just check` when the slice could affect the gate.
|
|
16
|
+
4. Commit the slice with a conventional commit message.
|
|
17
|
+
5. Review the branch locally; fix P0/P1/P2 before the next loop.
|
|
18
|
+
6. Update `RETRO.md` with what changed, checks, review result, and remaining risk.
|
|
19
|
+
|
|
20
|
+
Keep the loop boring and sharp. Use subagents only for bounded review or scouting, and verify their claims yourself. Do not open a PR, push, merge, publish, or touch live user agent state.
|
|
21
|
+
|
|
22
|
+
Stop when either: queued findings are closed, `just check` is green, local review has no P0/P1/P2, `RETRO.md` is accurate, and you would be comfortable shipping the branch; or 5 loops are complete; or the same blocker repeats 3 times.
|
|
23
|
+
|
|
24
|
+
Final report: loops run, commits made, exact checks, review result, queued issues closed/deferred, remaining risks, and final git state.
|
|
25
|
+
```
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# CLI/MCP Ergonomics — implementation plan
|
|
2
|
+
|
|
3
|
+
One-branch implementation packet for reshaping dispatch's operator surfaces
|
|
4
|
+
without breaking the contract-first/no-drift architecture. This is intentionally
|
|
5
|
+
a single big swing, not a Graphite stack. Goal loop: [`GOAL.md`](./GOAL.md).
|
|
6
|
+
Execution ledger: [`RETRO.md`](./RETRO.md). References: [`REFS.md`](./REFS.md).
|
|
7
|
+
|
|
8
|
+
## Objective
|
|
9
|
+
|
|
10
|
+
Ship a coherent CLI/MCP projection centered on:
|
|
11
|
+
|
|
12
|
+
- `dispatch send` and `dispatch stop`
|
|
13
|
+
- first-class `dispatch lane`
|
|
14
|
+
- grouped `dispatch goal`
|
|
15
|
+
- grouped `dispatch trigger`
|
|
16
|
+
- jq-friendly `--json` output and generated schemas
|
|
17
|
+
- MCP tools grouped by workflow/safety boundary, not CLI spelling
|
|
18
|
+
|
|
19
|
+
## Product grammar
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
dispatch send @docs "Review the README."
|
|
23
|
+
dispatch send @docs "Also check ADRs." --steer
|
|
24
|
+
dispatch send @docs "After this finishes, summarize risks." --queue
|
|
25
|
+
dispatch send @docs "Stop that and fix tests first." --interject
|
|
26
|
+
dispatch send @docs --context "Prior decision: use lane publicly, thread internally."
|
|
27
|
+
|
|
28
|
+
dispatch stop @docs
|
|
29
|
+
dispatch stop --lane @docs
|
|
30
|
+
|
|
31
|
+
dispatch lane get @docs
|
|
32
|
+
dispatch lane status @docs
|
|
33
|
+
dispatch lane list
|
|
34
|
+
dispatch lane list --unmanaged
|
|
35
|
+
dispatch lane attach <thread-id>
|
|
36
|
+
dispatch lane rename @docs docs-review
|
|
37
|
+
dispatch lane tail @docs
|
|
38
|
+
dispatch lane tail @docs --follow
|
|
39
|
+
dispatch lane fork @docs --name docs-copy
|
|
40
|
+
dispatch lane rollback @docs --turns 1
|
|
41
|
+
dispatch lane compact @docs
|
|
42
|
+
dispatch lane archive @docs
|
|
43
|
+
|
|
44
|
+
dispatch goal status @docs
|
|
45
|
+
dispatch goal set @docs "Loop until checks are green."
|
|
46
|
+
dispatch goal clear @docs
|
|
47
|
+
|
|
48
|
+
dispatch trigger add --lane @docs ...
|
|
49
|
+
dispatch trigger list
|
|
50
|
+
dispatch trigger rm <trigger-id>
|
|
51
|
+
dispatch trigger pause <trigger-id>
|
|
52
|
+
dispatch trigger resume <trigger-id>
|
|
53
|
+
|
|
54
|
+
dispatch daemon status
|
|
55
|
+
dispatch daemon log --limit 20
|
|
56
|
+
|
|
57
|
+
dispatch schema send
|
|
58
|
+
dispatch preset list
|
|
59
|
+
dispatch preset new reviewer
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Decisions
|
|
63
|
+
|
|
64
|
+
- `send` is the primary verb for putting instructions or context into a lane;
|
|
65
|
+
it pairs with `stop`.
|
|
66
|
+
- `stop` is cancel-only. It maps to App Server `turn/interrupt` and sends no
|
|
67
|
+
replacement message.
|
|
68
|
+
- `--steer`, `--queue`, `--interject`, and `--context` are first-class send
|
|
69
|
+
flags. Equivalent `--mode steer|queue|interject|context` is automation-friendly.
|
|
70
|
+
The choices are mutually exclusive.
|
|
71
|
+
- `--interject` means stop the active turn, then start the replacement message.
|
|
72
|
+
- `--context` means model-visible context injection only; it does not wake the
|
|
73
|
+
lane.
|
|
74
|
+
- Keep `--lane` for operational commands. It is clearer than `--to`.
|
|
75
|
+
- `lane list --unmanaged` replaces a standalone `discover` concept.
|
|
76
|
+
- `open` folds into `new --no-send` or an equivalent explicit flag; `attach`
|
|
77
|
+
becomes `lane attach`.
|
|
78
|
+
- `tail` should consolidate `transcript` and `watch` if it can do so honestly.
|
|
79
|
+
Until true streaming exists, never describe bounded event samples as infinite
|
|
80
|
+
tails.
|
|
81
|
+
- History/lifecycle controls move under `lane`.
|
|
82
|
+
- `up`/`down` can remain short; daemon status/logging should live under
|
|
83
|
+
`daemon`.
|
|
84
|
+
- Config and presets get operator-facing inspection first: `preset list`, then
|
|
85
|
+
a minimal `preset new <name>` only if the config writer is well understood.
|
|
86
|
+
- No backwards-compatible CLI aliases are required yet.
|
|
87
|
+
|
|
88
|
+
## Implementation guidance
|
|
89
|
+
|
|
90
|
+
- Preserve author-once derivation. Add projection metadata/grouping to the
|
|
91
|
+
contract layer instead of hand-writing a separate CLI/MCP world.
|
|
92
|
+
- Internal ops and handlers may remain small and mechanical: send/start, steer,
|
|
93
|
+
context injection, stop, lane read/list/attach/rename, goal lifecycle, trigger
|
|
94
|
+
lifecycle, daemon read, schema, preset.
|
|
95
|
+
- MCP should stay workflow-shaped. A single lane-management MCP tool may expose
|
|
96
|
+
`get/list/attach/rename/tail` actions; it should not mirror every CLI
|
|
97
|
+
subcommand one-for-one.
|
|
98
|
+
- If the full surface is too much for one clean PR, prioritize:
|
|
99
|
+
`send`, `stop`, `lane get/list/attach/rename`, grouped `goal`, grouped
|
|
100
|
+
`trigger`, JSON/schema derivation, and MCP grouping. Defer broader reshapes
|
|
101
|
+
only with tests proving current behavior and explicit follow-up notes/issues.
|
|
102
|
+
- Treat `--queue` as real only if durable behavior is implemented and tested.
|
|
103
|
+
If not, fail clearly and document the unsupported mode.
|
|
104
|
+
|
|
105
|
+
## Verification
|
|
106
|
+
|
|
107
|
+
- CLI projection tests for `send`, `stop`, `lane get/list/attach/rename`,
|
|
108
|
+
grouped `goal`, grouped `trigger`, `daemon status/log`, and schema output.
|
|
109
|
+
- Handler/contract tests for lane rename and any new composed send modes.
|
|
110
|
+
- MCP projection tests proving every op remains reachable through grouped tools
|
|
111
|
+
with matching schemas, intent/idempotence annotations, examples, and error
|
|
112
|
+
semantics.
|
|
113
|
+
- JSON/schema tests: representative commands support jq-friendly `--json`, and
|
|
114
|
+
`dispatch schema <command>` returns a stable derived schema.
|
|
115
|
+
- Docs/skills updated to the new grammar.
|
|
116
|
+
- Smoke representative CLI help/commands with isolated dispatch/Codex state
|
|
117
|
+
where needed; never touch live user agent state in tests.
|
|
118
|
+
- Final gate: `just check`.
|
|
119
|
+
|
|
120
|
+
## Done
|
|
121
|
+
|
|
122
|
+
Done only when the new grammar is implemented, docs/skills are updated, local
|
|
123
|
+
checks pass, local review has no unresolved P0/P1/P2 findings, and the branch is
|
|
124
|
+
ready for PR/submission. Record verification, review, deferred scope, and final
|
|
125
|
+
state in [`RETRO.md`](./RETRO.md).
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# CLI/MCP Ergonomics — references
|
|
2
|
+
|
|
3
|
+
Paths are repo-relative.
|
|
4
|
+
|
|
5
|
+
## Packet
|
|
6
|
+
|
|
7
|
+
- `.agents/plans/cli-mcp-ergonomics/PLAN.md` — product grammar, decisions,
|
|
8
|
+
implementation guidance, and verification contract.
|
|
9
|
+
- `.agents/plans/cli-mcp-ergonomics/GOAL.md` — pasteable `/goal`.
|
|
10
|
+
- `.agents/plans/cli-mcp-ergonomics/RETRO.md` — execution ledger.
|
|
11
|
+
- `.agents/plans/PLANNING.md` — repo planning and review conventions.
|
|
12
|
+
|
|
13
|
+
## Design and ADRs
|
|
14
|
+
|
|
15
|
+
- `docs/development/design.md` — original architecture and op list.
|
|
16
|
+
- `docs/adrs/0000-contract-first-surface-derived.md` — author once, derive
|
|
17
|
+
surfaces.
|
|
18
|
+
- `docs/adrs/0010-surface-projections-are-ergonomic-not-isomorphic.md` — CLI
|
|
19
|
+
and MCP projection direction.
|
|
20
|
+
- `docs/adrs/0015-new-command-config-presets-and-name-prefixes.md` — `new`,
|
|
21
|
+
config, presets, and name prefixes.
|
|
22
|
+
- `docs/adrs/0016-history-goals-and-bounded-watch.md` — transcript, goals,
|
|
23
|
+
watch, fork, rollback, compact.
|
|
24
|
+
|
|
25
|
+
## Implementation entrypoints
|
|
26
|
+
|
|
27
|
+
- `src/outfitter/dispatch/contracts/derive_cli.py`
|
|
28
|
+
- `src/outfitter/dispatch/contracts/derive_mcp.py`
|
|
29
|
+
- `src/outfitter/dispatch/core/ops.py`
|
|
30
|
+
- `src/outfitter/dispatch/core/models.py`
|
|
31
|
+
- `src/outfitter/dispatch/core/handlers.py`
|
|
32
|
+
- `src/outfitter/dispatch/core/trigger_handlers.py`
|
|
33
|
+
- `src/outfitter/dispatch/registry/store.py`
|
|
34
|
+
- `src/outfitter/dispatch/surfaces/cli.py`
|
|
35
|
+
- `src/outfitter/dispatch/surfaces/mcp.py`
|
|
36
|
+
|
|
37
|
+
## Tests to inspect first
|
|
38
|
+
|
|
39
|
+
- `tests/surfaces/test_derive_cli.py`
|
|
40
|
+
- `tests/surfaces/test_derive_mcp.py`
|
|
41
|
+
- `tests/surfaces/test_mcp_routing.py`
|
|
42
|
+
- `tests/surfaces/test_parity.py`
|
|
43
|
+
- `tests/core/test_handlers.py`
|
|
44
|
+
- `tests/core/test_examples.py`
|
|
45
|
+
- `tests/core/test_new_config.py`
|
|
46
|
+
- `tests/core/test_trigger_handlers.py`
|
|
47
|
+
|
|
48
|
+
## Operator docs and skills
|
|
49
|
+
|
|
50
|
+
- `README.md`
|
|
51
|
+
- `docs/usage/README.md`
|
|
52
|
+
- `skills/dispatch/SKILL.md`
|
|
53
|
+
- `skills/dm/SKILL.md`
|
|
54
|
+
- `plugins/dispatch/`
|
|
55
|
+
|
|
56
|
+
## Commands
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
uv run dispatch --help
|
|
60
|
+
uv run dispatch mcp --help
|
|
61
|
+
just check
|
|
62
|
+
```
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
# CLI/MCP Ergonomics — retro
|
|
2
|
+
|
|
3
|
+
Durable execution ledger for the one-branch CLI/MCP ergonomics goal.
|
|
4
|
+
|
|
5
|
+
Status: **quality loop complete**.
|
|
6
|
+
|
|
7
|
+
## Current branch
|
|
8
|
+
|
|
9
|
+
- Branch: `feat/cli-mcp-ergonomics`
|
|
10
|
+
- Base: `main`
|
|
11
|
+
- Intended shape: one branch / one big swing, not a Graphite stack
|
|
12
|
+
|
|
13
|
+
## Preparation log
|
|
14
|
+
|
|
15
|
+
- 2026-06-04: Created the tracked execution packet under
|
|
16
|
+
`.agents/plans/cli-mcp-ergonomics/` so a fresh goal worker can read the plan
|
|
17
|
+
from a clean worktree.
|
|
18
|
+
- 2026-06-04: Added `.claude/worktrees/` to `.gitignore` so Claude-owned
|
|
19
|
+
background worktrees do not pollute `git status`.
|
|
20
|
+
|
|
21
|
+
## Execution log
|
|
22
|
+
|
|
23
|
+
- 2026-06-04: Implemented ergonomic CLI projection metadata in
|
|
24
|
+
`contracts/derive_cli.py`: root `send`, root cancel-only `stop`, grouped
|
|
25
|
+
`lane`, `goal`, `trigger`, `daemon`, and local `schema <command>`.
|
|
26
|
+
- 2026-06-04: Changed the authored `send` contract to carry
|
|
27
|
+
`mode=send|steer|queue|interject|context`; CLI mode flags are mutually
|
|
28
|
+
exclusive aliases over that contract mode.
|
|
29
|
+
- 2026-06-04: Implemented `send --context`, `send --steer`, and
|
|
30
|
+
`send --interject`; initial `send --queue` deliberately failed because
|
|
31
|
+
durable queue storage/supervision was not implemented yet.
|
|
32
|
+
- 2026-06-04: Added `lane-rename` as a real authored op plus registry handle
|
|
33
|
+
update support; owned lanes also attempt App Server `thread/name/set`.
|
|
34
|
+
- 2026-06-04: Kept MCP workflow grouping derived from the op registry and added
|
|
35
|
+
`rename` to lane write grouping. MCP remains grouped by workflow/safety
|
|
36
|
+
boundary rather than CLI spelling.
|
|
37
|
+
- 2026-06-04: Updated README, usage docs, design command-surface summary,
|
|
38
|
+
plugin README, and `skills/dispatch` + `skills/dm` to the new grammar.
|
|
39
|
+
- 2026-06-04: Committed the green ergonomics baseline as
|
|
40
|
+
`59b4fef feat: project ergonomic cli and mcp surfaces`.
|
|
41
|
+
- 2026-06-04: Implemented durable local `send --queue`: registry-backed
|
|
42
|
+
queued messages, one pending message drained per idle transition, restart
|
|
43
|
+
recovery for claimed-but-not-finished queue rows, and docs/help updates.
|
|
44
|
+
- 2026-06-04: Retired public registry ops `steer`, `brief`, and `interrupt`.
|
|
45
|
+
Their behavior now lives under the single `send` contract (`mode=...`) and
|
|
46
|
+
the `stop` contract. The lower-level handlers remain as small internals for
|
|
47
|
+
triggers and send-mode composition.
|
|
48
|
+
- 2026-06-04: Resolved the coordinator P1 `turn/interrupt` active-turn-id
|
|
49
|
+
finding. Made `TurnInterruptParams.turn_id` and `LaneClient.turn_interrupt`
|
|
50
|
+
(client + `Ctx` protocol + fake) require `str`. Added a shared
|
|
51
|
+
`_require_active_turn(lane, action)` helper so `steer`, `send --interject`,
|
|
52
|
+
internal `interrupt`, and `stop` all raise a clean `ValidationError` on an
|
|
53
|
+
idle lane instead of calling the App Server with a null `turnId`.
|
|
54
|
+
- 2026-06-04: Resolved the queued P3 forced-color JSON finding. Replaced Rich's
|
|
55
|
+
module-level `print_json` calls with a plain `json.dumps`/`typer.echo` helper
|
|
56
|
+
so command and schema JSON stay jq-friendly even when `FORCE_COLOR` is set.
|
|
57
|
+
- 2026-06-04: Quality loop pass 1 verified the forced-color schema regression
|
|
58
|
+
remains fixed, then found and fixed a P2 schema projection drift: composed CLI
|
|
59
|
+
routes `schema "lane list --unmanaged"` and `schema "lane tail --follow"` now
|
|
60
|
+
resolve to `discover` and `watch` respectively, and unknown schema targets exit
|
|
61
|
+
cleanly instead of rendering a traceback.
|
|
62
|
+
- 2026-06-04: Quality loop pass 2 reviewed docs/skills, live CLI help, schema
|
|
63
|
+
smokes, queue semantics, trigger handlers, and daemon log behavior. Fixed a
|
|
64
|
+
P3 audit gap: `trigger pause` and `trigger resume` now write `actions_log`
|
|
65
|
+
entries like `trigger add` and `trigger rm`.
|
|
66
|
+
- 2026-06-04: Quality loop pass 3 reviewed the branch-vs-main diff, MCP
|
|
67
|
+
routing/error projection, generated schemas, and stale-marker scan. Fixed a
|
|
68
|
+
P3 projected-schema wording issue: `SendInput.mode` no longer says queue is
|
|
69
|
+
"reserved" after durable queueing shipped.
|
|
70
|
+
- 2026-06-04: Final no-findings pass reviewed the current diff, retro drift,
|
|
71
|
+
MCP/parity tests, schema smokes, and live help. No unresolved P0/P1/P2 and no
|
|
72
|
+
easy worthwhile P3 remained.
|
|
73
|
+
- 2026-06-04: Post-Spark audit loop fixed the remaining derived-surface gaps:
|
|
74
|
+
`schema "lane fork"`, `schema "lane rollback"`, `schema "lane compact"`, and
|
|
75
|
+
`schema "lane archive"` now resolve to their canonical ops. Added a parity
|
|
76
|
+
guard that all public CLI schema routes resolve, with `open` explicitly
|
|
77
|
+
allowlisted as the only intentional MCP-only op.
|
|
78
|
+
|
|
79
|
+
## Verification log
|
|
80
|
+
|
|
81
|
+
- 2026-06-04: Focused surface/handler/example tests:
|
|
82
|
+
`uv run pytest tests/surfaces/test_derive_cli.py tests/surfaces/test_derive_mcp.py tests/surfaces/test_mcp_routing.py tests/surfaces/test_parity.py tests/core/test_handlers.py tests/core/test_examples.py -q`
|
|
83
|
+
-> 52 passed.
|
|
84
|
+
- 2026-06-04: Isolated CLI smokes used temporary `DISPATCH_HOME` only:
|
|
85
|
+
`dispatch --help`, `dispatch lane --help`, `dispatch goal --help`,
|
|
86
|
+
`dispatch trigger --help`, `dispatch send --help`, `dispatch goal set --help`,
|
|
87
|
+
`dispatch schema send`, and `dispatch schema "goal set"`.
|
|
88
|
+
- 2026-06-04: Schema smoke with `jq` confirmed `schema "goal set"` maps to
|
|
89
|
+
`goal-set` with `lane,objective,status,token_budget`.
|
|
90
|
+
- 2026-06-04: `git diff --check` -> clean.
|
|
91
|
+
- 2026-06-04: Final gate `just check` -> ruff check passed, ruff format
|
|
92
|
+
passed, mypy passed, pytest 130 passed / 8 deselected.
|
|
93
|
+
- 2026-06-04: Queue-focused tests:
|
|
94
|
+
`uv run pytest tests/registry/test_store.py tests/core/test_handlers.py tests/core/test_triggers.py tests/daemon/test_supervisor.py tests/surfaces/test_derive_cli.py tests/core/test_examples.py -q`
|
|
95
|
+
-> 64 passed.
|
|
96
|
+
- 2026-06-04: Queue loop final gate `just check` -> ruff check passed, ruff
|
|
97
|
+
format passed, mypy passed, pytest 136 passed / 8 deselected.
|
|
98
|
+
- 2026-06-04: Queue CLI smoke used temporary `DISPATCH_HOME`:
|
|
99
|
+
`dispatch send --help` shows `--queue` as "Queue after current work"; `schema
|
|
100
|
+
send` still derives mode schema from `SendInput`.
|
|
101
|
+
- 2026-06-04: Final cleanup focused tests:
|
|
102
|
+
`uv run pytest tests/core/test_examples.py tests/surfaces/test_derive_mcp.py tests/surfaces/test_mcp_routing.py tests/surfaces/test_derive_cli.py tests/surfaces/test_parity.py tests/core/test_handlers.py -q`
|
|
103
|
+
-> 54 passed.
|
|
104
|
+
- 2026-06-04: Final cleanup gate `just check` -> ruff check passed, ruff
|
|
105
|
+
format passed, mypy passed, pytest 136 passed / 8 deselected.
|
|
106
|
+
- 2026-06-04: Final cleanup smokes used temporary `DISPATCH_HOME`: `schema stop`
|
|
107
|
+
maps to op `stop` with input key `lane`; `send --help` and `stop --help`
|
|
108
|
+
render successfully.
|
|
109
|
+
- 2026-06-04: `turn/interrupt` fix focused tests:
|
|
110
|
+
`uv run pytest tests/core/test_handlers.py tests/core/test_examples.py tests/surfaces/test_parity.py -q`
|
|
111
|
+
-> 41 passed. New cases: `test_stop_requires_active_turn`,
|
|
112
|
+
`test_interrupt_requires_active_turn`, `test_interject_requires_active_turn`.
|
|
113
|
+
- 2026-06-04: `turn/interrupt` fix gate `just check` -> ruff check passed, ruff
|
|
114
|
+
format passed, mypy passed, pytest 139 passed / 8 deselected. Note: this
|
|
115
|
+
background shell exports `FORCE_COLOR=3`, which makes the `schema` command
|
|
116
|
+
emit ANSI codes and fails the substring assertion in
|
|
117
|
+
`test_derive_cli.py::test_schema_command_prints_derived_schema_without_daemon`;
|
|
118
|
+
the gate is green once color is not force-enabled (`env -u FORCE_COLOR`). That
|
|
119
|
+
test is a pre-existing P3 robustness gap (it should strip ANSI), unrelated to
|
|
120
|
+
this fix.
|
|
121
|
+
- 2026-06-04: Forced-color JSON focused tests:
|
|
122
|
+
`FORCE_COLOR=3 uv run pytest tests/surfaces/test_derive_cli.py::test_schema_command_prints_derived_schema_without_daemon tests/surfaces/test_derive_cli.py::test_schema_command_stays_plain_json_when_color_is_forced -q`
|
|
123
|
+
-> 2 passed.
|
|
124
|
+
- 2026-06-04: Surface focused tests:
|
|
125
|
+
`uv run pytest tests/surfaces/test_derive_cli.py tests/surfaces/test_parity.py tests/surfaces/test_derive_mcp.py tests/surfaces/test_mcp_routing.py -q`
|
|
126
|
+
-> 20 passed.
|
|
127
|
+
- 2026-06-04: Forced-color JSON loop gate `just check` -> ruff check passed,
|
|
128
|
+
ruff format passed, mypy passed, pytest 140 passed / 8 deselected.
|
|
129
|
+
- 2026-06-04: Forced-color seed verification:
|
|
130
|
+
`FORCE_COLOR=3 uv run pytest tests/surfaces/test_derive_cli.py::test_schema_command_prints_derived_schema_without_daemon tests/surfaces/test_derive_cli.py::test_schema_command_stays_plain_json_when_color_is_forced -q`
|
|
131
|
+
-> 2 passed.
|
|
132
|
+
- 2026-06-04: Schema composed-route focused tests:
|
|
133
|
+
`uv run pytest tests/surfaces/test_derive_cli.py -q` -> 12 passed.
|
|
134
|
+
- 2026-06-04: Surface projection focused tests:
|
|
135
|
+
`uv run pytest tests/surfaces/test_derive_cli.py tests/surfaces/test_parity.py tests/surfaces/test_derive_mcp.py tests/surfaces/test_mcp_routing.py -q`
|
|
136
|
+
-> 22 passed.
|
|
137
|
+
- 2026-06-04: Schema composed-route CLI smokes:
|
|
138
|
+
`uv run dispatch schema "lane list --unmanaged" | jq -r .op` -> `discover`;
|
|
139
|
+
`uv run dispatch schema "lane tail --follow" | jq -r .op` -> `watch`.
|
|
140
|
+
- 2026-06-04: Schema composed-route gate `just check` -> ruff check passed,
|
|
141
|
+
ruff format passed, mypy passed, pytest 142 passed / 8 deselected.
|
|
142
|
+
- 2026-06-04: Trigger audit focused tests:
|
|
143
|
+
`uv run pytest tests/core/test_trigger_handlers.py tests/core/test_triggers.py tests/core/test_handlers.py::test_status_and_log_reflect_activity -q`
|
|
144
|
+
-> 18 passed.
|
|
145
|
+
- 2026-06-04: Trigger audit surface/examples smoke:
|
|
146
|
+
`uv run pytest tests/core/test_examples.py tests/surfaces/test_derive_cli.py tests/surfaces/test_mcp_routing.py -q`
|
|
147
|
+
-> 18 passed.
|
|
148
|
+
- 2026-06-04: Trigger audit gate `just check` -> ruff check passed, ruff
|
|
149
|
+
format passed, mypy passed, pytest 142 passed / 8 deselected.
|
|
150
|
+
- 2026-06-04: MCP/parity review:
|
|
151
|
+
`uv run pytest tests/surfaces/test_derive_mcp.py tests/surfaces/test_mcp_routing.py tests/surfaces/test_parity.py tests/contracts/test_contracts.py -q`
|
|
152
|
+
-> 14 passed.
|
|
153
|
+
- 2026-06-04: Schema wording focused tests:
|
|
154
|
+
`uv run pytest tests/surfaces/test_derive_cli.py tests/surfaces/test_derive_mcp.py tests/surfaces/test_parity.py -q`
|
|
155
|
+
-> 18 passed.
|
|
156
|
+
- 2026-06-04: Schema wording smoke:
|
|
157
|
+
`uv run dispatch schema send | jq -r '.input.properties.mode.description'`
|
|
158
|
+
-> describes queue as durable delivery for the next idle transition.
|
|
159
|
+
- 2026-06-04: Schema wording gate `just check` -> ruff check passed, ruff
|
|
160
|
+
format passed, mypy passed, pytest 142 passed / 8 deselected.
|
|
161
|
+
- 2026-06-04: Final no-findings focused sweep:
|
|
162
|
+
`uv run pytest tests/surfaces/test_derive_cli.py tests/surfaces/test_derive_mcp.py tests/surfaces/test_mcp_routing.py tests/surfaces/test_parity.py tests/core/test_examples.py tests/core/test_handlers.py tests/core/test_trigger_handlers.py tests/core/test_triggers.py tests/registry/test_store.py tests/daemon/test_supervisor.py -q`
|
|
163
|
+
-> 85 passed.
|
|
164
|
+
- 2026-06-04: Final schema smokes:
|
|
165
|
+
`uv run dispatch schema send`, `uv run dispatch schema "lane tail --follow"`,
|
|
166
|
+
and `uv run dispatch schema "lane list --unmanaged"` -> ops `send`, `watch`,
|
|
167
|
+
and `discover`.
|
|
168
|
+
- 2026-06-04: Final closure gate `just check` -> ruff check passed, ruff
|
|
169
|
+
format passed, mypy passed, pytest 142 passed / 8 deselected.
|
|
170
|
+
- 2026-06-04: Post-Spark focused surface tests:
|
|
171
|
+
`uv run pytest tests/surfaces/test_derive_cli.py tests/surfaces/test_parity.py -q`
|
|
172
|
+
-> 16 passed.
|
|
173
|
+
- 2026-06-04: Post-Spark forced-color focused tests:
|
|
174
|
+
`FORCE_COLOR=3 COLORTERM=truecolor uv run pytest tests/surfaces/test_derive_cli.py tests/surfaces/test_parity.py -q`
|
|
175
|
+
-> 16 passed.
|
|
176
|
+
- 2026-06-04: Post-Spark schema route smokes:
|
|
177
|
+
`send`, `stop`, `new`, all public `lane`, `goal`, `trigger`, and `daemon`
|
|
178
|
+
schema commands resolved to their expected canonical ops; `open` remains
|
|
179
|
+
intentionally MCP-only.
|
|
180
|
+
- 2026-06-04: Post-Spark closure gate `just check` -> ruff check passed, ruff
|
|
181
|
+
format passed, mypy passed, pytest 143 passed / 8 deselected.
|
|
182
|
+
|
|
183
|
+
## Review log
|
|
184
|
+
|
|
185
|
+
- 2026-06-04 coordinator review:
|
|
186
|
+
Overall score: not ready yet
|
|
187
|
+
Summary: Branch is close and `just check` is green, but two non-PR findings
|
|
188
|
+
should seed the next quality loop.
|
|
189
|
+
Findings:
|
|
190
|
+
- P1 — `src/outfitter/dispatch/core/handlers.py` / `src/outfitter/dispatch/client/models.py`
|
|
191
|
+
— `stop` and `send --interject` can call App Server `turn/interrupt` without
|
|
192
|
+
a known active turn id, while the installed App Server schema requires
|
|
193
|
+
`turnId: string`. Make `TurnInterruptParams.turn_id` required, make the
|
|
194
|
+
client require a `str`, and have idle-lane `stop`/`interject` raise a clean
|
|
195
|
+
`ValidationError` like `steer`.
|
|
196
|
+
- P2 — this retro's final state had stale source-control wording after the
|
|
197
|
+
final cleanup commit. Keep `RETRO.md` accurate as part of the loop.
|
|
198
|
+
|
|
199
|
+
- 2026-06-04 local self-review:
|
|
200
|
+
Overall score: 4/5
|
|
201
|
+
Summary: Core grammar is implemented and verified; no open P0/P1/P2 findings.
|
|
202
|
+
Findings: none P0/P1/P2.
|
|
203
|
+
No-findings statement: Inspected CLI projection diff, send/rename handlers,
|
|
204
|
+
MCP grouping, parity tests, docs/skills updates, and isolated CLI smokes.
|
|
205
|
+
Residual risk is P3-level polish around whether future contract cleanup should
|
|
206
|
+
retire internal legacy ops (`steer`, `brief`, `interrupt`) once all surfaces
|
|
207
|
+
are fully send/stop-centered.
|
|
208
|
+
- 2026-06-04 queue-loop local self-review:
|
|
209
|
+
Overall score: 4.5/5
|
|
210
|
+
Summary: Durable local queue semantics are implemented and verified; no open
|
|
211
|
+
P0/P1/P2 findings.
|
|
212
|
+
Findings: none P0/P1/P2.
|
|
213
|
+
No-findings statement: Inspected registry queue schema, queue drainer,
|
|
214
|
+
handler enqueue path, reactor/supervisor drains, docs/help, and tests. The
|
|
215
|
+
remaining P3 cleanup is contract naming polish around legacy internal message
|
|
216
|
+
ops that no longer match the operator grammar.
|
|
217
|
+
- 2026-06-04 final cleanup local review:
|
|
218
|
+
Overall score: 5/5
|
|
219
|
+
Summary: CLI, MCP, contracts, docs, skills, queue behavior, and tests now tell
|
|
220
|
+
one coherent story.
|
|
221
|
+
Findings: none.
|
|
222
|
+
No-findings statement: Inspected final registry IDs, CLI stop/schema routing,
|
|
223
|
+
MCP route coverage, message-mode handlers, queue semantics, docs/skills, and
|
|
224
|
+
full `just check`. Remaining deferred work (`preset list/new`, true infinite
|
|
225
|
+
tail, optional `open` primitive retirement) is explicitly scoped outside this
|
|
226
|
+
branch rather than a quality gap in the implemented grammar.
|
|
227
|
+
- 2026-06-04 turn/interrupt fix:
|
|
228
|
+
Coordinator P1 (required `turn/interrupt` turnId) is resolved; coordinator P2
|
|
229
|
+
(keep this retro accurate) is addressed by this update. No new P0/P1/P2
|
|
230
|
+
findings. Residual risk: the `schema` command test does not strip ANSI, so it
|
|
231
|
+
fails under forced color — a P3 test-robustness item left for the broader
|
|
232
|
+
quality loop, not this scoped fix.
|
|
233
|
+
- 2026-06-04 forced-color JSON loop:
|
|
234
|
+
Overall score: 5/5
|
|
235
|
+
Summary: The queued P3 is fixed in production behavior and covered by a
|
|
236
|
+
regression test.
|
|
237
|
+
Findings: none.
|
|
238
|
+
No-findings statement: Inspected CLI JSON rendering, schema command output,
|
|
239
|
+
forced-color regression coverage, surface parity, and full `just check`.
|
|
240
|
+
Queued findings are now closed; remaining deferred scope is intentional and
|
|
241
|
+
documented below.
|
|
242
|
+
- 2026-06-04 schema composed-route loop:
|
|
243
|
+
Overall score: 4.5/5
|
|
244
|
+
Summary: The forced-color seed issue is verified closed; a new P2 schema drift
|
|
245
|
+
for flag-composed CLI routes was found and fixed.
|
|
246
|
+
Findings fixed:
|
|
247
|
+
- P2 — `src/outfitter/dispatch/contracts/derive_cli.py` — `schema "lane tail --follow"`
|
|
248
|
+
crashed with a traceback and could not show the `watch` schema, while
|
|
249
|
+
`schema "lane list --unmanaged"` did not expose the `discover` schema.
|
|
250
|
+
No-findings statement: Rechecked CLI schema routing, forced-color behavior,
|
|
251
|
+
surface parity tests, direct schema smokes, and full `just check`. Continue
|
|
252
|
+
looping on handlers, queue semantics, MCP action projection, and docs/skills
|
|
253
|
+
consistency before declaring the branch boring.
|
|
254
|
+
- 2026-06-04 trigger audit loop:
|
|
255
|
+
Overall score: 4.5/5
|
|
256
|
+
Summary: Docs/skills and live help align with the ergonomic grammar; one easy
|
|
257
|
+
worthwhile P3 in trigger-management audit coverage was found and fixed.
|
|
258
|
+
Findings fixed:
|
|
259
|
+
- P3 — `src/outfitter/dispatch/core/trigger_handlers.py` — `trigger pause`
|
|
260
|
+
and `trigger resume` changed durable trigger state without appearing in
|
|
261
|
+
`daemon log`, unlike `trigger add` and `trigger rm`.
|
|
262
|
+
No-findings statement: Rechecked repo-wide public command references, usage
|
|
263
|
+
docs, skills, live `send`/`lane list`/`trigger add`/`new` help, representative
|
|
264
|
+
schema smokes, queue drain code, trigger handlers, and full `just check`.
|
|
265
|
+
Continue one more skeptical pass over MCP routing, error projection, and
|
|
266
|
+
branch-vs-main diff before closing.
|
|
267
|
+
- 2026-06-04 schema wording loop:
|
|
268
|
+
Overall score: 4.5/5
|
|
269
|
+
Summary: MCP routing/parity passed; one stale P3 projected-schema phrase was
|
|
270
|
+
found and fixed.
|
|
271
|
+
Findings fixed:
|
|
272
|
+
- P3 — `src/outfitter/dispatch/core/models.py` — `SendInput.mode` still said
|
|
273
|
+
queue was "reserved for durable queued delivery" even though durable queueing
|
|
274
|
+
is implemented; this stale wording projected into CLI/MCP schemas.
|
|
275
|
+
No-findings statement: Rechecked branch diff shape, MCP grouped tools/routes,
|
|
276
|
+
error projection tests, representative schema outputs, and stale-marker scan.
|
|
277
|
+
The focused schema/MCP tests and full gate passed.
|
|
278
|
+
- 2026-06-04 final no-findings review:
|
|
279
|
+
Overall score: 5/5
|
|
280
|
+
Summary: The branch is boring to ship locally.
|
|
281
|
+
Findings: none.
|
|
282
|
+
No-findings statement: Rechecked current git state, branch diff shape,
|
|
283
|
+
docs/skills public command references, live CLI help, schema smokes, MCP
|
|
284
|
+
grouped routes, MCP error projection, examples-as-tests, handler/queue/trigger
|
|
285
|
+
tests, stale-marker scan, and full `just check`. Deferred items are intentional
|
|
286
|
+
feature scope (`preset list/new`, true infinite tail, optional `open` primitive
|
|
287
|
+
retirement) rather than unresolved quality findings in this branch.
|
|
288
|
+
- 2026-06-04 post-Spark audit review:
|
|
289
|
+
Overall score: 5/5
|
|
290
|
+
Summary: Two read-only Spark audits agreed current docs/skills/help/MCP
|
|
291
|
+
wording is migrated; their actionable derived-surface findings are fixed.
|
|
292
|
+
Findings fixed:
|
|
293
|
+
- P2 — `src/outfitter/dispatch/contracts/derive_cli.py` — composed schema
|
|
294
|
+
routes for `lane fork`, `lane rollback`, `lane compact`, and `lane archive`
|
|
295
|
+
did not resolve to their canonical ops.
|
|
296
|
+
- P3 — `src/outfitter/dispatch/contracts/derive_cli.py` — JSON output is now
|
|
297
|
+
rendered without Rich so forced-color/highlighting environments cannot emit
|
|
298
|
+
ANSI into jq-facing output.
|
|
299
|
+
- P3 — `tests/surfaces/test_parity.py` — CLI op reachability now has an
|
|
300
|
+
explicit public-route coverage assertion with `open` allowlisted as the only
|
|
301
|
+
intentional MCP-only op.
|
|
302
|
+
No-findings statement: Rechecked public docs/skills/help, schema route matrix,
|
|
303
|
+
MCP grouped route coverage, forced-color output, focused surface tests, and
|
|
304
|
+
full `just check`.
|
|
305
|
+
|
|
306
|
+
## Deferred scope / follow-up
|
|
307
|
+
|
|
308
|
+
- Durable `send --queue`: follow-up loop implemented local durable queued sends
|
|
309
|
+
with a registry queue table, one-message idle draining, and restart recovery
|
|
310
|
+
for in-flight queue claims.
|
|
311
|
+
- `preset list` / `preset new`: deferred to avoid growing this branch into config
|
|
312
|
+
authoring. `new --preset` remains supported. Follow-up should expose config
|
|
313
|
+
inspection/writer ops through the contract layer.
|
|
314
|
+
- Full `open` removal from internals: operator docs and CLI now steer users to
|
|
315
|
+
`new --no-send`; the lower-level `open` op remains in the registry/MCP for
|
|
316
|
+
existing core coverage until a separate contract cleanup decides whether to
|
|
317
|
+
retire it.
|
|
318
|
+
- True live tail: `lane tail --follow` remains bounded `watch` behavior. A
|
|
319
|
+
durable infinite tail still needs subscription-capable control socket support.
|
|
320
|
+
|
|
321
|
+
## Queued quality loop
|
|
322
|
+
|
|
323
|
+
1. ~~Fix the `turn/interrupt` active-turn-id contract for `stop` and
|
|
324
|
+
`send --interject`, including client model and tests.~~ Done
|
|
325
|
+
(`require turnId; raise ValidationError on idle lanes`).
|
|
326
|
+
2. ~~Keep this retro accurate after each loop and commit.~~ Done.
|
|
327
|
+
|
|
328
|
+
3. ~~Strip ANSI from CLI JSON/schema output under forced color.~~ Done
|
|
329
|
+
(plain `json.dumps`/`typer.echo` JSON helper plus forced-color regression
|
|
330
|
+
test).
|
|
331
|
+
4. ~~Fix schema projection drift for flag-composed ergonomic CLI routes.~~ Done
|
|
332
|
+
(`schema "lane list --unmanaged"` -> `discover`; `schema "lane tail --follow"`
|
|
333
|
+
-> `watch`; `schema "lane fork|rollback|compact|archive"` -> their
|
|
334
|
+
canonical ops; unknown schema targets exit 2 without tracebacks).
|
|
335
|
+
5. ~~Audit trigger pause/resume mutations.~~ Done (`actions_log` now records
|
|
336
|
+
`trigger-pause` and `trigger-resume`).
|
|
337
|
+
6. ~~Remove stale "queue is reserved" projected schema wording.~~ Done
|
|
338
|
+
(`SendInput.mode` describes durable queued delivery as implemented).
|
|
339
|
+
7. ~~Add an explicit CLI reachability guard for ergonomic projections.~~ Done
|
|
340
|
+
(public schema routes cover every op except intentionally MCP-only `open`).
|
|
341
|
+
|
|
342
|
+
No queued quality-loop findings remain open.
|
|
343
|
+
|
|
344
|
+
## Final state
|
|
345
|
+
|
|
346
|
+
- Branch: `feat/cli-mcp-ergonomics`.
|
|
347
|
+
- Source-control state: one Graphite-tracked commit over `main`, squashed and
|
|
348
|
+
amended after the Spark audit findings.
|
|
349
|
+
- Proof constraints: no destructive git operations, no secrets, no live user
|
|
350
|
+
agent state used in tests/smokes, no hand-written separate MCP world.
|
|
351
|
+
- Final review result: no unresolved P0/P1/P2; no easy worthwhile P3 left.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# dispatch v0 — goal
|
|
2
|
+
|
|
3
|
+
Long-running execution goal for the dispatch v0 build. The pasteable `/goal` below is the evaluator contract: it keeps the loop alive without chat history. Detail lives in `PLAN.md` (phases, gates, verification), `design.md` (architecture), `docs/adrs/` (decisions), `RETRO.md` (ledger). Runtime notes: works as a Codex or Claude `/goal`; the executor owns the Graphite stack and per-phase local-review gate.
|
|
4
|
+
|
|
5
|
+
## Pasteable `/goal`
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
/goal Implement dispatch v0. cwd: ~/Developer/outfitter/dispatch. Packet: .agents/plans/v0/ — read PLAN.md (phases + gates + review contract) and RETRO.md (where execution left off) before acting; design.md = architecture; docs/adrs/0000-0009 = decisions; .agents/plans/PLANNING.md = conventions.
|
|
9
|
+
|
|
10
|
+
OBJECTIVE: build dispatch v0 end-to-end as a Graphite stack, one branch per PLAN phase (0 scaffold → 1 client+spikes → 2 contracts+CLI → 3 triggers → 4 MCP → 5 daemon-lifecycle), each green and LOCALLY REVIEWED before the next begins.
|
|
11
|
+
|
|
12
|
+
LOOP, per phase N: (1) implement TDD on the phase branch per PLAN; (2) run the validation ladder until green; (3) self-review; (4) request a LOCAL review in the code-review contract (Overall score n/5; P0-P3 findings with file:line + Prompt-To-Fix); (5) fix P0-P2 (P3 fix-if-cheap else record deferred); (6) update RETRO.md with the round; (7) gt submit --draft; (8) advance to N+1 ONLY after the gate passes — local reviewer >=4/5 with no open P0/P1/P2, or explicit user OK. Post a short progress note each phase: phase, branch, ladder result, review score, next.
|
|
13
|
+
|
|
14
|
+
VALIDATION LADDER: just check (ruff + ruff format --check + mypy --strict + pytest) -> examples-as-tests (test_examples) -> integration vs a REAL ephemeral codex app-server (isolated CODEX_HOME, ephemeral:true lanes). Phase 1 has two gating spikes — cross-process safety (gates ADR-0005 attached-lane authority) and concurrent-lane backpressure (F); record findings in RETRO.md and STOP for a decision if either is unsafe.
|
|
15
|
+
|
|
16
|
+
COMPLETION (all true): phases 0-5 done; PLAN Definition of Done met (open/attach lanes [owned read/write; attached observe-only unless ADR-0005 cleared], send/steer/brief/interrupt, time+event triggers, a CLI AND an MCP server derived from ONE op registry with a passing parity test, a recoverable daemon); CI green per branch; each phase locally reviewed; RETRO.md finalized (execution, verification, review, forbidden-action logs + final state). The final transcript points to RETRO.md's final state — a transcript-only report is NOT sufficient.
|
|
17
|
+
|
|
18
|
+
CONSTRAINTS: honor ADRs 0000-0009; one contract set -> derived surfaces (never hand-write a CLI command or MCP tool); typed exceptions projected at the surface boundary; pin the codex binary and drive it directly (not the openai-codex SDK); NEVER touch the user's ~/.codex or live daemon in tests; subagents perform no source-control writes; PRs stay DRAFT — no merge, no non-draft submit, no package publish without explicit user OK.
|
|
19
|
+
|
|
20
|
+
STOP/PAUSE and report if: a Phase-1 spike shows cross-process unsafe (keep attached lanes observe-only) or backpressure problematic; a gate cannot pass after reasonable attempts; blocked on Graphite sync; any P0 needs a human decision; or scope materially changes.
|
|
21
|
+
|
|
22
|
+
Before any handoff / ready-for-review / merge: update RETRO.md, then summarize its final state in the report.
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Notes for the launcher
|
|
26
|
+
- Prerequisite: the review-findings stack (PRs #1/#2) and this packet should be on `main` (or the stack base) first, and the repo synced to Graphite so `gt submit` works. Until synced, open PRs via `gh` (draft).
|
|
27
|
+
- The local-review gate may be satisfied by a reviewer subagent, a Codex review, or the user — record whichever in `RETRO.md`.
|