@akagilnc/pi-workflow-roles 0.1.4259 → 0.1.4274

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.
@@ -19,62 +19,6 @@ function seatModelOnly(seat) {
19
19
  if (seat?.provider === void 0 || seat.model === void 0) return void 0;
20
20
  return seat.thinking === void 0 ? { provider: seat.provider, model: seat.model } : { provider: seat.provider, model: seat.model, thinking: seat.thinking };
21
21
  }
22
- const STARTUP_CANDIDATES = {
23
- judge: [
24
- { provider: "openai-codex", model: "gpt-5.6-sol", thinking: "high" },
25
- { provider: "xai", model: "grok-4.5", thinking: "high" }
26
- ],
27
- countersign: [
28
- { provider: "openai-codex", model: "gpt-5.6-sol", thinking: "high" },
29
- { provider: "xai", model: "grok-4.5", thinking: "high" }
30
- ],
31
- "gleaner-left": [
32
- { provider: "openai-codex", model: "gpt-5.6-sol", thinking: "medium" },
33
- { provider: "xai", model: "grok-4.5", thinking: "high" }
34
- ],
35
- reviewer: [
36
- { provider: "openai-codex", model: "gpt-5.6-sol", thinking: "medium" },
37
- { provider: "xai", model: "grok-4.5", thinking: "high" }
38
- ],
39
- coder: [
40
- { provider: "openai-codex", model: "gpt-5.6-luna", thinking: "high" },
41
- { provider: "xai", model: "grok-4.5", thinking: "high" }
42
- ],
43
- fixer: [
44
- { provider: "openai-codex", model: "gpt-5.6-luna", thinking: "high" },
45
- { provider: "xai", model: "grok-4.5", thinking: "high" }
46
- ],
47
- collector: [
48
- { provider: "openai-codex", model: "gpt-5.6-luna", thinking: "high" },
49
- { provider: "xai", model: "grok-4.5", thinking: "high" }
50
- ],
51
- doctor: [
52
- { provider: "openai-codex", model: "gpt-5.6-luna", thinking: "high" },
53
- { provider: "xai", model: "grok-4.5", thinking: "high" }
54
- ],
55
- merger: [
56
- { provider: "openai-codex", model: "gpt-5.6-luna", thinking: "high" },
57
- { provider: "xai", model: "grok-4.5", thinking: "high" }
58
- ],
59
- // #620: subordinate officers inherit gatekeeper; no package startup model.
60
- notary: [],
61
- // #453/#620/#639: gatekeeper callable but no package startup model — caller
62
- // configures it or inherits on the province path.
63
- gatekeeper: [],
64
- inspector: [],
65
- navigator: [
66
- { provider: "openai-codex", model: "gpt-5.6-luna", thinking: "medium" },
67
- { provider: "xai", model: "grok-4.5", thinking: "high" }
68
- ],
69
- // #675: auditor public seat — no package startup; caller configures.
70
- auditor: [],
71
- // #708 `diarist-seat-default`: owner-set initial value; changed in the seat
72
- // table like any other seat. No engine axis, package-default host.
73
- diarist: [{ provider: "xai", model: "grok-4.5", thinking: "medium" }]
74
- };
75
- function publicStartupCandidates(seat) {
76
- return STARTUP_CANDIDATES[seat];
77
- }
78
22
  const PUBLIC_DETERMINISTIC_COMMANDS = ["analyst"];
