@feigi/fleet-ctl 3.17.2 → 3.17.4

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.
@@ -79,7 +79,7 @@ It cannot ask the user anything and cannot wait on CI — rebasing, watching che
79
79
  - **Do not trust the obvious contamination check.** `diff -rq` and `md5` against the mutating tree both returned *clean* — because the probe had been reverted between the two reads. A clean diff against a live tree is not evidence in either direction; only `snap-ro` and the object store settle it.
80
80
  - **`git archive` carries tracked files only.** No `node_modules`, no gitignored runner or config. Provision in the same step — symlink `node_modules`, copy in what the runner needs — or specialists silently have no runnable suite and reason from source instead of measuring. That failure is invisible: you get confident prose where you asked for a measurement.
81
81
  - **Initialize the copy before anyone measures in it — a bare `git archive` tree cannot validly run every suite.** It is not a git repository, so anything that asks git about the checkout breaks: `derive_workspace_id` shells out to `git rev-parse`, falls back to the directory basename and the hook tests fail on the *name* — naming the dir after the repo makes those pass **by coincidence, not correctness** — while every sweep that asks git what ships declines instead of running, which is the silent half (measured on this repo at `ffa9026`: 2401 tests, 2382 pass, 19 skipped in an extraction against 2401/2401/0 in a worktree, the totals identical). `git init && git add -A -f && git commit` in the extracted copy is what makes a count mean what it looks like; the review's snapshot agent does exactly that and verifies it by comparing the new commit's tree hash against the reviewed commit's (#1056), and a hand-cut tree needs the same before you read a count off it. Suites that need the real worktree for some *other* reason — the stack below — still do.
