@akagilnc/pi-workflow-roles 0.1.2296 → 0.1.2310
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 +3345 -2778
- package/extensions/role-runtime.ts +11 -1
- package/package.json +1 -1
- package/souls/judge-output-guide.md +4 -1
- package/src/analyst-gate-cycles-read.ts +7 -2
- 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
package/src/public-cli/cli.ts
CHANGED
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
parseFixerArgv,
|
|
39
39
|
parseJudgeArgv,
|
|
40
40
|
parseMergerArgv,
|
|
41
|
+
parseNotaryArgv,
|
|
41
42
|
parseReviewerArgv,
|
|
42
43
|
parseAnalystArgv,
|
|
43
44
|
} from "./invocation.ts";
|
|
@@ -55,6 +56,7 @@ import { runPublicCoder, runPublicCoderResume } from "./coder-run.ts";
|
|
|
55
56
|
import { runPublicCollector } from "./collector-run.ts";
|
|
56
57
|
import { runPublicDoctor } from "./doctor-run.ts";
|
|
57
58
|
import { runPublicFixer, runPublicFixerResume } from "./fixer-run.ts";
|
|
59
|
+
import { runPublicNotary } from "./notary-run.ts";
|
|
58
60
|
import { runPublicJudge, runPublicResume } from "./judge-run.ts";
|
|
59
61
|
import { runPublicMerger, runPublicMergerResume } from "./merger-run.ts";
|
|
60
62
|
import { runPublicReviewer, runPublicReviewerResume } from "./reviewer-run.ts";
|
|
@@ -94,6 +96,7 @@ export const PUBLIC_ROLE_ARGV = {
|
|
|
94
96
|
collector: { parse: parseCollectorArgv, options: optionsForOwner("collector") },
|
|
95
97
|
doctor: { parse: parseDoctorArgv, options: optionsForOwner("doctor") },
|
|
96
98
|
merger: { parse: parseMergerArgv, options: optionsForOwner("merger") },
|
|
99
|
+
notary: { parse: parseNotaryArgv, options: optionsForOwner("notary") },
|
|
97
100
|
reviewer: { parse: parseReviewerArgv, options: optionsForOwner("reviewer") },
|
|
98
101
|
/** Deterministic analysis seat (#336) — argv parse only; no LLM admission. */
|
|
99
102
|
analyst: { parse: parseAnalystArgv, options: optionsForOwner("analyst") },
|
|
@@ -190,6 +193,10 @@ export type CliEnv = {
|
|
|
190
193
|
mergerExtraPiArgs?: readonly string[];
|
|
191
194
|
/** Override Merger role-run timeout (tests). */
|
|
192
195
|
mergerTimeoutMs?: number;
|
|
196
|
+
/** Extra Pi args for Notary runs (tests: faux provider). */
|
|
197
|
+
notaryExtraPiArgs?: readonly string[];
|
|
198
|
+
/** Override Notary role-run timeout (tests). */
|
|
199
|
+
notaryTimeoutMs?: number;
|
|
193
200
|
createRunId?: () => string;
|
|
194
201
|
};
|
|
195
202
|
|
|
@@ -1203,6 +1210,50 @@ export async function runAkRole(
|
|
|
1203
1210
|
};
|
|
1204
1211
|
}
|
|
1205
1212
|
|
|
1213
|
+
// Notary public run path: source-run locator only, direct officer seat (#448).
|
|
1214
|
+
if (parsed.command === "notary") {
|
|
1215
|
+
const agentDir = resolveAgentDir(env, home);
|
|
1216
|
+
const cwd = env.cwd ?? process.cwd();
|
|
1217
|
+
const config = await loadAndValidateConfig(home, env.packageRoot);
|
|
1218
|
+
const credentials =
|
|
1219
|
+
env.credentials ?? (await loadCredentialProviders(agentDir));
|
|
1220
|
+
const seat = resolveEffectiveSeat(
|
|
1221
|
+
config,
|
|
1222
|
+
"notary",
|
|
1223
|
+
credentials,
|
|
1224
|
+
invocationFromParsed(parsed),
|
|
1225
|
+
);
|
|
1226
|
+
const result = await runPublicNotary(
|
|
1227
|
+
parsed.args,
|
|
1228
|
+
{
|
|
1229
|
+
home,
|
|
1230
|
+
agentDir,
|
|
1231
|
+
packageRoot: env.packageRoot,
|
|
1232
|
+
cwd,
|
|
1233
|
+
credentials,
|
|
1234
|
+
...(env.correlationId === undefined
|
|
1235
|
+
? {}
|
|
1236
|
+
: { correlationId: env.correlationId }),
|
|
1237
|
+
...(env.piRunner === undefined ? {} : { piRunner: env.piRunner }),
|
|
1238
|
+
...(seat.selection === undefined ? {} : { model: seat.selection }),
|
|
1239
|
+
...projectSeatEngine(seat),
|
|
1240
|
+
...(env.notaryExtraPiArgs === undefined
|
|
1241
|
+
? {}
|
|
1242
|
+
: { extraPiArgs: env.notaryExtraPiArgs }),
|
|
1243
|
+
...(env.notaryTimeoutMs === undefined
|
|
1244
|
+
? {}
|
|
1245
|
+
: { timeoutMs: env.notaryTimeoutMs }),
|
|
1246
|
+
...(env.createRunId === undefined ? {} : { createRunId: env.createRunId }),
|
|
1247
|
+
},
|
|
1248
|
+
io,
|
|
1249
|
+
PUBLIC_ROLE_ARGV.notary.parse,
|
|
1250
|
+
);
|
|
1251
|
+
return {
|
|
1252
|
+
exitCode: result.exitCode,
|
|
1253
|
+
...(result.terminal === undefined ? {} : { terminal: result.terminal }),
|
|
1254
|
+
};
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1206
1257
|
// Merger public run path: derive active-merge envelope + forced merge-only method (#114).
|
|
1207
1258
|
if (parsed.command === "merger") {
|
|
1208
1259
|
const agentDir = resolveAgentDir(env, home);
|
|
@@ -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.
|