@feigi/fleet-ctl 3.82.19 → 3.82.21

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.
@@ -492,7 +492,7 @@ every five Pulls by construction.
492
492
  The last guard fired with n=1 on the control side. The pre-cell pair query
493
493
  counted pairs that are no cell's comparisons, and the query before that one
494
494
  counted every session whose implementers merely differed, so it cleared the
495
- cell floor SKILL.md's **Report** states — at least ten comparisons across five
495
+ cell floor **Do not read a cell early** states — at least ten comparisons across five
496
496
  or more distinct `run_date`s — by an order of magnitude while the controlled
497
497
  comparison did not exist yet.
498
498
 
@@ -576,3 +576,38 @@ The raw split still favours the top tier — 3 failures in 11 `routine`/`sonnet`
576
576
  ## What minted_false_claim reads
577
577
 
578
578
  `minted_false_claim` **discriminates and no longer reads "always yes"** — 20 of the 66 `routine` rows carry `no`, 18 at `opus` and 2 at `sonnet`. Read it as a property of the TICKET before the tier: a pure code simplification need not add prose, while a correction ticket adds prose by construction. The honest summary is unchanged and is the reason this paragraph exists: the guard fired on the criterion the maintainer chose in advance, not on a demonstration that the cheaper tier is worse.
579
+
580
+ ## Do not read a cell early
581
+
582
+ **Do not read a cell early.** A cell's
583
+ comparison is one session holding an admissible row at that cell — its tier
584
+ check passed and its resolved effort is the cell's level — and one at
585
+ `slow-high` whose resolved model and effort differ. Count them per cell, never
586
+ pooled across cells, and stop until
587
+ there are at least ten of them across five or more distinct `run_date`s; below
588
+ that, a comparison count is a number, not evidence. SKILL.md's **Report**
589
+ reports the count `cell-readout.mjs` prints, which holds a cell below that
590
+ floor to a count on stderr.
591
+
592
+ ## A Pull's entry and exits, in full
593
+
594
+ A Pull's entry is `~/.fleet/bin/fleet-run pull.mjs next --head <N>`, run from the
595
+ main checkout (without `--head`, the next shortlist entry). It runs the
596
+ mechanical steps in order and stops at each judgement with a `QUESTION
597
+ <qid>:` block and exit 10; `pull.mjs answer <N> <qid> <token> [--path <p>] [--]
598
+ [<text>…]` records the answer and resumes it. Exit 0 prints `DISPATCH {name,
599
+ agent, brief}`, the `task` call that the dispatch makes; exit 1 means the ticket left the
600
+ Pull, so take the next entry; exit 2 names what could not be looked at —
601
+ `next --head <N>` again retries a step that failed, the same `answer` again
602
+ retries one that failed while applying an answer (the question stands), and
603
+ after a router refusal `next --head <N>` starts the ticket over; exit 3 is a
604
+ usage mistake, or an answer the question does not take, and records nothing.
605
+ The record is `<scratch>/impl-<N>/pull.json`.
606
+
607
+ ## No multi-select, no maintainer tick
608
+
609
+ **No multi-select, no maintainer tick.** Selection and ordering are batched —
610
+ one scan, oldest first; admission never is. The invariant this replaces — one
611
+ human decision per batch of admissions, zero unilateral grabs — is retired
612
+ is retired: zero human decisions per admission, and every non-admission is a
613
+ label or a premise the maintainer can read.
@@ -148,3 +148,84 @@ to matter, and a confident wrong report from a reviewer flips a verdict.
148
148
  "Nothing else references this", "the sweep
149
149
  is clean" — most likely false, least likely checked: a grep that found nothing
150
150
  looks like a grep never run.
