@feigi/fleet-ctl 3.81.3 → 3.81.5

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feigi/fleet-ctl",
3
- "version": "3.81.3",
3
+ "version": "3.81.5",
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": {
package/scripts/reap.sh CHANGED
@@ -371,10 +371,10 @@ keep() {
371
371
  # at, by two DIFFERENT rules for two DIFFERENT groups. Three call sites below
372
372
  # read `status --porcelain` (`-uall`, or `-unormal --ignored`) and are safe
373
373
  # because git quotes PATHS; a fourth, added after this comment was first
374
- # written, reads `for-each-ref --format='%(refname)
375
- # %(upstream:track)'` and is safe for an unrelated reason — a REFNAME,
376
- # unlike a path, can never contain the byte at all. Nothing in the body
377
- # checks either invariant.
374
+ # written, reads `for-each-ref` with a format that prints only refnames and
375
+ # fixed words, and is safe for an unrelated reason — a REFNAME, unlike a
376
+ # path, can never contain the byte at all, and a fixed word is text git
377
+ # itself prints. Nothing in the body checks either invariant.
378
378
  #
379
379
  # The path-reading three: both halves of git's answer put a control byte in
380
380
  # a path beyond reach of the split, by two DIFFERENT rules — measured on git
@@ -394,13 +394,19 @@ keep() {
394
394
  # 0x02 there either.
395
395
  #
396
396
  # The ref-reading fourth: no PATH-quoting rule is doing the work, because no
397
- # quoting is needed — git refuses to CREATE the ref at all. Measured, git
398
- # 2.50.1 (Apple Git-155): `git branch "$(printf 'a\002b')"` fails outright —
399
- # `fatal: 'a?b' is not a valid branch name` — and so does `git update-ref
400
- # refs/heads/"$(printf 'a\002b')" HEAD` — `refusing to update ref with bad
401
- # name`. `%(refname)` and `%(upstream:track)` can only ever answer with
402
- # bytes that already survived `check-ref-format` on the way in, so a raw
403
- # 0x02 can never reach either field to begin with. A fifth call site joins
397
+ # quoting is needed — every field its format prints is either a validated
398
+ # refname or a fixed word git prints. git refuses to CREATE a ref whose name
399
+ # holds the byte at all. Measured, git 2.50.1 (Apple Git-155): `git branch
400
+ # "$(printf 'a\002b')"` fails outright — `fatal: 'a?b' is not a valid branch
401
+ # name` — and so does `git update-ref refs/heads/"$(printf 'a\002b')" HEAD`
402
+ # — `refusing to update ref with bad name`. `%(refname)` can only ever
403
+ # answer with bytes that already survived `check-ref-format` on the way in.
404
+ # The other two fields are fixed words: the `%(if)%(upstream)` test prints
405
+ # `upstream` or `no-upstream` out of the format itself, and
406
+ # `%(upstream:track)` prints git's own tracking words — `[gone]`, `[ahead N]`
407
+ # and their siblings. `%(upstream)`'s own text is never printed: it is built
408
+ # from the branch.<b>.merge value, which git does not validate, and a raw
409
+ # 0x02 written there reaches it (measured, git 2.50.1). A fifth call site joins
404
410
  # this ref group: `rev-parse --verify refs/heads/<b>`, where
405
411
  # `<b>` is a name the `for-each-ref` call site produced. Its stdout is an
406
412
  # object id in hex, and what it can put on stderr is git's own fixed prose
@@ -416,10 +422,10 @@ keep() {
416
422
  # -uall -z` carries the raw 0x02 straight through, `-z` being the
417
423
  # machine-readable form that drops the quoting, and so does any command
418
424
  # emitting CONTENT rather than paths or refnames (`log --format=%s`, `show
419
- # <rev>:<path>`, both measured). The ref group has no equivalent flag —
420
- # `for-each-ref` cannot be asked to emit an unvalidated refname — so this
421
- # warning is really aimed at the path group and at any THIRD kind of call
422
- # site a future caller might add.
425
+ # <rev>:<path>`, both measured). The ref group stays out of reach only while
426
+ # its format prints no atom built from config, such as `%(upstream)` — so
427
+ # this warning is aimed at the path group, at that format, and at any THIRD
428
+ # kind of call site a future caller might add.
423
429
  #
424
430
  # Left unguarded anyway, deliberately: every call site is shaped
425
431
  # `if ! git_probe …; then keep …`, so a garbled $gp_rc can never come back 0
@@ -980,13 +986,14 @@ EOF
980
986
  #
981
987
  # The [gone] test reads $3 and the no-upstream test reads $2: a space is not
982
988
  # legal in a branch name (measured — git refuses `has space` as invalid), so
983
- # the name is always the whole of $1, and $2 is `upstream=` followed by
984
- # %(upstream)'s ref — exactly `upstream=` when the branch has none. The
985
- # tracking forms that DO carry a space, `[ahead 1]` and its siblings, split so
986
- # that $3 holds `[ahead` — not `[gone]` either way. That layout holds only
987
- # while the upstream ref carries no whitespace: %(upstream) is built from the
988
- # branch.<b>.merge value, which git does not validate, and a space there moves
989
- # the track out of $3 (measured, git 2.50.1).
989
+ # the name is always the whole of $1. $2 is a fixed word the format itself
990
+ # prints — `upstream` when the branch has one, `no-upstream` when it has
991
+ # none — so an unset upstream still fills $2 rather than leaving the
992
+ # whitespace split to drop an empty field. $3 is %(upstream:track). The
993
+ # tracking forms that DO carry a space, `[ahead 1]` and its siblings, split
994
+ # so that $3 holds `[ahead` — not `[gone]` either way. No field prints
995
+ # %(upstream)'s own text, which git builds from the unvalidated
996
+ # branch.<b>.merge value.
990
997
  # A command substitution inside a `for ... in` word list discards its own
991
998
  # exit status entirely, in every shell measured here (bash, dash, macOS
992
999
  # /bin/sh): `for x in $(false); do …; done` completes at the loop's own end,
@@ -1011,10 +1018,7 @@ EOF
1011
1018
  # the same reason — dying here would also abort the second sweep and the
1012
1019
  # final `worktree prune`, neither of which this enumeration failing has
1013
1020
  # anything to do with, over a failure that only defers reaping to a later pass.
1014
- # `upstream=` makes an unset %(upstream) a field of its own. Without it the
1015
- # whitespace split drops the empty field, and `$2` reads the track instead, so
1016
- # `$2=="upstream="` is exactly the no-upstream case and `$3` the [gone] test.
1017
- if ! git_probe for-each-ref --format='%(refname) upstream=%(upstream) %(upstream:track)' refs/heads; then
1021
+ if ! git_probe for-each-ref --format='%(refname) %(if)%(upstream)%(then)upstream%(else)no-upstream%(end) %(upstream:track)' refs/heads; then
1018
1022
  keep "" "could not enumerate [gone] branches — none reaped, and none reported reapable either$(gp_why)"
1019
1023
  gone_branches=""
1020
1024
  no_upstream=""
@@ -1032,7 +1036,7 @@ else
1032
1036
  keep "" "could not enumerate [gone] branches — none reaped, and none reported reapable either"
1033
1037
  gone_branches=""
1034
1038
  fi
1035
- if ! no_upstream=$(printf '%s\n' "$gp_out" | awk '$2=="upstream="{sub(/^refs\/heads\//,"",$1); print $1}'); then
1039
+ if ! no_upstream=$(printf '%s\n' "$gp_out" | awk '$2=="no-upstream"{sub(/^refs\/heads\//,"",$1); print $1}'); then
1036
1040
  keep "" "could not enumerate branches with no upstream — none reported kept"
1037
1041
  no_upstream=""
1038
1042
  fi
@@ -47,14 +47,25 @@ bill a second one that `rate_limit` does not report; the boundary is per route,
47
47
  so `actions/runs/<id>/jobs` is on the reported counter. Every response says
48
48
  `X-Ratelimit-Resource: core`, so only the reset epoch and the used sequence tell
49
49
  the two apart, and the unreported bucket's remaining count is readable only from
50
- the `X-Ratelimit-Remaining` header of a call that bills it. **A second pass gate
51
- therefore probes it too**: one `gh api -i` read of
50
+ the `X-Ratelimit-Remaining` header of a call that bills it. GitHub's REST
51
+ rate-limit documentation does not describe this bucket (it says `core` covers
52
+ "all non-search-related resources in the REST API"), so the gate rests on
53
+ measurement (2026-10-13 and 2026-10-19), not on documentation. **A second pass
54
+ gate therefore probes it too**: one `gh api -i` read of
52
55
  `actions/workflows?per_page=1` per tick, 1 unit of that bucket (measured
53
56
  2026-10-13: its remaining count fell by 1 per call while `rate_limit` stood
54
57
  still, and its reset epoch differed from `rate_limit`'s). A `ci-state` call
55
58
  spends 4 units of it on the common path — one `gh run list` and one `gh run view`
56
59
  cost 2 each (measured the same day) — so it is held to the same `200 + 4 × count`
57
- reserve. It has its own global latch (`hidden_out`) and its DEGRADED and
60
+ reserve. 4 is the most one call spends on this bucket for a repo with at most 100
61
+ workflows: 0 with no CI, 2 with no run on the PR's head, 4 otherwise. The
62
+ dropped-required-jobs path adds only reported-bucket calls, and the workflow-name
63
+ lookup pages 100 workflows per page, so a repo with more pays more per call. The
64
+ bucket is account-wide, not per repository: probes on three unrelated
65
+ repositories drew one countdown and one reset epoch (measured 2026-10-19), so
66
+ another run on the same token, or any `gh run` use, spends it, and its
67
+ DEGRADED line can fire with few open PRs on this repository. It has its own
68
+ global latch (`hidden_out`) and its DEGRADED and
58
69
  RECOVERED lines name it, so a pause on this bucket is not misread as the
59
70
  reported budget running low. An unreadable header is an outage here exactly as a
60
71
  non-numeric `rate_limit` read is. The probe runs only when the reported-bucket