@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.
- package/agents/fleet-merge-bot.agent.md +6 -6
- package/package.json +1 -1
- package/scripts/tier-outcomes.mjs +46 -6
- package/skills/run-team/SKILL.md +178 -579
- package/skills/run-team/references/ci-and-staleness.md +47 -0
- package/skills/run-team/references/ci-watcher.md +138 -3
- package/skills/run-team/references/close-out.md +34 -1
- package/skills/run-team/references/failure-handling.md +43 -0
- package/skills/run-team/references/finisher.md +185 -0
- package/skills/run-team/references/instruments.md +20 -0
- package/skills/run-team/references/isolation.md +10 -0
- package/skills/run-team/references/ledger.md +4 -0
- package/skills/run-team/references/member-lifecycle.md +18 -0
- package/skills/run-team/references/phase-0.md +50 -0
- package/skills/run-team/references/pull.md +36 -1
- package/skills/run-team/references/reviewers.md +81 -0
- package/skills/run-team/references/shell-traps.md +10 -9
- package/skills/run-team/references/tick-rows.md +35 -0
|
@@ -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
|
|
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
|
|
6
|
-
prescriptive — copied verbatim into a watcher or
|
|
7
|
-
body. So every trap here is a zsh-vs-bash difference
|
|
8
|
-
green-looking gate: correct in the shell you tested in,
|
|
9
|
-
one it runs in.
|
|
10
|
-
restating any of it. The merge bot's agent
|
|
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
|
|
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*
|
|
37
|
-
and it binds every watcher
|
|
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
|
+
|