catherd-cli 1.3.0 → 1.4.0
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.
- package/README.md +75 -36
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/plugin.json +11 -0
- package/plugin/.mcp-codex.json +10 -0
- package/plugin/bin/catherd-mcp +1 -1
- package/plugin/skills/catherd/SKILL.md +44 -38
- package/plugin/skills/catherd-setup/SKILL.md +22 -6
- package/src/adapters/access.ts +7 -1
- package/src/adapters/cli.ts +1 -64
- package/src/cli.ts +48 -19
- package/src/domain/host.ts +17 -0
- package/src/domain/notice.ts +5 -2
- package/src/domain/profile-rules.ts +17 -0
- package/src/domain/profile.ts +32 -5
- package/src/domain/record.ts +1 -0
- package/src/entry/catalog-command.ts +4 -2
- package/src/entry/deps.ts +6 -3
- package/src/entry/doctor-command.ts +11 -2
- package/src/entry/host-arg.ts +28 -0
- package/src/entry/init-command.ts +18 -7
- package/src/entry/lock-command.ts +7 -2
- package/src/entry/mcp/handshake.ts +3 -1
- package/src/entry/mcp/run-tools.ts +5 -2
- package/src/entry/mcp/server.ts +129 -40
- package/src/entry/mcp/setup-tools.ts +7 -2
- package/src/entry/profile-command.ts +108 -12
- package/src/entry/runs-command.ts +81 -5
- package/src/entry/tui/effects.ts +19 -8
- package/src/entry/tui/fixtures.ts +33 -10
- package/src/entry/tui/run.tsx +10 -4
- package/src/entry/tui/state.ts +19 -6
- package/src/entry/tui/stories.ts +11 -4
- package/src/entry/tui/views/profile-actions.ts +4 -2
- package/src/entry/tui/views/profiles.tsx +2 -2
- package/src/entry/tui/views/save-dialog.tsx +2 -2
- package/src/infra/cli.ts +65 -0
- package/src/infra/codex-queue.ts +165 -0
- package/src/infra/delivery.ts +83 -0
- package/src/infra/dispatch-dir.ts +1 -0
- package/src/infra/env.ts +4 -1
- package/src/infra/host-context.ts +58 -0
- package/src/infra/peer-inbox.ts +4 -1
- package/src/infra/supervisor.ts +3 -2
- package/src/services/admission.ts +7 -3
- package/src/services/agent-links.ts +30 -5
- package/src/services/backends.ts +7 -0
- package/src/services/dispatch-service.ts +17 -7
- package/src/services/dispatches.ts +6 -1
- package/src/services/doctor-backends.ts +30 -7
- package/src/services/doctor-checks.ts +20 -5
- package/src/services/doctor-push.ts +69 -90
- package/src/services/doctor.ts +105 -33
- package/src/services/finalize.ts +1 -1
- package/src/services/lane-service.ts +1 -0
- package/src/services/notifier.ts +322 -70
- package/src/services/peek.ts +46 -9
- package/src/services/ports.ts +8 -2
- package/src/services/profile-service.ts +116 -30
- package/src/services/profile-store.ts +23 -6
- package/src/services/routing-service.ts +6 -1
- package/src/services/run-debug.ts +98 -4
- package/src/services/run-service.ts +2 -0
- package/src/services/run-store.ts +10 -4
- package/src/services/runs-page.ts +3 -2
- package/src/services/session-view.ts +18 -13
- package/src/services/sessions.ts +32 -16
- package/src/services/setup.ts +31 -10
- package/src/services/summary.ts +40 -5
- package/src/services/treat-likes.ts +22 -9
package/README.md
CHANGED
|
@@ -6,19 +6,18 @@
|
|
|
6
6
|
(")(")
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
Autopilot builds from your own Claude Code session.
|
|
10
|
-
Antigravity or headless Claude Code
|
|
9
|
+
Autopilot builds from your own Claude Code or native Codex session. Your profile routes the architect, verifier and workers to their backends; Codex, opencode, Cursor, Grok Build,
|
|
10
|
+
Antigravity or headless Claude Code processes write the code, and [Jev](https://typesafe.ai) picks the model and effort for each piece
|
|
11
11
|
of work, climbing a ladder only when a cheaper rung falls short.
|
|
12
12
|
|
|
13
13
|
- **Your harness, as you set it up.** Every role runs in its vendor's own CLI with your config,
|
|
14
14
|
hooks, skills and `AGENTS.md`. Isolation is an opt-in toggle per profile and harness, for when
|
|
15
15
|
you'd rather save the tokens your customizations cost.
|
|
16
|
-
- **Claude roles stay native.** `claude:` rungs run as ordinary Claude Code subagents; Codex,
|
|
16
|
+
- **Claude roles stay native on Claude Code.** `claude:` rungs require that host and run as ordinary Claude Code subagents; Codex,
|
|
17
17
|
opencode, Cursor, Grok Build, Antigravity and headless `claude-code:` rungs run through catherd's MCP server.
|
|
18
18
|
- **Survives restarts.** Workers are detached processes writing straight to disk, so a dropped
|
|
19
19
|
MCP server never loses a run.
|
|
20
|
-
- **Results come to you.** Roles run side by side while you keep talking
|
|
21
|
-
arrives in the session as a message, like a native subagent's notice, and `peek` shows how a run stands.
|
|
20
|
+
- **Results come to you.** Roles run side by side while you keep talking. Claude Code uses its peer inbox; Codex uses queued next input through its existing native server. A busy Codex conversation processes it after the active turn. Queue acceptance and result collection are separate; `peek` shows how a run stands.
|
|
22
21
|
- **A protocol the tools enforce.** Every lane is routed, every brief ends with the reply contract, and a
|
|
23
22
|
milestone lands only after a reviewer and a verifier passed it. Workers can run their own checks (network,
|
|
24
23
|
loopback, Docker, the lock dir); an owner question parks one milestone, not the run.
|
|
@@ -28,7 +27,7 @@ of work, climbing a ladder only when a cheaper rung falls short.
|
|
|
28
27
|
## Requirements
|
|
29
28
|
|
|
30
29
|
- [Bun](https://bun.sh) ≥ 1.4
|
|
31
|
-
- [Claude Code](https://claude.com/claude-code) (
|
|
30
|
+
- An orchestration host: [Claude Code](https://claude.com/claude-code), or native [Codex](https://github.com/openai/codex) CLI/Desktop with plugin support and the existing native queue endpoint (installed CLI 0.159.2 verified for packaging; queue support is feature-detected)
|
|
32
31
|
- At least one worker backend, logged in:
|
|
33
32
|
- [Codex CLI](https://github.com/openai/codex) 0.157.0 or newer
|
|
34
33
|
- [opencode](https://opencode.ai) **v2**, 2.0.16 or newer: `curl -fsSL https://opencode.ai/v2/install | bash`
|
|
@@ -47,7 +46,7 @@ of work, climbing a ladder only when a cheaper rung falls short.
|
|
|
47
46
|
|
|
48
47
|
`catherd doctor` checks each backend's version and login and prints the fix for anything missing. The default
|
|
49
48
|
profile runs its workers on Codex; without Codex, doctor's fix also names how to move those roles to a backend
|
|
50
|
-
you have (`/catherd-setup
|
|
49
|
+
you have (`/catherd-setup`, or `catherd profile set roles.<role>.rungs <rung> --host <codex|claude-code>`). Codex-only setup does not require or configure Claude; enabled selected roles and reachable failover decide optional dependencies. Doctor sends nothing by default; `--test-push` is an explicit smoke send from a validated host session.
|
|
51
50
|
|
|
52
51
|
### Cursor
|
|
53
52
|
|
|
@@ -111,12 +110,17 @@ route is the one meant for automation; check the terms before you rely on a plan
|
|
|
111
110
|
|
|
112
111
|
## Install
|
|
113
112
|
|
|
113
|
+
The published `v1.3.0` marketplace and global `catherd-cli@1.3.0` remain the stable Claude integration. The native Codex feature in this checkout is unreleased and held pending actual packaged CLI/Desktop/Claude acceptance. A matching version alone does not prove that the feature core ran. Use the [local packaged acceptance procedure](docs/dev/live-verification.md#14-native-codex-packaging-and-completion-acceptance) for this candidate; do not publish or update the remote tag to test it.
|
|
114
|
+
|
|
115
|
+
### Claude Code
|
|
116
|
+
|
|
114
117
|
```sh
|
|
115
118
|
bun add -g catherd-cli
|
|
116
|
-
catherd init
|
|
119
|
+
catherd init --host claude-code
|
|
117
120
|
```
|
|
118
121
|
|
|
119
|
-
The npm package is `catherd-cli`; the command it installs is `catherd`. `bunx catherd-cli init
|
|
122
|
+
The npm package is `catherd-cli`; the command it installs is `catherd`. `bunx catherd-cli init --host claude-code`
|
|
123
|
+
works too (a terminal with no host evidence cannot pick the architect/verifier defaults, so name the host): `init`
|
|
120
124
|
installs the global command at its own version (`--no-global` skips it) and says `installing catherd…` before
|
|
121
125
|
it does, though the first `bunx` resolve itself prints nothing for up to half a minute. `init` asks for the
|
|
122
126
|
optional Jev key and the optional Artificial Analysis key, syncs the public model sources, writes the default
|
|
@@ -132,41 +136,76 @@ claude plugin install catherd@catherd
|
|
|
132
136
|
```
|
|
133
137
|
|
|
134
138
|
Start a new Claude Code session so the plugin, its MCP server and the agent files load, then check with
|
|
135
|
-
`catherd doctor
|
|
136
|
-
|
|
139
|
+
`catherd doctor --host claude-code`. From inside that session, explicit `catherd doctor --test-push` sends a labeled smoke notice; inspect actual processing separately from transport acceptance.
|
|
140
|
+
|
|
141
|
+
### Native Codex — after the feature release
|
|
142
|
+
|
|
143
|
+
These remote commands become feature installation guidance only after the held release is published:
|
|
144
|
+
|
|
145
|
+
```sh
|
|
146
|
+
bun add -g catherd-cli
|
|
147
|
+
catherd init --host codex
|
|
148
|
+
codex plugin marketplace add 47vigen/catherd
|
|
149
|
+
codex plugin add catherd@catherd
|
|
150
|
+
codex mcp list --json
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Restart the Codex host to load the installed shared skills and server. Native CLI accepts `owner/repo[@ref]` and a local marketplace path. The supported marketplace uses `.claude-plugin/marketplace.json` with its plugin subdirectory; the native manifest is `plugin/.codex-plugin/plugin.json`, with `skills: "./skills/"` and `mcpServers: "./.mcp-codex.json"`. Installed native resolution supplies `command: "sh"`, `args: ["./bin/catherd-mcp"]`, `cwd: <installed plugin root>` and `CATHERD_ORCHESTRATION_HOST=codex`. No Claude root macro or synthetic session ID belongs in that declaration. The shared launcher/core remains versioned together with both manifests.
|
|
154
|
+
|
|
155
|
+
Pass the actual project `repo` to repository-aware MCP profile/setup/catalog calls, because the server cwd is the plugin root. `run_start(repo, ...)` already requires it. Terminal `init` and `doctor` accept `--host codex|claude-code|auto`; selecting a terminal host chooses setup checks without inventing a conversation owner.
|
|
137
156
|
|
|
138
157
|
## Use
|
|
139
158
|
|
|
140
|
-
In
|
|
159
|
+
In either supported host, use the installed shared skills through that host's skill invocation and tool discovery:
|
|
141
160
|
|
|
142
161
|
- `/catherd <task>` runs a task on autopilot; `/catherd` alone resumes the latest run. While it runs, keep
|
|
143
|
-
talking:
|
|
162
|
+
talking: completion arrives through the host's transport, and "how is it going?" gets a `peek`.
|
|
144
163
|
- `/catherd-setup` tunes your profile in conversation: which models and efforts each role may
|
|
145
164
|
use, cost or speed, isolation, budget and failover.
|
|
146
165
|
|
|
166
|
+
`route` chooses the backend for every role. Native `claude:` uses Claude Code's `Agent` and `record_agent_run` only on Claude Code; process backends, including Codex architect/verifier, use `dispatch` followed by `result`. Omitted Codex architect/verifier choices are exactly `codex:gpt-6.1-sol#high` / `codex:gpt-6.1-sol#low`; omitted Claude choices retain their existing native defaults. Verify that exact model ID against native catalog discovery and validation; if spelling differs, resolve the mismatch explicitly with the owner, never silently normalize or substitute, and retain high/low efforts. Explicit ladders and materialized profiles are preserved, without silently converting `claude:` to `claude-code:`. To opt into host defaults, review and save the narrow reset:
|
|
167
|
+
|
|
168
|
+
```sh
|
|
169
|
+
catherd profile reset-host-defaults <profile> --host codex --preview --json > /tmp/catherd-host-defaults-review.json
|
|
170
|
+
# Review the diff, effective defaults, errors and warnings.
|
|
171
|
+
catherd profile reset-host-defaults <profile> --host codex --expect /tmp/catherd-host-defaults-review.json --json
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
It removes only architect/verifier `rungs` and `defaultRung`; every other setting stays intact. Run profile CLI commands from the project directory and choose the actual profile name. Use `--host claude-code` for Claude defaults.
|
|
175
|
+
|
|
176
|
+
Completion never uses `await_results` or model polling. Codex sends through `codex queue --remote unix://` to the validated original thread: idle wake and ordered busy follow-up are the native semantics, without Claude's urgent tool-round priority. A receipt proves queue acceptance, not observed generation or collection; unloaded/interrupted hosts may retain input. Only `result` collects the actual stored record. Explicit `peek(run)` adopts the run for the current host/session; `status` and `result` do not. Unknown/conflicting identity never owns or pushes.
|
|
177
|
+
|
|
178
|
+
Recover unread work with `peek` and `result`. Accepted or ambiguous attempts are not automatically resent. When ambiguity needs a deliberate retry, run from the current owner's validated host session:
|
|
179
|
+
|
|
180
|
+
```sh
|
|
181
|
+
catherd runs retry-push <run> <name> --event '<exact event ID from peek/status>' --acknowledge-possible-duplicate
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
This acknowledges possible duplicate native input; an accepted receipt still suppresses a repeat for that owner/event. Without a supported history reconciliation API, retain ambiguity until an explicit decision. Notices preserve all event IDs, including coalesced events; repeated input means idempotent reads, never another dispatch or landing. Stored records and independent reviewer/verifier gates are authoritative. Profile notification moments use an available host facility, without inventing a Codex notification tool or scheduled wake.
|
|
185
|
+
|
|
147
186
|
In a terminal:
|
|
148
187
|
|
|
149
|
-
| Command
|
|
150
|
-
|
|
|
151
|
-
| `catherd`
|
|
152
|
-
| `catherd init [--no-input] [--no-global] [--profile <p>]`
|
|
153
|
-
| `catherd doctor [--json]`
|
|
154
|
-
| `catherd profile list\|show\|use [--repo]\|new [--from <p>]\|copy\|rm\|diff\|validate`
|
|
155
|
-
| `catherd profile use --repo --clear`
|
|
156
|
-
| `catherd profile set <path> <value> [--profile <p>]`
|
|
157
|
-
| `catherd status [run]`, `catherd watch [--once] [--interval <s>]`
|
|
158
|
-
| `catherd runs list [--repo <path>]\|show <id> [--debug [--name <n>]]\|cancel <id> <name>`
|
|
159
|
-
| `catherd catalog refresh\|list [--backend <b>] [--role <r>] [--text <t>] [--scored]`
|
|
160
|
-
| `catherd catalog sync [--force] [--unmatched]`
|
|
161
|
-
| `catherd catalog treat-like <rung> <like>`
|
|
162
|
-
| `catherd catalog treat-like --suggest <rung>\|--clear <rung>\|--reset`
|
|
163
|
-
| `catherd knowledge show\|add "<line>"\|path [--repo <path>]`
|
|
164
|
-
| `catherd lock [--slots N] -- <cmd>`
|
|
165
|
-
| `catherd mcp`
|
|
166
|
-
| `catherd capture-fixtures [--backend <b>] [--out <dir>]`
|
|
188
|
+
| Command | What it does |
|
|
189
|
+
| ------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
|
|
190
|
+
| `catherd` | The dashboard: Status, Profiles and Runs (below) |
|
|
191
|
+
| `catherd init [--host codex\|claude-code\|auto] [--no-input] [--no-global] [--profile <p>]` | First-run setup; installs the global `catherd` at its own version unless `--no-global` |
|
|
192
|
+
| `catherd doctor [--host codex\|claude-code\|auto] [--test-push] [--json]` | Readiness and capability report; no send unless explicit smoke; exits 3 when not ready |
|
|
193
|
+
| `catherd profile list\|show\|use [--repo]\|new [--from <p>]\|copy\|rm\|diff\|validate` | Profiles; `use --repo` binds one to the repo you are in |
|
|
194
|
+
| `catherd profile use --repo --clear` | Unbinds the repo you are in; it runs on the active profile again |
|
|
195
|
+
| `catherd profile set <path> <value> [--profile <p>]` | One field, e.g. `roles.verifier.access read-only`, `roles.worker.network false`, `budget.usd 20` |
|
|
196
|
+
| `catherd status [run]`, `catherd watch [--once] [--interval <s>]` | Where runs stand, grouped by host and session; read-only ownership |
|
|
197
|
+
| `catherd runs list [--repo <path>]\|show <id> [--debug [--name <n>]]\|cancel <id> <name>` | Past runs, by session; `--debug` adds exit.json and the stderr and event tails, `--name` one role's |
|
|
198
|
+
| `catherd catalog refresh\|list [--backend <b>] [--role <r>] [--text <t>] [--scored]` | The models catherd can place, filtered |
|
|
199
|
+
| `catherd catalog sync [--force] [--unmatched]` | Fetches the public model facts and scores now (below); `--unmatched` lists ids no model matched |
|
|
200
|
+
| `catherd catalog treat-like <rung> <like>` | Scores an unscored rung as a scored one |
|
|
201
|
+
| `catherd catalog treat-like --suggest <rung>\|--clear <rung>\|--reset` | The three nearest stand-ins for a rung; removes one or every mapping of yours |
|
|
202
|
+
| `catherd knowledge show\|add "<line>"\|path [--repo <path>]` | The repo's knowledge.md, which new runs read; `add` appends a fact of yours, marked "by hand" |
|
|
203
|
+
| `catherd lock [--slots N] -- <cmd>` | Runs a heavy command behind the machine-wide semaphore, in its own session (no /dev/tty) |
|
|
204
|
+
| `catherd mcp` | The MCP server on stdio; the plugin starts it, you never need to |
|
|
205
|
+
| `catherd capture-fixtures [--backend <b>] [--out <dir>]` | Contributors: records sanitized test fixtures from real runs (see CONTRIBUTING.md) |
|
|
167
206
|
|
|
168
207
|
A profile command without a profile name (`show`, `set`, `diff`, `validate`), like the MCP profile tools, acts
|
|
169
|
-
on the profile the repo you are in runs on: the one bound to it, else the active one. Run them as
|
|
208
|
+
on the profile the repo you are in runs on: the one bound to it, else the active one. Pass `repo` explicitly to MCP tools; profile CLI commands accept `--host` for effective defaults. Run them as
|
|
170
209
|
`bunx catherd-cli <command>` when catherd is not installed globally. Every read command takes `--json`; a bare `catherd runs` is `catherd runs list`. Exit codes: 0 ok, 1 error, 2 usage, 3 not ready, 130 interrupted; an error prints
|
|
171
210
|
`error E_CODE: message` and a `fix:` line. `--verbose` (or `CATHERD_LOG=debug`) logs more to
|
|
172
211
|
`~/.local/share/catherd/logs/`, kept for 7 days with secrets redacted. The dashboard takes `--plain` (ASCII, no colour)
|
|
@@ -174,7 +213,7 @@ and `--reduced-motion`; `doctor` and `init` take `--plain` for ASCII glyphs too.
|
|
|
174
213
|
|
|
175
214
|
Model facts and scores also come from public sources: models.dev, OpenRouter, LiteLLM, Arena (LMArena), Vectara's
|
|
176
215
|
hallucination leaderboard and Epoch AI, plus Artificial Analysis when you give `catherd init` a free key. The MCP
|
|
177
|
-
server syncs them in the background when a
|
|
216
|
+
server syncs them in the background when a host session starts (each source at most every 12 hours, never
|
|
178
217
|
delaying the session), `init` syncs them, and `catherd catalog sync` (or the `catalog_sync` tool) does it on demand.
|
|
179
218
|
Each answer is kept in `~/.local/share/catherd/sources/`; a source that fails keeps its last good answer, and with no
|
|
180
219
|
network and no sync at all catherd routes on the scores it ships. Those are the keyless sources' values, refreshed
|
|
@@ -219,7 +258,7 @@ tests (CONTRIBUTING.md has the rest).
|
|
|
219
258
|
|
|
220
259
|
`catherd` opens three tabs: **1 Status** (every check with its fix; `y` copies the fix, `r` checks again),
|
|
221
260
|
**2 Profiles** (one tree per profile: roles with their access, default rung, models and efforts, then routing,
|
|
222
|
-
harness, budget, failover, timeouts and notify) and **3 Runs** (the
|
|
261
|
+
harness, budget, failover, timeouts and notify) and **3 Runs** (the host sessions that drove your runs, newest
|
|
223
262
|
first; a session opens on its runs, their milestones and every role with its rung, status, time and last event, live
|
|
224
263
|
ones first; a milestone opens on its digest (what landed, lanes and climbs, reviewer and verifier, tokens); a role
|
|
225
264
|
opens on its brief, reply and record; the open screen redraws as run files change; `esc` goes back,
|
|
@@ -278,8 +317,8 @@ Code session. The details are in [MIGRATION.md](MIGRATION.md).
|
|
|
278
317
|
|
|
279
318
|
## Contributing
|
|
280
319
|
|
|
281
|
-
See [CONTRIBUTING.md](CONTRIBUTING.md). CI
|
|
282
|
-
|
|
320
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md). This feature's checks and acceptance are local, with release held; do not request or re-enable CI for it. The documented historical CI matrix uses Linux/macOS and Bun 1.4.0/latest;
|
|
321
|
+
live verification is in [`docs/dev/live-verification.md`](docs/dev/live-verification.md). Report security issues
|
|
283
322
|
privately, as [SECURITY.md](SECURITY.md) describes. Everyone taking part follows the
|
|
284
323
|
[Code of Conduct](CODE_OF_CONDUCT.md).
|
|
285
324
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "catherd",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Herds coding agents: Claude plans and verifies, Codex, opencode or headless Claude Code workers write the code, and Jev picks the model and effort for each piece.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "47vigen",
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "catherd",
|
|
3
|
+
"version": "1.4.0",
|
|
4
|
+
"description": "Shared catherd orchestration, profiles and durable role results through the versioned MCP core.",
|
|
5
|
+
"author": { "name": "47vigen", "url": "https://github.com/47vigen" },
|
|
6
|
+
"homepage": "https://github.com/47vigen/catherd",
|
|
7
|
+
"repository": "https://github.com/47vigen/catherd",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"skills": "./skills/",
|
|
10
|
+
"mcpServers": "./.mcp-codex.json"
|
|
11
|
+
}
|
package/plugin/bin/catherd-mcp
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
2
|
# catherd's MCP launcher (spec 1.1 §12): the plugin's .mcp.json runs it. The release stamps VERSION
|
|
3
3
|
# (scripts/stamp-plugin-version.mjs), so the plugin always starts the server it was released with.
|
|
4
|
-
VERSION="1.
|
|
4
|
+
VERSION="1.4.0"
|
|
5
5
|
|
|
6
6
|
# a global catherd at this version (catherd init installs one): start it, no resolve at all
|
|
7
7
|
if command -v catherd >/dev/null 2>&1 && [ "$(catherd --version 2>/dev/null)" = "$VERSION" ]; then
|
|
@@ -23,17 +23,19 @@ Your job:
|
|
|
23
23
|
|
|
24
24
|
The catherd server keeps `state.md` true: it rewrites it on every dispatch, climb and landing.
|
|
25
25
|
|
|
26
|
-
**Your first call is `status()`.** Its `version` must be the one this plugin pins, `catherd-cli@1.
|
|
26
|
+
**Your first call is `status()`.** Its `version` must be the one this plugin pins, `catherd-cli@1.4.0`. If it differs, stop and tell the user to restart their host session so the plugin and its server match. Read its host and capability diagnostics; unknown or conflicting identity never authorizes ownership or push.
|
|
27
27
|
|
|
28
28
|
**You never edit product files.** Every line of code, tests or docs comes from a role, including a one-line fix.
|
|
29
29
|
|
|
30
|
-
**You run in the user's own session, on purpose.** The main thread is the user's own model in Claude Code, with their plugins, hooks and memory beside it: the environment they decide in every day. Never propose a stripped launcher or a headless relay to save tokens.
|
|
30
|
+
**You run in the user's own session, on purpose.** The main thread is the user's own model in Claude Code or native Codex, with their plugins, hooks and memory beside it: the environment they decide in every day. Never propose a stripped launcher or a headless relay to save tokens.
|
|
31
31
|
|
|
32
32
|
**Each role runs in its vendor's own harness with the user's customizations — never isolate it.** Codex roles keep the user's config, hooks, MCP servers, skills and `AGENTS.md`. The one exception is the user's own choice, the profile's `harness.<name>.isolated`, and `dispatch` applies it for you.
|
|
33
33
|
|
|
34
34
|
## Tools
|
|
35
35
|
|
|
36
|
-
The catherd MCP tools ship with this plugin.
|
|
36
|
+
The catherd MCP tools ship with this plugin. Discover them through the host's available capability mechanism: tool names and deferred loading vary by host. In Claude Code they appear as `mcp__plugin_catherd_catherd__<name>`; use `ToolSearch` there when deferred, and load `PushNotification` if available. Codex uses its own exposed tools and discovery facility; never invent a Claude `ToolSearch`, `Agent` or notification tool there.
|
|
37
|
+
|
|
38
|
+
Pass the actual project `repo` explicitly to profile, setup and catalog tools that accept it. The native Codex MCP server starts in the installed plugin root, so its cwd is not evidence of the project. `run_start(repo, ...)` establishes the run's repository.
|
|
37
39
|
|
|
38
40
|
| Tool | Use |
|
|
39
41
|
| ----------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
@@ -45,7 +47,7 @@ The catherd MCP tools ship with this plugin. They appear as `mcp__plugin_catherd
|
|
|
45
47
|
| `dispatch(run, role, name, brief, rung, thread?, lane?, next?)` | Starts one process role (Codex, claude-code or opencode) and returns at launch, in about a second, with `dispatched`. It routes a lane not routed yet, appends the role's reply contract to the brief, and its result arrives as a catherd message |
|
|
46
48
|
| `result(run, name)` | A role's latest reply, capped, its record and its `hints`; reading a finished record marks it read |
|
|
47
49
|
| `cancel(run, name)` | Stops a live role and returns its record, `cancelled`, and `hints` |
|
|
48
|
-
| `record_agent_run(run, name, role, rung, total_tokens, duration_ms?, cost_usd?, status?, lane?)` |
|
|
50
|
+
| `record_agent_run(run, name, role, rung, total_tokens, duration_ms?, cost_usd?, status?, lane?)` | Native Claude Agent results on Claude Code only. The budget counts them; `lane` counts their time toward that lane's kind; a verifier named `verifier-<M>` records FAIL with `status: "failed"` |
|
|
49
51
|
| `climb(run, lane, reason, evidence?, env?)` | The lane's next rung, with its `backend` and `agent`, or `top: true`. `env: true` when the environment, not the rung, caused it |
|
|
50
52
|
| `ask(run, question, state)` | Jev's `finding` or `same-defect` answer |
|
|
51
53
|
| `gate_check(run, item, command, paths, milestone?)`, `gate_pass(run, item, command, paths, evidence)` | The verifier's gate ledger: an item that passed on the same content is carried over, not run again; `milestone` scopes the digest's carried items |
|
|
@@ -63,7 +65,7 @@ The catherd MCP tools ship with this plugin. They appear as `mcp__plugin_catherd
|
|
|
63
65
|
|
|
64
66
|
- `E_ADMIT_OVERLAP`: the lane shares an owned path with a running lane. Dispatch it when that one returns.
|
|
65
67
|
- `E_ADMIT_DUPLICATE`: that role name is already running. It reports through a catherd message when it finishes; `peek(run, name)` shows it now, and `cancel` stops it.
|
|
66
|
-
- `E_ADMIT_RUNG`: the rung is not on that role's ladder, it is a `claude:` rung, or the profile turns the role off. Use the rung `route` returned;
|
|
68
|
+
- `E_ADMIT_RUNG`: the rung is not on that role's ladder, it is a `claude:` rung, or the profile turns the role off. Use the rung `route` returned; native `claude:` requires Claude Code; skip a role that is off. On Codex, explain the exact `claude-code:` model/effort equivalent or the reviewed host-default reset instead of converting the rung yourself.
|
|
67
69
|
- `E_RUN_BUDGET`: the run's budget is spent (a soft cap: roles already running finish). Pause, report and push.
|
|
68
70
|
- `E_BACKEND_MISSING`, `E_BACKEND_NOT_LOGGED_IN`, `E_BACKEND_TOO_OLD`, `E_BACKEND_CANNOT_RUN`: tell the user the `fix`, word for word, then pause.
|
|
69
71
|
- `E_LANE_INVALID`: a lane file's `Kind:` or `Difficulty:` is missing or not one the catalog knows. Fix the header (the `fix` lists the values), or have the architect fix it, then call again.
|
|
@@ -72,24 +74,26 @@ The catherd MCP tools ship with this plugin. They appear as `mcp__plugin_catherd
|
|
|
72
74
|
|
|
73
75
|
## Roles
|
|
74
76
|
|
|
75
|
-
| Role | How to run it
|
|
76
|
-
| ----------- |
|
|
77
|
-
| architect | `
|
|
78
|
-
| verifier | `
|
|
79
|
-
| worker | `dispatch(run, "worker", "worker-<lane>", brief, rung, lane: "<lane>")`
|
|
80
|
-
| reviewer | `dispatch(run, "reviewer", "reviewer-<m>", brief, rung)`
|
|
81
|
-
| ui-reviewer | `dispatch(run, "ui-reviewer", "ui-<m>", brief, rung)`
|
|
82
|
-
| artist | `dispatch(run, "artist", "artist-<n>", brief, rung)`
|
|
83
|
-
| writer | `dispatch(run, "writer", "writer-<m>", brief, rung)`
|
|
84
|
-
| researcher | `dispatch(run, "researcher", "researcher-<n>", brief, rung)`
|
|
85
|
-
|
|
86
|
-
- **Every rung comes from `route`,** never from you. A rung names its backend: `backend:model#effort`, like `codex:gpt-6-sol#high` or `claude:claude-opus-5-5#high`.
|
|
87
|
-
- **
|
|
77
|
+
| Role | How to run it | Job |
|
|
78
|
+
| ----------- | ----------------------------------------------------------------------- | ------------------------------------------------------- |
|
|
79
|
+
| architect | `route(run, role: "architect")`, then the backend rule below | Decisions, milestones, lane files. No code. |
|
|
80
|
+
| verifier | `route(run, role: "verifier")`, then the backend rule below | Independent PASS/FAIL of a milestone, by running it |
|
|
81
|
+
| worker | `dispatch(run, "worker", "worker-<lane>", brief, rung, lane: "<lane>")` | One lane: its code and its tests |
|
|
82
|
+
| reviewer | `dispatch(run, "reviewer", "reviewer-<m>", brief, rung)` | Review of a milestone's diff |
|
|
83
|
+
| ui-reviewer | `dispatch(run, "ui-reviewer", "ui-<m>", brief, rung)` | Screenshots of the changed screens with `agent-browser` |
|
|
84
|
+
| artist | `dispatch(run, "artist", "artist-<n>", brief, rung)` | Images a screen needs, with Codex's built-in image tool |
|
|
85
|
+
| writer | `dispatch(run, "writer", "writer-<m>", brief, rung)` | README, docs, changelog, MR body |
|
|
86
|
+
| researcher | `dispatch(run, "researcher", "researcher-<n>", brief, rung)` | The dossier, or one factual question about the code |
|
|
87
|
+
|
|
88
|
+
- **Every rung comes from `route`,** never from you, for every role including architect and verifier. A rung names its backend: `backend:model#effort`, like `codex:gpt-6.1-sol#high` or `claude:claude-opus-5-5#high`. Only `backend: "claude"` on a Claude Code host uses `Agent(subagent_type: <agent>)`, with the brief and run id as its prompt. Every process backend uses `dispatch` followed by `result`, on either host. `dispatch` refuses native Claude rungs; Codex never fabricates native agents or silently changes `claude:` to `claude-code:`.
|
|
89
|
+
- **Only omitted architect/verifier rungs follow the host:** Codex uses exactly `codex:gpt-6.1-sol#high` and `codex:gpt-6.1-sol#low`; Claude Code retains its native Claude defaults. Explicit ladders, model IDs, efforts and existing materialized profiles stay unchanged. A deliberate reset removes only those two roles' `rungs` and `defaultRung` through the reviewed CLI workflow in the setup skill.
|
|
90
|
+
- **Verify the exact `gpt-6.1-sol` model ID against native catalog discovery and validation.** If the catalog spells it differently, report the mismatch and resolve it explicitly with the owner; never silently normalize or substitute a model. Retain architect high and verifier low effort.
|
|
91
|
+
- **After every native Claude subagent returns on Claude Code,** call `record_agent_run(run, name, role, rung, total_tokens, duration_ms, lane)` with the numbers its Agent result reports (`lane` when it worked one). Claude runs cost the budget too, and catherd cannot see them otherwise. Process roles already have dispatch records; do not report them as native agents.
|
|
88
92
|
- **A role the profile disables** (`profile_get`; every role but the worker can be off) is skipped, and the report says so.
|
|
89
93
|
- **Access:** catherd sets it per role. Worker, artist and writer write in the repo, the temp dir and catherd's lock dir, and reach the network, loopback ports and a local Docker, so a worker runs its installs and tests itself; reviewer, researcher and architect read; verifier and UI reviewer get full access for Docker, a browser, gate logs and screenshots. `catherd doctor` says per backend what a worker can reach.
|
|
90
94
|
- **A read-only role on claude-code or opencode has no shell** (no `git diff`, no `ls`), so its brief must list the files to read.
|
|
91
95
|
- **Cheap rungs hide broken tools.** The lowest Track A rung stays silent about a broken tool about a third of the time, so every lane on it is checked by your fast check, not by its own word.
|
|
92
|
-
- **Claude agents:**
|
|
96
|
+
- **Native Claude agents, only on Claude Code:**
|
|
93
97
|
- catherd generates them from the profile, and Claude Code registers them at session start.
|
|
94
98
|
- Pass no `model` to those Agent calls. Never let `Plan`, `general-purpose` or `Explore` stand in.
|
|
95
99
|
- `Agent type … not found` means the profile changed after this session started: tell the user to open a new session.
|
|
@@ -154,14 +158,16 @@ Your context is re-read on every turn, and it is the run's most expensive token.
|
|
|
154
158
|
Call `dispatch` from your main thread only, never from a subagent: catherd messages the session that dispatched.
|
|
155
159
|
|
|
156
160
|
- **Dispatch every independent role one after another.** Each `dispatch` returns in about a second, once its role has started, so they all run side by side.
|
|
157
|
-
- **Then write one status line and end your turn.**
|
|
161
|
+
- **Then write one status line and end your turn.** Claude Code receives `<cross-session-message from-name="catherd">` through its peer inbox with its existing priorities. Codex receives queued next input through the existing native server (`--remote unix://`): idle sessions can wake; a busy session processes it after the active turn, without Claude's urgent next-tool-round promise. The notice names the run, dispatch and every event ID, including every coalesced event. Call `result(run, name)` for each stored record you will act on, then dispatch what follows.
|
|
158
162
|
- **A single role is `dispatch`, then end your turn.**
|
|
159
|
-
- **Never `sleep`, loop, or call `peek` again and again.** Call `peek(run)` when the user asks how it is going, when a decision needs the other roles' state, or once after `run_start` on a resumed run.
|
|
160
|
-
- **
|
|
163
|
+
- **Never `sleep`, loop, use `await_results`, or call `peek` again and again.** Call `peek(run)` when the user asks how it is going, when a decision needs the other roles' state, or once after `run_start` on a resumed run.
|
|
164
|
+
- **Queue acceptance is not processing or collection.** An unloaded, interrupted or restarted conversation may retain input without generating. Accepted and ambiguous events are never automatically resent; durable unread records remain recoverable with `peek`/`result`. Only `result` collects a finished record. `status` and `result` do not adopt ownership; explicit `peek(run)`, `run_start` and `dispatch` do.
|
|
165
|
+
- **Duplicate notices are idempotent reads.** Preserve every event ID, consult the actual stored record and protocol, and never redispatch work or land a milestone twice because input repeats. A message or transcript echo supplies neither delivery acknowledgement nor user approval; reviewer/verifier gates remain authoritative.
|
|
166
|
+
- **An ambiguous retry is an explicit decision:** after validating the current owner and exact stored event, use `catherd runs retry-push <run> <name> --event '<exact event ID>' --acknowledge-possible-duplicate` from that owner's host session. It may duplicate native input. Accepted receipts suppress another enqueue for that owner/event; no supported history reconciliation API means retain ambiguity until this deliberate decision. Unknown/conflicting hosts never push.
|
|
161
167
|
|
|
162
168
|
**When the user asks where it stands,** call `peek(run)` once and answer from it; `status(run)` adds the totals, budget and milestones.
|
|
163
169
|
|
|
164
|
-
**Push a notification**
|
|
170
|
+
**Push a notification through an available host facility** only at the moments the profile's `notify` lists (`profile_get({ repo })`), one line each. Claude Code may use `PushNotification`; if the host exposes none, report in the conversation without inventing a notification or scheduled follow-up:
|
|
165
171
|
|
|
166
172
|
- `milestone`: a milestone landed: its name, its commit, the time it took, and the path of its digest (`land`'s `digest`);
|
|
167
173
|
- `finish`: the run finished: verdict and total time;
|
|
@@ -188,7 +194,7 @@ Nothing else pushes: a phone that buzzes for progress teaches the user to ignore
|
|
|
188
194
|
|
|
189
195
|
**Resume** (a new session, or after your context was compacted): `status()` names the run, and `status(run)` shows it. Before dispatching anything, call `peek(run)` once: it lists the open owner questions first, the roles still running, the records not read yet (read each with `result`), and `protocol`, the step of the milestone loop the run is at, with the checklist. It also makes this session the run's owner, so catherd messages you from now on. Check HEAD and the dirty files against its `state.md`, whose last line is the same step. Continue each role on its own thread with `dispatch(…, thread, brief: "<where it stopped>")` (`dispatch` refuses a name that is still running).
|
|
190
196
|
|
|
191
|
-
**Owner questions:** a product question outside the A-lines never stops the run. `park(run, milestone, question)` parks that milestone (`land` refuses it until it is answered),
|
|
197
|
+
**Owner questions:** a product question outside the A-lines never stops the run. `park(run, milestone, question)` parks that milestone (`land` refuses it until it is answered), notify through the available host facility as above, and go on with the milestones and runs that do not depend on it. When the owner answers in this session, `answer(run, milestone, answer)`, then finish the milestone.
|
|
192
198
|
|
|
193
199
|
## The sequence
|
|
194
200
|
|
|
@@ -206,7 +212,7 @@ Nothing else pushes: a phone that buzzes for progress teaches the user to ignore
|
|
|
206
212
|
- the repo's rules (`CLAUDE.md`, `AGENTS.md`, conventions) that bind this work;
|
|
207
213
|
- risks: shared files, generated code, slow or flaky tests.
|
|
208
214
|
|
|
209
|
-
It may run to 200 lines; the 15-line cap does not apply to it. Its reply is `result(run, "researcher-dossier")`, at the record's `replyPath`. A Claude researcher writes it to `R/dossier.md` with `write_run_file` instead.
|
|
215
|
+
It may run to 200 lines; the 15-line cap does not apply to it. Its reply is `result(run, "researcher-dossier")`, at the record's `replyPath`. A native Claude researcher on Claude Code writes it to `R/dossier.md` with `write_run_file` instead.
|
|
210
216
|
|
|
211
217
|
3. **Architect,** once, with the A-lines, the run id and the dossier's path. It reads the dossier first, writes `plan.md` and every `lanes/Mx.Ly.md` itself with `write_run_file`, and replies with a short list of milestones and lanes. Each lane names its owned files and its **fast check**: its targeted tests plus the linter, and the type check when the repo has one, scoped to the lane's owned packages (seconds to a minute or two). Each milestone names its **full check** (the whole suite).
|
|
212
218
|
- A full check slower than about five minutes is a problem to solve, not to live with. The architect makes speeding it up (parallel tests, a shared fixture) an early lane.
|
|
@@ -230,22 +236,22 @@ Nothing else pushes: a phone that buzzes for progress teaches the user to ignore
|
|
|
230
236
|
7. **reviewer,** named `reviewer-<M>`, once, over the whole milestone diff on a frozen tree.
|
|
231
237
|
- **UI pass,** when the milestone touched a screen. List the changed files (`git diff --name-only <milestone base>`), map them to the screens that render them, and brief the UI reviewer on those screens only. You start the app first.
|
|
232
238
|
8. **One fix round.** Send each lane's findings, verbatim, to its own worker thread, at its rung. A BLOCKER climbs a rung instead, on a fresh thread. Dispatch every lane's fix, then end your turn. Then resume the same reviewer thread, and it re-checks only the BLOCKER and BUG lines.
|
|
233
|
-
- Before routing a finding that questions the plan, `ask(run, "finding", …)`. `design` goes to the architect
|
|
239
|
+
- Before routing a finding that questions the plan, `ask(run, "finding", …)`. `design` goes to the architect: `SendMessage` to the same native Claude agent on Claude Code, or `dispatch` with its recorded process `thread` for its own delta, followed by `result`. Its delta rewrites the lane files.
|
|
234
240
|
- A finding that comes back: `ask(run, "same-defect", …)`. `yes` gets one climb and one re-check of that line. Anything still open goes to the report, not into another round.
|
|
235
|
-
9. **verifier,** named `verifier-<M>`, with the run id, the milestone's A-lines and the **full check**, on a frozen tree
|
|
241
|
+
9. **verifier,** named `verifier-<M>`, with the run id, the milestone's A-lines and the **full check**, on a frozen tree: it owns the independent gate. Route it first. A native Claude verifier runs in the foreground on Claude Code; a Codex or other process verifier uses `dispatch`, end the turn, then `result`. A full check that starts while a role still edits proves nothing, and it has to run again. Never give it a worker's reply.
|
|
236
242
|
- It checks each gate item with `gate_check` first and skips an item that passed on the same content (carried over from its commit); it records each pass with `gate_pass`, runs independent items side by side within the lock's slots, and builds each commit's images once. It names git-ignored inputs (`.env`, generated files) in `paths` explicitly: `.` covers only HEAD and uncommitted not-ignored changes. It passes `gate_check` the milestone it verifies, so the digest lists only that milestone's carried items. `peek` and `status` show its current step.
|
|
237
|
-
-
|
|
238
|
-
- On FAIL, the owning worker fixes it, and you
|
|
243
|
+
- For a native Claude verifier only, call `record_agent_run(run, "verifier-<M>", "verifier", rung, …)`, with `status: "failed"` when its verdict is FAIL: only a PASS is recorded `ok`. A process verifier on any backend counts through its dispatch record only when its reply opens `VERDICT: PASS`; collect it with `result` before landing.
|
|
244
|
+
- On FAIL, the owning worker fixes it, and you ask the same verifier to re-check: native Claude `SendMessage`, or process `dispatch` with its own recorded thread followed by `result`.
|
|
239
245
|
- A second FAIL on the same line goes to the architect.
|
|
240
246
|
- A third one: pause, report and push.
|
|
241
247
|
10. **Land.** Commit the milestone path-scoped, then `land(run, milestone, what, commit, evidence, next, learned)`, passing `learned` when the milestone taught the next run something worth knowing (a slow suite, a flaky test, a pattern to copy); push if the profile's `notify` has `milestone`, with the digest's path, and move to the next milestone.
|
|
242
|
-
- `land` refuses (`E_LAND_GATE`) a milestone with no reviewer record (a `reviewer-<M>` dispatch record, or a `record_agent_run` row with role reviewer and that name, status `ok`) or no verifier verdict since its lanes started. A skip over an empty commit range is refused too: commit first. A milestone that changed only docs lands with `skip: "docs-only"`; one that changed no source file with `skip: "no-code"` and the
|
|
248
|
+
- `land` refuses (`E_LAND_GATE`) a milestone with no reviewer record (a `reviewer-<M>` dispatch record, or a native Claude `record_agent_run` row with role reviewer and that name, status `ok`) or no verifier verdict since its lanes started. A skip over an empty commit range is refused too: commit first. A milestone that changed only docs lands with `skip: "docs-only"`; one that changed no source file with `skip: "no-code"` and the required local gate evidence in `evidence`. Follow the repo's CI policy; a skill never authorizes triggering checks.
|
|
243
249
|
- Commit only while no role is writing. A pre-commit hook may stash unstaged files, and a role's edits vanish under it.
|
|
244
250
|
- The next milestone's lanes can start in the same turn as the `land`.
|
|
245
251
|
|
|
246
252
|
**Finish:** run the project's final gate if it has one.
|
|
247
253
|
|
|
248
|
-
- The verifier is the gate owner,
|
|
254
|
+
- The verifier is the gate owner, with `gate_check` and `gate_pass`. On Claude Code a native Claude verifier runs in the **foreground** (`run_in_background: false`); a background subagent dies with the session. A process verifier on either host uses `dispatch`/`result` and its durable record; finish only after its PASS.
|
|
249
255
|
- Beside it, in the background:
|
|
250
256
|
- any independent review (a spec or milestone review by a fresh verifier);
|
|
251
257
|
- the writer's MR body;
|
|
@@ -266,7 +272,7 @@ Roles never commit. You commit, following the repo's rules.
|
|
|
266
272
|
|
|
267
273
|
## Brief for a role
|
|
268
274
|
|
|
269
|
-
The brief is the `brief` text you pass to `dispatch` (catherd writes it to the dispatch's own `brief.md` and hands it to the CLI on stdin), or the prompt of a Claude role's Agent call, with the run id. It has these parts, in order:
|
|
275
|
+
The brief is the `brief` text you pass to `dispatch` (catherd writes it to the dispatch's own `brief.md` and hands it to the CLI on stdin), or the prompt of a native Claude role's Agent call on Claude Code, with the run id. It has these parts, in order:
|
|
270
276
|
|
|
271
277
|
1. The role and the goal, in one line.
|
|
272
278
|
2. The A-lines this run must meet.
|
|
@@ -274,7 +280,7 @@ The brief is the `brief` text you pass to `dispatch` (catherd writes it to the d
|
|
|
274
280
|
4. For a worker:
|
|
275
281
|
- "Read `<R>/lanes/Mx.Ly.md`": decisions, signatures, data shapes;
|
|
276
282
|
- its fast check (targeted tests, lint and type check), to run until it passes;
|
|
277
|
-
- "Run the full suite only if this brief says so", and "Wrap any full build or full test suite in `bunx catherd-cli@1.
|
|
283
|
+
- "Run the full suite only if this brief says so", and "Wrap any full build or full test suite in `bunx catherd-cli@1.4.0 lock -- <command>`": other lanes share the machine.
|
|
278
284
|
5. For a reviewer: the A-lines and the changed files, with new files read in full. It reports every finding as `BLOCKER|BUG|NIT file:line — problem — fix`, covering:
|
|
279
285
|
- unmet A-lines and edge cases;
|
|
280
286
|
- code or abstractions nobody needs;
|
|
@@ -318,7 +324,7 @@ The brief is the `brief` text you pass to `dispatch` (catherd writes it to the d
|
|
|
318
324
|
| ----------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
319
325
|
| A lane waits on another lane that shares none of its files | Dispatch it now, beside the others |
|
|
320
326
|
| A role dispatched, then waited on, before the next independent one is dispatched | Dispatch every independent role first, then end your turn |
|
|
321
|
-
| `sleep`, a loop, or repeated
|
|
327
|
+
| `sleep`, `await_results`, a loop, or repeated `peek` to see whether a role is done | End your turn; use the host's completion input and durable `result` recovery |
|
|
322
328
|
| A worker or fix loop runs the full suite to check one change | Its fast check. The full check is the verifier's, once per milestone |
|
|
323
329
|
| A reviewer or verifier runs after each lane | Once per milestone, over the whole milestone |
|
|
324
330
|
| A third review round | One fix round, one climb for a returning defect, one re-check. The rest goes to the report |
|
|
@@ -333,7 +339,7 @@ The brief is the `brief` text you pass to `dispatch` (catherd writes it to the d
|
|
|
333
339
|
| A dossier, or an architect designing afresh, with a plan in hand | No dossier. Brief the architect to translate the plan, and to design only what it leaves undecided |
|
|
334
340
|
| A dossier or an architect for a polish or fix run | Write the lane files from the A-lines yourself |
|
|
335
341
|
| A lane file without an `Owns:` line | Add it: `dispatch` refuses the lane without one |
|
|
336
|
-
| A Claude subagent returned and you moved on
|
|
342
|
+
| A native Claude subagent on Claude Code returned and you moved on | `record_agent_run` with its `total_tokens` and `duration_ms` first |
|
|
337
343
|
| A rung written as `model#effort` | `backend:model#effort`, exactly as `route` returned it |
|
|
338
344
|
| `dispatch` retried after an `E_*` error without doing what its `fix` says | Do the `fix`, or pause and tell the user |
|
|
339
345
|
| A `cannot-start` preflight lane dispatched anyway | Fix its fast check first, and run `preflight` again |
|
|
@@ -342,7 +348,7 @@ The brief is the `brief` text you pass to `dispatch` (catherd writes it to the d
|
|
|
342
348
|
| A reply from the lowest Track A rung trusted without your fast check | Run it. Cheap rungs hide broken tools |
|
|
343
349
|
| A reviewer, or a `logic`/`hard` lane, on a rung you chose yourself | The rung `route` returned |
|
|
344
350
|
| Exit 0 with the owned files unchanged, treated as done | A refusal: climb with reason `unchanged` |
|
|
345
|
-
|
|
|
351
|
+
| A native Claude gate verifier dispatched in the background | Foreground on Claude Code; process verifiers use `dispatch`/`result` on either host |
|
|
346
352
|
| A full check started while a worker still edits | Wait for a frozen tree. That run proves nothing |
|
|
347
353
|
| Lanes dispatched before `preflight` ran | Run `preflight(run)` first; a lane whose check cannot even start wastes a dispatch |
|
|
348
354
|
| An architect planning without reading what past runs learned | `read_knowledge(repo)` first, from the dossier brief |
|
|
@@ -350,12 +356,12 @@ The brief is the `brief` text you pass to `dispatch` (catherd writes it to the d
|
|
|
350
356
|
| You update catherd, this plugin or the profile while a run is in flight | After the run. A role mid-flight must see one version |
|
|
351
357
|
| You stop to ask the user something mid-run | Decide within the A-lines and note it for the report. A product question outside them parks its milestone (`park`), with a push; the rest goes on |
|
|
352
358
|
| A brief that spells out the reply shape and the STATUS line | `dispatch` appends the reply contract itself |
|
|
353
|
-
| A milestone landed without its reviewer and verifier | `reviewer-<M>`, then the verifier
|
|
359
|
+
| A milestone landed without its reviewer and verifier | `reviewer-<M>`, then the routed verifier's independent PASS, then `land` |
|
|
354
360
|
| A climb for a finding that questions the plan or the lane's owned files | `ask` finding, then the architect. `climb` refuses it (`E_CLIMB_DESIGN`) |
|
|
355
361
|
| A gate item run again on content that already passed it | The verifier's `gate_check` carries it over |
|
|
356
362
|
| A push for progress that is not a landed milestone, the finish or a block | No push. `status(run)` answers when the user asks |
|
|
357
363
|
| Your own decision changes behavior that already exists and no A-line asked for it (e.g. re-numbering `list` to match a new command) | Pick the option that keeps existing behavior, and fit the new code to it |
|
|
358
|
-
| `Agent(subagent_type: "Plan", model: "opus")` for the architect |
|
|
364
|
+
| `Agent(subagent_type: "Plan", model: "opus")` for the architect | Route first: native Claude's returned `agent` with no model on Claude Code, otherwise `dispatch`/`result` |
|
|
359
365
|
| `dispatch` called from a subagent | The main thread: catherd messages the session that dispatched |
|
|
360
366
|
| `codex exec` or `opencode run` called by hand | Always `dispatch`: it records the run, keeps `state.md` true and guards the lanes |
|
|
361
367
|
| You isolate a role's harness yourself, or tell a role to ignore the user's config | Never. Only the profile's `harness.<name>.isolated`, which the user sets |
|