@akagilnc/pi-workflow-roles 0.1.4586 → 0.1.4620

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.
Files changed (47) hide show
  1. package/README.md +2 -2
  2. package/README.zh-CN.md +2 -2
  3. package/dist/acp-host/production-host.js +951 -497
  4. package/dist/archivist-record-topology.js +27 -35
  5. package/dist/headless-host/description.js +7 -4
  6. package/dist/headless-host/production-host.js +783 -393
  7. package/dist/migrate-book-topology.js +3 -6
  8. package/dist/navigator-attendance.js +146 -241
  9. package/dist/navigator-public-session.js +81 -15
  10. package/dist/package-contracts/navigator-output.js +30 -12
  11. package/dist/public-cli/judge-run.js +2 -2
  12. package/dist/public-cli/main.js +69 -94
  13. package/dist/public-cli/option-definitions.js +1 -1
  14. package/dist/public-cli/post-admission.js +2 -2
  15. package/dist/public-cli/run-lifecycle.js +29 -7
  16. package/dist/public-cli/settlement.js +46 -32
  17. package/dist/public-cli/terminal.js +8 -27
  18. package/dist/public-role-summons.js +22 -4
  19. package/dist/submission-ledger.js +56 -23
  20. package/package.json +1 -1
  21. package/resources/836-deleted-machine-instruction-inventory.md +2 -0
  22. package/resources/navigator-route-playbook.md +9 -0
  23. package/scripts/build-package.mjs +6 -1
  24. package/src/acp-host/role-turn-host.ts +129 -13
  25. package/src/headless-host/description.ts +17 -7
  26. package/src/headless-host/role-turn-host.ts +42 -11
  27. package/src/navigator-attendance.ts +290 -425
  28. package/src/navigator-public-session.ts +126 -25
  29. package/src/navigator-role.ts +2 -2
  30. package/src/package-contracts/navigator-output.ts +41 -25
  31. package/src/public-cli/coder-run.ts +2 -2
  32. package/src/public-cli/fixer-run.ts +2 -2
  33. package/src/public-cli/judge-run.ts +2 -2
  34. package/src/public-cli/merger-run.ts +2 -2
  35. package/src/public-cli/option-definitions.ts +1 -1
  36. package/src/public-cli/post-admission.ts +2 -1
  37. package/src/public-cli/run-lifecycle.ts +37 -7
  38. package/src/public-cli/settlement.ts +42 -33
  39. package/src/public-cli/terminal.ts +12 -37
  40. package/src/public-role-summons.ts +34 -5
  41. package/src/role-envelope.ts +89 -4
  42. package/src/role-runtime.ts +74 -14
  43. package/src/submission-ledger.ts +63 -21
  44. package/dist/public-cli/command-renderer.js +0 -5
  45. package/dist/public-command-renderer.js +0 -29
  46. package/src/public-cli/command-renderer.ts +0 -9
  47. package/src/public-command-renderer.ts +0 -55
@@ -1,3 +1,4 @@
1
+ import { basename } from "node:path";
1
2
  import { sitianReport } from "./sitian-facade.js";
