@akagilnc/pi-workflow-roles 0.1.4239 → 0.1.4259
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/acp-host/production-host.js +547 -221
- package/dist/engine-detour-tool.js +64 -5
- package/dist/engine-detour-usage.js +285 -0
- package/dist/headless-host/production-host.js +557 -231
- package/dist/pi/role-turn-host.js +10 -0
- package/dist/public-cli/main.js +433 -202
- package/dist/public-cli/post-admission.js +72 -43
- package/dist/public-cli/settlement.js +80 -24
- package/dist/public-cli/turn-request.js +3 -0
- package/package.json +1 -1
- package/src/engine-detour-tool.ts +106 -8
- package/src/engine-detour-usage.ts +373 -0
- package/src/host-contracts.ts +12 -1
- package/src/pi/adapter.ts +6 -0
- package/src/pi/role-turn-host.ts +6 -0
- package/src/public-cli/post-admission.ts +91 -49
- package/src/public-cli/settlement.ts +148 -23
- package/src/public-cli/turn-request.ts +5 -0
- package/src/role-envelope.ts +2 -0
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Role runners supply only turn request projection and narrow settlement adapters.
|
|
7
7
|
*/
|
|
8
8
|
import { randomUUID } from "node:crypto";
|
|
9
|
-
import {
|
|
9
|
+
import { writeFile } from "node:fs/promises";
|
|
10
10
|
import { isAbsolute, join, resolve } from "node:path";
|
|
11
11
|
|
|
12
12
|
import {
|
|
@@ -73,6 +73,11 @@ function isStationChildOfficerDialogue(
|
|
|
73
73
|
): boolean {
|
|
74
74
|
return env.stationChild === true && isOfficerReviewSeat(role);
|
|
75
75
|
}
|
|
76
|
+
import {
|
|
77
|
+
mintEngineDetourInvocationScope,
|
|
78
|
+
readInvocationSelectedHost,
|
|
79
|
+
withEngineDetourInvocationScope,
|
|
80
|
+
} from "../engine-detour-usage.ts";
|
|
76
81
|
import { projectHostTransitionPriorNative } from "../host-transition-prior-native.ts";
|
|
77
82
|
import type { CredentialProviders, SeatModelConfig } from "./config.ts";
|
|
78
83
|
import {
|
|
@@ -208,19 +213,6 @@ async function recordBestEffortPostDispatchDiagnostic<A extends AdmittedRoleInvo
|
|
|
208
213
|
}
|
|
209
214
|
}
|
|
210
215
|
|
|
211
|
-
/** Previous main-session host recorded on invocation.json, if any. */
|
|
212
|
-
async function readInvocationHost(runDirectory: string): Promise<string | undefined> {
|
|
213
|
-
try {
|
|
214
|
-
const raw = JSON.parse(await readFile(join(runDirectory, "invocation.json"), "utf8")) as {
|
|
215
|
-
host?: unknown;
|
|
216
|
-
};
|
|
217
|
-
return typeof raw.host === "string" && raw.host.trim() !== "" ? raw.host : undefined;
|
|
218
|
-
} catch (error) {
|
|
219
|
-
if ((error as NodeJS.ErrnoException).code === "ENOENT") return undefined;
|
|
220
|
-
throw error;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
216
|
export type PostAdmissionEnv = {
|
|
225
217
|
home: string;
|
|
226
218
|
agentDir: string;
|
|
@@ -312,6 +304,8 @@ export type ControlledFailureInput = {
|
|
|
312
304
|
* already the reported cause.
|
|
313
305
|
*/
|
|
314
306
|
skipRunStateWrite?: boolean;
|
|
307
|
+
/** Public-invocation scope from the shared Host envelope (#537). */
|
|
308
|
+
invocationScopeId?: string;
|
|
315
309
|
};
|
|
316
310
|
|
|
317
311
|
/** Result of seat prep after the single pre-lease admitted load. */
|
|
@@ -451,9 +445,15 @@ export async function presentControlledFailure<
|
|
|
451
445
|
admitted,
|
|
452
446
|
failure,
|
|
453
447
|
authority,
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
448
|
+
{
|
|
449
|
+
...(resumable
|
|
450
|
+
? { resume: { command: renderResumeCommand(admitted.runId) } }
|
|
451
|
+
: {}),
|
|
452
|
+
...(failureInput.invocationScopeId === undefined ||
|
|
453
|
+
failureInput.invocationScopeId.length === 0
|
|
454
|
+
? {}
|
|
455
|
+
: { invocationScopeId: failureInput.invocationScopeId }),
|
|
456
|
+
},
|
|
457
457
|
),
|
|
458
458
|
);
|
|
459
459
|
presentFailureTerminal(terminal, io);
|
|
@@ -613,12 +613,12 @@ export async function dispatchPostAdmissionTurn<
|
|
|
613
613
|
return {
|
|
614
614
|
...(await presentControlledFailure(
|
|
615
615
|
admitted,
|
|
616
|
-
{
|
|
616
|
+
withEngineDetourInvocationScope({
|
|
617
617
|
timedOut: false,
|
|
618
618
|
code: null,
|
|
619
619
|
stderr: "",
|
|
620
620
|
thrown: error,
|
|
621
|
-
},
|
|
621
|
+
}, request.invocationScopeId),
|
|
622
622
|
adapters,
|
|
623
623
|
env.principalAuthority,
|
|
624
624
|
io,
|
|
@@ -639,7 +639,7 @@ export async function dispatchPostAdmissionTurn<
|
|
|
639
639
|
return {
|
|
640
640
|
...(await presentControlledFailure(
|
|
641
641
|
admitted,
|
|
642
|
-
missingCredential,
|
|
642
|
+
withEngineDetourInvocationScope(missingCredential, request.invocationScopeId),
|
|
643
643
|
adapters,
|
|
644
644
|
env.principalAuthority,
|
|
645
645
|
io,
|
|
@@ -659,7 +659,7 @@ export async function dispatchPostAdmissionTurn<
|
|
|
659
659
|
: env.principalAuthority.decode(admitted.principal);
|
|
660
660
|
let hostTransition: RoleTurnRequest["hostTransition"];
|
|
661
661
|
try {
|
|
662
|
-
previousHost =
|
|
662
|
+
previousHost = readInvocationSelectedHost(admitted.runDirectory);
|
|
663
663
|
hostTransition =
|
|
664
664
|
previousHost !== undefined && liveHost !== undefined && principalCoordinates !== undefined
|
|
665
665
|
? await projectHostTransitionPriorNative({
|
|
@@ -673,12 +673,12 @@ export async function dispatchPostAdmissionTurn<
|
|
|
673
673
|
return {
|
|
674
674
|
...(await presentControlledFailure(
|
|
675
675
|
admitted,
|
|
676
|
-
{
|
|
676
|
+
withEngineDetourInvocationScope({
|
|
677
677
|
timedOut: false,
|
|
678
678
|
code: null,
|
|
679
679
|
stderr: "",
|
|
680
680
|
thrown: error,
|
|
681
|
-
},
|
|
681
|
+
}, request.invocationScopeId),
|
|
682
682
|
adapters,
|
|
683
683
|
env.principalAuthority,
|
|
684
684
|
io,
|
|
@@ -696,7 +696,7 @@ export async function dispatchPostAdmissionTurn<
|
|
|
696
696
|
// executeTurn — not merely past beforeDispatch (#840 r9 判词 class 2). Any
|
|
697
697
|
// pre-turn retry (beforeDispatch, dossier projection, continuation
|
|
698
698
|
// assembly) must still see the prior invocation host on its next attempt;
|
|
699
|
-
// committing env.host earlier would make
|
|
699
|
+
// committing env.host earlier would make readInvocationSelectedHost read back the
|
|
700
700
|
// new host on the retry and silently drop hostTransition.
|
|
701
701
|
// Failures settle the run (presentControlledFailure); they must not leave it
|
|
702
702
|
// permanently running. Call-local auto-resume retries this hook until it
|
|
@@ -708,12 +708,12 @@ export async function dispatchPostAdmissionTurn<
|
|
|
708
708
|
} catch (error) {
|
|
709
709
|
const settled = (await presentControlledFailure(
|
|
710
710
|
admitted,
|
|
711
|
-
{
|
|
711
|
+
withEngineDetourInvocationScope({
|
|
712
712
|
timedOut: false,
|
|
713
713
|
code: null,
|
|
714
714
|
stderr: "",
|
|
715
715
|
thrown: error,
|
|
716
|
-
},
|
|
716
|
+
}, request.invocationScopeId),
|
|
717
717
|
adapters,
|
|
718
718
|
env.principalAuthority,
|
|
719
719
|
io,
|
|
@@ -740,6 +740,11 @@ export async function dispatchPostAdmissionTurn<
|
|
|
740
740
|
if (hostTransition !== undefined) {
|
|
741
741
|
turnRequest = { ...turnRequest, hostTransition };
|
|
742
742
|
}
|
|
743
|
+
// Selected host axis rides the shared Host envelope for in-turn tools
|
|
744
|
+
// (detour usage ledger) — never a pre-spawn invocation.json reread.
|
|
745
|
+
if (typeof liveHost === "string" && liveHost.trim() !== "") {
|
|
746
|
+
turnRequest = { ...turnRequest, host: liveHost.trim() };
|
|
747
|
+
}
|
|
743
748
|
if (isStationChildOfficerDialogue(admitted.role, env)) {
|
|
744
749
|
// 0081 non-body face: freeze pointer section under run/attachments/.
|
|
745
750
|
// Peer dialogue continuation.prompt stays parent payload only — the seat
|
|
@@ -780,18 +785,22 @@ export async function dispatchPostAdmissionTurn<
|
|
|
780
785
|
env.engineModel,
|
|
781
786
|
);
|
|
782
787
|
|
|
788
|
+
// #537 invocation scope is bound once at the public-entry boundary
|
|
789
|
+
// (runPostAdmissionResumable / ManualResume / station-child), not here:
|
|
790
|
+
// auto-resume re-enters this dispatch and must reuse the same scope.
|
|
791
|
+
|
|
783
792
|
let result: RoleTurnResult;
|
|
784
793
|
try {
|
|
785
794
|
result = await env.roleTurnHost.executeTurn(turnRequest);
|
|
786
795
|
} catch (error) {
|
|
787
796
|
const settled = await settleAfterTurnStarted(
|
|
788
|
-
|
|
789
|
-
|
|
797
|
+
admitted,
|
|
798
|
+
withEngineDetourInvocationScope({
|
|
790
799
|
timedOut: false,
|
|
791
800
|
code: null,
|
|
792
801
|
stderr: "",
|
|
793
802
|
thrown: error,
|
|
794
|
-
},
|
|
803
|
+
}, request.invocationScopeId),
|
|
795
804
|
adapters,
|
|
796
805
|
env.principalAuthority,
|
|
797
806
|
io,
|
|
@@ -851,9 +860,18 @@ export async function dispatchPostAdmissionTurn<
|
|
|
851
860
|
}
|
|
852
861
|
|
|
853
862
|
const courtScope =
|
|
854
|
-
request.courtAttemptId === undefined || request.courtAttemptId.length === 0
|
|
863
|
+
(request.courtAttemptId === undefined || request.courtAttemptId.length === 0) &&
|
|
864
|
+
(request.invocationScopeId === undefined || request.invocationScopeId.length === 0)
|
|
855
865
|
? undefined
|
|
856
|
-
: {
|
|
866
|
+
: {
|
|
867
|
+
...(request.courtAttemptId === undefined || request.courtAttemptId.length === 0
|
|
868
|
+
? {}
|
|
869
|
+
: { courtAttemptId: request.courtAttemptId }),
|
|
870
|
+
...(request.invocationScopeId === undefined ||
|
|
871
|
+
request.invocationScopeId.length === 0
|
|
872
|
+
? {}
|
|
873
|
+
: { invocationScopeId: request.invocationScopeId }),
|
|
874
|
+
};
|
|
857
875
|
|
|
858
876
|
// Single complete boundary (#840 r9 判词 class 1): resolving the
|
|
859
877
|
// host/runner failure facts, trySettle, its shouldPresent gate, and the
|
|
@@ -989,13 +1007,13 @@ export async function dispatchPostAdmissionTurn<
|
|
|
989
1007
|
// Settle (or its shouldPresent gate, or the failure-fact resolution
|
|
990
1008
|
// above) throw is a real failure fact — never swallow into undefined.
|
|
991
1009
|
const settledFailure = await settleAfterTurnStarted(
|
|
992
|
-
|
|
993
|
-
|
|
1010
|
+
admitted,
|
|
1011
|
+
withEngineDetourInvocationScope({
|
|
994
1012
|
timedOut: false,
|
|
995
1013
|
code: result.code,
|
|
996
1014
|
stderr: result.stderr,
|
|
997
1015
|
thrown: error,
|
|
998
|
-
},
|
|
1016
|
+
}, request.invocationScopeId),
|
|
999
1017
|
adapters,
|
|
1000
1018
|
env.principalAuthority,
|
|
1001
1019
|
io,
|
|
@@ -1019,14 +1037,14 @@ export async function dispatchPostAdmissionTurn<
|
|
|
1019
1037
|
// write presentControlledFailure would otherwise retry — don't
|
|
1020
1038
|
// call a known-failing operation twice.
|
|
1021
1039
|
const failed = await settleAfterTurnStarted(
|
|
1022
|
-
|
|
1023
|
-
|
|
1040
|
+
admitted,
|
|
1041
|
+
withEngineDetourInvocationScope({
|
|
1024
1042
|
timedOut: false,
|
|
1025
1043
|
code: null,
|
|
1026
1044
|
stderr: "",
|
|
1027
1045
|
thrown: error,
|
|
1028
1046
|
skipRunStateWrite: true,
|
|
1029
|
-
},
|
|
1047
|
+
}, request.invocationScopeId),
|
|
1030
1048
|
adapters,
|
|
1031
1049
|
env.principalAuthority,
|
|
1032
1050
|
io,
|
|
@@ -1048,8 +1066,8 @@ export async function dispatchPostAdmissionTurn<
|
|
|
1048
1066
|
? undefined
|
|
1049
1067
|
: { stderrLogWriteFailure: describeCaughtError(stderrLogWriteFailure) };
|
|
1050
1068
|
const failed = await settleAfterTurnStarted(
|
|
1051
|
-
|
|
1052
|
-
|
|
1069
|
+
admitted,
|
|
1070
|
+
withEngineDetourInvocationScope({
|
|
1053
1071
|
timedOut: result.timedOut,
|
|
1054
1072
|
code: result.code,
|
|
1055
1073
|
stderr: result.stderr,
|
|
@@ -1067,7 +1085,7 @@ export async function dispatchPostAdmissionTurn<
|
|
|
1067
1085
|
},
|
|
1068
1086
|
}
|
|
1069
1087
|
: { knownDetails: stderrLogWriteDetails }),
|
|
1070
|
-
},
|
|
1088
|
+
}, request.invocationScopeId),
|
|
1071
1089
|
adapters,
|
|
1072
1090
|
env.principalAuthority,
|
|
1073
1091
|
io,
|
|
@@ -1081,13 +1099,13 @@ export async function dispatchPostAdmissionTurn<
|
|
|
1081
1099
|
// lawful absence of a receipt. Honest and loud, not silently no_receipt.
|
|
1082
1100
|
if (stderrLogWriteFailure !== undefined) {
|
|
1083
1101
|
const failed = await settleAfterTurnStarted(
|
|
1084
|
-
|
|
1085
|
-
|
|
1102
|
+
admitted,
|
|
1103
|
+
withEngineDetourInvocationScope({
|
|
1086
1104
|
timedOut: false,
|
|
1087
1105
|
code: result.code,
|
|
1088
1106
|
stderr: result.stderr,
|
|
1089
1107
|
thrown: stderrLogWriteFailure,
|
|
1090
|
-
},
|
|
1108
|
+
}, request.invocationScopeId),
|
|
1091
1109
|
adapters,
|
|
1092
1110
|
env.principalAuthority,
|
|
1093
1111
|
io,
|
|
@@ -1098,7 +1116,7 @@ export async function dispatchPostAdmissionTurn<
|
|
|
1098
1116
|
|
|
1099
1117
|
const noReceipt = await attachRecordedSubmissions(
|
|
1100
1118
|
admitted,
|
|
1101
|
-
await settleHostEndedNoReceipt(admitted, env.principalAuthority) as T,
|
|
1119
|
+
await settleHostEndedNoReceipt(admitted, env.principalAuthority, courtScope) as T,
|
|
1102
1120
|
courtScope,
|
|
1103
1121
|
);
|
|
1104
1122
|
if (persistRunState) {
|
|
@@ -1112,13 +1130,13 @@ export async function dispatchPostAdmissionTurn<
|
|
|
1112
1130
|
// skipRunStateWrite: don't retry the write that just threw.
|
|
1113
1131
|
const failed = await settleAfterTurnStarted(
|
|
1114
1132
|
admitted,
|
|
1115
|
-
{
|
|
1133
|
+
withEngineDetourInvocationScope({
|
|
1116
1134
|
timedOut: false,
|
|
1117
1135
|
code: null,
|
|
1118
1136
|
stderr: "",
|
|
1119
1137
|
thrown: error,
|
|
1120
1138
|
skipRunStateWrite: true,
|
|
1121
|
-
},
|
|
1139
|
+
}, request.invocationScopeId),
|
|
1122
1140
|
adapters,
|
|
1123
1141
|
env.principalAuthority,
|
|
1124
1142
|
io,
|
|
@@ -1463,6 +1481,12 @@ export async function runPostAdmissionSeatResume<
|
|
|
1463
1481
|
let firstTurn: RoleTurnRequest | undefined;
|
|
1464
1482
|
const stationAdapters = withOnceSuccessfulBeforeDispatch(adapters);
|
|
1465
1483
|
type StationChildAttempt = { readonly resumeTurn: boolean };
|
|
1484
|
+
// One public call → one detour scope across in-place auto-resume dispatches.
|
|
1485
|
+
const invocationScopeId = mintEngineDetourInvocationScope({
|
|
1486
|
+
...(input.effectiveEngine === undefined
|
|
1487
|
+
? {}
|
|
1488
|
+
: { effectiveEngine: input.effectiveEngine }),
|
|
1489
|
+
});
|
|
1466
1490
|
return await runWithAutoResumeLoop({
|
|
1467
1491
|
admitted: loaded.admitted,
|
|
1468
1492
|
principalAuthority: input.env.principalAuthority,
|
|
@@ -1500,7 +1524,10 @@ export async function runPostAdmissionSeatResume<
|
|
|
1500
1524
|
},
|
|
1501
1525
|
};
|
|
1502
1526
|
}
|
|
1503
|
-
const turnRequest =
|
|
1527
|
+
const turnRequest = withEngineDetourInvocationScope(
|
|
1528
|
+
await buildRequestAfterLease(),
|
|
1529
|
+
invocationScopeId,
|
|
1530
|
+
);
|
|
1504
1531
|
firstTurn = turnRequest;
|
|
1505
1532
|
return turnRequest;
|
|
1506
1533
|
},
|
|
@@ -1621,6 +1648,15 @@ export async function runPostAdmissionResumable<
|
|
|
1621
1648
|
const { admitted, env, io, buildInitialRequest, buildResumeRequest, effectiveEngine } = input;
|
|
1622
1649
|
const adapters = withOnceSuccessfulBeforeDispatch(input.adapters);
|
|
1623
1650
|
|
|
1651
|
+
// One public call → one detour scope across in-place auto-resume dispatches.
|
|
1652
|
+
const invocationScopeId = mintEngineDetourInvocationScope({
|
|
1653
|
+
...(effectiveEngine === undefined ? {} : { effectiveEngine }),
|
|
1654
|
+
});
|
|
1655
|
+
const buildScopedInitial = (): RoleTurnRequest =>
|
|
1656
|
+
withEngineDetourInvocationScope(buildInitialRequest(), invocationScopeId);
|
|
1657
|
+
const buildScopedResume = (): RoleTurnRequest =>
|
|
1658
|
+
withEngineDetourInvocationScope(buildResumeRequest(), invocationScopeId);
|
|
1659
|
+
|
|
1624
1660
|
return runWithAutoResumeLoop({
|
|
1625
1661
|
admitted,
|
|
1626
1662
|
principalAuthority: env.principalAuthority,
|
|
@@ -1628,8 +1664,8 @@ export async function runPostAdmissionResumable<
|
|
|
1628
1664
|
io,
|
|
1629
1665
|
sessionAppender: env.sessionAppender,
|
|
1630
1666
|
autoResumeLimit: env.autoResumeLimit,
|
|
1631
|
-
buildInitialPayload:
|
|
1632
|
-
buildResumePayload:
|
|
1667
|
+
buildInitialPayload: buildScopedInitial,
|
|
1668
|
+
buildResumePayload: buildScopedResume,
|
|
1633
1669
|
dispatch: async (request, lease, _isFirst, attemptIo) => {
|
|
1634
1670
|
const result = await dispatchPostAdmissionTurn({
|
|
1635
1671
|
admitted,
|
|
@@ -1714,6 +1750,11 @@ export async function runPostAdmissionManualResume<
|
|
|
1714
1750
|
throw error;
|
|
1715
1751
|
}
|
|
1716
1752
|
|
|
1753
|
+
// Explicit public resume is a new counting unit — mint once for this call.
|
|
1754
|
+
const invocationScopeId = mintEngineDetourInvocationScope({
|
|
1755
|
+
...(effectiveEngine === undefined ? {} : { effectiveEngine }),
|
|
1756
|
+
});
|
|
1757
|
+
|
|
1717
1758
|
const result = await dispatchAfterWriterLease({
|
|
1718
1759
|
lease,
|
|
1719
1760
|
build: async () => {
|
|
@@ -1725,6 +1766,7 @@ export async function runPostAdmissionManualResume<
|
|
|
1725
1766
|
}
|
|
1726
1767
|
request = await buildRequestAfterLease();
|
|
1727
1768
|
}
|
|
1769
|
+
request = withEngineDetourInvocationScope(request, invocationScopeId);
|
|
1728
1770
|
return request;
|
|
1729
1771
|
},
|
|
1730
1772
|
dispatch: (turnRequest) =>
|