@akagilnc/pi-workflow-roles 0.1.4673 → 0.1.4695
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 +496 -518
- package/dist/compliance-transport.js +6 -2
- package/dist/gatekeeper-role.js +6 -7
- package/dist/headless-host/production-host.js +492 -514
- package/dist/migrate-book-topology.js +8 -0
- package/dist/public-cli/countersign-run.js +63 -18
- package/dist/public-cli/main.js +488 -513
- package/dist/public-cli/settlement.js +316 -247
- package/dist/public-cli/terminal.js +36 -9
- package/dist/run-terminal-artifacts.js +71 -32
- package/package.json +1 -1
- package/src/compliance-transport.ts +8 -2
- package/src/gatekeeper-role.ts +6 -6
- package/src/public-cli/countersign-run.ts +75 -26
- package/src/public-cli/secretariat-run.ts +2 -3
- package/src/public-cli/settlement.ts +380 -355
- package/src/public-cli/terminal.ts +48 -13
- package/src/role-runtime.ts +9 -11
- package/src/run-terminal-artifacts.ts +81 -28
- package/src/secretariat-role.ts +9 -4
|
@@ -17,7 +17,11 @@ export function exitCodeForTerminalOutcome(outcome) {
|
|
|
17
17
|
* auto-resumes occurred during this single LLM call; it is not persisted to
|
|
18
18
|
* run-state.json and does not participate in limit decisions.
|
|
19
19
|
*/
|
|
20
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* Current-result payloads on a terminal — accepted/audit role result, or a
|
|
22
|
+
* rare intentional failure face. Run history is TerminalResult.submissions
|
|
23
|
+
* (#836 / #953), not this helper.
|
|
24
|
+
*/
|
|
21
25
|
export function roleResultPayloads(outcome) {
|
|
22
26
|
if (outcome.kind === "accepted" || outcome.kind === "audit_escalation")
|
|
23
27
|
return outcome.payloads ?? [];
|
|
@@ -25,6 +29,18 @@ export function roleResultPayloads(outcome) {
|
|
|
25
29
|
return outcome.payloads ?? [];
|
|
26
30
|
return [];
|
|
27
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Prefer non-empty current-result payloads; an empty array must not shadow
|
|
34
|
+
* top-level submissions (#953 / #836). Callers that need failure history must
|
|
35
|
+
* read TerminalResult.submissions directly — do not coalesce into failure.payloads.
|
|
36
|
+
*/
|
|
37
|
+
export function coalesceSubmissionRows(payloads, submissions) {
|
|
38
|
+
if (payloads !== undefined && payloads.length > 0)
|
|
39
|
+
return payloads;
|
|
40
|
+
if (submissions !== undefined && submissions.length > 0)
|
|
41
|
+
return submissions;
|
|
42
|
+
return payloads ?? submissions ?? [];
|
|
43
|
+
}
|
|
28
44
|
/**
|
|
29
45
|
* Build an advice navigator fact (#959). Prose is presented as submitted;
|
|
30
46
|
* code does not parse route/next or judge usability.
|
|
@@ -109,15 +125,26 @@ export function formatTerminalResult(result) {
|
|
|
109
125
|
}
|
|
110
126
|
// Role-result block: original payloads, newest first for humans (#961).
|
|
111
127
|
// Typed payloads/submissions stay ledger order; only this presentation reverses.
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
128
|
+
// #953: failure history is the top-level submissions carrier (#836) — present
|
|
129
|
+
// as recorded-submission, never as this-turn submission/receipt.
|
|
130
|
+
if (result.roleOutcome.kind === "failure") {
|
|
131
|
+
const recorded = result.submissions ?? [];
|
|
132
|
+
for (let i = recorded.length - 1; i >= 0; i -= 1) {
|
|
133
|
+
const payload = recorded[i];
|
|
134
|
+
const rendered = typeof payload === "string" ? payload : JSON.stringify(payload);
|
|
135
|
+
lines.push(`recorded-submission\t${encodeTerminalField(rendered)}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
const payloads = result.roleOutcome.kind === "accepted" ||
|
|
140
|
+
result.roleOutcome.kind === "audit_escalation"
|
|
141
|
+
? coalesceSubmissionRows(result.roleOutcome.payloads, result.submissions)
|
|
116
142
|
: result.submissions ?? [];
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
143
|
+
for (let i = payloads.length - 1; i >= 0; i -= 1) {
|
|
144
|
+
const payload = payloads[i];
|
|
145
|
+
const rendered = typeof payload === "string" ? payload : JSON.stringify(payload);
|
|
146
|
+
lines.push(`submission\t${encodeTerminalField(rendered)}`);
|
|
147
|
+
}
|
|
121
148
|
}
|
|
122
149
|
return `${lines.join("\n")}\n`;
|
|
123
150
|
}
|
|
@@ -137,6 +137,7 @@ export function runIdFromRunDirectory(runDirectory) {
|
|
|
137
137
|
* Shared parent-directory unique fallback may be adopted only when the
|
|
138
138
|
* publisher-owned body.runId equals this run directory's runId. Same-run
|
|
139
139
|
* artifactsDir / runDirectory candidates keep path ownership and skip this.
|
|
140
|
+
* expectedRunId undefined (unparseable run dir) → never bound.
|
|
140
141
|
*/
|
|
141
142
|
function presentUniqueFallbackBoundToRun(body, expectedRunId) {
|
|
142
143
|
if (expectedRunId === undefined)
|
|
@@ -144,49 +145,87 @@ function presentUniqueFallbackBoundToRun(body, expectedRunId) {
|
|
|
144
145
|
return typeof body.runId === "string" && body.runId === expectedRunId;
|
|
145
146
|
}
|
|
146
147
|
/**
|
|
147
|
-
*
|
|
148
|
-
*
|
|
148
|
+
* Sole authority for seam-owned unique error.<uuid>.json candidates.
|
|
149
|
+
* Used by both clearOpposite (settlement) and readRunTerminalArtifact — do not
|
|
150
|
+
* re-enumerate the same-run / parent unique set elsewhere.
|
|
151
|
+
* Ownership:
|
|
152
|
+
* - same-run dirs (artifacts/, runDir): path ownership — all unique names
|
|
153
|
+
* - parent runs/: only body.runId-bound faces; unparseable runId or unreadable body → none
|
|
154
|
+
*/
|
|
155
|
+
export async function listSeamOwnedUniqueErrorFacePaths(runDirectory) {
|
|
156
|
+
const artifactsDir = roleRunArtifactsDirectory(runDirectory);
|
|
157
|
+
const owned = await listUniqueErrorFallbackPaths([
|
|
158
|
+
artifactsDir,
|
|
159
|
+
runDirectory,
|
|
160
|
+
]);
|
|
161
|
+
const expectedRunId = runIdFromRunDirectory(runDirectory);
|
|
162
|
+
for (const path of await listUniqueErrorFallbackPaths([dirname(runDirectory)])) {
|
|
163
|
+
const read = await readTerminalArtifactAtPath(path, "error.json");
|
|
164
|
+
if (read === undefined || read.status !== "present")
|
|
165
|
+
continue;
|
|
166
|
+
if (!presentUniqueFallbackBoundToRun(read.body, expectedRunId))
|
|
167
|
+
continue;
|
|
168
|
+
owned.push(path);
|
|
169
|
+
}
|
|
170
|
+
return owned;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Publish contract (#953): only failure publish continues after clearOpposite
|
|
174
|
+
* failure, so a multi-class residue (residual report/audit beside a new error
|
|
175
|
+
* face) means the current settlement is failure. Prefer failure-class faces
|
|
176
|
+
* over success/audit — never filesystem mtime (copy/restore/utimes can lie).
|
|
177
|
+
*/
|
|
178
|
+
function failureClassRank(file) {
|
|
179
|
+
return file === "error.json" ? 1 : 0;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Read the current typed terminal artifact for a run directory.
|
|
183
|
+
*
|
|
184
|
+
* Candidate set (publisher-owned faces only):
|
|
149
185
|
* 1) conventional artifacts/{report,error,audit-incomplete}.json
|
|
150
186
|
* 2) publisher fixed failure fallbacks (error.settlement.json faces)
|
|
151
|
-
* 3)
|
|
152
|
-
*
|
|
187
|
+
* 3) seam-owned unique error.<uuid>.json via listSeamOwnedUniqueErrorFacePaths
|
|
188
|
+
* (same-run path ownership + parent body.runId binding — shared with clear)
|
|
153
189
|
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
190
|
+
* Invariant: when more than one present face remains (e.g. clearOpposite failed
|
|
191
|
+
* during failure publish and a fallback was settled beside a residual report),
|
|
192
|
+
* adopt failure-class over success/audit by the publish contract — not mtime.
|
|
193
|
+
* Same-class ties keep candidate enumeration order (conventional before
|
|
194
|
+
* fallbacks before unique).
|
|
195
|
+
*
|
|
196
|
+
* Unreadable faces never outrank a present face. Parent unique unreadable
|
|
197
|
+
* files never enter the shared enumerator (cannot prove run identity).
|
|
198
|
+
* Absence of every known durable face is a valid no-receipt state.
|
|
156
199
|
*/
|
|
157
200
|
export async function readRunTerminalArtifact(runDirectory) {
|
|
158
201
|
const artifactsDir = roleRunArtifactsDirectory(runDirectory);
|
|
202
|
+
const present = [];
|
|
203
|
+
const unreadable = [];
|
|
204
|
+
const consider = (read) => {
|
|
205
|
+
if (read === undefined || read.status === "absent")
|
|
206
|
+
return;
|
|
207
|
+
if (read.status === "present") {
|
|
208
|
+
present.push(read);
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
unreadable.push(read);
|
|
212
|
+
};
|
|
159
213
|
for (const file of RUN_TERMINAL_ARTIFACT_FILES) {
|
|
160
|
-
|
|
161
|
-
const read = await readTerminalArtifactAtPath(path, file);
|
|
162
|
-
if (read !== undefined)
|
|
163
|
-
return read;
|
|
214
|
+
consider(await readTerminalArtifactAtPath(join(artifactsDir, file), file));
|
|
164
215
|
}
|
|
165
|
-
// Publisher settled a durable failure outside the conventional error.json name.
|
|
166
216
|
for (const relative of RUN_TERMINAL_ERROR_FALLBACK_RELATIVE_PATHS) {
|
|
167
|
-
|
|
168
|
-
const read = await readTerminalArtifactAtPath(path, "error.json");
|
|
169
|
-
if (read !== undefined)
|
|
170
|
-
return read;
|
|
217
|
+
consider(await readTerminalArtifactAtPath(join(runDirectory, relative), "error.json"));
|
|
171
218
|
}
|
|
172
|
-
//
|
|
173
|
-
for (const path of await
|
|
174
|
-
|
|
175
|
-
if (read !== undefined)
|
|
176
|
-
return read;
|
|
219
|
+
// Unique same-run + parent-bound faces: one enumerator shared with clear.
|
|
220
|
+
for (const path of await listSeamOwnedUniqueErrorFacePaths(runDirectory)) {
|
|
221
|
+
consider(await readTerminalArtifactAtPath(path, "error.json"));
|
|
177
222
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
if (read.status === "present") {
|
|
185
|
-
if (!presentUniqueFallbackBoundToRun(read.body, expectedRunId))
|
|
186
|
-
continue;
|
|
187
|
-
return read;
|
|
188
|
-
}
|
|
189
|
-
// Unreadable parent unique file cannot prove run identity — do not adopt.
|
|
223
|
+
if (present.length > 0) {
|
|
224
|
+
present.sort((a, b) => failureClassRank(b.file) - failureClassRank(a.file));
|
|
225
|
+
return present[0];
|
|
226
|
+
}
|
|
227
|
+
if (unreadable.length > 0) {
|
|
228
|
+
return unreadable[0];
|
|
190
229
|
}
|
|
191
230
|
return { status: "absent" };
|
|
192
231
|
}
|
package/package.json
CHANGED
|
@@ -5,6 +5,7 @@ import type { HostContext } from "./host-contracts.ts";
|
|
|
5
5
|
import type { NoReceiptLifecycleFacts } from "./receipt-delivery-policy.ts";
|
|
6
6
|
import type { PublicSummonResult } from "./public-role-summons.ts";
|
|
7
7
|
import { OFFICER_CONCLUSION_REASK } from "./gatekeeper-role.ts";
|
|
8
|
+
import { coalesceSubmissionRows } from "./public-cli/terminal.ts";
|
|
8
9
|
|
|
9
10
|
export type ComplianceNoReceipt = NoReceiptLifecycleFacts & { status: "no-receipt"; usage?: Usage };
|
|
10
11
|
/**
|
|
@@ -149,7 +150,9 @@ async function projectAuditorTerminal(summoned: PublicSummonResult): Promise<Com
|
|
|
149
150
|
};
|
|
150
151
|
}
|
|
151
152
|
if (outcome.kind === "failure") {
|
|
152
|
-
|
|
153
|
+
// #953: history stays on the historical carrier; do not read failure.payloads
|
|
154
|
+
// as if they were the current failure result (#836 A.3 beside-channel).
|
|
155
|
+
const rows = summoned.terminal?.submissions ?? [];
|
|
153
156
|
return {
|
|
154
157
|
status: "transport_failure",
|
|
155
158
|
diagnostic: outcome.diagnostic,
|
|
@@ -159,7 +162,10 @@ async function projectAuditorTerminal(summoned: PublicSummonResult): Promise<Com
|
|
|
159
162
|
};
|
|
160
163
|
}
|
|
161
164
|
if (outcome.kind === "accepted") {
|
|
162
|
-
const rows =
|
|
165
|
+
const rows = coalesceSubmissionRows(
|
|
166
|
+
outcome.payloads,
|
|
167
|
+
summoned.terminal?.submissions,
|
|
168
|
+
);
|
|
163
169
|
if (rows.length === 0) {
|
|
164
170
|
return readComplianceCandidate({}, usage);
|
|
165
171
|
}
|
package/src/gatekeeper-role.ts
CHANGED
|
@@ -260,20 +260,20 @@ function projectOfficerDecision(
|
|
|
260
260
|
*/
|
|
261
261
|
function thisCourtOfficerPayloads(terminal: TerminalResult | undefined): readonly unknown[] {
|
|
262
262
|
const outcome = terminal?.roleOutcome;
|
|
263
|
+
// This-court identity only from accepted/audit_escalation settlement payloads
|
|
264
|
+
// (#879). Failure history is not this-court (#953) — it rides submissions.
|
|
263
265
|
if (outcome !== undefined && (outcome.kind === "accepted" || outcome.kind === "audit_escalation")) {
|
|
264
266
|
if (outcome.payloads !== undefined && outcome.payloads.length > 0) return outcome.payloads;
|
|
265
267
|
}
|
|
266
|
-
if (outcome?.kind === "failure" && outcome.payloads !== undefined && outcome.payloads.length > 0) {
|
|
267
|
-
return outcome.payloads;
|
|
268
|
-
}
|
|
269
268
|
// No sole-row identity guess: undivided submissions are not this-court (#879).
|
|
270
269
|
return [];
|
|
271
270
|
}
|
|
272
271
|
|
|
273
|
-
/**
|
|
272
|
+
/**
|
|
273
|
+
* Failure/transport channel surfaces recorded history beside the failure
|
|
274
|
+
* (#836 A.3) via the historical carrier only (#953 — not failure.payloads).
|
|
275
|
+
*/
|
|
274
276
|
function officerFailurePayloads(terminal: TerminalResult | undefined): readonly unknown[] {
|
|
275
|
-
const outcome = terminal?.roleOutcome;
|
|
276
|
-
if (outcome?.kind === "failure") return outcome.payloads ?? terminal?.submissions ?? [];
|
|
277
277
|
return terminal?.submissions ?? [];
|
|
278
278
|
}
|
|
279
279
|
|
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
} from "../package-resources/engine-material.ts";
|
|
32
32
|
import { CliUsageError } from "./cli-errors.ts";
|
|
33
33
|
import { projectCourtTicketNumbers } from "../diarist-contracts.ts";
|
|
34
|
+
import { readableGateItem } from "../readable-gate-item.ts";
|
|
34
35
|
import { isSafePositiveTicketNumber } from "../run-ticket-number.ts";
|
|
35
36
|
import {
|
|
36
37
|
admitCountersignInvocation,
|
|
@@ -139,13 +140,74 @@ export type CourtDiaristIdentity =
|
|
|
139
140
|
readonly courtTicketNumbers?: readonly number[];
|
|
140
141
|
}
|
|
141
142
|
| { readonly kind: "unbound" }
|
|
142
|
-
| {
|
|
143
|
+
| {
|
|
144
|
+
readonly kind: "escalate";
|
|
145
|
+
/** Honest diagnostic from diarist escalate payload (#953) — never invent 认不出. */
|
|
146
|
+
readonly diagnostic: string;
|
|
147
|
+
};
|
|
143
148
|
|
|
144
149
|
export type CourtDiaristInvocationResult = {
|
|
145
150
|
readonly identity: CourtDiaristIdentity;
|
|
146
151
|
readonly failedWithoutEscalate?: { readonly diagnostic: string };
|
|
147
152
|
};
|
|
148
153
|
|
|
154
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
155
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function isEscalatePayload(payload: unknown): boolean {
|
|
159
|
+
if (!isRecord(payload)) return false;
|
|
160
|
+
return (
|
|
161
|
+
payload.status === "escalate" || payload.countersignStatus === "escalate"
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Rows a parent may read from a nested diarist terminal (#836 / #953).
|
|
167
|
+
* Accepted/audit use role result payloads; failure history is submissions only.
|
|
168
|
+
*/
|
|
169
|
+
function courtDiaristPayloadRows(
|
|
170
|
+
roleOutcome: TerminalRoleOutcome | undefined,
|
|
171
|
+
submissions: readonly unknown[] | undefined,
|
|
172
|
+
): readonly unknown[] {
|
|
173
|
+
if (roleOutcome === undefined) return submissions ?? [];
|
|
174
|
+
if (roleOutcome.kind === "accepted" || roleOutcome.kind === "audit_escalation") {
|
|
175
|
+
return roleOutcome.payloads ?? [];
|
|
176
|
+
}
|
|
177
|
+
if (roleOutcome.kind === "failure") return submissions ?? [];
|
|
178
|
+
return [];
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Parent diagnostic for court-diarist escalate (#953 / 失败诚实 / 传话).
|
|
183
|
+
* Relays diarist escalate payload(s) via readableGateItem — never invents
|
|
184
|
+
* "cannot identify court target" when a payload already carries other facts
|
|
185
|
+
* (e.g. ticketNumber present with a different reason).
|
|
186
|
+
*
|
|
187
|
+
* Multiple escalate payloads remain reachable after the run (ADR 0003/0041;
|
|
188
|
+
* no courtAttempt sole-filter on diarist). Same law as secretariat parent face:
|
|
189
|
+
* every escalate receipt as-is, last = currentConclusion.
|
|
190
|
+
*/
|
|
191
|
+
function courtDiaristEscalateDiagnostic(
|
|
192
|
+
roleOutcome: TerminalRoleOutcome | undefined,
|
|
193
|
+
submissions?: readonly unknown[],
|
|
194
|
+
): string {
|
|
195
|
+
const payloads = courtDiaristPayloadRows(roleOutcome, submissions);
|
|
196
|
+
const escalatePayloads: unknown[] = [];
|
|
197
|
+
for (const payload of payloads) {
|
|
198
|
+
if (isEscalatePayload(payload)) escalatePayloads.push(payload);
|
|
199
|
+
}
|
|
200
|
+
if (escalatePayloads.length === 0) return "court diarist station escalated";
|
|
201
|
+
// Single escalate: prior carrier (payload body only) — no shape churn.
|
|
202
|
+
if (escalatePayloads.length === 1) {
|
|
203
|
+
return `court diarist station escalated: ${readableGateItem(escalatePayloads[0])}`;
|
|
204
|
+
}
|
|
205
|
+
return `court diarist station escalated: ${readableGateItem({
|
|
206
|
+
receipts: escalatePayloads,
|
|
207
|
+
currentConclusion: escalatePayloads[escalatePayloads.length - 1],
|
|
208
|
+
})}`;
|
|
209
|
+
}
|
|
210
|
+
|
|
149
211
|
/** Env slice shared by court diarist identity summons (countersign / secretariat). */
|
|
150
212
|
export type CourtDiaristSummonEnv = Pick<
|
|
151
213
|
CountersignRunEnv,
|
|
@@ -171,14 +233,10 @@ export type CourtDiaristSummonEnv = Pick<
|
|
|
171
233
|
function courtTicketNumbersFromOutcome(
|
|
172
234
|
roleOutcome: TerminalRoleOutcome | undefined,
|
|
173
235
|
principalTicket: number,
|
|
236
|
+
submissions?: readonly unknown[],
|
|
174
237
|
): readonly number[] | undefined {
|
|
175
238
|
if (roleOutcome === undefined) return undefined;
|
|
176
|
-
const payloads =
|
|
177
|
-
roleOutcome.kind === "accepted" ||
|
|
178
|
-
roleOutcome.kind === "audit_escalation" ||
|
|
179
|
-
roleOutcome.kind === "failure"
|
|
180
|
-
? (roleOutcome.payloads ?? [])
|
|
181
|
-
: [];
|
|
239
|
+
const payloads = courtDiaristPayloadRows(roleOutcome, submissions);
|
|
182
240
|
let latest: readonly number[] | undefined;
|
|
183
241
|
for (const payload of payloads) {
|
|
184
242
|
if (
|
|
@@ -216,18 +274,7 @@ function courtDiaristEscalated(
|
|
|
216
274
|
if (roleOutcome === undefined) return false;
|
|
217
275
|
if (roleOutcome.kind === "audit_escalation") return true;
|
|
218
276
|
if (roleOutcome.kind !== "accepted") return false;
|
|
219
|
-
return (roleOutcome.payloads ?? []).some(
|
|
220
|
-
if (
|
|
221
|
-
typeof payload !== "object" ||
|
|
222
|
-
payload === null ||
|
|
223
|
-
Array.isArray(payload)
|
|
224
|
-
)
|
|
225
|
-
return false;
|
|
226
|
-
const record = payload as Record<string, unknown>;
|
|
227
|
-
return (
|
|
228
|
-
record.status === "escalate" || record.countersignStatus === "escalate"
|
|
229
|
-
);
|
|
230
|
-
});
|
|
277
|
+
return (roleOutcome.payloads ?? []).some(isEscalatePayload);
|
|
231
278
|
}
|
|
232
279
|
|
|
233
280
|
/**
|
|
@@ -292,11 +339,15 @@ export async function invokeCourtDiarist(
|
|
|
292
339
|
});
|
|
293
340
|
|
|
294
341
|
const roleOutcome = result.terminal?.roleOutcome;
|
|
342
|
+
const submissions = result.terminal?.submissions;
|
|
295
343
|
// Escalate routing is a boolean over the preserved sequence (#881). Reasons and
|
|
296
344
|
// payload bodies stay on roleOutcome — never rewritten into a sole identity reason.
|
|
297
345
|
if (courtDiaristEscalated(roleOutcome)) {
|
|
298
346
|
return {
|
|
299
|
-
identity: {
|
|
347
|
+
identity: {
|
|
348
|
+
kind: "escalate",
|
|
349
|
+
diagnostic: courtDiaristEscalateDiagnostic(roleOutcome, submissions),
|
|
350
|
+
},
|
|
300
351
|
};
|
|
301
352
|
}
|
|
302
353
|
|
|
@@ -319,6 +370,7 @@ export async function invokeCourtDiarist(
|
|
|
319
370
|
const courtTicketNumbers = courtTicketNumbersFromOutcome(
|
|
320
371
|
roleOutcome,
|
|
321
372
|
asserted,
|
|
373
|
+
submissions,
|
|
322
374
|
);
|
|
323
375
|
return {
|
|
324
376
|
identity: {
|
|
@@ -390,9 +442,7 @@ export async function runCountersignCourtDiaristStation(
|
|
|
390
442
|
);
|
|
391
443
|
|
|
392
444
|
if (outcome.identity.kind === "escalate") {
|
|
393
|
-
throw new StationChildExhaustedError(
|
|
394
|
-
"court diarist station escalated (cannot identify court target)",
|
|
395
|
-
);
|
|
445
|
+
throw new StationChildExhaustedError(outcome.identity.diagnostic);
|
|
396
446
|
}
|
|
397
447
|
if (outcome.failedWithoutEscalate !== undefined) {
|
|
398
448
|
throw new StationChildExhaustedError(
|
|
@@ -509,6 +559,7 @@ export async function runPublicCountersign(
|
|
|
509
559
|
|
|
510
560
|
if (outcome.identity.kind === "escalate") {
|
|
511
561
|
// 御批: 识别不了就上抛 — materialize and settle this countersign run.
|
|
562
|
+
// Diagnostic relays diarist escalate payload facts (#953).
|
|
512
563
|
await materializeAdmission();
|
|
513
564
|
await markRunAdmitted(admitted, env.principalAuthority);
|
|
514
565
|
return await presentControlledFailure(
|
|
@@ -517,9 +568,7 @@ export async function runPublicCountersign(
|
|
|
517
568
|
timedOut: false,
|
|
518
569
|
code: null,
|
|
519
570
|
stderr: "",
|
|
520
|
-
thrown: new Error(
|
|
521
|
-
"court diarist station escalated (cannot identify court target)",
|
|
522
|
-
),
|
|
571
|
+
thrown: new Error(outcome.identity.diagnostic),
|
|
523
572
|
},
|
|
524
573
|
countersignAdapters(),
|
|
525
574
|
env.principalAuthority,
|
|
@@ -139,15 +139,14 @@ export async function runPublicSecretariat(
|
|
|
139
139
|
);
|
|
140
140
|
|
|
141
141
|
if (outcome.identity.kind === "escalate") {
|
|
142
|
+
// Diagnostic relays diarist escalate payload facts (#953) — never invent 认不出.
|
|
142
143
|
return await presentControlledFailure(
|
|
143
144
|
admitted,
|
|
144
145
|
{
|
|
145
146
|
timedOut: false,
|
|
146
147
|
code: null,
|
|
147
148
|
stderr: "",
|
|
148
|
-
thrown: new Error(
|
|
149
|
-
"court diarist station escalated (cannot identify court target)",
|
|
150
|
-
),
|
|
149
|
+
thrown: new Error(outcome.identity.diagnostic),
|
|
151
150
|
},
|
|
152
151
|
secretariatAdapters(),
|
|
153
152
|
env.principalAuthority,
|