@feigi/fleet-ctl 3.82.15 → 3.82.16
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/package.json
CHANGED
package/skills/run-team/SKILL.md
CHANGED
|
@@ -59,8 +59,8 @@ phase, or in any later one, asks the maintainer which tickets to take.
|
|
|
59
59
|
one stopped; before it, a re-run runs every step again.
|
|
60
60
|
|
|
61
61
|
The `tier-roles` step runs `~/.fleet/bin/fleet-run tier-roles.mjs --check
|
|
62
|
-
--in-flight <B>`, `<B>` being the `--in-flight` given, else the default
|
|
63
|
-
**
|
|
62
|
+
--in-flight <B>`, `<B>` being the `--in-flight` given, else the default.
|
|
63
|
+
**Default: In-flight bound 5, fixed for the run.** See references/pull.md. What it checks is in the header of `scripts/tier-roles.mjs`, under
|
|
64
64
|
the tier routes. A line it prints on a pass about omp's `task.maxConcurrency`
|
|
65
65
|
is a notice in the step's output and never holds: read it, report it, and
|
|
66
66
|
go on — the fleet never writes that setting.
|
|
@@ -151,8 +151,7 @@ phase, or in any later one, asks the maintainer which tickets to take.
|
|
|
151
151
|
`REFRESHED shortlist: <n> entries; <k> lifted`. A head whose Pull ended
|
|
152
152
|
this run is not counted, unless on a lifted exclusion. Phase 0 runs it by hand
|
|
153
153
|
once because a dead run's shortlist is stale by definition.
|
|
154
|
-
None of those triggers runs while `HOLD (in-flight <n>/<B>)` stands
|
|
155
|
-
(**Queue depth**).
|
|
154
|
+
None of those triggers runs while `HOLD (in-flight <n>/<B>)` stands.
|
|
156
155
|
|
|
157
156
|
**No multi-select, no maintainer tick.** Selection and ordering are batched —
|
|
158
157
|
one scan, oldest first; admission never is. The invariant this replaces — one
|
|
@@ -386,6 +385,29 @@ treat as a live scratch write until you have checked it.
|
|
|
386
385
|
|
|
387
386
|
**A refutation resting on an injection nothing proved landed is not a refutation — it is a cell that never ran.** See references/reviewers.md.
|
|
388
387
|
|
|
388
|
+
**Guard: accumulate per PR, never conclude inside one run.** **Append one row to
|
|
389
|
+
`docs/metrics/tier-outcomes.tsv` when you rule each PR's review, with
|
|
390
|
+
`~/.fleet/bin/fleet-run tier-outcomes.mjs append <pr> --closed-own-ticket yes|no --minted-false-claim yes|no --note "<text>"`,
|
|
391
|
+
never by hand** (that file's header carries the column meanings). The script
|
|
392
|
+
fills `run_date`, `pr`, `ticket` and `tier` itself — `tier` from what actually
|
|
393
|
+
ran, off the implementer's `tier-ok=` ledger verdict or else its one
|
|
394
|
+
member-outcomes row (a `tier-unverifiable=` member has no ledger verdict, so
|
|
395
|
+
its one member-outcomes row decides), and BLANK with a WARNING naming why
|
|
396
|
+
when neither settles
|
|
397
|
+
it; never type a tier in over that. That append is the whole duty. See references/pull.md.
|
|
398
|
+
|
|
399
|
+
The row's last four fields are the ticket's difficulty, and they are what lets a
|
|
400
|
+
tier comparison condition on the thing that swamps it. `sizing` is the
|
|
401
|
+
**member's** own `light`/`heavy` verdict from its dispatched `sizing-a-ticket`
|
|
402
|
+
run, which `append` reads itself off the member's report file
|
|
403
|
+
(`<scratch>/reports/impl-<ticket>[-x].json`, its `sizing.verdict`, the highest
|
|
404
|
+
retry letter's when there are several), so you pass no `--sizing`; the member
|
|
405
|
+
also puts it in the PR body's `Sizing:` line, with the signal it turned on;
|
|
406
|
+
`profile`, `loc` and `files` all come from `diff-stats.mjs` over the merged
|
|
407
|
+
diff.
|
|
408
|
+
|
|
409
|
+
**A verdict is a measurement only if it post-dates the run that produced it.** See references/reviewers.md.
|
|
410
|
+
|
|
389
411
|
### Nothing to do: arm the beat
|
|
390
412
|
|
|
391
413
|
- **Nothing to do right now** → **do not end your turn.** Arm the heartbeat
|
|
@@ -463,6 +485,18 @@ Act on each line the tick prints as its row reads here, then stop: the next wake
|
|
|
463
485
|
~/.fleet/bin/fleet-run fleet-tick.mjs --apply [--in-flight <n>]
|
|
464
486
|
```
|
|
465
487
|
|
|
488
|
+
Read the depth off the tick and never derive it by hand: act on the row it prints, and when it prints `SUGGEST /triage, hold idle`, hold the implementer row idle and suggest `/triage` in the report. See references/tick-rows.md.
|
|
489
|
+
|
|
490
|
+
**The review backlog never gates, and the merge-queue depth is still no
|
|
491
|
+
signal.** The only gate on a Pull is the In-flight count. A deep backlog is a
|
|
492
|
+
`DISPATCH review` on the same tick, never a reason to idle an implementer.
|
|
493
|
+
A starved implementer queue never stalls the review or merge side.
|
|
494
|
+
For the merge queue, see references/pull.md.
|
|
495
|
+
|
|
496
|
+
**Reconcile, do not wait for an event.** With the shortlist empty the tick's rows
|
|
497
|
+
govern — refresh, and never Pull a ticket the shortlist does not hold.
|
|
498
|
+
See references/pull.md.
|
|
499
|
+
|
|
466
500
|
It reads the run itself, and nobody states a count. The In-flight count —
|
|
467
501
|
every open PR that closes an issue off `gh`, plus every claimed ticket whose
|
|
468
502
|
newest implementer is live or owed a replacement and has no such PR yet, off
|
|
@@ -482,12 +516,11 @@ row with `ledger.mjs row` and tick again. The In-flight bound defaults to 5
|
|
|
482
516
|
and is fixed for the run: pass `--in-flight` on every tick when `$ARGUMENTS`
|
|
483
517
|
set it, and never otherwise.
|
|
484
518
|
|
|
485
|
-
It prints `actual/target` and a named ACTION per role
|
|
486
|
-
depth** guard table applied in code. Act on each line as it reads:
|
|
519
|
+
It prints `actual/target` and a named ACTION per role. Act on each line as it reads:
|
|
487
520
|
|
|
488
521
|
- `PULL #<N> …` — one Pull per named ticket, in the order printed: `pull.mjs next --head <N>`, or the `pull.mjs answer` the row names (phase 1), then the dispatch under **Dispatching the Pull's member**.
|
|
489
522
|
- `REFRESHED shortlist: <n> entries; <k> lifted` — the tick refreshed the shortlist itself, and its `PULL` row already reads the result; `REFRESH FAILED` is yours, since `shortlist.mjs` could not run.
|
|
490
|
-
- `SUGGEST /triage, hold idle` — nothing is admissible after the refresh: suggest `/triage` in the report, never run it.
|
|
523
|
+
- `SUGGEST /triage, hold idle` — nothing is admissible after the refresh: suggest `/triage` in the report, never run it. The suggestion is a report, not a blocking prompt.
|
|
491
524
|
- `specs-dropped=#<N> …` — never actionable: log those tickets as specs awaiting to-tickets, not as no work.
|
|
492
525
|
- `DISPATCH fix-pr PR#<M> …` — a fix-applier for that PR (review findings, a dispositions mismatch no retry has answered, or a conflict hold): render its brief with `dispatch-prompt.mjs render fix-applier --kind <kind>`, `ledger.mjs dispatch <M> fix-pr-<M>` (the next suffix when that name is already on record), then the `task` call.
|
|
493
526
|
- `DISPATCH review PR#<M> …` — a review per PR, oldest first, off your turn: record `review=member:review-pr-<M>` with `ledger.mjs review <M> …`, then dispatch `review-pr-<M>`.
|
|
@@ -1019,6 +1052,16 @@ report recovery, never the exit code alone.
|
|
|
1019
1052
|
|
|
1020
1053
|
Each rule here is a judgement a driver stops for: answer it by the cause it names, then run the tick, and report to the maintainer what the evidence cannot settle.
|
|
1021
1054
|
|
|
1055
|
+
### A member's claims
|
|
1056
|
+
|
|
1057
|
+
**Cross-check what members report about their environment.**
|
|
1058
|
+
|
|
1059
|
+
**Distrust negative claims hardest.** Make members state their search scope. Negative claim
|
|
1060
|
+
vs specific finding with paths → paths win. See references/reviewers.md.
|
|
1061
|
+
|
|
1062
|
+
Suspect a neighbour before a member's own diff — for unexplained failures, and
|
|
1063
|
+
equally for any **finding** that came from reading source.
|
|
1064
|
+
|
|
1022
1065
|
### Relabel causes
|
|
1023
1066
|
|
|
1024
1067
|
- **Implementer bails before implementing** → `fleet-event.mjs impl-report impl-<N>`
|
|
@@ -1244,224 +1287,20 @@ this section's dispatch recipe — the cwd recipe above, the isolated-workspace
|
|
|
1244
1287
|
measurement, or the teardown scoping — moves
|
|
1245
1288
|
where the controller itself runs from.
|
|
1246
1289
|
|
|
1247
|
-
## Queue depth
|
|
1248
|
-
|
|
1249
|
-
Read the depth off the tick and never derive it by hand: act on the row it prints, and when it prints `SUGGEST /triage, hold idle`, hold the implementer row idle and suggest `/triage` in the report.
|
|
1250
|
-
|
|
1251
|
-
- **shortlist** — `.fleet/shortlist.json`'s entries with no `impl-` row and no
|
|
1252
|
-
live `excluded` row: admissible, not yet pulled. The tick's `unclaimed=`.
|
|
1253
|
-
Not after a refresh at unclaimed < B (below). A head whose Pull ended this
|
|
1254
|
-
run is not counted, unless on a lifted exclusion.
|
|
1255
|
-
- **supply** — `scanned`, the open `ready-for-agent` tickets `shortlist.mjs`'s
|
|
1256
|
-
candidate scan returned, before any filter. Only a Pull's full read judges
|
|
1257
|
-
decided?, so a shortlist of undecided tickets is supply that every Pull
|
|
1258
|
-
relabels away — and relabelling is what stops it being counted next scan.
|
|
1259
|
-
- **review backlog** — PRs owed a review. `fleet-tick.mjs` counts every
|
|
1260
|
-
open PR without `ready-to-merge` **that closes an issue** and carries no `review=`
|
|
1261
|
-
token on the ledger — one settled `=failed` is owed a review again, and so is
|
|
1262
|
-
one whose latest finisher halted `past-pin` past its latest `reviewed=` head
|
|
1263
|
-
(**Resolving a finisher halt**) — and it
|
|
1264
|
-
prints them as `review-due=`. Exact, not a wider read: the ledger records
|
|
1265
|
-
which PRs are under review or reviewed, so nothing about it is guesswork. The
|
|
1266
|
-
closing-issue test is what keeps it from widening: a PR that closes no issue
|
|
1267
|
-
— one you author yourself, for instance — is left unlabelled for the
|
|
1268
|
-
maintainer, so no member of the fleet will ever review it, and counting it
|
|
1269
|
-
floors the backlog at a depth nothing in the run can drain — the reviewer
|
|
1270
|
-
row would then report a review owed for the rest of the run.
|
|
1271
|
-
GitHub's own linked-issue set decides that, not a keyword regex over the body.
|
|
1272
|
-
**That exemption is for a PR THIS run authors, never one a PRIOR run left
|
|
1273
|
-
open** — step 0 folds those into this run's review queue, so count one when
|
|
1274
|
-
you reason about backlog BY HAND. **The `fleet-tick.mjs` number still
|
|
1275
|
-
excludes it**: nothing in its filter distinguishes an inherited PR from this
|
|
1276
|
-
run's own, since a PR closing no issue fails the closing-issue test either
|
|
1277
|
-
way — folding one in cannot reach the count. So the by-hand judgement and
|
|
1278
|
-
the script's output differ here, and such a PR's review is dispatched by
|
|
1279
|
-
hand.
|
|
1280
|
-
- **In flight** — a ticket between its Claim and its PR's merge: an implementer
|
|
1281
|
-
live or owed a replacement on it, or an open PR closing it. A PR closing
|
|
1282
|
-
nothing is never in flight, and a ticket whose newest implementer settled
|
|
1283
|
-
`blocked` is not either. The tick's `n`; the implementer row's counts read it
|
|
1284
|
-
as `implementers=<i> prs=<p>`, n being i + p.
|
|
1285
|
-
- **In-flight bound** — the most tickets a run lets be In flight at once, fixed
|
|
1286
|
-
for the run, set by `/run-team`'s one argument. Reaching it holds every Pull
|
|
1287
|
-
until a merge brings the count below it; reviewers, finishers and the merge
|
|
1288
|
-
bot never slow for it. The tick's `B`.
|
|
1289
|
-
|
|
1290
|
-
**Default: In-flight bound 5, fixed for the run.** See references/pull.md.
|
|
1291
|
-
|
|
1292
|
-
**The review backlog never gates, and the merge-queue depth is still no
|
|
1293
|
-
signal.** The only gate on a Pull is the In-flight count. A deep backlog is a
|
|
1294
|
-
`DISPATCH review` on the same tick, never a reason to idle an implementer.
|
|
1295
|
-
For the merge queue, see references/pull.md.
|
|
1296
|
-
|
|
1297
|
-
**Reconcile, do not wait for an event.** With the shortlist empty the table
|
|
1298
|
-
below governs — refresh, and never Pull a ticket the shortlist does not hold.
|
|
1299
|
-
See references/pull.md.
|
|
1300
|
-
|
|
1301
|
-
**Do not re-derive this by hand — `fleet-tick.mjs` computes it.** One invocation
|
|
1302
|
-
prints per-role `actual/target` and an explicit ACTION with the backlog gate
|
|
1303
|
-
above and every row of the table below already applied; every wake
|
|
1304
|
-
ends in it. The deficit is then *computed, not remembered*, which is
|
|
1305
|
-
the whole point: a table you must remember to consult is one you will not
|
|
1306
|
-
consult under a merge-side event storm, and that is how implementers reached
|
|
1307
|
-
0/target with ~57 `ready-for-agent` in supply while nobody
|
|
1308
|
-
noticed (#3). What follows stays here as the explanation of what the script decides —
|
|
1309
|
-
never as a second, hand-run copy of it. The table's shortlist counts no head
|
|
1310
|
-
whose Pull ended this run, unless on a lifted exclusion. A refresh at unclaimed < B leaves `unclaimed=` at
|
|
1311
|
-
that count, so `SUGGEST /triage` can print it above 0.
|
|
1312
|
-
|
|
1313
|
-
| shortlist (unclaimed) | implementer row prints |
|
|
1314
|
-
|---|---|
|
|
1315
|
-
| ≥ 1 | `PULL #N …`, one head per free slot — a Pull each (phase 1) |
|
|
1316
|
-
| below the In-flight bound, missing or empty | the tick refreshes first — `REFRESHED shortlist: n entries; k lifted` — and Pulls from what it found |
|
|
1317
|
-
| 0 after that refresh | `SUGGEST /triage, hold idle` |
|
|
1318
|
-
|
|
1319
|
-
### Specs, the refresh bound and the holds
|
|
1320
|
-
|
|
1321
|
-
Whatever the row prints, a `specs-dropped=#<N> (…)` at the end of its counts
|
|
1322
|
-
names the tickets the to-spec filter kept out of the shortlist — specs
|
|
1323
|
-
awaiting to-tickets, so an empty shortlist carrying one is not "no work".
|
|
1324
|
-
|
|
1325
|
-
The refresh runs at unclaimed < B and, with every other refresh trigger, never
|
|
1326
|
-
while the bound holds: a refresh then cannot feed a Pull, and the first tick
|
|
1327
|
-
back under the bound refreshes and Pulls in the same tick. Unclaimed there
|
|
1328
|
-
counts no head whose Pull ended this run, unless on a lifted exclusion.
|
|
1329
|
-
|
|
1330
|
-
Four holds outrank every row: `HOLD (draining)` once `ledger.mjs drain` has
|
|
1331
|
-
recorded the drain, `HOLD (tier mismatch impl-<N>)` until a replacement is
|
|
1332
|
-
dispatched at the right tier, `HOLD (tier unchecked impl-<N>)` until
|
|
1333
|
-
`tier-check.mjs` has written its verdict on the newest implementer —
|
|
1334
|
-
`tier-ok=`, `tier-mismatch=` or `tier-unverifiable=` — and
|
|
1335
|
-
`HOLD (in-flight <n>/<B>)` when n tickets are between Claim and merge and
|
|
1336
|
-
n ≥ B — refreshing to enable a Pull you are holding buys nothing.
|
|
1337
|
-
|
|
1338
|
-
`HOLD (in-flight <n>/<B>)` ranks last of the four: the other three print in
|
|
1339
|
-
its place. Its detail is the implementer row's counts, `implementers=<i>
|
|
1340
|
-
prs=<p> unclaimed=<k> supply=<s>`. It is quiet — a merge brings n below B and
|
|
1341
|
-
the next tick Pulls — except for a ticket whose newest implementer settled
|
|
1342
|
-
`killed` or `tier-mismatch`: it counts as In flight with no PR that could
|
|
1343
|
-
merge, so the row asks for the replacement's dispatch and names it in the
|
|
1344
|
-
detail. The reviewer row reads `<units>/<B>`, its live review units against
|
|
1345
|
-
the same bound, and never holds on it.
|
|
1346
|
-
|
|
1347
|
-
A main checkout that is not `clean` against its Phase 0 baseline outranks all
|
|
1348
|
-
of them, and every dispatching row besides: `HOLD (main checkout dirty)`,
|
|
1349
|
-
`HOLD (main checkout unknown)` or `HOLD (main checkout no baseline)` on the
|
|
1350
|
-
implementer, reviewer and merge-bot rows alike, beside the `MAIN-CHECKOUT-*`
|
|
1351
|
-
line that says why.
|
|
1352
|
-
|
|
1353
|
-
`/triage` is user-invoked only — suggest, never run. The suggestion is a report,
|
|
1354
|
-
not a blocking prompt. Counts come from cheap `gh issue list --search`, no bodies.
|
|
1355
|
-
A starved implementer queue never stalls the review or merge side.
|
|
1356
|
-
|
|
1357
|
-
## Tier outcomes guard
|
|
1358
|
-
|
|
1359
|
-
This guard is done when you have run `tier-outcomes.mjs append` once for each PR whose review you rule; never conclude a tier result inside one run.
|
|
1360
|
-
|
|
1361
|
-
**Guard: accumulate per PR, never conclude inside one run.** The unit is the PR —
|
|
1362
|
-
supply is one Pull per free slot, so there are no implementer batches. **Append one row to
|
|
1363
|
-
`docs/metrics/tier-outcomes.tsv` when you rule each PR's review, with
|
|
1364
|
-
`~/.fleet/bin/fleet-run tier-outcomes.mjs append <pr> --closed-own-ticket yes|no --minted-false-claim yes|no --note "<text>"`,
|
|
1365
|
-
never by hand** (that file's header carries the column meanings). The script
|
|
1366
|
-
fills `run_date`, `pr`, `ticket` and `tier` itself — `tier` from what actually
|
|
1367
|
-
ran, off the implementer's `tier-ok=` ledger verdict or else its one
|
|
1368
|
-
member-outcomes row (a `tier-unverifiable=` member has no ledger verdict, so
|
|
1369
|
-
its one member-outcomes row decides), and BLANK with a WARNING naming why
|
|
1370
|
-
when neither settles
|
|
1371
|
-
it; never type a tier in over that. A PR that already has a row is left
|
|
1372
|
-
untouched, so re-running it is safe. That append is the whole duty.
|
|
1373
|
-
|
|
1374
|
-
The row's last four fields are the ticket's difficulty, and they are what lets a
|
|
1375
|
-
tier comparison condition on the thing that swamps it. `sizing` is the
|
|
1376
|
-
**member's** own `light`/`heavy` verdict from its dispatched `sizing-a-ticket`
|
|
1377
|
-
run, which `append` reads itself off the member's report file
|
|
1378
|
-
(`<scratch>/reports/impl-<ticket>[-x].json`, its `sizing.verdict`, the highest
|
|
1379
|
-
retry letter's when there are several), so you pass no `--sizing`; the member
|
|
1380
|
-
also puts it in the PR body's `Sizing:` line, with the signal it turned on;
|
|
1381
|
-
`profile`, `loc` and `files` all come from `diff-stats.mjs` over the merged
|
|
1382
|
-
diff. **Phase 0 does not size anything** — it shortlists, a Pull claims, and
|
|
1383
|
-
the sizing run happens inside the member after both, which is why the verdict
|
|
1384
|
-
has to travel in the member's report rather than being something you already hold.
|
|
1385
|
-
|
|
1386
|
-
**A verdict is a measurement only if it post-dates the run that produced it.** See references/reviewers.md.
|
|
1387
|
-
|
|
1388
|
-
The member-facts scrape, the drain of the pending ticket-features rows and the
|
|
1389
|
-
commit of the metrics files are steps of `closeout.mjs finish`, which **End of
|
|
1390
|
-
run** (**What a wake owes beyond its call**) drives. See references/close-out.md.
|
|
1391
|
-
|
|
1392
|
-
**Why not decide inside one run.** A run holds 2-3 implementer PRs, and ticket
|
|
1393
|
-
difficulty swamps the tier effect — a gojq parity harness and a two-statement
|
|
1394
|
-
shell reorder are not comparable units. Finding-counts are not comparable either:
|
|
1395
|
-
`selectDimensions` trims the fan-out by diff profile, so one PR fields 29 agents
|
|
1396
|
-
over six dimensions and its sibling fields 8 over three. And the fleet is not
|
|
1397
|
-
stationary — this prompt gets edited mid-run when a defect earns it. Hence a
|
|
1398
|
-
binary outcome per PR, accumulating, rather than a per-run verdict.
|
|
1399
|
-
|
|
1400
|
-
**Why the rows this guard fired on could not answer the tier question, and this
|
|
1401
|
-
is the load-bearing part.** Until the 2026-08-16 revert, `class` and `tier` were
|
|
1402
|
-
perfectly confounded: routine always ran `sonnet`, correction always ran top
|
|
1403
|
-
tier. So the comparison the file invites — routine-at-sonnet against
|
|
1404
|
-
correction-at-top-tier — measures **class, not tier**, because those classes fail
|
|
1405
|
-
in different ways by construction: corrections ship false claims in prose,
|
|
1406
|
-
routines ship incomplete or regressing code. A run that "mixes both" does not fix
|
|
1407
|
-
it. **Only a same-class comparison across tiers is informative**, and the old
|
|
1408
|
-
rule could not produce one, since no routine ticket ever ran at top tier.
|
|
1409
|
-
|
|
1410
|
-
**That last sentence is no longer true, and this is the part to re-read.** Since
|
|
1411
|
-
the revert every routine ticket runs at top tier, so the file now holds 55
|
|
1412
|
-
`routine`/`opus` rows against 11 `routine`/`sonnet` (as of 2026-08-28, 103 rows
|
|
1413
|
-
— recount before citing). The same-class comparison the paragraph above calls
|
|
1414
|
-
the only informative one therefore EXISTS now. It is still not clean: the two
|
|
1415
|
-
groups are split almost entirely by calendar date, so it measures prompt
|
|
1416
|
-
evolution at least as much as tier. The counter-evidence paragraph earlier in
|
|
1417
|
-
this section carries the split and the three rows that cut against it. Recount
|
|
1418
|
-
both, and every other figure in this section, with:
|
|
1419
|
-
|
|
1420
|
-
```bash
|
|
1421
|
-
grep -vc '^#' docs/metrics/tier-outcomes.tsv
|
|
1422
|
-
awk -F'\t' '!/^#/ && $4=="routine" {n++; d[$1]=1; if($6=="no") no++} \
|
|
1423
|
-
END{print n, length(d), no+0}' docs/metrics/tier-outcomes.tsv
|
|
1424
|
-
awk -F'\t' '!/^#/ && $4=="routine" {t[$5]++; if($6=="no") f[$5]++} \
|
|
1425
|
-
END{for(k in t) print k, t[k], f[k]+0}' docs/metrics/tier-outcomes.tsv
|
|
1426
|
-
```
|
|
1427
|
-
|
|
1428
|
-
**These rows are the historical corpus, and nothing appended to them fixes the
|
|
1429
|
-
confound.** What fixes it is the exploration draw in the dispatch rule above:
|
|
1430
|
-
one implementer in every five — every one, during burn-in — runs at a drawn
|
|
1431
|
-
cell beside the policy cell's, against the same prompts on the same day, so
|
|
1432
|
-
the comparison stops depending on which tier history happened to leave in
|
|
1433
|
-
which week. Read each cell's comparisons, not the whole-file split, once there
|
|
1434
|
-
are enough of them.
|
|
1435
|
-
|
|
1436
|
-
**So read what the guard actually established: routine tickets sometimes fail to
|
|
1437
|
-
close their own ticket. Not that `sonnet` caused it.** The revert is the
|
|
1438
|
-
pre-committed rule being honoured, not a measurement. Restoring a cheap tier is
|
|
1439
|
-
still the maintainer's call and still a change to the dispatch rule — but the
|
|
1440
|
-
deliberate control it used to require is no longer something anyone has to
|
|
1441
|
-
authorize one ticket at a time: the exploration draw above produces one in
|
|
1442
|
-
every five Pulls by construction. **Do not read a cell early.** A cell's
|
|
1443
|
-
comparison is one session holding an admissible row at that cell — its tier
|
|
1444
|
-
check passed and its resolved effort is the cell's level — and one at
|
|
1445
|
-
`slow-high` whose resolved model and effort differ. Count them per cell, never
|
|
1446
|
-
pooled across cells, and stop until
|
|
1447
|
-
there are at least ten of them across five or more distinct `run_date`s; below
|
|
1448
|
-
that, a comparison count is a number, not evidence, and the last guard fired
|
|
1449
|
-
with n=1 on the control side. **Report the count the per-cell readout prints,
|
|
1450
|
-
never one from any other query:** `~/.fleet/bin/fleet-run cell-readout.mjs`
|
|
1451
|
-
prints `<cell> <comparisons> <run_dates> <resolved models>` for each cell past
|
|
1452
|
-
that floor and a cell below it only as a count on stderr; a `mixed (…)` models
|
|
1453
|
-
column means the cell's history spans more than one model behind its role.
|
|
1454
|
-
The pre-cell pair query counted pairs that are no cell's comparisons, and the
|
|
1455
|
-
query before that one counted every session whose implementers merely
|
|
1456
|
-
differed, so it cleared this floor by an order of magnitude while the
|
|
1457
|
-
controlled comparison did not exist yet.
|
|
1458
|
-
|
|
1459
1290
|
## Why the implementer body carries what it does
|
|
1460
1291
|
|
|
1461
1292
|
Read this before you edit any `fleet-implementer-<cell>` file, and stop editing when every cell's body is byte-identical again.
|
|
1462
1293
|
|
|
1463
1294
|
Why the agent body carries what it does — read this before editing any `fleet-implementer-<cell>` file, and keep every cell's body byte-identical. See references/pull.md.
|
|
1464
1295
|
|
|
1296
|
+
- **Every implementer body carries the claim discipline, because tickets that restate facts ship new wrong claims** — inherited from the ticket, and minted in prose nobody asked for. See references/correction-tickets.md.
|
|
1297
|
+
- **The settling command for "which files read X" must never be a literal-path
|
|
1298
|
+
grep.** Replace the file with `MUTATED` in a throwaway copy, run the suite, and read off
|
|
1299
|
+
which suites red: that answers which ones **depend on its contents**, which is
|
|
1300
|
+
the question a coverage claim actually needs, and it returns a different set
|
|
1301
|
+
from any spelling of the grep. See references/correction-tickets.md.
|
|
1302
|
+
- **A settling command over literal text uses `grep -F`, and its zero counts only after the same command finds a line known to match.** See references/correction-tickets.md.
|
|
1303
|
+
|
|
1465
1304
|
**Prose-first** and **wrongly-REFUSE** are not padding — they are the case
|
|
1466
1305
|
which shipped with **enumerate-and-declare** already in its prompt. It missed a
|
|
1467
1306
|
shape its own ticket named in passing, because it enumerated from the mechanism
|
|
@@ -1578,10 +1417,6 @@ review-due. A
|
|
|
1578
1417
|
runner member that is killed rather than failed follows **Failure
|
|
1579
1418
|
handling** (fresh name, inherited state stated).
|
|
1580
1419
|
|
|
1581
|
-
## Guards
|
|
1582
|
-
|
|
1583
|
-
Each guard here is a check to run before the step it guards: run it, and where it fails, stop and report rather than go on.
|
|
1584
|
-
|
|
1585
1420
|
**Verify every reported SHA.** `~/.fleet/bin/fleet-run verify-sha.sh
|
|
1586
1421
|
<branch> <sha>` before enqueueing — a member can commit in a nested worktree,
|
|
1587
1422
|
leaving the SHA on a stray branch while its report reads normally. Exit codes as
|
|
@@ -1597,14 +1432,7 @@ ticket over a failure a re-run would have cleared.
|
|
|
1597
1432
|
|
|
1598
1433
|
**Never `--delete-branch` — the merge bot deletes the head branch itself.**
|
|
1599
1434
|
`gh pr merge <n> --merge` alone: the flag's local cleanup errors on a `main`
|
|
1600
|
-
held by another worktree, or strands the feature worktree on `main`.
|
|
1601
|
-
merge, `delete-merged-branch.sh <pr>` deletes the branch from `origin` and reads
|
|
1602
|
-
the deletion back; `reap.sh` takes the `[gone]` local branch and its worktree.
|
|
1603
|
-
No repo setting is relied on to do it. A branch another open PR still
|
|
1604
|
-
uses as its head or base is kept instead — `branch-kept-#<that PR>` in the bot's
|
|
1605
|
-
report, a deliberate keep and not a failure.
|
|
1606
|
-
The branch-delete step also releases the claim label: it drops `in-progress` from
|
|
1607
|
-
every issue the PR closes.
|
|
1435
|
+
held by another worktree, or strands the feature worktree on `main`.
|
|
1608
1436
|
|
|
1609
1437
|
**Never force a rebase to start.** No `git clean`, `git checkout .`,
|
|
1610
1438
|
`git reset --hard`, `git stash`. Uncommitted changes may exist nowhere else.
|
|
@@ -1614,14 +1442,6 @@ empty answer here and licenses the rebase over work this check exists to
|
|
|
1614
1442
|
protect. Stashing empties it either way, so that check and
|
|
1615
1443
|
`no-undo-audit.sh` both go quiet on work nothing else holds.
|
|
1616
1444
|
|
|
1617
|
-
**Cross-check what members report about their environment.** Wrong often enough
|
|
1618
|
-
to matter, and a confident wrong report from a reviewer flips a verdict.
|
|
1619
|
-
|
|
1620
|
-
**Distrust negative claims hardest.** "Nothing else references this", "the sweep
|
|
1621
|
-
is clean" — most likely false, least likely checked: a grep that found nothing
|
|
1622
|
-
looks like a grep never run. Make members state their search scope. Negative claim
|
|
1623
|
-
vs specific finding with paths → paths win.
|
|
1624
|
-
|
|
1625
1445
|
**Members share one filesystem, one docker stack and one process table**, and the
|
|
1626
1446
|
failures arrive as *wrong findings*, not errors:
|
|
1627
1447
|
|
|
@@ -1640,70 +1460,18 @@ failures arrive as *wrong findings*, not errors:
|
|
|
1640
1460
|
and the controller re-checks any measurement taken in the window.
|
|
1641
1461
|
|
|
1642
1462
|
**Do not guess the victim — the blast radius is the machine, not the Pull.**
|
|
1643
|
-
|
|
1644
|
-
certainly `impl-<N>`" and told the maintainer so; the named member then proved
|
|
1645
|
-
it was not the victim (it had never invoked those files standalone, and its
|
|
1646
|
-
mutation baselines post-dated the window). Idle members of *previous* runs,
|
|
1647
|
-
other omp sessions on the same machine, and the maintainer's own shell are
|
|
1648
|
-
all `pkill -f` targets and none of them appear in your ledger. Warn every live
|
|
1463
|
+
Warn every live
|
|
1649
1464
|
member, record the incident as unattributed, and re-check measurements by
|
|
1650
|
-
timestamp rather than by who you think was running.
|
|
1465
|
+
timestamp rather than by who you think was running. See references/isolation.md.
|
|
1651
1466
|
|
|
1652
1467
|
- **A warning acted on silently is indistinguishable from one that never
|
|
1653
|
-
arrived.**
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
round trip asking whether its own outbox was lossy. So the briefs say that
|
|
1657
|
-
**confirmation state includes warnings received and acted on, even
|
|
1658
|
-
when the outcome is no change** — one line, in the report the member already
|
|
1659
|
-
owes. That is the cheap half of the *never read silence as assent* rule, paid
|
|
1660
|
-
by the member rather than by the controller's guesswork.
|
|
1661
|
-
|
|
1662
|
-
- **Specialist tree isolation is `review-and-fix.md`'s job — do not restate it.**
|
|
1663
|
-
It owns the object-store rule, the two-tree split, snapshot provisioning, and
|
|
1664
|
-
which suites a snapshot cannot validly run. Your only duty is to *not*
|
|
1665
|
-
contradict it.
|
|
1666
|
-
- **Filesystem isolation is not stack isolation.** A private copy of the
|
|
1667
|
-
tree and a test command solve different problems; the compose project
|
|
1668
|
-
name comes from the environment, not the working directory, so three
|
|
1669
|
-
agents on three snapshots still collide on one postgres. "I'm on my own
|
|
1670
|
-
copy" is exactly the intuition that skips the command — say both, every
|
|
1671
|
-
time. Which command depends on the audience: a member in a worktree
|
|
1672
|
-
uses `./agent-test`; a specialist on a snapshot does not, and takes the
|
|
1673
|
-
one `review-and-fix.md` hands out. Which runner the worktree holds
|
|
1674
|
-
decides why: the runner a claim writes is untracked, so a `git archive`
|
|
1675
|
-
snapshot never carries it; one the repository tracks does ride along,
|
|
1676
|
-
but no claim exported ports into it — its isolation is whatever that
|
|
1677
|
-
repository built, not one triple per snapshot. See
|
|
1678
|
-
references/isolation.md.
|
|
1468
|
+
arrived.** See references/isolation.md.
|
|
1469
|
+
- **Specialist tree isolation is `review-and-fix.md`'s job — do not restate it.** See references/isolation.md.
|
|
1470
|
+
- **Filesystem isolation is not stack isolation.** See references/isolation.md.
|
|
1679
1471
|
- **Scratchpad paths need two levels — the member's own partition, then one
|
|
1680
|
-
directory per child it dispatches — and nothing outside them.**
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
runner is handed the scratch root, never that partition; any member that
|
|
1684
|
-
dispatches a child writes an absolute directory under its own partition into
|
|
1685
|
-
that child's prompt, one per child and never shared, and a child never
|
|
1686
|
-
derives its own. Finding ids restart at 1 every review, so two fix-appliers
|
|
1687
|
-
on different PRs both reach for `unv1`; one
|
|
1688
|
-
agent overwrote a sibling's `package.json`, and a probe built a git repo at
|
|
1689
|
-
the *checkout root*. Read from the object store at a pinned ref, write only
|
|
1690
|
-
under your own path. See references/isolation.md.
|
|
1691
|
-
- **IDE/harness diagnostics attribute by bare filename, with no path.** **Never
|
|
1692
|
-
relay a diagnostic without reproducing it in that member's specific worktree**
|
|
1693
|
-
(re-run the check that raised it from there): probe copies carry the real
|
|
1694
|
-
tree's filenames, so a sibling's throwaway mutation reads exactly like a live
|
|
1695
|
-
worktree's error.
|
|
1696
|
-
See references/isolation.md.
|
|
1697
|
-
- **Every implementer body carries the claim discipline, because tickets that restate facts ship new wrong claims** — inherited from the ticket, and minted in prose nobody asked for. See references/correction-tickets.md.
|
|
1698
|
-
- **The settling command for "which files read X" must never be a literal-path
|
|
1699
|
-
grep.** Replace the file with `MUTATED` in a throwaway copy, run the suite, and read off
|
|
1700
|
-
which suites red: that answers which ones **depend on its contents**, which is
|
|
1701
|
-
the question a coverage claim actually needs, and it returns a different set
|
|
1702
|
-
from any spelling of the grep. See references/correction-tickets.md.
|
|
1703
|
-
- **A settling command over literal text uses `grep -F`, and its zero counts only after the same command finds a line known to match.** See references/correction-tickets.md.
|
|
1704
|
-
|
|
1705
|
-
Suspect a neighbour before a member's own diff — for unexplained failures, and
|
|
1706
|
-
equally for any **finding** that came from reading source.
|
|
1472
|
+
directory per child it dispatches — and nothing outside them.** See references/isolation.md.
|
|
1473
|
+
- **Never relay a diagnostic without reproducing it in that member's specific worktree**
|
|
1474
|
+
(re-run the check that raised it from there). See references/isolation.md.
|
|
1707
1475
|
|
|
1708
1476
|
## Red flags
|
|
1709
1477
|
|
|
@@ -1752,3 +1520,15 @@ One running table, updated as events land:
|
|
|
1752
1520
|
```
|
|
1753
1521
|
|
|
1754
1522
|
Plus a queue-depth line: shortlist, supply, whether triage was suggested.
|
|
1523
|
+
|
|
1524
|
+
**Do not read a cell early.** A cell's
|
|
1525
|
+
comparison is one session holding an admissible row at that cell — its tier
|
|
1526
|
+
check passed and its resolved effort is the cell's level — and one at
|
|
1527
|
+
`slow-high` whose resolved model and effort differ. Count them per cell, never
|
|
1528
|
+
pooled across cells, and stop until
|
|
1529
|
+
there are at least ten of them across five or more distinct `run_date`s; below
|
|
1530
|
+
that, a comparison count is a number, not evidence. **Report the count the per-cell readout prints,
|
|
1531
|
+
never one from any other query:** `~/.fleet/bin/fleet-run cell-readout.mjs`
|
|
1532
|
+
prints `<cell> <comparisons> <run_dates> <resolved models>` for each cell past
|
|
1533
|
+
that floor and a cell below it only as a count on stderr; a `mixed (…)` models
|
|
1534
|
+
column means the cell's history spans more than one model behind its role. See references/pull.md.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Isolation: filesystem vs stack
|
|
2
2
|
|
|
3
|
-
Why isolation envelope file not briefing, why private filesystem not private stack. Assertions these justify live in references/pull.md Claiming section and SKILL.md
|
|
3
|
+
Why isolation envelope file not briefing, why private filesystem not private stack. Assertions these justify live in references/pull.md Claiming section and SKILL.md Failure handling section; evidence here.
|
|
4
4
|
|
|
5
5
|
## Materialize the isolation envelope as a file, not a briefing
|
|
6
6
|
|
|
@@ -262,3 +262,29 @@ get is not yours to choose — members are briefed on `./agent-test` with the
|
|
|
262
262
|
arguments the Test entrypoint takes, and the runner hands them on exactly as
|
|
263
263
|
its caller's shell expanded them. Clearing your own leftover process needs its
|
|
264
264
|
PID, not a pattern.
|
|
265
|
+
|
|
266
|
+
## Do not guess the victim — the blast radius is the machine, not the Pull
|
|
267
|
+
|
|
268
|
+
In the `pkill -f` incident "A pattern kill reaches siblings" measures, the controller reasoned from dispatch scope to "almost
|
|
269
|
+
certainly `impl-<N>`" and told the maintainer so; the named member then proved
|
|
270
|
+
it was not the victim (it had never invoked those files standalone, and its
|
|
271
|
+
mutation baselines post-dated the window). Idle members of *previous* runs,
|
|
272
|
+
other omp sessions on the same machine, and the maintainer's own shell are
|
|
273
|
+
all `pkill -f` targets and none of them appear in your ledger.
|
|
274
|
+
|
|
275
|
+
## A warning acted on silently is indistinguishable from one that never arrived
|
|
276
|
+
|
|
277
|
+
The same `pkill -f` incident: the controller's warning DID reach the member,
|
|
278
|
+
which re-ran, found nothing changed, and said nothing — correctly reading
|
|
279
|
+
"send once, never re-send" as covering it. The controller then had to spend a
|
|
280
|
+
round trip asking whether its own outbox was lossy. So the briefs say that
|
|
281
|
+
**confirmation state includes warnings received and acted on, even
|
|
282
|
+
when the outcome is no change** — one line, in the report the member already
|
|
283
|
+
owes. That is the cheap half of the *never read silence as assent* rule, paid
|
|
284
|
+
by the member rather than by the controller's guesswork.
|
|
285
|
+
|
|
286
|
+
## Specialist tree isolation is `review-and-fix.md`'s job
|
|
287
|
+
|
|
288
|
+
It owns the object-store rule, the two-tree split, snapshot provisioning, and
|
|
289
|
+
which suites a snapshot cannot validly run. Your only duty is to *not*
|
|
290
|
+
contradict it.
|
|
@@ -426,6 +426,71 @@ is not enough either: the two rows must actually have RUN a different model or
|
|
|
426
426
|
effort, because a deliberate dispatch whose two sides resolve to the same model
|
|
427
427
|
(a `modelRoles` override, measured on omp 2026-09-12) controls nothing.
|
|
428
428
|
|
|
429
|
+
## Accumulate per PR, never conclude a tier result inside one run
|
|
430
|
+
|
|
431
|
+
The unit is the PR —
|
|
432
|
+
supply is one Pull per free slot, so there are no implementer batches. The
|
|
433
|
+
guard this section speaks of is SKILL.md's **Guard: accumulate per PR, never
|
|
434
|
+
conclude inside one run**, under **Reading a review result**.
|
|
435
|
+
|
|
436
|
+
**Why not decide inside one run.** A run holds 2-3 implementer PRs, and ticket
|
|
437
|
+
difficulty swamps the tier effect — a gojq parity harness and a two-statement
|
|
438
|
+
shell reorder are not comparable units. Finding-counts are not comparable either:
|
|
439
|
+
`selectDimensions` trims the fan-out by diff profile, so one PR fields 29 agents
|
|
440
|
+
over six dimensions and its sibling fields 8 over three. And the fleet is not
|
|
441
|
+
stationary — this prompt gets edited mid-run when a defect earns it. Hence a
|
|
442
|
+
binary outcome per PR, accumulating, rather than a per-run verdict.
|
|
443
|
+
|
|
444
|
+
**Why the rows this guard fired on could not answer the tier question, and this
|
|
445
|
+
is the load-bearing part.** Until the 2026-08-16 revert, `class` and `tier` were
|
|
446
|
+
perfectly confounded: routine always ran `sonnet`, correction always ran top
|
|
447
|
+
tier. So the comparison the file invites — routine-at-sonnet against
|
|
448
|
+
correction-at-top-tier — measures **class, not tier**, because those classes fail
|
|
449
|
+
in different ways by construction: corrections ship false claims in prose,
|
|
450
|
+
routines ship incomplete or regressing code. A run that "mixes both" does not fix
|
|
451
|
+
it. **Only a same-class comparison across tiers is informative**, and the old
|
|
452
|
+
rule could not produce one, since no routine ticket ever ran at top tier.
|
|
453
|
+
|
|
454
|
+
**That last sentence is no longer true, and this is the part to re-read.** Since
|
|
455
|
+
the revert every routine ticket runs at top tier, so the file now holds 55
|
|
456
|
+
`routine`/`opus` rows against 11 `routine`/`sonnet` (as of 2026-08-28, 103 rows
|
|
457
|
+
— recount before citing). The same-class comparison the paragraph above calls
|
|
458
|
+
the only informative one therefore EXISTS now. It is still not clean: the two
|
|
459
|
+
groups are split almost entirely by calendar date, so it measures prompt
|
|
460
|
+
evolution at least as much as tier. Recount
|
|
461
|
+
both, and every other figure in this section, with:
|
|
462
|
+
|
|
463
|
+
```bash
|
|
464
|
+
grep -vc '^#' docs/metrics/tier-outcomes.tsv
|
|
465
|
+
awk -F'\t' '!/^#/ && $4=="routine" {n++; d[$1]=1; if($6=="no") no++} \
|
|
466
|
+
END{print n, length(d), no+0}' docs/metrics/tier-outcomes.tsv
|
|
467
|
+
awk -F'\t' '!/^#/ && $4=="routine" {t[$5]++; if($6=="no") f[$5]++} \
|
|
468
|
+
END{for(k in t) print k, t[k], f[k]+0}' docs/metrics/tier-outcomes.tsv
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
**These rows are the historical corpus, and nothing appended to them fixes the
|
|
472
|
+
confound.** What fixes it is the exploration draw in the dispatch rule above:
|
|
473
|
+
one implementer in every five — every one, during burn-in — runs at a drawn
|
|
474
|
+
cell beside the policy cell's, against the same prompts on the same day, so
|
|
475
|
+
the comparison stops depending on which tier history happened to leave in
|
|
476
|
+
which week. Read each cell's comparisons, not the whole-file split, once there
|
|
477
|
+
are enough of them.
|
|
478
|
+
|
|
479
|
+
**So read what the guard actually established: routine tickets sometimes fail to
|
|
480
|
+
close their own ticket. Not that `sonnet` caused it.** The revert is the
|
|
481
|
+
pre-committed rule being honoured, not a measurement. Restoring a cheap tier is
|
|
482
|
+
still the maintainer's call and still a change to the dispatch rule — but the
|
|
483
|
+
deliberate control it used to require is no longer something anyone has to
|
|
484
|
+
authorize one ticket at a time: the exploration draw above produces one in
|
|
485
|
+
every five Pulls by construction.
|
|
486
|
+
|
|
487
|
+
The last guard fired with n=1 on the control side. The pre-cell pair query
|
|
488
|
+
counted pairs that are no cell's comparisons, and the query before that one
|
|
489
|
+
counted every session whose implementers merely differed, so it cleared the
|
|
490
|
+
cell floor SKILL.md's **Report** states — at least ten comparisons across five
|
|
491
|
+
or more distinct `run_date`s — by an order of magnitude while the controlled
|
|
492
|
+
comparison did not exist yet.
|
|
493
|
+
|
|
429
494
|
## Why the implementer body carries enumerate-and-declare
|
|
430
495
|
|
|
431
496
|
Why the agent body carries what it does — read this before editing any
|
|
@@ -27,6 +27,10 @@ in-between width cannot be told apart from a shifted one. The `note` field is
|
|
|
27
27
|
free text and sits before those four, so the script refuses a tab or newline in
|
|
28
28
|
it: one tab would shift all four for that row alone.
|
|
29
29
|
|
|
30
|
+
**Phase 0 does not size anything** — it shortlists, a Pull claims, and
|
|
31
|
+
the sizing run happens inside the member after both, which is why the verdict
|
|
32
|
+
has to travel in the member's report rather than being something you already hold.
|
|
33
|
+
|
|
30
34
|
## Know the trim before you rely on it
|
|
31
35
|
|
|
32
36
|
**Know the trim before you rely on it — it is wider than `docsOnly` suggests.**
|
|
@@ -135,3 +139,12 @@ reviewed and is not.
|
|
|
135
139
|
## The review's scratch is the scratch root, not its partition
|
|
136
140
|
|
|
137
141
|
**`scratch` is the scratch root itself, the absolute path `scratch-root.mjs` prints, never the review side's `<scratch>/pr<N>` partition:** the review creates `pr<N>/` under it, so a `pr<N>` passed in nests every run root at `pr<N>/pr<N>/`, and the review refuses a `scratch` whose last component is `pr` plus digits before dispatching anything.
|
|
142
|
+
|
|
143
|
+
## Cross-check what members report, and distrust negative claims hardest
|
|
144
|
+
|
|
145
|
+
Wrong often enough
|
|
146
|
+
to matter, and a confident wrong report from a reviewer flips a verdict.
|
|
147
|
+
|
|
148
|
+
"Nothing else references this", "the sweep
|
|
149
|
+
is clean" — most likely false, least likely checked: a grep that found nothing
|
|
150
|
+
looks like a grep never run.
|
|
@@ -14,7 +14,7 @@ The full text of each row `fleet-tick.mjs` prints and what it asks of the contro
|
|
|
14
14
|
lifted), the implementer row's `unclaimed=` prints that same
|
|
15
15
|
`<u>`, not the refreshed file's count.
|
|
16
16
|
- `SUGGEST /triage, hold idle` — nothing is admissible after the refresh.
|
|
17
|
-
Suggest, never run
|
|
17
|
+
Suggest, never run. A head whose Pull already ended in
|
|
18
18
|
this run is not counted toward the refresh, so a shortlist of only such
|
|
19
19
|
heads triggers the refresh before this row prints. It is not printed while the
|
|
20
20
|
refreshed shortlist holds a head whose Pull ended only on an exclusion whose
|
|
@@ -245,3 +245,11 @@ The full text of each row `fleet-tick.mjs` prints and what it asks of the contro
|
|
|
245
245
|
could-not-look (exit 2), never a mismatch. The settle runs neither command,
|
|
246
246
|
and a repository whose Recipe cache is absent or refused has no gate; the
|
|
247
247
|
record is the member's own word, at the trust level of its report.
|
|
248
|
+
|
|
249
|
+
## Read the depth off the tick, never derive it by hand
|
|
250
|
+
|
|
251
|
+
**Do not re-derive this by hand — `fleet-tick.mjs` computes it.** The deficit is then *computed, not remembered*, which is
|
|
252
|
+
the whole point: a table you must remember to consult is one you will not
|
|
253
|
+
consult under a merge-side event storm, and that is how implementers reached
|
|
254
|
+
0/target with ~57 `ready-for-agent` in supply while nobody
|
|
255
|
+
noticed.
|