@akagilnc/pi-workflow-roles 0.1.3280 → 0.1.3353
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/README.md +5 -5
- package/README.zh-CN.md +5 -5
- package/dist/audit-escalation.js +31 -4
- package/dist/gatekeeper-role.js +25 -4
- package/dist/grok/production-host.js +1167 -862
- package/dist/inspector-contracts.js +5 -2
- package/dist/notary-contracts.js +16 -5
- package/dist/packaged-role-registry.js +0 -7
- package/dist/public-cli/main.js +867 -757
- package/package.json +1 -1
- package/src/audit-escalation.ts +52 -8
- package/src/collector-ledger.ts +309 -74
- package/src/collector-receipt.ts +0 -1
- package/src/collector-role.ts +21 -14
- package/src/diarist-mechanical.ts +16 -5
- package/src/gatekeeper-role.ts +33 -4
- package/src/grok/role-envelope.ts +68 -52
- package/src/inspector-contracts.ts +6 -3
- package/src/inspector-role.ts +5 -2
- package/src/notary-contracts.ts +20 -5
- package/src/notary-role.ts +2 -2
- package/src/packaged-role-registry.ts +0 -12
- package/src/public-cli/cli.ts +50 -125
- package/src/public-cli/coder-run.ts +5 -19
- package/src/public-cli/collector-run.ts +65 -21
- package/src/public-cli/countersign-run.ts +14 -40
- package/src/public-cli/doctor-run.ts +50 -6
- package/src/public-cli/fixer-run.ts +5 -19
- package/src/public-cli/gleaner-left-run.ts +14 -40
- package/src/public-cli/inspector-run.ts +51 -7
- package/src/public-cli/instruction-seat-run.ts +27 -0
- package/src/public-cli/judge-run.ts +11 -36
- package/src/public-cli/merger-run.ts +5 -19
- package/src/public-cli/notary-run.ts +54 -5
- package/src/public-cli/option-definitions.ts +3 -3
- package/src/public-cli/post-admission.ts +76 -0
- package/src/public-cli/reviewer-run.ts +5 -19
- package/src/public-cli/run-lifecycle.ts +342 -107
- package/src/public-cli/settlement.ts +134 -71
- package/src/role-runtime.ts +18 -1
- package/src/submission-ledger.ts +55 -5
|
@@ -28,6 +28,9 @@ export {
|
|
|
28
28
|
} from "../typed-provider-http.ts";
|
|
29
29
|
import type { FixerPhase } from "../package-contracts/fixer-output.ts";
|
|
30
30
|
import type { FixerPrerequisite } from "../package-contracts/fixer-packet.ts";
|
|
31
|
+
import { parseCollectorRepository } from "../collector-config.ts";
|
|
32
|
+
import type { DoctorCaseIdentity } from "../doctor-contracts.ts";
|
|
33
|
+
import type { NotarySourceRunLocator } from "../notary-contracts.ts";
|
|
31
34
|
import {
|
|
32
35
|
appendEngineSessionMaterial,
|
|
33
36
|
engineSessionMaterialFromOptions,
|
|
@@ -40,9 +43,15 @@ import {
|
|
|
40
43
|
requireAuthorityRef,
|
|
41
44
|
type AdmittedCoderInvocation,
|
|
42
45
|
type AdmittedCountersignInvocation,
|
|
46
|
+
type AdmittedCollectorInvocation,
|
|
47
|
+
type AdmittedDoctorInvocation,
|
|
48
|
+
type AdmittedInspectorInvocation,
|
|
49
|
+
type AdmittedNotaryInvocation,
|
|
43
50
|
type AdmittedFixerInvocation,
|
|
44
51
|
type AdmittedGleanerLeftInvocation,
|
|
52
|
+
type AdmittedGatekeeperInvocation,
|
|
45
53
|
type AdmittedJudgeInvocation,
|
|
54
|
+
type AdmittedNavigatorInvocation,
|
|
46
55
|
type AdmittedMergerInvocation,
|
|
47
56
|
type AdmittedReviewerInvocation,
|
|
48
57
|
type AdmittedRoleInvocation,
|
|
@@ -849,6 +858,19 @@ type LoadedAdmittedRequestFields = {
|
|
|
849
858
|
readonly derived?: DerivedMergerEnvelope;
|
|
850
859
|
readonly correlationId?: string;
|
|
851
860
|
readonly ticketNumber?: number;
|
|
861
|
+
/** Collector — admitted repository/PR identity restored on resume (#633). */
|
|
862
|
+
readonly prNumber?: number;
|
|
863
|
+
readonly repository?: string;
|
|
864
|
+
readonly repositoryDisplay?: string;
|
|
865
|
+
readonly requestManifestPath?: string;
|
|
866
|
+
readonly manifestDigest?: string;
|
|
867
|
+
/** Doctor — admitted single-case identity restored on resume (#633). */
|
|
868
|
+
readonly issueNumber?: number;
|
|
869
|
+
readonly caseRunsPath?: string;
|
|
870
|
+
readonly caseIdentity?: DoctorCaseIdentity;
|
|
871
|
+
/** Notary — admitted source-run locator restored on resume (#633). */
|
|
872
|
+
readonly sourceRunPath?: string;
|
|
873
|
+
readonly sourceRun?: NotarySourceRunLocator;
|
|
852
874
|
/** Effective model restored from the invocation identity page on resume. */
|
|
853
875
|
readonly model?: InvocationEffectiveModel;
|
|
854
876
|
};
|
|
@@ -929,6 +951,16 @@ async function loadResumableRunRecord(
|
|
|
929
951
|
let derived: DerivedMergerEnvelope | undefined;
|
|
930
952
|
let correlationId: string | undefined;
|
|
931
953
|
let ticketNumber: number | undefined;
|
|
954
|
+
let prNumber: number | undefined;
|
|
955
|
+
let repository: string | undefined;
|
|
956
|
+
let repositoryDisplay: string | undefined;
|
|
957
|
+
let requestManifestPath: string | undefined;
|
|
958
|
+
let manifestDigest: string | undefined;
|
|
959
|
+
let issueNumber: number | undefined;
|
|
960
|
+
let caseRunsPath: string | undefined;
|
|
961
|
+
let caseIdentity: DoctorCaseIdentity | undefined;
|
|
962
|
+
let sourceRunPath: string | undefined;
|
|
963
|
+
let sourceRun: NotarySourceRunLocator | undefined;
|
|
932
964
|
try {
|
|
933
965
|
const raw: unknown = JSON.parse(
|
|
934
966
|
await readFile(run.admittedRequestPath, "utf8"),
|
|
@@ -968,6 +1000,70 @@ async function loadResumableRunRecord(
|
|
|
968
1000
|
) {
|
|
969
1001
|
baseRevision = record.baseRevision;
|
|
970
1002
|
}
|
|
1003
|
+
// Collector — admitted repository/PR identity (#633 resume).
|
|
1004
|
+
if (typeof record.prNumber === "number" && Number.isSafeInteger(record.prNumber) && record.prNumber >= 1) {
|
|
1005
|
+
prNumber = record.prNumber;
|
|
1006
|
+
}
|
|
1007
|
+
if (typeof record.repository === "string" && record.repository.trim() !== "") {
|
|
1008
|
+
repository = record.repository;
|
|
1009
|
+
}
|
|
1010
|
+
if (typeof record.repositoryDisplay === "string" && record.repositoryDisplay.trim() !== "") {
|
|
1011
|
+
repositoryDisplay = record.repositoryDisplay;
|
|
1012
|
+
}
|
|
1013
|
+
if (typeof record.requestManifestPath === "string" && record.requestManifestPath.trim() !== "") {
|
|
1014
|
+
requestManifestPath = record.requestManifestPath;
|
|
1015
|
+
}
|
|
1016
|
+
if (typeof record.manifestDigest === "string" && record.manifestDigest.trim() !== "") {
|
|
1017
|
+
manifestDigest = record.manifestDigest;
|
|
1018
|
+
}
|
|
1019
|
+
// Doctor — admitted single-case identity (#633 resume).
|
|
1020
|
+
if (typeof record.issueNumber === "number" && Number.isSafeInteger(record.issueNumber) && record.issueNumber >= 1) {
|
|
1021
|
+
issueNumber = record.issueNumber;
|
|
1022
|
+
}
|
|
1023
|
+
if (typeof record.caseRunsPath === "string" && record.caseRunsPath.trim() !== "") {
|
|
1024
|
+
caseRunsPath = record.caseRunsPath;
|
|
1025
|
+
}
|
|
1026
|
+
if (
|
|
1027
|
+
record.caseIdentity !== null &&
|
|
1028
|
+
typeof record.caseIdentity === "object" &&
|
|
1029
|
+
!Array.isArray(record.caseIdentity)
|
|
1030
|
+
) {
|
|
1031
|
+
const ci = record.caseIdentity as Record<string, unknown>;
|
|
1032
|
+
if (
|
|
1033
|
+
typeof ci.issueNumber === "number" &&
|
|
1034
|
+
Number.isSafeInteger(ci.issueNumber) &&
|
|
1035
|
+
ci.issueNumber >= 1 &&
|
|
1036
|
+
typeof ci.runsPath === "string" &&
|
|
1037
|
+
ci.runsPath.trim() !== ""
|
|
1038
|
+
) {
|
|
1039
|
+
caseIdentity = { issueNumber: ci.issueNumber, runsPath: ci.runsPath };
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
// Notary — admitted source-run locator identity (#633 resume).
|
|
1043
|
+
if (typeof record.sourceRunPath === "string" && record.sourceRunPath.trim() !== "") {
|
|
1044
|
+
sourceRunPath = record.sourceRunPath;
|
|
1045
|
+
}
|
|
1046
|
+
if (
|
|
1047
|
+
record.sourceRun !== null &&
|
|
1048
|
+
typeof record.sourceRun === "object" &&
|
|
1049
|
+
!Array.isArray(record.sourceRun)
|
|
1050
|
+
) {
|
|
1051
|
+
const sr = record.sourceRun as Record<string, unknown>;
|
|
1052
|
+
if (
|
|
1053
|
+
typeof sr.runId === "string" &&
|
|
1054
|
+
sr.runId.trim() !== "" &&
|
|
1055
|
+
typeof sr.role === "string" &&
|
|
1056
|
+
sr.role.trim() !== "" &&
|
|
1057
|
+
typeof sr.runDirectory === "string" &&
|
|
1058
|
+
sr.runDirectory.trim() !== ""
|
|
1059
|
+
) {
|
|
1060
|
+
sourceRun = {
|
|
1061
|
+
runId: sr.runId,
|
|
1062
|
+
role: sr.role,
|
|
1063
|
+
runDirectory: sr.runDirectory,
|
|
1064
|
+
};
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
971
1067
|
if (Array.isArray(record.authorityRefs)) {
|
|
972
1068
|
// Reuse unique --authority-ref grammar; blank/inline prose must not resume as authority.
|
|
973
1069
|
authorityRefs = Object.freeze(
|
|
@@ -1083,6 +1179,16 @@ async function loadResumableRunRecord(
|
|
|
1083
1179
|
...(derived === undefined ? {} : { derived }),
|
|
1084
1180
|
...(correlationId === undefined ? {} : { correlationId }),
|
|
1085
1181
|
...(ticketNumber === undefined ? {} : { ticketNumber }),
|
|
1182
|
+
...(prNumber === undefined ? {} : { prNumber }),
|
|
1183
|
+
...(repository === undefined ? {} : { repository }),
|
|
1184
|
+
...(repositoryDisplay === undefined ? {} : { repositoryDisplay }),
|
|
1185
|
+
...(requestManifestPath === undefined ? {} : { requestManifestPath }),
|
|
1186
|
+
...(manifestDigest === undefined ? {} : { manifestDigest }),
|
|
1187
|
+
...(issueNumber === undefined ? {} : { issueNumber }),
|
|
1188
|
+
...(caseRunsPath === undefined ? {} : { caseRunsPath }),
|
|
1189
|
+
...(caseIdentity === undefined ? {} : { caseIdentity }),
|
|
1190
|
+
...(sourceRunPath === undefined ? {} : { sourceRunPath }),
|
|
1191
|
+
...(sourceRun === undefined ? {} : { sourceRun }),
|
|
1086
1192
|
...(model === undefined ? {} : { model }),
|
|
1087
1193
|
},
|
|
1088
1194
|
};
|
|
@@ -1125,23 +1231,23 @@ export type LoadedResumableGleanerLeftRun = {
|
|
|
1125
1231
|
readonly observation?: TypedHttp429Observation;
|
|
1126
1232
|
};
|
|
1127
1233
|
|
|
1234
|
+
export type LoadedResumableInstructionSeatRun = {
|
|
1235
|
+
readonly admitted: AdmittedGatekeeperInvocation | AdmittedNavigatorInvocation;
|
|
1236
|
+
readonly run: RoleRunRecord;
|
|
1237
|
+
readonly observation?: TypedHttp429Observation;
|
|
1238
|
+
};
|
|
1239
|
+
|
|
1128
1240
|
/**
|
|
1129
|
-
*
|
|
1130
|
-
*
|
|
1241
|
+
* Base admitted projection shared by every seat loader: durable identity +
|
|
1242
|
+
* instruction/attachments + principal + restored ticket identity + model (#633).
|
|
1243
|
+
* Seat loaders add only their seat-specific fields on top.
|
|
1131
1244
|
*/
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
)
|
|
1137
|
-
|
|
1138
|
-
if (loaded.run.role !== "judge") {
|
|
1139
|
-
throw new CliUsageError(
|
|
1140
|
-
`role run ${runId} belongs to ${loaded.run.role}, not judge`,
|
|
1141
|
-
);
|
|
1142
|
-
}
|
|
1143
|
-
const admitted: AdmittedJudgeInvocation = {
|
|
1144
|
-
role: "judge",
|
|
1245
|
+
function resumedBaseAdmitted(loaded: {
|
|
1246
|
+
readonly run: RoleRunRecord;
|
|
1247
|
+
readonly principal: DurablePrincipal;
|
|
1248
|
+
readonly admittedFields: LoadedAdmittedRequestFields;
|
|
1249
|
+
}) {
|
|
1250
|
+
return {
|
|
1145
1251
|
runId: loaded.run.runId,
|
|
1146
1252
|
bookKey: loaded.run.bookKey,
|
|
1147
1253
|
projectRoot: loaded.run.projectRoot,
|
|
@@ -1154,6 +1260,16 @@ export async function loadResumableJudgeRun(
|
|
|
1154
1260
|
...(loaded.admittedFields.model === undefined ? {} : { model: loaded.admittedFields.model }),
|
|
1155
1261
|
...restoredTicketFields(loaded.admittedFields),
|
|
1156
1262
|
};
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
/** Loaded-run envelope projection; seat loaders add only their seat fields. */
|
|
1266
|
+
function seatLoadedResult<R extends AdmittedRoleInvocation>(
|
|
1267
|
+
loaded: {
|
|
1268
|
+
readonly run: RoleRunRecord;
|
|
1269
|
+
readonly observation?: TypedHttp429Observation;
|
|
1270
|
+
},
|
|
1271
|
+
admitted: R,
|
|
1272
|
+
): { admitted: R; run: RoleRunRecord; observation?: TypedHttp429Observation } {
|
|
1157
1273
|
return {
|
|
1158
1274
|
admitted,
|
|
1159
1275
|
run: loaded.run,
|
|
@@ -1161,6 +1277,28 @@ export async function loadResumableJudgeRun(
|
|
|
1161
1277
|
};
|
|
1162
1278
|
}
|
|
1163
1279
|
|
|
1280
|
+
/**
|
|
1281
|
+
* Load a resumable Judge run for resume. Rejects unknown, terminal,
|
|
1282
|
+
* non-resumable, and non-Judge IDs without replaying dispatch.
|
|
1283
|
+
*/
|
|
1284
|
+
export async function loadResumableJudgeRun(
|
|
1285
|
+
home: string,
|
|
1286
|
+
runId: string,
|
|
1287
|
+
authority: DurablePrincipalAuthority,
|
|
1288
|
+
): Promise<LoadedResumableJudgeRun> {
|
|
1289
|
+
const loaded = await loadResumableRunRecord(home, runId, authority);
|
|
1290
|
+
if (loaded.run.role !== "judge") {
|
|
1291
|
+
throw new CliUsageError(
|
|
1292
|
+
`role run ${runId} belongs to ${loaded.run.role}, not judge`,
|
|
1293
|
+
);
|
|
1294
|
+
}
|
|
1295
|
+
const admitted: AdmittedJudgeInvocation = {
|
|
1296
|
+
role: "judge",
|
|
1297
|
+
...resumedBaseAdmitted(loaded),
|
|
1298
|
+
};
|
|
1299
|
+
return seatLoadedResult(loaded, admitted);
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1164
1302
|
/**
|
|
1165
1303
|
* Load a resumable Coder run for resume. Phase and task path are restored from
|
|
1166
1304
|
* the admitted request so continuation stays role-correct (#109).
|
|
@@ -1196,24 +1334,11 @@ export async function loadResumableCoderRun(
|
|
|
1196
1334
|
const admitted: AdmittedCoderInvocation = {
|
|
1197
1335
|
role: "coder",
|
|
1198
1336
|
phase,
|
|
1199
|
-
|
|
1200
|
-
bookKey: loaded.run.bookKey,
|
|
1201
|
-
projectRoot: loaded.run.projectRoot,
|
|
1202
|
-
instruction: loaded.admittedFields.instruction,
|
|
1337
|
+
...resumedBaseAdmitted(loaded),
|
|
1203
1338
|
instructionEmpty: false,
|
|
1204
|
-
attachments: loaded.admittedFields.attachments,
|
|
1205
|
-
runDirectory: loaded.run.runDirectory,
|
|
1206
|
-
principal: loaded.principal,
|
|
1207
|
-
admittedRequestPath: loaded.run.admittedRequestPath,
|
|
1208
1339
|
taskPath,
|
|
1209
|
-
...(loaded.admittedFields.model === undefined ? {} : { model: loaded.admittedFields.model }),
|
|
1210
|
-
...restoredTicketFields(loaded.admittedFields),
|
|
1211
|
-
};
|
|
1212
|
-
return {
|
|
1213
|
-
admitted,
|
|
1214
|
-
run: loaded.run,
|
|
1215
|
-
...(loaded.observation === undefined ? {} : { observation: loaded.observation }),
|
|
1216
1340
|
};
|
|
1341
|
+
return seatLoadedResult(loaded, admitted);
|
|
1217
1342
|
}
|
|
1218
1343
|
|
|
1219
1344
|
/**
|
|
@@ -1252,28 +1377,15 @@ export async function loadResumableFixerRun(
|
|
|
1252
1377
|
const admitted: AdmittedFixerInvocation = {
|
|
1253
1378
|
role: "fixer",
|
|
1254
1379
|
phase,
|
|
1255
|
-
|
|
1256
|
-
bookKey: loaded.run.bookKey,
|
|
1257
|
-
projectRoot: loaded.run.projectRoot,
|
|
1258
|
-
instruction: loaded.admittedFields.instruction,
|
|
1380
|
+
...resumedBaseAdmitted(loaded),
|
|
1259
1381
|
instructionEmpty: false,
|
|
1260
|
-
attachments: loaded.admittedFields.attachments,
|
|
1261
|
-
runDirectory: loaded.run.runDirectory,
|
|
1262
|
-
principal: loaded.principal,
|
|
1263
|
-
admittedRequestPath: loaded.run.admittedRequestPath,
|
|
1264
1382
|
packetPath,
|
|
1265
1383
|
...(loaded.admittedFields.prerequisitesPath === undefined
|
|
1266
1384
|
? {}
|
|
1267
1385
|
: { prerequisitesPath: loaded.admittedFields.prerequisitesPath }),
|
|
1268
1386
|
prerequisites,
|
|
1269
|
-
...(loaded.admittedFields.model === undefined ? {} : { model: loaded.admittedFields.model }),
|
|
1270
|
-
...restoredTicketFields(loaded.admittedFields),
|
|
1271
|
-
};
|
|
1272
|
-
return {
|
|
1273
|
-
admitted,
|
|
1274
|
-
run: loaded.run,
|
|
1275
|
-
...(loaded.observation === undefined ? {} : { observation: loaded.observation }),
|
|
1276
1387
|
};
|
|
1388
|
+
return seatLoadedResult(loaded, admitted);
|
|
1277
1389
|
}
|
|
1278
1390
|
|
|
1279
1391
|
/**
|
|
@@ -1303,25 +1415,11 @@ export async function loadResumableReviewerRun(
|
|
|
1303
1415
|
}
|
|
1304
1416
|
const admitted: AdmittedReviewerInvocation = {
|
|
1305
1417
|
role: "reviewer",
|
|
1306
|
-
|
|
1307
|
-
bookKey: loaded.run.bookKey,
|
|
1308
|
-
projectRoot: loaded.run.projectRoot,
|
|
1309
|
-
instruction: loaded.admittedFields.instruction,
|
|
1310
|
-
instructionEmpty: loaded.admittedFields.instructionEmpty,
|
|
1311
|
-
attachments: loaded.admittedFields.attachments,
|
|
1312
|
-
runDirectory: loaded.run.runDirectory,
|
|
1313
|
-
principal: loaded.principal,
|
|
1314
|
-
admittedRequestPath: loaded.run.admittedRequestPath,
|
|
1418
|
+
...resumedBaseAdmitted(loaded),
|
|
1315
1419
|
baseRevision,
|
|
1316
1420
|
authorityRefs: Object.freeze([...(loaded.admittedFields.authorityRefs ?? [])]),
|
|
1317
|
-
...(loaded.admittedFields.model === undefined ? {} : { model: loaded.admittedFields.model }),
|
|
1318
|
-
...restoredTicketFields(loaded.admittedFields),
|
|
1319
|
-
};
|
|
1320
|
-
return {
|
|
1321
|
-
admitted,
|
|
1322
|
-
run: loaded.run,
|
|
1323
|
-
...(loaded.observation === undefined ? {} : { observation: loaded.observation }),
|
|
1324
1421
|
};
|
|
1422
|
+
return seatLoadedResult(loaded, admitted);
|
|
1325
1423
|
}
|
|
1326
1424
|
|
|
1327
1425
|
/**
|
|
@@ -1341,29 +1439,33 @@ export async function loadResumableCountersignRun(
|
|
|
1341
1439
|
}
|
|
1342
1440
|
const admitted: AdmittedCountersignInvocation = {
|
|
1343
1441
|
role: "countersign",
|
|
1344
|
-
|
|
1345
|
-
bookKey: loaded.run.bookKey,
|
|
1346
|
-
projectRoot: loaded.run.projectRoot,
|
|
1347
|
-
instruction: loaded.admittedFields.instruction,
|
|
1348
|
-
instructionEmpty: loaded.admittedFields.instructionEmpty,
|
|
1349
|
-
attachments: loaded.admittedFields.attachments,
|
|
1350
|
-
runDirectory: loaded.run.runDirectory,
|
|
1351
|
-
principal: loaded.principal,
|
|
1352
|
-
admittedRequestPath: loaded.run.admittedRequestPath,
|
|
1353
|
-
...(loaded.admittedFields.model === undefined ? {} : { model: loaded.admittedFields.model }),
|
|
1354
|
-
...restoredTicketFields(loaded.admittedFields),
|
|
1355
|
-
};
|
|
1356
|
-
return {
|
|
1357
|
-
admitted,
|
|
1358
|
-
run: loaded.run,
|
|
1359
|
-
...(loaded.observation === undefined ? {} : { observation: loaded.observation }),
|
|
1442
|
+
...resumedBaseAdmitted(loaded),
|
|
1360
1443
|
};
|
|
1444
|
+
return seatLoadedResult(loaded, admitted);
|
|
1361
1445
|
}
|
|
1362
1446
|
|
|
1363
1447
|
/**
|
|
1364
1448
|
* Load a resumable Gleaner-Left run for resume (#599). Fixed base restores from
|
|
1365
1449
|
* the admitted request so continuation stays comparison-correct.
|
|
1366
1450
|
*/
|
|
1451
|
+
export async function loadResumableInstructionSeatRun(
|
|
1452
|
+
home: string,
|
|
1453
|
+
runId: string,
|
|
1454
|
+
authority: DurablePrincipalAuthority,
|
|
1455
|
+
): Promise<LoadedResumableInstructionSeatRun> {
|
|
1456
|
+
const loaded = await loadResumableRunRecord(home, runId, authority);
|
|
1457
|
+
if (loaded.run.role !== "gatekeeper" && loaded.run.role !== "navigator") {
|
|
1458
|
+
throw new CliUsageError(
|
|
1459
|
+
`role run ${runId} belongs to ${loaded.run.role}, not an instruction seat`,
|
|
1460
|
+
);
|
|
1461
|
+
}
|
|
1462
|
+
const admitted = {
|
|
1463
|
+
role: loaded.run.role,
|
|
1464
|
+
...resumedBaseAdmitted(loaded),
|
|
1465
|
+
} as AdmittedGatekeeperInvocation | AdmittedNavigatorInvocation;
|
|
1466
|
+
return seatLoadedResult(loaded, admitted);
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1367
1469
|
export async function loadResumableGleanerLeftRun(
|
|
1368
1470
|
home: string,
|
|
1369
1471
|
runId: string,
|
|
@@ -1383,24 +1485,10 @@ export async function loadResumableGleanerLeftRun(
|
|
|
1383
1485
|
}
|
|
1384
1486
|
const admitted: AdmittedGleanerLeftInvocation = {
|
|
1385
1487
|
role: "gleaner-left",
|
|
1386
|
-
|
|
1387
|
-
bookKey: loaded.run.bookKey,
|
|
1388
|
-
projectRoot: loaded.run.projectRoot,
|
|
1389
|
-
instruction: loaded.admittedFields.instruction,
|
|
1390
|
-
instructionEmpty: loaded.admittedFields.instructionEmpty,
|
|
1391
|
-
attachments: loaded.admittedFields.attachments,
|
|
1392
|
-
runDirectory: loaded.run.runDirectory,
|
|
1393
|
-
principal: loaded.principal,
|
|
1394
|
-
admittedRequestPath: loaded.run.admittedRequestPath,
|
|
1488
|
+
...resumedBaseAdmitted(loaded),
|
|
1395
1489
|
baseRevision,
|
|
1396
|
-
...(loaded.admittedFields.model === undefined ? {} : { model: loaded.admittedFields.model }),
|
|
1397
|
-
...restoredTicketFields(loaded.admittedFields),
|
|
1398
|
-
};
|
|
1399
|
-
return {
|
|
1400
|
-
admitted,
|
|
1401
|
-
run: loaded.run,
|
|
1402
|
-
...(loaded.observation === undefined ? {} : { observation: loaded.observation }),
|
|
1403
1490
|
};
|
|
1491
|
+
return seatLoadedResult(loaded, admitted);
|
|
1404
1492
|
}
|
|
1405
1493
|
|
|
1406
1494
|
export type LoadedResumableMergerRun = {
|
|
@@ -1443,25 +1531,172 @@ export async function loadResumableMergerRun(
|
|
|
1443
1531
|
}
|
|
1444
1532
|
const admitted: AdmittedMergerInvocation = {
|
|
1445
1533
|
role: "merger",
|
|
1446
|
-
|
|
1447
|
-
bookKey: loaded.run.bookKey,
|
|
1448
|
-
projectRoot: loaded.run.projectRoot,
|
|
1449
|
-
instruction: loaded.admittedFields.instruction,
|
|
1534
|
+
...resumedBaseAdmitted(loaded),
|
|
1450
1535
|
instructionEmpty: false,
|
|
1451
|
-
attachments: loaded.admittedFields.attachments,
|
|
1452
|
-
runDirectory: loaded.run.runDirectory,
|
|
1453
|
-
principal: loaded.principal,
|
|
1454
|
-
admittedRequestPath: loaded.run.admittedRequestPath,
|
|
1455
1536
|
mergerInputPath,
|
|
1456
1537
|
derived,
|
|
1457
|
-
...(loaded.admittedFields.model === undefined ? {} : { model: loaded.admittedFields.model }),
|
|
1458
|
-
...restoredTicketFields(loaded.admittedFields),
|
|
1459
1538
|
};
|
|
1460
|
-
return
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1539
|
+
return seatLoadedResult(loaded, admitted);
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
export type LoadedResumableCollectorRun = {
|
|
1543
|
+
readonly admitted: AdmittedCollectorInvocation;
|
|
1544
|
+
readonly run: RoleRunRecord;
|
|
1545
|
+
readonly observation?: TypedHttp429Observation;
|
|
1546
|
+
};
|
|
1547
|
+
|
|
1548
|
+
/**
|
|
1549
|
+
* Load a resumable Collector run for resume (#633). Admitted repository/PR
|
|
1550
|
+
* identity restores from the durable admitted request so the continuation
|
|
1551
|
+
* stays binding-correct.
|
|
1552
|
+
*/
|
|
1553
|
+
export async function loadResumableCollectorRun(
|
|
1554
|
+
home: string,
|
|
1555
|
+
runId: string,
|
|
1556
|
+
authority: DurablePrincipalAuthority,
|
|
1557
|
+
): Promise<LoadedResumableCollectorRun> {
|
|
1558
|
+
const loaded = await loadResumableRunRecord(home, runId, authority);
|
|
1559
|
+
if (loaded.run.role !== "collector") {
|
|
1560
|
+
throw new CliUsageError(
|
|
1561
|
+
`role run ${runId} belongs to ${loaded.run.role}, not collector`,
|
|
1562
|
+
);
|
|
1563
|
+
}
|
|
1564
|
+
const { prNumber, repository, repositoryDisplay, manifestDigest } = loaded.admittedFields;
|
|
1565
|
+
if (
|
|
1566
|
+
prNumber === undefined ||
|
|
1567
|
+
repository === undefined ||
|
|
1568
|
+
repositoryDisplay === undefined ||
|
|
1569
|
+
manifestDigest === undefined
|
|
1570
|
+
) {
|
|
1571
|
+
throw new CliUsageError(
|
|
1572
|
+
`role run admitted collector repository identity is missing: ${runId}`,
|
|
1573
|
+
);
|
|
1574
|
+
}
|
|
1575
|
+
let parsedRepository;
|
|
1576
|
+
try {
|
|
1577
|
+
parsedRepository = parseCollectorRepository(repositoryDisplay);
|
|
1578
|
+
} catch (error) {
|
|
1579
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
1580
|
+
throw new CliUsageError(detail, { cause: error });
|
|
1581
|
+
}
|
|
1582
|
+
if (parsedRepository.canonical !== repository) {
|
|
1583
|
+
throw new CliUsageError(
|
|
1584
|
+
`role run admitted collector repository does not match its canonical form: ${runId}`,
|
|
1585
|
+
);
|
|
1586
|
+
}
|
|
1587
|
+
const admitted: AdmittedCollectorInvocation = {
|
|
1588
|
+
role: "collector",
|
|
1589
|
+
...resumedBaseAdmitted(loaded),
|
|
1590
|
+
prNumber,
|
|
1591
|
+
repository: parsedRepository,
|
|
1592
|
+
...(loaded.admittedFields.requestManifestPath === undefined
|
|
1593
|
+
? {}
|
|
1594
|
+
: { requestManifestPath: loaded.admittedFields.requestManifestPath }),
|
|
1595
|
+
manifestDigest,
|
|
1596
|
+
};
|
|
1597
|
+
return seatLoadedResult(loaded, admitted);
|
|
1598
|
+
}
|
|
1599
|
+
|
|
1600
|
+
export type LoadedResumableDoctorRun = {
|
|
1601
|
+
readonly admitted: AdmittedDoctorInvocation;
|
|
1602
|
+
readonly run: RoleRunRecord;
|
|
1603
|
+
readonly observation?: TypedHttp429Observation;
|
|
1604
|
+
};
|
|
1605
|
+
|
|
1606
|
+
/**
|
|
1607
|
+
* Load a resumable Doctor run for resume (#633). Issue + retained case
|
|
1608
|
+
* identity restore from the durable admitted request.
|
|
1609
|
+
*/
|
|
1610
|
+
export async function loadResumableDoctorRun(
|
|
1611
|
+
home: string,
|
|
1612
|
+
runId: string,
|
|
1613
|
+
authority: DurablePrincipalAuthority,
|
|
1614
|
+
): Promise<LoadedResumableDoctorRun> {
|
|
1615
|
+
const loaded = await loadResumableRunRecord(home, runId, authority);
|
|
1616
|
+
if (loaded.run.role !== "doctor") {
|
|
1617
|
+
throw new CliUsageError(
|
|
1618
|
+
`role run ${runId} belongs to ${loaded.run.role}, not doctor`,
|
|
1619
|
+
);
|
|
1620
|
+
}
|
|
1621
|
+
const { issueNumber, caseRunsPath, caseIdentity } = loaded.admittedFields;
|
|
1622
|
+
if (
|
|
1623
|
+
issueNumber === undefined ||
|
|
1624
|
+
caseRunsPath === undefined ||
|
|
1625
|
+
caseIdentity === undefined
|
|
1626
|
+
) {
|
|
1627
|
+
throw new CliUsageError(
|
|
1628
|
+
`role run admitted doctor case identity is missing: ${runId}`,
|
|
1629
|
+
);
|
|
1630
|
+
}
|
|
1631
|
+
const admitted: AdmittedDoctorInvocation = {
|
|
1632
|
+
role: "doctor",
|
|
1633
|
+
...resumedBaseAdmitted(loaded),
|
|
1634
|
+
issueNumber,
|
|
1635
|
+
caseRunsPath,
|
|
1636
|
+
caseIdentity,
|
|
1637
|
+
};
|
|
1638
|
+
return seatLoadedResult(loaded, admitted);
|
|
1639
|
+
}
|
|
1640
|
+
|
|
1641
|
+
export type LoadedResumableNotaryRun = {
|
|
1642
|
+
readonly admitted: AdmittedNotaryInvocation;
|
|
1643
|
+
readonly run: RoleRunRecord;
|
|
1644
|
+
readonly observation?: TypedHttp429Observation;
|
|
1645
|
+
};
|
|
1646
|
+
|
|
1647
|
+
/**
|
|
1648
|
+
* Load a resumable Notary run for resume (#633). Source-run locator restores
|
|
1649
|
+
* from the durable admitted request; the locator is not re-resolved.
|
|
1650
|
+
*/
|
|
1651
|
+
export async function loadResumableNotaryRun(
|
|
1652
|
+
home: string,
|
|
1653
|
+
runId: string,
|
|
1654
|
+
authority: DurablePrincipalAuthority,
|
|
1655
|
+
): Promise<LoadedResumableNotaryRun> {
|
|
1656
|
+
const loaded = await loadResumableRunRecord(home, runId, authority);
|
|
1657
|
+
if (loaded.run.role !== "notary") {
|
|
1658
|
+
throw new CliUsageError(
|
|
1659
|
+
`role run ${runId} belongs to ${loaded.run.role}, not notary`,
|
|
1660
|
+
);
|
|
1661
|
+
}
|
|
1662
|
+
const { sourceRunPath, sourceRun } = loaded.admittedFields;
|
|
1663
|
+
if (sourceRunPath === undefined || sourceRun === undefined) {
|
|
1664
|
+
throw new CliUsageError(
|
|
1665
|
+
`role run admitted notary source-run locator is missing: ${runId}`,
|
|
1666
|
+
);
|
|
1667
|
+
}
|
|
1668
|
+
const admitted: AdmittedNotaryInvocation = {
|
|
1669
|
+
role: "notary",
|
|
1670
|
+
...resumedBaseAdmitted(loaded),
|
|
1671
|
+
sourceRunPath,
|
|
1672
|
+
sourceRun,
|
|
1673
|
+
};
|
|
1674
|
+
return seatLoadedResult(loaded, admitted);
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1677
|
+
export type LoadedResumableInspectorRun = {
|
|
1678
|
+
readonly admitted: AdmittedInspectorInvocation;
|
|
1679
|
+
readonly run: RoleRunRecord;
|
|
1680
|
+
readonly observation?: TypedHttp429Observation;
|
|
1681
|
+
};
|
|
1682
|
+
|
|
1683
|
+
/** Load a resumable Inspector run for resume (#633); base admitted identity only. */
|
|
1684
|
+
export async function loadResumableInspectorRun(
|
|
1685
|
+
home: string,
|
|
1686
|
+
runId: string,
|
|
1687
|
+
authority: DurablePrincipalAuthority,
|
|
1688
|
+
): Promise<LoadedResumableInspectorRun> {
|
|
1689
|
+
const loaded = await loadResumableRunRecord(home, runId, authority);
|
|
1690
|
+
if (loaded.run.role !== "inspector") {
|
|
1691
|
+
throw new CliUsageError(
|
|
1692
|
+
`role run ${runId} belongs to ${loaded.run.role}, not inspector`,
|
|
1693
|
+
);
|
|
1694
|
+
}
|
|
1695
|
+
const admitted: AdmittedInspectorInvocation = {
|
|
1696
|
+
role: "inspector",
|
|
1697
|
+
...resumedBaseAdmitted(loaded),
|
|
1464
1698
|
};
|
|
1699
|
+
return seatLoadedResult(loaded, admitted);
|
|
1465
1700
|
}
|
|
1466
1701
|
|
|
1467
1702
|
export async function peekRoleRunRole(
|