@open-tomato/rafa 0.39.0 → 0.40.0
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/dist/cli.js +781 -164
- package/dist/effort/store/index.js +2 -2
- package/dist/{index-m0wt4nr1.js → index-334y39tn.js} +66 -0
- package/dist/{index-1r2b1052.js → index-8veaj0t9.js} +2 -2
- package/dist/{index-psv1sxkv.js → index-j7kjj0dd.js} +138 -51
- package/dist/{index-g4116t9m.js → index-krpmxpkh.js} +1 -1
- package/dist/{index-nwgwxfkt.js → index-zcbj07aq.js} +553 -100
- package/dist/index.js +4 -4
- package/dist/plan/index.js +2 -2
- package/package.json +1 -1
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
trackerPathFor,
|
|
15
15
|
updateTrackerLine,
|
|
16
16
|
writeTrackerBlocker
|
|
17
|
-
} from "./index-
|
|
17
|
+
} from "./index-krpmxpkh.js";
|
|
18
18
|
import {
|
|
19
19
|
ACROSS_STORES_ORDER,
|
|
20
20
|
CORE_ADAPTER_REGISTRY,
|
|
@@ -129,7 +129,7 @@ import {
|
|
|
129
129
|
writeNames,
|
|
130
130
|
writePositionFile,
|
|
131
131
|
writeSqliteStore
|
|
132
|
-
} from "./index-
|
|
132
|
+
} from "./index-8veaj0t9.js";
|
|
133
133
|
import {
|
|
134
134
|
CHANGE_LEVELS,
|
|
135
135
|
CONFIG_DEFAULTS,
|
|
@@ -158,7 +158,7 @@ import {
|
|
|
158
158
|
requiredPrerequisite,
|
|
159
159
|
resolveTiers,
|
|
160
160
|
stampPrompt
|
|
161
|
-
} from "./index-
|
|
161
|
+
} from "./index-334y39tn.js";
|
|
162
162
|
import {
|
|
163
163
|
promotable
|
|
164
164
|
} from "./index-d6d0942q.js";
|
|
@@ -11056,6 +11056,149 @@ function createGhIssueBoard(options) {
|
|
|
11056
11056
|
return Object.freeze(board);
|
|
11057
11057
|
}
|
|
11058
11058
|
|
|
11059
|
+
// src/board/project/retry.ts
|
|
11060
|
+
var NEVER_RETRIED = Object.freeze([
|
|
11061
|
+
/RATE_LIMITED|(?:secondary )?rate limit/iu,
|
|
11062
|
+
/INSUFFICIENT_SCOPES|not been granted the required scopes|needs the "[^"]*" scope/u,
|
|
11063
|
+
/NOT_FOUND|Could not resolve to [^\n]*/u
|
|
11064
|
+
]);
|
|
11065
|
+
var RETRIED = Object.freeze([
|
|
11066
|
+
/operation timed out|i\/o timeout|TLS handshake timeout/u,
|
|
11067
|
+
/connection reset|\bEOF\b/u,
|
|
11068
|
+
/\bHTTP 50[234]\b/u
|
|
11069
|
+
]);
|
|
11070
|
+
var UNKNOWN_REASON = "unknown error";
|
|
11071
|
+
function firstMatch(patterns, text) {
|
|
11072
|
+
for (const pattern of patterns) {
|
|
11073
|
+
const match = pattern.exec(text);
|
|
11074
|
+
if (match !== null)
|
|
11075
|
+
return match[0];
|
|
11076
|
+
}
|
|
11077
|
+
return;
|
|
11078
|
+
}
|
|
11079
|
+
function lastLine(text) {
|
|
11080
|
+
const lines = text.split(`
|
|
11081
|
+
`).map((line) => line.trim()).filter((line) => line !== "");
|
|
11082
|
+
return lines.at(-1) ?? UNKNOWN_REASON;
|
|
11083
|
+
}
|
|
11084
|
+
function classifyFailure(stderr) {
|
|
11085
|
+
const permanent = firstMatch(NEVER_RETRIED, stderr);
|
|
11086
|
+
if (permanent !== undefined)
|
|
11087
|
+
return { kind: "permanent", reason: permanent };
|
|
11088
|
+
const retried = firstMatch(RETRIED, stderr);
|
|
11089
|
+
if (retried !== undefined)
|
|
11090
|
+
return { kind: "retried", reason: retried };
|
|
11091
|
+
return { kind: "permanent", reason: lastLine(stderr) };
|
|
11092
|
+
}
|
|
11093
|
+
function callNumber(args) {
|
|
11094
|
+
for (let index = 0;index + 1 < args.length; index += 1) {
|
|
11095
|
+
const value = args[index + 1] ?? "";
|
|
11096
|
+
if (args[index] !== "-F" || !value.startsWith("number="))
|
|
11097
|
+
continue;
|
|
11098
|
+
const number = Number(value.slice("number=".length));
|
|
11099
|
+
if (Number.isSafeInteger(number))
|
|
11100
|
+
return number;
|
|
11101
|
+
}
|
|
11102
|
+
return;
|
|
11103
|
+
}
|
|
11104
|
+
var FIRST_FIELD = /\{\s*([A-Za-z_]\w*)/u;
|
|
11105
|
+
function callSubject(args) {
|
|
11106
|
+
const number = callNumber(args);
|
|
11107
|
+
if (number !== undefined)
|
|
11108
|
+
return `#${String(number)}`;
|
|
11109
|
+
const query = args.find((arg) => arg.startsWith("query="));
|
|
11110
|
+
const field3 = query === undefined ? undefined : FIRST_FIELD.exec(query)?.[1];
|
|
11111
|
+
return field3 ?? args.slice(0, 2).join(" ");
|
|
11112
|
+
}
|
|
11113
|
+
var MS_PER_SECOND = 1000;
|
|
11114
|
+
function isWholeFrom(value, min) {
|
|
11115
|
+
return Number.isSafeInteger(value) && value >= min;
|
|
11116
|
+
}
|
|
11117
|
+
function checkOptions(options) {
|
|
11118
|
+
if (options.retries !== false && !isWholeFrom(options.retries, 1)) {
|
|
11119
|
+
throw new RangeError(`board.project.retries must be false or a whole number from 1, not ${String(options.retries)}`);
|
|
11120
|
+
}
|
|
11121
|
+
if (!isWholeFrom(options.retryWaitSeconds, 1)) {
|
|
11122
|
+
throw new RangeError(`board.project.retryWaitSeconds must be a whole number from 1, not ${String(options.retryWaitSeconds)}`);
|
|
11123
|
+
}
|
|
11124
|
+
}
|
|
11125
|
+
function retryingGhRunner(gh, options) {
|
|
11126
|
+
checkOptions(options);
|
|
11127
|
+
const { retries, retryWaitSeconds, onRetry } = options;
|
|
11128
|
+
if (retries === false)
|
|
11129
|
+
return gh;
|
|
11130
|
+
const sleep = options.sleep ?? ((ms) => Bun.sleep(ms));
|
|
11131
|
+
return async (args, stdin) => {
|
|
11132
|
+
let result = await gh(args, stdin);
|
|
11133
|
+
for (let attempt = 1;attempt <= retries && !result.ok; attempt += 1) {
|
|
11134
|
+
const reading2 = classifyFailure(result.stderr);
|
|
11135
|
+
if (reading2.kind === "permanent")
|
|
11136
|
+
return result;
|
|
11137
|
+
const waitMs = retryWaitSeconds * MS_PER_SECOND * 2 ** (attempt - 1);
|
|
11138
|
+
onRetry?.({
|
|
11139
|
+
attempt,
|
|
11140
|
+
of: retries,
|
|
11141
|
+
reason: reading2.reason,
|
|
11142
|
+
subject: callSubject(args),
|
|
11143
|
+
number: callNumber(args),
|
|
11144
|
+
waitMs,
|
|
11145
|
+
args
|
|
11146
|
+
});
|
|
11147
|
+
await sleep(waitMs);
|
|
11148
|
+
result = await gh(args, stdin);
|
|
11149
|
+
}
|
|
11150
|
+
return result;
|
|
11151
|
+
};
|
|
11152
|
+
}
|
|
11153
|
+
|
|
11154
|
+
// src/board/project/project-runner.ts
|
|
11155
|
+
var RETRY_EVENT = "retry";
|
|
11156
|
+
var OPENED = new WeakSet;
|
|
11157
|
+
function retryLine(notice) {
|
|
11158
|
+
return `retrying ${notice.subject} (${String(notice.attempt)} of ${String(notice.of)}): ${notice.reason}`;
|
|
11159
|
+
}
|
|
11160
|
+
function retryEvent(notice, now) {
|
|
11161
|
+
return {
|
|
11162
|
+
type: "event",
|
|
11163
|
+
name: RETRY_EVENT,
|
|
11164
|
+
summary: retryLine(notice),
|
|
11165
|
+
data: {
|
|
11166
|
+
attempt: notice.attempt,
|
|
11167
|
+
of: notice.of,
|
|
11168
|
+
reason: notice.reason,
|
|
11169
|
+
subject: notice.subject,
|
|
11170
|
+
number: notice.number ?? null,
|
|
11171
|
+
waitMs: notice.waitMs
|
|
11172
|
+
},
|
|
11173
|
+
ts: now.toISOString()
|
|
11174
|
+
};
|
|
11175
|
+
}
|
|
11176
|
+
function retryReporter(output, mode, now = () => new Date) {
|
|
11177
|
+
return (notice) => {
|
|
11178
|
+
if (mode === "json")
|
|
11179
|
+
output.emit(retryEvent(notice, now()));
|
|
11180
|
+
else
|
|
11181
|
+
output.info(retryLine(notice));
|
|
11182
|
+
};
|
|
11183
|
+
}
|
|
11184
|
+
function commandRetrySeams(output, mode, sleep) {
|
|
11185
|
+
const onRetry = retryReporter(output, mode);
|
|
11186
|
+
return sleep === undefined ? { onRetry } : { onRetry, sleep };
|
|
11187
|
+
}
|
|
11188
|
+
var activeRetryReport = (notice) => {
|
|
11189
|
+
retryReporter(activeOutput(), activeOutputMode())(notice);
|
|
11190
|
+
};
|
|
11191
|
+
function openProjectRunner(gh, config, seams = {}) {
|
|
11192
|
+
if (OPENED.has(gh))
|
|
11193
|
+
return gh;
|
|
11194
|
+
const onRetry = seams.onRetry ?? activeRetryReport;
|
|
11195
|
+
const base = { retries: config.boardProjectRetries, retryWaitSeconds: config.boardProjectRetryWaitSeconds, onRetry };
|
|
11196
|
+
const opened = retryingGhRunner(gh, seams.sleep === undefined ? base : { ...base, sleep: seams.sleep });
|
|
11197
|
+
if (opened !== gh)
|
|
11198
|
+
OPENED.add(opened);
|
|
11199
|
+
return opened;
|
|
11200
|
+
}
|
|
11201
|
+
|
|
11059
11202
|
// src/board/project/options.ts
|
|
11060
11203
|
var STAGE_OPTIONS = Object.freeze([
|
|
11061
11204
|
"Backlog",
|
|
@@ -11080,8 +11223,6 @@ var HORIZON_OPTIONS = Object.freeze([
|
|
|
11080
11223
|
|
|
11081
11224
|
// src/board/project/port.ts
|
|
11082
11225
|
var PROJECT_PAGE_SIZE = 100;
|
|
11083
|
-
var PROJECT_WRITE_BATCH_SIZE = 20;
|
|
11084
|
-
var PROJECT_WRITE_PAUSE_MS = 1000;
|
|
11085
11226
|
var PROJECT_PORT_PREFIX = "board project";
|
|
11086
11227
|
var FIELD_DATA_TYPES = Object.freeze({
|
|
11087
11228
|
singleSelect: "SINGLE_SELECT",
|
|
@@ -11167,6 +11308,9 @@ function notFoundWarning(ref) {
|
|
|
11167
11308
|
function skippedFieldWarning(mismatch) {
|
|
11168
11309
|
return `The project's field "${mismatch.template.name}" was skipped and the rest were written: ${mismatch.sentence} Run \`${DOCTOR_FIX}\`.`;
|
|
11169
11310
|
}
|
|
11311
|
+
function notRefreshedWarning(refusal2) {
|
|
11312
|
+
return `#${String(refusal2.number)} not refreshed: ${refusal2.reason}`;
|
|
11313
|
+
}
|
|
11170
11314
|
|
|
11171
11315
|
// src/release/fragment-tree.ts
|
|
11172
11316
|
import { posix } from "path";
|
|
@@ -11423,18 +11567,31 @@ function readFragmentTree(git, tree, directory) {
|
|
|
11423
11567
|
// src/board/project/facts-query.ts
|
|
11424
11568
|
var PAGE_SIZE = 100;
|
|
11425
11569
|
var ISSUE_BATCH = 20;
|
|
11570
|
+
var LIST_BATCH = 20;
|
|
11426
11571
|
var PULL_BATCH = 20;
|
|
11427
11572
|
var FRAGMENT_BATCH = 20;
|
|
11428
11573
|
var PULL_FIELDS = "number state baseRefName headRefOid";
|
|
11429
|
-
var
|
|
11430
|
-
|
|
11431
|
-
|
|
11432
|
-
|
|
11433
|
-
|
|
11434
|
-
|
|
11435
|
-
|
|
11436
|
-
|
|
11437
|
-
|
|
11574
|
+
var ISSUE_LISTS = Object.freeze(["labels", "closedByPullRequestsReferences", "timelineItems"]);
|
|
11575
|
+
var LIST_CODES = Object.freeze({
|
|
11576
|
+
labels: "la",
|
|
11577
|
+
closedByPullRequestsReferences: "cb",
|
|
11578
|
+
timelineItems: "tl"
|
|
11579
|
+
});
|
|
11580
|
+
var LIST_ARGUMENTS = Object.freeze({
|
|
11581
|
+
labels: "",
|
|
11582
|
+
closedByPullRequestsReferences: ", includeClosedPrs: true",
|
|
11583
|
+
timelineItems: ", itemTypes: [CROSS_REFERENCED_EVENT]"
|
|
11584
|
+
});
|
|
11585
|
+
var LIST_NODES = Object.freeze({
|
|
11586
|
+
labels: "name",
|
|
11587
|
+
closedByPullRequestsReferences: "...pull",
|
|
11588
|
+
timelineItems: "... on CrossReferencedEvent { isCrossRepository source { ... on PullRequest { ...pull body } } }"
|
|
11589
|
+
});
|
|
11590
|
+
function listSelection(list, after) {
|
|
11591
|
+
const from = after === null ? "" : `, after: $${after}`;
|
|
11592
|
+
return `${list}(first: ${String(PAGE_SIZE)}${from}${LIST_ARGUMENTS[list]})` + ` { pageInfo { hasNextPage endCursor } nodes { ${LIST_NODES[list]} } }`;
|
|
11593
|
+
}
|
|
11594
|
+
var ISSUE_SELECTION = ["number state stateReason", ...ISSUE_LISTS.map((list) => listSelection(list, null))].join(" ");
|
|
11438
11595
|
function checkNumber(number) {
|
|
11439
11596
|
if (!Number.isSafeInteger(number) || number < 1)
|
|
11440
11597
|
throw new RangeError(`not an issue number: ${String(number)}`);
|
|
@@ -11456,6 +11613,9 @@ function graphqlArgs(query, variables) {
|
|
|
11456
11613
|
function issueAlias(number) {
|
|
11457
11614
|
return `i${checkNumber(number)}`;
|
|
11458
11615
|
}
|
|
11616
|
+
function listAlias(number, list) {
|
|
11617
|
+
return `${LIST_CODES[list]}${checkNumber(number)}`;
|
|
11618
|
+
}
|
|
11459
11619
|
function pullAlias(number) {
|
|
11460
11620
|
return `p${checkNumber(number)}`;
|
|
11461
11621
|
}
|
|
@@ -11467,6 +11627,18 @@ function issuesArgs(numbers) {
|
|
|
11467
11627
|
const query = `query($owner: String!, $repo: String!) { repository(owner: $owner, name: $repo) { nameWithOwner${issues} } }` + ` fragment facts on Issue { ${ISSUE_SELECTION} } fragment pull on PullRequest { ${PULL_FIELDS} }`;
|
|
11468
11628
|
return graphqlArgs(query, []);
|
|
11469
11629
|
}
|
|
11630
|
+
function listPagesArgs(pages) {
|
|
11631
|
+
const aliases = pages.map(({ number, list }) => listAlias(number, list));
|
|
11632
|
+
const declared = aliases.map((alias) => `, $${alias}: String!`).join("");
|
|
11633
|
+
const issues = pages.map(({ number, list }, index) => {
|
|
11634
|
+
const alias = aliases[index] ?? listAlias(number, list);
|
|
11635
|
+
return ` ${alias}: issue(number: ${String(number)}) { ${listSelection(list, alias)} }`;
|
|
11636
|
+
}).join("");
|
|
11637
|
+
const usesPull = pages.some(({ list }) => list !== "labels");
|
|
11638
|
+
const fragment = usesPull ? ` fragment pull on PullRequest { ${PULL_FIELDS} }` : "";
|
|
11639
|
+
const query = `query($owner: String!, $repo: String!${declared}) { repository(owner: $owner, name: $repo) {${issues} } }${fragment}`;
|
|
11640
|
+
return graphqlArgs(query, pages.map(({ cursor }, index) => [aliases[index] ?? "", cursor]));
|
|
11641
|
+
}
|
|
11470
11642
|
function filesArgs(pages) {
|
|
11471
11643
|
const cursors = pages.map(({ number }) => `, $c${checkNumber(number)}: String`).join("");
|
|
11472
11644
|
const pulls = pages.map(({ number }) => ` ${pullAlias(number)}: pullRequest(number: ${String(number)})` + ` { files(first: ${String(PAGE_SIZE)}, after: $c${String(number)})` + " { pageInfo { hasNextPage endCursor } nodes { path changeType } } }").join("");
|
|
@@ -13660,7 +13832,7 @@ var CHECKOUT_ROSTER_TIMEOUT_MS = 30000;
|
|
|
13660
13832
|
var DESCRIBE_LINE = `bun ${RAFA_ENTRY} describe --output=json`;
|
|
13661
13833
|
async function coreRoster() {
|
|
13662
13834
|
const [{ CORE_REGISTRY }, { describeRegistry }] = await Promise.all([
|
|
13663
|
-
import("./index-
|
|
13835
|
+
import("./index-j7kjj0dd.js"),
|
|
13664
13836
|
import("./describe-pwhh0vws.js")
|
|
13665
13837
|
]);
|
|
13666
13838
|
return describeRegistry(CORE_REGISTRY, version);
|
|
@@ -15241,6 +15413,17 @@ var CLOSING_REFERENCE = /\b(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?):?\s+(?:([\w
|
|
|
15241
15413
|
function refuse8(problem) {
|
|
15242
15414
|
throw new Error(`${PREFIX19}: ${problem}`);
|
|
15243
15415
|
}
|
|
15416
|
+
function reasonOf2(error) {
|
|
15417
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
15418
|
+
return message.startsWith(`${PREFIX19}: `) ? message.slice(PREFIX19.length + 2) : message;
|
|
15419
|
+
}
|
|
15420
|
+
function settle(item, read) {
|
|
15421
|
+
try {
|
|
15422
|
+
return { item, ok: true, value: read() };
|
|
15423
|
+
} catch (error) {
|
|
15424
|
+
return { item, ok: false, reason: reasonOf2(error) };
|
|
15425
|
+
}
|
|
15426
|
+
}
|
|
15244
15427
|
function readMapping3(value, where) {
|
|
15245
15428
|
if (!isMapping(value))
|
|
15246
15429
|
refuse8(`${where} is ${describeValue(value)}, expected a mapping`);
|
|
@@ -15262,12 +15445,16 @@ function readList2(value, where) {
|
|
|
15262
15445
|
refuse8(`${where} is ${describeValue(value)}, expected a list`);
|
|
15263
15446
|
return value;
|
|
15264
15447
|
}
|
|
15265
|
-
function
|
|
15448
|
+
function readPage(value, where) {
|
|
15266
15449
|
const connection = readMapping3(value, where);
|
|
15267
15450
|
const pageInfo = readMapping3(connection["pageInfo"], `${where}.pageInfo`);
|
|
15268
|
-
|
|
15269
|
-
|
|
15270
|
-
|
|
15451
|
+
const nodes = readList2(connection["nodes"], `${where}.nodes`);
|
|
15452
|
+
const more = pageInfo["hasNextPage"];
|
|
15453
|
+
if (more === false)
|
|
15454
|
+
return { nodes, next: null };
|
|
15455
|
+
if (more !== true)
|
|
15456
|
+
refuse8(`${where}.pageInfo.hasNextPage is ${describeValue(more)}, expected true or false`);
|
|
15457
|
+
return { nodes, next: readString4(pageInfo["endCursor"], `${where}.pageInfo.endCursor`) };
|
|
15271
15458
|
}
|
|
15272
15459
|
async function readRepository(gh, args) {
|
|
15273
15460
|
const result = await gh(args);
|
|
@@ -15282,6 +15469,21 @@ async function readRepository(gh, args) {
|
|
|
15282
15469
|
const data = readMapping3(readMapping3(parsed, "the answer")["data"], "data");
|
|
15283
15470
|
return readMapping3(data["repository"], "data.repository");
|
|
15284
15471
|
}
|
|
15472
|
+
async function readEach(gh, items, how) {
|
|
15473
|
+
const read = [];
|
|
15474
|
+
for (const batch of batchesOf(items, how.size)) {
|
|
15475
|
+
let answer3;
|
|
15476
|
+
try {
|
|
15477
|
+
answer3 = await readRepository(gh, how.argsOf(batch));
|
|
15478
|
+
} catch (error) {
|
|
15479
|
+
const alone = batch.length === 1 ? batch.map((item) => ({ item, ok: false, reason: reasonOf2(error) })) : await readEach(gh, batch, { ...how, size: 1 });
|
|
15480
|
+
read.push(...alone);
|
|
15481
|
+
continue;
|
|
15482
|
+
}
|
|
15483
|
+
read.push(...batch.map((item, index) => settle(item, () => how.readOne(answer3, item, index))));
|
|
15484
|
+
}
|
|
15485
|
+
return read;
|
|
15486
|
+
}
|
|
15285
15487
|
function readPull(value, where) {
|
|
15286
15488
|
const pull = readMapping3(value, where);
|
|
15287
15489
|
const state = pull["state"];
|
|
@@ -15311,35 +15513,102 @@ function crossReferencedPull(value, where, issue3, repository) {
|
|
|
15311
15513
|
refuse8(`${where}.source.body is ${describeValue(body)}, expected a string`);
|
|
15312
15514
|
return bodyCloses(body, issue3, repository) ? readPull(source, `${where}.source`) : null;
|
|
15313
15515
|
}
|
|
15314
|
-
function
|
|
15516
|
+
function listWhere(number, list) {
|
|
15517
|
+
return `issue #${String(number)}.${list}`;
|
|
15518
|
+
}
|
|
15519
|
+
function readIssueFirstPages(answer3, number, repository) {
|
|
15315
15520
|
const where = `issue #${String(number)}`;
|
|
15316
|
-
const issue3 = readMapping3(
|
|
15521
|
+
const issue3 = readMapping3(answer3[issueAlias(number)], where);
|
|
15317
15522
|
const state = issue3["state"];
|
|
15318
15523
|
if (state !== "OPEN" && state !== "CLOSED")
|
|
15319
15524
|
refuse8(`${where}.state is ${describeValue(state)}, expected OPEN or CLOSED`);
|
|
15320
15525
|
const reason = issue3["stateReason"];
|
|
15321
15526
|
if (reason !== null && typeof reason !== "string")
|
|
15322
15527
|
refuse8(`${where}.stateReason is ${describeValue(reason)}, expected a string or null`);
|
|
15323
|
-
const
|
|
15324
|
-
|
|
15325
|
-
|
|
15528
|
+
const pages = Object.fromEntries(ISSUE_LISTS.map((list) => [list, readPage(issue3[list], listWhere(number, list))]));
|
|
15529
|
+
return { head: { number, state, stateReason: reason }, repository, pages };
|
|
15530
|
+
}
|
|
15531
|
+
function listKey(number, list) {
|
|
15532
|
+
return `${String(number)}:${list}`;
|
|
15533
|
+
}
|
|
15534
|
+
function readListPage(answer3, { number, list }) {
|
|
15535
|
+
return readPage(readMapping3(answer3[listAlias(number, list)], `issue #${String(number)}`)[list], listWhere(number, list));
|
|
15536
|
+
}
|
|
15537
|
+
var LIST_PAGES = { size: LIST_BATCH, argsOf: listPagesArgs, readOne: readListPage };
|
|
15538
|
+
async function readRemainingPages(gh, firsts, refused) {
|
|
15539
|
+
const nodes = new Map;
|
|
15540
|
+
const seen = new Map;
|
|
15541
|
+
let pending = firsts.flatMap(({ head: { number }, pages }) => ISSUE_LISTS.flatMap((list) => {
|
|
15542
|
+
const page = pages[list];
|
|
15543
|
+
nodes.set(listKey(number, list), [...page.nodes]);
|
|
15544
|
+
seen.set(listKey(number, list), new Set(page.next === null ? [] : [page.next]));
|
|
15545
|
+
return page.next === null ? [] : [{ number, list, cursor: page.next }];
|
|
15546
|
+
}));
|
|
15547
|
+
while (pending.length > 0) {
|
|
15548
|
+
const next = [];
|
|
15549
|
+
for (const settled of await readEach(gh, pending, LIST_PAGES)) {
|
|
15550
|
+
const { number, list } = settled.item;
|
|
15551
|
+
if (refused.has(number))
|
|
15552
|
+
continue;
|
|
15553
|
+
if (!settled.ok) {
|
|
15554
|
+
refused.set(number, settled.reason);
|
|
15555
|
+
continue;
|
|
15556
|
+
}
|
|
15557
|
+
nodes.get(listKey(number, list))?.push(...settled.value.nodes);
|
|
15558
|
+
const cursor = settled.value.next;
|
|
15559
|
+
if (cursor === null)
|
|
15560
|
+
continue;
|
|
15561
|
+
const cursors = seen.get(listKey(number, list));
|
|
15562
|
+
if (cursors?.has(cursor) === true) {
|
|
15563
|
+
refused.set(number, `${listWhere(number, list)} answered the cursor ${JSON.stringify(cursor)} a second time, so its next page would repeat one read before`);
|
|
15564
|
+
continue;
|
|
15565
|
+
}
|
|
15566
|
+
cursors?.add(cursor);
|
|
15567
|
+
next.push({ number, list, cursor });
|
|
15568
|
+
}
|
|
15569
|
+
pending = next.filter(({ number }) => !refused.has(number));
|
|
15570
|
+
}
|
|
15571
|
+
return nodes;
|
|
15572
|
+
}
|
|
15573
|
+
function readIssue(head, lists, repository) {
|
|
15574
|
+
const where = `issue #${String(head.number)}`;
|
|
15575
|
+
const labels = lists.labels.map((label, index) => readString4(readMapping3(label, `${where}.labels[${String(index)}]`)["name"], `${where}.labels[${String(index)}].name`));
|
|
15576
|
+
const linked = lists.closedByPullRequestsReferences.map((pull, index) => readPull(pull, `${where}.closedByPullRequestsReferences[${String(index)}]`));
|
|
15577
|
+
const mentioned = lists.timelineItems.map((event, index) => crossReferencedPull(event, `${where}.timelineItems[${String(index)}]`, head.number, repository));
|
|
15326
15578
|
const pulls = new Map([...linked, ...mentioned].flatMap((pull) => pull === null ? [] : [[pull.number, pull]]));
|
|
15327
15579
|
return {
|
|
15328
|
-
|
|
15329
|
-
state,
|
|
15330
|
-
stateReason: reason,
|
|
15580
|
+
...head,
|
|
15331
15581
|
labels,
|
|
15332
15582
|
pulls: [...pulls.values()].sort((left, right) => left.number - right.number)
|
|
15333
15583
|
};
|
|
15334
15584
|
}
|
|
15335
|
-
|
|
15336
|
-
|
|
15337
|
-
|
|
15338
|
-
|
|
15339
|
-
|
|
15340
|
-
|
|
15585
|
+
function readFirstPagesOf(answer3, number) {
|
|
15586
|
+
return readIssueFirstPages(answer3, number, readString4(answer3["nameWithOwner"], "data.repository.nameWithOwner"));
|
|
15587
|
+
}
|
|
15588
|
+
var ISSUES = { size: ISSUE_BATCH, argsOf: issuesArgs, readOne: readFirstPagesOf };
|
|
15589
|
+
async function readIssues(gh, numbers, refused, onRead) {
|
|
15590
|
+
const settledFirsts = [];
|
|
15591
|
+
for (const batch of batchesOf(numbers, ISSUES.size)) {
|
|
15592
|
+
settledFirsts.push(...await readEach(gh, batch, ISSUES));
|
|
15593
|
+
onRead(settledFirsts.length);
|
|
15341
15594
|
}
|
|
15342
|
-
|
|
15595
|
+
const firsts = settledFirsts.flatMap((settled) => {
|
|
15596
|
+
if (settled.ok)
|
|
15597
|
+
return [settled.value];
|
|
15598
|
+
refused.set(settled.item, settled.reason);
|
|
15599
|
+
return [];
|
|
15600
|
+
});
|
|
15601
|
+
const nodes = await readRemainingPages(gh, firsts, refused);
|
|
15602
|
+
return firsts.flatMap(({ head, repository }) => {
|
|
15603
|
+
if (refused.has(head.number))
|
|
15604
|
+
return [];
|
|
15605
|
+
const lists = Object.fromEntries(ISSUE_LISTS.map((list) => [list, nodes.get(listKey(head.number, list)) ?? []]));
|
|
15606
|
+
const issue3 = settle(head.number, () => readIssue(head, lists, repository));
|
|
15607
|
+
if (issue3.ok)
|
|
15608
|
+
return [issue3.value];
|
|
15609
|
+
refused.set(head.number, issue3.reason);
|
|
15610
|
+
return [];
|
|
15611
|
+
});
|
|
15343
15612
|
}
|
|
15344
15613
|
function readFilesPage(value, where, prefix) {
|
|
15345
15614
|
const files = readMapping3(readMapping3(value, where)["files"], `${where}.files`);
|
|
@@ -15356,41 +15625,41 @@ function readFilesPage(value, where, prefix) {
|
|
|
15356
15625
|
next: pageInfo["hasNextPage"] === true ? readString4(pageInfo["endCursor"], `${where}.files.pageInfo.endCursor`) : null
|
|
15357
15626
|
};
|
|
15358
15627
|
}
|
|
15359
|
-
async function readAddedFragments(gh, numbers, prefix) {
|
|
15628
|
+
async function readAddedFragments(gh, numbers, prefix, failed2) {
|
|
15360
15629
|
const added = new Map(numbers.map((number) => [number, []]));
|
|
15630
|
+
const how = {
|
|
15631
|
+
size: PULL_BATCH,
|
|
15632
|
+
argsOf: filesArgs,
|
|
15633
|
+
readOne: (answer3, { number }) => readFilesPage(answer3[pullAlias(number)], `pull request #${String(number)}`, prefix)
|
|
15634
|
+
};
|
|
15361
15635
|
let pending = numbers.map((number) => ({ number, cursor: null }));
|
|
15362
15636
|
while (pending.length > 0) {
|
|
15363
15637
|
const next = [];
|
|
15364
|
-
for (const
|
|
15365
|
-
const
|
|
15366
|
-
|
|
15367
|
-
|
|
15368
|
-
|
|
15369
|
-
if (page.next !== null)
|
|
15370
|
-
next.push({ number, cursor: page.next });
|
|
15638
|
+
for (const settled of await readEach(gh, pending, how)) {
|
|
15639
|
+
const { number } = settled.item;
|
|
15640
|
+
if (!settled.ok) {
|
|
15641
|
+
failed2.set(number, settled.reason);
|
|
15642
|
+
continue;
|
|
15371
15643
|
}
|
|
15644
|
+
added.get(number)?.push(...settled.value.paths);
|
|
15645
|
+
if (settled.value.next !== null)
|
|
15646
|
+
next.push({ number, cursor: settled.value.next });
|
|
15372
15647
|
}
|
|
15373
15648
|
pending = next;
|
|
15374
15649
|
}
|
|
15375
15650
|
return added;
|
|
15376
15651
|
}
|
|
15377
|
-
|
|
15378
|
-
const
|
|
15379
|
-
|
|
15380
|
-
|
|
15381
|
-
|
|
15382
|
-
|
|
15383
|
-
|
|
15384
|
-
|
|
15385
|
-
|
|
15386
|
-
const text = headBlob === null ? null : readMapping3(headBlob, `${path3} at the head`)["text"];
|
|
15387
|
-
if (text !== null && typeof text !== "string")
|
|
15388
|
-
refuse8(`${path3} at the head has text ${describeValue(text)}, expected a string`);
|
|
15389
|
-
return { text, onBase: answer3[base] !== null };
|
|
15390
|
-
}));
|
|
15391
|
-
}
|
|
15392
|
-
return read;
|
|
15652
|
+
function readBlobsOf(answer3, { path: path3 }, index) {
|
|
15653
|
+
const { head, base } = blobAliases(index);
|
|
15654
|
+
if (!(head in answer3) || !(base in answer3))
|
|
15655
|
+
refuse8(`the blob read answered no ${head} or ${base} for ${path3}`);
|
|
15656
|
+
const headBlob = answer3[head];
|
|
15657
|
+
const text = headBlob === null ? null : readMapping3(headBlob, `${path3} at the head`)["text"];
|
|
15658
|
+
if (text !== null && typeof text !== "string")
|
|
15659
|
+
refuse8(`${path3} at the head has text ${describeValue(text)}, expected a string`);
|
|
15660
|
+
return { text, onBase: answer3[base] !== null };
|
|
15393
15661
|
}
|
|
15662
|
+
var BLOBS = { size: FRAGMENT_BATCH, argsOf: blobsArgs, readOne: readBlobsOf };
|
|
15394
15663
|
function fragmentOf(path3, blobs) {
|
|
15395
15664
|
if (blobs.text === null) {
|
|
15396
15665
|
return { path: path3, level: UNREAD_LEVEL, onBase: blobs.onBase, problem: "The fragment could not be read at the head of its pull request." };
|
|
@@ -15404,20 +15673,45 @@ function decidingFragment(fragments) {
|
|
|
15404
15673
|
function blobKey(pull, path3) {
|
|
15405
15674
|
return `${String(pull)}:${path3}`;
|
|
15406
15675
|
}
|
|
15676
|
+
async function readFragments(gh, pulls, prefix, failed2) {
|
|
15677
|
+
const added = await readAddedFragments(gh, pulls.map(({ number }) => number), prefix, failed2);
|
|
15678
|
+
const lookups = pulls.filter(({ number }) => !failed2.has(number)).flatMap((pull) => (added.get(pull.number) ?? []).map((path3) => ({ pull: pull.number, path: path3, headRefOid: pull.headRefOid, baseRefName: pull.baseRefName })));
|
|
15679
|
+
const fragments = new Map((await readEach(gh, lookups, BLOBS)).flatMap((settled) => {
|
|
15680
|
+
if (settled.ok)
|
|
15681
|
+
return [[blobKey(settled.item.pull, settled.item.path), fragmentOf(settled.item.path, settled.value)]];
|
|
15682
|
+
failed2.set(settled.item.pull, settled.reason);
|
|
15683
|
+
return [];
|
|
15684
|
+
}));
|
|
15685
|
+
return { added, fragments };
|
|
15686
|
+
}
|
|
15407
15687
|
async function readIssueFacts(options, numbers) {
|
|
15408
15688
|
const { gh } = options;
|
|
15409
|
-
const
|
|
15410
|
-
const
|
|
15689
|
+
const asked = [...new Set(numbers)];
|
|
15690
|
+
const refused = new Map;
|
|
15691
|
+
const failed2 = new Map;
|
|
15692
|
+
const issues = await readIssues(gh, asked, refused, options.onRead ?? (() => {
|
|
15693
|
+
return;
|
|
15694
|
+
}));
|
|
15411
15695
|
const pulls = [...new Map(issues.flatMap(({ pulls: read }) => read.map((pull) => [pull.number, pull]))).values()];
|
|
15412
|
-
const added = await
|
|
15413
|
-
const lookups = pulls.flatMap((pull) => (added.get(pull.number) ?? []).map((path3) => ({ pull: pull.number, path: path3, headRefOid: pull.headRefOid, baseRefName: pull.baseRefName })));
|
|
15414
|
-
const blobs = await readBlobs(gh, lookups);
|
|
15415
|
-
const fragments = new Map(lookups.map(({ pull, path: path3 }, index) => [blobKey(pull, path3), fragmentOf(path3, blobs[index] ?? { text: null, onBase: false })]));
|
|
15696
|
+
const { added, fragments } = await readFragments(gh, pulls, directoryPrefix(options.fragments), failed2);
|
|
15416
15697
|
const factsOf = (pull) => {
|
|
15417
15698
|
const own = [...added.get(pull.number) ?? []].sort().flatMap((path3) => fragments.get(blobKey(pull.number, path3)) ?? []);
|
|
15418
15699
|
return { number: pull.number, state: pull.state, baseRefName: pull.baseRefName, fragments: own, fragment: decidingFragment(own) };
|
|
15419
15700
|
};
|
|
15420
|
-
|
|
15701
|
+
const facts = new Map(issues.flatMap(({ pulls: read, ...issue3 }) => {
|
|
15702
|
+
const unread3 = read.find(({ number }) => failed2.has(number));
|
|
15703
|
+
if (unread3 === undefined)
|
|
15704
|
+
return [[issue3.number, { ...issue3, pullRequests: read.map(factsOf) }]];
|
|
15705
|
+
refused.set(issue3.number, `pull request #${String(unread3.number)} could not be read: ${failed2.get(unread3.number) ?? ""}`);
|
|
15706
|
+
return [];
|
|
15707
|
+
}));
|
|
15708
|
+
return {
|
|
15709
|
+
facts,
|
|
15710
|
+
refused: asked.flatMap((number) => {
|
|
15711
|
+
const reason = refused.get(number);
|
|
15712
|
+
return reason === undefined ? [] : [{ number, reason }];
|
|
15713
|
+
})
|
|
15714
|
+
};
|
|
15421
15715
|
}
|
|
15422
15716
|
|
|
15423
15717
|
// src/board/project/gh.ts
|
|
@@ -15469,7 +15763,7 @@ function readList3(value, where) {
|
|
|
15469
15763
|
refuse9(`${where} is ${describeValue(value)}, expected a list`);
|
|
15470
15764
|
return value;
|
|
15471
15765
|
}
|
|
15472
|
-
function
|
|
15766
|
+
function readOnePage(value, where) {
|
|
15473
15767
|
const connection = readMapping4(value, where);
|
|
15474
15768
|
if (readMapping4(connection["pageInfo"], `${where}.pageInfo`)["hasNextPage"] !== false) {
|
|
15475
15769
|
refuse9(`${where} holds more than ${String(PROJECT_PAGE_SIZE)} entries, one page`);
|
|
@@ -15528,7 +15822,7 @@ function readProject(owner, value, where) {
|
|
|
15528
15822
|
url: readString5(project["url"], `${where}.url`),
|
|
15529
15823
|
closed: readBoolean2(project["closed"], `${where}.closed`),
|
|
15530
15824
|
public: readBoolean2(project["public"], `${where}.public`),
|
|
15531
|
-
fields:
|
|
15825
|
+
fields: readOnePage(project["fields"], `${where}.fields`).map((field4, index) => readField(field4, `${where}.fields.nodes[${String(index)}]`))
|
|
15532
15826
|
};
|
|
15533
15827
|
}
|
|
15534
15828
|
function findArgs(ref3) {
|
|
@@ -15626,7 +15920,7 @@ function readContent(item, where) {
|
|
|
15626
15920
|
}
|
|
15627
15921
|
function readItem(value, where) {
|
|
15628
15922
|
const item = readMapping4(value, where);
|
|
15629
|
-
const values =
|
|
15923
|
+
const values = readOnePage(item["fieldValues"], `${where}.fieldValues`).map((node, index) => readValue(node, `${where}.fieldValues.nodes[${String(index)}]`));
|
|
15630
15924
|
return {
|
|
15631
15925
|
id: readString5(item["id"], `${where}.id`),
|
|
15632
15926
|
archived: readBoolean2(item["isArchived"], `${where}.isArchived`),
|
|
@@ -15705,6 +15999,129 @@ function createGhProjectPort(gh) {
|
|
|
15705
15999
|
};
|
|
15706
16000
|
}
|
|
15707
16001
|
|
|
16002
|
+
// src/board/project/progress.ts
|
|
16003
|
+
var PROGRESS_EVENT = "progress";
|
|
16004
|
+
var PROGRESS_PHASES = Object.freeze({
|
|
16005
|
+
adds: "adding issues",
|
|
16006
|
+
facts: "reading facts",
|
|
16007
|
+
writes: "writing fields"
|
|
16008
|
+
});
|
|
16009
|
+
var SILENT_PHASE = Object.freeze({
|
|
16010
|
+
advance: () => {
|
|
16011
|
+
return;
|
|
16012
|
+
},
|
|
16013
|
+
wait: () => {
|
|
16014
|
+
return;
|
|
16015
|
+
},
|
|
16016
|
+
end: () => {
|
|
16017
|
+
return;
|
|
16018
|
+
}
|
|
16019
|
+
});
|
|
16020
|
+
var MS_PER_SECOND2 = 1000;
|
|
16021
|
+
var SECONDS_PER_MINUTE = 60;
|
|
16022
|
+
var SECONDS_PER_HOUR = 3600;
|
|
16023
|
+
function formatElapsed(elapsedMs) {
|
|
16024
|
+
const seconds = Math.floor(Math.max(0, elapsedMs) / MS_PER_SECOND2);
|
|
16025
|
+
const hours = Math.floor(seconds / SECONDS_PER_HOUR);
|
|
16026
|
+
const minutes = Math.floor(seconds % SECONDS_PER_HOUR / SECONDS_PER_MINUTE);
|
|
16027
|
+
const rest = seconds % SECONDS_PER_MINUTE;
|
|
16028
|
+
if (hours > 0)
|
|
16029
|
+
return `${String(hours)}h ${String(minutes)}m ${String(rest)}s`;
|
|
16030
|
+
if (minutes > 0)
|
|
16031
|
+
return `${String(minutes)}m ${String(rest)}s`;
|
|
16032
|
+
return `${String(rest)}s`;
|
|
16033
|
+
}
|
|
16034
|
+
function waitLine(waitMs) {
|
|
16035
|
+
return `waiting ${String(Math.ceil(Math.max(0, waitMs) / MS_PER_SECOND2))} s for GitHub's write limit`;
|
|
16036
|
+
}
|
|
16037
|
+
function progressEvent(line, now) {
|
|
16038
|
+
return {
|
|
16039
|
+
type: "event",
|
|
16040
|
+
name: PROGRESS_EVENT,
|
|
16041
|
+
summary: line.text,
|
|
16042
|
+
data: { ...line.data },
|
|
16043
|
+
ts: now.toISOString()
|
|
16044
|
+
};
|
|
16045
|
+
}
|
|
16046
|
+
function phaseReporter(options) {
|
|
16047
|
+
const label = PROGRESS_PHASES[options.phase];
|
|
16048
|
+
const total2 = String(options.total);
|
|
16049
|
+
const gapMs = options.progressSeconds === false ? null : options.progressSeconds * MS_PER_SECOND2;
|
|
16050
|
+
let startedAt = options.now();
|
|
16051
|
+
let lastLineAt = startedAt;
|
|
16052
|
+
let doneSoFar = 0;
|
|
16053
|
+
const base = (step, done, at) => ({
|
|
16054
|
+
phase: options.phase,
|
|
16055
|
+
step,
|
|
16056
|
+
done,
|
|
16057
|
+
total: options.total,
|
|
16058
|
+
elapsedMs: at - startedAt
|
|
16059
|
+
});
|
|
16060
|
+
return {
|
|
16061
|
+
start: () => {
|
|
16062
|
+
startedAt = options.now();
|
|
16063
|
+
lastLineAt = startedAt;
|
|
16064
|
+
return { text: `${label}: ${total2}`, data: base("start", 0, startedAt) };
|
|
16065
|
+
},
|
|
16066
|
+
advance: (done) => {
|
|
16067
|
+
doneSoFar = done;
|
|
16068
|
+
if (gapMs === null)
|
|
16069
|
+
return;
|
|
16070
|
+
const at = options.now();
|
|
16071
|
+
if (at - lastLineAt < gapMs)
|
|
16072
|
+
return;
|
|
16073
|
+
lastLineAt = at;
|
|
16074
|
+
const data = base("progress", done, at);
|
|
16075
|
+
return { text: `${label}: ${String(done)}/${total2}, ${formatElapsed(data.elapsedMs)}`, data };
|
|
16076
|
+
},
|
|
16077
|
+
end: ({ done, refused }) => {
|
|
16078
|
+
const data = { ...base("end", done, options.now()), refused };
|
|
16079
|
+
return {
|
|
16080
|
+
text: `${label}: ${String(done)}/${total2}, ${String(refused)} refused, ${formatElapsed(data.elapsedMs)}`,
|
|
16081
|
+
data
|
|
16082
|
+
};
|
|
16083
|
+
},
|
|
16084
|
+
wait: (waitMs) => {
|
|
16085
|
+
const data = { ...base("wait", doneSoFar, options.now()), waitMs };
|
|
16086
|
+
return { text: waitLine(waitMs), data };
|
|
16087
|
+
}
|
|
16088
|
+
};
|
|
16089
|
+
}
|
|
16090
|
+
function openPhase(feed, phase, total2) {
|
|
16091
|
+
if (feed === undefined)
|
|
16092
|
+
return SILENT_PHASE;
|
|
16093
|
+
const reporter = phaseReporter({ phase, total: total2, now: feed.now, progressSeconds: feed.progressSeconds });
|
|
16094
|
+
feed.sink(reporter.start());
|
|
16095
|
+
return {
|
|
16096
|
+
advance: (done) => {
|
|
16097
|
+
const line = reporter.advance(done);
|
|
16098
|
+
if (line !== undefined)
|
|
16099
|
+
feed.sink(line);
|
|
16100
|
+
},
|
|
16101
|
+
wait: (waitMs) => {
|
|
16102
|
+
feed.sink(reporter.wait(waitMs));
|
|
16103
|
+
},
|
|
16104
|
+
end: (result) => {
|
|
16105
|
+
feed.sink(reporter.end(result));
|
|
16106
|
+
}
|
|
16107
|
+
};
|
|
16108
|
+
}
|
|
16109
|
+
function progressSink(output, mode, stamp = () => new Date) {
|
|
16110
|
+
return (line) => {
|
|
16111
|
+
if (mode === "json")
|
|
16112
|
+
output.emit(progressEvent(line, stamp()));
|
|
16113
|
+
else
|
|
16114
|
+
output.info(line.text);
|
|
16115
|
+
};
|
|
16116
|
+
}
|
|
16117
|
+
function commandProgressFeed(output, mode, progressSeconds, clocks = {}) {
|
|
16118
|
+
return {
|
|
16119
|
+
sink: progressSink(output, mode, clocks.stamp),
|
|
16120
|
+
now: clocks.now ?? (() => Date.now()),
|
|
16121
|
+
progressSeconds
|
|
16122
|
+
};
|
|
16123
|
+
}
|
|
16124
|
+
|
|
15708
16125
|
// src/board/project/refresh-values.ts
|
|
15709
16126
|
function projectValuesOf(facts, board) {
|
|
15710
16127
|
return {
|
|
@@ -15814,8 +16231,16 @@ function writeBatchArgs(projectId, batch) {
|
|
|
15814
16231
|
const query = `mutation(${declarations}) { ${parts.map((part) => part.mutation).join(" ")} }`;
|
|
15815
16232
|
return graphqlArgs2(query, [["-f", "project", projectId], ...parts.flatMap((part) => part.fields)]);
|
|
15816
16233
|
}
|
|
15817
|
-
function
|
|
15818
|
-
|
|
16234
|
+
function requirePace(batchSize, pauseMs) {
|
|
16235
|
+
if (!Number.isSafeInteger(batchSize) || batchSize < 1) {
|
|
16236
|
+
throw new RangeError(`not a batch size of writes: ${String(batchSize)}, expected a whole number from 1`);
|
|
16237
|
+
}
|
|
16238
|
+
if (!Number.isSafeInteger(pauseMs) || pauseMs < 0) {
|
|
16239
|
+
throw new RangeError(`not a pause between write requests: ${String(pauseMs)}, expected a whole number from 0`);
|
|
16240
|
+
}
|
|
16241
|
+
}
|
|
16242
|
+
function batchesOf2(writes, batchSize) {
|
|
16243
|
+
return Array.from({ length: Math.ceil(writes.length / batchSize) }, (_, index) => writes.slice(index * batchSize, (index + 1) * batchSize));
|
|
15819
16244
|
}
|
|
15820
16245
|
function isRateLimited(stdout, stderr) {
|
|
15821
16246
|
const answer3 = parsed(stdout);
|
|
@@ -15852,26 +16277,46 @@ async function sendBatch(gh, args, size) {
|
|
|
15852
16277
|
function itemCount(writes) {
|
|
15853
16278
|
return new Set(writes.map((write) => write.itemId)).size;
|
|
15854
16279
|
}
|
|
15855
|
-
async function writeProjectFields(gh, projectId, writes,
|
|
15856
|
-
const
|
|
15857
|
-
|
|
16280
|
+
async function writeProjectFields(gh, projectId, writes, options) {
|
|
16281
|
+
const { batchSize, pauseMs } = options;
|
|
16282
|
+
requirePace(batchSize, pauseMs);
|
|
16283
|
+
const sleep = options.sleep ?? ((ms) => Bun.sleep(ms));
|
|
16284
|
+
const batches = batchesOf2(writes, batchSize);
|
|
15858
16285
|
const requests = batches.map((batch) => writeBatchArgs(projectId, batch));
|
|
16286
|
+
const phase = openPhase(options.progress, "writes", writes.length);
|
|
15859
16287
|
let sent = 0;
|
|
15860
16288
|
for (const [index, batch] of batches.entries()) {
|
|
15861
|
-
if (index > 0)
|
|
15862
|
-
|
|
16289
|
+
if (index > 0) {
|
|
16290
|
+
if (pauseMs > 0)
|
|
16291
|
+
phase.wait(pauseMs);
|
|
16292
|
+
await sleep(pauseMs);
|
|
16293
|
+
}
|
|
15863
16294
|
const outcome = await sendBatch(gh, requests[index] ?? [], batch.length);
|
|
15864
16295
|
if (outcome.rateLimited) {
|
|
15865
16296
|
const unwritten = [...batch.filter((_, at) => !outcome.landed.has(at)), ...batches.slice(index + 1).flat()];
|
|
15866
|
-
|
|
16297
|
+
const written2 = sent + outcome.landed.size;
|
|
16298
|
+
phase.end({ done: written2, refused: writes.length - written2 });
|
|
16299
|
+
return { written: written2, notUpdated: itemCount(unwritten), rateLimited: true, detail: outcome.detail };
|
|
15867
16300
|
}
|
|
15868
16301
|
sent += batch.length;
|
|
16302
|
+
phase.advance(sent);
|
|
15869
16303
|
}
|
|
16304
|
+
phase.end({ done: sent, refused: 0 });
|
|
15870
16305
|
return { written: sent, notUpdated: 0, rateLimited: false, detail: "" };
|
|
15871
16306
|
}
|
|
15872
16307
|
|
|
15873
16308
|
// src/board/project/refresh.ts
|
|
15874
16309
|
var PREFIX20 = "board project refresh";
|
|
16310
|
+
function writesOptionsOf(options) {
|
|
16311
|
+
const { sleep, progress } = options;
|
|
16312
|
+
return {
|
|
16313
|
+
batchSize: options.config.boardProjectWriteBatchSize,
|
|
16314
|
+
pauseMs: options.config.boardProjectWritePauseMs,
|
|
16315
|
+
...sleep === undefined ? {} : { sleep },
|
|
16316
|
+
...progress === undefined ? {} : { progress }
|
|
16317
|
+
};
|
|
16318
|
+
}
|
|
16319
|
+
var NOTHING_READ = Object.freeze({ changes: [], refused: [] });
|
|
15875
16320
|
var NOTHING_WRITTEN = Object.freeze({ written: 0, notUpdated: 0, rateLimited: false, detail: "" });
|
|
15876
16321
|
var NO_UNLABELLED_SEARCH = () => Promise.resolve([]);
|
|
15877
16322
|
function issueNumbers(issues) {
|
|
@@ -15921,16 +16366,17 @@ async function readRefreshBoard(config, gh, repository) {
|
|
|
15921
16366
|
async function changesFor(options, repository, project, present, read) {
|
|
15922
16367
|
const { config, gh } = options;
|
|
15923
16368
|
const numbers = [...present.keys()];
|
|
15924
|
-
const
|
|
16369
|
+
const phase = openPhase(options.progress, "facts", numbers.length);
|
|
16370
|
+
const { facts, refused } = await readIssueFacts({ gh, fragments: config.releaseFragments, onRead: phase.advance }, numbers);
|
|
16371
|
+
phase.end({ done: facts.size, refused: refused.length });
|
|
15925
16372
|
const board = read ?? await readRefreshBoard(config, gh, repository);
|
|
15926
16373
|
const { matched } = matchProjectFields(project);
|
|
15927
|
-
|
|
15928
|
-
const
|
|
16374
|
+
const changes = numbers.flatMap((issue3) => {
|
|
16375
|
+
const issueFacts = facts.get(issue3);
|
|
15929
16376
|
const item = present.get(issue3);
|
|
15930
|
-
|
|
15931
|
-
throw new Error(`${PREFIX20}: no facts were read for #${String(issue3)}`);
|
|
15932
|
-
return projectChangesOf(issue3, item, projectValuesOf(read2, board), matched);
|
|
16377
|
+
return issueFacts === undefined || item === undefined ? [] : projectChangesOf(issue3, item, projectValuesOf(issueFacts, board), matched);
|
|
15933
16378
|
});
|
|
16379
|
+
return { changes, refused };
|
|
15934
16380
|
}
|
|
15935
16381
|
function rankShifted(issue3, item, rankField, rank) {
|
|
15936
16382
|
const values = { stage: null, horizon: null, rank, blockedBy: null, progress: null };
|
|
@@ -15962,13 +16408,14 @@ async function refreshOn(options, repository, ref3, asked, widening) {
|
|
|
15962
16408
|
}));
|
|
15963
16409
|
const missing = numbers.filter((issue3) => !present.has(issue3));
|
|
15964
16410
|
const { mismatched: skipped2 } = matchProjectFields(project);
|
|
15965
|
-
const changes = present.size === 0 ?
|
|
15966
|
-
const writes = changes.length === 0 || options.dryRun === true ? NOTHING_WRITTEN : await writeProjectFields(gh, project.id, changes.map(({ write }) => write), options
|
|
16411
|
+
const { changes, refused } = present.size === 0 ? NOTHING_READ : await changesFor(options, repository, project, present, board);
|
|
16412
|
+
const writes = changes.length === 0 || options.dryRun === true ? NOTHING_WRITTEN : await writeProjectFields(gh, project.id, changes.map(({ write }) => write), writesOptionsOf(options));
|
|
15967
16413
|
const warnings = [
|
|
16414
|
+
...refused.map(notRefreshedWarning),
|
|
15968
16415
|
...writes.rateLimited ? [rateLimitWarning(writes.notUpdated)] : [],
|
|
15969
16416
|
...skipped2.map(skippedFieldWarning)
|
|
15970
16417
|
];
|
|
15971
|
-
return { kind: "refreshed", project: ref3, changes, writes, missing, skipped: skipped2, warnings };
|
|
16418
|
+
return { kind: "refreshed", project: ref3, changes, writes, missing, skipped: skipped2, refused, warnings };
|
|
15972
16419
|
}
|
|
15973
16420
|
async function refreshProjectItems(options, issues, widening = {}) {
|
|
15974
16421
|
const { config, gh } = options;
|
|
@@ -15997,7 +16444,13 @@ async function refreshProjectItems(options, issues, widening = {}) {
|
|
|
15997
16444
|
|
|
15998
16445
|
// src/board/project/issue-board-refresh.ts
|
|
15999
16446
|
function refreshIssueItems(options, issues, widening = {}) {
|
|
16000
|
-
return refreshProjectItems(options, issues, widening);
|
|
16447
|
+
return refreshProjectItems(retrying(options), issues, widening);
|
|
16448
|
+
}
|
|
16449
|
+
function retrying(options) {
|
|
16450
|
+
if (options.config.boardProjectNumber === null)
|
|
16451
|
+
return options;
|
|
16452
|
+
const seams = options.sleep === undefined ? {} : { sleep: options.sleep };
|
|
16453
|
+
return { ...options, gh: openProjectRunner(options.gh, options.config, seams) };
|
|
16001
16454
|
}
|
|
16002
16455
|
function refreshFailedWarning(issue3, error) {
|
|
16003
16456
|
return `The project was not updated for #${String(issue3)}: ${messageOf(error)}. Run \`${BOARD_SYNC_FIX}\` to catch up.`;
|
|
@@ -16037,7 +16490,7 @@ function createRefreshingGhIssueBoard(options) {
|
|
|
16037
16490
|
});
|
|
16038
16491
|
const refreshOptions = sleep === undefined ? { config, gh } : { config, gh, sleep };
|
|
16039
16492
|
return withProjectRefresh(createGhIssueBoard({ gh }), {
|
|
16040
|
-
refresh: (issues) => refreshProjectItems(refreshOptions, issues),
|
|
16493
|
+
refresh: (issues) => refreshProjectItems(retrying(refreshOptions), issues),
|
|
16041
16494
|
warn
|
|
16042
16495
|
});
|
|
16043
16496
|
}
|
|
@@ -16073,8 +16526,8 @@ function createLinePrompter(input, output) {
|
|
|
16073
16526
|
return next;
|
|
16074
16527
|
if (ended)
|
|
16075
16528
|
return null;
|
|
16076
|
-
return new Promise((
|
|
16077
|
-
waiting.push(
|
|
16529
|
+
return new Promise((settle2) => {
|
|
16530
|
+
waiting.push(settle2);
|
|
16078
16531
|
});
|
|
16079
16532
|
},
|
|
16080
16533
|
close: () => {
|
|
@@ -21211,7 +21664,7 @@ function settleWhy(waiting) {
|
|
|
21211
21664
|
return `${count} ${wait} on ${waiting.base} and ${fold} into ${waiting.version}`;
|
|
21212
21665
|
}
|
|
21213
21666
|
function readFollowUps(reading2) {
|
|
21214
|
-
const { liveLoopBranches, rafaCheckout, runtimeInstalled, settle, version: version2 } = reading2;
|
|
21667
|
+
const { liveLoopBranches, rafaCheckout, runtimeInstalled, settle: settle2, version: version2 } = reading2;
|
|
21215
21668
|
const followUps = [];
|
|
21216
21669
|
if (version2 !== null && rafaCheckout && !runtimeInstalled) {
|
|
21217
21670
|
followUps.push({
|
|
@@ -21220,8 +21673,8 @@ function readFollowUps(reading2) {
|
|
|
21220
21673
|
why: selfUpdateWhy(version2, liveLoopBranches)
|
|
21221
21674
|
});
|
|
21222
21675
|
}
|
|
21223
|
-
if (
|
|
21224
|
-
followUps.push({ id: "release-settle", command: RELEASE_SETTLE_COMMAND, why: settleWhy(
|
|
21676
|
+
if (settle2 !== null) {
|
|
21677
|
+
followUps.push({ id: "release-settle", command: RELEASE_SETTLE_COMMAND, why: settleWhy(settle2) });
|
|
21225
21678
|
}
|
|
21226
21679
|
return Object.freeze(followUps.map((followUp) => Object.freeze(followUp)));
|
|
21227
21680
|
}
|
|
@@ -24702,7 +25155,7 @@ function matchIn(shape, field4) {
|
|
|
24702
25155
|
return null;
|
|
24703
25156
|
return { kind: shape.kind, shape: shape.name, evidence: found[0] };
|
|
24704
25157
|
}
|
|
24705
|
-
function
|
|
25158
|
+
function firstMatch2(fields) {
|
|
24706
25159
|
for (const shape of SHAPES2) {
|
|
24707
25160
|
for (const field4 of fields) {
|
|
24708
25161
|
const found = matchIn(shape, field4);
|
|
@@ -24713,7 +25166,7 @@ function firstMatch(fields) {
|
|
|
24713
25166
|
return null;
|
|
24714
25167
|
}
|
|
24715
25168
|
function readMachineFault(bug) {
|
|
24716
|
-
return
|
|
25169
|
+
return firstMatch2(fieldsOf(bug));
|
|
24717
25170
|
}
|
|
24718
25171
|
function isMachineFault(bug) {
|
|
24719
25172
|
return readMachineFault(bug) !== null;
|
|
@@ -30475,7 +30928,7 @@ function resultOf(run, action, fields = {}) {
|
|
|
30475
30928
|
...fields
|
|
30476
30929
|
};
|
|
30477
30930
|
}
|
|
30478
|
-
async function
|
|
30931
|
+
async function settle2(run, action, ref8, foundBy, supersedes) {
|
|
30479
30932
|
const { store } = run.route;
|
|
30480
30933
|
const { key } = run.filing;
|
|
30481
30934
|
if (store === null || key === null)
|
|
@@ -30487,13 +30940,13 @@ async function fileNew(run, extras = {}) {
|
|
|
30487
30940
|
const { filing } = run;
|
|
30488
30941
|
const draft = extras.supersedes === undefined && extras.duplicates === undefined ? filing.draft : { ...filing.draft, body: issueText(ISSUE_OPENING, { ...filing.values, ...extras }, run.redact) };
|
|
30489
30942
|
const created = await step(run, `the ${run.route.channel} tracker create`, () => run.route.tracker.create(draft));
|
|
30490
|
-
return created.ok ?
|
|
30943
|
+
return created.ok ? settle2(run, "filed", created.value, null, extras.supersedes) : resultOf(run, "failed", { problem: created.problem });
|
|
30491
30944
|
}
|
|
30492
30945
|
async function commentOn(run, ref8, foundBy, action = "commented", comment = run.filing.comment) {
|
|
30493
30946
|
const commented = await step(run, `the ${run.route.channel} tracker comment`, () => run.route.tracker.comment(ref8, comment));
|
|
30494
30947
|
if (!commented.ok)
|
|
30495
30948
|
return resultOf(run, "failed", { ref: ref8, foundBy, problem: commented.problem });
|
|
30496
|
-
return foundBy === "store" ? resultOf(run, action, { ref: ref8, foundBy }) :
|
|
30949
|
+
return foundBy === "store" ? resultOf(run, action, { ref: ref8, foundBy }) : settle2(run, action, ref8, foundBy);
|
|
30497
30950
|
}
|
|
30498
30951
|
async function lookUp2(run, key, searchText) {
|
|
30499
30952
|
const { route, filing } = run;
|
|
@@ -30833,7 +31286,7 @@ var BRANCH_FORMAT = [
|
|
|
30833
31286
|
].join("%09");
|
|
30834
31287
|
var REMOTE3 = "origin";
|
|
30835
31288
|
var FIELD_COUNT = 5;
|
|
30836
|
-
var
|
|
31289
|
+
var MS_PER_SECOND3 = 1000;
|
|
30837
31290
|
var GONE_TRACK = "gone";
|
|
30838
31291
|
function readRemoteHead(git) {
|
|
30839
31292
|
const result = git(["symbolic-ref", "--quiet", "--short", `refs/remotes/${REMOTE3}/HEAD`]);
|
|
@@ -30891,7 +31344,7 @@ function parseBranchLine(line) {
|
|
|
30891
31344
|
if (unix === "" || !Number.isInteger(seconds)) {
|
|
30892
31345
|
return `git for-each-ref wrote no commit date for ${name2}: ${JSON.stringify(unix)}`;
|
|
30893
31346
|
}
|
|
30894
|
-
const lastCommit = new Date(seconds *
|
|
31347
|
+
const lastCommit = new Date(seconds * MS_PER_SECOND3);
|
|
30895
31348
|
const current = head === "*";
|
|
30896
31349
|
if (upstreamField === "") {
|
|
30897
31350
|
return { current, branch: { name: name2, upstream: null, gone: false, ahead: null, lastCommit } };
|
|
@@ -34248,4 +34701,4 @@ async function plan(args, repoRoot, registry = CORE_ADAPTER_REGISTRY) {
|
|
|
34248
34701
|
}
|
|
34249
34702
|
}
|
|
34250
34703
|
|
|
34251
|
-
export { SERVE_CLI_VERSION, PROVENANCE_FIELD, SKILL_FILE2 as SKILL_FILE, provenanceBlock, serveVerdict, SKILL_USE_CLI_VERSION, sessionLogDir, MANIFEST_VERSION, FEATURE_TYPES, OUTPUT_CHANNELS, RUNNING_MANIFEST_SEAMS, validateManifest, loadModules, moduleSettings, pullBeforeRead, collectSessionRow, collect, AGENT_DEFINITION_DIR, VENDOR_COMMAND, readAgentDirectory, resolveAgentRoster, missingPlanAgents, isStackList, stackPaths, stacksFromEccSkillName, DESCRIPTION_LIMIT, LISTING_LIMIT, SKILL_SIGNALS, countCharacters, toolOf, pathDirectories, checkReferences, checkFile, checkDirectory, bundledAgentsDirectory, sourceItem, byName, skillItem, readTrees, parseReportArgs, formatCount, alignRows, verdictOf, failingRows, formatRows, waitForChecks, recordPlanCi, formatTokens, formatTrendSegment, formatLoopsSegment, readTrendInputs, trendReportOf, buildReport, readSkillsReport, report, SPEC_EXTENSION, boardId, notesFileName, branchName, shellQuote, ghMissingMessage, ghUnauthenticatedMessage, ghHostOf, ghPreflightItems, parseWorkingTree, parseTreePaths, untrackedLeftLine, parseWorktrees, worktreesHolding, readMergeRefusal, resolvePrProvider, requireGhProvider, createGhPullRequests, ghPullRequestsIn, REMOTE, BRANCH_PREFIX2 as BRANCH_PREFIX, parseBaseStanding, hasDiverged, parseClaimMessage, claimBranchIssue, makeOwnershipCommit, fetchClaimBranches, readClaimBranch, pushOwnershipCommit, CLAIMED_LABEL, IN_DEVELOPMENT_LABEL, readClaimState, idleText, ROADMAP_TITLE, ROADMAP_SETTING, parseRoadmapBody, createGhRoadmapSearch, severalRoadmapsMessage, createGhOpenPullRequests, closedIssuesIn, branchClaims, scanClaimBranches, readEpicBody, SPEC_BLOCKED_LABEL, BLOCKED_BY_FIELD, hasSpecBlockedLabel, readBlockedBy, EPIC_LABEL_PREFIX, epicSlugsOf, isNotPlanned, groupByEpicLabel, localDay, readEpics, BOARD_LISTING_LIMIT, createGhBoardListing, SPEC_READY_LABEL, findReadinessGaps, requireCompleteSpec, validate_default, RefsBlockError, fingerprintText, PREVIOUS_COPY_WARN_ABOVE, previousDir, countPreviousCopies, createGhSpecIssueReader, hasSpecLabel, readRoadmapSetting, ROADMAP_LABEL, BOARD_LABELS, LABEL_LIST_LIMIT, SPEC_TEMPLATE_PATH, TEMPLATES_DIRNAME, boardChanged, listBoardLabels, missingBoardLabels, setUpLabels, anythingAt, writeShippedFile, setUpBoard, resolveDefaultBoard, unlabelledRoadmapMessage, createGhRoadmapBody, tickSentence, appendLine, tickLine, editChecklist, noBoardListsLine, epicTickSentence, tickRoadmapAfterMerge, createGhIssueBoard,
|
|
34704
|
+
export { SERVE_CLI_VERSION, PROVENANCE_FIELD, SKILL_FILE2 as SKILL_FILE, provenanceBlock, serveVerdict, SKILL_USE_CLI_VERSION, sessionLogDir, MANIFEST_VERSION, FEATURE_TYPES, OUTPUT_CHANNELS, RUNNING_MANIFEST_SEAMS, validateManifest, loadModules, moduleSettings, pullBeforeRead, collectSessionRow, collect, AGENT_DEFINITION_DIR, VENDOR_COMMAND, readAgentDirectory, resolveAgentRoster, missingPlanAgents, isStackList, stackPaths, stacksFromEccSkillName, DESCRIPTION_LIMIT, LISTING_LIMIT, SKILL_SIGNALS, countCharacters, toolOf, pathDirectories, checkReferences, checkFile, checkDirectory, bundledAgentsDirectory, sourceItem, byName, skillItem, readTrees, parseReportArgs, formatCount, alignRows, verdictOf, failingRows, formatRows, waitForChecks, recordPlanCi, formatTokens, formatTrendSegment, formatLoopsSegment, readTrendInputs, trendReportOf, buildReport, readSkillsReport, report, SPEC_EXTENSION, boardId, notesFileName, branchName, shellQuote, ghMissingMessage, ghUnauthenticatedMessage, ghHostOf, ghPreflightItems, parseWorkingTree, parseTreePaths, untrackedLeftLine, parseWorktrees, worktreesHolding, readMergeRefusal, resolvePrProvider, requireGhProvider, createGhPullRequests, ghPullRequestsIn, REMOTE, BRANCH_PREFIX2 as BRANCH_PREFIX, parseBaseStanding, hasDiverged, parseClaimMessage, claimBranchIssue, makeOwnershipCommit, fetchClaimBranches, readClaimBranch, pushOwnershipCommit, CLAIMED_LABEL, IN_DEVELOPMENT_LABEL, readClaimState, idleText, ROADMAP_TITLE, ROADMAP_SETTING, parseRoadmapBody, createGhRoadmapSearch, severalRoadmapsMessage, createGhOpenPullRequests, closedIssuesIn, branchClaims, scanClaimBranches, readEpicBody, SPEC_BLOCKED_LABEL, BLOCKED_BY_FIELD, hasSpecBlockedLabel, readBlockedBy, EPIC_LABEL_PREFIX, epicSlugsOf, isNotPlanned, groupByEpicLabel, localDay, readEpics, BOARD_LISTING_LIMIT, createGhBoardListing, SPEC_READY_LABEL, findReadinessGaps, requireCompleteSpec, validate_default, RefsBlockError, fingerprintText, PREVIOUS_COPY_WARN_ABOVE, previousDir, countPreviousCopies, createGhSpecIssueReader, hasSpecLabel, readRoadmapSetting, ROADMAP_LABEL, BOARD_LABELS, LABEL_LIST_LIMIT, SPEC_TEMPLATE_PATH, TEMPLATES_DIRNAME, boardChanged, listBoardLabels, missingBoardLabels, setUpLabels, anythingAt, writeShippedFile, setUpBoard, resolveDefaultBoard, unlabelledRoadmapMessage, createGhRoadmapBody, tickSentence, appendLine, tickLine, editChecklist, noBoardListsLine, epicTickSentence, tickRoadmapAfterMerge, createGhIssueBoard, commandRetrySeams, openProjectRunner, matchProjectFields, PROJECT_SCOPE_FIX, BOARD_SYNC_FIX, isMissingProjectScope, scopeWarning, rateLimitWarning, notFoundWarning, skippedFieldWarning, notRefreshedWarning, isWaiting, blockerArg, createNativeRelations, selectBoardRelations, resolveTracker, DEFAULT_ISSUE_SEAMS, lineRefusal, expectTwoArguments, readTextFlag, readNonBlankFlag, readRequiredFlag, readChoice, readChoiceFlag, issueProject, issueSubjectConfig, resolveIssueTracker, issueRef, issueName, urlLines, onTracker, NATIVE_MODE, NATIVE_RETRY_HINT, nativeEpicLeft, nativeAlreadyMessage, nativeParentLine, readBoardRepository, configuredMoveRelations, FRAGMENT_PLAN_ID_PATTERN, serializeFragment, allocateFragmentName, directoryPrefix, HORIZON_LABEL_PREFIX, readEpicProblems, epicProblemMessage, readEpicDependents, REASON_FLAG, normaliseReason, renderHorizonComment, renderParkedPullRequestComment, renderMoveComment, renderCloseComment, renderCancelComment, cancelMoveReason, renderDependentComment, renderUnblockNote, readReason, unaskedReasonMessage, blankReasonMessage, readRefsText, readCopyRefs, restampCopyRefs, RefVerifyError, readConfiguredRelations, requireNoLeak, blockedLineSentence, boardRepoLabel, memoiseVerifier, LEARNED_DIRECTORY, ORIGIN_FIELD, DEMOTION_VERDICTS, WHEN_TO_USE_HEADING, bodySections, classifySkill, firstSentence, convertToInstinct, rankCandidates, readRankCandidate, NO_NEXT_STEP, readSchemaReport, gateMeaning, unknownAdditive, unknownAdditiveWarning, developmentApplied, isFirstDispatch, STAGE_LABELS, unlabelReleased, createStartPreflightClaim, invalidateRows, checkDrift, driftLines, readDoctorEffortSync, renderDoctorEffortSync, effortSyncRefusal, SESSION_ID_FLAG2 as SESSION_ID_FLAG, readBoardBody, openBoards, boardOfEpic, createOwnerResolver, runIssueList, ISSUE_LIST_FLAGS, list_default, firstNowEpic, show_default, samePlace, resolvePlace, openPhase, commandProgressFeed, createGhProjectPort, resolveLoopSeams, sessionIdFlag, lineRefusal2 as lineRefusal1, refusal3 as refusal, NoSessionRefusal, isLive, planLabel, sessionLine, projectRoot2 as projectRoot, readRecords, pickSession, writeSession, readSessionChecklist, phaseNote, phasedCounts, checkboxAt, estimateEta, readSessionFinishes, formatDuration, etaLine, RELEASE_REMOTE, RELEASE_BASE_BRANCH, parseSemanticVersion, readManifestVersion, replaceManifestVersion, gitPathOf, receiptProblem, readReceiptVerdict, CHANGELOG_TITLE, releaseCommitSubject, readSettle, buildSettle, waitingSettingsOf, readWaiting, forecastPhrase, DEFAULT_RELEASE_SEAMS, compareVersions, changelogVersions, readTags, status_default, epicEndLines, watchDryEpic, nextOwnerGate, resolveReleaseEnabled, refuseMisplacedRuntime, readBinPath, self_update_default, versionTag, INDENT4 as INDENT, cleanUpAfterMerge, reportFollowUps, RELEASE_BLOCK_OPEN, RELEASE_BLOCK_CLOSE, localPlanNotes, readGuard, guardLines, mergeGuardSettings, readMergeGuard, guardReaction, followsMerge, readSettleAfterMerge, DEFAULT_BASE_BRANCH, ghNextBoard, openNextSources, readRemoteHead, eventsFilePath, WORKTREES_SUBDIR, resolveWorktreePath, crossRepositoryRefusal, addResolveWorktree, removeResolveWorktree, pushResolved, worktreeAt, worktreeDirAt, WORKTREE_STATUS, countChanges, cleanupSteps, dryRunLines, runCleanupSteps, defaultCleanupSeams, readCleanup, cleanupCounts, createLinePrompter, openNextRelations, list_default2 as list_default1, readBranch2 as readBranch, readPlans, readOpenPull, readBranchPlan, readNextState, readHomeAfterLoop, commandWords, nextQuestion, NEXT_COMMAND_ACTIONS, LABELS_ONLY_ACTIONS, actionInvocation, runAction, HINT_FLAG_SPEC, actionOutput, endWithNextStep, endingWith, lazyPrompter2 as lazyPrompter, ready_default, DEFAULT_PLAN_FILE, resolvePlanPath, assessPlanRisk, renderRiskText, announceRiskTotal, readBlockedIssues, renderBlockedIssues, blockerToken, addBlockerToBody, resolveCreateSpec, TRIAGE_MODULE, namedSecrets, triageReport, unresolvedTracker, DISK_ROOTS_FILE_SYSTEM, gitToplevel, rootRefusal, rootCandidates, DEFAULT_CI_TIMEOUT_MIN, CI_POLL_INTERVAL_MS, DEFAULT_CI_ATTEMPTS, retargetedLine, MECHANICAL_CONFLICT_SENTENCE, start, createPlanRefsVerifier, readDoctorRefs, renderDoctorRefs, createPlanDirNames, hasPlanFor, HORIZONS, horizonOf, readListedEpics, stageOf, rankOf, readIssueFacts, readRefreshBoard, refreshProjectItems, refreshIssueItems, refreshFailedWarning, unblock_default, unblockAfterMerge, labelsLineBlockersOf, LABELS_READS, createLabelsRelations, EPIC_TYPE_LABEL, plan };
|