@codemeall/agent-fleet 0.1.0-preview.1
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/.claude-plugin/plugin.json +14 -0
- package/CHANGELOG.md +23 -0
- package/LICENSE +21 -0
- package/README.md +229 -0
- package/bin/build.js +5 -0
- package/bin/fleet.js +27 -0
- package/bin/setup.js +138 -0
- package/config.example.toml +21 -0
- package/dist/codex/agent-fleet/.codex-plugin/plugin.json +23 -0
- package/dist/codex/agent-fleet/skills/fleet/LICENSE +21 -0
- package/dist/codex/agent-fleet/skills/fleet/SKILL.md +82 -0
- package/dist/codex/agent-fleet/skills/fleet/agents/openai.yaml +6 -0
- package/dist/codex/agent-fleet/skills/fleet/bin/fleet +1028 -0
- package/dist/codex/agent-fleet/skills/fleet/providers.toml +106 -0
- package/dist/codex/agent-fleet/skills/fleet/references/harnesses.md +24 -0
- package/dist/codex/agent-fleet/skills/fleet/references/providers.md +31 -0
- package/dist/codex/agent-fleet/skills/fleet/references/routing.md +40 -0
- package/dist/codex/agent-fleet/skills/fleet/templates/preamble.md +16 -0
- package/dist/codex/agent-fleet/skills/fleet/templates/report.md +26 -0
- package/dist/codex/agent-fleet/skills/fleet/templates/review-prompt.md +14 -0
- package/dist/codex/agent-fleet/skills/fleet/templates/ticket-prompt.md +18 -0
- package/examples/README.md +58 -0
- package/examples/plan.json +12 -0
- package/examples/rules.md +25 -0
- package/examples/tickets/glossary.md +12 -0
- package/examples/tickets/guide.md +13 -0
- package/examples/tickets/overview.md +13 -0
- package/install.sh +9 -0
- package/package.json +63 -0
- package/plugin-manifests/codex.json +23 -0
- package/skill/LICENSE +21 -0
- package/skill/SKILL.md +83 -0
- package/skill/agents/openai.yaml +6 -0
- package/skill/bin/fleet +1028 -0
- package/skill/providers.toml +106 -0
- package/skill/references/harnesses.md +24 -0
- package/skill/references/providers.md +31 -0
- package/skill/references/routing.md +40 -0
- package/skill/templates/preamble.md +16 -0
- package/skill/templates/report.md +26 -0
- package/skill/templates/review-prompt.md +14 -0
- package/skill/templates/ticket-prompt.md +18 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agent-fleet",
|
|
3
|
+
"version": "0.1.0-preview.1",
|
|
4
|
+
"description": "Lead coding-agent CLIs in cmux from a portable Fleet skill.",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "codemeall"
|
|
7
|
+
},
|
|
8
|
+
"homepage": "https://github.com/codemeall/agent-fleet",
|
|
9
|
+
"repository": "https://github.com/codemeall/agent-fleet",
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"skills": [
|
|
12
|
+
"./skill/"
|
|
13
|
+
]
|
|
14
|
+
}
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0-preview.1
|
|
4
|
+
|
|
5
|
+
Initial distributable preview, under the MIT license.
|
|
6
|
+
|
|
7
|
+
- Published to npm as `@codemeall/agent-fleet` under the `preview` tag: `npx @codemeall/agent-fleet@preview setup`.
|
|
8
|
+
- Install with the skills CLI: `npx skills add codemeall/agent-fleet`.
|
|
9
|
+
- Install from GitHub without npm: `npx github:codemeall/agent-fleet setup`.
|
|
10
|
+
- Add a Claude Code plugin marketplace manifest (`/plugin marketplace add codemeall/agent-fleet`).
|
|
11
|
+
- Restructure the README around installation methods.
|
|
12
|
+
- Persist ticket dependencies, exact ownership, model/effort assignments and decisions; resume existing runs.
|
|
13
|
+
- Track worker exit receipts independently from reports. Failed stops retain capacity; reviewers can use a released writer slot even at capacity one.
|
|
14
|
+
- Gate acceptance on lead evidence and required cross-family review of the current scoped diff.
|
|
15
|
+
- Compare full Git index entries, quote model arguments, validate IDs and paths, and serialize mutations within a checkout.
|
|
16
|
+
- Provide dedicated reviewer prompts and current Matt Pocock skill integration guidance.
|
|
17
|
+
- Install durable skill copies for Claude Code, Codex and Cursor, preserving modified or unrelated installations.
|
|
18
|
+
- Package the runtime for npm, a Claude plugin at the source root, and a generated Codex plugin bundle. Include MIT notices in standalone copies.
|
|
19
|
+
- Add CI and 43 tests, including a real child-process exit receipt and installation from an npm tarball.
|
|
20
|
+
|
|
21
|
+
Validated locally: automated tests, JavaScript syntax, Claude plugin manifest, generated Codex plugin and skill, and package installation. Live authenticated provider runs and marketplace installation remain unverified. The npm package has not been published by this change.
|
|
22
|
+
|
|
23
|
+
Existing prototype run records are not automatically migrated: inspect and stop their workers before starting a new run. New run records use schema version 2.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 codemeall
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# Agent Fleet
|
|
2
|
+
|
|
3
|
+
Run a fleet of coding-agent CLIs (Claude Code, Codex, Cursor) in visible [cmux](https://github.com/manaflow-ai/cmux) tabs, led by the agent you are already talking to.
|
|
4
|
+
|
|
5
|
+
The lead turns approved tickets into a saved execution plan, picks a worker model and effort for each ticket, watches progress, and verifies every result before dependents start. Workers share one Git checkout with explicit file ownership. **You keep control of commits and publishing.**
|
|
6
|
+
|
|
7
|
+
> **Preview `0.1.0-preview.1`.** Bundled adapters exist for Claude Code, Codex and Cursor. Live compatibility depends on your installed CLI versions, account models and local permissions. MIT licensed.
|
|
8
|
+
|
|
9
|
+
- [Quick start](#quick-start)
|
|
10
|
+
- [Installation](#installation)
|
|
11
|
+
- [Usage](#usage)
|
|
12
|
+
- [State, continuation and safety](#state-continuation-and-safety)
|
|
13
|
+
- [Compatibility and adapters](#compatibility-and-adapters)
|
|
14
|
+
- [Development](#development)
|
|
15
|
+
|
|
16
|
+
## Quick start
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
# 1. Install the skill globally with the skills CLI
|
|
20
|
+
npx skills add codemeall/agent-fleet -g -a claude-code -a codex -a cursor
|
|
21
|
+
|
|
22
|
+
# 2. Check cmux, Python and worker CLIs
|
|
23
|
+
~/.claude/skills/fleet/bin/fleet doctor
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Restart your agent host, open it inside a cmux workspace, and ask:
|
|
27
|
+
|
|
28
|
+
> Use `/fleet` with auto routing for the approved tickets in `.scratch/my-feature/issues`.
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
### Requirements
|
|
33
|
+
|
|
34
|
+
- macOS (cmux is a macOS terminal) with **Python 3.11+**, **Git** and **[cmux](https://github.com/manaflow-ai/cmux)** running with a reachable socket
|
|
35
|
+
- At least one installed, authenticated worker CLI: `claude`, `codex` or `cursor-agent`
|
|
36
|
+
- **Node.js 18+** for the installer (not needed at runtime)
|
|
37
|
+
|
|
38
|
+
The lead host must be allowed to use the local shell, the repository and cmux. Installing the skill does not grant those permissions; see [host setup](skill/references/harnesses.md).
|
|
39
|
+
|
|
40
|
+
### Pick an install method
|
|
41
|
+
|
|
42
|
+
| Method | Best for | Command |
|
|
43
|
+
| --- | --- | --- |
|
|
44
|
+
| **skills CLI** (recommended) | Claude Code, Codex, Cursor and other agents | `npx skills add codemeall/agent-fleet` |
|
|
45
|
+
| **Fleet installer (npm)** | Version-tracked installs, `fleet` on PATH | `npx @codemeall/agent-fleet@preview setup --harness all` |
|
|
46
|
+
| **Claude Code plugin** | Claude Code only, managed updates | `/plugin marketplace add codemeall/agent-fleet` |
|
|
47
|
+
| **Git clone** | Contributors, pinned checkouts | `./install.sh --harness all` |
|
|
48
|
+
|
|
49
|
+
Pick one method per host. Installing the same skill twice (for example, with the skills CLI and the Fleet installer) leaves duplicate copies; the Fleet installer refuses to overwrite a directory it didn't create.
|
|
50
|
+
|
|
51
|
+
#### Option 1: skills CLI (recommended)
|
|
52
|
+
|
|
53
|
+
The [skills CLI](https://github.com/vercel-labs/skills) installs the `fleet` skill, including its bundled `bin/fleet` runtime, into your agents' skill directories:
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
npx skills add codemeall/agent-fleet # interactive: pick agents and scope
|
|
57
|
+
npx skills add codemeall/agent-fleet -g -a claude-code -a codex -a cursor # user-level, no prompts
|
|
58
|
+
npx skills add codemeall/agent-fleet -a claude-code -y # current project only
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Without `-g`, the skill goes into the current project (`.agents/skills/fleet`, symlinked into `.claude/skills/fleet` for Claude Code). With `-g`, it goes into your user-level skill directories. Pass `-a` once per agent. Run `npx skills add codemeall/agent-fleet --list` to preview what will be installed.
|
|
62
|
+
|
|
63
|
+
To update, run `npx skills update fleet`. To remove, run `npx skills remove fleet`.
|
|
64
|
+
|
|
65
|
+
#### Option 2: Fleet installer from npm
|
|
66
|
+
|
|
67
|
+
The package's own installer copies the skill to each host and records the installed version, so later runs can upgrade it safely:
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
npx @codemeall/agent-fleet@preview setup --harness all # one-off install
|
|
71
|
+
npm install -g @codemeall/agent-fleet@preview # also adds `fleet` to PATH
|
|
72
|
+
fleet setup --harness all
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The package is published under the `preview` tag during the preview period. To install straight from GitHub instead of npm, use `npx github:codemeall/agent-fleet setup --harness all`.
|
|
76
|
+
|
|
77
|
+
Use `--harness claude`, `codex`, `cursor` or `all`. The skill is copied to:
|
|
78
|
+
|
|
79
|
+
| Host | User install (default) | Project install (`--scope project`) |
|
|
80
|
+
| --- | --- | --- |
|
|
81
|
+
| Claude Code | `~/.claude/skills/fleet` | `<repo>/.claude/skills/fleet` |
|
|
82
|
+
| Codex | `~/.agents/skills/fleet` | `<repo>/.agents/skills/fleet` |
|
|
83
|
+
| Cursor | `~/.cursor/skills/fleet` | `<repo>/.cursor/skills/fleet` |
|
|
84
|
+
|
|
85
|
+
For a single repository:
|
|
86
|
+
|
|
87
|
+
```sh
|
|
88
|
+
npx @codemeall/agent-fleet@preview setup --harness codex --scope project --root /absolute/path/to/repo
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
To update, run `setup` again with the newest version (for example, `npx @codemeall/agent-fleet@preview setup --harness all`, or `npm update -g @codemeall/agent-fleet` for a global install). Each installed copy records its version in `.fleet-install.json`. Setup replaces only copies it installed itself. If you edited an installed copy, or another skill already uses that directory, setup stops and reports it without overwriting anything.
|
|
92
|
+
|
|
93
|
+
#### Option 3: Claude Code plugin marketplace
|
|
94
|
+
|
|
95
|
+
This repository is also a Claude Code plugin marketplace. In Claude Code:
|
|
96
|
+
|
|
97
|
+
```text
|
|
98
|
+
/plugin marketplace add codemeall/agent-fleet
|
|
99
|
+
/plugin install agent-fleet@agent-fleet
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Or from a terminal:
|
|
103
|
+
|
|
104
|
+
```sh
|
|
105
|
+
claude plugin marketplace add codemeall/agent-fleet
|
|
106
|
+
claude plugin install agent-fleet@agent-fleet
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Plugin skills are namespaced, so you invoke this one as `/agent-fleet:fleet`. To update, run `claude plugin marketplace update agent-fleet`, then `claude plugin update agent-fleet@agent-fleet`. The plugin does not add `fleet` to your PATH. The skill finds its bundled runtime itself, and you can [add a PATH command](#put-fleet-on-your-path-optional) if you want one.
|
|
110
|
+
|
|
111
|
+
#### Option 4: Git clone
|
|
112
|
+
|
|
113
|
+
```sh
|
|
114
|
+
git clone https://github.com/codemeall/agent-fleet.git
|
|
115
|
+
cd agent-fleet
|
|
116
|
+
./install.sh --harness all # same options as `setup`
|
|
117
|
+
./skill/bin/fleet doctor
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Claude Code can also load the checkout directly as a plugin: `claude --plugin-dir /absolute/path/to/agent-fleet`.
|
|
121
|
+
|
|
122
|
+
### Put `fleet` on your PATH (optional)
|
|
123
|
+
|
|
124
|
+
The skill never needs `fleet` on PATH; it calls its own copied runtime. For convenience in your shell:
|
|
125
|
+
|
|
126
|
+
```sh
|
|
127
|
+
mkdir -p ~/.local/bin
|
|
128
|
+
ln -s ~/.claude/skills/fleet/bin/fleet ~/.local/bin/fleet # or ~/.agents/… / ~/.cursor/…
|
|
129
|
+
fleet doctor
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Verify
|
|
133
|
+
|
|
134
|
+
```sh
|
|
135
|
+
fleet doctor
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`doctor` checks cmux connectivity, worker executables and login signals. It cannot guarantee model access or a successful worker session. Launch one small ticket first (the [documentation-only example](examples/README.md) is a safe choice).
|
|
139
|
+
|
|
140
|
+
### Configure
|
|
141
|
+
|
|
142
|
+
Personal overrides live in `~/.config/agent-fleet/config.toml`; start from [config.example.toml](config.example.toml). No cmux workspace is pinned by default. Start the lead in the intended workspace, or pass `workspace=<ref>` explicitly.
|
|
143
|
+
|
|
144
|
+
### Uninstall
|
|
145
|
+
|
|
146
|
+
```sh
|
|
147
|
+
npx skills remove fleet # if installed with the skills CLI (add -g for global)
|
|
148
|
+
npx @codemeall/agent-fleet@preview uninstall --harness all # same --scope/--root as setup
|
|
149
|
+
claude plugin uninstall agent-fleet@agent-fleet # if installed as a Claude plugin
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Uninstall removes only the Fleet skill it installed. It keeps modified copies, and it never touches `.fleet/` run history in your repositories.
|
|
153
|
+
|
|
154
|
+
## Usage
|
|
155
|
+
|
|
156
|
+
| Host | Invoke |
|
|
157
|
+
| --- | --- |
|
|
158
|
+
| Claude Code | `/fleet …` (plugin install: `/agent-fleet:fleet …`) |
|
|
159
|
+
| Codex CLI / desktop | `$fleet …` or pick it in the skill menu |
|
|
160
|
+
| Cursor | `/fleet …` |
|
|
161
|
+
|
|
162
|
+
```text
|
|
163
|
+
/fleet [auto | single:<provider> | agents=<provider>[:<model>],...]
|
|
164
|
+
[workspace=<ref>] [review=off|cross-heavy|cross-all]
|
|
165
|
+
-- <local tickets directory or task list>
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
The lead interprets these options and saves them with CLI commands; there's no autonomous scheduler behind them. `single:codex` restricts the pool to one adapter. Required review still needs a *different* model family, so either set `review=off` explicitly or widen the pool. Fleet does not fetch issue URLs. Export tracker tickets to local Markdown first, keeping their IDs, blockers, acceptance criteria and source links.
|
|
169
|
+
|
|
170
|
+
Example request to the lead:
|
|
171
|
+
|
|
172
|
+
> Use Fleet with auto routing and cross-heavy review for the approved tickets in `.scratch/settings/issues`. Carry the agreed spec and testing decisions into each worker prompt. Resume the `settings` run if it already exists.
|
|
173
|
+
|
|
174
|
+
### Daily workflow
|
|
175
|
+
|
|
176
|
+
Fleet starts from approved tickets. It works with plain Markdown tickets, or as the execution step after [mattpocock/skills](https://github.com/mattpocock/skills):
|
|
177
|
+
|
|
178
|
+
1. Brainstorm and discuss the feature.
|
|
179
|
+
2. Run upstream `grill-with-docs` (or `grill-me`), then `to-spec`, then `to-tickets`.
|
|
180
|
+
3. Ask Fleet to plan and implement the resulting local tickets.
|
|
181
|
+
4. The lead verifies each ticket, gets any configured cross-family review, and reports back for your review and commit.
|
|
182
|
+
|
|
183
|
+
Point the lead at the real spec, glossary (`GLOSSARY.md`, optionally `GLOSSARY-MAP.md`; older repos may use `CONTEXT.md`), ADRs and tickets. Upstream `/implement` includes a commit step, so Fleet workers follow Fleet's no-commit contract instead. Workers don't need the upstream skills installed. These conventions were checked on 2026-09-30, and upstream may change them.
|
|
184
|
+
|
|
185
|
+
More: [safe first run](examples/README.md) · [agent workflow](skill/SKILL.md) · [routing](skill/references/routing.md) · [host setup](skill/references/harnesses.md) · [providers](skill/references/providers.md)
|
|
186
|
+
|
|
187
|
+
## State, continuation and safety
|
|
188
|
+
|
|
189
|
+
- **Saved plan.** `fleet plan` saves every ticket, dependency, exact file scope, model assignment and decision. Run records, prompts, reports and exit receipts live in `.fleet/runs/<run>/`, which Git ignores. Repository-specific checks belong in `.fleet/rules.md`.
|
|
190
|
+
- **Resume.** A fresh lead runs `fleet resume <run>` and reconciles reports and processes before continuing. The plan is frozen after the first launch. Record later decisions in run notes, and use a follow-up run for changed scope.
|
|
191
|
+
- **Capacity.** A report does not free a slot; the worker must actually exit, and a failed stop keeps its slot. Stop an implementation worker before capturing its review diff, then stop and verify the reviewer before accepting the work. This works even with a single slot. Dependents stay blocked until `fleet verify` accepts the ticket.
|
|
192
|
+
- **Isolation is by instruction, not by the OS.** All workers share one checkout. Exact file scope and read-only review are prompt rules plus lead checks. Use one active run per checkout, keep sensitive or high-conflict work out of concurrent waves, inspect scoped diffs, and run checks on the combined tree. The Git check compares the captured HEAD and index; it can't prove that no Git operation happened in between.
|
|
193
|
+
|
|
194
|
+
## Compatibility and adapters
|
|
195
|
+
|
|
196
|
+
| Lead or worker | Preview scope |
|
|
197
|
+
| --- | --- |
|
|
198
|
+
| Local Claude Code, Codex CLI, Cursor CLI | Bundled worker adapters; the lead needs shell, repository and cmux access |
|
|
199
|
+
| Codex desktop / ChatGPT with local execution | Usable when the same capabilities and permissions are available |
|
|
200
|
+
| Cloud-only or remote session | Needs an explicit connection to the machine running cmux |
|
|
201
|
+
| Other providers or accounts | Configure and test an adapter yourself |
|
|
202
|
+
|
|
203
|
+
The lead host, worker CLI, provider account and model family are independent choices. For example, a Claude lead can run Codex workers, and Cursor can serve several model families. The bundled model IDs are examples that depend on your account, so check which IDs and effort levels you can actually use before assigning work.
|
|
204
|
+
|
|
205
|
+
[providers.toml](skill/providers.toml) holds launch templates, login checks, shutdown keys and tiers. Optional `claude-co`, Antigravity and placeholder adapters ship disabled. Before relying on a new adapter, test authentication, model selection, the full launch → report → confirmed exit → verify loop, crash recovery, and a full-capacity review cycle. Passing `doctor` alone doesn't certify an adapter. See [provider notes](skill/references/providers.md).
|
|
206
|
+
|
|
207
|
+
## Development
|
|
208
|
+
|
|
209
|
+
```sh
|
|
210
|
+
python3 -m unittest discover tests -v
|
|
211
|
+
npm run check
|
|
212
|
+
npm pack --dry-run
|
|
213
|
+
claude plugin validate .claude-plugin/marketplace.json
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
`skill/` is the single source of truth: agent instructions, runtime, templates and adapter defaults. Everything else is packaging around it.
|
|
217
|
+
|
|
218
|
+
| Artifact | Source |
|
|
219
|
+
| --- | --- |
|
|
220
|
+
| Portable skill (`setup`, `install.sh`) | `skill/` copied to each host's skills directory |
|
|
221
|
+
| Claude plugin + marketplace | `.claude-plugin/plugin.json`, `.claude-plugin/marketplace.json` (repo root) |
|
|
222
|
+
| Codex plugin | `npm run build` → `dist/codex/agent-fleet/` from `skill/` + `plugin-manifests/codex.json` |
|
|
223
|
+
| npm package | `npm pack` (runs the build and includes the Codex bundle) |
|
|
224
|
+
|
|
225
|
+
The Codex bundle expresses explicit invocation through `agents/openai.yaml`. Add it through a configured Codex plugin marketplace, because `codex plugin add` takes a marketplace selector rather than a local path. Codex marketplace discovery still needs live validation, so the portable skill install is the common path for all three hosts.
|
|
226
|
+
|
|
227
|
+
**Releasing:** bump the version in `package.json`, `.claude-plugin/plugin.json`, `.claude-plugin/marketplace.json` and `plugin-manifests/codex.json`. Run the checks above and `npm pack`, then inspect the tarball. Once npm publishing is set up, publish with `npm publish --access public --tag preview`. Setup, build and tests never publish anything.
|
|
228
|
+
|
|
229
|
+
See [CHANGELOG.md](CHANGELOG.md) for changes. The review that motivated this preview is kept in [REVIEW.md](https://github.com/codemeall/agent-fleet/blob/main/REVIEW.md) as a historical assessment.
|
package/bin/build.js
ADDED
package/bin/fleet.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
const path = require('node:path');
|
|
4
|
+
const { spawnSync } = require('node:child_process');
|
|
5
|
+
const args = process.argv.slice(2);
|
|
6
|
+
if (['setup', 'uninstall'].includes(args[0])) {
|
|
7
|
+
try { require('./setup.js').run(args[0], args.slice(1)); }
|
|
8
|
+
catch (error) { console.error(`fleet: ${error.message}`); process.exitCode = 1; }
|
|
9
|
+
} else if (args[0] === '--version') {
|
|
10
|
+
console.log(require('../package.json').version);
|
|
11
|
+
} else {
|
|
12
|
+
if (args.length === 0 || args[0] === '--help' || args[0] === '-h') {
|
|
13
|
+
console.log('Skill installation: fleet setup --harness claude|codex|cursor|all [--scope user|project] [--root /absolute/base]');
|
|
14
|
+
console.log('Skill removal: fleet uninstall (same options; preserves modified installations)\n');
|
|
15
|
+
}
|
|
16
|
+
const python = process.env.FLEET_PYTHON || 'python3';
|
|
17
|
+
const probe = spawnSync(python, ['-c', 'import sys; sys.exit(0 if sys.version_info >= (3, 11) else 1)'], { encoding: 'utf8' });
|
|
18
|
+
if (probe.error || probe.status !== 0) {
|
|
19
|
+
console.error('fleet: Python 3.11+ is required. Install it or set FLEET_PYTHON to its executable path.');
|
|
20
|
+
process.exitCode = 1;
|
|
21
|
+
} else {
|
|
22
|
+
const result = spawnSync(python, [path.join(__dirname, '..', 'skill', 'bin', 'fleet'), ...args], { stdio: 'inherit' });
|
|
23
|
+
if (result.error) console.error(`fleet: ${result.error.message}`);
|
|
24
|
+
if (result.signal) process.kill(process.pid, result.signal);
|
|
25
|
+
else process.exitCode = result.status ?? 1;
|
|
26
|
+
}
|
|
27
|
+
}
|
package/bin/setup.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const fs = require('node:fs');
|
|
3
|
+
const path = require('node:path');
|
|
4
|
+
const os = require('node:os');
|
|
5
|
+
const crypto = require('node:crypto');
|
|
6
|
+
const OWNER = '@codemeall/agent-fleet';
|
|
7
|
+
const MARKER = '.fleet-install.json';
|
|
8
|
+
const HARNESSES = { claude: '.claude', codex: '.agents', cursor: '.cursor' };
|
|
9
|
+
const source = path.join(__dirname, '..', 'skill');
|
|
10
|
+
|
|
11
|
+
function exists(file) {
|
|
12
|
+
try { fs.lstatSync(file); return true; } catch (e) { if (e.code === 'ENOENT') return false; throw e; }
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Record the complete tree, including empty directories, so added user files are preserved.
|
|
16
|
+
function inventory(root, forSource = false) {
|
|
17
|
+
const entries = {};
|
|
18
|
+
function walk(dir, prefix = '') {
|
|
19
|
+
for (const name of fs.readdirSync(dir).sort()) {
|
|
20
|
+
if (!prefix && name === MARKER) continue;
|
|
21
|
+
if (forSource && (name === '__pycache__' || name === '.DS_Store' || name.endsWith('.pyc'))) continue;
|
|
22
|
+
const rel = prefix ? `${prefix}/${name}` : name;
|
|
23
|
+
const file = path.join(dir, name);
|
|
24
|
+
const stat = fs.lstatSync(file);
|
|
25
|
+
if (stat.isSymbolicLink()) throw new Error(`Refusing symbolic link: ${file}`);
|
|
26
|
+
if (stat.isDirectory()) { entries[rel] = 'directory'; walk(file, rel); }
|
|
27
|
+
else if (stat.isFile()) entries[rel] = crypto.createHash('sha256').update(fs.readFileSync(file)).digest('hex') + `:${stat.mode & 0o777}`;
|
|
28
|
+
else throw new Error(`Unsupported file: ${file}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
walk(root);
|
|
32
|
+
return entries;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function assertOwned(target) {
|
|
36
|
+
const stat = fs.lstatSync(target);
|
|
37
|
+
if (!stat.isDirectory() || stat.isSymbolicLink()) throw new Error(`Refusing unowned installation: ${target}`);
|
|
38
|
+
const marker = path.join(target, MARKER);
|
|
39
|
+
if (!exists(marker) || !fs.lstatSync(marker).isFile() || fs.lstatSync(marker).isSymbolicLink()) throw new Error(`Refusing unowned installation: ${target}`);
|
|
40
|
+
let record;
|
|
41
|
+
try { record = JSON.parse(fs.readFileSync(marker, 'utf8')); } catch { throw new Error(`Invalid ownership record: ${marker}`); }
|
|
42
|
+
const actual = inventory(target);
|
|
43
|
+
if (record.owner !== OWNER || record.format !== 1 || !record.files ||
|
|
44
|
+
Object.keys(actual).length !== Object.keys(record.files).length ||
|
|
45
|
+
Object.entries(actual).some(([name, digest]) => record.files[name] !== digest)) {
|
|
46
|
+
throw new Error(`Preserving modified or unowned installation: ${target}. Back it up and move it aside before retrying.`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function assertParents(base, target) {
|
|
51
|
+
let current = path.dirname(target);
|
|
52
|
+
while (current !== base) {
|
|
53
|
+
if (exists(current) && (fs.lstatSync(current).isSymbolicLink() || !fs.lstatSync(current).isDirectory())) {
|
|
54
|
+
throw new Error(`Refusing non-directory or symbolic-link parent: ${current}`);
|
|
55
|
+
}
|
|
56
|
+
const parent = path.dirname(current);
|
|
57
|
+
if (parent === current) throw new Error(`Target escapes installation root: ${target}`);
|
|
58
|
+
current = parent;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function install(target, files, quiet = false) {
|
|
63
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
64
|
+
const staging = fs.mkdtempSync(path.join(path.dirname(target), '.fleet-stage-'));
|
|
65
|
+
let backup;
|
|
66
|
+
try {
|
|
67
|
+
for (const [rel, digest] of Object.entries(files)) {
|
|
68
|
+
const to = path.join(staging, rel);
|
|
69
|
+
if (digest === 'directory') fs.mkdirSync(to, { recursive: true });
|
|
70
|
+
else { fs.copyFileSync(path.join(source, rel), to); fs.chmodSync(to, fs.statSync(path.join(source, rel)).mode & 0o777); }
|
|
71
|
+
}
|
|
72
|
+
fs.writeFileSync(path.join(staging, MARKER), JSON.stringify({ owner: OWNER, format: 1, version: require('../package.json').version, files: inventory(staging) }, null, 2) + '\n');
|
|
73
|
+
if (exists(target)) {
|
|
74
|
+
assertOwned(target);
|
|
75
|
+
backup = `${staging}-previous`;
|
|
76
|
+
fs.renameSync(target, backup);
|
|
77
|
+
}
|
|
78
|
+
try { fs.renameSync(staging, target); }
|
|
79
|
+
catch (error) { if (backup) fs.renameSync(backup, target); backup = undefined; throw error; }
|
|
80
|
+
if (backup) fs.rmSync(backup, { recursive: true });
|
|
81
|
+
} finally {
|
|
82
|
+
if (exists(staging)) fs.rmSync(staging, { recursive: true });
|
|
83
|
+
}
|
|
84
|
+
if (!quiet) console.log(`installed ${target}`);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function run(action, args) {
|
|
88
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
89
|
+
console.log(`fleet ${action} --harness claude|codex|cursor|all [--scope user|project] [--root /absolute/base]\nUser scope defaults to your home; project scope defaults to the current directory.\nCopies the skill and runtime. Does not change PATH, configuration, or plugin registries.\nModified or unowned installations are preserved and produce an error.`);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const opts = { scope: 'user' };
|
|
93
|
+
for (let i = 0; i < args.length; i += 2) {
|
|
94
|
+
const key = args[i].replace(/^--/, '');
|
|
95
|
+
if (!['harness', 'scope', 'root'].includes(key) || args[i] !== `--${key}` || !args[i + 1] || args[i + 1].startsWith('--')) throw new Error(`Invalid option: ${args[i]}. Use fleet ${action} --help.`);
|
|
96
|
+
if (Object.hasOwn(opts, key) && key !== 'scope') throw new Error(`Repeated option: ${args[i]}`);
|
|
97
|
+
opts[key] = args[i + 1];
|
|
98
|
+
}
|
|
99
|
+
if (!Object.hasOwn(HARNESSES, opts.harness) && opts.harness !== 'all') throw new Error('--harness must be claude, codex, cursor, or all');
|
|
100
|
+
if (!['user', 'project'].includes(opts.scope)) throw new Error('--scope must be user or project');
|
|
101
|
+
if (opts.root && !path.isAbsolute(opts.root)) throw new Error('--root must be absolute');
|
|
102
|
+
const requestedBase = opts.root || (opts.scope === 'user' ? os.homedir() : process.cwd());
|
|
103
|
+
// Resolve the explicit root itself (e.g. macOS /tmp), but never follow harness-directory links.
|
|
104
|
+
const base = exists(requestedBase) ? fs.realpathSync(requestedBase) : path.resolve(requestedBase);
|
|
105
|
+
const harnesses = opts.harness === 'all' ? Object.keys(HARNESSES) : [opts.harness];
|
|
106
|
+
const targets = harnesses.map(name => path.join(base, HARNESSES[name], 'skills', 'fleet'));
|
|
107
|
+
for (const target of targets) { assertParents(base, target); if (exists(target)) assertOwned(target); }
|
|
108
|
+
const files = action === 'setup' ? inventory(source, true) : null;
|
|
109
|
+
for (const target of targets) {
|
|
110
|
+
if (action === 'setup') install(target, files);
|
|
111
|
+
else if (exists(target)) { assertOwned(target); fs.rmSync(target, { recursive: true }); console.log(`removed ${target}`); }
|
|
112
|
+
else console.log(`absent ${target}`);
|
|
113
|
+
}
|
|
114
|
+
if (action === 'setup') {
|
|
115
|
+
console.log('Restart your harness to discover Fleet. fleet is not added to PATH; use the copied runtime (or npx @codemeall/agent-fleet@preview):');
|
|
116
|
+
console.log(path.join(targets[0], 'bin', 'fleet'));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function buildPluginSkills() {
|
|
120
|
+
const root = fs.realpathSync(path.join(__dirname, '..'));
|
|
121
|
+
const legacy = path.join(root, 'skills', 'fleet');
|
|
122
|
+
if (exists(legacy)) { assertOwned(legacy); fs.rmSync(legacy, { recursive: true }); }
|
|
123
|
+
const pluginRoot = path.join(root, 'dist', 'codex', 'agent-fleet');
|
|
124
|
+
const target = path.join(pluginRoot, 'skills', 'fleet');
|
|
125
|
+
assertParents(root, target);
|
|
126
|
+
if (exists(target)) assertOwned(target);
|
|
127
|
+
install(target, inventory(source, true), true);
|
|
128
|
+
// Codex represents explicit invocation in agents/openai.yaml, not this Claude field.
|
|
129
|
+
const skillFile = path.join(target, 'SKILL.md');
|
|
130
|
+
fs.writeFileSync(skillFile, fs.readFileSync(skillFile, 'utf8').replace(/^disable-model-invocation: true\r?\n/m, ''));
|
|
131
|
+
const markerFile = path.join(target, MARKER);
|
|
132
|
+
const record = JSON.parse(fs.readFileSync(markerFile, 'utf8'));
|
|
133
|
+
record.files = inventory(target);
|
|
134
|
+
fs.writeFileSync(markerFile, JSON.stringify(record, null, 2) + '\n');
|
|
135
|
+
fs.mkdirSync(path.join(pluginRoot, '.codex-plugin'), { recursive: true });
|
|
136
|
+
fs.copyFileSync(path.join(root, 'plugin-manifests', 'codex.json'), path.join(pluginRoot, '.codex-plugin', 'plugin.json'));
|
|
137
|
+
}
|
|
138
|
+
module.exports = { run, buildPluginSkills };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Optional ~/.config/agent-fleet/config.toml overrides.
|
|
2
|
+
# fleet providers prints the merged configuration. No workspace is pinned.
|
|
3
|
+
[defaults]
|
|
4
|
+
routing = "auto"
|
|
5
|
+
prefer = ["claude", "codex", "cursor"]
|
|
6
|
+
max_parallel = 3
|
|
7
|
+
review = "cross-heavy"
|
|
8
|
+
|
|
9
|
+
# Set only when you intentionally target a validated cmux workspace:
|
|
10
|
+
# workspace = "workspace:3"
|
|
11
|
+
|
|
12
|
+
# Models are account-dependent examples: verify availability before assigning work.
|
|
13
|
+
# [providers.codex.tiers.standard]
|
|
14
|
+
# model = "gpt-6-sol"
|
|
15
|
+
# effort = "medium"
|
|
16
|
+
# family = "openai"
|
|
17
|
+
|
|
18
|
+
# Optional second account. Authenticate it separately before enabling.
|
|
19
|
+
# [providers.claude-co]
|
|
20
|
+
# enabled = true
|
|
21
|
+
# max = 1
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agent-fleet",
|
|
3
|
+
"version": "0.1.0-preview.1",
|
|
4
|
+
"description": "Lead coding-agent CLIs in cmux from a portable Fleet skill.",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "codemeall"
|
|
7
|
+
},
|
|
8
|
+
"homepage": "https://github.com/codemeall/agent-fleet",
|
|
9
|
+
"repository": "https://github.com/codemeall/agent-fleet",
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"skills": "./skills/",
|
|
12
|
+
"interface": {
|
|
13
|
+
"displayName": "Agent Fleet",
|
|
14
|
+
"shortDescription": "Coordinate coding agents in cmux.",
|
|
15
|
+
"longDescription": "Plan, route, launch and verify coding-agent workers with a portable local Fleet skill.",
|
|
16
|
+
"developerName": "codemeall",
|
|
17
|
+
"category": "Productivity",
|
|
18
|
+
"capabilities": [],
|
|
19
|
+
"defaultPrompt": [
|
|
20
|
+
"Use Fleet to plan and implement my tickets."
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 codemeall
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: fleet
|
|
3
|
+
description: Plan, launch, resume and verify a local fleet of coding-agent CLIs in visible cmux tabs for approved tickets, with saved dependencies and explicit file ownership.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Fleet
|
|
7
|
+
|
|
8
|
+
You are the lead. Workers are local interactive CLIs in cmux tabs sharing one checkout. You own planning, routing, decisions, review and final verification. Workers implement one ticket at a time. The owner controls commits and publishing.
|
|
9
|
+
|
|
10
|
+
Use `fleet` on PATH; if unavailable, resolve this installed skill's absolute path and invoke `<absolute-skill-path>/bin/fleet`. Never guess a checkout path. Read `fleet <command> --help` when a flag is unclear.
|
|
11
|
+
|
|
12
|
+
```text
|
|
13
|
+
/fleet [auto | single:<provider> | agents=<provider>[:<model>],...]
|
|
14
|
+
[workspace=<ref>] [review=off|cross-heavy|cross-all]
|
|
15
|
+
-- <local tickets directory or task list>
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
These are conversational options for you to translate into CLI flags, not an autonomous scheduler. Defaults come from `fleet providers`. Read [harness requirements](references/harnesses.md), [routing](references/routing.md), and [provider notes](references/providers.md) as needed.
|
|
19
|
+
|
|
20
|
+
## 1. Establish or resume the run
|
|
21
|
+
|
|
22
|
+
- Read repository instructions, `.fleet/rules.md`, the agreed spec and the full tickets. Export remote issue content to local files first; a URL is not a `--ticket` input. Preserve original IDs and source links, using safe slug IDs for Fleet (`settings-copy`, not a path or URL).
|
|
23
|
+
- Verify the active machine's absolute repository path. Run `fleet doctor` from it. Route only to adapters whose executable and authentication checks pass, and verify the selected model/effort is available. Doctor does not prove launch readiness.
|
|
24
|
+
- If the named run exists, use `fleet resume <run>`, then inspect its complete saved plan, reports, decisions, any `notes.md` and reconciled process states. Do not initialize a replacement or relaunch a worker whose exit is unconfirmed.
|
|
25
|
+
- Otherwise use `fleet init <run> [--workspace <ref>] [--routing <mode>] [--review <mode>]`. Map conversational `workspace=`, routing and `review=` directly to these flags. Init validates the selected cmux workspace; never fall back to an unrelated workspace.
|
|
26
|
+
|
|
27
|
+
## 2. Save a complete plan
|
|
28
|
+
|
|
29
|
+
Discover the exact repository-relative files each ticket needs. Preserve blockers, acceptance criteria, spec decisions and testing requirements. A wave contains tickets with satisfied blockers and disjoint file scopes. Existing owner edits require careful review and must be preserved.
|
|
30
|
+
|
|
31
|
+
Show a compact table: wave, ticket, tier, provider/model/effort, exact files. Persist the complete graph with `fleet plan <run> --file <plan.json>` before launch:
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"tickets": [
|
|
36
|
+
{"id":"copy","ticket":".scratch/feature/issues/copy.md","files":["docs/copy.md"],"blockers":[],"provider":"codex","tier":"light"},
|
|
37
|
+
{"id":"guide","ticket":".scratch/feature/issues/guide.md","files":["docs/guide.md"],"blockers":["copy"],"provider":"claude","tier":"standard"}
|
|
38
|
+
],
|
|
39
|
+
"decisions": ["Checks and context are specified in each generated prompt."]
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Optional per-ticket `model`, `effort` and `family` pin routing. The CLI validates dependencies, cycles, scope and assignments. Use exact files, not directories or globs. Record decisions and agreed routing before the first launch; the plan is immutable once workers have launched. Use one active run per checkout. Serialize CLI mutations through this lead; concurrent leads must not edit the same run.
|
|
44
|
+
|
|
45
|
+
## 3. Generate prompts and launch ready tickets
|
|
46
|
+
|
|
47
|
+
- `fleet prompt <run> <id>` uses the planned local ticket (`--ticket <local-path>` may supply it explicitly). Inspect the generated prompt, preserve the worker rules, and fill its context and exact checks, then remove the LEAD instruction comment before launch. Its file list must match the saved plan.
|
|
48
|
+
- Resolve the actual glossary/ADR paths from project configuration. Prefer `GLOSSARY.md` and optional `GLOSSARY-MAP.md`, with `CONTEXT.md` for older repositories. Carry upstream `to-spec` testing and design decisions forward. Do not blindly invoke upstream `/implement`: it includes commits that Fleet forbids.
|
|
49
|
+
- `fleet launch <run> <id> <provider> --tier <tier> [--model <model>] [--effort <effort>] [--family <family>]` must match the saved assignment. The CLI enforces blockers, active file ownership and capacity.
|
|
50
|
+
- `fleet peek <run> <id>` after launch confirms progress or reveals a login, trust, model or permission prompt. Never assume creating a tab means work started.
|
|
51
|
+
|
|
52
|
+
## 4. Watch and resolve blockers
|
|
53
|
+
|
|
54
|
+
Use `fleet wait <run>` (45-second default; `--timeout` is bounded at 60 seconds) and report meaningful progress within your host's time limits. On `needs-verification`, inspect the report and go to verification. On `blocked`, clarify an authorized task decision with `fleet send <run> <id> <answer>` and save the decision in `.fleet/runs/<run>/notes.md` (the saved plan is frozen after launch). On timeout, inspect `fleet status` and `fleet peek` for stale or missing reports.
|
|
55
|
+
|
|
56
|
+
Respect host approval boundaries. Task clarification does not authorize accepting a permission request, logging into an account, disabling a sandbox or rerouting to evade a denial. Stop and ask the owner when their action is required. A report never proves that the worker process exited.
|
|
57
|
+
|
|
58
|
+
## 5. Stop, review and verify
|
|
59
|
+
|
|
60
|
+
Read the implementation report and scoped changes against all criteria. Run the exact agreed checks yourself, plus appropriate combined-tree checks and visual inspection for UI work. Do not add low-value tests for prose or mechanical changes merely to satisfy a template.
|
|
61
|
+
|
|
62
|
+
- For gaps while the worker is active: set the report to `Status: changes-requested`, send a bounded fix list, and wait for a new `needs-verification` report. Never mark a ticket verified by editing its report alone.
|
|
63
|
+
- When ready for stable review, `fleet stop <run> <id>`. It waits for confirmed exit. A failed stop retains capacity: inspect the process before proceeding. This releases the writer slot before a reviewer is launched, including at `max_parallel=1`.
|
|
64
|
+
- If required by the saved review mode, run `fleet diff <run> <id> --output <diff-path>` to capture changes against the launch baseline, including new files. Then `fleet prompt <run> <review-id> --review-of <id> --diff <diff-path>`. Inspect the dedicated reviewer prompt, which permits writing only its report; this is an instruction boundary, not OS isolation.
|
|
65
|
+
- Launch that reviewer with `--tier review` on a permitted provider/model whose known family differs from the writer. Read its findings and run any necessary checks. Resolve findings before acceptance. Any changes after the reviewed diff invalidate review; stop writers, regenerate the diff and obtain a fresh review.
|
|
66
|
+
- Stop the reviewer, write concrete verification evidence to a local file, then `fleet verify <run> <review-id> --evidence <evidence-file>`. Verify the writer separately with its own evidence file using the same command. The writer's process must have exited, its report must need verification, required review must be verified, and its current diff must match the reviewed content.
|
|
67
|
+
- Only after successful writer verification update the source ticket's resolved status/acceptance boxes and launch newly unblocked tickets. Reviewers never resolve tickets themselves.
|
|
68
|
+
|
|
69
|
+
Evidence records commands, outcomes, acceptance criteria and review disposition. Preserve failures and limits honestly. If a stopped worker needs repair within its existing assignment, relaunch only after its prior exit is confirmed; give it the existing edits and remaining scope explicitly. Scope or routing changes after the first launch need a new follow-up run: first stop every worker that could overlap, then carry forward unresolved tickets, partial edits and decisions. Do not edit run.json to bypass immutable planning.
|
|
70
|
+
|
|
71
|
+
## 6. Recovery and completion
|
|
72
|
+
|
|
73
|
+
Use `fleet resume <run>` after interruption. Exit receipts reconcile process state; reports and missing tabs are not exit evidence. If normal stop cannot establish exit, independently verify that the recorded worker process is truly gone, write that evidence to a file, then use `fleet recover <run> <id> --evidence <file>`. Recovery releases process state only; it does not accept implementation. Never use it just because a tab disappeared.
|
|
74
|
+
|
|
75
|
+
Before finishing, run combined-tree gates and `fleet check <run>`. Check compares captured HEAD and full index entries (including already-staged content); investigate differences with the owner. It cannot prove no intervening Git action occurred. Stop remaining workers; use `--close` only when exit is confirmed and tabs are no longer needed. Report ticket outcomes, resolved model/effort, evidence, decisions, remaining limits and the owner's review/commit steps.
|
|
76
|
+
|
|
77
|
+
## Shared-checkout rules
|
|
78
|
+
|
|
79
|
+
- Preserve the worker preamble and exact scope. Scope additions need a conflict check and, after launch, a follow-up run before editing.
|
|
80
|
+
- Use Fleet or non-focusing cmux actions. Do not take the owner's focus.
|
|
81
|
+
- Run builds that would disturb a live dev server in an appropriate isolated copy; never run them over shared build output without checking repository instructions.
|
|
82
|
+
- No worker commits, stages, pushes, deploys, installs packages, migrates data or accesses secrets. Network-dependent work must be handled separately under explicit owner authorization; changing providers does not remove these rules.
|