@feigi/fleet-ctl 3.88.6 → 3.88.7
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
|
@@ -8,8 +8,10 @@
|
|
|
8
8
|
// append <pr> --closed-own-ticket yes|no --minted-false-claim yes|no
|
|
9
9
|
// --note <text> [--sizing light|heavy] [--profile <p>] [--loc <n>] [--files <n>]
|
|
10
10
|
// [--scratch <dir>]
|
|
11
|
-
// Fills `run_date` (today's UTC date, the ruling date), `pr`, `ticket` (
|
|
12
|
-
// `gh pr view --json closingIssuesReferences`
|
|
11
|
+
// Fills `run_date` (today's UTC date, the ruling date), `pr`, `ticket` (the
|
|
12
|
+
// PR's one `gh pr view --json closingIssuesReferences` issue; when the PR
|
|
13
|
+
// closes zero or several, the N of its one settled `impl-<N>=PR#<pr>` token
|
|
14
|
+
// in the run ledger), `tier` and, unless
|
|
13
15
|
// `--sizing` names it, `sizing` (see below). Idempotent by
|
|
14
16
|
// PR: a row already present is named and nothing is written, exit 0.
|
|
15
17
|
// check [--live]
|
|
@@ -20,12 +22,14 @@
|
|
|
20
22
|
// lack a member row (nothing from that run was checked). `--live`
|
|
21
23
|
// (a run in progress; CI never passes it) adds a WARNING, never a
|
|
22
24
|
// failure, per PR whose run-ledger row carries `reviewed=` but which has
|
|
23
|
-
// no row here
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
//
|
|
25
|
+
// no row here. A PR whose closing references are not exactly one, and that
|
|
26
|
+
// no settled `impl-` token names, is named in a `note` line and never
|
|
27
|
+
// warned about: `append` has no ticket to key a row on. Where such tokens
|
|
28
|
+
// do name it but `append` would still refuse it, its WARNING says why. A
|
|
29
|
+
// read of that PR that does not answer keeps the warning, after a line
|
|
30
|
+
// naming why the read failed. Both reads of a PR's closing references
|
|
31
|
+
// ignore an ambient GH_REPO and give `gh` 60s. `--ledger <path>` names
|
|
32
|
+
// another ledger than the run's own.
|
|
29
33
|
//
|
|
30
34
|
// `tier` resolution, in order (never tie-broken by `run_date`: the two files'
|
|
31
35
|
// `run_date`s mean different things — this file's header measures 92 of 267
|
|
@@ -451,12 +455,13 @@ function readLedger(ledgerFile, requireFile) {
|
|
|
451
455
|
}
|
|
452
456
|
}
|
|
453
457
|
|
|
454
|
-
//
|
|
455
|
-
//
|
|
456
|
-
//
|
|
457
|
-
//
|
|
458
|
+
// The unique issue numbers of a PR's closingIssuesReferences, in GitHub's
|
|
459
|
+
// order, or an Error naming why they could not be read — a reference with no
|
|
460
|
+
// integer issue number among the reasons. GH_REPO is blanked so an ambient one
|
|
461
|
+
// naming another repository never decides which PR is read; the timeout keeps
|
|
462
|
+
// a hung `gh` from stalling `append` or a close-out's `check --live`.
|
|
458
463
|
const GH_TIMEOUT_MS = 60_000;
|
|
459
|
-
function
|
|
464
|
+
function closingIssueNumbers(pr) {
|
|
460
465
|
let raw;
|
|
461
466
|
try {
|
|
462
467
|
raw = execFileSync("gh", ["pr", "view", String(pr), "--json", "closingIssuesReferences"], {
|
|
@@ -472,21 +477,56 @@ function closingRefs(pr) {
|
|
|
472
477
|
throw new Error(`gh pr view ${pr} returned unreadable JSON: ${e.message}`);
|
|
473
478
|
}
|
|
474
479
|
if (!Array.isArray(refs)) throw new Error(`gh pr view ${pr} returned no closingIssuesReferences array`);
|
|
475
|
-
|
|
480
|
+
const numbers = [...new Set(refs.map((r) => r?.number))];
|
|
481
|
+
const unreadable = numbers.filter((n) => !Number.isInteger(n));
|
|
482
|
+
if (unreadable.length > 0) {
|
|
483
|
+
throw new Error(`gh pr view ${pr} returned a closing reference with no issue number (${unreadable.map((n) => JSON.stringify(n) ?? "undefined").join(", ")})`);
|
|
484
|
+
}
|
|
485
|
+
return numbers;
|
|
476
486
|
}
|
|
477
487
|
|
|
478
|
-
function
|
|
479
|
-
let refs;
|
|
488
|
+
function closingNumbers(pr) {
|
|
480
489
|
try {
|
|
481
|
-
|
|
490
|
+
return closingIssueNumbers(pr);
|
|
482
491
|
} catch (e) {
|
|
483
492
|
die(e.message);
|
|
484
493
|
}
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
// Every settled `impl-<N>=PR#<pr>` token in the run ledger's rows, each with the
|
|
497
|
+
// row that carries it and its ticket N. The dispatched list is not read.
|
|
498
|
+
function implementerClaims(ledger, pr) {
|
|
499
|
+
const claims = [];
|
|
500
|
+
for (const text of ledger?.rows ?? []) {
|
|
501
|
+
const key = text.split(/\s/)[0];
|
|
502
|
+
for (const t of memberTokens(text)) {
|
|
503
|
+
if (t.family === "impl" && t.error === null && t.outcome === `PR#${pr}`) claims.push({ key, ticket: t.number });
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
return claims;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// The ticket a PR's row keys on: its one closing issue, else the N of its one
|
|
510
|
+
// settled impl token. Otherwise `refusal` says why there is none, and `claims`
|
|
511
|
+
// counts the settled impl tokens naming the PR — none is a PR no implementer
|
|
512
|
+
// names. Refused: no such token, several, or several closing issues that do not
|
|
513
|
+
// include the token's N.
|
|
514
|
+
function ticketFor(pr, numbers, ledger) {
|
|
515
|
+
if (numbers.length === 1) return { ticket: String(numbers[0]) };
|
|
516
|
+
const claims = implementerClaims(ledger, pr);
|
|
517
|
+
const closes = numbers.length === 0 ? "closes no issue" : `closes ${numbers.length} issues (${numbers.map((n) => `#${n}`).join(", ")})`;
|
|
518
|
+
const refused = (why) => ({ claims: claims.length, refusal: `PR #${pr} ${closes} per GitHub's closingIssuesReferences, and ${why}` });
|
|
519
|
+
if (claims.length === 0) {
|
|
520
|
+
return refused(`no run-ledger row carries a settled impl-N=PR#${pr} token to name its ticket — a tier-outcomes row keys on exactly one ticket`);
|
|
521
|
+
}
|
|
522
|
+
if (claims.length > 1) {
|
|
523
|
+
return refused(`${claims.length} run-ledger rows carry a settled impl-N=PR#${pr} token (${claims.map((c) => c.key).join(", ")}) — a tier-outcomes row keys on exactly one ticket`);
|
|
524
|
+
}
|
|
525
|
+
const [{ key, ticket }] = claims;
|
|
526
|
+
if (numbers.length > 1 && !numbers.includes(ticket)) {
|
|
527
|
+
return refused(`its settled impl-${ticket}=PR#${pr} token in ${key} names #${ticket}, which is not among them`);
|
|
488
528
|
}
|
|
489
|
-
return String(
|
|
529
|
+
return { ticket: String(ticket) };
|
|
490
530
|
}
|
|
491
531
|
|
|
492
532
|
// The UTC date, the convention of a session id's date and so of every Pull's
|
|
@@ -525,8 +565,9 @@ function append(pr, paths) {
|
|
|
525
565
|
return;
|
|
526
566
|
}
|
|
527
567
|
|
|
528
|
-
const ticket = closingTicket(pr);
|
|
529
568
|
const ledger = readLedger(paths.ledger, false);
|
|
569
|
+
const { ticket, refusal } = ticketFor(pr, closingNumbers(pr), ledger);
|
|
570
|
+
if (refusal) die(refusal);
|
|
530
571
|
const memberRows = readMemberRows(paths.members);
|
|
531
572
|
const resolved = resolveTier({ ledger, memberRows, ticket, pr });
|
|
532
573
|
if (resolved.warning) console.error(`${NAME}: WARNING tier left blank for PR #${pr} (ticket #${ticket}): ${resolved.warning}`);
|
|
@@ -557,17 +598,15 @@ function append(pr, paths) {
|
|
|
557
598
|
console.log(line);
|
|
558
599
|
}
|
|
559
600
|
|
|
560
|
-
//
|
|
561
|
-
//
|
|
562
|
-
//
|
|
563
|
-
|
|
564
|
-
// into a NEED.
|
|
565
|
-
function closesNoIssue(pr) {
|
|
601
|
+
// A PR's closing issue numbers, or null after a line naming why they could not
|
|
602
|
+
// be read. That line never reads `WARNING PR #`, which closeout.mjs turns into
|
|
603
|
+
// a NEED; a PR whose read failed keeps its warning.
|
|
604
|
+
function closingNumbersOrNull(pr) {
|
|
566
605
|
try {
|
|
567
|
-
return
|
|
606
|
+
return closingIssueNumbers(pr);
|
|
568
607
|
} catch (e) {
|
|
569
608
|
console.error(`${NAME}: could not read the closing references of PR #${pr}: ${e.message}`);
|
|
570
|
-
return
|
|
609
|
+
return null;
|
|
571
610
|
}
|
|
572
611
|
}
|
|
573
612
|
|
|
@@ -583,11 +622,15 @@ function check(paths) {
|
|
|
583
622
|
if (has("live")) {
|
|
584
623
|
const ledger = readLedger(paths.ledger, true);
|
|
585
624
|
for (const pr of unrecordedReviewedPrs(ledger, rows)) {
|
|
586
|
-
|
|
587
|
-
|
|
625
|
+
const numbers = closingNumbersOrNull(pr);
|
|
626
|
+
const { refusal, claims } = numbers === null ? {} : ticketFor(pr, numbers, ledger);
|
|
627
|
+
if (refusal && claims === 0) {
|
|
628
|
+
const closes = numbers.length === 0 ? "closes no issue" : `closes ${numbers.length} issues`;
|
|
629
|
+
console.error(`${NAME}: note PR #${pr} carries reviewed= on the ledger and ${closes}, and no settled impl token names it, so it takes no row in ${paths.file}`);
|
|
588
630
|
continue;
|
|
589
631
|
}
|
|
590
|
-
|
|
632
|
+
const next = refusal ? `\`tier-outcomes.mjs append ${pr}\` refuses it: ${refusal}` : `run \`tier-outcomes.mjs append ${pr}\` if it is an implementer PR`;
|
|
633
|
+
console.error(`${NAME}: WARNING PR #${pr} carries reviewed= on the ledger but has no row in ${paths.file} — ${next}`);
|
|
591
634
|
}
|
|
592
635
|
}
|
|
593
636
|
|
package/skills/run-team/SKILL.md
CHANGED
|
@@ -211,7 +211,7 @@ owes beyond its call:
|
|
|
211
211
|
a recorded stop as the end of the run. A `NEED tier-outcomes append
|
|
212
212
|
<pr>` is a PR the ledger marks reviewed with no verdict row: append it with
|
|
213
213
|
the verdict you rule (**Guard: accumulate per PR**) and run `finish` again.
|
|
214
|
-
A
|
|
214
|
+
A PR closing none or several: a row only if an impl token names it.
|
|
215
215
|
A step it fails is explained in references/close-out.md. Exit 0 is the run
|
|
216
216
|
closed.
|
|
217
217
|
Drain only when a documented trigger fired, and name the trigger in `--reason`.
|
|
@@ -25,8 +25,12 @@
|
|
|
25
25
|
stop as the end of the run. A `NEED tier-outcomes append <pr>` is a PR
|
|
26
26
|
the ledger marks reviewed with no verdict row: append it with the verdict
|
|
27
27
|
you rule (**Guard: accumulate per PR**) and run `finish` again. A reviewed
|
|
28
|
-
PR that closes no issue,
|
|
29
|
-
check names it in a `note` line and
|
|
28
|
+
PR that closes no issue, or several, with no settled `impl-<N>=PR#<pr>`
|
|
29
|
+
token naming it takes no row: the check names it in a `note` line and
|
|
30
|
+
never asks for one. With such a token it is a NEED: `append` takes the
|
|
31
|
+
ticket from the token when exactly one row carries it and, for several
|
|
32
|
+
closing issues, it is among them; otherwise the WARNING behind the NEED
|
|
33
|
+
says why `append` refuses it. A step it fails is
|
|
30
34
|
explained in references/close-out.md. Exit 0 is the run closed.
|
|
31
35
|
Drain only when a documented trigger fired, and name the trigger in `--reason`.
|
|
32
36
|
**Undrain** only when the maintainer asks, never a drain that budget or
|
|
@@ -86,9 +90,11 @@ run's member rows if they are missing, or blank each named row's `tier` and say
|
|
|
86
90
|
why in `note`.
|
|
87
91
|
Each WARNING names a PR this run's ledger marks `reviewed=` that has no row yet
|
|
88
92
|
— append it before committing if it is an implementer PR. A reviewed PR that
|
|
89
|
-
closes no issue
|
|
90
|
-
|
|
91
|
-
|
|
93
|
+
closes no issue, or several, and that no settled `impl-<N>=PR#<pr>` token
|
|
94
|
+
names, is named in a `note` line instead: it takes no row. A WARNING for a PR
|
|
95
|
+
that such tokens name but that `append` would refuse says why. A line
|
|
96
|
+
saying the PR's closing references could not be read — a reference with no
|
|
97
|
+
issue number among the reasons — comes before that PR's WARNING and says why.
|
|
92
98
|
|
|
93
99
|
## Drain the pending ticket-features rows and refresh the cost guard
|
|
94
100
|
|