@akagilnc/pi-workflow-roles 0.1.5096 → 0.1.5124
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 +197 -33
- package/dist/headless-host/production-host.js +197 -33
- package/dist/public-cli/cli.js +24 -1
- package/dist/public-cli/instruction-seat-run.js +8 -6
- package/dist/public-cli/main.js +6704 -6540
- package/dist/public-cli/post-admission.js +125 -26
- package/dist/public-cli/settlement.js +28 -4
- package/package.json +1 -1
- package/resources/engines/opencode.md +9 -4
- package/src/public-cli/cli-io.ts +2 -0
- package/src/public-cli/cli.ts +38 -4
- package/src/public-cli/instruction-seat-run.ts +10 -6
- package/src/public-cli/invocation.ts +6 -1
- package/src/public-cli/post-admission.ts +189 -34
- package/src/public-cli/settlement.ts +37 -4
|
@@ -11,6 +11,8 @@ import { isAbsolute, join, resolve } from "node:path";
|
|
|
11
11
|
|
|
12
12
|
import {
|
|
13
13
|
buildAutoResumeContinuationPrompt,
|
|
14
|
+
findRunDirectoryById,
|
|
15
|
+
readRoleRunState,
|
|
14
16
|
RESUME_TRANSPORT_ENVELOPE,
|
|
15
17
|
type PublicResumeRequest,
|
|
16
18
|
type SameTicketSummonsMaterials,
|
|
@@ -26,12 +28,14 @@ import {
|
|
|
26
28
|
import { readRecordedSubmissionRows } from "../submission-ledger.ts";
|
|
27
29
|
import { pathContainedIn } from "../activation-ledger-topology.ts";
|
|
28
30
|
import { pickEngineAxis } from "../package-resources/engine-material.ts";
|
|
29
|
-
import {
|
|
31
|
+
import {
|
|
32
|
+
readStoredHostSessionId,
|
|
33
|
+
resolveHostAwareSessionAvailability,
|
|
34
|
+
} from "../session-identity.ts";
|
|
30
35
|
import { rewriteRunDirectoryPathValue } from "../role-run-relocation.ts";
|
|
31
36
|
|
|
32
37
|
import type {
|
|
33
38
|
ControlledFailureCause,
|
|
34
|
-
DurablePrincipal,
|
|
35
39
|
DurablePrincipalAuthority,
|
|
36
40
|
RoleTurnHost,
|
|
37
41
|
RoleTurnKnownFailure,
|
|
@@ -94,19 +98,23 @@ import {
|
|
|
94
98
|
exitCodeForTerminalOutcome,
|
|
95
99
|
explicitInternalKnownFailureClassificationInput,
|
|
96
100
|
formatCliDiagnostic,
|
|
101
|
+
formatErrorCauseDetail,
|
|
97
102
|
formatTerminalResult,
|
|
98
103
|
inspectJudgeSession,
|
|
99
104
|
isLawfulTypedTerminalOutcome,
|
|
100
105
|
presentFailureTerminal,
|
|
106
|
+
publishedFailureErrorPath,
|
|
101
107
|
presentStructuralRejection,
|
|
102
108
|
resolveAuditedRunnerFailureResolution,
|
|
103
109
|
resolveControlledFailureResumeObservation,
|
|
104
110
|
settleFailureTerminalResult,
|
|
105
111
|
settleHostEndedNoReceipt,
|
|
106
112
|
attachRecordedSubmissions,
|
|
113
|
+
rewritePublishedFailureErrorPath,
|
|
114
|
+
type ControlledFailure,
|
|
107
115
|
} from "./settlement.ts";
|
|
108
116
|
import type { CliIo } from "./cli-io.ts";
|
|
109
|
-
import type { AdmittedRoleInvocation } from "./invocation.ts";
|
|
117
|
+
import type { AdmittedRoleInvocation, RunDirectoryRelocation } from "./invocation.ts";
|
|
110
118
|
import type { NamedRoleTurnHostAdapter } from "./role-turn-host-resolution.ts";
|
|
111
119
|
import {
|
|
112
120
|
type TerminalResult,
|
|
@@ -140,6 +148,11 @@ function projectRelocatedTurnIdentity(
|
|
|
140
148
|
}
|
|
141
149
|
}
|
|
142
150
|
if (result.terminal !== undefined) {
|
|
151
|
+
rewritePublishedFailureErrorPath(
|
|
152
|
+
result.terminal,
|
|
153
|
+
relocation.oldRunDirectory,
|
|
154
|
+
relocation.newRunDirectory,
|
|
155
|
+
);
|
|
143
156
|
for (const artifact of result.terminal.artifacts) {
|
|
144
157
|
artifact.path = rewrite(artifact.path) as string;
|
|
145
158
|
}
|
|
@@ -361,7 +374,12 @@ export type PostAdmissionAdapters<
|
|
|
361
374
|
* held lease (when present) follows the run directory and failures stay
|
|
362
375
|
* controlled. Public manual resume (#987) may omit the lease.
|
|
363
376
|
*/
|
|
364
|
-
afterDispatch?: (
|
|
377
|
+
afterDispatch?: (
|
|
378
|
+
admitted: A,
|
|
379
|
+
lease?: RunWriterLease,
|
|
380
|
+
) => Promise<RunDirectoryRelocation | undefined>
|
|
381
|
+
| RunDirectoryRelocation
|
|
382
|
+
| void;
|
|
365
383
|
};
|
|
366
384
|
|
|
367
385
|
export type ControlledFailureInput = {
|
|
@@ -442,7 +460,7 @@ export async function resolveResumeMethodMaterialAdapters<
|
|
|
442
460
|
},
|
|
443
461
|
input.emptyAdapters,
|
|
444
462
|
input.authority,
|
|
445
|
-
input.io,
|
|
463
|
+
{ ...input.io, omitFailureStderrDiagnostic: true },
|
|
446
464
|
);
|
|
447
465
|
return { kind: "terminal", ...terminal };
|
|
448
466
|
}
|
|
@@ -522,23 +540,26 @@ export async function presentControlledFailure<
|
|
|
522
540
|
await persistReturnedRunState(admitted, authority);
|
|
523
541
|
}
|
|
524
542
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
)
|
|
541
|
-
|
|
543
|
+
let publishedErrorPath: string | undefined;
|
|
544
|
+
let terminal: TerminalResult;
|
|
545
|
+
try {
|
|
546
|
+
const settled = await settleFailureTerminalResult(admitted, failure, authority, {
|
|
547
|
+
...(resumable
|
|
548
|
+
? { resume: { command: renderResumeCommand(admitted.runId) } }
|
|
549
|
+
: {}),
|
|
550
|
+
...(failureInput.invocationScopeId === undefined ||
|
|
551
|
+
failureInput.invocationScopeId.length === 0
|
|
552
|
+
? {}
|
|
553
|
+
: { invocationScopeId: failureInput.invocationScopeId }),
|
|
554
|
+
onErrorPublished: (path) => { publishedErrorPath = path; },
|
|
555
|
+
});
|
|
556
|
+
terminal = await attachRecordedSubmissions(admitted, settled);
|
|
557
|
+
} catch (error) {
|
|
558
|
+
if (io.omitFailureStderrDiagnostic && publishedErrorPath !== undefined) {
|
|
559
|
+
writeResumeFailurePointer(io, publishedErrorPath);
|
|
560
|
+
}
|
|
561
|
+
throw error;
|
|
562
|
+
}
|
|
542
563
|
presentFailureTerminal(terminal, io);
|
|
543
564
|
return {
|
|
544
565
|
exitCode: exitCodeForTerminalOutcome(terminal.roleOutcome),
|
|
@@ -738,7 +759,12 @@ export async function dispatchPostAdmissionTurn<
|
|
|
738
759
|
if (relocation !== undefined) {
|
|
739
760
|
projectRelocatedTurnIdentity(request, result, admitted, relocation);
|
|
740
761
|
}
|
|
741
|
-
|
|
762
|
+
const afterDispatchRelocation = adapters.afterDispatch === undefined
|
|
763
|
+
? undefined
|
|
764
|
+
: await adapters.afterDispatch(admitted, lease);
|
|
765
|
+
if (afterDispatchRelocation !== undefined) {
|
|
766
|
+
projectRelocatedTurnIdentity(request, result, admitted, afterDispatchRelocation);
|
|
767
|
+
}
|
|
742
768
|
return result;
|
|
743
769
|
} catch (error) {
|
|
744
770
|
if (result.terminal !== undefined) {
|
|
@@ -1524,17 +1550,31 @@ export async function runPostAdmissionSeatResume<
|
|
|
1524
1550
|
try {
|
|
1525
1551
|
loaded = await input.load(request);
|
|
1526
1552
|
} catch (error) {
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1553
|
+
const usageError = error instanceof CliUsageError;
|
|
1554
|
+
// Unknown usage failures retain the structural fallback. Other load
|
|
1555
|
+
// failures keep the CLI's outer handling unless an existing run is found.
|
|
1556
|
+
const recorded = await pointExistingRunFailure(
|
|
1557
|
+
input.env.home,
|
|
1558
|
+
request.runId,
|
|
1559
|
+
input.env.principalAuthority,
|
|
1560
|
+
input.io,
|
|
1561
|
+
error,
|
|
1562
|
+
);
|
|
1563
|
+
if (!recorded) {
|
|
1564
|
+
if (usageError) {
|
|
1565
|
+
presentStructuralRejection(error, input.io);
|
|
1566
|
+
return { exitCode: 2 };
|
|
1567
|
+
}
|
|
1568
|
+
throw error;
|
|
1530
1569
|
}
|
|
1531
|
-
|
|
1570
|
+
return { exitCode: usageError ? 2 : 1 };
|
|
1532
1571
|
}
|
|
1533
1572
|
|
|
1534
1573
|
let adapters = input.adapters;
|
|
1535
1574
|
if (input.afterAdmittedLoad !== undefined) {
|
|
1536
1575
|
const prepared = await input.afterAdmittedLoad(loaded.admitted);
|
|
1537
1576
|
if (prepared.kind === "terminal") {
|
|
1577
|
+
showResumeErrorPointer(input.io, prepared.exitCode, prepared.terminal);
|
|
1538
1578
|
return {
|
|
1539
1579
|
exitCode: prepared.exitCode,
|
|
1540
1580
|
admitted: prepared.admitted,
|
|
@@ -1710,26 +1750,141 @@ export async function runPostAdmissionSeatResume<
|
|
|
1710
1750
|
}),
|
|
1711
1751
|
});
|
|
1712
1752
|
}
|
|
1713
|
-
|
|
1753
|
+
const resumed = await runPostAdmissionManualResume({
|
|
1714
1754
|
admitted: loaded.admitted,
|
|
1715
1755
|
env,
|
|
1716
|
-
io: input.io,
|
|
1756
|
+
io: { ...input.io, omitFailureStderrDiagnostic: true },
|
|
1717
1757
|
adapters,
|
|
1718
1758
|
...(input.effectiveEngine === undefined
|
|
1719
1759
|
? {}
|
|
1720
1760
|
: { effectiveEngine: input.effectiveEngine }),
|
|
1721
1761
|
buildRequestAfterLease,
|
|
1722
1762
|
});
|
|
1763
|
+
showResumeErrorPointer(input.io, resumed.exitCode, resumed.terminal);
|
|
1764
|
+
return resumed;
|
|
1723
1765
|
} catch (error) {
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1766
|
+
if (error instanceof TurnDispatchedFailure) throw error;
|
|
1767
|
+
await presentResumeFailurePointer(
|
|
1768
|
+
input.io,
|
|
1769
|
+
error,
|
|
1770
|
+
(failure) => writeResumeDiagnosticFile(
|
|
1771
|
+
loaded.admitted.runDirectory,
|
|
1772
|
+
loaded.admitted.runId,
|
|
1773
|
+
failure,
|
|
1774
|
+
loaded.admitted.role,
|
|
1775
|
+
),
|
|
1776
|
+
);
|
|
1777
|
+
return { exitCode: error instanceof CliUsageError ? 2 : 1 };
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
|
|
1781
|
+
async function pointExistingRunFailure(
|
|
1782
|
+
home: string,
|
|
1783
|
+
runId: string,
|
|
1784
|
+
authority: DurablePrincipalAuthority,
|
|
1785
|
+
io: CliIo,
|
|
1786
|
+
thrown: unknown,
|
|
1787
|
+
): Promise<boolean> {
|
|
1788
|
+
let foundRunDirectory: string | undefined;
|
|
1789
|
+
try {
|
|
1790
|
+
foundRunDirectory = await findRunDirectoryById(home, runId);
|
|
1791
|
+
} catch {
|
|
1792
|
+
return false;
|
|
1793
|
+
}
|
|
1794
|
+
if (foundRunDirectory === undefined) return false;
|
|
1795
|
+
const runDirectory = foundRunDirectory;
|
|
1796
|
+
|
|
1797
|
+
let record: Awaited<ReturnType<typeof readRoleRunState>>;
|
|
1798
|
+
try {
|
|
1799
|
+
record = await readRoleRunState(runDirectory, authority);
|
|
1800
|
+
} catch {
|
|
1801
|
+
await presentResumeFailurePointer(io, thrown, (failure) =>
|
|
1802
|
+
writeResumeDiagnosticFile(runDirectory, runId, failure),
|
|
1803
|
+
);
|
|
1804
|
+
return true;
|
|
1805
|
+
}
|
|
1806
|
+
if (record === undefined) return false;
|
|
1807
|
+
await presentResumeFailurePointer(io, thrown, (failure) =>
|
|
1808
|
+
writeResumeDiagnosticFile(runDirectory, runId, failure, record.role),
|
|
1809
|
+
);
|
|
1810
|
+
return true;
|
|
1811
|
+
}
|
|
1812
|
+
|
|
1813
|
+
export async function presentLocatedResumeFailure(
|
|
1814
|
+
home: string,
|
|
1815
|
+
runId: string,
|
|
1816
|
+
authority: DurablePrincipalAuthority,
|
|
1817
|
+
io: CliIo,
|
|
1818
|
+
thrown: unknown,
|
|
1819
|
+
): Promise<boolean> {
|
|
1820
|
+
return await pointExistingRunFailure(home, runId, authority, io, thrown);
|
|
1821
|
+
}
|
|
1822
|
+
|
|
1823
|
+
function writeResumeFailurePointer(io: CliIo, errorPath: string): void {
|
|
1824
|
+
io.stderr(formatCliDiagnostic(`续跑失败,当次错误记录:${errorPath}`));
|
|
1825
|
+
}
|
|
1826
|
+
|
|
1827
|
+
export function showResumeErrorPointer(
|
|
1828
|
+
io: CliIo,
|
|
1829
|
+
exitCode: number,
|
|
1830
|
+
terminal: TerminalResult | undefined,
|
|
1831
|
+
): void {
|
|
1832
|
+
if (exitCode === 0 || terminal === undefined) return;
|
|
1833
|
+
const publishedError = terminal.artifacts.find((artifact) => artifact.kind === "error")?.path
|
|
1834
|
+
?? publishedFailureErrorPath(terminal);
|
|
1835
|
+
if (publishedError !== undefined) writeResumeFailurePointer(io, publishedError);
|
|
1836
|
+
}
|
|
1837
|
+
|
|
1838
|
+
async function presentResumeFailurePointer(
|
|
1839
|
+
io: CliIo,
|
|
1840
|
+
thrown: unknown,
|
|
1841
|
+
publish: (failure: ControlledFailure) => Promise<string>,
|
|
1842
|
+
): Promise<void> {
|
|
1843
|
+
const failure = classifyPostAdmissionFailure({
|
|
1844
|
+
timedOut: false,
|
|
1845
|
+
code: null,
|
|
1846
|
+
stderr: "",
|
|
1847
|
+
thrown,
|
|
1848
|
+
});
|
|
1849
|
+
try {
|
|
1850
|
+
writeResumeFailurePointer(io, await publish(failure));
|
|
1851
|
+
} catch (publishError) {
|
|
1852
|
+
const cause: { thrownCause?: string; publishError: string } = {
|
|
1853
|
+
publishError: formatErrorCauseDetail(publishError),
|
|
1854
|
+
};
|
|
1855
|
+
if (thrown instanceof Error && thrown.cause !== undefined) {
|
|
1856
|
+
cause.thrownCause = formatErrorCauseDetail(thrown.cause);
|
|
1728
1857
|
}
|
|
1729
|
-
|
|
1858
|
+
presentStructuralRejection({
|
|
1859
|
+
message: thrown instanceof Error ? thrown.message : String(thrown),
|
|
1860
|
+
cause,
|
|
1861
|
+
}, io);
|
|
1730
1862
|
}
|
|
1731
1863
|
}
|
|
1732
1864
|
|
|
1865
|
+
async function writeResumeDiagnosticFile(
|
|
1866
|
+
runDirectory: string,
|
|
1867
|
+
runId: string,
|
|
1868
|
+
failure: ControlledFailure,
|
|
1869
|
+
role?: AdmittedRoleInvocation["role"],
|
|
1870
|
+
): Promise<string> {
|
|
1871
|
+
const dir = await ensureRealArtifactsDirectory(runDirectory);
|
|
1872
|
+
const path = join(dir, `resume-diagnostic-${randomUUID()}.json`);
|
|
1873
|
+
await writeFile(
|
|
1874
|
+
path,
|
|
1875
|
+
`${JSON.stringify({
|
|
1876
|
+
runId,
|
|
1877
|
+
...(role === undefined ? {} : { role }),
|
|
1878
|
+
diagnostic: failure.diagnostic,
|
|
1879
|
+
...(failure.cause === undefined ? {} : { cause: failure.cause }),
|
|
1880
|
+
...(failure.identity === undefined ? {} : { identity: failure.identity }),
|
|
1881
|
+
...(failure.details === undefined ? {} : { details: failure.details }),
|
|
1882
|
+
}, null, 2)}\n`,
|
|
1883
|
+
{ encoding: "utf8", flag: "wx" },
|
|
1884
|
+
);
|
|
1885
|
+
return path;
|
|
1886
|
+
}
|
|
1887
|
+
|
|
1733
1888
|
/**
|
|
1734
1889
|
* Shared post-admission one-shot path: folds into runPostAdmissionResumable (#840 / #416).
|
|
1735
1890
|
* All callable roles share the single auto-resume loop.
|
|
@@ -116,6 +116,7 @@ import type {
|
|
|
116
116
|
DurablePrincipalCoordinates,
|
|
117
117
|
} from "../host-contracts.ts";
|
|
118
118
|
import { roleRunArtifactsDirectory } from "../role-run-placement.ts";
|
|
119
|
+
import { rewriteRunDirectoryPathValue } from "../role-run-relocation.ts";
|
|
119
120
|
import {
|
|
120
121
|
listSeamOwnedUniqueErrorFacePaths,
|
|
121
122
|
RUN_TERMINAL_ARTIFACT_FILES,
|
|
@@ -286,10 +287,13 @@ export async function attachRecordedSubmissions<T extends TerminalResult>(
|
|
|
286
287
|
// pass courtAttemptId here — roleOutcome already carries this-court payloads
|
|
287
288
|
// from sealedLedgerOutcome when scoped; withSubmissions keeps them.
|
|
288
289
|
void scope;
|
|
289
|
-
|
|
290
|
+
const result = withSubmissions(
|
|
290
291
|
terminal,
|
|
291
292
|
await recordedSubmissionPayloads(admitted, undefined),
|
|
292
293
|
);
|
|
294
|
+
const errorPath = privateFailureErrorPaths.get(terminal);
|
|
295
|
+
if (errorPath !== undefined) privateFailureErrorPaths.set(result, errorPath);
|
|
296
|
+
return result;
|
|
293
297
|
}
|
|
294
298
|
|
|
295
299
|
/**
|
|
@@ -373,6 +377,28 @@ export type ControlledFailure = {
|
|
|
373
377
|
readonly details?: Readonly<Record<string, unknown>>;
|
|
374
378
|
};
|
|
375
379
|
|
|
380
|
+
// A resumable public Terminal omits artifact paths (#108); its actual error
|
|
381
|
+
// publication remains available only to the CLI's resume presentation seam.
|
|
382
|
+
const privateFailureErrorPaths = new WeakMap<TerminalResult, string>();
|
|
383
|
+
|
|
384
|
+
export function publishedFailureErrorPath(terminal: TerminalResult): string | undefined {
|
|
385
|
+
return privateFailureErrorPaths.get(terminal);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
export function rewritePublishedFailureErrorPath(
|
|
389
|
+
terminal: TerminalResult,
|
|
390
|
+
oldRunDirectory: string,
|
|
391
|
+
newRunDirectory: string,
|
|
392
|
+
): void {
|
|
393
|
+
const errorPath = privateFailureErrorPaths.get(terminal);
|
|
394
|
+
if (errorPath !== undefined) {
|
|
395
|
+
privateFailureErrorPaths.set(
|
|
396
|
+
terminal,
|
|
397
|
+
rewriteRunDirectoryPathValue(errorPath, oldRunDirectory, newRunDirectory) as string,
|
|
398
|
+
);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
376
402
|
/**
|
|
377
403
|
* Host stderr as recorded — full bytes, no flood filter, no char clip (#836).
|
|
378
404
|
*/
|
|
@@ -3185,6 +3211,7 @@ export async function publishFailureArtifacts(
|
|
|
3185
3211
|
admitted: AdmittedRoleInvocation,
|
|
3186
3212
|
failure: ControlledFailure,
|
|
3187
3213
|
authority: DurablePrincipalAuthority,
|
|
3214
|
+
onErrorPublished?: (path: string) => void,
|
|
3188
3215
|
): Promise<TerminalArtifactRef[]> {
|
|
3189
3216
|
const { sessionDirectory, sessionFile } = coordinatesFromAdmitted(authority, admitted);
|
|
3190
3217
|
const { baseDir, attempt: baseAttempt } = await resolveFailureArtifactsBase(
|
|
@@ -3267,6 +3294,7 @@ export async function publishFailureArtifacts(
|
|
|
3267
3294
|
errorPayloadBase,
|
|
3268
3295
|
priorIssues,
|
|
3269
3296
|
);
|
|
3297
|
+
onErrorPublished?.(errorWrite.path);
|
|
3270
3298
|
|
|
3271
3299
|
const evidencePayload: Record<string, unknown> = {
|
|
3272
3300
|
runId: admitted.runId,
|
|
@@ -3306,6 +3334,7 @@ export async function settleFailureTerminalResult(
|
|
|
3306
3334
|
authority: DurablePrincipalAuthority,
|
|
3307
3335
|
options: SettlementCourtScope & {
|
|
3308
3336
|
readonly resume?: TerminalResume;
|
|
3337
|
+
readonly onErrorPublished?: (path: string) => void;
|
|
3309
3338
|
} = {},
|
|
3310
3339
|
): Promise<TerminalResult> {
|
|
3311
3340
|
const coordinates = coordinatesFromAdmitted(authority, admitted);
|
|
@@ -3376,7 +3405,8 @@ export async function settleFailureTerminalResult(
|
|
|
3376
3405
|
// Exact-session attendance only — never infer no-advice from caller omission.
|
|
3377
3406
|
const navigator = await extractNavigatorFactFromAdmittedSession(sessionFile);
|
|
3378
3407
|
// Private durable artifacts retain the original diagnostic identity (including run ID).
|
|
3379
|
-
const artifacts = await publishFailureArtifacts(admitted, failure, authority);
|
|
3408
|
+
const artifacts = await publishFailureArtifacts(admitted, failure, authority, options.onErrorPublished);
|
|
3409
|
+
const errorPath = artifacts.find((artifact) => artifact.kind === "error")?.path;
|
|
3380
3410
|
const decisiveFacts: Record<string, unknown> = {
|
|
3381
3411
|
...(failure.cause === undefined ? {} : { cause: failure.cause }),
|
|
3382
3412
|
diagnostic: failure.diagnostic,
|
|
@@ -3402,7 +3432,7 @@ export async function settleFailureTerminalResult(
|
|
|
3402
3432
|
diagnostic: failure.diagnostic,
|
|
3403
3433
|
decisiveFacts,
|
|
3404
3434
|
};
|
|
3405
|
-
|
|
3435
|
+
const terminal = await withOptionalGateProjection(
|
|
3406
3436
|
{
|
|
3407
3437
|
roleOutcome,
|
|
3408
3438
|
navigator,
|
|
@@ -3412,6 +3442,8 @@ export async function settleFailureTerminalResult(
|
|
|
3412
3442
|
sessionDirectory,
|
|
3413
3443
|
detourGateContext(admitted, options),
|
|
3414
3444
|
);
|
|
3445
|
+
if (errorPath !== undefined) privateFailureErrorPaths.set(terminal, errorPath);
|
|
3446
|
+
return terminal;
|
|
3415
3447
|
}
|
|
3416
3448
|
const roleOutcome: TerminalRoleOutcome = {
|
|
3417
3449
|
kind: "failure",
|
|
@@ -3451,13 +3483,14 @@ export async function settleJudgeFailureTerminalResult(
|
|
|
3451
3483
|
*/
|
|
3452
3484
|
export function presentFailureTerminal(
|
|
3453
3485
|
terminal: TerminalResult,
|
|
3454
|
-
io: { stdout: (text: string) => void; stderr: (text: string) => void },
|
|
3486
|
+
io: { stdout: (text: string) => void; stderr: (text: string) => void; omitFailureStderrDiagnostic?: boolean },
|
|
3455
3487
|
): void {
|
|
3456
3488
|
if (terminal.roleOutcome.kind !== "failure" && terminal.roleOutcome.kind !== "no_receipt") {
|
|
3457
3489
|
throw new TypeError("presentFailureTerminal requires a failure or no-receipt role outcome");
|
|
3458
3490
|
}
|
|
3459
3491
|
io.stdout(formatTerminalResult(terminal));
|
|
3460
3492
|
if (terminal.roleOutcome.kind === "failure") {
|
|
3493
|
+
if (io.omitFailureStderrDiagnostic) return;
|
|
3461
3494
|
io.stderr(formatFailureStderrDiagnostic({
|
|
3462
3495
|
...(terminal.roleOutcome.cause === undefined ? {} : { cause: terminal.roleOutcome.cause }),
|
|
3463
3496
|
diagnostic: terminal.roleOutcome.diagnostic,
|