151
+
152
+ ## Reading a review result's digest, field by field
153
+
154
+ Findings never enter your context —
155
+ a result runs 26-61 KB, 7-15k tokens that used to land in yours and then again,
156
+ up to ~10k characters, in every fix-applier prompt you wrote. What the digest tells you:
157
+
158
+ **`testEnvironment` says what the review's shared test run is evidence about**,
159
+ and it is present on a healthy run as well as a degraded one, so there is
160
+ nothing to notice by its absence. The
161
+ fix-applier reads it before acting on any count from the shared test run; you
162
+ read it so a degraded review never passes for a clean one.
163
+ `unverified` is *not* "checked and cleared" — a `suggestion` skips the pass by
164
+ policy, and a finding whose refuters all crashed or abstained lands there too.
165
+ All go to the fix-applier with the rest, in the file; never rule on them yourself.
166
+ **`refutersDispatched`, carried on every finding, is what tells the skip
167
+ apart** — zero is the policy skip, above zero with no deciding vote is a
168
+ refuter pass that decided nothing — and `refutersInconclusive` splits that
169
+ one: the refuters it counts abstained, every other one dispatched crashed. So
170
+ the population is read off those fields rather than off severity,
171
+ which records only how much a finding would matter if true. `resume` is
172
+ non-null exactly when a specialist or a refuter pair crashed again after the
173
+ review's own in-run retry, and **resume beats handing a crash-heavy review
174
+ on**: a deferred crash is a finding nobody ever looked at.
175
+ No replay exists for a review that ran in a runner's own kernel — `resume` is reported, not acted on, and the fix-applier defers what it names.
176
+ `refuted` comes back deliberately as well — a refutation is itself a claim, and
177
+ one has been reversed on new evidence. The fix-applier may reverse one; it
178
+ records each reversal as a `refuted` entry in its disposition record, the
179
+ evidence in `reason`, and you copy those entries to the ledger's `ruled` line by
180
+ running `fleet-event.mjs fix-report`, whose `settle --from-report` records each
181
+ refutation the report defers.
182
+
183
+ **`dimensionsRun` is the dispatch; `dimensionsUnrun` is what names a gap.** A
184
+ specialist that dies contributes zero findings while its key stays in
185
+ `dimensionsRun`. So read the two together. A key
186
+ in `dimensionsRun` and NOT in `dimensionsUnrun` returned a review; every
187
+ `dimensionsUnrun` entry is `{dimension, reason}` naming a specialist that
188
+ returned nothing, its `reason` the crash.
189
+ The review already re-dispatched each crashed specialist once, so what
190
+ `dimensionsUnrun` still names is residue: the fix-applier names it unrun in its
191
+ report and re-runs nothing — an absence of findings is not coverage.
192
+
193
+ **`suiteVerdict` is the review's one judgement on its shared test run:
194
+ `{usable, reason}`, always present.** The review runs the test command once,
195
+ and every specialist reads that run instead of running its own. `{usable: true,
196
+ reason: null}` says the run executed real tests and its exit status is
197
+ explained by its counts; usable is not green, so a usable run can have failing
198
+ tests. `usable: false` carries `reason`, including a run that never started
199
+ (install skipped, no suite slot). The verdict says nothing about whether a
200
+ dimension reviewed: a specialist that returned reviewed, its findings verified
201
+ as usual, whatever the suite verdict. With `usable: false` the
202
+ fix-applier names `shared test run not usable: <reason>` in its final verdict
203
+ and does nothing more — its own `<testCmd>` run and CI cover the suite.
204
+ **Exit 75 is not a test result.** In a review it makes
205
+ `suiteVerdict` not usable, `suiteVerdict.reason` beginning "no suite slot within
206
+ <n> s — the host is at its suite bound; not a test failure", with no retry
207
+ inside the run: read that `reason` off the digest and re-review it
208
+ under the next runner letter (`review-pr-<pr#>-b` after a first runner), as for
209
+ a runner that reported `failed`.
210
+
211
+ **`cwdAudit` is the specialist's own inherited-checkout audit, one entry per
212
+ dispatched dimension: `{dimension, state, line}`, `state` one of**
213
+ `clean`/`dirty`/`unrepo`/`missing`. The prompt asks every specialist to run
214
+ `git status --porcelain -uall` against the directory it inherited before
215
+ returning and fold the result into a `CWD-AUDIT:` line — a convention, not
216
+ schema, so a specialist that never emits it or misspells it still validates
217
+ clean. This field is the runtime backstop that reads for the line regardless:
218
+ `missing` is exactly as loud as `dirty`, and both name a checkout you should
219
+ treat as a live scratch write until you have checked it.
220
+
221
+ ## The tier-outcomes row's difficulty fields
222
+
223
+ The row's last four fields are the ticket's difficulty, and they are what lets a
224
+ tier comparison condition on the thing that swamps it. `sizing` is the
225
+ **member's** own `light`/`heavy` verdict from its dispatched `sizing-a-ticket`
226
+ run, which `append` reads itself off the member's report file
227
+ (`<scratch>/reports/impl-<ticket>[-x].json`, its `sizing.verdict`, the highest
228
+ retry letter's when there are several), so you pass no `--sizing`; the member
229
+ also puts it in the PR body's `Sizing:` line, with the signal it turned on;
230
+ `profile`, `loc` and `files` all come from `diff-stats.mjs` over the merged
231
+ diff.
@@ -2,12 +2,13 @@
2
2
 
3
3
  ## Shell traps
4
4
 
5
- Monitor and Bash commands run under **zsh**, and the shell in SKILL.md is
6
- prescriptive — copied verbatim into a watcher or into the merge bot's agent
7
- body. So every trap here is a zsh-vs-bash difference that ships as a
8
- green-looking gate: correct in the shell you tested in, silently wrong in the
9
- one it runs in. **Own the CI waits**'s monitor paragraph points here instead of
10
- restating any of it. The merge bot's agent body is the one place this block is
5
+ Monitor and Bash commands run under **zsh**, and the shell in
6
+ references/ci-watcher.md is prescriptive — copied verbatim into a watcher or
7
+ into the merge bot's agent body. So every trap here is a zsh-vs-bash difference
8
+ that ships as a green-looking gate: correct in the shell you tested in,
9
+ silently wrong in the one it runs in. references/ci-watcher.md's monitor
10
+ paragraph points here instead of restating any of it. The merge bot's agent
11
+ body is the one place this block is
11
12
  copied whole (see **The merge bot**); the other deliberate copy is named at the end.
12
13
 
13
14
  A bot already looping cannot be corrected — the loop consumes the turns a correction would land in — so `agents/fleet-merge-bot.agent.md` carries **every entry in `references/shell-traps.md`'s Shell traps**, each written out in full: the rules with the measurements from that file beside them, and the bot has them before its first turn. An edit to `references/shell-traps.md` lands in that body in the same change.
@@ -28,13 +29,13 @@ $prs
28
29
  EOF
29
30
  ```
30
31
 
31
- The inline `$(printf '%s\n' "$prs")` form splits correctly too and is what the watcher block under **Own the CI waits** uses, but it splits on *every* whitespace character, so it is safe only for values that cannot contain one — PR numbers cannot, branch names and paths can.
32
+ The inline `$(printf '%s\n' "$prs")` form splits correctly too and is what the watcher block in references/ci-watcher.md uses, but it splits on *every* whitespace character, so it is safe only for values that cannot contain one — PR numbers cannot, branch names and paths can.
32
33
 
33
34
  **`</dev/null` every command inside a `while read` loop.**
34
35
 
35
36
  **A probe that could not look emits an event; it never `continue`s.** Stated in
36
- full at *A probe that cannot read is a transition event, not silence* under **Own the CI waits**,
37
- and it binds every watcher in SKILL.md rather than that one block: the third
37
+ full at *A probe that cannot read is a transition event, not silence* in references/ci-watcher.md,
38
+ and it binds every watcher rather than that one block: the third
38
39
  value beside pass and fail is what turns a broken loop into a loud failure
39
40
  instead of a quiet one. A guard that drops an unreadable probe — `[ -n "$json" ]
40
41
  || continue` — makes *could not look* indistinguishable from *nothing to report*.
@@ -253,3 +253,38 @@ the whole point: a table you must remember to consult is one you will not
253
253
  consult under a merge-side event storm, and that is how implementers reached
254
254
  0/target with ~57 `ready-for-agent` in supply while nobody
255
255
  noticed.
256
+
257
+ ## What the tick reads
258
+
259
+ It reads the run itself, and nobody states a count. The In-flight count —
260
+ every open PR that closes an issue off `gh`, plus every claimed ticket whose
261
+ newest implementer is live or owed a replacement and has no such PR yet, off
262
+ the ledger — sits beside the live review units (in-flight `review=` tokens
263
+ plus unsettled `fix-pr-` ones), the merge bot, merge holds, tier mismatches
264
+ and the drain marker, all off `.fleet/ledger.md`; the unclaimed heads and the
265
+ supply come off `.fleet/shortlist.json`, which it refreshes itself when the
266
+ unclaimed count is below the In-flight bound, when the file is missing or
267
+ empty, when an Exclusion's premise has lifted, or when a branch-named
268
+ `behind-pr` or a `behind-issue` Exclusion still not lifted names a ticket the
269
+ file carries — never while the bound holds; the open PRs come off `gh`. A
270
+ head whose Pull ended this run is not counted, unless on a lifted exclusion. A
271
+ ledger token it
272
+ cannot read, it refuses rather than guessing — a member counted live or gone on
273
+ a guess is the over- or under-dispatch it exists to prevent — so correct that
274
+ row with `ledger.mjs row` and tick again. The In-flight bound defaults to 5
275
+ and is fixed for the run: pass `--in-flight` on every tick when `$ARGUMENTS`
276
+ set it, and never otherwise.
277
+
278
+ ## Refresh is the tick's
279
+
280
+ 2. **Refresh is the tick's from here on.** `fleet-tick.mjs` runs
281
+ `shortlist.mjs` itself when unclaimed entries fall below the In-flight
282
+ bound, when the file is missing or empty, when an `excluded` premise has
283
+ lifted, and when a branch-named `behind-pr` exclusion whose PR is not yet
284
+ MERGED or CLOSED, or a `behind-issue` exclusion whose issue is not yet
285
+ closed, names a ticket the file still carries, and prints
286
+ `REFRESHED shortlist: <n> entries; <k> lifted`. A head whose Pull ended
287
+ this run is not counted, unless on a lifted exclusion. Phase 0 runs it by hand
288
+ once because a dead run's shortlist is stale by definition.
289
+ None of those triggers runs while `HOLD (in-flight <n>/<B>)` stands.
290
+