2
3
  import {
3
4
  NavigatorUnavailableError,
@@ -7,6 +8,7 @@ import {
7
8
  parseNavigatorModelSetting
8
9
  } from "./navigator-session-contracts.js";
9
10
  import { runDirectoryFromHostContext } from "./host-contracts.js";
11
+ import { CliUsageError } from "./public-cli/cli-errors.js";
10
12
  async function resolveNavigatorLedgerHome(context) {
11
13
  const { tryHomeFromAkRolesPath } = await import("./activation-ledger-topology.js");
12
14
  const runDirectory = runDirectoryFromHostContext(context);
@@ -21,7 +23,42 @@ async function resolveNavigatorLedgerHome(context) {
21
23
  }
22
24
  return void 0;
23
25
  }
24
- function createNativeNavigatorSessionFactory() {
26
+ const NAVIGATOR_HOST_RUN_POINTER_ENTRY = "ak-navigator-host-run";
27
+ function exactRecord(value) {
28
+ return typeof value === "object" && value !== null && !Array.isArray(value);
29
+ }
30
+ function runIdFromNavigatorDirectory(runDirectory) {
31
+ const entry = basename(runDirectory);
32
+ const suffix = "@navigator";
33
+ if (!entry.endsWith(suffix)) return void 0;
34
+ const runId = entry.slice(0, entry.length - suffix.length);
35
+ return runId.length > 0 ? runId : void 0;
36
+ }
37
+ function readNavigatorHostRunPointer(entries) {
38
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
39
+ const entry = entries[index];
40
+ if (!exactRecord(entry)) continue;
41
+ if (entry.type === "custom" && entry.customType === NAVIGATOR_HOST_RUN_POINTER_ENTRY) {
42
+ const data = entry.data;
43
+ if (exactRecord(data) && typeof data.runId === "string" && data.runId.trim() !== "") {
44
+ return data.runId.trim();
45
+ }
46
+ }
47
+ }
48
+ return void 0;
49
+ }
50
+ async function navigatorHostRunResumable(home, runId) {
51
+ const { piDurablePrincipalAuthority } = await import("./pi/durable-principal.js");
52
+ const { loadResumableInstructionSeatRun } = await import("./public-cli/run-lifecycle.js");
53
+ try {
54
+ const loaded = await loadResumableInstructionSeatRun(home, runId, piDurablePrincipalAuthority);
55
+ return loaded.admitted.role === "navigator";
56
+ } catch (error) {
57
+ if (error instanceof CliUsageError) return false;
58
+ throw error;
59
+ }
60
+ }
61
+ function createNativeNavigatorSessionFactory(deps) {
25
62
  return async ({ context, subject, tool }) => {
26
63
  let thinkingLevel;
27
64
  const { createRecordSession, NAVIGATOR_RECORD_KIND } = await import("./archivist-record-entry.js");
@@ -37,6 +74,11 @@ function createNativeNavigatorSessionFactory() {
37
74
  let noReceipt;
38
75
  let disposed = false;
39
76
  let inFlightPrompt;
77
+ let hostRunId = readNavigatorHostRunPointer(sessionManager.getEntries());
78
+ const summon = deps?.summonPublicRole ?? (async (options) => {
79
+ const { summonPublicRole } = await import("./public-role-summons.js");
80
+ return summonPublicRole(options);
81
+ });
40
82
  return {
41
83
  prompt: async (text) => {
42
84
  if (disposed) {
@@ -46,14 +88,24 @@ function createNativeNavigatorSessionFactory() {
46
88
  noReceipt = void 0;
47
89
  const run = (async () => {
48
90
  try {
49
- const { summonPublicRole } = await import("./public-role-summons.js");
50
91
  const summonHome = await resolveNavigatorLedgerHome(context);
51
- const summoned = await summonPublicRole({
92
+ const resumeRunId = hostRunId;
93
+ const baseSummon = {
52
94
  role: "navigator",
53
95
  argv: [text],
54
96
  cwd: context.cwd,
55
97
  ...summonHome === void 0 ? {} : { home: summonHome }
56
- });
98
+ };
99
+ const resumable = deps?.hostRunResumable ?? navigatorHostRunResumable;
100
+ let summoned;
101
+ if (resumeRunId === void 0 || summonHome === void 0) {
102
+ summoned = await summon(baseSummon);
103
+ } else if (await resumable(summonHome, resumeRunId)) {
104
+ summoned = await summon({ ...baseSummon, resumeRunId });
105
+ } else {
106
+ hostRunId = void 0;
107
+ summoned = await summon(baseSummon);
108
+ }
57
109
  const outcome = summoned.terminal?.roleOutcome;
58
110
  if (outcome === void 0) {
59
111
  const detail = summoned.stderr?.trim() || `exit ${summoned.exitCode}`;
@@ -76,21 +128,31 @@ function createNativeNavigatorSessionFactory() {
76
128
  noReceipt = outcome;
77
129
  return;
78
130
  }
131
+ const runDirectory = summoned.runDirectory ?? (typeof summoned.admitted?.runDirectory === "string" ? summoned.admitted.runDirectory : void 0);
132
+ if (typeof runDirectory === "string" && runDirectory.trim() !== "") {
133
+ const nextRunId = runIdFromNavigatorDirectory(runDirectory);
134
+ if (nextRunId !== void 0) {
135
+ hostRunId = nextRunId;
136
+ sessionManager.appendCustomEntry(NAVIGATOR_HOST_RUN_POINTER_ENTRY, { runId: nextRunId });
137
+ }
138
+ }
79
139
  if (outcome.kind !== "accepted") {
80
140
  return;
81
141
  }
142
+ const { navigatorProseFromUnknown } = await import("./package-contracts/navigator-output.js");
143
+ const proseParts = [];
82
144
  for (const payload of outcome.payloads ?? []) {
83
- if (typeof payload !== "object" || payload === null || Array.isArray(payload)) continue;
84
- const candidates = payload.candidates;
85
- if (!Array.isArray(candidates)) continue;
86
- await tool.execute(
87
- "navigator-public-prepare",
88
- { candidates },
89
- void 0,
90
- void 0,
91
- context
92
- );
145
+ const prose = navigatorProseFromUnknown(payload);
146
+ if (prose !== void 0) proseParts.push(prose);
93
147
  }
148
+ if (proseParts.length === 0) return;
149
+ await tool.execute(
150
+ "navigator-public-prepare",
151
+ { prose: proseParts.join("\n\n") },
152
+ void 0,
153
+ void 0,
154
+ context
155
+ );
94
156
  } catch (error) {
95
157
  if (error instanceof NavigatorUnavailableError) throw error;
96
158
  const fact = navigatorProviderFailureFromError(error);
@@ -142,5 +204,9 @@ function createNativeNavigatorSessionFactory() {
142
204
  };
143
205
  }
144
206
  export {
145
- createNativeNavigatorSessionFactory
207
+ NAVIGATOR_HOST_RUN_POINTER_ENTRY,
208
+ createNativeNavigatorSessionFactory,
209
+ navigatorHostRunResumable,
210
+ readNavigatorHostRunPointer,
211
+ runIdFromNavigatorDirectory
146
212
  };
@@ -6,31 +6,49 @@ const NAVIGATOR_ACCEPTED_TEXT = "\u6E38\u5955\u4F7F\u5EFA\u8BAE\u5DF2\u53D7\u740
6
6
  const navigatorOutputSchema = withTerminatingOutputDeclarations(
7
7
  openToolObject(
8
8
  Type.Object({
9
- status: Type.Unknown({
10
- description: "advice \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8"
11
- }),
12
- candidates: Type.Unknown({
13
- description: "\u6392\u597D\u5E8F\u7684\u8DEF\u7EBF\u5EFA\u8BAE\u6570\u7EC4\uFF0C\u5143\u7D20\u542B next/phase/reason \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8"
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\u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8"
14
11
  })
15
12
  })
16
13
  )
17
14
  );
18
- function isRecord(value) {
19
- return typeof value === "object" && value !== null && !Array.isArray(value);
20
- }
21
15
  function projectLawfulNavigatorOutput(value) {
22
- return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
16
+ if (value === void 0 || value === null) return void 0;
17
+ if (typeof value === "string") return { prose: value };
18
+ if (typeof value === "object" && !Array.isArray(value)) {
19
+ const record = value;
20
+ if (typeof record.prose === "string") return { prose: record.prose };
21
+ if (record.prose !== void 0 && record.prose !== null) {
22
+ return { prose: typeof record.prose === "string" ? record.prose : String(record.prose) };
23
+ }
24
+ const keys = Object.keys(record);
25
+ if (keys.length === 0) return { prose: "" };
26
+ try {
27
+ return { prose: JSON.stringify(record) };
28
+ } catch {
29
+ return { prose: String(record) };
30
+ }
31
+ }
32
+ return { prose: String(value) };
23
33
  }
24
34
  function validateRecordedNavigatorOutput(value) {
25
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
26
- throw new Error("Navigator output is not an object");
35
+ const projected = projectLawfulNavigatorOutput(value);
36
+ if (projected === void 0) {
37
+ throw new Error("Navigator output is empty");
27
38
  }
28
- return value;
39
+ return projected;
40
+ }
41
+ function navigatorProseFromUnknown(value) {
42
+ const projected = projectLawfulNavigatorOutput(value);
43
+ if (projected === void 0) return void 0;
44
+ const trimmed = projected.prose.trim();
45
+ return trimmed === "" ? void 0 : projected.prose;
29
46
  }
30
47
  export {
31
48
  NAVIGATOR_ACCEPTED_TEXT,
32
49
  NAVIGATOR_OUTPUT_TOOL_NAME,
33
50
  navigatorOutputSchema,
51
+ navigatorProseFromUnknown,
34
52
  projectLawfulNavigatorOutput,
35
53
  validateRecordedNavigatorOutput
36
54
  };
@@ -1,7 +1,7 @@
1
1
  import { engineSessionMaterialFromOptions, pickEngineAxis } from "../package-resources/engine-material.js";
2
2
  import { CliUsageError } from "./cli-errors.js";
3
3
  import { admitJudgeInvocation, buildJudgeTransportPrompt, } from "./invocation.js";
4
- import { loadResumableJudgeRun, markRunAdmitted, buildResumeContinuationPrompt, } from "./run-lifecycle.js";
4
+ import { loadResumableJudgeRun, markRunAdmitted, buildAutoResumeContinuationPrompt, } from "./run-lifecycle.js";
5
5
  import { presentStructuralRejection, readEngineDetourInfrastructureFailure, trySettleJudgeTerminalResult, } from "./settlement.js";
6
6
  import { projectRoleTurnRequest, } from "./turn-request.js";
7
7
  import { runPostAdmissionResumable, runPostAdmissionSeatResume, resumeTurnRequestProjectionOptions, } from "./post-admission.js";
@@ -86,7 +86,7 @@ export async function runPublicJudge(argv, env, io, parseJudgeArgv) {
86
86
  : { correlationId: admitted.correlationId ?? env.correlationId }),
87
87
  continuation: {
88
88
  kind: "resume",
89
- prompt: buildResumeContinuationPrompt({
89
+ prompt: buildAutoResumeContinuationPrompt({
90
90
  packageRoot: env.packageRoot,
91
91
  ...pickEngineAxis(env),
92
92
  }),
@@ -8548,11 +8548,8 @@ var init_navigator_output = __esm({
8548
8548
  navigatorOutputSchema = withTerminatingOutputDeclarations(
8549
8549
  openToolObject(
8550
8550
  typebox_exports.Object({
8551
- status: typebox_exports.Unknown({
8552
- description: "advice \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8"
8553
- }),
8554
- candidates: typebox_exports.Unknown({
8555
- description: "\u6392\u597D\u5E8F\u7684\u8DEF\u7EBF\u5EFA\u8BAE\u6570\u7EC4\uFF0C\u5143\u7D20\u542B next/phase/reason \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8"
8551
+ prose: typebox_exports.Unknown({
8552
+ 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\u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8"
8556
8553
  })
8557
8554
  })
8558
8555
  )
@@ -18165,6 +18162,15 @@ function buildResumeContinuationPrompt(options) {
18165
18162
  })
18166
18163
  );
18167
18164
  }
18165
+ function buildAutoResumeContinuationPrompt(options) {
18166
+ return selectResumeContinuationPrompt(
18167
+ RESUME_TRANSPORT_ENVELOPE,
18168
+ engineSessionMaterialFromOptions({
18169
+ packageRoot: options.packageRoot,
18170
+ ...pickEngineAxis(options)
18171
+ })
18172
+ );
18173
+ }
18168
18174
  function isV1ResumableProvider(provider) {
18169
18175
  return V1_RESUMABLE_PROVIDERS.includes(provider);
18170
18176
  }
@@ -19397,7 +19403,7 @@ var init_run_lifecycle = __esm({
19397
19403
  init_invocation();
19398
19404
  V1_RESUMABLE_PROVIDERS = ["openai-codex", "xai"];
19399
19405
  AUTO_RESUME_LIMIT = 2;
19400
- RESUME_TRANSPORT_ENVELOPE = "[ak-role:resume-continue]";
19406
+ RESUME_TRANSPORT_ENVELOPE = "\u7EE7\u7EED\u3002";
19401
19407
  RUN_STATE_FILE = "run-state.json";
19402
19408
  WRITER_LOCK_FILE = "writer.lock";
19403
19409
  RunWriterLeaseHeldError = class extends Error {
@@ -20512,7 +20518,7 @@ var init_option_definitions = __esm({
20512
20518
  },
20513
20519
  navigator: {
20514
20520
  command: "navigator",
20515
- summary: "Direct Navigator (\u6E38\u5955\u4F7F) route advice: ordered next-role candidates.",
20521
+ summary: "Direct Navigator (\u6E38\u5955\u4F7F) free-form prose route advice.",
20516
20522
  usage: ["ak-role navigator [options] [instruction]"],
20517
20523
  examples: [
20518
20524
  'ak-role navigator "\u521A\u5B8C\u6210 coder apply \u6536\u655B\uFF0C\u4E0B\u4E00\u6B65\uFF1F"'
@@ -24882,44 +24888,6 @@ var init_receipt_delivery_policy = __esm({
24882
24888
  }
24883
24889
  });
24884
24890
 
24885
- // src/public-command-renderer.ts
24886
- function isPublicCallableRole2(role) {
24887
- return PUBLIC_CALLABLE_ROLES3.has(role);
24888
- }
24889
- function renderPublicAkRoleCommand(target) {
24890
- if (!isPublicCallableRole2(target.role)) return void 0;
24891
- const role = target.role;
24892
- const metadata = packagedRoleMetadata(role);
24893
- if (metadata !== void 0 && "bareCommand" in metadata && metadata.bareCommand === false) {
24894
- return void 0;
24895
- }
24896
- if (target.phase === null || target.phase === void 0) {
24897
- return `ak-role ${role}`;
24898
- }
24899
- if (role === "coder" || role === "fixer") {
24900
- return `ak-role ${role} ${target.phase}`;
24901
- }
24902
- return `ak-role ${role}`;
24903
- }
24904
- var PUBLIC_CALLABLE_ROLES3;
24905
- var init_public_command_renderer = __esm({
24906
- "src/public-command-renderer.ts"() {
24907
- "use strict";
24908
- init_packaged_role_registry();
24909
- PUBLIC_CALLABLE_ROLES3 = new Set(
24910
- PACKAGED_ROLE_REGISTRY.map((entry) => entry.role)
24911
- );
24912
- }
24913
- });
24914
-
24915
- // src/public-cli/command-renderer.ts
24916
- var init_command_renderer = __esm({
24917
- "src/public-cli/command-renderer.ts"() {
24918
- "use strict";
24919
- init_public_command_renderer();
24920
- }
24921
- });
24922
-
24923
24891
  // src/public-cli/terminal.ts
24924
24892
  function encodeTerminalField(value) {
24925
24893
  return JSON.stringify(value);
@@ -24930,14 +24898,10 @@ function isLawfulTypedTerminalOutcome(outcome) {
24930
24898
  function exitCodeForTerminalOutcome(outcome) {
24931
24899
  return isLawfulTypedTerminalOutcome(outcome) ? 0 : 1;
24932
24900
  }
24933
- function recommendationNavigatorFact(input) {
24934
- const command = typeof input.modelCommand === "string" && input.modelCommand.trim() !== "" ? input.modelCommand : isPublicCallableRole2(input.next.role) ? renderPublicAkRoleCommand(input.next) : void 0;
24901
+ function adviceNavigatorFact(input) {
24935
24902
  return {
24936
- disposition: "recommendation",
24937
- next: input.next,
24938
- reason: input.reason,
24939
- ...command === void 0 ? {} : { command },
24940
- ...input.route === void 0 ? {} : { route: input.route },
24903
+ disposition: "advice",
24904
+ prose: input.prose,
24941
24905
  ...input.advisoryDiagnostic === void 0 ? {} : { advisoryDiagnostic: input.advisoryDiagnostic }
24942
24906
  };
24943
24907
  }
@@ -24965,14 +24929,8 @@ function formatTerminalResult(result2) {
24965
24929
  if (result2.navigator.advisoryDiagnostic !== void 0) {
24966
24930
  lines.push(`navigator-advisory ${encodeTerminalField(result2.navigator.advisoryDiagnostic)}`);
24967
24931
  }
24968
- if (result2.navigator.disposition === "recommendation") {
24969
- lines.push(
24970
- `next ${result2.navigator.next.role} ${result2.navigator.next.phase ?? "none"}`
24971
- );
24972
- lines.push(`reason ${encodeTerminalField(result2.navigator.reason)}`);
24973
- if (result2.navigator.command !== void 0) {
24974
- lines.push(`command ${encodeTerminalField(result2.navigator.command)}`);
24975
- }
24932
+ if (result2.navigator.disposition === "advice") {
24933
+ lines.push(`prose ${encodeTerminalField(result2.navigator.prose)}`);
24976
24934
  } else if (result2.navigator.disposition === "unavailable") {
24977
24935
  lines.push(
24978
24936
  `unavailable ${result2.navigator.source} ${encodeTerminalField(result2.navigator.reason)}`
@@ -25021,7 +24979,6 @@ function formatTerminalResult(result2) {
25021
24979
  var init_terminal = __esm({
25022
24980
  "src/public-cli/terminal.ts"() {
25023
24981
  "use strict";
25024
- init_command_renderer();
25025
24982
  }
25026
24983
  });
25027
24984
 
@@ -26001,10 +25958,6 @@ async function appendRunAttemptHistory(source, outcome) {
26001
25958
  } catch {
26002
25959
  }
26003
25960
  }
26004
- function navigatorPhaseValue(value) {
26005
- if (value === "plan" || value === "apply") return value;
26006
- return null;
26007
- }
26008
25961
  function navigatorAttendanceCorrelatedWithBoundMarker(details, attendanceIndex, terminalIndex, marker) {
26009
25962
  if (attendanceIndex <= terminalIndex) return false;
26010
25963
  if (details.invocationId !== marker.invocationId) return false;
@@ -26013,29 +25966,33 @@ function navigatorAttendanceCorrelatedWithBoundMarker(details, attendanceIndex,
26013
25966
  function parseNavigatorAttendanceDetails(details) {
26014
25967
  const disposition = details.disposition;
26015
25968
  const advisoryDiagnostic = typeof details.routePlaybookReadFailure === "string" ? { advisoryDiagnostic: details.routePlaybookReadFailure } : {};
26016
- if (disposition === "recommendation") {
26017
- const next = details.next;
26018
- if (!isRecord10(next) || typeof next.role !== "string") {
25969
+ if (disposition === "advice" || disposition === "recommendation") {
25970
+ let prose;
25971
+ if (typeof details.prose === "string" && details.prose.trim() !== "") {
25972
+ prose = details.prose;
25973
+ } else {
25974
+ const next = isRecord10(details.next) && typeof details.next.role === "string" ? details.next.role : void 0;
25975
+ const reason = typeof details.reason === "string" && details.reason.trim() !== "" ? details.reason : void 0;
25976
+ const command = typeof details.command === "string" && details.command.trim() !== "" ? details.command : void 0;
25977
+ if (reason !== void 0 && next !== void 0) {
25978
+ prose = `${reason}\uFF08\u4E0B\u4E00\u6B65\uFF1A${next}\uFF09`;
25979
+ } else if (reason !== void 0) {
25980
+ prose = reason;
25981
+ } else if (next !== void 0) {
25982
+ prose = `\u4E0B\u4E00\u6B65\uFF1A${next}`;
25983
+ } else if (command !== void 0) {
25984
+ prose = command;
25985
+ }
25986
+ }
25987
+ if (prose === void 0 || prose.trim() === "") {
26019
25988
  return {
26020
- disposition: "unavailable",
26021
- source: "unknown",
26022
- reason: "navigator recommendation missing typed next role"
25989
+ disposition: "no-advice",
25990
+ ...advisoryDiagnostic
26023
25991
  };
26024
25992
  }
26025
- const reason = typeof details.reason === "string" ? details.reason : "";
26026
- const route = Array.isArray(details.route) ? details.route.filter(isRecord10).map((target) => ({
26027
- role: String(target.role),
26028
- phase: navigatorPhaseValue(target.phase)
26029
- })) : void 0;
26030
- return recommendationNavigatorFact({
26031
- ...advisoryDiagnostic,
26032
- next: {
26033
- role: next.role,
26034
- phase: navigatorPhaseValue(next.phase)
26035
- },
26036
- reason,
26037
- ...route === void 0 ? {} : { route },
26038
- ...typeof details.command === "string" ? { modelCommand: details.command } : {}
25993
+ return adviceNavigatorFact({
25994
+ prose,
25995
+ ...advisoryDiagnostic
26039
25996
  });
26040
25997
  }
26041
25998
  if (disposition === "unavailable") {
@@ -28997,7 +28954,7 @@ async function runPostAdmissionOneShot(input) {
28997
28954
  ...input.request,
28998
28955
  continuation: {
28999
28956
  kind: "resume",
29000
- prompt: buildResumeContinuationPrompt({
28957
+ prompt: buildAutoResumeContinuationPrompt({
29001
28958
  packageRoot: input.env.packageRoot,
29002
28959
  ...pickEngineAxis({
29003
28960
  engine: input.effectiveEngine ?? input.env.engine,
@@ -29254,7 +29211,7 @@ async function runPublicCoder(argv, env, io, parseCoderArgv2) {
29254
29211
  ...admitted.correlationId === void 0 && env.correlationId === void 0 ? {} : { correlationId: admitted.correlationId ?? env.correlationId },
29255
29212
  continuation: {
29256
29213
  kind: "resume",
29257
- prompt: buildResumeContinuationPrompt({
29214
+ prompt: buildAutoResumeContinuationPrompt({
29258
29215
  packageRoot: env.packageRoot,
29259
29216
  ...pickEngineAxis(env)
29260
29217
  })
@@ -30138,7 +30095,7 @@ async function runPublicJudge(argv, env, io, parseJudgeArgv2) {
30138
30095
  ...admitted.correlationId === void 0 && env.correlationId === void 0 ? {} : { correlationId: admitted.correlationId ?? env.correlationId },
30139
30096
  continuation: {
30140
30097
  kind: "resume",
30141
- prompt: buildResumeContinuationPrompt({
30098
+ prompt: buildAutoResumeContinuationPrompt({
30142
30099
  packageRoot: env.packageRoot,
30143
30100
  ...pickEngineAxis(env)
30144
30101
  })
@@ -31047,14 +31004,32 @@ async function summonPublicRole(options) {
31047
31004
  case "navigator":
31048
31005
  case "gatekeeper": {
31049
31006
  const seat2 = options.role;
31050
- const [{ runPublicInstructionSeat: runPublicInstructionSeat2 }, invocation] = await Promise.all([
31007
+ const [{ runPublicInstructionSeat: runPublicInstructionSeat2, runPublicInstructionSeatResume: runPublicInstructionSeatResume2 }, invocation] = await Promise.all([
31051
31008
  Promise.resolve().then(() => (init_instruction_seat_run(), instruction_seat_run_exports)),
31052
31009
  Promise.resolve().then(() => (init_invocation(), invocation_exports))
31053
31010
  ]);
31054
31011
  const parse = seat2 === "auditor" ? invocation.parseAuditorArgv : seat2 === "navigator" ? invocation.parseNavigatorArgv : invocation.parseGatekeeperArgv;
31055
- const stepped = await runPrepared(parse, (env, once) => runPublicInstructionSeat2(options.argv, env, io, seat2, once));
31056
- if ("fail" in stepped) return stepped.fail;
31057
- result2 = stepped.ok;
31012
+ const resumeRunId = typeof options.resumeRunId === "string" && options.resumeRunId.trim() !== "" ? options.resumeRunId.trim() : void 0;
31013
+ if (resumeRunId !== void 0) {
31014
+ const instruction = options.argv[0] ?? "";
31015
+ const stepped = await runPrepared(parse, (env) => runPublicInstructionSeatResume2(
31016
+ {
31017
+ runId: resumeRunId,
31018
+ summons: {
31019
+ instruction,
31020
+ instructionEmpty: instruction.trim() === ""
31021
+ }
31022
+ },
31023
+ env,
31024
+ io
31025
+ ));
31026
+ if ("fail" in stepped) return stepped.fail;
31027
+ result2 = stepped.ok;
31028
+ } else {
31029
+ const stepped = await runPrepared(parse, (env, once) => runPublicInstructionSeat2(options.argv, env, io, seat2, once));
31030
+ if ("fail" in stepped) return stepped.fail;
31031
+ result2 = stepped.ok;
31032
+ }
31058
31033
  break;
31059
31034
  }
31060
31035
  case "judge": {
@@ -32340,7 +32315,7 @@ async function runPublicFixer(argv, env, io, parseFixerArgv2) {
32340
32315
  ...admitted.correlationId === void 0 && env.correlationId === void 0 ? {} : { correlationId: admitted.correlationId ?? env.correlationId },
32341
32316
  continuation: {
32342
32317
  kind: "resume",
32343
- prompt: buildResumeContinuationPrompt({
32318
+ prompt: buildAutoResumeContinuationPrompt({
32344
32319
  packageRoot: env.packageRoot,
32345
32320
  ...pickEngineAxis(env)
32346
32321
  })
@@ -32519,7 +32494,7 @@ async function runPublicMerger(argv, env, io, parseMergerArgv2) {
32519
32494
  ...admitted.correlationId === void 0 && env.correlationId === void 0 ? {} : { correlationId: admitted.correlationId ?? env.correlationId },
32520
32495
  continuation: {
32521
32496
  kind: "resume",
32522
- prompt: buildResumeContinuationPrompt({
32497
+ prompt: buildAutoResumeContinuationPrompt({
32523
32498
  packageRoot: env.packageRoot,
32524
32499
  ...pickEngineAxis(env)
32525
32500
  })
@@ -1050,7 +1050,7 @@ const ROLE_COMMAND_HELP = {
1050
1050
  },
1051
1051
  navigator: {
1052
1052
  command: "navigator",
1053
- summary: "Direct Navigator (游奕使) route advice: ordered next-role candidates.",
1053
+ summary: "Direct Navigator (游奕使) free-form prose route advice.",
1054
1054
  usage: ["ak-role navigator [options] [instruction]"],
1055
1055
  examples: [
1056
1056
  'ak-role navigator "刚完成 coder apply 收敛,下一步?"',
@@ -8,7 +8,7 @@
8
8
  import { randomUUID } from "node:crypto";
9
9
  import { writeFile } from "node:fs/promises";
10
10
  import { isAbsolute, join, resolve } from "node:path";
11
- import { buildResumeContinuationPrompt, RESUME_TRANSPORT_ENVELOPE, } from "./run-lifecycle.js";
11
+ import { buildAutoResumeContinuationPrompt, buildResumeContinuationPrompt, RESUME_TRANSPORT_ENVELOPE, } from "./run-lifecycle.js";
12
12
  import { CliUsageError } from "./cli-errors.js";
13
13
  import { bindAdmittedTicketNumber, buildInstructionTransportPrompt, freezeAttachmentsIntoRun, } from "./invocation.js";
14
14
  import { readRecordedSubmissionRows } from "../submission-ledger.js";
@@ -1062,7 +1062,7 @@ export async function runPostAdmissionOneShot(input) {
1062
1062
  ...input.request,
1063
1063
  continuation: {
1064
1064
  kind: "resume",
1065
- prompt: buildResumeContinuationPrompt({
1065
+ prompt: buildAutoResumeContinuationPrompt({
1066
1066
  packageRoot: input.env.packageRoot,
1067
1067
  ...pickEngineAxis({
1068
1068
  engine: input.effectiveEngine ?? input.env.engine,
@@ -26,20 +26,31 @@ export const V1_RESUMABLE_PROVIDERS = ["openai-codex", "xai"];
26
26
  * source: runWithAutoResumeLoop receives the effective value once per call.
27
27
  */
28
28
  export const AUTO_RESUME_LIMIT = 2;
29
- /** Package-owned turn trigger for resume. Not caller instruction and not semantic task content. */
30
- export const RESUME_TRANSPORT_ENVELOPE = "[ak-role:resume-continue]";
31
29
  /**
32
- * Unique continuation-prompt selector for manual/auto engine-axis resume
33
- * (#471 / #600 / #736). Message present → those bytes; absent → engine pointers only.
34
- * #836: no transport-token prompt, no line-by-line 重新读 rewrite.
30
+ * Package-owned non-empty Chinese neutral resume transport (#959 / ADR 0073).
31
+ * Used by:
32
+ * - auto-resume (all seats via buildAutoResumeContinuationPrompt) — required so
33
+ * hosts that reject empty stdin (codex) still receive a prompt;
34
+ * - reviewer seat manual resume (reviewerResumePrompt) — same non-empty need on
35
+ * that seat's own manual entry.
36
+ * Generic bare `ak-role resume` stays empty-capable via selectResumeContinuationPrompt
37
+ * / buildResumeContinuationPrompt — ADR 0080 keeps auto and generic-manual entries separate.
38
+ */
39
+ export const RESUME_TRANSPORT_ENVELOPE = "继续。";
40
+ /**
41
+ * Manual resume continuation selector (#471 / #600 / #736 / ADR 0080).
42
+ * Message present → those bytes; absent → engine pointers only (may be empty).
43
+ * Caller message (including blank) still wins verbatim when supplied.
44
+ * Auto-resume must use buildAutoResumeContinuationPrompt — do not fold the
45
+ * non-empty Chinese envelope into this shared manual selector (#959).
35
46
  */
36
47
  export function selectResumeContinuationPrompt(message, engineMaterial) {
37
48
  const lines = message !== undefined ? [message] : [];
38
49
  return appendEngineSessionMaterial(lines, engineMaterial).join("\n");
39
50
  }
40
51
  /**
41
- * Resume continuation with engine material resolved from the seat env (#600).
42
- * Seat table / invocation engine axis rides the same prompt seam as initial runs.
52
+ * Manual resume continuation with engine material from the seat env (#600).
53
+ * Bare manual resume stays empty-prompt-capable; auto-resume is a separate entry.
43
54
  */
44
55
  export function buildResumeContinuationPrompt(options) {
45
56
  return selectResumeContinuationPrompt(options.message, engineSessionMaterialFromOptions({
@@ -47,6 +58,17 @@ export function buildResumeContinuationPrompt(options) {
47
58
  ...pickEngineAxis(options),
48
59
  }));
49
60
  }
61
+ /**
62
+ * Auto-resume continuation only (#959 / ADR 0080).
63
+ * Always non-empty: Chinese neutral envelope plus optional engine pointers.
64
+ * Never call this from manual `ak-role resume`.
65
+ */
66
+ export function buildAutoResumeContinuationPrompt(options) {
67
+ return selectResumeContinuationPrompt(RESUME_TRANSPORT_ENVELOPE, engineSessionMaterialFromOptions({
68
+ packageRoot: options.packageRoot,
69
+ ...pickEngineAxis(options),
70
+ }));
71
+ }
50
72
  const RUN_STATE_FILE = "run-state.json";
51
73
  const WRITER_LOCK_FILE = "writer.lock";
52
74
  /** @deprecated #416: 429-only classification removed; kept for compatibility. */