@akagilnc/pi-workflow-roles 0.1.4321 → 0.1.4387
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 +4 -1
- package/README.zh-CN.md +5 -1
- package/dist/acp-host/production-host.js +1308 -587
- package/dist/doctor-contracts.js +2 -2
- package/dist/engine-detour-tool.js +2 -8
- package/dist/gatekeeper-role.js +4 -19
- package/dist/headless-host/production-host.js +2613 -1892
- package/dist/merger-contracts.js +2 -2
- package/dist/migrate-book-topology.js +34 -9
- package/dist/notary-contracts.js +2 -2
- package/dist/package-contracts/auditor-output.js +2 -2
- package/dist/package-contracts/fixer-output.js +2 -2
- package/dist/package-contracts/gatekeeper-output.js +2 -2
- package/dist/package-contracts/navigator-output.js +2 -2
- package/dist/package-contracts/terminating-infrastructure.js +7 -2
- package/dist/package-contracts/terminating-tools.js +6 -0
- package/dist/packaged-role-registry.js +20 -1
- package/dist/public-cli/case-dossier-delivery.js +45 -28
- package/dist/public-cli/countersign-run.js +439 -0
- package/dist/public-cli/invocation.js +10 -0
- package/dist/public-cli/main.js +388 -101
- package/dist/public-cli/option-definitions.js +14 -0
- package/dist/public-cli/post-admission.js +44 -49
- package/dist/public-cli/run-lifecycle.js +13 -1
- package/dist/public-cli/settlement.js +14 -53
- package/dist/public-role-summons.js +14 -0
- package/dist/secretariat-contracts.js +8 -0
- package/dist/sitian-appender.js +21 -4
- package/extensions/role-runtime.ts +1 -0
- package/package.json +1 -1
- package/scripts/build-package.mjs +1 -0
- package/souls/secretariat.md +26 -0
- package/souls/ticket-law.md +9 -0
- package/src/collector-tool-schemas.ts +2 -2
- package/src/countersign-role.ts +2 -2
- package/src/diarist-role.ts +2 -2
- package/src/doctor-contracts.ts +2 -2
- package/src/engine-detour-tool.ts +3 -9
- package/src/gatekeeper-pass-envelope.ts +35 -2
- package/src/gatekeeper-role.ts +8 -31
- package/src/gleaner-left-role.ts +2 -2
- package/src/host-contracts.ts +2 -1
- package/src/inspector-role.ts +2 -2
- package/src/judge-role.ts +2 -2
- package/src/merger-contracts.ts +2 -2
- package/src/notary-contracts.ts +2 -2
- package/src/package-contracts/auditor-output.ts +2 -2
- package/src/package-contracts/fixer-output.ts +2 -2
- package/src/package-contracts/gatekeeper-output.ts +2 -2
- package/src/package-contracts/navigator-output.ts +2 -2
- package/src/package-contracts/terminating-infrastructure.ts +13 -3
- package/src/package-contracts/terminating-tools.ts +9 -1
- package/src/packaged-role-registry.ts +20 -1
- package/src/public-cli/case-dossier-delivery.ts +48 -29
- package/src/public-cli/cli.ts +10 -0
- package/src/public-cli/countersign-run.ts +29 -5
- package/src/public-cli/invocation.ts +28 -2
- package/src/public-cli/option-definitions.ts +17 -0
- package/src/public-cli/post-admission.ts +45 -58
- package/src/public-cli/run-lifecycle.ts +29 -2
- package/src/public-cli/secretariat-run.ts +266 -0
- package/src/public-cli/settlement.ts +31 -55
- package/src/public-cli/terminal.ts +2 -1
- package/src/public-role-summons.ts +23 -1
- package/src/reviewer-role.ts +2 -2
- package/src/role-runtime-dependencies.ts +1 -0
- package/src/role-runtime.ts +203 -18
- package/src/secretariat-contracts.ts +27 -0
- package/src/secretariat-role.ts +210 -0
- package/src/sitian-appender.ts +36 -3
- package/src/worker-role.ts +2 -2
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public Secretariat (中书省) Role run: admit → 起居郎 typed identity → bind/relocate
|
|
3
|
+
* → shared post-admission (dossier delivery) → settle (#924).
|
|
4
|
+
* Instruction-seat face like Judge; nested countersign is role-tool driven.
|
|
5
|
+
* Ticket identity reuses the court diarist seam (no prose regex; no second lifecycle).
|
|
6
|
+
*/
|
|
7
|
+
import type { DurablePrincipalAuthority, RoleTurnRequest } from "../host-contracts.ts";
|
|
8
|
+
import { engineSessionMaterialFromOptions, pickEngineAxis } from "../package-resources/engine-material.ts";
|
|
9
|
+
import { CliUsageError } from "./cli-errors.ts";
|
|
10
|
+
import {
|
|
11
|
+
admitSecretariatInvocation,
|
|
12
|
+
bindAdmittedTicketNumber,
|
|
13
|
+
buildSecretariatTransportPrompt,
|
|
14
|
+
relocateAdmittedRunToTicket,
|
|
15
|
+
type AdmittedSecretariatInvocation,
|
|
16
|
+
type ParseSecretariatArgvResult,
|
|
17
|
+
} from "./invocation.ts";
|
|
18
|
+
import {
|
|
19
|
+
invokeCourtDiarist,
|
|
20
|
+
type CourtDiaristSummonEnv,
|
|
21
|
+
} from "./countersign-run.ts";
|
|
22
|
+
import {
|
|
23
|
+
presentControlledFailure,
|
|
24
|
+
runPostAdmissionOneShot,
|
|
25
|
+
type PostAdmissionEnv,
|
|
26
|
+
runPostAdmissionSeatResume,
|
|
27
|
+
resumeTurnRequestProjectionOptions,
|
|
28
|
+
} from "./post-admission.ts";
|
|
29
|
+
import {
|
|
30
|
+
loadResumableSecretariatRun,
|
|
31
|
+
markRunAdmitted,
|
|
32
|
+
type PublicResumeRequest,
|
|
33
|
+
} from "./run-lifecycle.ts";
|
|
34
|
+
import {
|
|
35
|
+
presentStructuralRejection,
|
|
36
|
+
trySettleSecretariatTerminalResult,
|
|
37
|
+
} from "./settlement.ts";
|
|
38
|
+
import type { CliIo } from "./cli-io.ts";
|
|
39
|
+
import type { TerminalResult } from "./terminal.ts";
|
|
40
|
+
import {
|
|
41
|
+
projectRoleTurnRequest,
|
|
42
|
+
type RoleTurnRequestProjectionOptions,
|
|
43
|
+
} from "./turn-request.ts";
|
|
44
|
+
|
|
45
|
+
export type SecretariatRunEnv = PostAdmissionEnv & {
|
|
46
|
+
principalAuthority: DurablePrincipalAuthority;
|
|
47
|
+
createRunId?: () => string;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/** Project admitted invocation onto the host-neutral turn request. */
|
|
51
|
+
export function buildSecretariatTurnRequest(
|
|
52
|
+
admitted: AdmittedSecretariatInvocation,
|
|
53
|
+
options: RoleTurnRequestProjectionOptions,
|
|
54
|
+
): RoleTurnRequest {
|
|
55
|
+
return projectRoleTurnRequest(
|
|
56
|
+
admitted,
|
|
57
|
+
{
|
|
58
|
+
activation: {
|
|
59
|
+
role: "secretariat" as const,
|
|
60
|
+
...(admitted.ticketNumber === undefined
|
|
61
|
+
? {}
|
|
62
|
+
: { ticketNumber: admitted.ticketNumber }),
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
options,
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function diaristEnv(env: SecretariatRunEnv): CourtDiaristSummonEnv {
|
|
70
|
+
return {
|
|
71
|
+
cwd: env.cwd,
|
|
72
|
+
home: env.home,
|
|
73
|
+
agentDir: env.agentDir,
|
|
74
|
+
packageRoot: env.packageRoot,
|
|
75
|
+
...(env.credentials === undefined ? {} : { credentials: env.credentials }),
|
|
76
|
+
...(env.signal === undefined ? {} : { signal: env.signal }),
|
|
77
|
+
...(env.hostAdapters === undefined ? {} : { hostAdapters: env.hostAdapters }),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export async function runPublicSecretariat(
|
|
82
|
+
argv: readonly string[],
|
|
83
|
+
env: SecretariatRunEnv,
|
|
84
|
+
io: CliIo,
|
|
85
|
+
parseSecretariatArgv: (args: readonly string[]) => ParseSecretariatArgvResult,
|
|
86
|
+
): Promise<{
|
|
87
|
+
exitCode: number;
|
|
88
|
+
admitted?: AdmittedSecretariatInvocation;
|
|
89
|
+
terminal?: TerminalResult;
|
|
90
|
+
}> {
|
|
91
|
+
let parsed: ParseSecretariatArgvResult;
|
|
92
|
+
try {
|
|
93
|
+
parsed = parseSecretariatArgv(argv);
|
|
94
|
+
} catch (error) {
|
|
95
|
+
if (error instanceof CliUsageError) {
|
|
96
|
+
presentStructuralRejection(error, io);
|
|
97
|
+
return { exitCode: 2 };
|
|
98
|
+
}
|
|
99
|
+
throw error;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
let admitted: AdmittedSecretariatInvocation;
|
|
103
|
+
try {
|
|
104
|
+
admitted = await admitSecretariatInvocation({
|
|
105
|
+
home: env.home,
|
|
106
|
+
principalAuthority: env.principalAuthority,
|
|
107
|
+
cwd: env.cwd,
|
|
108
|
+
instruction: parsed.instruction,
|
|
109
|
+
attachmentPaths: parsed.attachmentPaths,
|
|
110
|
+
...(parsed.project === undefined ? {} : { project: parsed.project }),
|
|
111
|
+
...(env.createRunId === undefined ? {} : { createRunId: env.createRunId }),
|
|
112
|
+
...(env.model === undefined ? {} : { model: env.model }),
|
|
113
|
+
...(env.correlationId === undefined ? {} : { correlationId: env.correlationId }),
|
|
114
|
+
});
|
|
115
|
+
} catch (error) {
|
|
116
|
+
if (error instanceof CliUsageError) {
|
|
117
|
+
presentStructuralRejection(error, io);
|
|
118
|
+
return { exitCode: 2 };
|
|
119
|
+
}
|
|
120
|
+
throw error;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
await markRunAdmitted(admitted, env.principalAuthority);
|
|
124
|
+
|
|
125
|
+
// #924 G3 / ADR 0075 / 0081: ticket identity is 起居郎 typed assertion — never
|
|
126
|
+
// prose regex. escalate / real station failure → controlled failure; lawful
|
|
127
|
+
// true-unbound continues unbound (ADR 0075 真无票→无录; 第 0 条不拒收);
|
|
128
|
+
// ticket → bind + relocate so post-admission can deliver 起居录.
|
|
129
|
+
const outcome = await invokeCourtDiarist(
|
|
130
|
+
{
|
|
131
|
+
instruction: parsed.instruction,
|
|
132
|
+
projectRoot: admitted.projectRoot,
|
|
133
|
+
failureLabel: "secretariat unbound summons",
|
|
134
|
+
attachmentPaths: admitted.attachments.map((attachment) => attachment.frozenPath),
|
|
135
|
+
correlationId: admitted.runId,
|
|
136
|
+
},
|
|
137
|
+
diaristEnv(env),
|
|
138
|
+
io,
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
if (outcome.identity.kind === "escalate") {
|
|
142
|
+
return await presentControlledFailure(
|
|
143
|
+
admitted,
|
|
144
|
+
{
|
|
145
|
+
timedOut: false,
|
|
146
|
+
code: null,
|
|
147
|
+
stderr: "",
|
|
148
|
+
thrown: new Error(
|
|
149
|
+
"court diarist station escalated (cannot identify court target)",
|
|
150
|
+
),
|
|
151
|
+
},
|
|
152
|
+
secretariatAdapters(),
|
|
153
|
+
env.principalAuthority,
|
|
154
|
+
io,
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (outcome.failedWithoutEscalate !== undefined) {
|
|
159
|
+
return await presentControlledFailure(
|
|
160
|
+
admitted,
|
|
161
|
+
{
|
|
162
|
+
timedOut: false,
|
|
163
|
+
code: null,
|
|
164
|
+
stderr: "",
|
|
165
|
+
thrown: new Error(outcome.failedWithoutEscalate.diagnostic),
|
|
166
|
+
},
|
|
167
|
+
secretariatAdapters(),
|
|
168
|
+
env.principalAuthority,
|
|
169
|
+
io,
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (outcome.identity.kind === "ticket") {
|
|
174
|
+
try {
|
|
175
|
+
await bindAdmittedTicketNumber(admitted, outcome.identity.ticketNumber);
|
|
176
|
+
await relocateAdmittedRunToTicket(admitted, env.principalAuthority);
|
|
177
|
+
} catch (error) {
|
|
178
|
+
return await presentControlledFailure(
|
|
179
|
+
admitted,
|
|
180
|
+
{
|
|
181
|
+
timedOut: false,
|
|
182
|
+
code: null,
|
|
183
|
+
stderr: "",
|
|
184
|
+
thrown: error,
|
|
185
|
+
},
|
|
186
|
+
secretariatAdapters(),
|
|
187
|
+
env.principalAuthority,
|
|
188
|
+
io,
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const turnRequest = buildSecretariatTurnRequest(admitted, {
|
|
194
|
+
packageRoot: env.packageRoot,
|
|
195
|
+
home: env.home,
|
|
196
|
+
agentDir: env.agentDir,
|
|
197
|
+
...(env.model === undefined ? {} : { model: env.model }),
|
|
198
|
+
...pickEngineAxis(env),
|
|
199
|
+
...(env.timeoutMs === undefined ? {} : { timeoutMs: env.timeoutMs }),
|
|
200
|
+
...(env.correlationId === undefined || env.correlationId.trim() === ""
|
|
201
|
+
? {}
|
|
202
|
+
: { correlationId: env.correlationId }),
|
|
203
|
+
continuation: {
|
|
204
|
+
kind: "initial",
|
|
205
|
+
prompt: buildSecretariatTransportPrompt(
|
|
206
|
+
admitted,
|
|
207
|
+
engineSessionMaterialFromOptions({
|
|
208
|
+
...pickEngineAxis(env),
|
|
209
|
+
packageRoot: env.packageRoot,
|
|
210
|
+
}),
|
|
211
|
+
),
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
return await runPostAdmissionOneShot({
|
|
216
|
+
admitted,
|
|
217
|
+
env,
|
|
218
|
+
io,
|
|
219
|
+
request: turnRequest,
|
|
220
|
+
adapters: secretariatAdapters(),
|
|
221
|
+
...(env.engine === undefined ? {} : { effectiveEngine: env.engine }),
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function secretariatAdapters() {
|
|
226
|
+
return {
|
|
227
|
+
trySettle: (
|
|
228
|
+
admitted: AdmittedSecretariatInvocation,
|
|
229
|
+
authority: DurablePrincipalAuthority,
|
|
230
|
+
scope?: { readonly courtAttemptId?: string },
|
|
231
|
+
) => trySettleSecretariatTerminalResult(admitted, authority, scope),
|
|
232
|
+
shouldPresentSettled: () => true,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Resume a previously admitted Secretariat run (#599).
|
|
238
|
+
*/
|
|
239
|
+
export async function runPublicSecretariatResume(
|
|
240
|
+
request: PublicResumeRequest,
|
|
241
|
+
env: SecretariatRunEnv,
|
|
242
|
+
io: CliIo,
|
|
243
|
+
): Promise<{
|
|
244
|
+
exitCode: number;
|
|
245
|
+
admitted?: AdmittedSecretariatInvocation;
|
|
246
|
+
terminal?: TerminalResult;
|
|
247
|
+
}> {
|
|
248
|
+
return await runPostAdmissionSeatResume({
|
|
249
|
+
request,
|
|
250
|
+
env,
|
|
251
|
+
io,
|
|
252
|
+
load: (effective) =>
|
|
253
|
+
loadResumableSecretariatRun(
|
|
254
|
+
env.home,
|
|
255
|
+
effective.runId,
|
|
256
|
+
env.principalAuthority,
|
|
257
|
+
),
|
|
258
|
+
buildTurnRequest: (admitted, effective) =>
|
|
259
|
+
buildSecretariatTurnRequest(
|
|
260
|
+
admitted,
|
|
261
|
+
resumeTurnRequestProjectionOptions(admitted, effective, env),
|
|
262
|
+
),
|
|
263
|
+
adapters: secretariatAdapters(),
|
|
264
|
+
...(env.engine === undefined ? {} : { effectiveEngine: env.engine }),
|
|
265
|
+
});
|
|
266
|
+
}
|
|
@@ -94,6 +94,9 @@ import {
|
|
|
94
94
|
import {
|
|
95
95
|
DIARIST_OUTPUT_TOOL_NAME,
|
|
96
96
|
} from "../diarist-contracts.ts";
|
|
97
|
+
import {
|
|
98
|
+
SECRETARIAT_OUTPUT_TOOL_NAME,
|
|
99
|
+
} from "../secretariat-contracts.ts";
|
|
97
100
|
import {
|
|
98
101
|
INSPECTOR_OUTPUT_TOOL_NAME,
|
|
99
102
|
} from "../inspector-contracts.ts";
|
|
@@ -146,6 +149,7 @@ import {
|
|
|
146
149
|
type AdmittedMergerInvocation,
|
|
147
150
|
type AdmittedCountersignInvocation,
|
|
148
151
|
type AdmittedDiaristInvocation,
|
|
152
|
+
type AdmittedSecretariatInvocation,
|
|
149
153
|
type AdmittedGleanerLeftInvocation,
|
|
150
154
|
type AdmittedInspectorInvocation,
|
|
151
155
|
type AdmittedGatekeeperInvocation,
|
|
@@ -1086,38 +1090,7 @@ async function loadBoundAuditorVolumes(
|
|
|
1086
1090
|
}
|
|
1087
1091
|
const parentId = parentEntries.find((entry) => entry.type === "session")?.id;
|
|
1088
1092
|
if (parentId === undefined) return undefined;
|
|
1089
|
-
const isResumeEnvelopeBytes = (value: unknown): boolean => {
|
|
1090
|
-
if (typeof value !== "string") return false;
|
|
1091
|
-
if (value.length === 0) return true;
|
|
1092
|
-
const nl = value.indexOf("\n");
|
|
1093
|
-
const firstLine = nl === -1 ? value : value.slice(0, nl);
|
|
1094
|
-
const body = firstLine === "" && nl !== -1 ? value.slice(nl + 1) : value;
|
|
1095
|
-
return body.startsWith("本次配置的劳务引擎及其手册:") || body.startsWith("- engine:");
|
|
1096
|
-
};
|
|
1097
|
-
const isResumeEnvelope = (msg: unknown): boolean => {
|
|
1098
|
-
if (!isRecord(msg) || msg.role !== "user") return false;
|
|
1099
|
-
const text = typeof msg.text === "string" ? msg.text : typeof (msg as { content?: unknown }).content === "string" ? (msg as { content: string }).content : undefined;
|
|
1100
|
-
if (isResumeEnvelopeBytes(text)) return true;
|
|
1101
|
-
const content = (msg as { content?: unknown }).content;
|
|
1102
|
-
if (Array.isArray(content)) {
|
|
1103
|
-
return content.some((p) => isRecord(p) && (isResumeEnvelopeBytes(p.text) || isResumeEnvelopeBytes(p.content)));
|
|
1104
|
-
}
|
|
1105
|
-
return false;
|
|
1106
|
-
};
|
|
1107
|
-
let latestParentUserIndex = -1;
|
|
1108
|
-
for (let i = parentEntries.length - 1; i >= 0; i -= 1) {
|
|
1109
|
-
const entry = parentEntries[i];
|
|
1110
|
-
if (entry?.type !== "message" || entry.message?.role !== "user") continue;
|
|
1111
|
-
if (isResumeEnvelope(entry.message)) continue;
|
|
1112
|
-
latestParentUserIndex = i;
|
|
1113
|
-
break;
|
|
1114
|
-
}
|
|
1115
1093
|
const childDirectories = [join(dirname(sessionFile), "auditor-roles")];
|
|
1116
|
-
// Auto-resume seam (owner A): stale check must ignore resume envelope and
|
|
1117
|
-
// prioritize retention. Previous `attemptEntryIndex < latest` discarded the
|
|
1118
|
-
// first attempt's child after resume advanced latest, losing retentionFailure
|
|
1119
|
-
// when retry had no compliance entry. Fix: ignore envelope for staleness and
|
|
1120
|
-
// prefer any valid compliance failure before falling back to primary.
|
|
1121
1094
|
const valid: BoundAuditorVolume[] = [];
|
|
1122
1095
|
let sawAnyDirectory = false;
|
|
1123
1096
|
for (const childDirectory of childDirectories) {
|
|
@@ -1166,10 +1139,6 @@ async function loadBoundAuditorVolumes(
|
|
|
1166
1139
|
typeof bindingParent?.attemptEntryId === "string"
|
|
1167
1140
|
? bindingParent.attemptEntryId
|
|
1168
1141
|
: undefined;
|
|
1169
|
-
const attemptEntryIndex =
|
|
1170
|
-
attemptEntryId === undefined
|
|
1171
|
-
? -1
|
|
1172
|
-
: parentEntries.findIndex((entry) => entry.id === attemptEntryId);
|
|
1173
1142
|
const boundSessionFile =
|
|
1174
1143
|
typeof bindingParent?.sessionFile === "string"
|
|
1175
1144
|
? bindingParent.sessionFile
|
|
@@ -1177,12 +1146,7 @@ async function loadBoundAuditorVolumes(
|
|
|
1177
1146
|
? header.parentSession
|
|
1178
1147
|
: undefined;
|
|
1179
1148
|
if (boundSessionFile !== sessionFile) continue;
|
|
1180
|
-
if (
|
|
1181
|
-
bindingParent !== undefined &&
|
|
1182
|
-
(bindingParent.sessionId !== parentId || attemptEntryIndex < latestParentUserIndex)
|
|
1183
|
-
) {
|
|
1184
|
-
continue;
|
|
1185
|
-
}
|
|
1149
|
+
if (bindingParent !== undefined && bindingParent.sessionId !== parentId) continue;
|
|
1186
1150
|
if (bindingParent === undefined && header.parentSession !== sessionFile) continue;
|
|
1187
1151
|
valid.push({
|
|
1188
1152
|
entries: entries.slice(start, end),
|
|
@@ -1190,8 +1154,8 @@ async function loadBoundAuditorVolumes(
|
|
|
1190
1154
|
sessionFile,
|
|
1191
1155
|
...(attemptEntryId === undefined ? {} : { attemptEntryId }),
|
|
1192
1156
|
});
|
|
1193
|
-
// Keep every
|
|
1194
|
-
//
|
|
1157
|
+
// Keep every interval bound to this parent. Auditor payload is relayed as
|
|
1158
|
+
// recorded; code does not expire it from later user-message shape (#858).
|
|
1195
1159
|
}
|
|
1196
1160
|
}
|
|
1197
1161
|
}
|
|
@@ -1254,16 +1218,6 @@ function providerStopFallbackFromAuditorVolumes(
|
|
|
1254
1218
|
return undefined;
|
|
1255
1219
|
}
|
|
1256
1220
|
|
|
1257
|
-
/** Recover a provider stop from the auditor child bound to the current parent attempt. */
|
|
1258
|
-
export async function readBoundAuditorKnownFailure(
|
|
1259
|
-
sessionFile: string,
|
|
1260
|
-
): Promise<RoleTurnKnownFailure | undefined> {
|
|
1261
|
-
const volumes = await loadBoundAuditorVolumes(sessionFile);
|
|
1262
|
-
if (volumes === undefined) return undefined;
|
|
1263
|
-
return complianceFailureFromAuditorVolumes(volumes)
|
|
1264
|
-
?? providerStopFallbackFromAuditorVolumes(volumes);
|
|
1265
|
-
}
|
|
1266
|
-
|
|
1267
1221
|
/** Strong auditor tier only — retained compliance-failure entries, no provider-stop fallback. */
|
|
1268
1222
|
async function readBoundAuditorComplianceFailure(
|
|
1269
1223
|
sessionFile: string,
|
|
@@ -3193,7 +3147,8 @@ type SeatAcceptedSettlementSpec = {
|
|
|
3193
3147
|
| "gatekeeper"
|
|
3194
3148
|
| "navigator"
|
|
3195
3149
|
| "auditor"
|
|
3196
|
-
| "diarist"
|
|
3150
|
+
| "diarist"
|
|
3151
|
+
| "secretariat";
|
|
3197
3152
|
readonly toolName: string;
|
|
3198
3153
|
};
|
|
3199
3154
|
|
|
@@ -3217,7 +3172,8 @@ async function settleLawfulSeatAcceptedTerminalResult(
|
|
|
3217
3172
|
| AdmittedGatekeeperInvocation
|
|
3218
3173
|
| AdmittedNavigatorInvocation
|
|
3219
3174
|
| import("./invocation.ts").AdmittedAuditorInvocation
|
|
3220
|
-
| AdmittedDiaristInvocation
|
|
3175
|
+
| AdmittedDiaristInvocation
|
|
3176
|
+
| AdmittedSecretariatInvocation,
|
|
3221
3177
|
authority: DurablePrincipalAuthority,
|
|
3222
3178
|
spec: SeatAcceptedSettlementSpec,
|
|
3223
3179
|
scope?: SettlementCourtScope,
|
|
@@ -3434,6 +3390,26 @@ export async function trySettleDiaristTerminalResult(
|
|
|
3434
3390
|
return settleLawfulDiaristTerminalResult(admitted, authority, scope);
|
|
3435
3391
|
}
|
|
3436
3392
|
|
|
3393
|
+
async function settleLawfulSecretariatTerminalResult(
|
|
3394
|
+
admitted: AdmittedSecretariatInvocation,
|
|
3395
|
+
authority: DurablePrincipalAuthority,
|
|
3396
|
+
scope?: SettlementCourtScope,
|
|
3397
|
+
): Promise<TerminalResult | undefined> {
|
|
3398
|
+
return settleLawfulSeatAcceptedTerminalResult(admitted, authority, {
|
|
3399
|
+
role: "secretariat",
|
|
3400
|
+
toolName: SECRETARIAT_OUTPUT_TOOL_NAME,
|
|
3401
|
+
}, scope);
|
|
3402
|
+
}
|
|
3403
|
+
|
|
3404
|
+
/** Try to settle a lawful Secretariat Terminal; undefined only for genuine absence. */
|
|
3405
|
+
export async function trySettleSecretariatTerminalResult(
|
|
3406
|
+
admitted: AdmittedSecretariatInvocation,
|
|
3407
|
+
authority: DurablePrincipalAuthority,
|
|
3408
|
+
scope?: SettlementCourtScope,
|
|
3409
|
+
): Promise<TerminalResult | undefined> {
|
|
3410
|
+
return settleLawfulSecretariatTerminalResult(admitted, authority, scope);
|
|
3411
|
+
}
|
|
3412
|
+
|
|
3437
3413
|
/** Lawful Inspector accepted outcome (pass/bounce/escalate). */
|
|
3438
3414
|
export type LawfulInspectorRoleOutcome = Extract<TerminalRoleOutcome, { kind: "accepted" }>;
|
|
3439
3415
|
|
|
@@ -32,7 +32,8 @@ export type PublicSummonRole =
|
|
|
32
32
|
| "gatekeeper"
|
|
33
33
|
| "judge"
|
|
34
34
|
| "doctor"
|
|
35
|
-
| "diarist"
|
|
35
|
+
| "diarist"
|
|
36
|
+
| "countersign";
|
|
36
37
|
|
|
37
38
|
export type PublicSummonRequest = {
|
|
38
39
|
readonly role: PublicSummonRole;
|
|
@@ -82,6 +83,8 @@ export type PublicSummonRequest = {
|
|
|
82
83
|
readonly createRunId?: () => string;
|
|
83
84
|
/** Typed ticket number handoff for diarist child run (#840). */
|
|
84
85
|
readonly boundTicketNumber?: number;
|
|
86
|
+
/** Caller correlation id for nested leg ledger (ADR 0010 / #924). */
|
|
87
|
+
readonly correlationId?: string;
|
|
85
88
|
};
|
|
86
89
|
|
|
87
90
|
export type PublicSummonResult = {
|
|
@@ -339,6 +342,11 @@ export async function summonPublicRole(
|
|
|
339
342
|
env: {
|
|
340
343
|
...built.env,
|
|
341
344
|
stationChild: true,
|
|
345
|
+
// Forward composition-root adapters so nested court stations (e.g.
|
|
346
|
+
// countersign → diarist) select the same faux/production table (#924).
|
|
347
|
+
...(options.hostAdapters === undefined
|
|
348
|
+
? {}
|
|
349
|
+
: { hostAdapters: options.hostAdapters }),
|
|
342
350
|
...(config.autoResumeLimit === undefined
|
|
343
351
|
? {}
|
|
344
352
|
: { autoResumeLimit: config.autoResumeLimit }),
|
|
@@ -350,6 +358,9 @@ export async function summonPublicRole(
|
|
|
350
358
|
...(options.boundTicketNumber === undefined
|
|
351
359
|
? {}
|
|
352
360
|
: { boundTicketNumber: options.boundTicketNumber }),
|
|
361
|
+
...(options.correlationId === undefined || options.correlationId.trim() === ""
|
|
362
|
+
? {}
|
|
363
|
+
: { correlationId: options.correlationId }),
|
|
353
364
|
...(options.createRunId === undefined ? {} : { createRunId: options.createRunId }),
|
|
354
365
|
},
|
|
355
366
|
};
|
|
@@ -481,6 +492,17 @@ export async function summonPublicRole(
|
|
|
481
492
|
result = stepped.ok;
|
|
482
493
|
break;
|
|
483
494
|
}
|
|
495
|
+
case "countersign": {
|
|
496
|
+
const [{ runPublicCountersign }, { parseCountersignArgv }] = await Promise.all([
|
|
497
|
+
import("./public-cli/countersign-run.ts"),
|
|
498
|
+
import("./public-cli/invocation.ts"),
|
|
499
|
+
]);
|
|
500
|
+
const stepped = await runPrepared(parseCountersignArgv, (env, once) =>
|
|
501
|
+
runPublicCountersign(options.argv, env as never, io, once));
|
|
502
|
+
if ("fail" in stepped) return stepped.fail;
|
|
503
|
+
result = stepped.ok;
|
|
504
|
+
break;
|
|
505
|
+
}
|
|
484
506
|
}
|
|
485
507
|
|
|
486
508
|
const stderr = captured?.stderrText();
|
package/src/reviewer-role.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { RoleHost, HostContext, HostToolResult } from "./host-contracts.ts";
|
|
2
2
|
import { Type } from "typebox";
|
|
3
3
|
import { openToolObjectFromUnion } from "./open-tool-schema.ts";
|
|
4
|
-
import {
|
|
4
|
+
import { withTerminatingOutputDeclarations } from "./package-contracts/terminating-infrastructure.ts";
|
|
5
5
|
|
|
6
6
|
import type { AnyCanonicalSkillBinding, CanonicalSkillBinding } from "./canonical-skill-binding.ts";
|
|
7
7
|
export type { CanonicalSkillBinding };
|
|
@@ -43,7 +43,7 @@ const reviewerOutputVariants = Type.Union([
|
|
|
43
43
|
amendments: Type.Optional(reviewerAmendmentsSchema),
|
|
44
44
|
}, { additionalProperties: false }),
|
|
45
45
|
]);
|
|
46
|
-
export const reviewerOutputSchema =
|
|
46
|
+
export const reviewerOutputSchema = withTerminatingOutputDeclarations(
|
|
47
47
|
openToolObjectFromUnion(reviewerOutputVariants),
|
|
48
48
|
);
|
|
49
49
|
export type ReviewerRoleDependencies = {
|
|
@@ -47,6 +47,7 @@ export function createRoleRuntimeDependencies(packageRoot: string): RoleRuntimeD
|
|
|
47
47
|
loadCountersignSoul: () => loadMainRoleSessionMaterials("countersign"),
|
|
48
48
|
loadGleanerLeftSoul: () => loadMainRoleSessionMaterials("gleaner-left"),
|
|
49
49
|
loadDiaristSoul: () => loadMainRoleSessionMaterials("diarist"),
|
|
50
|
+
loadSecretariatSoul: () => loadMainRoleSessionMaterials("secretariat"),
|
|
50
51
|
loadNotarySourceRun: loadNotarySourceRunLocator,
|
|
51
52
|
loadMergerSoul: () => loadMainRoleSessionMaterials("merger"),
|
|
52
53
|
loadMergerInput: async (path) => JSON.parse(await readFile(path, "utf8")),
|