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.
Files changed (143) hide show
  1. outfitter_dispatch-0.1.0/.agents/plans/PLANNING.md +35 -0
  2. outfitter_dispatch-0.1.0/.agents/plans/cli-mcp-ergonomics/GOAL.md +25 -0
  3. outfitter_dispatch-0.1.0/.agents/plans/cli-mcp-ergonomics/PLAN.md +125 -0
  4. outfitter_dispatch-0.1.0/.agents/plans/cli-mcp-ergonomics/REFS.md +62 -0
  5. outfitter_dispatch-0.1.0/.agents/plans/cli-mcp-ergonomics/RETRO.md +351 -0
  6. outfitter_dispatch-0.1.0/.agents/plans/v0/GOAL.md +27 -0
  7. outfitter_dispatch-0.1.0/.agents/plans/v0/PLAN.md +81 -0
  8. outfitter_dispatch-0.1.0/.agents/plans/v0/REFS.md +32 -0
  9. outfitter_dispatch-0.1.0/.agents/plans/v0/RETRO.md +108 -0
  10. outfitter_dispatch-0.1.0/.agents/plugins/marketplace.json +20 -0
  11. outfitter_dispatch-0.1.0/.claude/rules/agent-docs.md +28 -0
  12. outfitter_dispatch-0.1.0/.claude/rules/client.md +29 -0
  13. outfitter_dispatch-0.1.0/.claude/rules/contracts.md +54 -0
  14. outfitter_dispatch-0.1.0/.claude/rules/python-conventions.md +12 -0
  15. outfitter_dispatch-0.1.0/.claude/rules/surfaces.md +24 -0
  16. outfitter_dispatch-0.1.0/.github/workflows/ci.yml +32 -0
  17. outfitter_dispatch-0.1.0/.github/workflows/publish.yml +27 -0
  18. outfitter_dispatch-0.1.0/.gitignore +29 -0
  19. outfitter_dispatch-0.1.0/.python-version +1 -0
  20. outfitter_dispatch-0.1.0/AGENTS.md +68 -0
  21. outfitter_dispatch-0.1.0/CLAUDE.md +17 -0
  22. outfitter_dispatch-0.1.0/PKG-INFO +87 -0
  23. outfitter_dispatch-0.1.0/README.md +67 -0
  24. outfitter_dispatch-0.1.0/docs/adrs/0000-contract-first-surface-derived.md +44 -0
  25. outfitter_dispatch-0.1.0/docs/adrs/0001-typed-exceptions-over-result.md +42 -0
  26. outfitter_dispatch-0.1.0/docs/adrs/0002-single-daemon-over-one-app-server.md +43 -0
  27. outfitter_dispatch-0.1.0/docs/adrs/0003-own-scheduler-not-codex-automations.md +42 -0
  28. outfitter_dispatch-0.1.0/docs/adrs/0005-lane-authority-capability-ladder.md +56 -0
  29. outfitter_dispatch-0.1.0/docs/adrs/0006-handler-context-and-di.md +45 -0
  30. outfitter_dispatch-0.1.0/docs/adrs/0007-normalized-internal-lane-events.md +45 -0
  31. outfitter_dispatch-0.1.0/docs/adrs/0008-control-socket-protocol.md +47 -0
  32. outfitter_dispatch-0.1.0/docs/adrs/0009-mcp-daemon-lifecycle.md +57 -0
  33. outfitter_dispatch-0.1.0/docs/adrs/0010-surface-projections-are-ergonomic-not-isomorphic.md +65 -0
  34. outfitter_dispatch-0.1.0/docs/adrs/0011-codex-session-registration-is-explicit.md +56 -0
  35. outfitter_dispatch-0.1.0/docs/adrs/0012-conditional-triggers-and-event-sinks.md +60 -0
  36. outfitter_dispatch-0.1.0/docs/adrs/0013-dispatch-mesh-is-daemon-federation.md +60 -0
  37. outfitter_dispatch-0.1.0/docs/adrs/0014-mesh-auth-discovery-and-durable-queues.md +70 -0
  38. outfitter_dispatch-0.1.0/docs/adrs/0015-new-command-config-presets-and-name-prefixes.md +141 -0
  39. outfitter_dispatch-0.1.0/docs/adrs/0016-history-goals-and-bounded-watch.md +69 -0
  40. outfitter_dispatch-0.1.0/docs/adrs/README.md +27 -0
  41. outfitter_dispatch-0.1.0/docs/adrs/template.md +37 -0
  42. outfitter_dispatch-0.1.0/docs/development/design.md +182 -0
  43. outfitter_dispatch-0.1.0/docs/research/app-server-verification.md +132 -0
  44. outfitter_dispatch-0.1.0/docs/research/orchestration-thesis.md +61 -0
  45. outfitter_dispatch-0.1.0/docs/usage/README.md +367 -0
  46. outfitter_dispatch-0.1.0/justfile +32 -0
  47. outfitter_dispatch-0.1.0/lefthook.yml +17 -0
  48. outfitter_dispatch-0.1.0/plugins/dispatch/.codex-plugin/plugin.json +46 -0
  49. outfitter_dispatch-0.1.0/plugins/dispatch/.mcp.json +9 -0
  50. outfitter_dispatch-0.1.0/plugins/dispatch/README.md +19 -0
  51. outfitter_dispatch-0.1.0/plugins/dispatch/assets/dispatch.svg +7 -0
  52. outfitter_dispatch-0.1.0/plugins/dispatch/skills/README.md +10 -0
  53. outfitter_dispatch-0.1.0/plugins/dispatch/skills/dispatch/SKILL.md +238 -0
  54. outfitter_dispatch-0.1.0/plugins/dispatch/skills/dm/SKILL.md +114 -0
  55. outfitter_dispatch-0.1.0/pyproject.toml +95 -0
  56. outfitter_dispatch-0.1.0/spikes/01_stdio_grammar.py +87 -0
  57. outfitter_dispatch-0.1.0/spikes/02_messaging.py +101 -0
  58. outfitter_dispatch-0.1.0/spikes/03_approvals_guardian.py +64 -0
  59. outfitter_dispatch-0.1.0/spikes/04_resume_fanout.py +105 -0
  60. outfitter_dispatch-0.1.0/spikes/05_ws_multiclient.py +106 -0
  61. outfitter_dispatch-0.1.0/spikes/README.md +22 -0
  62. outfitter_dispatch-0.1.0/src/outfitter/dispatch/__init__.py +6 -0
  63. outfitter_dispatch-0.1.0/src/outfitter/dispatch/cli.py +16 -0
  64. outfitter_dispatch-0.1.0/src/outfitter/dispatch/client/AGENTS.md +1 -0
  65. outfitter_dispatch-0.1.0/src/outfitter/dispatch/client/__init__.py +47 -0
  66. outfitter_dispatch-0.1.0/src/outfitter/dispatch/client/client.py +360 -0
  67. outfitter_dispatch-0.1.0/src/outfitter/dispatch/client/errors.py +33 -0
  68. outfitter_dispatch-0.1.0/src/outfitter/dispatch/client/events.py +163 -0
  69. outfitter_dispatch-0.1.0/src/outfitter/dispatch/client/models.py +247 -0
  70. outfitter_dispatch-0.1.0/src/outfitter/dispatch/client/router.py +148 -0
  71. outfitter_dispatch-0.1.0/src/outfitter/dispatch/client/transport.py +123 -0
  72. outfitter_dispatch-0.1.0/src/outfitter/dispatch/config.py +34 -0
  73. outfitter_dispatch-0.1.0/src/outfitter/dispatch/contracts/AGENTS.md +1 -0
  74. outfitter_dispatch-0.1.0/src/outfitter/dispatch/contracts/__init__.py +43 -0
  75. outfitter_dispatch-0.1.0/src/outfitter/dispatch/contracts/context.py +144 -0
  76. outfitter_dispatch-0.1.0/src/outfitter/dispatch/contracts/derive_cli.py +388 -0
  77. outfitter_dispatch-0.1.0/src/outfitter/dispatch/contracts/derive_mcp.py +191 -0
  78. outfitter_dispatch-0.1.0/src/outfitter/dispatch/contracts/errors.py +101 -0
  79. outfitter_dispatch-0.1.0/src/outfitter/dispatch/contracts/examples.py +51 -0
  80. outfitter_dispatch-0.1.0/src/outfitter/dispatch/contracts/execute.py +27 -0
  81. outfitter_dispatch-0.1.0/src/outfitter/dispatch/contracts/op.py +75 -0
  82. outfitter_dispatch-0.1.0/src/outfitter/dispatch/contracts/registry.py +38 -0
  83. outfitter_dispatch-0.1.0/src/outfitter/dispatch/core/__init__.py +2 -0
  84. outfitter_dispatch-0.1.0/src/outfitter/dispatch/core/handlers.py +631 -0
  85. outfitter_dispatch-0.1.0/src/outfitter/dispatch/core/models.py +331 -0
  86. outfitter_dispatch-0.1.0/src/outfitter/dispatch/core/new_config.py +255 -0
  87. outfitter_dispatch-0.1.0/src/outfitter/dispatch/core/ops.py +403 -0
  88. outfitter_dispatch-0.1.0/src/outfitter/dispatch/core/queue.py +59 -0
  89. outfitter_dispatch-0.1.0/src/outfitter/dispatch/core/reactor.py +93 -0
  90. outfitter_dispatch-0.1.0/src/outfitter/dispatch/core/scheduler.py +79 -0
  91. outfitter_dispatch-0.1.0/src/outfitter/dispatch/core/trigger_handlers.py +118 -0
  92. outfitter_dispatch-0.1.0/src/outfitter/dispatch/core/triggers.py +102 -0
  93. outfitter_dispatch-0.1.0/src/outfitter/dispatch/daemon/__init__.py +6 -0
  94. outfitter_dispatch-0.1.0/src/outfitter/dispatch/daemon/__main__.py +61 -0
  95. outfitter_dispatch-0.1.0/src/outfitter/dispatch/daemon/control.py +94 -0
  96. outfitter_dispatch-0.1.0/src/outfitter/dispatch/daemon/host.py +79 -0
  97. outfitter_dispatch-0.1.0/src/outfitter/dispatch/daemon/lifecycle.py +103 -0
  98. outfitter_dispatch-0.1.0/src/outfitter/dispatch/daemon/supervisor.py +94 -0
  99. outfitter_dispatch-0.1.0/src/outfitter/dispatch/registry/__init__.py +2 -0
  100. outfitter_dispatch-0.1.0/src/outfitter/dispatch/registry/models.py +121 -0
  101. outfitter_dispatch-0.1.0/src/outfitter/dispatch/registry/store.py +380 -0
  102. outfitter_dispatch-0.1.0/src/outfitter/dispatch/surfaces/AGENTS.md +1 -0
  103. outfitter_dispatch-0.1.0/src/outfitter/dispatch/surfaces/__init__.py +5 -0
  104. outfitter_dispatch-0.1.0/src/outfitter/dispatch/surfaces/cli.py +122 -0
  105. outfitter_dispatch-0.1.0/src/outfitter/dispatch/surfaces/mcp.py +137 -0
  106. outfitter_dispatch-0.1.0/src/outfitter/dispatch/version.py +15 -0
  107. outfitter_dispatch-0.1.0/tests/__init__.py +1 -0
  108. outfitter_dispatch-0.1.0/tests/client/__init__.py +1 -0
  109. outfitter_dispatch-0.1.0/tests/client/conftest.py +57 -0
  110. outfitter_dispatch-0.1.0/tests/client/test_client.py +207 -0
  111. outfitter_dispatch-0.1.0/tests/client/test_events.py +76 -0
  112. outfitter_dispatch-0.1.0/tests/client/test_models.py +169 -0
  113. outfitter_dispatch-0.1.0/tests/client/test_router.py +60 -0
  114. outfitter_dispatch-0.1.0/tests/conftest.py +46 -0
  115. outfitter_dispatch-0.1.0/tests/contracts/__init__.py +1 -0
  116. outfitter_dispatch-0.1.0/tests/contracts/test_contracts.py +127 -0
  117. outfitter_dispatch-0.1.0/tests/core/__init__.py +1 -0
  118. outfitter_dispatch-0.1.0/tests/core/test_examples.py +57 -0
  119. outfitter_dispatch-0.1.0/tests/core/test_handlers.py +641 -0
  120. outfitter_dispatch-0.1.0/tests/core/test_new_config.py +78 -0
  121. outfitter_dispatch-0.1.0/tests/core/test_trigger_handlers.py +81 -0
  122. outfitter_dispatch-0.1.0/tests/core/test_triggers.py +267 -0
  123. outfitter_dispatch-0.1.0/tests/daemon/__init__.py +1 -0
  124. outfitter_dispatch-0.1.0/tests/daemon/test_control.py +94 -0
  125. outfitter_dispatch-0.1.0/tests/daemon/test_lifecycle.py +56 -0
  126. outfitter_dispatch-0.1.0/tests/daemon/test_supervisor.py +90 -0
  127. outfitter_dispatch-0.1.0/tests/fakes.py +275 -0
  128. outfitter_dispatch-0.1.0/tests/integration/__init__.py +1 -0
  129. outfitter_dispatch-0.1.0/tests/integration/_drive.py +97 -0
  130. outfitter_dispatch-0.1.0/tests/integration/conftest.py +78 -0
  131. outfitter_dispatch-0.1.0/tests/integration/test_app_server.py +144 -0
  132. outfitter_dispatch-0.1.0/tests/integration/test_daemon_e2e.py +74 -0
  133. outfitter_dispatch-0.1.0/tests/integration/test_lifecycle_e2e.py +67 -0
  134. outfitter_dispatch-0.1.0/tests/registry/__init__.py +1 -0
  135. outfitter_dispatch-0.1.0/tests/registry/test_store.py +89 -0
  136. outfitter_dispatch-0.1.0/tests/registry/test_triggers_store.py +78 -0
  137. outfitter_dispatch-0.1.0/tests/surfaces/__init__.py +1 -0
  138. outfitter_dispatch-0.1.0/tests/surfaces/test_derive_cli.py +214 -0
  139. outfitter_dispatch-0.1.0/tests/surfaces/test_derive_mcp.py +61 -0
  140. outfitter_dispatch-0.1.0/tests/surfaces/test_mcp_routing.py +104 -0
  141. outfitter_dispatch-0.1.0/tests/surfaces/test_parity.py +143 -0
  142. outfitter_dispatch-0.1.0/tests/test_smoke.py +38 -0
  143. 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`.