@akagilnc/pi-workflow-roles 0.1.2296 → 0.1.2306
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 +7 -0
- package/README.zh-CN.md +7 -0
- package/dist/notary-contracts.js +96 -0
- package/dist/package-contracts/terminating-tools.js +10 -2
- package/dist/packaged-role-registry.js +3 -1
- package/dist/public-cli/main.js +3344 -2778
- package/extensions/role-runtime.ts +11 -1
- package/package.json +1 -1
- package/souls/judge-output-guide.md +4 -1
- package/src/notary-contracts.ts +134 -0
- package/src/notary-role.ts +148 -0
- package/src/notary-source-run.ts +168 -0
- package/src/package-contracts/terminating-tools.ts +13 -2
- package/src/packaged-role-registry.ts +2 -0
- package/src/public-cli/cli.ts +51 -0
- package/src/public-cli/doctor-run.ts +18 -250
- package/src/public-cli/invocation.ts +170 -0
- package/src/public-cli/notary-run.ts +117 -0
- package/src/public-cli/one-shot-dispatch.ts +300 -0
- package/src/public-cli/option-definitions.ts +29 -0
- package/src/public-cli/registry.ts +4 -0
- package/src/public-cli/run-lifecycle.ts +5 -2
- package/src/public-cli/settlement.ts +101 -0
- package/src/public-cli/terminal.ts +4 -3
- package/src/role-runtime.ts +16 -0
- package/src/session-opening-materials.ts +1 -0
|
@@ -1,19 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Public Doctor Role run: admit Issue → retained case via #78 →
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Public Doctor Role run: admit Issue → retained case via #78 → shared one-shot
|
|
3
|
+
* dispatch → settle Terminal result (#113). Lifecycle is the shared
|
|
4
|
+
* Doctor-isomorphic seam; this module keeps only Doctor adapters.
|
|
5
5
|
*/
|
|
6
|
-
import { writeFile } from "node:fs/promises";
|
|
7
|
-
import { join } from "node:path";
|
|
8
|
-
|
|
9
|
-
import { applyEngineChildEnv } from "../engine-detour.ts";
|
|
10
6
|
import { engineSessionMaterialFromOptions } from "../package-resources/engine-material.ts";
|
|
11
|
-
import {
|
|
12
|
-
runExplicitInternalActivation,
|
|
13
|
-
type ExplicitInternalKnownFailure,
|
|
14
|
-
type ExplicitInternalPiRunner,
|
|
15
|
-
type ExplicitInternalPiResult,
|
|
16
|
-
} from "./explicit-internal.ts";
|
|
17
7
|
import { CliUsageError } from "./cli-errors.ts";
|
|
18
8
|
import {
|
|
19
9
|
admitDoctorInvocation,
|
|
@@ -23,59 +13,28 @@ import {
|
|
|
23
13
|
} from "./invocation.ts";
|
|
24
14
|
import {
|
|
25
15
|
buildSeatModelCliArgs,
|
|
26
|
-
type CredentialProviders,
|
|
27
16
|
type SeatModelConfig,
|
|
28
17
|
} from "./config.ts";
|
|
29
18
|
import {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
} from "./
|
|
19
|
+
runAdmittedOneShotRole,
|
|
20
|
+
type OneShotRunEnv,
|
|
21
|
+
} from "./one-shot-dispatch.ts";
|
|
33
22
|
import {
|
|
34
|
-
acquireRunWriterLease,
|
|
35
|
-
clearTypedProviderHttpObservation,
|
|
36
|
-
markRunAdmitted,
|
|
37
|
-
markRunRunning,
|
|
38
|
-
markRunTerminal,
|
|
39
|
-
RunWriterLeaseHeldError,
|
|
40
|
-
type RunWriterLease,
|
|
41
|
-
} from "./run-lifecycle.ts";
|
|
42
|
-
import {
|
|
43
|
-
classifyPostAdmissionFailure,
|
|
44
|
-
exitCodeForTerminalOutcome,
|
|
45
|
-
formatTerminalResult,
|
|
46
|
-
inspectJudgeSession,
|
|
47
|
-
isLawfulTypedTerminalOutcome,
|
|
48
|
-
presentFailureTerminal,
|
|
49
23
|
presentStructuralRejection,
|
|
50
|
-
resolveAuditedRunnerKnownFailure,
|
|
51
|
-
explicitInternalKnownFailureClassificationInput,
|
|
52
|
-
settleFailureTerminalResult,
|
|
53
|
-
trySettleDoctorTerminalResult,
|
|
54
24
|
trySettleComplianceAuditIncompleteTerminalResult,
|
|
25
|
+
trySettleDoctorTerminalResult,
|
|
55
26
|
} from "./settlement.ts";
|
|
56
27
|
import type { CliIo } from "./cli-io.ts";
|
|
57
|
-
import
|
|
58
|
-
|
|
59
|
-
TerminalResult,
|
|
28
|
+
import {
|
|
29
|
+
isLawfulTypedTerminalOutcome,
|
|
30
|
+
type TerminalResult,
|
|
60
31
|
} from "./terminal.ts";
|
|
61
32
|
|
|
62
|
-
export type DoctorRunEnv = {
|
|
63
|
-
home: string;
|
|
64
|
-
agentDir: string;
|
|
65
|
-
packageRoot: string;
|
|
66
|
-
cwd: string;
|
|
67
|
-
correlationId?: string;
|
|
68
|
-
piRunner?: ExplicitInternalPiRunner;
|
|
69
|
-
model?: SeatModelConfig;
|
|
70
|
-
/** Optional labor engine name (config→activation; session material + env signal). */
|
|
71
|
-
engine?: string;
|
|
72
|
-
credentials?: CredentialProviders;
|
|
33
|
+
export type DoctorRunEnv = OneShotRunEnv & {
|
|
73
34
|
createRunId?: () => string;
|
|
74
35
|
extraPiArgs?: readonly string[];
|
|
75
|
-
timeoutMs?: number;
|
|
76
36
|
};
|
|
77
37
|
|
|
78
|
-
|
|
79
38
|
/**
|
|
80
39
|
* Build Internal activation extra-args for an admitted Doctor run.
|
|
81
40
|
* Always --no-skills (Doctor forbids every Skill). Session under #78 book.
|
|
@@ -115,189 +74,6 @@ export function buildDoctorActivationExtraArgs(
|
|
|
115
74
|
];
|
|
116
75
|
}
|
|
117
76
|
|
|
118
|
-
async function presentControlledFailure(
|
|
119
|
-
admitted: AdmittedDoctorInvocation,
|
|
120
|
-
failureInput: {
|
|
121
|
-
timedOut: boolean;
|
|
122
|
-
code: number | null;
|
|
123
|
-
stderr: string;
|
|
124
|
-
thrown?: unknown;
|
|
125
|
-
knownFailure?: ExplicitInternalKnownFailure;
|
|
126
|
-
},
|
|
127
|
-
io: CliIo,
|
|
128
|
-
): Promise<{
|
|
129
|
-
exitCode: number;
|
|
130
|
-
admitted: AdmittedDoctorInvocation;
|
|
131
|
-
terminal: TerminalResult;
|
|
132
|
-
}> {
|
|
133
|
-
const hasThrown = Object.hasOwn(failureInput, "thrown");
|
|
134
|
-
const session =
|
|
135
|
-
!hasThrown &&
|
|
136
|
-
!failureInput.timedOut &&
|
|
137
|
-
failureInput.knownFailure === undefined
|
|
138
|
-
? await inspectJudgeSession(admitted.sessionFile)
|
|
139
|
-
: undefined;
|
|
140
|
-
const failure = classifyPostAdmissionFailure({
|
|
141
|
-
timedOut: failureInput.timedOut,
|
|
142
|
-
code: failureInput.code,
|
|
143
|
-
stderr: failureInput.stderr,
|
|
144
|
-
...(hasThrown ? { thrown: failureInput.thrown } : {}),
|
|
145
|
-
...explicitInternalKnownFailureClassificationInput(failureInput.knownFailure),
|
|
146
|
-
...(session === undefined ? {} : { session }),
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
// Doctor does not support resume — always terminal.
|
|
150
|
-
await markRunTerminal(admitted.runDirectory).catch(() => undefined);
|
|
151
|
-
|
|
152
|
-
const terminal = await settleFailureTerminalResult(admitted, failure);
|
|
153
|
-
presentFailureTerminal(terminal, io);
|
|
154
|
-
return {
|
|
155
|
-
exitCode: exitCodeForTerminalOutcome(terminal.roleOutcome),
|
|
156
|
-
admitted,
|
|
157
|
-
terminal,
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
async function dispatchAdmittedDoctor(input: {
|
|
162
|
-
admitted: AdmittedDoctorInvocation;
|
|
163
|
-
env: DoctorRunEnv;
|
|
164
|
-
io: CliIo;
|
|
165
|
-
extraArgs: string[];
|
|
166
|
-
lease: RunWriterLease;
|
|
167
|
-
effectiveEngine?: string;
|
|
168
|
-
}): Promise<{
|
|
169
|
-
exitCode: number;
|
|
170
|
-
admitted: AdmittedDoctorInvocation;
|
|
171
|
-
terminal?: TerminalResult;
|
|
172
|
-
}> {
|
|
173
|
-
const { admitted, env, io, extraArgs, lease, effectiveEngine } = input;
|
|
174
|
-
try {
|
|
175
|
-
const missingCredential = missingCredentialPreDispatchFailure(
|
|
176
|
-
env.model,
|
|
177
|
-
env.credentials,
|
|
178
|
-
);
|
|
179
|
-
if (missingCredential !== undefined) {
|
|
180
|
-
return await presentControlledFailure(
|
|
181
|
-
admitted,
|
|
182
|
-
missingCredential,
|
|
183
|
-
io,
|
|
184
|
-
);
|
|
185
|
-
}
|
|
186
|
-
await markRunRunning(admitted.runDirectory, env.model, effectiveEngine);
|
|
187
|
-
await clearTypedProviderHttpObservation(admitted.runDirectory);
|
|
188
|
-
|
|
189
|
-
const childEnv: NodeJS.ProcessEnv = {
|
|
190
|
-
...process.env,
|
|
191
|
-
HOME: env.home,
|
|
192
|
-
PI_CODING_AGENT_DIR: env.agentDir,
|
|
193
|
-
AK_ROLE_RUN_DIR: admitted.runDirectory,
|
|
194
|
-
};
|
|
195
|
-
applyEngineChildEnv(childEnv, env.engine);
|
|
196
|
-
if (env.correlationId !== undefined && env.correlationId.trim() !== "") {
|
|
197
|
-
childEnv.AK_CORRELATION_ID = env.correlationId;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
let result: ExplicitInternalPiResult;
|
|
201
|
-
try {
|
|
202
|
-
result = await runExplicitInternalActivation({
|
|
203
|
-
packageRoot: env.packageRoot,
|
|
204
|
-
extraArgs,
|
|
205
|
-
cwd: admitted.projectRoot,
|
|
206
|
-
home: env.home,
|
|
207
|
-
agentDir: env.agentDir,
|
|
208
|
-
env: childEnv,
|
|
209
|
-
timeoutMs: env.timeoutMs,
|
|
210
|
-
...(env.piRunner === undefined ? {} : { runner: env.piRunner }),
|
|
211
|
-
});
|
|
212
|
-
} catch (error) {
|
|
213
|
-
return await presentControlledFailure(
|
|
214
|
-
admitted,
|
|
215
|
-
{
|
|
216
|
-
timedOut: false,
|
|
217
|
-
code: null,
|
|
218
|
-
stderr: "",
|
|
219
|
-
thrown: error,
|
|
220
|
-
},
|
|
221
|
-
io,
|
|
222
|
-
);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
try {
|
|
226
|
-
await writeFile(
|
|
227
|
-
join(admitted.runDirectory, "stderr.log"),
|
|
228
|
-
result.stderr,
|
|
229
|
-
"utf8",
|
|
230
|
-
);
|
|
231
|
-
} catch {
|
|
232
|
-
// continue to lawful / controlled-failure settlement
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
let lawful: TerminalResult | undefined;
|
|
236
|
-
try {
|
|
237
|
-
lawful = await trySettleDoctorTerminalResult(admitted);
|
|
238
|
-
} catch (error) {
|
|
239
|
-
return await presentControlledFailure(
|
|
240
|
-
admitted,
|
|
241
|
-
{
|
|
242
|
-
timedOut: false,
|
|
243
|
-
code: result.code,
|
|
244
|
-
stderr: result.stderr,
|
|
245
|
-
thrown: error,
|
|
246
|
-
},
|
|
247
|
-
io,
|
|
248
|
-
);
|
|
249
|
-
}
|
|
250
|
-
if (lawful !== undefined && isLawfulTypedTerminalOutcome(lawful.roleOutcome)) {
|
|
251
|
-
await markRunTerminal(admitted.runDirectory).catch(() => undefined);
|
|
252
|
-
io.stdout(formatTerminalResult(lawful));
|
|
253
|
-
return {
|
|
254
|
-
exitCode: exitCodeForTerminalOutcome(lawful.roleOutcome),
|
|
255
|
-
admitted,
|
|
256
|
-
terminal: lawful,
|
|
257
|
-
};
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
const auditIncomplete = await trySettleComplianceAuditIncompleteTerminalResult(admitted);
|
|
261
|
-
if (auditIncomplete !== undefined) {
|
|
262
|
-
await markRunTerminal(admitted.runDirectory).catch(() => undefined);
|
|
263
|
-
if (auditIncomplete.roleOutcome.kind === "failure") {
|
|
264
|
-
presentFailureTerminal(auditIncomplete, io);
|
|
265
|
-
} else {
|
|
266
|
-
io.stdout(formatTerminalResult(auditIncomplete));
|
|
267
|
-
}
|
|
268
|
-
return {
|
|
269
|
-
exitCode: exitCodeForTerminalOutcome(auditIncomplete.roleOutcome),
|
|
270
|
-
admitted,
|
|
271
|
-
terminal: auditIncomplete,
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
const credentialFailure = postRunMissingCredentialFailure(
|
|
276
|
-
result,
|
|
277
|
-
env.model,
|
|
278
|
-
env.credentials,
|
|
279
|
-
);
|
|
280
|
-
const knownFailure = await resolveAuditedRunnerKnownFailure({
|
|
281
|
-
runner: result.knownFailure,
|
|
282
|
-
sessionFile: admitted.sessionFile,
|
|
283
|
-
credential: credentialFailure,
|
|
284
|
-
runDirectory: admitted.runDirectory,
|
|
285
|
-
});
|
|
286
|
-
return await presentControlledFailure(
|
|
287
|
-
admitted,
|
|
288
|
-
{
|
|
289
|
-
timedOut: result.timedOut,
|
|
290
|
-
code: result.code,
|
|
291
|
-
stderr: result.stderr,
|
|
292
|
-
...(knownFailure === undefined ? {} : { knownFailure }),
|
|
293
|
-
},
|
|
294
|
-
io,
|
|
295
|
-
);
|
|
296
|
-
} finally {
|
|
297
|
-
await lease.release();
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
|
|
301
77
|
export async function runPublicDoctor(
|
|
302
78
|
argv: readonly string[],
|
|
303
79
|
env: DoctorRunEnv,
|
|
@@ -330,19 +106,6 @@ export async function runPublicDoctor(
|
|
|
330
106
|
throw error;
|
|
331
107
|
}
|
|
332
108
|
|
|
333
|
-
await markRunAdmitted(admitted);
|
|
334
|
-
|
|
335
|
-
let lease: RunWriterLease;
|
|
336
|
-
try {
|
|
337
|
-
lease = await acquireRunWriterLease(admitted.runDirectory, (diagnostic) => io.stderr(diagnostic));
|
|
338
|
-
} catch (error) {
|
|
339
|
-
if (error instanceof RunWriterLeaseHeldError) {
|
|
340
|
-
presentStructuralRejection(error, io);
|
|
341
|
-
return { exitCode: 2 };
|
|
342
|
-
}
|
|
343
|
-
throw error;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
109
|
const extraArgs = buildDoctorActivationExtraArgs(admitted, {
|
|
347
110
|
packageRoot: env.packageRoot,
|
|
348
111
|
...(env.model === undefined ? {} : { model: env.model }),
|
|
@@ -350,12 +113,17 @@ export async function runPublicDoctor(
|
|
|
350
113
|
...(env.extraPiArgs === undefined ? {} : { extraPiArgs: env.extraPiArgs }),
|
|
351
114
|
});
|
|
352
115
|
|
|
353
|
-
return await
|
|
116
|
+
return await runAdmittedOneShotRole({
|
|
354
117
|
admitted,
|
|
355
118
|
env,
|
|
356
119
|
io,
|
|
357
120
|
extraArgs,
|
|
358
|
-
|
|
121
|
+
adapters: {
|
|
122
|
+
trySettle: trySettleDoctorTerminalResult,
|
|
123
|
+
shouldPresentSettled: (terminal) =>
|
|
124
|
+
isLawfulTypedTerminalOutcome(terminal.roleOutcome),
|
|
125
|
+
trySettleSecondary: trySettleComplianceAuditIncompleteTerminalResult,
|
|
126
|
+
},
|
|
359
127
|
...(env.engine === undefined ? {} : { effectiveEngine: env.engine }),
|
|
360
128
|
});
|
|
361
129
|
}
|
|
@@ -47,6 +47,14 @@ import {
|
|
|
47
47
|
} from "../merger-contracts.ts";
|
|
48
48
|
import { sha256Hex } from "../sha256.ts";
|
|
49
49
|
import { uuidv7 } from "../uuidv7.ts";
|
|
50
|
+
import {
|
|
51
|
+
NOTARY_FIXED_KICKOFF,
|
|
52
|
+
type NotarySourceRunLocator,
|
|
53
|
+
} from "../notary-contracts.ts";
|
|
54
|
+
import {
|
|
55
|
+
NotarySourceRunError,
|
|
56
|
+
resolveNotarySourceRunLocator,
|
|
57
|
+
} from "../notary-source-run.ts";
|
|
50
58
|
import {
|
|
51
59
|
appendEngineSessionMaterial,
|
|
52
60
|
type EngineSessionMaterial,
|
|
@@ -143,6 +151,14 @@ export type AdmittedDoctorInvocation = AdmittedRoleInvocationBase & {
|
|
|
143
151
|
readonly caseIdentity: DoctorCaseIdentity;
|
|
144
152
|
};
|
|
145
153
|
|
|
154
|
+
export type AdmittedNotaryInvocation = AdmittedRoleInvocationBase & {
|
|
155
|
+
readonly role: "notary";
|
|
156
|
+
/** Absolute source run directory passed to internal --ak-notary-source-run. */
|
|
157
|
+
readonly sourceRunPath: string;
|
|
158
|
+
/** Typed locator identity bound at admission (self-fetch target). */
|
|
159
|
+
readonly sourceRun: NotarySourceRunLocator;
|
|
160
|
+
};
|
|
161
|
+
|
|
146
162
|
export type AdmittedReviewerInvocation = AdmittedRoleInvocationBase & {
|
|
147
163
|
readonly role: "reviewer";
|
|
148
164
|
/** Required fixed base revision for the pinned review target (ADR 0037). */
|
|
@@ -177,6 +193,7 @@ export type AdmittedRoleInvocation =
|
|
|
177
193
|
| AdmittedFixerInvocation
|
|
178
194
|
| AdmittedCollectorInvocation
|
|
179
195
|
| AdmittedDoctorInvocation
|
|
196
|
+
| AdmittedNotaryInvocation
|
|
180
197
|
| AdmittedReviewerInvocation
|
|
181
198
|
| AdmittedMergerInvocation;
|
|
182
199
|
|
|
@@ -1742,6 +1759,159 @@ export function buildDoctorTransportPrompt(
|
|
|
1742
1759
|
return appendEngineSessionMaterial(lines, engineMaterial).join("\n");
|
|
1743
1760
|
}
|
|
1744
1761
|
|
|
1762
|
+
export type ParseNotaryArgvResult = {
|
|
1763
|
+
readonly sourceRun: string;
|
|
1764
|
+
readonly project?: string;
|
|
1765
|
+
};
|
|
1766
|
+
|
|
1767
|
+
/**
|
|
1768
|
+
* Parse Notary-specific argv after the `notary` token.
|
|
1769
|
+
* Input contract = zero prompt, zero attachment projection (#448 / #276).
|
|
1770
|
+
*/
|
|
1771
|
+
export function parseNotaryArgv(args: readonly string[]): ParseNotaryArgvResult {
|
|
1772
|
+
let project: string | undefined;
|
|
1773
|
+
let sourceRun: string | undefined;
|
|
1774
|
+
const tokens = [...args];
|
|
1775
|
+
const definitions = roleOptions("notary");
|
|
1776
|
+
const options = createTypedOptionConsumer(definitions);
|
|
1777
|
+
|
|
1778
|
+
while (tokens.length > 0) {
|
|
1779
|
+
if (tokens[0] === "--") {
|
|
1780
|
+
tokens.shift();
|
|
1781
|
+
if (tokens.length > 0) {
|
|
1782
|
+
throw new CliUsageError(
|
|
1783
|
+
"notary rejects caller prompt/instruction; only --source-run locator is admitted",
|
|
1784
|
+
);
|
|
1785
|
+
}
|
|
1786
|
+
break;
|
|
1787
|
+
}
|
|
1788
|
+
const taken = options.takeDashed(tokens);
|
|
1789
|
+
if (taken !== undefined) {
|
|
1790
|
+
if (taken.def.id === "project") {
|
|
1791
|
+
project = requireOptionPath(taken.def.canonical, taken.value);
|
|
1792
|
+
continue;
|
|
1793
|
+
}
|
|
1794
|
+
if (taken.def.id === "source-run") {
|
|
1795
|
+
if (taken.value === undefined || taken.value.trim() === "") {
|
|
1796
|
+
throw new CliUsageError("notary --source-run requires a run locator");
|
|
1797
|
+
}
|
|
1798
|
+
sourceRun = taken.value;
|
|
1799
|
+
continue;
|
|
1800
|
+
}
|
|
1801
|
+
throw new CliUsageError(`unknown notary option: ${taken.def.canonical}`);
|
|
1802
|
+
}
|
|
1803
|
+
const token = tokens.shift()!;
|
|
1804
|
+
if (token.startsWith("-") && token !== "-") {
|
|
1805
|
+
throw new CliUsageError(`unknown notary option: ${token}`);
|
|
1806
|
+
}
|
|
1807
|
+
throw new CliUsageError(
|
|
1808
|
+
"notary rejects caller prompt/instruction; only --source-run locator is admitted",
|
|
1809
|
+
);
|
|
1810
|
+
}
|
|
1811
|
+
|
|
1812
|
+
options.assertRequired();
|
|
1813
|
+
if (sourceRun === undefined || sourceRun.trim() === "") {
|
|
1814
|
+
throw new CliUsageError("notary --source-run requires a run locator");
|
|
1815
|
+
}
|
|
1816
|
+
return {
|
|
1817
|
+
sourceRun,
|
|
1818
|
+
...(project === undefined ? {} : { project }),
|
|
1819
|
+
};
|
|
1820
|
+
}
|
|
1821
|
+
|
|
1822
|
+
export async function admitNotaryInvocation(options: {
|
|
1823
|
+
readonly home: string;
|
|
1824
|
+
readonly cwd: string;
|
|
1825
|
+
readonly sourceRun: string;
|
|
1826
|
+
readonly project?: string;
|
|
1827
|
+
readonly runs?: string;
|
|
1828
|
+
readonly createRunId?: () => string;
|
|
1829
|
+
readonly model?: InvocationEffectiveModel;
|
|
1830
|
+
readonly correlationId?: string;
|
|
1831
|
+
}): Promise<AdmittedNotaryInvocation> {
|
|
1832
|
+
if (options.project !== undefined) {
|
|
1833
|
+
requireOptionPath("--project", options.project);
|
|
1834
|
+
}
|
|
1835
|
+
const projectRoot = resolve(options.project ?? options.cwd);
|
|
1836
|
+
let sourceRun: NotarySourceRunLocator;
|
|
1837
|
+
try {
|
|
1838
|
+
sourceRun = await resolveNotarySourceRunLocator({
|
|
1839
|
+
projectRoot,
|
|
1840
|
+
sourceRun: options.sourceRun,
|
|
1841
|
+
home: options.home,
|
|
1842
|
+
});
|
|
1843
|
+
} catch (error) {
|
|
1844
|
+
if (error instanceof NotarySourceRunError) {
|
|
1845
|
+
throw new CliUsageError(error.message, { cause: error });
|
|
1846
|
+
}
|
|
1847
|
+
throw error;
|
|
1848
|
+
}
|
|
1849
|
+
|
|
1850
|
+
const runId = options.createRunId?.() ?? uuidv7();
|
|
1851
|
+
const { ledgerHome, bookKey, runDirectory, sessionDirectory, sessionFile } =
|
|
1852
|
+
roleRunSessionCoordinates({
|
|
1853
|
+
cwd: projectRoot,
|
|
1854
|
+
runId,
|
|
1855
|
+
role: "notary",
|
|
1856
|
+
home: options.home,
|
|
1857
|
+
});
|
|
1858
|
+
ensureRealDirectoryTree(ledgerHome, sessionDirectory);
|
|
1859
|
+
|
|
1860
|
+
const admitted = {
|
|
1861
|
+
role: "notary" as const,
|
|
1862
|
+
runId,
|
|
1863
|
+
bookKey,
|
|
1864
|
+
projectRoot,
|
|
1865
|
+
runDirectory,
|
|
1866
|
+
sessionDirectory,
|
|
1867
|
+
sessionFile,
|
|
1868
|
+
instruction: "",
|
|
1869
|
+
instructionEmpty: true,
|
|
1870
|
+
attachments: [] as const,
|
|
1871
|
+
sourceRunPath: sourceRun.runDirectory,
|
|
1872
|
+
sourceRun,
|
|
1873
|
+
...(options.correlationId === undefined
|
|
1874
|
+
? {}
|
|
1875
|
+
: { correlationId: options.correlationId }),
|
|
1876
|
+
};
|
|
1877
|
+
const admittedRequestPath = join(runDirectory, "admitted-request.json");
|
|
1878
|
+
await writeFile(
|
|
1879
|
+
admittedRequestPath,
|
|
1880
|
+
`${JSON.stringify(admitted, null, 2)}\n`,
|
|
1881
|
+
"utf8",
|
|
1882
|
+
);
|
|
1883
|
+
await writeRoleInvocationLedger(admitted, admitted.role, options.model);
|
|
1884
|
+
|
|
1885
|
+
return {
|
|
1886
|
+
role: "notary",
|
|
1887
|
+
runId,
|
|
1888
|
+
bookKey,
|
|
1889
|
+
projectRoot,
|
|
1890
|
+
instruction: "",
|
|
1891
|
+
instructionEmpty: true,
|
|
1892
|
+
attachments: [],
|
|
1893
|
+
runDirectory,
|
|
1894
|
+
sessionDirectory,
|
|
1895
|
+
sessionFile,
|
|
1896
|
+
admittedRequestPath,
|
|
1897
|
+
sourceRunPath: sourceRun.runDirectory,
|
|
1898
|
+
sourceRun,
|
|
1899
|
+
...(options.correlationId === undefined
|
|
1900
|
+
? {}
|
|
1901
|
+
: { correlationId: options.correlationId }),
|
|
1902
|
+
};
|
|
1903
|
+
}
|
|
1904
|
+
|
|
1905
|
+
/** Package-owned fixed kickoff only — never caller instruction/attachments. */
|
|
1906
|
+
export function buildNotaryTransportPrompt(
|
|
1907
|
+
_admitted: AdmittedNotaryInvocation,
|
|
1908
|
+
engineMaterial?: EngineSessionMaterial,
|
|
1909
|
+
): string {
|
|
1910
|
+
return appendEngineSessionMaterial([NOTARY_FIXED_KICKOFF], engineMaterial).join(
|
|
1911
|
+
"\n",
|
|
1912
|
+
);
|
|
1913
|
+
}
|
|
1914
|
+
|
|
1745
1915
|
/**
|
|
1746
1916
|
* Parse Reviewer-specific argv after the `reviewer` token.
|
|
1747
1917
|
* Public flags: --project, required --base, optional repeatable --authority-ref.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public Notary Role run: admit source-run locator → shared one-shot dispatch
|
|
3
|
+
* → settle Terminal result (#448). Zero caller prompt/attachment. Lifecycle is
|
|
4
|
+
* the shared Doctor-isomorphic seam; this module keeps only Notary adapters.
|
|
5
|
+
*/
|
|
6
|
+
import { engineSessionMaterialFromOptions } from "../package-resources/engine-material.ts";
|
|
7
|
+
import { CliUsageError } from "./cli-errors.ts";
|
|
8
|
+
import {
|
|
9
|
+
admitNotaryInvocation,
|
|
10
|
+
buildNotaryTransportPrompt,
|
|
11
|
+
type AdmittedNotaryInvocation,
|
|
12
|
+
type ParseNotaryArgvResult,
|
|
13
|
+
} from "./invocation.ts";
|
|
14
|
+
import {
|
|
15
|
+
buildSeatModelCliArgs,
|
|
16
|
+
type SeatModelConfig,
|
|
17
|
+
} from "./config.ts";
|
|
18
|
+
import {
|
|
19
|
+
runAdmittedOneShotRole,
|
|
20
|
+
type OneShotRunEnv,
|
|
21
|
+
} from "./one-shot-dispatch.ts";
|
|
22
|
+
import {
|
|
23
|
+
presentStructuralRejection,
|
|
24
|
+
trySettleNotaryTerminalResult,
|
|
25
|
+
} from "./settlement.ts";
|
|
26
|
+
import type { CliIo } from "./cli-io.ts";
|
|
27
|
+
import type { TerminalResult } from "./terminal.ts";
|
|
28
|
+
|
|
29
|
+
export type NotaryRunEnv = OneShotRunEnv & {
|
|
30
|
+
createRunId?: () => string;
|
|
31
|
+
extraPiArgs?: readonly string[];
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export function buildNotaryActivationExtraArgs(
|
|
35
|
+
admitted: AdmittedNotaryInvocation,
|
|
36
|
+
options: {
|
|
37
|
+
model?: SeatModelConfig;
|
|
38
|
+
engine?: string;
|
|
39
|
+
packageRoot?: string;
|
|
40
|
+
extraPiArgs?: readonly string[];
|
|
41
|
+
} = {},
|
|
42
|
+
): string[] {
|
|
43
|
+
const prompt = buildNotaryTransportPrompt(
|
|
44
|
+
admitted,
|
|
45
|
+
engineSessionMaterialFromOptions(options),
|
|
46
|
+
);
|
|
47
|
+
return [
|
|
48
|
+
"--no-skills",
|
|
49
|
+
"--no-prompt-templates",
|
|
50
|
+
"--no-themes",
|
|
51
|
+
"--no-context-files",
|
|
52
|
+
"--session",
|
|
53
|
+
admitted.sessionFile,
|
|
54
|
+
"--session-dir",
|
|
55
|
+
admitted.sessionDirectory,
|
|
56
|
+
...(options.extraPiArgs ?? []),
|
|
57
|
+
"--ak-role",
|
|
58
|
+
"notary",
|
|
59
|
+
"--ak-notary-source-run",
|
|
60
|
+
admitted.sourceRunPath,
|
|
61
|
+
"--mode",
|
|
62
|
+
"json",
|
|
63
|
+
...buildSeatModelCliArgs(options.model),
|
|
64
|
+
prompt,
|
|
65
|
+
];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export async function runPublicNotary(
|
|
69
|
+
argv: readonly string[],
|
|
70
|
+
env: NotaryRunEnv,
|
|
71
|
+
io: CliIo,
|
|
72
|
+
parseNotaryArgv: (args: readonly string[]) => ParseNotaryArgvResult,
|
|
73
|
+
): Promise<{
|
|
74
|
+
exitCode: number;
|
|
75
|
+
admitted?: AdmittedNotaryInvocation;
|
|
76
|
+
terminal?: TerminalResult;
|
|
77
|
+
}> {
|
|
78
|
+
let admitted: AdmittedNotaryInvocation;
|
|
79
|
+
try {
|
|
80
|
+
const parsed = parseNotaryArgv(argv);
|
|
81
|
+
admitted = await admitNotaryInvocation({
|
|
82
|
+
home: env.home,
|
|
83
|
+
cwd: env.cwd,
|
|
84
|
+
sourceRun: parsed.sourceRun,
|
|
85
|
+
...(parsed.project === undefined ? {} : { project: parsed.project }),
|
|
86
|
+
...(env.createRunId === undefined ? {} : { createRunId: env.createRunId }),
|
|
87
|
+
...(env.model === undefined ? {} : { model: env.model }),
|
|
88
|
+
...(env.correlationId === undefined ? {} : { correlationId: env.correlationId }),
|
|
89
|
+
});
|
|
90
|
+
} catch (error) {
|
|
91
|
+
if (error instanceof CliUsageError) {
|
|
92
|
+
presentStructuralRejection(error, io);
|
|
93
|
+
return { exitCode: 2 };
|
|
94
|
+
}
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const extraArgs = buildNotaryActivationExtraArgs(admitted, {
|
|
99
|
+
packageRoot: env.packageRoot,
|
|
100
|
+
...(env.model === undefined ? {} : { model: env.model }),
|
|
101
|
+
...(env.engine === undefined ? {} : { engine: env.engine }),
|
|
102
|
+
...(env.extraPiArgs === undefined ? {} : { extraPiArgs: env.extraPiArgs }),
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
return await runAdmittedOneShotRole({
|
|
106
|
+
admitted,
|
|
107
|
+
env,
|
|
108
|
+
io,
|
|
109
|
+
extraArgs,
|
|
110
|
+
adapters: {
|
|
111
|
+
trySettle: trySettleNotaryTerminalResult,
|
|
112
|
+
// Accepted receipts and residual incomplete share one present path.
|
|
113
|
+
shouldPresentSettled: () => true,
|
|
114
|
+
},
|
|
115
|
+
...(env.engine === undefined ? {} : { effectiveEngine: env.engine }),
|
|
116
|
+
});
|
|
117
|
+
}
|