@akagilnc/pi-workflow-roles 0.1.5406 → 0.1.5475
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/CLAUDE.md +1 -1
- package/README.md +42 -55
- package/README.zh-CN.md +59 -73
- package/THIRD_PARTY_NOTICES.md +4 -7
- package/dist/acp-host/production-host.js +8261 -9073
- package/dist/collector-tool-schemas.js +1 -1
- package/dist/compliance-transport.js +2 -5
- package/dist/engine-detour-usage.js +3 -30
- package/dist/gatekeeper-role.js +4 -18
- package/dist/headless-host/description.js +0 -209
- package/dist/headless-host/production-host.js +6973 -8035
- package/dist/host-contracts.js +8 -0
- package/dist/migrate-book-topology.js +30 -27
- package/dist/packaged-role-registry.js +1 -9
- package/dist/pi/role-turn-host.js +37 -19
- package/dist/public-cli/auto-resume.js +29 -66
- package/dist/public-cli/countersign-run.js +4 -18
- package/dist/public-cli/instruction-seat-run.js +59 -76
- package/dist/public-cli/main.js +9844 -10720
- package/dist/public-cli/option-definitions.js +1 -1
- package/dist/public-cli/post-admission.js +204 -285
- package/dist/public-cli/process-cancel.js +8 -0
- package/dist/public-cli/run-lifecycle.js +24 -94
- package/dist/public-cli/settlement.js +614 -1524
- package/dist/public-cli/terminal.js +23 -53
- package/dist/public-role-summons.js +3 -8
- package/dist/receipt-delivery-policy.js +11 -12
- package/dist/run-terminal-artifacts.js +19 -14
- package/dist/serialize-thrown-value.js +7 -1
- package/dist/submission-ledger.js +21 -89
- package/package.json +1 -1
- package/packets/fixer-repair.md +3 -1
- package/packets/judge-apply.md +7 -16
- package/packets/judge-authority.md +7 -17
- package/packets/judge-plan.md +7 -18
- package/packets/judge-review.md +8 -22
- package/packets/judge-submission.md +4 -7
- package/resources/collector-bot-handbook.md +2 -2
- package/resources/diarist-collect.md +2 -2
- package/resources/engine-dispatch.md +2 -2
- package/resources/navigator-route-playbook.md +1 -1
- package/resources/secretariat-ticket-identity.md +1 -1
- package/scripts/build-package.mjs +0 -2
- package/souls/coder-output-guide.md +3 -3
- package/souls/coder.md +2 -3
- package/souls/doctor-auditor.md +0 -3
- package/souls/fixer-auditor.md +0 -2
- package/souls/fixer-output-guide.md +3 -3
- package/souls/fixer.md +2 -2
- package/souls/gate-output-guide.md +1 -1
- package/souls/quality-law.md +2 -0
- package/src/acp-host/role-turn-host.ts +168 -75
- package/src/collector-tool-schemas.ts +1 -1
- package/src/compliance-transport.ts +3 -6
- package/src/engine-detour-usage.ts +3 -33
- package/src/external-host-turn-loop.ts +81 -36
- package/src/gatekeeper-role.ts +5 -20
- package/src/headless-host/description.ts +4 -214
- package/src/headless-host/production-host.ts +2 -1
- package/src/headless-host/role-turn-host.ts +153 -186
- package/src/host-contracts.ts +13 -10
- package/src/navigator-public-session.ts +1 -1
- package/src/navigator-session-contracts.ts +1 -1
- package/src/package-contracts/gatekeeper-output.ts +1 -1
- package/src/package-contracts/navigator-output.ts +1 -1
- package/src/package-contracts/terminating-infrastructure.ts +1 -1
- package/src/packaged-role-registry.ts +2 -10
- package/src/pi/adapter.ts +0 -3
- package/src/pi/role-turn-host.ts +42 -28
- package/src/prepared-role-turn.ts +2 -0
- package/src/public-cli/auto-resume.ts +27 -66
- package/src/public-cli/countersign-run.ts +4 -22
- package/src/public-cli/instruction-seat-run.ts +79 -80
- package/src/public-cli/option-definitions.ts +1 -1
- package/src/public-cli/post-admission.ts +264 -340
- package/src/public-cli/process-cancel.ts +9 -0
- package/src/public-cli/run-lifecycle.ts +25 -126
- package/src/public-cli/settlement.ts +792 -1912
- package/src/public-cli/terminal.ts +29 -69
- package/src/public-role-summons.ts +3 -8
- package/src/receipt-delivery-policy.ts +11 -12
- package/src/role-envelope.ts +16 -9
- package/src/role-runtime.ts +14 -81
- package/src/run-terminal-artifacts.ts +21 -17
- package/src/serialize-thrown-value.ts +7 -1
- package/src/submission-ledger.ts +30 -116
- package/dist/audit-escalation.js +0 -7
- package/dist/pi/known-failure.js +0 -51
- package/dist/typed-provider-http.js +0 -57
- package/dist/upstream-error-testimony.js +0 -19
- package/src/pi/known-failure.ts +0 -76
- package/src/typed-provider-http.ts +0 -89
- package/src/upstream-error-testimony.ts +0 -45
package/dist/host-contracts.js
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Controlled post-admission failure classes (ADR 0052 / #107). Owner = host contract.
|
|
3
|
+
* Closed set of typed facts only — never a fabricated "could not classify" label (#881).
|
|
4
|
+
* When no typed confirmation exists, omit cause and keep the original diagnostic / error pointer.
|
|
5
|
+
*/
|
|
6
|
+
export const CONTROLLED_FAILURE_CAUSES = [
|
|
7
|
+
"activation", "provider", "session", "output", "timeout",
|
|
8
|
+
];
|
|
1
9
|
/**
|
|
2
10
|
* Thrown activation failure with a production-owned typed cause.
|
|
3
11
|
* Prefer this over ad-hoc Error property tags so settlement retains typed identity.
|
|
@@ -682,14 +682,6 @@ var init_cli_errors = __esm({
|
|
|
682
682
|
}
|
|
683
683
|
});
|
|
684
684
|
|
|
685
|
-
// src/typed-provider-http.ts
|
|
686
|
-
var init_typed_provider_http = __esm({
|
|
687
|
-
"src/typed-provider-http.ts"() {
|
|
688
|
-
"use strict";
|
|
689
|
-
init_unknown_value();
|
|
690
|
-
}
|
|
691
|
-
});
|
|
692
|
-
|
|
693
685
|
// src/sha256.ts
|
|
694
686
|
import { createHash } from "node:crypto";
|
|
695
687
|
function sha256Hex(bytes) {
|
|
@@ -14057,7 +14049,6 @@ var init_packaged_role_registry = __esm({
|
|
|
14057
14049
|
outputTool: JUDGE_OUTPUT_TOOL_NAME,
|
|
14058
14050
|
auditTool: JUDGE_AUDIT_TOOL_NAME,
|
|
14059
14051
|
settlement: "sealed",
|
|
14060
|
-
runnerFailure: "engine-detour-known-first",
|
|
14061
14052
|
/** Factory board: court until another station has started, then marshal. */
|
|
14062
14053
|
boardPlacement: "judge-history",
|
|
14063
14054
|
/** Navigator subject is the public admitted instruction when the run is bound. */
|
|
@@ -14175,7 +14166,6 @@ var init_packaged_role_registry = __esm({
|
|
|
14175
14166
|
},
|
|
14176
14167
|
/** Frozen base/lens/authority become the initial prompt; instruction follows. */
|
|
14177
14168
|
transportPrompt: "skill-args",
|
|
14178
|
-
runnerFailure: "engine-detour-record-first",
|
|
14179
14169
|
boardPlacement: "marshal",
|
|
14180
14170
|
activationFlags: [
|
|
14181
14171
|
{ field: "baseRevision", flag: "ak-review-base" },
|
|
@@ -14270,10 +14260,7 @@ var init_packaged_role_registry = __esm({
|
|
|
14270
14260
|
/** Method-material load failure keeps the activation cause (not reviewer/fixer). */
|
|
14271
14261
|
phases: [null],
|
|
14272
14262
|
outputTool: MERGER_OUTPUT_TOOL_NAME,
|
|
14273
|
-
settlement: "
|
|
14274
|
-
/** #836: residual scan stays on the whole host session. */
|
|
14275
|
-
residualScan: "session",
|
|
14276
|
-
residualTool: MERGER_OUTPUT_TOOL_NAME,
|
|
14263
|
+
settlement: "sealed",
|
|
14277
14264
|
artifactFace: {
|
|
14278
14265
|
evidenceRole: true,
|
|
14279
14266
|
leaves: [
|
|
@@ -14450,7 +14437,6 @@ var init_packaged_role_registry = __esm({
|
|
|
14450
14437
|
phases: [null],
|
|
14451
14438
|
outputTool: GATEKEEPER_OUTPUT_TOOL_NAME,
|
|
14452
14439
|
settlement: "accepted",
|
|
14453
|
-
runnerFailure: "engine-detour-record-first",
|
|
14454
14440
|
activationStage: "load-and-install",
|
|
14455
14441
|
// Province materials; officers reuse their own public records below.
|
|
14456
14442
|
sessionMaterials: ["CLAUDE.md", "souls/gatekeeper.md", "souls/quality-law.md", "souls/gate-output-guide.md"]
|
|
@@ -14465,7 +14451,6 @@ var init_packaged_role_registry = __esm({
|
|
|
14465
14451
|
phases: [null],
|
|
14466
14452
|
outputTool: NAVIGATOR_OUTPUT_TOOL_NAME,
|
|
14467
14453
|
settlement: "accepted",
|
|
14468
|
-
runnerFailure: "engine-detour-record-first",
|
|
14469
14454
|
activationStage: "load-and-install",
|
|
14470
14455
|
sessionMaterials: ["CLAUDE.md", "souls/navigator.md"]
|
|
14471
14456
|
},
|
|
@@ -14488,7 +14473,6 @@ var init_packaged_role_registry = __esm({
|
|
|
14488
14473
|
settlement: "accepted",
|
|
14489
14474
|
/** Court reask replaces the initial prompt. */
|
|
14490
14475
|
reaskPrompt: true,
|
|
14491
|
-
runnerFailure: "engine-detour-record-first",
|
|
14492
14476
|
gateStageLabel: "\u5BA1\u5211\u9662",
|
|
14493
14477
|
/** Gate summon binds --subject judge and --source-run. */
|
|
14494
14478
|
gateSummon: "subject-source",
|
|
@@ -14690,12 +14674,38 @@ var init_role_submission_declarations = __esm({
|
|
|
14690
14674
|
}
|
|
14691
14675
|
});
|
|
14692
14676
|
|
|
14677
|
+
// src/serialize-thrown-value.ts
|
|
14678
|
+
var init_serialize_thrown_value = __esm({
|
|
14679
|
+
"src/serialize-thrown-value.ts"() {
|
|
14680
|
+
"use strict";
|
|
14681
|
+
}
|
|
14682
|
+
});
|
|
14683
|
+
|
|
14684
|
+
// src/public-cli/terminal.ts
|
|
14685
|
+
var init_terminal = __esm({
|
|
14686
|
+
"src/public-cli/terminal.ts"() {
|
|
14687
|
+
"use strict";
|
|
14688
|
+
init_serialize_thrown_value();
|
|
14689
|
+
}
|
|
14690
|
+
});
|
|
14691
|
+
|
|
14693
14692
|
// src/run-terminal-artifacts.ts
|
|
14693
|
+
var RUN_TERMINAL_ERROR_SETTLEMENT_FILE, RUN_TERMINAL_ERROR_FALLBACK_RELATIVE_PATHS, UNIQUE_ERROR_FALLBACK_STEM, UNIQUE_ERROR_FALLBACK_NAME;
|
|
14694
14694
|
var init_run_terminal_artifacts = __esm({
|
|
14695
14695
|
"src/run-terminal-artifacts.ts"() {
|
|
14696
14696
|
"use strict";
|
|
14697
14697
|
init_role_run_placement();
|
|
14698
14698
|
init_unknown_value();
|
|
14699
|
+
RUN_TERMINAL_ERROR_SETTLEMENT_FILE = "error.settlement.json";
|
|
14700
|
+
RUN_TERMINAL_ERROR_FALLBACK_RELATIVE_PATHS = [
|
|
14701
|
+
`artifacts/${RUN_TERMINAL_ERROR_SETTLEMENT_FILE}`,
|
|
14702
|
+
RUN_TERMINAL_ERROR_SETTLEMENT_FILE
|
|
14703
|
+
];
|
|
14704
|
+
UNIQUE_ERROR_FALLBACK_STEM = "error";
|
|
14705
|
+
UNIQUE_ERROR_FALLBACK_NAME = new RegExp(
|
|
14706
|
+
`^${UNIQUE_ERROR_FALLBACK_STEM}\\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\.json$`,
|
|
14707
|
+
"i"
|
|
14708
|
+
);
|
|
14699
14709
|
}
|
|
14700
14710
|
});
|
|
14701
14711
|
|
|
@@ -14711,20 +14721,15 @@ var init_gatekeeper_role = __esm({
|
|
|
14711
14721
|
init_review_submission();
|
|
14712
14722
|
init_gatekeeper_output();
|
|
14713
14723
|
init_role_submission_declarations();
|
|
14724
|
+
init_terminal();
|
|
14714
14725
|
init_run_terminal_artifacts();
|
|
14715
14726
|
init_unknown_value();
|
|
14727
|
+
init_serialize_thrown_value();
|
|
14716
14728
|
init_submission_errors();
|
|
14717
14729
|
GATEKEEPER_TOOL_SPEC = roleSubmissionDeclaration("gatekeeper");
|
|
14718
14730
|
}
|
|
14719
14731
|
});
|
|
14720
14732
|
|
|
14721
|
-
// src/public-cli/terminal.ts
|
|
14722
|
-
var init_terminal = __esm({
|
|
14723
|
-
"src/public-cli/terminal.ts"() {
|
|
14724
|
-
"use strict";
|
|
14725
|
-
}
|
|
14726
|
-
});
|
|
14727
|
-
|
|
14728
14733
|
// src/host-descriptions.ts
|
|
14729
14734
|
var HOST_DESCRIPTIONS, HEADLESS_HOST_DESCRIPTIONS;
|
|
14730
14735
|
var init_host_descriptions = __esm({
|
|
@@ -16057,7 +16062,7 @@ var init_option_definitions = __esm({
|
|
|
16057
16062
|
},
|
|
16058
16063
|
notary: {
|
|
16059
16064
|
command: "notary",
|
|
16060
|
-
summary: "Direct Notary
|
|
16065
|
+
summary: "Direct Notary summons; duties: souls/notary.md. Zero prompt/attachment.",
|
|
16061
16066
|
usage: ["ak-role notary --source-run <runId@role|path> [options]"],
|
|
16062
16067
|
examples: [
|
|
16063
16068
|
"ak-role notary --source-run 01a034f1-75bf-71a6-bcf5-d1299145b1a5@judge",
|
|
@@ -16220,8 +16225,6 @@ var init_run_lifecycle = __esm({
|
|
|
16220
16225
|
init_role_run_placement();
|
|
16221
16226
|
init_run_ticket_number();
|
|
16222
16227
|
init_cli_errors();
|
|
16223
|
-
init_typed_provider_http();
|
|
16224
|
-
init_typed_provider_http();
|
|
16225
16228
|
init_collector_config();
|
|
16226
16229
|
init_role_run_relocation();
|
|
16227
16230
|
init_engine_material();
|
|
@@ -59,7 +59,6 @@ const PUBLIC_ROLE_RECORDS = [
|
|
|
59
59
|
outputTool: JUDGE_OUTPUT_TOOL_NAME,
|
|
60
60
|
auditTool: JUDGE_AUDIT_TOOL_NAME,
|
|
61
61
|
settlement: "sealed",
|
|
62
|
-
runnerFailure: "engine-detour-known-first",
|
|
63
62
|
/** Factory board: court until another station has started, then marshal. */
|
|
64
63
|
boardPlacement: "judge-history",
|
|
65
64
|
/** Navigator subject is the public admitted instruction when the run is bound. */
|
|
@@ -177,7 +176,6 @@ const PUBLIC_ROLE_RECORDS = [
|
|
|
177
176
|
},
|
|
178
177
|
/** Frozen base/lens/authority become the initial prompt; instruction follows. */
|
|
179
178
|
transportPrompt: "skill-args",
|
|
180
|
-
runnerFailure: "engine-detour-record-first",
|
|
181
179
|
boardPlacement: "marshal",
|
|
182
180
|
activationFlags: [
|
|
183
181
|
{ field: "baseRevision", flag: "ak-review-base" },
|
|
@@ -272,10 +270,7 @@ const PUBLIC_ROLE_RECORDS = [
|
|
|
272
270
|
/** Method-material load failure keeps the activation cause (not reviewer/fixer). */
|
|
273
271
|
phases: [null],
|
|
274
272
|
outputTool: MERGER_OUTPUT_TOOL_NAME,
|
|
275
|
-
settlement: "
|
|
276
|
-
/** #836: residual scan stays on the whole host session. */
|
|
277
|
-
residualScan: "session",
|
|
278
|
-
residualTool: MERGER_OUTPUT_TOOL_NAME,
|
|
273
|
+
settlement: "sealed",
|
|
279
274
|
artifactFace: {
|
|
280
275
|
evidenceRole: true,
|
|
281
276
|
leaves: [
|
|
@@ -452,7 +447,6 @@ const PUBLIC_ROLE_RECORDS = [
|
|
|
452
447
|
phases: [null],
|
|
453
448
|
outputTool: GATEKEEPER_OUTPUT_TOOL_NAME,
|
|
454
449
|
settlement: "accepted",
|
|
455
|
-
runnerFailure: "engine-detour-record-first",
|
|
456
450
|
activationStage: "load-and-install",
|
|
457
451
|
// Province materials; officers reuse their own public records below.
|
|
458
452
|
sessionMaterials: ["CLAUDE.md", "souls/gatekeeper.md", "souls/quality-law.md", "souls/gate-output-guide.md"]
|
|
@@ -467,7 +461,6 @@ const PUBLIC_ROLE_RECORDS = [
|
|
|
467
461
|
phases: [null],
|
|
468
462
|
outputTool: NAVIGATOR_OUTPUT_TOOL_NAME,
|
|
469
463
|
settlement: "accepted",
|
|
470
|
-
runnerFailure: "engine-detour-record-first",
|
|
471
464
|
activationStage: "load-and-install",
|
|
472
465
|
sessionMaterials: ["CLAUDE.md", "souls/navigator.md"]
|
|
473
466
|
},
|
|
@@ -490,7 +483,6 @@ const PUBLIC_ROLE_RECORDS = [
|
|
|
490
483
|
settlement: "accepted",
|
|
491
484
|
/** Court reask replaces the initial prompt. */
|
|
492
485
|
reaskPrompt: true,
|
|
493
|
-
runnerFailure: "engine-detour-record-first",
|
|
494
486
|
gateStageLabel: "\u5BA1\u5211\u9662",
|
|
495
487
|
/** Gate summon binds --subject judge and --source-run. */
|
|
496
488
|
gateSummon: "subject-source",
|
|
@@ -14,6 +14,8 @@ import { ExplicitInternalActivationError } from "../host-contracts.js";
|
|
|
14
14
|
import { applyEngineChildEnv, ENGINE_MODEL_FLAG_NAME, normalizeEngineName } from "../engine-detour.js";
|
|
15
15
|
import { projectActivationFlags } from "../role-activation-flags.js";
|
|
16
16
|
import { encodeUserDialogueStdin } from "../user-dialogue-stdin.js";
|
|
17
|
+
import { projectThrownFailureLeaf, retainPackageFault } from "../public-cli/settlement.js";
|
|
18
|
+
import { describeErrorIdentity } from "../public-cli/run-lifecycle.js";
|
|
17
19
|
import { RECEIPT_DELIVERY_LIMIT_ENV } from "../receipt-delivery-policy.js";
|
|
18
20
|
/** Package-relative Internal role entrypoint (ADR 0052; same path as public-cli registry). */
|
|
19
21
|
const INTERNAL_ROLE_ENTRYPOINT_RELATIVE = "extensions/role-runtime.ts";
|
|
@@ -191,7 +193,6 @@ export function createDefaultPiSpawnRunner(options) {
|
|
|
191
193
|
// fall back to rejecting on `error` if `close` never fires (e.g. spawn
|
|
192
194
|
// never succeeded so no `close` event will arrive).
|
|
193
195
|
let hasSpawned = false;
|
|
194
|
-
let executionError;
|
|
195
196
|
const armTimeoutAfterChildReady = () => {
|
|
196
197
|
if (spawnOptions.timeoutMs === undefined)
|
|
197
198
|
return;
|
|
@@ -207,6 +208,8 @@ export function createDefaultPiSpawnRunner(options) {
|
|
|
207
208
|
child.kill("SIGTERM");
|
|
208
209
|
};
|
|
209
210
|
parentSignal?.addEventListener("abort", terminateForParentAbort, { once: true });
|
|
211
|
+
const packageErrors = [];
|
|
212
|
+
let identityFailure;
|
|
210
213
|
let identityRecorded = Promise.resolve();
|
|
211
214
|
child.once("spawn", () => {
|
|
212
215
|
hasSpawned = true;
|
|
@@ -217,7 +220,10 @@ export function createDefaultPiSpawnRunner(options) {
|
|
|
217
220
|
if (typeof runDirectory === "string" &&
|
|
218
221
|
runDirectory !== "" &&
|
|
219
222
|
options.recordLaunchedPiIdentity !== undefined) {
|
|
220
|
-
identityRecorded = options.recordLaunchedPiIdentity(runDirectory, piIdentity)
|
|
223
|
+
identityRecorded = Promise.resolve().then(() => options.recordLaunchedPiIdentity(runDirectory, piIdentity)).catch((error) => {
|
|
224
|
+
packageErrors.push(error);
|
|
225
|
+
identityFailure = projectThrownFailureLeaf(error);
|
|
226
|
+
});
|
|
221
227
|
}
|
|
222
228
|
});
|
|
223
229
|
child.stderr.setEncoding("utf8").on("data", (chunk) => {
|
|
@@ -227,8 +233,10 @@ export function createDefaultPiSpawnRunner(options) {
|
|
|
227
233
|
// A pre-spawn error has no child lifecycle to close. After spawn,
|
|
228
234
|
// retain the execution error and let the mandatory close event own
|
|
229
235
|
// cleanup and the single settlement.
|
|
230
|
-
if (settled
|
|
231
|
-
|
|
236
|
+
if (settled)
|
|
237
|
+
return;
|
|
238
|
+
if (hasSpawned) {
|
|
239
|
+
packageErrors.push(error);
|
|
232
240
|
return;
|
|
233
241
|
}
|
|
234
242
|
if (timer !== undefined)
|
|
@@ -237,33 +245,43 @@ export function createDefaultPiSpawnRunner(options) {
|
|
|
237
245
|
settled = true;
|
|
238
246
|
reject(error);
|
|
239
247
|
});
|
|
240
|
-
|
|
248
|
+
// `close` carries (code, signal): a signal-killed child reports code null.
|
|
249
|
+
// Both travel out so a signal death is never read as a clean exit.
|
|
250
|
+
child.on("close", (code, closeSignal) => {
|
|
241
251
|
if (timer !== undefined)
|
|
242
252
|
clearTimeout(timer);
|
|
243
253
|
parentSignal?.removeEventListener("abort", terminateForParentAbort);
|
|
244
|
-
void
|
|
254
|
+
void (async () => {
|
|
245
255
|
if (settled)
|
|
246
256
|
return;
|
|
247
257
|
settled = true;
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
258
|
+
await identityRecorded;
|
|
259
|
+
if (stdinDeliveryError !== undefined)
|
|
260
|
+
packageErrors.push(stdinDeliveryError);
|
|
261
|
+
for (const error of packageErrors) {
|
|
262
|
+
const diagnostic = `Pi transport handling failed beside host terminal: ${describeErrorIdentity(error)}`;
|
|
263
|
+
const runDirectory = spawnOptions.env.AK_ROLE_RUN_DIR;
|
|
264
|
+
if (runDirectory !== undefined) {
|
|
265
|
+
await retainPackageFault({ runDirectory, diagnostic, error });
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
// Bare runner callers have no admitted artifact directory.
|
|
269
|
+
try {
|
|
270
|
+
process.stderr.write(`${diagnostic}\n`);
|
|
271
|
+
}
|
|
272
|
+
catch { /* Best-effort presentation beside the already closed child. */ }
|
|
273
|
+
}
|
|
255
274
|
}
|
|
256
275
|
resolveResult({
|
|
257
276
|
code,
|
|
258
277
|
stderr,
|
|
259
278
|
timedOut,
|
|
279
|
+
...(closeSignal === null ? {} : { signal: closeSignal }),
|
|
280
|
+
...(code === 0 && !timedOut && closeSignal === null && identityFailure !== undefined
|
|
281
|
+
? { knownFailure: identityFailure }
|
|
282
|
+
: {}),
|
|
260
283
|
});
|
|
261
|
-
}
|
|
262
|
-
if (settled)
|
|
263
|
-
return;
|
|
264
|
-
settled = true;
|
|
265
|
-
reject(error);
|
|
266
|
-
});
|
|
284
|
+
})();
|
|
267
285
|
});
|
|
268
286
|
});
|
|
269
287
|
};
|
|
@@ -13,45 +13,46 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { constants as fsConstants } from "node:fs";
|
|
15
15
|
import { randomUUID } from "node:crypto";
|
|
16
|
-
import {
|
|
16
|
+
import { open } from "node:fs/promises";
|
|
17
17
|
import { join } from "node:path";
|
|
18
|
-
import {
|
|
19
|
-
import { AUTO_RESUME_LIMIT, describeErrorIdentity, acquireRunWriterLease, markRunResumable, markRunTerminal, RunWriterLeaseHeldError, } from "./run-lifecycle.js";
|
|
18
|
+
import { AUTO_RESUME_LIMIT, describeErrorIdentity, acquireRunWriterLease, markRunTerminal, RunWriterLeaseHeldError, } from "./run-lifecycle.js";
|
|
20
19
|
import { parseAutoResumeLimit } from "./config.js";
|
|
21
20
|
import { processCancelSignalName } from "./process-cancel.js";
|
|
22
21
|
import { isLawfulTypedTerminalOutcome, formatTerminalResult } from "./terminal.js";
|
|
23
|
-
import { attachRecordedSubmissions, presentFailureTerminal,
|
|
22
|
+
import { attachRecordedSubmissions, ensureRealArtifactsDirectory, presentFailureTerminal, retainPackageFault, } from "./settlement.js";
|
|
23
|
+
export { ensureRealArtifactsDirectory };
|
|
24
24
|
import { serializeThrownValue } from "../serialize-thrown-value.js";
|
|
25
|
-
import { errorText
|
|
25
|
+
import { errorText } from "../unknown-value.js";
|
|
26
26
|
const dummyIo = { stdout: () => { }, stderr: () => { } };
|
|
27
27
|
/**
|
|
28
28
|
* Persist run-state after a host-turn result, outside the retried dispatch try.
|
|
29
|
-
*
|
|
30
|
-
* win (#416 成功即停). 429 only marks resumable on the controlled-failure path.
|
|
31
|
-
* Write failure must escape the retried dispatch try instead of becoming a
|
|
32
|
-
* synthetic host-turn terminal.
|
|
29
|
+
* The host outcome already decided the terminal. This write only seals the run.
|
|
33
30
|
*/
|
|
34
|
-
export async function persistReturnedRunState(admitted
|
|
35
|
-
if (options?.lawful === true) {
|
|
36
|
-
await markRunTerminal(admitted.runDirectory);
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
const resumeObservation = await resolveControlledFailureResumeObservation({
|
|
40
|
-
runDirectory: admitted.runDirectory,
|
|
41
|
-
});
|
|
42
|
-
const typedHttp429 = resumeObservation.typedHttp429;
|
|
43
|
-
if (admitted.principal !== undefined && typedHttp429 !== undefined) {
|
|
44
|
-
await markRunResumable(admitted.runDirectory, typedHttp429);
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
31
|
+
export async function persistReturnedRunState(admitted) {
|
|
47
32
|
await markRunTerminal(admitted.runDirectory);
|
|
48
33
|
}
|
|
49
|
-
function presentTerminal(terminal, io) {
|
|
50
|
-
|
|
51
|
-
|
|
34
|
+
export async function presentTerminal(terminal, io, runDirectory, held) {
|
|
35
|
+
try {
|
|
36
|
+
if (held !== undefined) {
|
|
37
|
+
for (const value of held)
|
|
38
|
+
io.stdout(value);
|
|
39
|
+
}
|
|
40
|
+
else if (terminal.roleOutcome.kind === "failure" || terminal.roleOutcome.kind === "no_receipt") {
|
|
41
|
+
presentFailureTerminal(terminal, io);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
io.stdout(formatTerminalResult(terminal));
|
|
45
|
+
}
|
|
52
46
|
}
|
|
53
|
-
|
|
54
|
-
|
|
47
|
+
catch (error) {
|
|
48
|
+
// Presentation consumes a settled report; it never reopens dispatch or
|
|
49
|
+
// replaces the host's cause, identity or open details.
|
|
50
|
+
await retainPackageFault({
|
|
51
|
+
runDirectory,
|
|
52
|
+
diagnostic: `terminal presentation failed beside host terminal: ${describeErrorIdentity(error)}`,
|
|
53
|
+
error,
|
|
54
|
+
stderr: (text) => io.stderr(text),
|
|
55
|
+
});
|
|
55
56
|
}
|
|
56
57
|
}
|
|
57
58
|
/**
|
|
@@ -89,39 +90,6 @@ export class TurnDispatchedFailure extends Error {
|
|
|
89
90
|
}
|
|
90
91
|
/** Session custom-entry type carrying the pointer to one dispatch error file. */
|
|
91
92
|
export const DISPATCH_ERROR_RETENTION_ENTRY_TYPE = "ak_run_dispatch_error_retention";
|
|
92
|
-
/**
|
|
93
|
-
* #182-A hardened path identity, mirrored from settlement.ts's
|
|
94
|
-
* ensureAuditEvidenceDirectory: a planted symlink at the run directory or the
|
|
95
|
-
* artifacts path must not receive a durable run artifact (O_NOFOLLOW only
|
|
96
|
-
* protects the final file name; recursive mkdir would accept a symlinked
|
|
97
|
-
* parent). Fails loudly with the true cause instead. Shared by every caller
|
|
98
|
-
* that needs a durable run-artifacts write independent of session/dossier
|
|
99
|
-
* health — dispatch-error retention here, and post-admission's best-effort
|
|
100
|
-
* cleanup diagnostic (#840 bounce class 2).
|
|
101
|
-
*/
|
|
102
|
-
export async function ensureRealArtifactsDirectory(runDirectory) {
|
|
103
|
-
const runStat = await lstat(runDirectory);
|
|
104
|
-
if (runStat.isSymbolicLink() || !runStat.isDirectory()) {
|
|
105
|
-
throw new Error("run artifact retention: run directory is not a real directory");
|
|
106
|
-
}
|
|
107
|
-
const artifactsDir = roleRunArtifactsDirectory(runDirectory);
|
|
108
|
-
try {
|
|
109
|
-
const existing = await lstat(artifactsDir);
|
|
110
|
-
if (existing.isSymbolicLink() || !existing.isDirectory()) {
|
|
111
|
-
throw new Error("run artifact retention: artifacts path is not a real directory");
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
catch (error) {
|
|
115
|
-
if (!isEnoent(error))
|
|
116
|
-
throw error;
|
|
117
|
-
await mkdir(artifactsDir, { recursive: true });
|
|
118
|
-
const created = await lstat(artifactsDir);
|
|
119
|
-
if (created.isSymbolicLink() || !created.isDirectory()) {
|
|
120
|
-
throw new Error("run artifact retention: artifacts directory is not a real directory");
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
return artifactsDir;
|
|
124
|
-
}
|
|
125
93
|
/** Cycle- and bigint-safe JSON replacer so serialization itself cannot drop data. */
|
|
126
94
|
function jsonSafeReplacer() {
|
|
127
95
|
const seen = new WeakSet();
|
|
@@ -406,12 +374,7 @@ export async function runWithAutoResumeLoop(options) {
|
|
|
406
374
|
} }
|
|
407
375
|
: terminal;
|
|
408
376
|
if (complete !== undefined) {
|
|
409
|
-
|
|
410
|
-
options.io.stdout(formatTerminalResult(complete));
|
|
411
|
-
}
|
|
412
|
-
else {
|
|
413
|
-
presentTerminal(complete, options.io);
|
|
414
|
-
}
|
|
377
|
+
await presentTerminal(complete, options.io, options.admitted.runDirectory);
|
|
415
378
|
}
|
|
416
379
|
return stoppedResult === undefined
|
|
417
380
|
? { exitCode: 1, terminal: complete }
|
|
@@ -1,24 +1,11 @@
|
|
|
1
1
|
import { readableGateItem } from "../readable-gate-item.js";
|
|
2
|
+
import { currentReplyRows } from "./terminal.js";
|
|
2
3
|
import { isRecord } from "../unknown-value.js";
|
|
3
4
|
function isEscalatePayload(payload) {
|
|
4
5
|
if (!isRecord(payload))
|
|
5
6
|
return false;
|
|
6
7
|
return (payload.status === "escalate");
|
|
7
8
|
}
|
|
8
|
-
/**
|
|
9
|
-
* Rows a parent may read from a nested diarist terminal (#836 / #953).
|
|
10
|
-
* Accepted/audit use role result payloads; failure history is submissions only.
|
|
11
|
-
*/
|
|
12
|
-
function courtDiaristPayloadRows(roleOutcome, submissions) {
|
|
13
|
-
if (roleOutcome === undefined)
|
|
14
|
-
return submissions ?? [];
|
|
15
|
-
if (roleOutcome.kind === "accepted" || roleOutcome.kind === "audit_escalation") {
|
|
16
|
-
return roleOutcome.payloads ?? [];
|
|
17
|
-
}
|
|
18
|
-
if (roleOutcome.kind === "failure")
|
|
19
|
-
return submissions ?? [];
|
|
20
|
-
return [];
|
|
21
|
-
}
|
|
22
9
|
/**
|
|
23
10
|
* Parent diagnostic for court-diarist escalate (#953 / 失败诚实 / 传话).
|
|
24
11
|
* Relays diarist escalate payload(s) via readableGateItem — never invents
|
|
@@ -29,8 +16,8 @@ function courtDiaristPayloadRows(roleOutcome, submissions) {
|
|
|
29
16
|
* no courtAttempt sole-filter on diarist). Same law as secretariat parent face:
|
|
30
17
|
* every escalate receipt as-is, last = currentConclusion.
|
|
31
18
|
*/
|
|
32
|
-
function courtDiaristEscalateDiagnostic(
|
|
33
|
-
const payloads =
|
|
19
|
+
function courtDiaristEscalateDiagnostic(terminal) {
|
|
20
|
+
const payloads = currentReplyRows(terminal);
|
|
34
21
|
const escalatePayloads = [];
|
|
35
22
|
for (const payload of payloads) {
|
|
36
23
|
if (isEscalatePayload(payload))
|
|
@@ -100,14 +87,13 @@ export async function invokeCourtDiarist(input, env, io) {
|
|
|
100
87
|
: { hostAdapters: env.hostAdapters }),
|
|
101
88
|
});
|
|
102
89
|
const roleOutcome = result.terminal?.roleOutcome;
|
|
103
|
-
const submissions = result.terminal?.submissions;
|
|
104
90
|
// Escalate routing is a boolean over the preserved sequence (#881). Reasons and
|
|
105
91
|
// payload bodies stay on roleOutcome — never rewritten into a sole identity reason.
|
|
106
92
|
if (latestPayloadEscalated(roleOutcome)) {
|
|
107
93
|
return {
|
|
108
94
|
identity: {
|
|
109
95
|
kind: "escalate",
|
|
110
|
-
diagnostic: courtDiaristEscalateDiagnostic(
|
|
96
|
+
diagnostic: courtDiaristEscalateDiagnostic(result.terminal),
|
|
111
97
|
},
|
|
112
98
|
...(result.admitted === undefined ? {} : { admitted: result.admitted }),
|
|
113
99
|
...(result.terminal === undefined ? {} : { terminal: result.terminal }),
|