79
23
  function listHelpCapabilities() {
80
24
  const support = PUBLIC_CLI_SUPPORT_COMMANDS.map((name) => ({
@@ -118,6 +62,5 @@ export {
118
62
  isPublicCliSupportCommand,
119
63
  isPublicConfigurableSeat,
120
64
  listHelpCapabilities,
121
- publicStartupCandidates,
122
65
  seatModelOnly
123
66
  };
@@ -77,11 +77,17 @@ function hostSelectionFailureFromUnknown(error) {
77
77
  const failure = error.failure;
78
78
  return failure;
79
79
  }
80
- async function createSummonEnv(options) {
81
- const [{ piDurablePrincipalAuthority }, { appendPiSessionCustomEntry }, { resolveRoleTurnHost }] = await Promise.all([
80
+ async function createSummonEnv(options, afterHost) {
81
+ const [
82
+ { piDurablePrincipalAuthority },
83
+ { appendPiSessionCustomEntry },
84
+ { resolveRoleTurnHost },
85
+ { missingResolvedSeatModelMessage, resolvedSeatWithModel }
86
+ ] = await Promise.all([
82
87
  import("./pi/durable-principal.js"),
83
88
  import("./pi/role-turn-host.js"),
84
- import("./public-cli/role-turn-host-resolution.js")
89
+ import("./public-cli/role-turn-host-resolution.js"),
90
+ import("./public-cli/config.js")
85
91
  ]);
86
92
  const principalAuthority = piDurablePrincipalAuthority;
87
93
  const roleTurnHost = resolveRoleTurnHost(
@@ -93,26 +99,37 @@ async function createSummonEnv(options) {
93
99
  },
94
100
  { role: options.role, seat: options.seat, principalAuthority }
95
101
  );
96
- const hostName = options.seat.host ?? "pi";
102
+ afterHost?.();
103
+ const seatWithModel = resolvedSeatWithModel(options.seat);
104
+ if (seatWithModel === void 0) {
105
+ return {
106
+ ok: false,
107
+ missingModelMessage: missingResolvedSeatModelMessage(options.role)
108
+ };
109
+ }
110
+ const hostName = seatWithModel.host ?? "pi";
97
111
  const { loadHostProvidersTable, projectHostFacingProvider } = await import("./public-cli/host-providers.js");
98
- const hostFacingSelection = options.seat.selection === void 0 ? void 0 : projectHostFacingProvider(
99
- options.seat.selection,
112
+ const hostFacingSelection = projectHostFacingProvider(
113
+ seatWithModel.selection,
100
114
  hostName,
101
115
  loadHostProvidersTable(options.home),
102
116
  options.home
103
117
  );
104
118
  return {
105
- home: options.home,
106
- principalAuthority,
107
- agentDir: options.agentDir,
108
- sessionAppender: appendPiSessionCustomEntry,
109
- packageRoot: options.packageRoot,
110
- roleTurnHost,
111
- cwd: options.cwd,
112
- credentials: options.credentials,
113
- ...hostFacingSelection === void 0 ? {} : { model: hostFacingSelection },
114
- ...projectSeatEngine(options.seat),
115
- ...projectSeatHost(options.seat)
119
+ ok: true,
120
+ env: {
121
+ home: options.home,
122
+ principalAuthority,
123
+ agentDir: options.agentDir,
124
+ sessionAppender: appendPiSessionCustomEntry,
125
+ packageRoot: options.packageRoot,
126
+ roleTurnHost,
127
+ cwd: options.cwd,
128
+ credentials: options.credentials,
129
+ ...hostFacingSelection === void 0 ? {} : { model: hostFacingSelection },
130
+ ...projectSeatEngine(seatWithModel),
131
+ ...projectSeatHost(seatWithModel)
132
+ }
116
133
  };
117
134
  }
118
135
  async function summonPublicRole(options) {
@@ -127,46 +144,72 @@ async function summonPublicRole(options) {
127
144
  const credentials = options.credentials ?? await loadCredentialProviders(agentDir);
128
145
  const config = await loadPublicCliConfig(home);
129
146
  const seat = resolveEffectiveSeat(config, options.role, credentials);
130
- let summonEnv;
131
- try {
132
- summonEnv = await createSummonEnv({
133
- role: options.role,
134
- home,
135
- agentDir,
136
- cwd: options.cwd,
137
- packageRoot,
138
- credentials,
139
- seat,
140
- ...options.extraPiArgs === void 0 ? {} : { extraPiArgs: options.extraPiArgs },
141
- ...options.roleTurnHost === void 0 ? {} : { roleTurnHost: options.roleTurnHost },
142
- ...options.hostAdapters === void 0 ? {} : { hostAdapters: options.hostAdapters }
143
- });
144
- } catch (error) {
145
- const failure = hostSelectionFailureFromUnknown(error);
146
- if (failure !== void 0) {
147
- const { formatHostSelectionFailure } = await import("./public-cli/role-turn-host-resolution.js");
148
- return { exitCode: 1, stderr: formatHostSelectionFailure(failure) };
149
- }
150
- throw error;
151
- }
152
- const env = {
153
- ...summonEnv,
154
- // Station child role run (#840): omit automatic navigator attendance.
155
- stationChild: true,
156
- // Host config passthrough only — same face as public CLI (#422 / #675).
157
- ...config.autoResumeLimit === void 0 ? {} : { autoResumeLimit: config.autoResumeLimit },
158
- // Parent cancellation reaches the nested activation's own turn dispatch.
159
- ...options.signal === void 0 ? {} : { signal: options.signal },
160
- // #753: reask rides the existing notary same-ticket resume summons.instruction.
161
- ...options.reviewReask === void 0 ? {} : { reviewReask: options.reviewReask },
162
- // #879: verbatim submission body on officer dialogue content channel.
163
- ...options.gateReviewInstruction === void 0 ? {} : { gateReviewInstruction: options.gateReviewInstruction },
164
- ...options.boundTicketNumber === void 0 ? {} : { boundTicketNumber: options.boundTicketNumber },
165
- // createRunId is the only remaining env overlay — host is seat-selected above.
166
- ...options.createRunId === void 0 ? {} : { createRunId: options.createRunId }
167
- };
168
147
  const captured = options.io === void 0 ? createCapturingIo() : void 0;
169
148
  const io = options.io ?? captured.io;
149
+ const summonEnvInput = {
150
+ role: options.role,
151
+ home,
152
+ agentDir,
153
+ cwd: options.cwd,
154
+ packageRoot,
155
+ credentials,
156
+ seat,
157
+ ...options.extraPiArgs === void 0 ? {} : { extraPiArgs: options.extraPiArgs },
158
+ ...options.roleTurnHost === void 0 ? {} : { roleTurnHost: options.roleTurnHost },
159
+ ...options.hostAdapters === void 0 ? {} : { hostAdapters: options.hostAdapters }
160
+ };
161
+ async function prepareSummonEnv(afterHost) {
162
+ try {
163
+ const built = await createSummonEnv(summonEnvInput, afterHost);
164
+ if (!built.ok) {
165
+ return { ok: false, exitCode: 1, stderr: built.missingModelMessage };
166
+ }
167
+ return {
168
+ ok: true,
169
+ env: {
170
+ ...built.env,
171
+ stationChild: true,
172
+ ...config.autoResumeLimit === void 0 ? {} : { autoResumeLimit: config.autoResumeLimit },
173
+ ...options.signal === void 0 ? {} : { signal: options.signal },
174
+ ...options.reviewReask === void 0 ? {} : { reviewReask: options.reviewReask },
175
+ ...options.gateReviewInstruction === void 0 ? {} : { gateReviewInstruction: options.gateReviewInstruction },
176
+ ...options.boundTicketNumber === void 0 ? {} : { boundTicketNumber: options.boundTicketNumber },
177
+ ...options.createRunId === void 0 ? {} : { createRunId: options.createRunId }
178
+ }
179
+ };
180
+ } catch (error) {
181
+ const failure = hostSelectionFailureFromUnknown(error);
182
+ if (failure !== void 0) {
183
+ const { formatHostSelectionFailure } = await import("./public-cli/role-turn-host-resolution.js");
184
+ return { ok: false, exitCode: 1, stderr: formatHostSelectionFailure(failure) };
185
+ }
186
+ const { CliUsageError } = await import("./public-cli/cli-errors.js");
187
+ if (error instanceof CliUsageError) {
188
+ const { presentStructuralRejection } = await import("./public-cli/settlement.js");
189
+ presentStructuralRejection(error, io);
190
+ return { ok: false, exitCode: 2 };
191
+ }
192
+ throw error;
193
+ }
194
+ }
195
+ function projectPrepareFailure(prepared) {
196
+ const parts = [prepared.stderr, captured?.stderrText()].filter(
197
+ (s) => typeof s === "string" && s !== ""
198
+ );
199
+ const stderr2 = parts.length === 0 ? void 0 : parts.join("");
200
+ return {
201
+ exitCode: prepared.exitCode,
202
+ ...stderr2 === void 0 ? {} : { stderr: stderr2 }
203
+ };
204
+ }
205
+ async function runPrepared(parse, run) {
206
+ let parsedArgv;
207
+ const prepared = await prepareSummonEnv(() => {
208
+ parsedArgv = parse(options.argv);
209
+ });
210
+ if (!prepared.ok) return { fail: projectPrepareFailure(prepared) };
211
+ return { ok: await run(prepared.env, () => parsedArgv) };
212
+ }
170
213
  let result;
171
214
  switch (options.role) {
172
215
  case "notary": {
@@ -174,7 +217,9 @@ async function summonPublicRole(options) {
174
217
  import("./public-cli/notary-run.js"),
175
218
  import("./public-cli/invocation.js")
176
219
  ]);
177
- result = await runPublicNotary(options.argv, env, io, parseNotaryArgv);
220
+ const stepped = await runPrepared(parseNotaryArgv, (env, once) => runPublicNotary(options.argv, env, io, once));
221
+ if ("fail" in stepped) return stepped.fail;
222
+ result = stepped.ok;
178
223
  break;
179
224
  }
180
225
  case "inspector": {
@@ -182,49 +227,23 @@ async function summonPublicRole(options) {
182
227
  import("./public-cli/inspector-run.js"),
183
228
  import("./public-cli/invocation.js")
184
229
  ]);
185
- result = await runPublicInspector(options.argv, env, io, parseInspectorArgv);
186
- break;
187
- }
188
- case "auditor": {
189
- const [{ runPublicInstructionSeat }, { parseAuditorArgv }] = await Promise.all([
190
- import("./public-cli/instruction-seat-run.js"),
191
- import("./public-cli/invocation.js")
192
- ]);
193
- result = await runPublicInstructionSeat(
194
- options.argv,
195
- env,
196
- io,
197
- "auditor",
198
- parseAuditorArgv
199
- );
200
- break;
201
- }
202
- case "navigator": {
203
- const [{ runPublicInstructionSeat }, { parseNavigatorArgv }] = await Promise.all([
204
- import("./public-cli/instruction-seat-run.js"),
205
- import("./public-cli/invocation.js")
206
- ]);
207
- result = await runPublicInstructionSeat(
208
- options.argv,
209
- env,
210
- io,
211
- "navigator",
212
- parseNavigatorArgv
213
- );
230
+ const stepped = await runPrepared(parseInspectorArgv, (env, once) => runPublicInspector(options.argv, env, io, once));
231
+ if ("fail" in stepped) return stepped.fail;
232
+ result = stepped.ok;
214
233
  break;
215
234
  }
235
+ case "auditor":
236
+ case "navigator":
216
237
  case "gatekeeper": {
217
- const [{ runPublicInstructionSeat }, { parseGatekeeperArgv }] = await Promise.all([
238
+ const seat2 = options.role;
239
+ const [{ runPublicInstructionSeat }, invocation] = await Promise.all([
218
240
  import("./public-cli/instruction-seat-run.js"),
219
241
  import("./public-cli/invocation.js")
220
242
  ]);
221
- result = await runPublicInstructionSeat(
222
- options.argv,
223
- env,
224
- io,
225
- "gatekeeper",
226
- parseGatekeeperArgv
227
- );
243
+ const parse = seat2 === "auditor" ? invocation.parseAuditorArgv : seat2 === "navigator" ? invocation.parseNavigatorArgv : invocation.parseGatekeeperArgv;
244
+ const stepped = await runPrepared(parse, (env, once) => runPublicInstructionSeat(options.argv, env, io, seat2, once));
245
+ if ("fail" in stepped) return stepped.fail;
246
+ result = stepped.ok;
228
247
  break;
229
248
  }
230
249
  case "judge": {
@@ -232,7 +251,9 @@ async function summonPublicRole(options) {
232
251
  import("./public-cli/judge-run.js"),
233
252
  import("./public-cli/invocation.js")
234
253
  ]);
235
- result = await runPublicJudge(options.argv, env, io, parseJudgeArgv);
254
+ const stepped = await runPrepared(parseJudgeArgv, (env, once) => runPublicJudge(options.argv, env, io, once));
255
+ if ("fail" in stepped) return stepped.fail;
256
+ result = stepped.ok;
236
257
  break;
237
258
  }
238
259
  case "doctor": {
@@ -240,7 +261,9 @@ async function summonPublicRole(options) {
240
261
  import("./public-cli/doctor-run.js"),
241
262
  import("./public-cli/invocation.js")
242
263
  ]);
243
- result = await runPublicDoctor(options.argv, env, io, parseDoctorArgv);
264
+ const stepped = await runPrepared(parseDoctorArgv, (env, once) => runPublicDoctor(options.argv, env, io, once));
265
+ if ("fail" in stepped) return stepped.fail;
266
+ result = stepped.ok;
244
267
  break;
245
268
  }
246
269
  case "diarist": {
@@ -248,7 +271,9 @@ async function summonPublicRole(options) {
248
271
  import("./public-cli/diarist-run.js"),
249
272
  import("./public-cli/invocation.js")
250
273
  ]);
251
- result = await runPublicDiarist(options.argv, env, io, parseDiaristArgv);
274
+ const stepped = await runPrepared(parseDiaristArgv, (env, once) => runPublicDiarist(options.argv, env, io, once));
275
+ if ("fail" in stepped) return stepped.fail;
276
+ result = stepped.ok;
252
277
  break;
253
278
  }
254
279
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akagilnc/pi-workflow-roles",
3
- "version": "0.1.4259",
3
+ "version": "0.1.4274",
4
4
  "description": "Soul-bound workflow roles for Pi",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -18,7 +18,6 @@ import {
18
18
  import type { HostContext } from "./host-contracts.ts";
19
19
  import { createNativeNavigatorSessionFactory } from "./navigator-public-session.ts";
20
20
  import {
21
- NAVIGATOR_DEFAULT_MODEL,
22
21
  NAVIGATOR_PREPARE_TOOL_NAME,
23
22
  NavigatorUnavailableError,
24
23
  navigatorModelSettingPath,
@@ -40,7 +39,6 @@ import {
40
39
  import { sitianReport } from "./sitian-facade.ts";
41
40
 
42
41
  export {
43
- NAVIGATOR_DEFAULT_MODEL,
44
42
  NAVIGATOR_PREPARE_TOOL_NAME,
45
43
  NavigatorUnavailableError,
46
44
  navigatorModelSettingPath,
@@ -12,7 +12,6 @@ import {
12
12
  navigatorProviderFailureFromError,
13
13
  navigatorUnavailableError,
14
14
  parseNavigatorModelSetting,
15
- resolveNavigatorSeatSelection,
16
15
  type NavigatorProviderFailureFact,
17
16
  type NavigatorSessionFactory,
18
17
  } from "./navigator-session-contracts.ts";
@@ -43,8 +42,9 @@ async function resolveNavigatorLedgerHome(context: HostContext): Promise<string
43
42
 
44
43
  export function createNativeNavigatorSessionFactory(): NavigatorSessionFactory {
45
44
  return async ({ context, subject, tool }) => {
46
- const resolved = await resolveNavigatorSeatSelection(context);
47
- let thinkingLevel = resolved.thinkingLevel;
45
+ // Model is enforced at prepare (attendance seat resolve) and at prompt (summon).
46
+ // Factory open only books the archivist nest — no package default, no eager seat read.
47
+ let thinkingLevel: string | undefined;
48
48
 
49
49
  // Archivist nest for attendance route memory only (ADR 0018 / 0065) — not a session open.
50
50
  // #852: navigator/<work-subject> is the sole book-top exception; always pass subject so
@@ -15,7 +15,6 @@ import type { NoReceiptLifecycleFacts } from "./receipt-delivery-policy.ts";
15
15
 
16
16
 
17
17
  export const NAVIGATOR_PREPARE_TOOL_NAME = "ak_navigator_prepare" as const;
18
- export const NAVIGATOR_DEFAULT_MODEL = "openai-codex/gpt-5.6-luna:max" as const;
19
18
 
20
19
  export type NavigatorUnavailableKey =
21
20
  | "context" | "session" | "model" | "thinking" | "auth" | "quota" | "transport" | "unknown";
@@ -229,8 +228,9 @@ export async function readNavigatorModelSetting(path = navigatorModelSettingPath
229
228
  }
230
229
  return raw.model;
231
230
  } catch (error) {
231
+ // #178: missing file is absence (no package default).
232
232
  if (error instanceof Error && "code" in error && (error as NodeJS.ErrnoException).code === "ENOENT") {
233
- return NAVIGATOR_DEFAULT_MODEL;
233
+ throw new Error("Navigator model setting is missing");
234
234
  }
235
235
  throw error;
236
236
  }
@@ -294,19 +294,13 @@ export async function resolveNavigatorSeatSelection(
294
294
  : packageMachineHome();
295
295
  const config = await loadPublicCliConfig(home);
296
296
  const modelOnly = seatModelOnly(config.seats.navigator);
297
- // Seat table is the only model authority — no legacy navigator-model.json.
298
- // Bare missing seat uses the package default constant (not a file path).
297
+ // Seat table only — missing navigator seat → typed model-unavailable (#178).
299
298
  if (modelOnly === undefined) {
300
- const parsed = parseNavigatorModelSetting(NAVIGATOR_DEFAULT_MODEL);
301
- return {
302
- selection: {
303
- provider: parsed.provider,
304
- model: parsed.model,
305
- ...(parsed.thinkingLevel === undefined ? {} : { thinking: parsed.thinkingLevel }),
306
- },
307
- configuredLabel: NAVIGATOR_DEFAULT_MODEL,
308
- ...(parsed.thinkingLevel === undefined ? {} : { thinkingLevel: parsed.thinkingLevel }),
309
- };
299
+ const { missingResolvedSeatModelMessage } = await import("./public-cli/config.ts");
300
+ throw navigatorUnavailableError(
301
+ "model",
302
+ new Error(missingResolvedSeatModelMessage("navigator")),
303
+ );
310
304
  }
311
305
  // Host params passthrough only — no map/validate/default (#675 ⑥).
312
306
  const thinkingRaw = modelOnly.thinking;