82
- - **Give specialists a stack-free test command, not the worktree's runner, and their own scratch dir** — `<scratch>/pr<N>/fleet-review-<key>/`, resolved to an absolute path that you write into that specialist's prompt; a specialist never derives its own. Specialists inherit no environment, and one falling back to the default config runs a `globalSetup` that brings the shared compose stack up and tears it down, recreating the DB mid-run for every sibling. **The snapshot does not cover this** — the compose project name comes from the environment, not the working directory, so three agents on three copies still collide. But `./agent-test` does not fix it either: it exports **one** `TEST_COMPOSE_PROJECT`/port triple per *worktree* (`ab-<issue>`), so N concurrent specialists sharing it tear down each other's postgres mid-run. Observed: a probe returned `No test files found / No such container` and would have read as a test failure. **That war story is from another repo, and the config-swap escape it calls for does not exist here** — `feigi/claude-config` has no compose file, no `globalSetup`, and no vitest, so there is no `vitest.ci.config.ts` to point anyone at. (It does now have CI — `.github/workflows/ci.yml` — but that runs `node --test`, not a stack.) Naming one sends every specialist into `Cannot find module`, which reads as a broken tree rather than a bad instruction. In *this* repo the collision is inert for a different reason: the `export TEST_COMPOSE_PROJECT=…` line `claim-ticket.sh` writes into the runner sets `TEST_COMPOSE_PROJECT`/`TEST_POSTGRES_PORT`/`TEST_OLLAMA_PORT` and **nothing reads them** — the suite is `node --test` throughout. So tell specialists `node --test plugin/scripts/*.test.mjs` directly, glob form — `review-core.mjs` derives the same effective command for this repo now rather than defaulting to it (#142), keeping this bullet's manual command in agreement with it — and keep `./agent-test` for your own verification. **Hand that command with its reading rule: `tests 0` is a failed run, not a pass.** A glob is not self-checking. Where it matches nothing, bash passes the pattern through literally, node globs it itself and finds no files, and you get `ℹ tests 0` / exit 0 — a green having run nothing. Read the count under either reporter: `node --test` prints `ℹ tests 0` to a terminal and `# tests 0` to a pipe on older node, so a rule that greps only for `ℹ` finds nothing in a CI log and cannot tell a zero-test run from a full one. Do not count on the shell to catch it: zsh errors (`no matches found`, exit 1) and bash does not, so the guard has to be the reading rule. Node v26.5.0 has no flag that fails a zero-test run. **And zero is not the only no-work count.** **0 passes with no failures** is everything skipped, and a count **materially below the full suite** is a partial copy of the tree — which is the *documented* behavior, since the prompt tells specialists to run their probe work inside their own copy of the snapshot and nothing anchors an expected count for them. `review-core.mjs` classifies the first itself, in `unrunReason`; the second it structurally cannot, because that function is kept pure and so never learns how many tests the tree has. Handing the rule over with the command is the only guard the partial-copy case has. Carry the rule, not the command: in a repo that *does* have a stack, N concurrent specialists sharing one runner still collide, and the escape is whatever that repo's stack-free config is.
82
+ - **Give specialists a stack-free test command, not the worktree's runner, and their own scratch dir** — `<scratch>/pr<N>/fleet-review-<key>/`, resolved to an absolute path that you write into that specialist's prompt; a specialist never derives its own. Specialists inherit no environment, and one falling back to the default config runs a `globalSetup` that brings the shared compose stack up and tears it down, recreating the DB mid-run for every sibling. **The snapshot does not cover this** — the compose project name comes from the environment, not the working directory, so three agents on three copies still collide. But `./agent-test` does not fix it either: it exports **one** `TEST_COMPOSE_PROJECT`/port triple per *worktree* (`ab-<issue>`), so N concurrent specialists sharing it tear down each other's postgres mid-run. Observed: a probe returned `No test files found / No such container` and would have read as a test failure. **That war story is from another repo, and the config-swap escape it calls for does not exist here** — `feigi/claude-config` has no compose file, no `globalSetup`, and no vitest, so there is no `vitest.ci.config.ts` to point anyone at. (It does now have CI — `.github/workflows/ci.yml` — but that runs `node --test`, not a stack.) Naming one sends every specialist into `Cannot find module`, which reads as a broken tree rather than a bad instruction. In *this* repo the collision is inert for a different reason: the `export TEST_COMPOSE_PROJECT=…` line `claim-ticket.sh` writes into the runner sets `TEST_COMPOSE_PROJECT`/`TEST_POSTGRES_PORT`/`TEST_OLLAMA_PORT` and **nothing reads them** — the suite is `node --test` throughout. So tell specialists this repo's test command directly — read off the Recipe cache the way step 3 reads it (`derive-testcmd.sh <worktree or main checkout> test` prints it; the snapshot carries no `.fleet/` cache, so pointing it at the snapshot refuses), here in glob form `node --test plugin/scripts/*.test.mjs` as this repo's example — and keep `./agent-test` for your own verification. **Hand that command with its reading rule: `tests 0` is a failed run, not a pass.** A glob is not self-checking. Where it matches nothing, bash passes the pattern through literally, node globs it itself and finds no files, and you get `ℹ tests 0` / exit 0 — a green having run nothing. Read the count under either reporter: `node --test` prints `ℹ tests 0` to a terminal and `# tests 0` to a pipe on older node, so a rule that greps only for `ℹ` finds nothing in a CI log and cannot tell a zero-test run from a full one. Do not count on the shell to catch it: zsh errors (`no matches found`, exit 1) and bash does not, so the guard has to be the reading rule. Node v26.5.0 has no flag that fails a zero-test run. **And zero is not the only no-work count.** **0 passes with no failures** is everything skipped, and a count **materially below the full suite** is a partial copy of the tree — which is the *documented* behavior, since the prompt tells specialists to run their probe work inside their own copy of the snapshot and nothing anchors an expected count for them. `review-core.mjs` classifies the first itself, in `unrunReason`; the second it structurally cannot, because that function is kept pure and so never learns how many tests the tree has. Handing the rule over with the command is the only guard the partial-copy case has. Carry the rule, not the command: in a repo that *does* have a stack, N concurrent specialists sharing one runner still collide, and the escape is whatever that repo's stack-free config is.
83
83
  - **Completion is not delivery — but you can reach a specialist, so never wait idle.** A specialist you dispatched reports when it settles; if a report is missing, `hub send` it by name and ask for the report. Judge delivery by whether a report came out. **Do not settle a dimension you hold no report for**: ask the specialist, then the controller by name; only when neither answers, rule and name that dimension **unrun** — a killed specialist never reports, so waiting on one is unbounded. Never ship "dispatched, never delivered" as settled; a ruling citing a report you do not hold gets verified from source, never applied on trust.
84
84
  - **Apply only once the fan-out is settled — every report either in hand or accounted for.** Collection is not guaranteed; a report that never arrived is an open dimension, not a smaller set. And editing while they read is the same defect as probing — one specialist reviewed uncommitted code that was never in the PR diff.
85
85
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feigi/fleet-ctl",
3
- "version": "3.17.2",
3
+ "version": "3.17.4",
4
4
  "description": "Agent fleet: run-team controller, merge bot, PR reviewer, and the ticket pipeline they share",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {