@akagilnc/pi-workflow-roles 0.1.5663 → 0.1.5671

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.
@@ -1,7 +1,7 @@
1
1
  import { mkdir, readFile, writeFile } from "node:fs/promises";
2
2
  import { homedir } from "node:os";
3
3
  import { dirname, join, resolve } from "node:path";
4
- import { Type } from "typebox";
4
+ import {} from "typebox";
5
5
  import {
6
6
  NAVIGATOR_INVOCATION_ENTRY,
7
7
  NAVIGATOR_ROUTE_PLAYBOOK_FAILURE_ENTRY,
@@ -31,7 +31,13 @@ import {
31
31
  import { sitianReport } from "./sitian-facade.js";
32
32
  import { issueRoot, subjectPath } from "./work-subject-identity.js";
33
33
  import { createReceiptDeliveryPolicy } from "./receipt-delivery-policy.js";
34
- import { navigatorProseFromUnknown } from "./package-contracts/navigator-output.js";
34
+ import {
35
+ byStatusToPlainObject,
36
+ mergePreparedAdvice,
37
+ navigatorAdviceBodySchema,
38
+ pickPreparedProse,
39
+ preparedAdviceFromUnknown
40
+ } from "./package-contracts/navigator-output.js";
35
41
  import { sha256Hex } from "./sha256.js";
36
42
  import { isRecord } from "./unknown-value.js";
37
43
  const NAVIGATOR_EVENT_TYPE = "ak-navigator-attendance";
@@ -41,11 +47,7 @@ function resolveNavigatorAuthorityMaterial(roleInput, fileAuthority) {
41
47
  return void 0;
42
48
  }
43
49
  const NAVIGATOR_TARGETS = PACKAGED_ROLE_REGISTRY.map(({ role, phases }) => ({ role, phases }));
44
- const prepareSchema = Type.Object({
45
- prose: Type.Optional(Type.Unknown({
46
- description: "\u6E38\u5955\u4F7F\u6563\u6587\u5EFA\u8BAE\uFF0C\u539F\u6837\u5448\u73B0\u3002\u4E0D\u8981\u6C42 candidates/next \u7ED3\u6784\u3002"
47
- }))
48
- }, { additionalProperties: true });
50
+ const prepareSchema = navigatorAdviceBodySchema;
49
51
  const INVOCATION_ENTRY = NAVIGATOR_INVOCATION_ENTRY;
50
52
  const SETTLEMENT_ENTRY = "ak-navigator-settlement";
51
53
  const unavailableKeys = /* @__PURE__ */ new Set(["context", "session", "model", "thinking", "auth", "quota", "transport", "unknown"]);
@@ -74,8 +76,8 @@ function rejectedPrepareReason(entries, start) {
74
76
  }
75
77
  return reason;
76
78
  }
77
- function normalizePrepareProse(value) {
78
- return navigatorProseFromUnknown(value);
79
+ function normalizePreparedAdvice(value) {
80
+ return preparedAdviceFromUnknown(value);
79
81
  }
80
82
  function navigatorSubjectKey(subjectRoot, subject, provenance = "role_input") {
81
83
  if (issueRoot(subjectRoot) !== void 0 || !subjectRoot.includes("/.ak/work/")) return subjectRoot;
@@ -125,7 +127,7 @@ function createNavigatorAttendance(options) {
125
127
  let subject = options.subject;
126
128
  let authority = options.authority;
127
129
  let contextError = options.contextError;
128
- let preparedProse;
130
+ let preparedAdvice;
129
131
  const invocationPrincipal = options.invocationId ?? mintNavigatorInvocationId();
130
132
  let activeInvocationId = invocationPrincipal;
131
133
  let outputSink;
@@ -150,7 +152,6 @@ function createNavigatorAttendance(options) {
150
152
  unavailableCause: failure.unavailableCause
151
153
  };
152
154
  };
153
- let prepareBoundSettlement;
154
155
  const loadMaterialsAndSession = async (invocationId) => {
155
156
  if (contextError !== void 0) throw navigatorUnavailableError("context", contextError);
156
157
  if (typeof authority !== "string" || authority.trim() === "") {
@@ -221,29 +222,32 @@ function createNavigatorAttendance(options) {
221
222
  if (session === void 0) throw new Error("Navigator session was not created");
222
223
  return session;
223
224
  };
224
- const prepare = async (existingSession) => {
225
- const boundSettlement = prepareBoundSettlement;
226
- prepareBoundSettlement = void 0;
225
+ const prepare = async () => {
227
226
  const invocationId = invocationPrincipal;
228
227
  activeInvocationId = invocationId;
229
228
  let output;
230
229
  let prepareBatchRejected = false;
231
230
  outputSink = (value) => {
231
+ const next = normalizePreparedAdvice(value);
232
232
  if (output === void 0) {
233
233
  output = value;
234
234
  return;
235
235
  }
236
- const prior = normalizePrepareProse(output) ?? "";
237
- const next = normalizePrepareProse(value) ?? "";
238
- const merged = [prior, next].filter((part) => part.trim() !== "").join("\n\n");
239
- output = { prose: merged };
236
+ const merged = mergePreparedAdvice(normalizePreparedAdvice(output), next);
237
+ output = {
238
+ ...merged?.prose === void 0 ? {} : { prose: merged.prose },
239
+ ...merged === void 0 || merged.byStatus.size === 0 ? {} : { byStatus: byStatusToPlainObject(merged.byStatus) }
240
+ };
240
241
  };
241
- const activeSession = existingSession ?? await loadMaterialsAndSession(invocationId);
242
- if (boundSettlement === void 0) return void 0;
242
+ const activeSession = await loadMaterialsAndSession(invocationId);
243
243
  const request = JSON.stringify({
244
- ...boundSettlement,
244
+ kind: "prepare",
245
+ role: options.role,
246
+ phase: options.phase,
245
247
  invocationId,
246
- subjectKey
248
+ subjectKey,
249
+ subject,
250
+ authority
247
251
  });
248
252
  try {
249
253
  try {
@@ -277,27 +281,21 @@ function createNavigatorAttendance(options) {
277
281
  }
278
282
  };
279
283
  await promptAllowingRejectedPrepare(request);
280
- if (boundSettlement !== void 0) {
281
- while (output === void 0 && prepareBatchRejected && delivery.nextAction() === "request-delivery") {
282
- delivery.recordDeliveryRequest();
283
- await promptAllowingRejectedPrepare(JSON.stringify(delivery.deliveryState()));
284
- }
285
- if (output === void 0 && delivery.nextAction() === "request-delivery") {
286
- delivery.closeBudget();
287
- }
288
- if (output === void 0 && delivery.nextAction() === "no-receipt" && activeSession.providerFailure?.() === void 0) {
289
- preparedProse = void 0;
290
- return void 0;
291
- }
284
+ while (output === void 0 && prepareBatchRejected && delivery.nextAction() === "request-delivery") {
285
+ delivery.recordDeliveryRequest();
286
+ await promptAllowingRejectedPrepare(JSON.stringify(delivery.deliveryState()));
287
+ }
288
+ if (output === void 0 && delivery.nextAction() === "request-delivery") {
289
+ delivery.closeBudget();
290
+ }
291
+ if (output === void 0 && delivery.nextAction() === "no-receipt" && activeSession.providerFailure?.() === void 0) {
292
+ preparedAdvice = void 0;
293
+ return void 0;
292
294
  }
293
295
  } catch (error) {
294
296
  throw error instanceof NavigatorUnavailableError ? error : navigatorUnavailableError("transport", error);
295
297
  }
296
298
  if (output === void 0) {
297
- if (boundSettlement === void 0) {
298
- preparedProse = void 0;
299
- return void 0;
300
- }
301
299
  const nativeFailure = [...activeSession.entries()].reverse().find((entry) => {
302
300
  if (!isRecord(entry) || entry.type !== "message" || !isRecord(entry.message)) return false;
303
301
  return entry.message.role === "assistant" && typeof entry.message.errorMessage === "string" && entry.message.errorMessage.trim() !== "";
@@ -309,12 +307,8 @@ function createNavigatorAttendance(options) {
309
307
  const cause = providerFailure?.cause ?? source;
310
308
  throw navigatorUnavailableError(source, errorMessage, cause);
311
309
  }
312
- if (boundSettlement === void 0) {
313
- preparedProse = void 0;
314
- return void 0;
315
- }
316
- preparedProse = normalizePrepareProse(output);
317
- return preparedProse;
310
+ preparedAdvice = normalizePreparedAdvice(output);
311
+ return preparedAdvice;
318
312
  } finally {
319
313
  const playbookFailure = activeSession.routePlaybookReadFailure?.();
320
314
  observedRoutePlaybookFailure = typeof playbookFailure === "string" && playbookFailure.trim() !== "" ? playbookFailure : void 0;
@@ -338,6 +332,7 @@ function createNavigatorAttendance(options) {
338
332
  prepare() {
339
333
  if (disposed || preparation !== void 0) return;
340
334
  preparationFailure = void 0;
335
+ preparedAdvice = void 0;
341
336
  preparationInFlight = true;
342
337
  preparation = prepare().finally(() => {
343
338
  preparationInFlight = false;
@@ -375,24 +370,8 @@ function createNavigatorAttendance(options) {
375
370
  };
376
371
  async function settleOnce(settlement) {
377
372
  if (disposed) return;
378
- observedRoutePlaybookFailure = void 0;
379
373
  const invocationId = activeInvocationId ?? invocationPrincipal;
380
374
  let report;
381
- if (sessionReady !== void 0) {
382
- try {
383
- await sessionReady;
384
- } catch (error) {
385
- preparationFailure ??= error;
386
- }
387
- }
388
- if (preparation !== void 0) {
389
- try {
390
- await preparation;
391
- } catch (error) {
392
- preparationFailure ??= error;
393
- }
394
- preparation = void 0;
395
- }
396
375
  const settlementFact = {
397
376
  invocationId,
398
377
  subjectKey,
@@ -401,8 +380,14 @@ function createNavigatorAttendance(options) {
401
380
  kind: settlement.kind,
402
381
  ..."status" in settlement && settlement.status !== void 0 ? { status: settlement.status } : {}
403
382
  };
404
- let drainedProse;
405
383
  if (settlement.kind === "arrival") {
384
+ if (sessionReady !== void 0) {
385
+ try {
386
+ await sessionReady;
387
+ } catch (error) {
388
+ preparationFailure ??= error;
389
+ }
390
+ }
406
391
  session?.appendEntry(SETTLEMENT_ENTRY, settlementFact);
407
392
  if (preparationFailure !== void 0) {
408
393
  report = unavailable(invocationId, preparationFailure);
@@ -413,35 +398,32 @@ function createNavigatorAttendance(options) {
413
398
  };
414
399
  }
415
400
  } else {
416
- if (session !== void 0) preparationFailure = void 0;
417
- let coldSession;
418
- if (session === void 0 && preparationFailure === void 0) {
401
+ if (sessionReady !== void 0) {
419
402
  try {
420
- coldSession = await loadMaterialsAndSession(invocationId);
403
+ await sessionReady;
421
404
  } catch (error) {
422
- preparationFailure = error;
405
+ preparationFailure ??= error;
423
406
  }
424
407
  }
425
- session?.appendEntry(SETTLEMENT_ENTRY, settlementFact);
426
- if (preparationFailure === void 0) {
427
- prepareBoundSettlement = settlement;
428
- preparation = prepare(coldSession);
429
- void preparation.catch((error) => {
430
- preparationFailure = error;
431
- });
408
+ if (preparation !== void 0) {
432
409
  try {
433
- drainedProse = await preparation;
410
+ await preparation;
434
411
  } catch (error) {
435
412
  preparationFailure ??= error;
436
413
  }
437
414
  preparation = void 0;
438
415
  }
416
+ session?.appendEntry(SETTLEMENT_ENTRY, settlementFact);
439
417
  if (preparationFailure !== void 0) {
440
418
  report = unavailable(invocationId, preparationFailure);
441
- } else if (typeof drainedProse === "string" && drainedProse.trim() !== "") {
442
- report = { disposition: "advice", prose: drainedProse };
443
419
  } else {
444
- report = { disposition: "no-advice" };
420
+ const status = "status" in settlement ? settlement.status : void 0;
421
+ const picked = pickPreparedProse(preparedAdvice, status);
422
+ if (typeof picked === "string" && picked.trim() !== "") {
423
+ report = { disposition: "advice", prose: picked };
424
+ } else {
425
+ report = { disposition: "no-advice" };
426
+ }
445
427
  }
446
428
  }
447
429
  if (observedRoutePlaybookFailure !== void 0) {
@@ -470,8 +452,9 @@ function createNavigatorAttendance(options) {
470
452
  }
471
453
  preparation = void 0;
472
454
  sessionReady = void 0;
473
- preparedProse = void 0;
455
+ preparedAdvice = void 0;
474
456
  preparationFailure = void 0;
457
+ observedRoutePlaybookFailure = void 0;
475
458
  }
476
459
  }
477
460
  function registerNavigatorModelCommand(pi, path = navigatorModelSettingPath()) {
@@ -43,7 +43,6 @@ async function navigatorHostRunResumable(home, runId) {
43
43
  }
44
44
  function createNativeNavigatorSessionFactory(deps) {
45
45
  return async ({ context, tool }) => {
46
- let thinkingLevel;
47
46
  const entries = [];
48
47
  let providerFailure;
49
48
  let noReceipt;
@@ -71,6 +70,9 @@ function createNativeNavigatorSessionFactory(deps) {
71
70
  role: "navigator",
72
71
  argv: [text],
73
72
  cwd: context.cwd,
73
+ // Attendance prepare always asks for structured byStatus (#1160).
74
+ // Direct `ak-role navigator` never sets this flag.
75
+ navigatorByStatusPrepare: true,
74
76
  ...summonHome === void 0 ? {} : { home: summonHome },
75
77
  ...context.signal === void 0 ? {} : { signal: context.signal }
76
78
  };
@@ -129,17 +131,23 @@ function createNativeNavigatorSessionFactory(deps) {
129
131
  if (outcome.kind !== "accepted") {
130
132
  return;
131
133
  }
132
- const { navigatorProseFromUnknown } = await import("./package-contracts/navigator-output.js");
133
- const proseParts = [];
134
+ const {
135
+ byStatusToPlainObject,
136
+ mergePreparedAdvice,
137
+ preparedAdviceFromUnknown
138
+ } = await import("./package-contracts/navigator-output.js");
139
+ let prepared = void 0;
134
140
  for (const payload of outcome.payloads ?? []) {
135
- const prose = navigatorProseFromUnknown(payload);
136
- if (prose !== void 0) proseParts.push(prose);
141
+ prepared = mergePreparedAdvice(prepared, preparedAdviceFromUnknown(payload));
137
142
  }
138
- if (proseParts.length === 0) return;
143
+ if (prepared === void 0) return;
139
144
  if (disposed) return;
140
145
  await tool.execute(
141
146
  "navigator-public-prepare",
142
- { prose: proseParts.join("\n\n") },
147
+ {
148
+ ...prepared.prose === void 0 ? {} : { prose: prepared.prose },
149
+ ...prepared.byStatus.size === 0 ? {} : { byStatus: byStatusToPlainObject(prepared.byStatus) }
150
+ },
143
151
  void 0,
144
152
  void 0,
145
153
  context
@@ -168,16 +176,13 @@ function createNativeNavigatorSessionFactory(deps) {
168
176
  });
169
177
  },
170
178
  entries: () => entries,
171
- setModel: async (next, nextThinking) => {
172
- let nextParsed;
179
+ setModel: async (next) => {
173
180
  try {
174
- nextParsed = parseNavigatorModelSetting(next);
181
+ parseNavigatorModelSetting(next);
175
182
  } catch (error) {
176
183
  throw navigatorUnavailableError("model", error);
177
184
  }
178
- thinkingLevel = nextThinking ?? nextParsed.thinkingLevel;
179
185
  },
180
- getThinkingLevel: () => thinkingLevel,
181
186
  dispose: async () => {
182
187
  disposed = true;
183
188
  }
@@ -3,30 +3,59 @@ import { isRecord } from "../unknown-value.js";
3
3
  import { openToolObject } from "../open-tool-schema.js";
4
4
  import { withTerminatingOutputDeclarations } from "./terminating-infrastructure.js";
5
5
  const NAVIGATOR_OUTPUT_TOOL_NAME = "ak_navigator_output";
6
- const navigatorOutputSchema = withTerminatingOutputDeclarations(
7
- openToolObject(
8
- Type.Object({
9
- prose: Type.Unknown({
10
- description: "\u6E38\u5955\u4F7F\u6563\u6587\u5EFA\u8BAE\uFF0C\u539F\u6837\u5448\u73B0\u3002\u4E0D\u8981\u6C42 candidates/next \u7B49\u7ED3\u6784\u5316\u5B57\u6BB5\u3002"
11
- })
12
- })
13
- )
14
- );
6
+ const navigatorAdviceFields = {
7
+ prose: Type.Unknown({
8
+ description: "\u5355\u6761\u6563\u6587\u5EFA\u8BAE\u3002\u65E0\u72B6\u6001\u5206\u53C9\u65F6\u4F7F\u7528\uFF1B\u539F\u6837\u5448\u73B0\u3002"
9
+ }),
10
+ byStatus: Type.Unknown({
11
+ description: "\u6309\u4E3B\u8859\u95E8\u7ED3\u5C40 status \u9884\u5199\u7684\u6563\u6587\u5EFA\u8BAE\u3002\u952E\u4E3A status \u5B57\u9762\u91CF\uFF0C\u503C\u4E3A\u5EFA\u8BAE\u6B63\u6587\u3002\u7ED3\u7B97\u65F6\u4EE3\u7801\u53EA\u6309\u5B9E\u9645 status \u53D6\u5BF9\u5E94\u539F\u6587\uFF0C\u4E0D\u89E3\u6790\u5EFA\u8BAE\u8BED\u4E49\u3002"
12
+ })
13
+ };
14
+ const navigatorAdviceBodySchema = openToolObject(Type.Object(navigatorAdviceFields));
15
+ const navigatorOutputSchema = withTerminatingOutputDeclarations(navigatorAdviceBodySchema);
16
+ function nonEmptyProse(value) {
17
+ if (typeof value === "string") {
18
+ return value.trim() === "" ? void 0 : value;
19
+ }
20
+ if (value === void 0 || value === null) return void 0;
21
+ if (typeof value === "object") {
22
+ const text2 = JSON.stringify(value);
23
+ if (text2 === void 0 || text2.trim() === "" || text2 === "{}" || text2 === "[]") return void 0;
24
+ return text2;
25
+ }
26
+ const text = String(value);
27
+ return text.trim() === "" ? void 0 : text;
28
+ }
29
+ function setStatusProse(target, key, prose) {
30
+ const prior = target.get(key);
31
+ target.set(key, prior === void 0 ? prose : `${prior}
32
+
33
+ ${prose}`);
34
+ }
35
+ function byStatusFromUnknown(value) {
36
+ const out = /* @__PURE__ */ new Map();
37
+ if (!isRecord(value)) return out;
38
+ for (const [key, raw] of Object.entries(value)) {
39
+ const prose = nonEmptyProse(raw);
40
+ if (prose !== void 0) out.set(key, prose);
41
+ }
42
+ return out;
43
+ }
44
+ function byStatusToPlainObject(byStatus) {
45
+ return Object.fromEntries(byStatus);
46
+ }
15
47
  function projectLawfulNavigatorOutput(value) {
16
48
  if (value === void 0 || value === null) return void 0;
17
49
  if (typeof value === "string") return { prose: value };
18
50
  if (isRecord(value)) {
19
51
  if (typeof value.prose === "string") return { prose: value.prose };
20
52
  if (value.prose !== void 0 && value.prose !== null) {
21
- return { prose: typeof value.prose === "string" ? value.prose : String(value.prose) };
53
+ const serialized = nonEmptyProse(value.prose);
54
+ if (serialized !== void 0) return { prose: serialized };
22
55
  }
23
56
  const keys = Object.keys(value);
24
57
  if (keys.length === 0) return { prose: "" };
25
- try {
26
- return { prose: JSON.stringify(value) };
27
- } catch {
28
- return { prose: String(value) };
29
- }
58
+ return { prose: JSON.stringify(value) };
30
59
  }
31
60
  return { prose: String(value) };
32
61
  }
@@ -43,10 +72,67 @@ function navigatorProseFromUnknown(value) {
43
72
  const trimmed = projected.prose.trim();
44
73
  return trimmed === "" ? void 0 : projected.prose;
45
74
  }
75
+ function preparedAdviceFromUnknown(value) {
76
+ if (value === void 0 || value === null) return void 0;
77
+ if (typeof value === "string") {
78
+ const prose2 = nonEmptyProse(value);
79
+ return prose2 === void 0 ? void 0 : { byStatus: /* @__PURE__ */ new Map(), prose: prose2 };
80
+ }
81
+ if (!isRecord(value)) {
82
+ const prose2 = nonEmptyProse(value);
83
+ return prose2 === void 0 ? void 0 : { byStatus: /* @__PURE__ */ new Map(), prose: prose2 };
84
+ }
85
+ const byStatus = byStatusFromUnknown(value.byStatus);
86
+ const hasProseField = Object.prototype.hasOwnProperty.call(value, "prose");
87
+ const hasByStatusField = Object.prototype.hasOwnProperty.call(value, "byStatus");
88
+ const prose = nonEmptyProse(value.prose);
89
+ if (byStatus.size === 0 && prose === void 0) {
90
+ if (hasProseField || hasByStatusField) return void 0;
91
+ const keys = Object.keys(value);
92
+ if (keys.length === 0) return void 0;
93
+ const text = JSON.stringify(value);
94
+ return text.trim() === "" || text === "{}" ? void 0 : { byStatus: /* @__PURE__ */ new Map(), prose: text };
95
+ }
96
+ return {
97
+ byStatus,
98
+ ...prose === void 0 ? {} : { prose }
99
+ };
100
+ }
101
+ function mergePreparedAdvice(prior, next) {
102
+ if (prior === void 0) return next;
103
+ if (next === void 0) return prior;
104
+ const byStatus = new Map(prior.byStatus);
105
+ for (const [key, prose2] of next.byStatus) {
106
+ setStatusProse(byStatus, key, prose2);
107
+ }
108
+ const proseParts = [prior.prose, next.prose].filter((part) => typeof part === "string" && part.trim() !== "");
109
+ const prose = proseParts.length === 0 ? void 0 : proseParts.join("\n\n");
110
+ if (byStatus.size === 0 && prose === void 0) return void 0;
111
+ return {
112
+ byStatus,
113
+ ...prose === void 0 ? {} : { prose }
114
+ };
115
+ }
116
+ function pickPreparedProse(prepared, status) {
117
+ if (prepared === void 0) return void 0;
118
+ if (prepared.byStatus.size > 0) {
119
+ if (status === void 0) return void 0;
120
+ const hit = prepared.byStatus.get(status);
121
+ return typeof hit === "string" && hit.trim() !== "" ? hit : void 0;
122
+ }
123
+ const prose = prepared.prose;
124
+ return typeof prose === "string" && prose.trim() !== "" ? prose : void 0;
125
+ }
46
126
  export {
47
127
  NAVIGATOR_OUTPUT_TOOL_NAME,
128
+ byStatusToPlainObject,
129
+ mergePreparedAdvice,
130
+ navigatorAdviceBodySchema,
131
+ navigatorAdviceFields,
48
132
  navigatorOutputSchema,
49
133
  navigatorProseFromUnknown,
134
+ pickPreparedProse,
135
+ preparedAdviceFromUnknown,
50
136
  projectLawfulNavigatorOutput,
51
137
  validateRecordedNavigatorOutput
52
138
  };
@@ -9037,7 +9037,7 @@ var init_gatekeeper_output = __esm({
9037
9037
  });
9038
9038
 
9039
9039
  // src/package-contracts/navigator-output.ts
9040
- var NAVIGATOR_OUTPUT_TOOL_NAME, navigatorOutputSchema;
9040
+ var NAVIGATOR_OUTPUT_TOOL_NAME, navigatorAdviceFields, navigatorAdviceBodySchema, navigatorOutputSchema;
9041
9041
  var init_navigator_output = __esm({
9042
9042
  "src/package-contracts/navigator-output.ts"() {
9043
9043
  "use strict";
@@ -9046,15 +9046,16 @@ var init_navigator_output = __esm({
9046
9046
  init_open_tool_schema();
9047
9047
  init_terminating_infrastructure();
9048
9048
  NAVIGATOR_OUTPUT_TOOL_NAME = "ak_navigator_output";
9049
- navigatorOutputSchema = withTerminatingOutputDeclarations(
9050
- openToolObject(
9051
- typebox_exports.Object({
9052
- prose: typebox_exports.Unknown({
9053
- description: "\u6E38\u5955\u4F7F\u6563\u6587\u5EFA\u8BAE\uFF0C\u539F\u6837\u5448\u73B0\u3002\u4E0D\u8981\u6C42 candidates/next \u7B49\u7ED3\u6784\u5316\u5B57\u6BB5\u3002"
9054
- })
9055
- })
9056
- )
9057
- );
9049
+ navigatorAdviceFields = {
9050
+ prose: typebox_exports.Unknown({
9051
+ description: "\u5355\u6761\u6563\u6587\u5EFA\u8BAE\u3002\u65E0\u72B6\u6001\u5206\u53C9\u65F6\u4F7F\u7528\uFF1B\u539F\u6837\u5448\u73B0\u3002"
9052
+ }),
9053
+ byStatus: typebox_exports.Unknown({
9054
+ description: "\u6309\u4E3B\u8859\u95E8\u7ED3\u5C40 status \u9884\u5199\u7684\u6563\u6587\u5EFA\u8BAE\u3002\u952E\u4E3A status \u5B57\u9762\u91CF\uFF0C\u503C\u4E3A\u5EFA\u8BAE\u6B63\u6587\u3002\u7ED3\u7B97\u65F6\u4EE3\u7801\u53EA\u6309\u5B9E\u9645 status \u53D6\u5BF9\u5E94\u539F\u6587\uFF0C\u4E0D\u89E3\u6790\u5EFA\u8BAE\u8BED\u4E49\u3002"
9055
+ })
9056
+ };
9057
+ navigatorAdviceBodySchema = openToolObject(typebox_exports.Object(navigatorAdviceFields));
9058
+ navigatorOutputSchema = withTerminatingOutputDeclarations(navigatorAdviceBodySchema);
9058
9059
  }
9059
9060
  });
9060
9061
 
@@ -18939,6 +18940,7 @@ function projectRoleTurnRequest(admitted, roleDetails, options) {
18939
18940
  ...options.courtAttemptId === void 0 || options.courtAttemptId.length === 0 ? {} : { courtAttemptId: options.courtAttemptId },
18940
18941
  ...options.invocationScopeId === void 0 || options.invocationScopeId.length === 0 ? {} : { invocationScopeId: options.invocationScopeId },
18941
18942
  ...options.stationChild === void 0 ? {} : { stationChild: options.stationChild },
18943
+ ...options.navigatorByStatusPrepare === void 0 ? {} : { navigatorByStatusPrepare: options.navigatorByStatusPrepare },
18942
18944
  ...options.deliveryRequestLimit === void 0 ? {} : { deliveryRequestLimit: options.deliveryRequestLimit }
18943
18945
  };
18944
18946
  }
@@ -20576,6 +20578,7 @@ async function summonPublicRole(options) {
20576
20578
  // Nested court stations keep station-child semantics; dual-lens
20577
20579
  // ordinary Reviewer axes opt out (#946 / ADR 0082).
20578
20580
  ...options.stationChild === false ? {} : { stationChild: true },
20581
+ ...options.navigatorByStatusPrepare === true ? { navigatorByStatusPrepare: true } : {},
20579
20582
  // Forward composition-root adapters so nested stations (e.g.
20580
20583
  // secretariat → diarist) select the same faux/production table (#924).
20581
20584
  ...options.hostAdapters === void 0 ? {} : { hostAdapters: options.hostAdapters },
@@ -22768,6 +22771,9 @@ async function dispatchPostAdmissionTurn(input) {
22768
22771
  if (env.stationChild !== void 0) {
22769
22772
  turnRequest = { ...turnRequest, stationChild: env.stationChild };
22770
22773
  }
22774
+ if (env.navigatorByStatusPrepare === true) {
22775
+ turnRequest = { ...turnRequest, navigatorByStatusPrepare: true };
22776
+ }
22771
22777
  if (typeof env.host === "string" && env.host.trim() !== "") {
22772
22778
  turnRequest = { ...turnRequest, host: env.host.trim() };
22773
22779
  }
@@ -23026,6 +23032,7 @@ function resumeTurnRequestProjectionOptions(admitted, request, env, summonsPrepa
23026
23032
  prompt
23027
23033
  },
23028
23034
  ...env.stationChild === void 0 ? {} : { stationChild: env.stationChild },
23035
+ ...env.navigatorByStatusPrepare === true ? { navigatorByStatusPrepare: true } : {},
23029
23036
  // #1132: one configured ceiling, already resolved by the caller (#422).
23030
23037
  deliveryRequestLimit: deliveryLimitFromConfig(env.autoResumeLimit)
23031
23038
  };
@@ -23038,6 +23045,7 @@ function roleTurnOptions(env, admitted, continuation) {
23038
23045
  ...correlationId === void 0 || correlationId.trim() === "" ? {} : { correlationId },
23039
23046
  continuation,
23040
23047
  ...env.stationChild === void 0 ? {} : { stationChild: env.stationChild },
23048
+ ...env.navigatorByStatusPrepare === true ? { navigatorByStatusPrepare: true } : {},
23041
23049
  // #1132: one configured ceiling, already resolved by the caller (#422).
23042
23050
  deliveryRequestLimit: deliveryLimitFromConfig(env.autoResumeLimit)
23043
23051
  };
@@ -812,6 +812,9 @@ export async function dispatchPostAdmissionTurn(input) {
812
812
  if (env.stationChild !== undefined) {
813
813
  turnRequest = { ...turnRequest, stationChild: env.stationChild };
814
814
  }
815
+ if (env.navigatorByStatusPrepare === true) {
816
+ turnRequest = { ...turnRequest, navigatorByStatusPrepare: true };
817
+ }
815
818
  // Selected host axis rides the shared Host envelope for in-turn tools
816
819
  // (detour usage ledger) — never a pre-spawn current.json reread.
817
820
  if (typeof env.host === "string" && env.host.trim() !== "") {
@@ -1115,6 +1118,9 @@ export function resumeTurnRequestProjectionOptions(admitted, request, env, summo
1115
1118
  prompt,
1116
1119
  },
1117
1120
  ...(env.stationChild === undefined ? {} : { stationChild: env.stationChild }),
1121
+ ...(env.navigatorByStatusPrepare === true
1122
+ ? { navigatorByStatusPrepare: true }
1123
+ : {}),
1118
1124
  // #1132: one configured ceiling, already resolved by the caller (#422).
1119
1125
  deliveryRequestLimit: deliveryLimitFromConfig(env.autoResumeLimit),
1120
1126
  };
@@ -1130,6 +1136,9 @@ export function roleTurnOptions(env, admitted, continuation) {
1130
1136
  : { correlationId }),
1131
1137
  continuation,
1132
1138
  ...(env.stationChild === undefined ? {} : { stationChild: env.stationChild }),
1139
+ ...(env.navigatorByStatusPrepare === true
1140
+ ? { navigatorByStatusPrepare: true }
1141
+ : {}),
1133
1142
  // #1132: one configured ceiling, already resolved by the caller (#422).
1134
1143
  deliveryRequestLimit: deliveryLimitFromConfig(env.autoResumeLimit),
1135
1144
  };
@@ -45,6 +45,9 @@ export function projectRoleTurnRequest(admitted, roleDetails, options) {
45
45
  ? {}
46
46
  : { invocationScopeId: options.invocationScopeId }),
47
47
  ...(options.stationChild === undefined ? {} : { stationChild: options.stationChild }),
48
+ ...(options.navigatorByStatusPrepare === undefined
49
+ ? {}
50
+ : { navigatorByStatusPrepare: options.navigatorByStatusPrepare }),
48
51
  ...(options.deliveryRequestLimit === undefined
49
52
  ? {}
50
53
  : { deliveryRequestLimit: options.deliveryRequestLimit }),
@@ -187,6 +187,7 @@ async function summonPublicRole(options) {
187
187
  // Nested court stations keep station-child semantics; dual-lens
188
188
  // ordinary Reviewer axes opt out (#946 / ADR 0082).
189
189
  ...options.stationChild === false ? {} : { stationChild: true },
190
+ ...options.navigatorByStatusPrepare === true ? { navigatorByStatusPrepare: true } : {},
190
191
  // Forward composition-root adapters so nested stations (e.g.
191
192
  // secretariat → diarist) select the same faux/production table (#924).
192
193
  ...options.hostAdapters === void 0 ? {} : { hostAdapters: options.hostAdapters },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akagilnc/pi-workflow-roles",
3
- "version": "0.1.5663",
3
+ "version": "0.1.5671",
4
4
  "description": "Soul-bound workflow roles for Pi",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -1,9 +1,9 @@
1
- ## 到场阶段(#959 / ADR 0073 / #1021)
1
+ ## 到场阶段(#1160 / ADR 0073)
2
2
 
3
3
  阶段行为说明住本手册。代码不写阶段句,也不把本手册再拼进用户消息。
4
4
 
5
- - **待命**:父衙门进行中时,代码只记到场,不调用模型。这一轮没有输出。
6
- - **结算**:父衙门结算送达后,用户消息只有该次 typed 三态及指针。Soul 与本手册已在系统提示里。根据这份结算和本手册给出下一步建议。
5
+ - **备答**:父衙门一开始即并行准备。自行判断当前进度——有票时读票卷宗里实际发生的角色运行,必要时看票面;不把过去建议或建议送达当作已经走过的站。按主衙门可能的结局 status 预写建议,经 `byStatus` 提交(键为 status 字面量,值为建议正文)。无状态分叉时可用单条 `prose`。
6
+ - **取用**:父衙门交卷后,代码只按实际 status 取对应原文,不再起模型轮次。没有对应建议则如实无建议。主衙门结束后最多再等十秒;到时停止等待,不扣押主结果。
7
7
 
8
8
  ## 宿主轴(与角色命令面)
9
9
 
@@ -433,7 +433,8 @@ export function codexTurnArgs(options: {
433
433
  /**
434
434
  * Absolute path for the native `--output-schema` flag.
435
435
  * File holds the Codex-strict transport projection of the open declaration (#1148).
436
- * Optional for prose-exit seats (#959 navigator) so agent_message stays free text.
436
+ * Optional: omit for direct navigator prose exit (#959); attendance byStatus
437
+ * prepare mounts it via RoleTurnRequest.navigatorByStatusPrepare (#1160).
437
438
  */
438
439
  readonly outputSchemaPath?: string;
439
440
  readonly mcpServers: readonly Readonly<Record<string, unknown>>[];