@akagilnc/pi-workflow-roles 0.1.5762 → 0.1.5797
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/acp-host/production-host.js +685 -285
- package/dist/external-host-turn-loop.js +3 -0
- package/dist/headless-host/production-host.js +658 -258
- package/dist/migrate-book-topology.js +70 -29
- package/dist/navigator-attendance.js +1 -1
- package/dist/packaged-role-registry.js +3 -2
- package/dist/pi/role-turn-host.js +6 -1
- package/dist/public-cli/instruction-seat-run.js +152 -60
- package/dist/public-cli/invocation.js +98 -46
- package/dist/public-cli/main.js +482 -222
- package/dist/public-cli/option-definitions.js +4 -4
- package/dist/public-cli/post-admission.js +19 -28
- package/dist/public-cli/run-lifecycle.js +10 -21
- package/dist/public-cli/turn-request.js +3 -0
- package/dist/public-role-summons.js +11 -8
- package/dist/report-ticket-tool.js +3 -3
- package/dist/role-run-placement.js +14 -2
- package/dist/role-run-relocation.js +2 -2
- package/dist/run-dossier.js +5 -4
- package/dist/run-terminal-artifacts.js +0 -7
- package/dist/session-identity.js +3 -2
- package/dist/sitian-appender.js +12 -3
- package/dist/submission-ledger.js +24 -0
- package/dist/ticket-progress.js +306 -0
- package/dist/user-dialogue-stdin.js +23 -17
- package/package.json +1 -1
- package/src/external-host-turn-loop.ts +7 -1
- package/src/host-contracts.ts +1 -1
- package/src/navigator-attendance.ts +2 -1
- package/src/packaged-role-registry.ts +3 -2
- package/src/pi/adapter.ts +57 -45
- package/src/pi/role-turn-host.ts +6 -1
- package/src/prepared-role-turn.ts +6 -0
- package/src/public-cli/instruction-seat-run.ts +166 -68
- package/src/public-cli/invocation.ts +120 -46
- package/src/public-cli/option-definitions.ts +5 -4
- package/src/public-cli/post-admission.ts +19 -30
- package/src/public-cli/run-lifecycle.ts +10 -27
- package/src/public-cli/turn-request.ts +3 -0
- package/src/public-role-summons.ts +27 -16
- package/src/report-ticket-tool.ts +7 -3
- package/src/role-envelope.ts +5 -0
- package/src/role-run-placement.ts +19 -2
- package/src/role-run-relocation.ts +2 -2
- package/src/role-runtime.ts +19 -2
- package/src/run-dossier.ts +5 -3
- package/src/run-terminal-artifacts.ts +0 -8
- package/src/session-identity.ts +3 -2
- package/src/sitian-appender.ts +14 -3
- package/src/submission-ledger.ts +27 -0
- package/src/ticket-progress.ts +383 -0
- package/src/user-dialogue-stdin.ts +21 -14
|
@@ -958,6 +958,12 @@ import { basename as basename3, dirname as dirname3, join as join2 } from "node:
|
|
|
958
958
|
function resolveSitianVolumeCategory(kind) {
|
|
959
959
|
return kind;
|
|
960
960
|
}
|
|
961
|
+
function runDirectoryOwningSessionParent(sessionParentDir) {
|
|
962
|
+
if (basename3(sessionParentDir) !== "session") return void 0;
|
|
963
|
+
const runDirectory = dirname3(sessionParentDir);
|
|
964
|
+
if (parseRunLeaf(basename3(runDirectory)) === void 0) return void 0;
|
|
965
|
+
return runDirectory;
|
|
966
|
+
}
|
|
961
967
|
function sitianVolumeDirectory(sessionDirectory, category) {
|
|
962
968
|
return join2(sessionDirectory, category);
|
|
963
969
|
}
|
|
@@ -989,8 +995,8 @@ function resolveSitianRecordPathInLedger(input, ledgerHome) {
|
|
|
989
995
|
throw new Error("Sitian record ownership requires a parent session inside the ledger home");
|
|
990
996
|
}
|
|
991
997
|
const sessionParentDir = dirname3(input.sessionParent);
|
|
992
|
-
const runDirectory =
|
|
993
|
-
if (
|
|
998
|
+
const runDirectory = runDirectoryOwningSessionParent(sessionParentDir);
|
|
999
|
+
if (runDirectory !== void 0) {
|
|
994
1000
|
sessionDir = runDirectory;
|
|
995
1001
|
recordFile = join2(runDirectory, RUN_HISTORY_KINDS.has(input.kind) ? RUN_HISTORY_FILE : RUN_STATE_KINDS.has(input.kind) ? RUN_STATE_FILE : RUN_LOG_FILE);
|
|
996
1002
|
} else {
|
|
@@ -1183,7 +1189,9 @@ function render(runDirectory, history, state, log, unreadable) {
|
|
|
1183
1189
|
original = payload.landingPath;
|
|
1184
1190
|
}
|
|
1185
1191
|
}
|
|
1186
|
-
if (typeof original === "string")
|
|
1192
|
+
if (typeof original === "string") {
|
|
1193
|
+
original = join3(sessionDirectoryOf(runDirectory), basename4(original));
|
|
1194
|
+
}
|
|
1187
1195
|
whole.host = { sessions, ...original === void 0 ? {} : { original } };
|
|
1188
1196
|
whole.submission = latest === void 0 ? {} : { latest };
|
|
1189
1197
|
if (Object.keys(unreadable).length > 0) whole.unreadable = unreadable;
|
|
@@ -9455,9 +9463,8 @@ var init_packaged_role_registry = __esm({
|
|
|
9455
9463
|
bareCommand: false,
|
|
9456
9464
|
outputTool: NOTARY_OUTPUT_TOOL_NAME,
|
|
9457
9465
|
settlement: "accepted",
|
|
9458
|
-
/**
|
|
9466
|
+
/** Dialogue via shared resolveReviewSeatDialogueBody (review = fixed dispatch). */
|
|
9459
9467
|
reaskPrompt: true,
|
|
9460
|
-
transportPrompt: "fixed-kickoff",
|
|
9461
9468
|
gateStageLabel: "\u7B26\u5B9D\u90CE",
|
|
9462
9469
|
/** Gate summon binds --source-run and keeps dialogue off the argv. */
|
|
9463
9470
|
gateSummon: "source-run",
|
|
@@ -9480,6 +9487,8 @@ var init_packaged_role_registry = __esm({
|
|
|
9480
9487
|
phases: [null],
|
|
9481
9488
|
outputTool: COUNTERSIGN_OUTPUT_TOOL_NAME,
|
|
9482
9489
|
settlement: "accepted",
|
|
9490
|
+
/** Same shared dialogue resolver as other review seats (#1208 C1). */
|
|
9491
|
+
reaskPrompt: true,
|
|
9483
9492
|
gateStageLabel: "\u7ED9\u4E8B\u4E2D",
|
|
9484
9493
|
/** Gate summon carries the parent payload as the instruction and a parent run id. */
|
|
9485
9494
|
gateSummon: "parent-instruction",
|
|
@@ -10175,7 +10184,7 @@ async function rewriteSessionTranscriptBindings(path, rewrites) {
|
|
|
10175
10184
|
);
|
|
10176
10185
|
}
|
|
10177
10186
|
async function rewriteNestedMachinePathPages(pagesDirectory, rewrites) {
|
|
10178
|
-
const sessionRoot =
|
|
10187
|
+
const sessionRoot = sessionDirectoryOf(pagesDirectory);
|
|
10179
10188
|
async function walk(directory) {
|
|
10180
10189
|
let entries;
|
|
10181
10190
|
try {
|
|
@@ -10272,13 +10281,30 @@ var init_role_run_relocation = __esm({
|
|
|
10272
10281
|
}
|
|
10273
10282
|
});
|
|
10274
10283
|
|
|
10275
|
-
// src/
|
|
10276
|
-
|
|
10277
|
-
|
|
10278
|
-
|
|
10279
|
-
|
|
10280
|
-
|
|
10281
|
-
|
|
10284
|
+
// src/sitian-facade.ts
|
|
10285
|
+
var init_sitian_facade = __esm({
|
|
10286
|
+
"src/sitian-facade.ts"() {
|
|
10287
|
+
"use strict";
|
|
10288
|
+
init_role_run_placement();
|
|
10289
|
+
init_sitian_appender();
|
|
10290
|
+
init_sitian_contracts();
|
|
10291
|
+
init_sitian_appender();
|
|
10292
|
+
init_sitian_reader();
|
|
10293
|
+
}
|
|
10294
|
+
});
|
|
10295
|
+
|
|
10296
|
+
// src/host-session-record.ts
|
|
10297
|
+
var init_host_session_record = __esm({
|
|
10298
|
+
"src/host-session-record.ts"() {
|
|
10299
|
+
"use strict";
|
|
10300
|
+
init_sitian_facade();
|
|
10301
|
+
init_unknown_value();
|
|
10302
|
+
}
|
|
10303
|
+
});
|
|
10304
|
+
|
|
10305
|
+
// src/host-contracts.ts
|
|
10306
|
+
var init_host_contracts = __esm({
|
|
10307
|
+
"src/host-contracts.ts"() {
|
|
10282
10308
|
"use strict";
|
|
10283
10309
|
}
|
|
10284
10310
|
});
|
|
@@ -10327,6 +10353,32 @@ var init_terminating_tools = __esm({
|
|
|
10327
10353
|
}
|
|
10328
10354
|
});
|
|
10329
10355
|
|
|
10356
|
+
// src/ticket-progress.ts
|
|
10357
|
+
var init_ticket_progress = __esm({
|
|
10358
|
+
"src/ticket-progress.ts"() {
|
|
10359
|
+
"use strict";
|
|
10360
|
+
init_host_session_record();
|
|
10361
|
+
init_host_contracts();
|
|
10362
|
+
init_terminating_tools();
|
|
10363
|
+
init_packaged_role_registry();
|
|
10364
|
+
init_role_run_placement();
|
|
10365
|
+
init_run_dossier();
|
|
10366
|
+
init_sitian_reader();
|
|
10367
|
+
init_unknown_value();
|
|
10368
|
+
}
|
|
10369
|
+
});
|
|
10370
|
+
|
|
10371
|
+
// src/sha256.ts
|
|
10372
|
+
import { createHash } from "node:crypto";
|
|
10373
|
+
function sha256Hex(bytes) {
|
|
10374
|
+
return createHash("sha256").update(bytes).digest("hex");
|
|
10375
|
+
}
|
|
10376
|
+
var init_sha256 = __esm({
|
|
10377
|
+
"src/sha256.ts"() {
|
|
10378
|
+
"use strict";
|
|
10379
|
+
}
|
|
10380
|
+
});
|
|
10381
|
+
|
|
10330
10382
|
// src/doctor-evidence.ts
|
|
10331
10383
|
var init_doctor_evidence = __esm({
|
|
10332
10384
|
"src/doctor-evidence.ts"() {
|
|
@@ -10381,18 +10433,6 @@ var init_session_dialogue = __esm({
|
|
|
10381
10433
|
}
|
|
10382
10434
|
});
|
|
10383
10435
|
|
|
10384
|
-
// src/sitian-facade.ts
|
|
10385
|
-
var init_sitian_facade = __esm({
|
|
10386
|
-
"src/sitian-facade.ts"() {
|
|
10387
|
-
"use strict";
|
|
10388
|
-
init_role_run_placement();
|
|
10389
|
-
init_sitian_appender();
|
|
10390
|
-
init_sitian_contracts();
|
|
10391
|
-
init_sitian_appender();
|
|
10392
|
-
init_sitian_reader();
|
|
10393
|
-
}
|
|
10394
|
-
});
|
|
10395
|
-
|
|
10396
10436
|
// src/ticket-provenance.ts
|
|
10397
10437
|
var init_ticket_provenance = __esm({
|
|
10398
10438
|
"src/ticket-provenance.ts"() {
|
|
@@ -10772,8 +10812,8 @@ var init_option_definitions = __esm({
|
|
|
10772
10812
|
repeatable: false,
|
|
10773
10813
|
form: "option",
|
|
10774
10814
|
description: {
|
|
10775
|
-
en: "Required source run locator (runId@role under the book home, or path to that run directory).
|
|
10776
|
-
zh: "\u5FC5\u586B\u6E90 run \u5B9A\u4F4D\u7B26\uFF08\u7C3F\u5185 runId@role\uFF0C\u6216\u8BE5 run \u76EE\u5F55\u8DEF\u5F84\uFF09\u3002\
|
|
10815
|
+
en: "Required source run locator (runId@role under the book home, or path to that run directory). Binds the audited identity; review dialogue is the fixed Notary dispatch (verdict stays in the ledger). Missing-ticket and unreadable-status reasks keep their existing diagnostic text.",
|
|
10816
|
+
zh: "\u5FC5\u586B\u6E90 run \u5B9A\u4F4D\u7B26\uFF08\u7C3F\u5185 runId@role\uFF0C\u6216\u8BE5 run \u76EE\u5F55\u8DEF\u5F84\uFF09\u3002\u7ED1\u5B9A\u53D7\u5BA1\u8EAB\u4EFD\uFF1B\u5BA1\u7A3F\u5BF9\u8BDD\u4E3A\u7B26\u5B9D\u90CE\u56FA\u5B9A\u6D3E\u5355\u6587\uFF08\u5224\u8BCD\u7559\u5728\u5377\u5B97\u81EA\u884C\u8BFB\u53D6\uFF09\u3002\u7F3A\u7968\u53F7\u4E0E\u8BFB\u4E0D\u51FA status \u7684\u91CD\u4EA4\u4ECD\u9012\u65E2\u6709\u8BCA\u65AD\u539F\u6587\u3002"
|
|
10777
10817
|
}
|
|
10778
10818
|
}
|
|
10779
10819
|
];
|
|
@@ -11107,7 +11147,7 @@ var init_option_definitions = __esm({
|
|
|
11107
11147
|
},
|
|
11108
11148
|
notary: {
|
|
11109
11149
|
command: "notary",
|
|
11110
|
-
summary: "Direct Notary summons; duties: souls/notary.md.
|
|
11150
|
+
summary: "Direct Notary summons; duties: souls/notary.md. Review uses fixed dispatch \u2014 binds --source-run identity; does not accept caller review prompt; verdict stays in the ledger. Missing-ticket (#1171) and unreadable-status reasks deliver their existing diagnostic text on the same seat, not the review sentence.",
|
|
11111
11151
|
usage: ["ak-role notary --source-run <runId@role|path> [options]"],
|
|
11112
11152
|
examples: [
|
|
11113
11153
|
"ak-role notary --source-run 01a034f1-75bf-71a6-bcf5-d1299145b1a5@judge",
|
|
@@ -11168,7 +11208,7 @@ var init_option_definitions = __esm({
|
|
|
11168
11208
|
},
|
|
11169
11209
|
resume: {
|
|
11170
11210
|
command: "resume",
|
|
11171
|
-
summary: "Resume a role run under the live seat table (model/host/engine); session principal must still exist. Every callable seat
|
|
11211
|
+
summary: "Resume a role run under the live seat table (model/host/engine); session principal must still exist. Every callable seat accepts the optional caller message and passes it through unchanged as the continuation prompt. Notary new/direct review calls use only --source-run plus the fixed review dispatch (no caller review prompt); public manual resume still passes the caller message. Global --model/--thinking/--host/--engine must be placed before <runId> (either before `resume` or between `resume` and <runId>); the one argv after <runId> is the opaque message, not a flag position (#471).",
|
|
11172
11212
|
usage: ["ak-role resume <runId> [message]"],
|
|
11173
11213
|
examples: [
|
|
11174
11214
|
"ak-role resume 01abc\u2026",
|
|
@@ -11204,6 +11244,7 @@ var init_invocation = __esm({
|
|
|
11204
11244
|
init_activation_ledger_topology();
|
|
11205
11245
|
init_activation_ledger_git();
|
|
11206
11246
|
init_role_run_placement();
|
|
11247
|
+
init_ticket_progress();
|
|
11207
11248
|
init_packaged_role_registry();
|
|
11208
11249
|
init_run_ticket_number();
|
|
11209
11250
|
init_role_run_relocation();
|
|
@@ -268,7 +268,7 @@ function createNavigatorAttendance(options) {
|
|
|
268
268
|
await promptAllowingRejectedPrepare(request);
|
|
269
269
|
while (output === void 0 && prepareBatchRejected && delivery.nextAction() === "request-delivery") {
|
|
270
270
|
delivery.recordDeliveryRequest();
|
|
271
|
-
await promptAllowingRejectedPrepare(
|
|
271
|
+
await promptAllowingRejectedPrepare(request);
|
|
272
272
|
}
|
|
273
273
|
if (output === void 0 && delivery.nextAction() === "request-delivery") {
|
|
274
274
|
delivery.closeBudget();
|
|
@@ -267,9 +267,8 @@ const PUBLIC_ROLE_RECORDS = [
|
|
|
267
267
|
bareCommand: false,
|
|
268
268
|
outputTool: NOTARY_OUTPUT_TOOL_NAME,
|
|
269
269
|
settlement: "accepted",
|
|
270
|
-
/**
|
|
270
|
+
/** Dialogue via shared resolveReviewSeatDialogueBody (review = fixed dispatch). */
|
|
271
271
|
reaskPrompt: true,
|
|
272
|
-
transportPrompt: "fixed-kickoff",
|
|
273
272
|
gateStageLabel: "\u7B26\u5B9D\u90CE",
|
|
274
273
|
/** Gate summon binds --source-run and keeps dialogue off the argv. */
|
|
275
274
|
gateSummon: "source-run",
|
|
@@ -292,6 +291,8 @@ const PUBLIC_ROLE_RECORDS = [
|
|
|
292
291
|
phases: [null],
|
|
293
292
|
outputTool: COUNTERSIGN_OUTPUT_TOOL_NAME,
|
|
294
293
|
settlement: "accepted",
|
|
294
|
+
/** Same shared dialogue resolver as other review seats (#1208 C1). */
|
|
295
|
+
reaskPrompt: true,
|
|
295
296
|
gateStageLabel: "\u7ED9\u4E8B\u4E2D",
|
|
296
297
|
/** Gate summon carries the parent payload as the instruction and a parent run id. */
|
|
297
298
|
gateSummon: "parent-instruction",
|
|
@@ -336,7 +336,9 @@ export function createPiRoleTurnHost(config) {
|
|
|
336
336
|
const roleEntry = await realpath(resolveInternalRoleEntrypoint(config.packageRoot));
|
|
337
337
|
const extraArgs = buildPiTurnExtraArgs(turnRequest, config.principalAuthority, config.extraPiArgs ?? []);
|
|
338
338
|
const args = buildExplicitInternalActivationArgs(roleEntry, extraArgs);
|
|
339
|
-
const
|
|
339
|
+
const transportBody = piUserDialogueBody(turnRequest);
|
|
340
|
+
// #1199: progress instruction is these same body bytes (actual seat input).
|
|
341
|
+
const stdin = encodeUserDialogueStdin(transportBody);
|
|
340
342
|
// Shared envelope isolates this call's court identity: omitting courtAttemptId
|
|
341
343
|
// must not inherit a parent process.env.AK_ROLE_COURT_ATTEMPT (#637).
|
|
342
344
|
const env = {
|
|
@@ -362,6 +364,9 @@ export function createPiRoleTurnHost(config) {
|
|
|
362
364
|
delete env.AK_ROLE_HOST;
|
|
363
365
|
else
|
|
364
366
|
env.AK_ROLE_HOST = request.host.trim();
|
|
367
|
+
// #1199: 传召词 is unknown-length body — never argv/env (execve ARG_MAX / E2BIG).
|
|
368
|
+
// Typed stdin envelope carries dialogue + optional progress 传召词.
|
|
369
|
+
delete env.AK_ROLE_SUMMONS_INSTRUCTION;
|
|
365
370
|
// #1132: the one effective delivery-request ceiling travels to the child
|
|
366
371
|
// on its own env so the in-child role runtime and the worker submission
|
|
367
372
|
// gate count with the same configured number the AK seam resolved. Omit
|
|
@@ -29,7 +29,7 @@ import { CliUsageError } from "./cli-errors.js";
|
|
|
29
29
|
import { admitPublicRole, admittedSourceRunPath, bindAdmittedTicketNumber, appendCallerFileFlagPaths, buildInstructionTransportPrompt, materializeCountersignInvocation, persistAdmittedAuditedSubmissionToolCallId, persistAdmittedSourceRunPath, readAdmittedAuditedSubmissionToolCallId, recordAdmittedCorrelation, recordChildDiaristRun, relocateAdmittedRunToTicket, } from "./invocation.js";
|
|
30
30
|
import { bindDiaristAssertedTicketNumber, presentControlledFailure, packageFaultNoteFor, prepareSummonsResumeMaterials, roleTurnOptions, runPostAdmissionOneShot, runPostAdmissionResumable, runPostAdmissionSeatResume, showResumeErrorPointer, resumeTurnRequestProjectionOptions, } from "./post-admission.js";
|
|
31
31
|
import { presentTerminal } from "./auto-resume.js";
|
|
32
|
-
import {
|
|
32
|
+
import { loadResumablePublicRole, markRunAdmitted, readCurrentCourt, } from "./run-lifecycle.js";
|
|
33
33
|
import { tryResumeSameTicketSeatRun } from "./seat-ticket-binding.js";
|
|
34
34
|
import { presentStructuralRejection, readBoundSessionEntries, trySettlePublicSeat, } from "./settlement.js";
|
|
35
35
|
import { warnMissingMethodSkills } from "./machine-method-skills.js";
|
|
@@ -49,6 +49,20 @@ const POST_SUBMISSION_ROUTING = {
|
|
|
49
49
|
judge: {
|
|
50
50
|
statuses: REVIEW_QUEUE_STATUSES,
|
|
51
51
|
},
|
|
52
|
+
// #1208 C1 / ADR 0055: every review-queue seat uses the shared
|
|
53
|
+
// unreadable-status seam (officerConclusionReask). Independent public
|
|
54
|
+
// entry for notary/auditor/inspector was the same miss — route here, do
|
|
55
|
+
// not invent a parallel loop. Gate summons still own the outer budget
|
|
56
|
+
// via nestedIncomplete when this seat exhausts unsettled.
|
|
57
|
+
notary: {
|
|
58
|
+
statuses: REVIEW_QUEUE_STATUSES,
|
|
59
|
+
},
|
|
60
|
+
auditor: {
|
|
61
|
+
statuses: REVIEW_QUEUE_STATUSES,
|
|
62
|
+
},
|
|
63
|
+
inspector: {
|
|
64
|
+
statuses: REVIEW_QUEUE_STATUSES,
|
|
65
|
+
},
|
|
52
66
|
coder: {
|
|
53
67
|
statuses: WORKER_ROUTING_STATUSES,
|
|
54
68
|
reask: WORKER_STATUS_REASK,
|
|
@@ -160,10 +174,13 @@ async function reaskUnreadablePostSubmissionStatus(admitted, terminal, env, io,
|
|
|
160
174
|
const next = withUnreadableReask(env);
|
|
161
175
|
if (next === undefined)
|
|
162
176
|
return UNREADABLE_REASK_EXHAUSTED;
|
|
177
|
+
// Named status-reask: summons opens a new court; message carries the diagnostic
|
|
178
|
+
// (not arbitrary summons.instruction passthrough through the review resolver).
|
|
163
179
|
return runPublicInstructionSeatResume({
|
|
164
180
|
runId: admitted.runId,
|
|
165
181
|
runDirectory: admitted.runDirectory,
|
|
166
|
-
|
|
182
|
+
message,
|
|
183
|
+
summons: { instructionEmpty: true },
|
|
167
184
|
}, next, io);
|
|
168
185
|
}
|
|
169
186
|
/**
|
|
@@ -201,10 +218,13 @@ async function reaskMissingTicketOnce(admitted, terminal, env, io) {
|
|
|
201
218
|
softTicketReaskTurn: true,
|
|
202
219
|
softTicketReaskOwnership,
|
|
203
220
|
};
|
|
221
|
+
// Named #1171 missing-ticket: summons opens a new court; message carries the
|
|
222
|
+
// package reask copy (not arbitrary summons.instruction passthrough).
|
|
204
223
|
const result = await runPublicInstructionSeatResume({
|
|
205
224
|
runId: admitted.runId,
|
|
206
225
|
runDirectory: admitted.runDirectory,
|
|
207
|
-
|
|
226
|
+
message: instruction,
|
|
227
|
+
summons: { instructionEmpty: true },
|
|
208
228
|
}, softReaskEnv, io);
|
|
209
229
|
if (softTicketReaskOwnership.sealedSubstitute
|
|
210
230
|
|| terminalCarriesSealedSubmission(result.terminal)) {
|
|
@@ -323,8 +343,8 @@ export function buildInstructionSeatTurnRequest(admitted, options) {
|
|
|
323
343
|
}
|
|
324
344
|
/**
|
|
325
345
|
* Direct review-seat call: reconnect ledger peer-body delivery (ADR 0085 / #1166).
|
|
326
|
-
* Gate summons already ride gateReviewInstruction; direct --source-run
|
|
327
|
-
*
|
|
346
|
+
* Gate summons already ride gateReviewInstruction; direct --source-run falls
|
|
347
|
+
* through the shared dialogue resolver (notary: fixed dispatch).
|
|
328
348
|
*/
|
|
329
349
|
async function loadLedgerPeerBody(sourceRunDirectory, projectRoot, home) {
|
|
330
350
|
const runId = runIdFromRunDirectory(sourceRunDirectory);
|
|
@@ -344,40 +364,50 @@ async function loadLedgerPeerBody(sourceRunDirectory, projectRoot, home) {
|
|
|
344
364
|
return undefined;
|
|
345
365
|
return readableGateItem(latest.accepted);
|
|
346
366
|
}
|
|
347
|
-
/** Owner-approved fixed Notary dispatch (2026-10-09); never the parent verdict. */
|
|
367
|
+
/** Owner-approved fixed Notary review dispatch (2026-10-09 #1208); never the parent verdict. */
|
|
348
368
|
export const NOTARY_FIXED_DISPATCH = "请审本轮受审对象,按符宝郎职掌交卷。";
|
|
349
369
|
/**
|
|
350
370
|
* One delivery rule for review-seat dialogue on new turns and same-parent resume
|
|
351
|
-
* (#1166 / ADR 0085 / ADR 0087):
|
|
352
|
-
*
|
|
353
|
-
*
|
|
354
|
-
*
|
|
371
|
+
* (#1166 / ADR 0085 / ADR 0087 / #1208): notary review uses fixed dispatch;
|
|
372
|
+
* named operational reasks ride reviewReask (first-mint / gate) or the resume
|
|
373
|
+
* request message seam — never arbitrary non-empty caller/summons passthrough.
|
|
374
|
+
* Other seats prefer format reask, then gate body, then caller dispatch, then
|
|
375
|
+
* ledger peer. Identity stays in startup materials. Notary never takes
|
|
376
|
+
* gate/parent verdict as dialogue (gateReviewInstruction stays unread for notary).
|
|
355
377
|
*/
|
|
356
|
-
async function resolveReviewSeatDialogueBody(input) {
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
378
|
+
export async function resolveReviewSeatDialogueBody(input) {
|
|
379
|
+
// #1208: fixed sentence is the review function only (owner 37bfe80d /
|
|
380
|
+
// 393daf98). reviewReask is the named operational override; caller/summons
|
|
381
|
+
// body is not a free passthrough (countersign rejected that prescription).
|
|
382
|
+
if (input.role === "notary") {
|
|
383
|
+
if (input.reviewReask !== undefined)
|
|
384
|
+
return input.reviewReask;
|
|
385
|
+
return NOTARY_FIXED_DISPATCH;
|
|
386
|
+
}
|
|
387
|
+
const preferred = input.reviewReask ?? input.gateReviewInstruction;
|
|
388
|
+
if (preferred !== undefined && preferred.length > 0)
|
|
389
|
+
return preferred;
|
|
360
390
|
const caller = input.callerInstruction ?? "";
|
|
361
391
|
if (caller.length > 0)
|
|
362
392
|
return caller;
|
|
363
393
|
const sourceRunPath = admittedSourceRunPath(input)?.trim();
|
|
364
394
|
if (sourceRunPath === undefined)
|
|
365
395
|
return undefined;
|
|
366
|
-
if (input.role === "notary") {
|
|
367
|
-
const { isTicketCourtCountersignSource } = await import("../run-terminal-artifacts.js");
|
|
368
|
-
if (isTicketCourtCountersignSource(sourceRunPath))
|
|
369
|
-
return NOTARY_FIXED_DISPATCH;
|
|
370
|
-
}
|
|
371
396
|
return await loadLedgerPeerBody(sourceRunPath, input.projectRoot, input.home);
|
|
372
397
|
}
|
|
373
|
-
|
|
398
|
+
/**
|
|
399
|
+
* Initial host prompt for this turn (#1199: progress instruction = these bytes).
|
|
400
|
+
*/
|
|
401
|
+
async function resolveInitialTurnPrompt(admitted, env) {
|
|
374
402
|
const record = roleRecord(admitted.role);
|
|
375
403
|
if ("reaskPrompt" in record && record.reaskPrompt === true) {
|
|
376
404
|
const sourceRunPath = admittedSourceRunPath(admitted);
|
|
377
|
-
const reask = env.reviewReask ?? env.gateReviewInstruction;
|
|
378
405
|
const body = await resolveReviewSeatDialogueBody({
|
|
379
406
|
role: admitted.role,
|
|
380
|
-
...(
|
|
407
|
+
...(env.reviewReask === undefined ? {} : { reviewReask: env.reviewReask }),
|
|
408
|
+
...(env.gateReviewInstruction === undefined
|
|
409
|
+
? {}
|
|
410
|
+
: { gateReviewInstruction: env.gateReviewInstruction }),
|
|
381
411
|
callerInstruction: admitted.instruction,
|
|
382
412
|
...(sourceRunPath === undefined ? {} : { sourceRunPath }),
|
|
383
413
|
projectRoot: admitted.projectRoot,
|
|
@@ -486,20 +516,21 @@ async function dispatchAdmitted(admitted, env, io) {
|
|
|
486
516
|
if (activeEnv.correlationId !== undefined && activeEnv.correlationId.trim() !== "") {
|
|
487
517
|
await recordAdmittedCorrelation(admitted, activeEnv.correlationId);
|
|
488
518
|
}
|
|
489
|
-
const
|
|
519
|
+
const initialPrompt = await resolveInitialTurnPrompt(admitted, activeEnv);
|
|
490
520
|
const auto = "inCallAutoResume" in record && record.inCallAutoResume === true;
|
|
491
521
|
if (auto) {
|
|
522
|
+
// #1208: auto-resume resends this turn's actual content, never a filler phrase.
|
|
492
523
|
return await runPostAdmissionResumable({
|
|
493
524
|
admitted,
|
|
494
525
|
env: activeEnv,
|
|
495
526
|
io: turnIo,
|
|
496
527
|
buildInitialRequest: () => buildInstructionSeatTurnRequest(admitted, roleTurnOptions(activeEnv, admitted, {
|
|
497
528
|
kind: "initial",
|
|
498
|
-
prompt:
|
|
529
|
+
prompt: initialPrompt,
|
|
499
530
|
})),
|
|
500
531
|
buildResumeRequest: () => buildInstructionSeatTurnRequest(admitted, roleTurnOptions(activeEnv, admitted, {
|
|
501
532
|
kind: "resume",
|
|
502
|
-
prompt:
|
|
533
|
+
prompt: initialPrompt,
|
|
503
534
|
})),
|
|
504
535
|
adapters,
|
|
505
536
|
...(activeEnv.engine === undefined ? {} : { effectiveEngine: activeEnv.engine }),
|
|
@@ -511,7 +542,7 @@ async function dispatchAdmitted(admitted, env, io) {
|
|
|
511
542
|
io: turnIo,
|
|
512
543
|
request: buildInstructionSeatTurnRequest(admitted, roleTurnOptions(activeEnv, admitted, {
|
|
513
544
|
kind: "initial",
|
|
514
|
-
prompt:
|
|
545
|
+
prompt: initialPrompt,
|
|
515
546
|
})),
|
|
516
547
|
adapters,
|
|
517
548
|
...(activeEnv.engine === undefined ? {} : { effectiveEngine: activeEnv.engine }),
|
|
@@ -607,22 +638,31 @@ function resumeSameParentInstructionSeat(input) {
|
|
|
607
638
|
...(input.ticketNumber === undefined ? {} : { ticketNumber: input.ticketNumber }),
|
|
608
639
|
freshSummons: input.env.freshSummons,
|
|
609
640
|
summons: input.summons,
|
|
610
|
-
resume: (runId, materials, runDirectory) =>
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
641
|
+
resume: (runId, materials, runDirectory) => {
|
|
642
|
+
// Named operational reask on this summon: explicit message seam.
|
|
643
|
+
// Review dialogue stays on summons → shared resolver (notary: fixed).
|
|
644
|
+
// Do not stuff reask into summons.instruction for later passthrough.
|
|
645
|
+
const reask = input.env.reviewReask;
|
|
646
|
+
return runPublicInstructionSeatResume({
|
|
647
|
+
runId,
|
|
648
|
+
runDirectory,
|
|
649
|
+
...(reask === undefined ? {} : { message: reask }),
|
|
650
|
+
...(materials === undefined ? {} : { summons: materials }),
|
|
651
|
+
}, input.env, input.io);
|
|
652
|
+
},
|
|
615
653
|
});
|
|
616
654
|
}
|
|
617
655
|
/**
|
|
618
|
-
* Same delivery rule as
|
|
619
|
-
*
|
|
656
|
+
* Same delivery rule as resolveInitialTurnPrompt for same-parent resume summons.
|
|
657
|
+
* Shared resolver owns the input choice — callers only pass env fields.
|
|
620
658
|
*/
|
|
621
659
|
async function sameParentDialogue(env, fallback, sourceRunPath, projectRoot, role) {
|
|
622
|
-
const reask = env.reviewReask ?? env.gateReviewInstruction;
|
|
623
660
|
const body = await resolveReviewSeatDialogueBody({
|
|
624
661
|
role,
|
|
625
|
-
...(
|
|
662
|
+
...(env.reviewReask === undefined ? {} : { reviewReask: env.reviewReask }),
|
|
663
|
+
...(env.gateReviewInstruction === undefined
|
|
664
|
+
? {}
|
|
665
|
+
: { gateReviewInstruction: env.gateReviewInstruction }),
|
|
626
666
|
callerInstruction: fallback.instruction,
|
|
627
667
|
sourceRunPath,
|
|
628
668
|
projectRoot,
|
|
@@ -638,15 +678,20 @@ async function sameParentDialogue(env, fallback, sourceRunPath, projectRoot, rol
|
|
|
638
678
|
* then the same one-shot settlement as every other seat.
|
|
639
679
|
*/
|
|
640
680
|
async function runCountersignBody(parsed, env, io) {
|
|
681
|
+
const projectRoot = resolve(parsed.project ?? env.cwd);
|
|
641
682
|
const gateParentRunPath = typeof env.parentRunPath === "string" && env.parentRunPath.trim() !== ""
|
|
642
683
|
? env.parentRunPath
|
|
643
684
|
: undefined;
|
|
644
685
|
if (gateParentRunPath !== undefined) {
|
|
645
|
-
|
|
686
|
+
// #1208 C1: same shared dialogue resolver as every other same-parent seat.
|
|
687
|
+
const dialogue = await sameParentDialogue(env, {
|
|
688
|
+
instruction: parsed.instruction ?? "",
|
|
689
|
+
instructionEmpty: (parsed.instruction ?? "").length === 0,
|
|
690
|
+
}, gateParentRunPath, projectRoot, "countersign");
|
|
646
691
|
const resumed = await resumeSameParentInstructionSeat({
|
|
647
692
|
env,
|
|
648
693
|
io,
|
|
649
|
-
projectRoot
|
|
694
|
+
projectRoot,
|
|
650
695
|
role: "countersign",
|
|
651
696
|
parentRunPath: gateParentRunPath,
|
|
652
697
|
...(isSafePositiveTicketNumber(env.boundTicketNumber)
|
|
@@ -654,8 +699,8 @@ async function runCountersignBody(parsed, env, io) {
|
|
|
654
699
|
: {}),
|
|
655
700
|
summons: {
|
|
656
701
|
sourceRunPath: gateParentRunPath,
|
|
657
|
-
instruction:
|
|
658
|
-
instructionEmpty:
|
|
702
|
+
instruction: dialogue.instruction,
|
|
703
|
+
instructionEmpty: dialogue.instructionEmpty,
|
|
659
704
|
// #1166 J11: same-parent resume delivers this call's file-flag paths
|
|
660
705
|
// through the shared summons → appendCallerFileFlagPaths rule.
|
|
661
706
|
attachmentPaths: parsed.attachmentPaths ?? [],
|
|
@@ -691,14 +736,10 @@ async function runCountersignBody(parsed, env, io) {
|
|
|
691
736
|
await persistAdmittedSourceRunPath(admitted, gateParentRunPath);
|
|
692
737
|
admitted = { ...admitted, sourceRunPath: gateParentRunPath };
|
|
693
738
|
}
|
|
694
|
-
// #1166 J11:
|
|
695
|
-
// resolveInitialPrompt / resumeTurnRequestProjectionOptions — never body alone.
|
|
696
|
-
const reviewBody = env.reviewReask ?? env.gateReviewInstruction;
|
|
739
|
+
// #1208 C1 / #1166 J11: one shared initial-prompt seam (incl. file flags).
|
|
697
740
|
const turnProjection = roleTurnOptions(env, admitted, {
|
|
698
741
|
kind: "initial",
|
|
699
|
-
prompt:
|
|
700
|
-
? appendCallerFileFlagPaths(reviewBody, admitted.attachments)
|
|
701
|
-
: buildInstructionTransportPrompt(admitted),
|
|
742
|
+
prompt: await resolveInitialTurnPrompt(admitted, env),
|
|
702
743
|
});
|
|
703
744
|
const turnRequest = buildInstructionSeatTurnRequest(admitted, turnProjection);
|
|
704
745
|
const result = await runPostAdmissionOneShot({
|
|
@@ -902,6 +943,10 @@ export async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
|
|
|
902
943
|
await persistAdmittedSourceRunPath(admitted, auditorSource, auditorSubject);
|
|
903
944
|
admitted = { ...admitted, sourceRunPath: auditorSource };
|
|
904
945
|
}
|
|
946
|
+
// #1208 C2: same helper as resume — known board ticket on the audited
|
|
947
|
+
// source binds and relocates before the missing-ticket soft reask can
|
|
948
|
+
// fire. True no-ticket sources stay unbound (#1171 asks once).
|
|
949
|
+
admitted = await inheritKnownTicketFromSource(admitted, env.principalAuthority);
|
|
905
950
|
const runAdmitted = async () => {
|
|
906
951
|
await markRunAdmitted(admitted, env.principalAuthority);
|
|
907
952
|
if (role === "secretariat") {
|
|
@@ -946,6 +991,24 @@ export async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
|
|
|
946
991
|
}
|
|
947
992
|
return runAdmitted();
|
|
948
993
|
}
|
|
994
|
+
/**
|
|
995
|
+
* #1208 C2: same as new source-locator admission — when this leg is still
|
|
996
|
+
* unbound, inherit the board ticket already on the audited source and relocate.
|
|
997
|
+
* True no-ticket sources stay unbound so #1171 still asks once.
|
|
998
|
+
*/
|
|
999
|
+
async function inheritKnownTicketFromSource(admitted, authority) {
|
|
1000
|
+
if (admitted.ticketNumber !== undefined)
|
|
1001
|
+
return admitted;
|
|
1002
|
+
const sourcePath = admittedSourceRunPath(admitted);
|
|
1003
|
+
if (sourcePath === undefined)
|
|
1004
|
+
return admitted;
|
|
1005
|
+
const sourceTicket = await readBoardTicketNumber(sourcePath);
|
|
1006
|
+
if (sourceTicket === undefined)
|
|
1007
|
+
return admitted;
|
|
1008
|
+
await bindAdmittedTicketNumber(admitted, sourceTicket);
|
|
1009
|
+
await relocateAdmittedRunToTicket(admitted, authority);
|
|
1010
|
+
return admitted;
|
|
1011
|
+
}
|
|
949
1012
|
export async function runPublicInstructionSeatResume(request, env, io) {
|
|
950
1013
|
let selectedRequest = request;
|
|
951
1014
|
const resume = async () => {
|
|
@@ -960,24 +1023,48 @@ export async function runPublicInstructionSeatResume(request, env, io) {
|
|
|
960
1023
|
io: turnIo,
|
|
961
1024
|
load: async (effective) => {
|
|
962
1025
|
const loaded = await loadResumablePublicRole(env.home, effective.runId, env.principalAuthority, effective.runDirectory === undefined ? undefined : { runDirectory: effective.runDirectory });
|
|
963
|
-
|
|
1026
|
+
let admitted = loaded.admitted;
|
|
1027
|
+
if (packagedRebindSourceOnResume(admitted.role)
|
|
964
1028
|
&& effective.summons?.sourceRunPath !== undefined
|
|
965
1029
|
&& effective.summons.sourceRun !== undefined) {
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
admitted
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
sourceRun: effective.summons.sourceRun,
|
|
972
|
-
},
|
|
1030
|
+
// source-locator seats only (notary); sourceRun is on that admission face.
|
|
1031
|
+
admitted = {
|
|
1032
|
+
...admitted,
|
|
1033
|
+
sourceRunPath: effective.summons.sourceRunPath,
|
|
1034
|
+
sourceRun: effective.summons.sourceRun,
|
|
973
1035
|
};
|
|
974
1036
|
}
|
|
975
|
-
|
|
1037
|
+
admitted = await inheritKnownTicketFromSource(admitted, env.principalAuthority);
|
|
1038
|
+
return { ...loaded, admitted };
|
|
976
1039
|
},
|
|
977
1040
|
buildTurnRequest: async (admitted, effective) => {
|
|
978
1041
|
const summonsPrepared = await prepareSummonsResumeMaterials(admitted.runDirectory, effective.summons);
|
|
1042
|
+
const projection = resumeTurnRequestProjectionOptions(admitted, effective, env, summonsPrepared);
|
|
1043
|
+
// #1208: internal summons only — shared resolver owns review dialogue.
|
|
1044
|
+
// Public bare resume / explicit message keep projection (operational
|
|
1045
|
+
// reasks use the message seam). Do not reselect stale env dialogue over
|
|
1046
|
+
// this-round summons (#1208 R1).
|
|
1047
|
+
if (effective.summons === undefined || effective.message !== undefined) {
|
|
1048
|
+
return buildInstructionSeatTurnRequest(admitted, { ...projection });
|
|
1049
|
+
}
|
|
1050
|
+
const sourceRunPath = admittedSourceRunPath(admitted);
|
|
1051
|
+
const body = await resolveReviewSeatDialogueBody({
|
|
1052
|
+
role: admitted.role,
|
|
1053
|
+
callerInstruction: summonsPrepared?.instruction ?? "",
|
|
1054
|
+
...(sourceRunPath === undefined ? {} : { sourceRunPath }),
|
|
1055
|
+
projectRoot: admitted.projectRoot,
|
|
1056
|
+
home: env.home,
|
|
1057
|
+
});
|
|
1058
|
+
if (body === undefined) {
|
|
1059
|
+
return buildInstructionSeatTurnRequest(admitted, { ...projection });
|
|
1060
|
+
}
|
|
1061
|
+
const fileFlags = summonsPrepared?.attachments ?? [];
|
|
1062
|
+
const prompt = fileFlags.length === 0
|
|
1063
|
+
? body
|
|
1064
|
+
: appendCallerFileFlagPaths(body, fileFlags);
|
|
979
1065
|
return buildInstructionSeatTurnRequest(admitted, {
|
|
980
|
-
...
|
|
1066
|
+
...projection,
|
|
1067
|
+
continuation: { kind: "resume", prompt },
|
|
981
1068
|
});
|
|
982
1069
|
},
|
|
983
1070
|
adapters: {
|
|
@@ -1037,9 +1124,12 @@ async function queueConclusionFromChild(child, env, io) {
|
|
|
1037
1124
|
return { stop: { exitCode: 0, ...(terminal === undefined ? {} : { terminal }) } };
|
|
1038
1125
|
}
|
|
1039
1126
|
let current = child;
|
|
1040
|
-
//
|
|
1041
|
-
//
|
|
1042
|
-
//
|
|
1127
|
+
// #1208: review-queue gate children also have seat-local
|
|
1128
|
+
// POST_SUBMISSION_ROUTING. This parent-side loop remains the
|
|
1129
|
+
// gate/correlation budget; nestedIncomplete from an exhausted seat-local
|
|
1130
|
+
// chain surfaces without a second spend. The child resume keeps the
|
|
1131
|
+
// caller's env so delivery, failure recovery, and other reask loops
|
|
1132
|
+
// stay separate.
|
|
1043
1133
|
let budgetEnv = envForCourtContinue(env);
|
|
1044
1134
|
for (;;) {
|
|
1045
1135
|
const terminal = await trySettlePublicSeat(current, env.principalAuthority, { ...await readCurrentCourt(current.runDirectory), ...packageFaultScope(current, env, io) });
|
|
@@ -1177,7 +1267,8 @@ async function auditSubmittedRole(turn, env, io, resumedOfficer, passedReceipt)
|
|
|
1177
1267
|
return runPublicInstructionSeatResume({
|
|
1178
1268
|
runId: admitted.runId,
|
|
1179
1269
|
runDirectory: admitted.runDirectory,
|
|
1180
|
-
|
|
1270
|
+
message: SECRETARIAT_STATUS_REASK,
|
|
1271
|
+
summons: { instructionEmpty: true },
|
|
1181
1272
|
}, next, io);
|
|
1182
1273
|
}
|
|
1183
1274
|
if (admitted.role === "countersign" && (typeof status !== "string" || !REVIEW_QUEUE_STATUSES.has(status))) {
|
|
@@ -1192,7 +1283,8 @@ async function auditSubmittedRole(turn, env, io, resumedOfficer, passedReceipt)
|
|
|
1192
1283
|
return runPublicInstructionSeatResume({
|
|
1193
1284
|
runId: admitted.runId,
|
|
1194
1285
|
runDirectory: admitted.runDirectory,
|
|
1195
|
-
|
|
1286
|
+
message: officerConclusionReask(status),
|
|
1287
|
+
summons: { instructionEmpty: true },
|
|
1196
1288
|
}, next, io);
|
|
1197
1289
|
}
|
|
1198
1290
|
// Self-escalation is a valid open routing state for these seats only.
|