@akagilnc/pi-workflow-roles 0.1.4528 → 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 (55) hide show
  1. package/README.md +5 -4
  2. package/README.zh-CN.md +6 -5
  3. package/dist/acp-host/production-host.js +1834 -637
  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 +1652 -519
  7. package/dist/migrate-book-topology.js +8 -11
  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/invocation.js +10 -4
  12. package/dist/public-cli/judge-run.js +2 -2
  13. package/dist/public-cli/main.js +879 -410
  14. package/dist/public-cli/option-definitions.js +6 -6
  15. package/dist/public-cli/post-admission.js +25 -10
  16. package/dist/public-cli/reviewer-run.js +339 -0
  17. package/dist/public-cli/run-lifecycle.js +29 -7
  18. package/dist/public-cli/settlement.js +46 -32
  19. package/dist/public-cli/terminal.js +17 -27
  20. package/dist/public-cli/turn-request.js +1 -1
  21. package/dist/public-role-summons.js +370 -20
  22. package/dist/submission-ledger.js +56 -23
  23. package/package.json +1 -1
  24. package/resources/836-deleted-machine-instruction-inventory.md +2 -0
  25. package/resources/navigator-route-playbook.md +9 -0
  26. package/scripts/build-package.mjs +6 -1
  27. package/src/acp-host/role-turn-host.ts +129 -13
  28. package/src/headless-host/description.ts +17 -7
  29. package/src/headless-host/role-turn-host.ts +42 -11
  30. package/src/host-contracts.ts +0 -1
  31. package/src/navigator-attendance.ts +290 -425
  32. package/src/navigator-public-session.ts +126 -25
  33. package/src/navigator-role.ts +2 -2
  34. package/src/package-contracts/navigator-output.ts +41 -25
  35. package/src/public-cli/coder-run.ts +2 -2
  36. package/src/public-cli/fixer-run.ts +2 -2
  37. package/src/public-cli/invocation.ts +19 -9
  38. package/src/public-cli/judge-run.ts +2 -2
  39. package/src/public-cli/merger-run.ts +2 -2
  40. package/src/public-cli/option-definitions.ts +6 -6
  41. package/src/public-cli/post-admission.ts +41 -10
  42. package/src/public-cli/reviewer-run.ts +238 -53
  43. package/src/public-cli/run-lifecycle.ts +37 -7
  44. package/src/public-cli/settlement.ts +42 -34
  45. package/src/public-cli/terminal.ts +39 -37
  46. package/src/public-cli/turn-request.ts +7 -1
  47. package/src/public-role-summons.ts +544 -22
  48. package/src/reviewer-role.ts +1 -2
  49. package/src/role-envelope.ts +89 -4
  50. package/src/role-runtime.ts +76 -16
  51. package/src/submission-ledger.ts +63 -21
  52. package/dist/public-cli/command-renderer.js +0 -5
  53. package/dist/public-command-renderer.js +0 -29
  54. package/src/public-cli/command-renderer.ts +0 -9
  55. package/src/public-command-renderer.ts +0 -55
@@ -417,7 +417,7 @@ function normalizeReviewComment(raw) {
417
417
  function createGhApiRunner(options = {}) {
418
418
  const spawnImpl = options.spawnImpl ?? spawn;
419
419
  return async (args, runOptions = {}) => {
420
- return await new Promise((resolve21, reject) => {
420
+ return await new Promise((resolve22, reject) => {
421
421
  const signal = runOptions.signal;
422
422
  if (signal?.aborted) {
423
423
  reject(signal.reason ?? new Error("aborted"));
@@ -490,11 +490,11 @@ function createGhApiRunner(options = {}) {
490
490
  const value = line2.slice(idx + 1).trim();
491
491
  headers[name] = value;
492
492
  }
493
- resolve21({ status, headers, bodyText });
493
+ resolve22({ status, headers, bodyText });
494
494
  return;
495
495
  }
496
496
  if (code === 0) {
497
- resolve21({ status: 200, headers: {}, bodyText: stdout });
497
+ resolve22({ status: 200, headers: {}, bodyText: stdout });
498
498
  return;
499
499
  }
500
500
  const failure2 = new Error(
@@ -1964,7 +1964,7 @@ async function spawnEngineDetourOnce(input) {
1964
1964
  }
1965
1965
  const command = input.argv[0];
1966
1966
  const args = input.argv.slice(1);
1967
- return await new Promise((resolve21, reject) => {
1967
+ return await new Promise((resolve22, reject) => {
1968
1968
  let settled = false;
1969
1969
  const signal = input.signal;
1970
1970
  const child = spawn2(command, args, {
@@ -1994,7 +1994,7 @@ async function spawnEngineDetourOnce(input) {
1994
1994
  if (signal !== void 0) {
1995
1995
  signal.removeEventListener("abort", onAbort);
1996
1996
  }
1997
- resolve21(result);
1997
+ resolve22(result);
1998
1998
  };
1999
1999
  const onAbort = () => {
2000
2000
  fail4(signal !== void 0 ? abortReasonError(signal) : new Error("aborted"));
@@ -2110,7 +2110,48 @@ var init_collector_output = __esm({
2110
2110
  });
2111
2111
 
2112
2112
  // src/package-contracts/navigator-output.ts
2113
+ var navigator_output_exports = {};
2114
+ __export(navigator_output_exports, {
2115
+ NAVIGATOR_ACCEPTED_TEXT: () => NAVIGATOR_ACCEPTED_TEXT,
2116
+ NAVIGATOR_OUTPUT_TOOL_NAME: () => NAVIGATOR_OUTPUT_TOOL_NAME,
2117
+ navigatorOutputSchema: () => navigatorOutputSchema,
2118
+ navigatorProseFromUnknown: () => navigatorProseFromUnknown,
2119
+ projectLawfulNavigatorOutput: () => projectLawfulNavigatorOutput,
2120
+ validateRecordedNavigatorOutput: () => validateRecordedNavigatorOutput
2121
+ });
2113
2122
  import { Type as Type5 } from "typebox";
2123
+ function projectLawfulNavigatorOutput(value) {
2124
+ if (value === void 0 || value === null) return void 0;
2125
+ if (typeof value === "string") return { prose: value };
2126
+ if (typeof value === "object" && !Array.isArray(value)) {
2127
+ const record4 = value;
2128
+ if (typeof record4.prose === "string") return { prose: record4.prose };
2129
+ if (record4.prose !== void 0 && record4.prose !== null) {
2130
+ return { prose: typeof record4.prose === "string" ? record4.prose : String(record4.prose) };
2131
+ }
2132
+ const keys = Object.keys(record4);
2133
+ if (keys.length === 0) return { prose: "" };
2134
+ try {
2135
+ return { prose: JSON.stringify(record4) };
2136
+ } catch {
2137
+ return { prose: String(record4) };
2138
+ }
2139
+ }
2140
+ return { prose: String(value) };
2141
+ }
2142
+ function validateRecordedNavigatorOutput(value) {
2143
+ const projected = projectLawfulNavigatorOutput(value);
2144
+ if (projected === void 0) {
2145
+ throw new Error("Navigator output is empty");
2146
+ }
2147
+ return projected;
2148
+ }
2149
+ function navigatorProseFromUnknown(value) {
2150
+ const projected = projectLawfulNavigatorOutput(value);
2151
+ if (projected === void 0) return void 0;
2152
+ const trimmed = projected.prose.trim();
2153
+ return trimmed === "" ? void 0 : projected.prose;
2154
+ }
2114
2155
  var NAVIGATOR_OUTPUT_TOOL_NAME, NAVIGATOR_ACCEPTED_TEXT, navigatorOutputSchema;
2115
2156
  var init_navigator_output = __esm({
2116
2157
  "src/package-contracts/navigator-output.ts"() {
@@ -2122,11 +2163,8 @@ var init_navigator_output = __esm({
2122
2163
  navigatorOutputSchema = withTerminatingOutputDeclarations(
2123
2164
  openToolObject(
2124
2165
  Type5.Object({
2125
- status: Type5.Unknown({
2126
- description: "advice \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8"
2127
- }),
2128
- candidates: Type5.Unknown({
2129
- 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"
2166
+ prose: Type5.Unknown({
2167
+ 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"
2130
2168
  })
2131
2169
  })
2132
2170
  )
@@ -4912,6 +4950,56 @@ var init_typed_provider_http = __esm({
4912
4950
  });
4913
4951
 
4914
4952
  // src/public-cli/run-lifecycle.ts
4953
+ var run_lifecycle_exports = {};
4954
+ __export(run_lifecycle_exports, {
4955
+ AUTO_RESUME_LIMIT: () => AUTO_RESUME_LIMIT,
4956
+ GATE_DOSSIER_POINTER_PREFIX: () => GATE_DOSSIER_POINTER_PREFIX,
4957
+ RESUME_TRANSPORT_ENVELOPE: () => RESUME_TRANSPORT_ENVELOPE,
4958
+ RunWriterLeaseHeldError: () => RunWriterLeaseHeldError,
4959
+ V1_RESUMABLE_PROVIDERS: () => V1_RESUMABLE_PROVIDERS,
4960
+ acquireRunWriterLease: () => acquireRunWriterLease,
4961
+ autopsyWriterLock: () => autopsyWriterLock,
4962
+ buildAutoResumeContinuationPrompt: () => buildAutoResumeContinuationPrompt,
4963
+ buildResumeContinuationPrompt: () => buildResumeContinuationPrompt,
4964
+ clearCurrentCourt: () => clearCurrentCourt,
4965
+ clearTypedProviderHttpObservation: () => clearTypedProviderHttpObservation,
4966
+ describeErrorIdentity: () => describeErrorIdentity,
4967
+ findLatestRunIdForSeatTicket: () => findLatestRunIdForSeatTicket,
4968
+ findRunDirectoryById: () => findRunDirectoryById,
4969
+ isDurablePrincipalAvailable: () => isDurablePrincipalAvailable,
4970
+ isV1ResumableProvider: () => isV1ResumableProvider,
4971
+ loadResumableCoderRun: () => loadResumableCoderRun,
4972
+ loadResumableCollectorRun: () => loadResumableCollectorRun,
4973
+ loadResumableCountersignRun: () => loadResumableCountersignRun,
4974
+ loadResumableDiaristRun: () => loadResumableDiaristRun,
4975
+ loadResumableDoctorRun: () => loadResumableDoctorRun,
4976
+ loadResumableFixerRun: () => loadResumableFixerRun,
4977
+ loadResumableGleanerLeftRun: () => loadResumableGleanerLeftRun,
4978
+ loadResumableInspectorRun: () => loadResumableInspectorRun,
4979
+ loadResumableInstructionSeatRun: () => loadResumableInstructionSeatRun,
4980
+ loadResumableJudgeRun: () => loadResumableJudgeRun,
4981
+ loadResumableMergerRun: () => loadResumableMergerRun,
4982
+ loadResumableNotaryRun: () => loadResumableNotaryRun,
4983
+ loadResumableReviewerRun: () => loadResumableReviewerRun,
4984
+ loadResumableSecretariatRun: () => loadResumableSecretariatRun,
4985
+ markRunAdmitted: () => markRunAdmitted,
4986
+ markRunResumable: () => markRunResumable,
4987
+ markRunRunning: () => markRunRunning,
4988
+ markRunTerminal: () => markRunTerminal,
4989
+ parentRunPathFromGatePointerInstruction: () => parentRunPathFromGatePointerInstruction,
4990
+ peekRoleRunRole: () => peekRoleRunRole,
4991
+ readCurrentCourt: () => readCurrentCourt,
4992
+ readLatestTypedProviderHttpObservation: () => readLatestTypedProviderHttpObservation,
4993
+ readRoleRunIdentity: () => readRoleRunIdentity,
4994
+ readRoleRunState: () => readRoleRunState,
4995
+ readRunParentPath: () => readRunParentPath,
4996
+ readTypedHttp429Observation: () => readTypedHttp429Observation,
4997
+ recordCurrentCourt: () => recordCurrentCourt,
4998
+ recordTypedProviderHttpStatus: () => recordTypedProviderHttpStatus,
4999
+ renderResumeCommand: () => renderResumeCommand,
5000
+ selectResumeContinuationPrompt: () => selectResumeContinuationPrompt,
5001
+ writeRoleRunState: () => writeRoleRunState
5002
+ });
4915
5003
  import { chmod, lstat as lstat2, open, readdir as readdir4, readFile as readFile10, unlink as unlink2, writeFile as writeFile4 } from "node:fs/promises";
4916
5004
  import { basename as basename4, join as join13 } from "node:path";
4917
5005
  function selectResumeContinuationPrompt(message, engineMaterial) {
@@ -4927,6 +5015,15 @@ function buildResumeContinuationPrompt(options) {
4927
5015
  })
4928
5016
  );
4929
5017
  }
5018
+ function buildAutoResumeContinuationPrompt(options) {
5019
+ return selectResumeContinuationPrompt(
5020
+ RESUME_TRANSPORT_ENVELOPE,
5021
+ engineSessionMaterialFromOptions({
5022
+ packageRoot: options.packageRoot,
5023
+ ...pickEngineAxis(options)
5024
+ })
5025
+ );
5026
+ }
4930
5027
  function isV1ResumableProvider(provider) {
4931
5028
  return V1_RESUMABLE_PROVIDERS.includes(provider);
4932
5029
  }
@@ -5090,6 +5187,11 @@ function materializeRoleRunFromDisk(disk, authority) {
5090
5187
  return void 0;
5091
5188
  }
5092
5189
  }
5190
+ async function readRoleRunState(runDirectory, authority) {
5191
+ const disk = await readRoleRunStateDisk(runDirectory);
5192
+ if (disk === void 0) return void 0;
5193
+ return materializeRoleRunFromDisk(disk, authority)?.run;
5194
+ }
5093
5195
  async function readRoleRunIdentity(runDirectory) {
5094
5196
  const disk = await readRoleRunStateDisk(runDirectory);
5095
5197
  if (disk === void 0) return void 0;
@@ -5823,6 +5925,117 @@ async function loadResumableJudgeRun(home, runId, authority) {
5823
5925
  };
5824
5926
  return seatLoadedResult(loaded, admitted);
5825
5927
  }
5928
+ async function loadResumableCoderRun(home, runId, authority) {
5929
+ const loaded = await loadResumableRunRecord(home, runId, authority);
5930
+ if (loaded.run.role !== "coder") {
5931
+ throw new CliUsageError(
5932
+ `role run ${runId} belongs to ${loaded.run.role}, not coder`
5933
+ );
5934
+ }
5935
+ const phase = loaded.admittedFields.phase ?? loaded.run.phase;
5936
+ if (phase !== "plan" && phase !== "apply") {
5937
+ throw new CliUsageError(
5938
+ `role run admitted coder phase is missing: ${runId}`
5939
+ );
5940
+ }
5941
+ const taskPath = loaded.admittedFields.taskPath;
5942
+ if (taskPath === void 0) {
5943
+ throw new CliUsageError(
5944
+ `role run admitted coder task path is missing: ${runId}`
5945
+ );
5946
+ }
5947
+ if (loaded.admittedFields.instruction.trim() === "") {
5948
+ throw new CliUsageError(
5949
+ `role run admitted coder task is blank: ${runId}`
5950
+ );
5951
+ }
5952
+ const admitted = {
5953
+ role: "coder",
5954
+ phase,
5955
+ ...resumedBaseAdmitted(loaded),
5956
+ instructionEmpty: false,
5957
+ taskPath
5958
+ };
5959
+ return seatLoadedResult(loaded, admitted);
5960
+ }
5961
+ async function loadResumableFixerRun(home, runId, authority) {
5962
+ const loaded = await loadResumableRunRecord(home, runId, authority);
5963
+ if (loaded.run.role !== "fixer") {
5964
+ throw new CliUsageError(
5965
+ `role run ${runId} belongs to ${loaded.run.role}, not fixer`
5966
+ );
5967
+ }
5968
+ const phase = loaded.admittedFields.phase ?? loaded.run.phase;
5969
+ if (phase !== "plan" && phase !== "apply") {
5970
+ throw new CliUsageError(
5971
+ `role run admitted fixer phase is missing: ${runId}`
5972
+ );
5973
+ }
5974
+ const packetPath = loaded.admittedFields.packetPath;
5975
+ if (packetPath === void 0) {
5976
+ throw new CliUsageError(
5977
+ `role run admitted fixer packet path is missing: ${runId}`
5978
+ );
5979
+ }
5980
+ if (loaded.admittedFields.instruction.trim() === "") {
5981
+ throw new CliUsageError(
5982
+ `role run admitted fixer instruction is blank: ${runId}`
5983
+ );
5984
+ }
5985
+ const prerequisites = loaded.admittedFields.prerequisites ?? Object.freeze([]);
5986
+ const admitted = {
5987
+ role: "fixer",
5988
+ phase,
5989
+ ...resumedBaseAdmitted(loaded),
5990
+ instructionEmpty: false,
5991
+ packetPath,
5992
+ ...loaded.admittedFields.prerequisitesPath === void 0 ? {} : { prerequisitesPath: loaded.admittedFields.prerequisitesPath },
5993
+ prerequisites
5994
+ };
5995
+ return seatLoadedResult(loaded, admitted);
5996
+ }
5997
+ async function loadResumableReviewerRun(home, runId, authority) {
5998
+ const loaded = await loadResumableRunRecord(home, runId, authority);
5999
+ if (loaded.run.role !== "reviewer") {
6000
+ throw new CliUsageError(
6001
+ `role run ${runId} belongs to ${loaded.run.role}, not reviewer`
6002
+ );
6003
+ }
6004
+ const rawBase = loaded.admittedFields.baseRevision;
6005
+ if (rawBase === void 0 || rawBase.trim() === "") {
6006
+ throw new CliUsageError(
6007
+ `role run admitted reviewer base revision is missing: ${runId}`
6008
+ );
6009
+ }
6010
+ if (/\s/.test(rawBase) || rawBase.startsWith("-")) {
6011
+ throw new CliUsageError(
6012
+ `role run admitted reviewer base revision is damaged: ${runId}`
6013
+ );
6014
+ }
6015
+ const baseRevision = rawBase;
6016
+ const lens = loaded.admittedFields.lens;
6017
+ if (!isReviewerLens(lens)) {
6018
+ throw new CliUsageError(
6019
+ `role run admitted reviewer lens is missing: ${runId}`
6020
+ );
6021
+ }
6022
+ const authorityRefs = Object.freeze([
6023
+ ...loaded.admittedFields.authorityRefs ?? []
6024
+ ]);
6025
+ if (authorityRefs.length === 0) {
6026
+ throw new CliUsageError(
6027
+ `role run admitted reviewer authority refs are missing: ${runId}`
6028
+ );
6029
+ }
6030
+ const admitted = {
6031
+ role: "reviewer",
6032
+ ...resumedBaseAdmitted(loaded),
6033
+ baseRevision,
6034
+ lens,
6035
+ authorityRefs
6036
+ };
6037
+ return seatLoadedResult(loaded, admitted);
6038
+ }
5826
6039
  async function loadResumableCountersignRun(home, runId, authority) {
5827
6040
  const loaded = await loadResumableRunRecord(home, runId, authority);
5828
6041
  if (loaded.run.role !== "countersign") {
@@ -5854,6 +6067,26 @@ async function loadResumableInstructionSeatRun(home, runId, authority) {
5854
6067
  };
5855
6068
  return seatLoadedResult(loaded, admitted);
5856
6069
  }
6070
+ async function loadResumableGleanerLeftRun(home, runId, authority) {
6071
+ const loaded = await loadResumableRunRecord(home, runId, authority);
6072
+ if (loaded.run.role !== "gleaner-left") {
6073
+ throw new CliUsageError(
6074
+ `role run ${runId} belongs to ${loaded.run.role}, not gleaner-left`
6075
+ );
6076
+ }
6077
+ const baseRevision = loaded.admittedFields.baseRevision;
6078
+ if (baseRevision === void 0 || baseRevision.trim() === "") {
6079
+ throw new CliUsageError(
6080
+ `role run admitted gleaner-left base revision is missing: ${runId}`
6081
+ );
6082
+ }
6083
+ const admitted = {
6084
+ role: "gleaner-left",
6085
+ ...resumedBaseAdmitted(loaded),
6086
+ baseRevision
6087
+ };
6088
+ return seatLoadedResult(loaded, admitted);
6089
+ }
5857
6090
  async function loadResumableDiaristRun(home, runId, authority) {
5858
6091
  const loaded = await loadResumableRunRecord(home, runId, authority);
5859
6092
  if (loaded.run.role !== "diarist") {
@@ -5867,6 +6100,88 @@ async function loadResumableDiaristRun(home, runId, authority) {
5867
6100
  };
5868
6101
  return seatLoadedResult(loaded, admitted);
5869
6102
  }
6103
+ async function loadResumableSecretariatRun(home, runId, authority) {
6104
+ const loaded = await loadResumableRunRecord(home, runId, authority);
6105
+ if (loaded.run.role !== "secretariat") {
6106
+ throw new CliUsageError(
6107
+ `role run ${runId} belongs to ${loaded.run.role}, not secretariat`
6108
+ );
6109
+ }
6110
+ const admitted = {
6111
+ role: "secretariat",
6112
+ ...resumedBaseAdmitted(loaded)
6113
+ };
6114
+ return seatLoadedResult(loaded, admitted);
6115
+ }
6116
+ async function loadResumableMergerRun(home, runId, authority) {
6117
+ const loaded = await loadResumableRunRecord(home, runId, authority);
6118
+ if (loaded.run.role !== "merger") {
6119
+ throw new CliUsageError(
6120
+ `role run ${runId} belongs to ${loaded.run.role}, not merger`
6121
+ );
6122
+ }
6123
+ const mergerInputPath = loaded.admittedFields.mergerInputPath;
6124
+ if (mergerInputPath === void 0) {
6125
+ throw new CliUsageError(
6126
+ `role run admitted merger input path is missing: ${runId}`
6127
+ );
6128
+ }
6129
+ const derived = loaded.admittedFields.derived;
6130
+ if (derived === void 0) {
6131
+ throw new CliUsageError(
6132
+ `role run admitted merger envelope is missing: ${runId}`
6133
+ );
6134
+ }
6135
+ if (loaded.admittedFields.instruction.trim() === "") {
6136
+ throw new CliUsageError(
6137
+ `role run admitted merger task is blank: ${runId}`
6138
+ );
6139
+ }
6140
+ const admitted = {
6141
+ role: "merger",
6142
+ ...resumedBaseAdmitted(loaded),
6143
+ instructionEmpty: false,
6144
+ mergerInputPath,
6145
+ derived
6146
+ };
6147
+ return seatLoadedResult(loaded, admitted);
6148
+ }
6149
+ async function loadResumableCollectorRun(home, runId, authority) {
6150
+ const loaded = await loadResumableRunRecord(home, runId, authority);
6151
+ if (loaded.run.role !== "collector") {
6152
+ throw new CliUsageError(
6153
+ `role run ${runId} belongs to ${loaded.run.role}, not collector`
6154
+ );
6155
+ }
6156
+ const { prNumber, repository, repositoryDisplay, manifestDigest } = loaded.admittedFields;
6157
+ if (repository === void 0 || repositoryDisplay === void 0 || manifestDigest === void 0) {
6158
+ throw new CliUsageError(
6159
+ `role run admitted collector repository identity is missing: ${runId}`
6160
+ );
6161
+ }
6162
+ let parsedRepository;
6163
+ try {
6164
+ parsedRepository = parseCollectorRepository(repositoryDisplay);
6165
+ } catch (error) {
6166
+ const detail = error instanceof Error ? error.message : String(error);
6167
+ throw new CliUsageError(detail, { cause: error });
6168
+ }
6169
+ if (parsedRepository.canonical !== repository) {
6170
+ throw new CliUsageError(
6171
+ `role run admitted collector repository does not match its canonical form: ${runId}`
6172
+ );
6173
+ }
6174
+ const admitted = {
6175
+ role: "collector",
6176
+ ...resumedBaseAdmitted(loaded),
6177
+ ...prNumber === void 0 ? {} : { prNumber },
6178
+ repository: parsedRepository,
6179
+ ...loaded.admittedFields.requestManifestPath === void 0 ? {} : { requestManifestPath: loaded.admittedFields.requestManifestPath },
6180
+ ...loaded.admittedFields.waitWindowMs === void 0 ? {} : { waitWindowMs: loaded.admittedFields.waitWindowMs },
6181
+ manifestDigest
6182
+ };
6183
+ return seatLoadedResult(loaded, admitted);
6184
+ }
5870
6185
  async function loadResumableDoctorRun(home, runId, authority) {
5871
6186
  const loaded = await loadResumableRunRecord(home, runId, authority);
5872
6187
  if (loaded.run.role !== "doctor") {
@@ -5924,6 +6239,12 @@ async function loadResumableInspectorRun(home, runId, authority) {
5924
6239
  };
5925
6240
  return seatLoadedResult(loaded, admitted);
5926
6241
  }
6242
+ async function peekRoleRunRole(home, runId) {
6243
+ const runDirectory = await findRunDirectoryById(home, runId);
6244
+ if (runDirectory === void 0) return void 0;
6245
+ const run = await readRoleRunIdentity(runDirectory);
6246
+ return run?.role;
6247
+ }
5927
6248
  var V1_RESUMABLE_PROVIDERS, AUTO_RESUME_LIMIT, RESUME_TRANSPORT_ENVELOPE, RUN_STATE_FILE, WRITER_LOCK_FILE, RunWriterLeaseHeldError, WRITER_LEASE_RECLAIM_ROUNDS, GATE_DOSSIER_POINTER_PREFIX;
5928
6249
  var init_run_lifecycle = __esm({
5929
6250
  "src/public-cli/run-lifecycle.ts"() {
@@ -5940,7 +6261,7 @@ var init_run_lifecycle = __esm({
5940
6261
  init_invocation();
5941
6262
  V1_RESUMABLE_PROVIDERS = ["openai-codex", "xai"];
5942
6263
  AUTO_RESUME_LIMIT = 2;
5943
- RESUME_TRANSPORT_ENVELOPE = "[ak-role:resume-continue]";
6264
+ RESUME_TRANSPORT_ENVELOPE = "\u7EE7\u7EED\u3002";
5944
6265
  RUN_STATE_FILE = "run-state.json";
5945
6266
  WRITER_LOCK_FILE = "writer.lock";
5946
6267
  RunWriterLeaseHeldError = class extends Error {
@@ -6580,12 +6901,12 @@ var init_option_definitions = __esm({
6580
6901
  canonical: "--lens",
6581
6902
  aliases: [],
6582
6903
  valueMetavar: "completeness|correctness",
6583
- required: true,
6904
+ required: false,
6584
6905
  repeatable: false,
6585
6906
  form: "option",
6586
6907
  description: {
6587
- en: "Required single review lens: completeness or correctness (no default).",
6588
- zh: "\u5FC5\u586B\u5355 lens\uFF1Acompleteness \u6216 correctness\uFF08\u65E0\u9ED8\u8BA4\u503C\uFF09\u3002"
6908
+ en: "Optional single-lens override: completeness or correctness; omitted runs both in parallel.",
6909
+ zh: "\u53EF\u9009\u5355 lens \u8986\u76D6\uFF1Acompleteness \u6216 correctness\uFF1B\u7701\u7565\u65F6\u5E76\u884C\u8FD0\u884C\u4E24\u8F74\u3002"
6589
6910
  }
6590
6911
  },
6591
6912
  {
@@ -6942,9 +7263,9 @@ var init_option_definitions = __esm({
6942
7263
  },
6943
7264
  reviewer: {
6944
7265
  command: "reviewer",
6945
- summary: "Fixed-target single-lens review (completeness or correctness).",
7266
+ summary: "Fixed-target parallel two-lens review, with an optional single-lens override.",
6946
7267
  usage: [
6947
- "ak-role reviewer --base <revision> --lens completeness|correctness --authority-ref <ref> [options] <instruction>"
7268
+ "ak-role reviewer --base <revision> [--lens completeness|correctness] --authority-ref <ref> [options] <instruction>"
6948
7269
  ],
6949
7270
  examples: [
6950
7271
  'ak-role reviewer --base main --lens completeness --authority-ref docs/adr/0001.md "Review the branch."',
@@ -6995,7 +7316,7 @@ var init_option_definitions = __esm({
6995
7316
  },
6996
7317
  navigator: {
6997
7318
  command: "navigator",
6998
- summary: "Direct Navigator (\u6E38\u5955\u4F7F) route advice: ordered next-role candidates.",
7319
+ summary: "Direct Navigator (\u6E38\u5955\u4F7F) free-form prose route advice.",
6999
7320
  usage: ["ak-role navigator [options] [instruction]"],
7000
7321
  examples: [
7001
7322
  'ak-role navigator "\u521A\u5B8C\u6210 coder apply \u6536\u655B\uFF0C\u4E0B\u4E00\u6B65\uFF1F"'
@@ -9077,7 +9398,7 @@ function parseReviewerArgv(args) {
9077
9398
  instruction: positional.join(" "),
9078
9399
  attachmentPaths,
9079
9400
  baseRevision,
9080
- lens,
9401
+ ...lens === void 0 ? {} : { lens },
9081
9402
  authorityRefs,
9082
9403
  ...project === void 0 ? {} : { project }
9083
9404
  };
@@ -9126,6 +9447,7 @@ async function admitReviewerInvocation(options) {
9126
9447
  baseRevision,
9127
9448
  lens,
9128
9449
  authorityRefs: [...authorityRefs],
9450
+ ...options.correlationId === void 0 ? {} : { correlationId: options.correlationId },
9129
9451
  attachments: attachments.map((a) => ({
9130
9452
  provenancePath: a.provenancePath,
9131
9453
  frozenPath: a.frozenPath,
@@ -9153,7 +9475,8 @@ async function admitReviewerInvocation(options) {
9153
9475
  admittedRequestPath,
9154
9476
  baseRevision,
9155
9477
  lens,
9156
- authorityRefs
9478
+ authorityRefs,
9479
+ ...options.correlationId === void 0 ? {} : { correlationId: options.correlationId }
9157
9480
  };
9158
9481
  }
9159
9482
  function buildReviewerSkillArgProjection(admitted) {
@@ -9370,11 +9693,11 @@ function parseAnalystCohortIssueToken(raw, flag) {
9370
9693
  `${flag} requires a comma-separated list of N or book:N`
9371
9694
  );
9372
9695
  }
9373
- const sep6 = trimmed.lastIndexOf(":");
9374
- if (sep6 > 0) {
9375
- const rhs = trimmed.slice(sep6 + 1);
9696
+ const sep7 = trimmed.lastIndexOf(":");
9697
+ if (sep7 > 0) {
9698
+ const rhs = trimmed.slice(sep7 + 1);
9376
9699
  if (ANALYST_TICKET_NUMBER_PATTERN.test(rhs)) {
9377
- const bookKey = trimmed.slice(0, sep6);
9700
+ const bookKey = trimmed.slice(0, sep7);
9378
9701
  if (bookKey.trim() === "") {
9379
9702
  throw new CliUsageError(
9380
9703
  `${flag} book:N requires a non-empty book key, got ${raw}`
@@ -11283,31 +11606,58 @@ async function restoreState(cwd, runId, scope) {
11283
11606
  }, 0)
11284
11607
  };
11285
11608
  }
11609
+ function sessionParentFromHostContext(context) {
11610
+ const runDirectory = runDirectoryFromHostContext(context);
11611
+ if (runDirectory !== void 0) return join22(runDirectory, "session", "session.jsonl");
11612
+ const sessionFile = context.sessionManager.getSessionFile?.();
11613
+ if (typeof sessionFile === "string" && sessionFile.length > 0) return sessionFile;
11614
+ const sessionDir = context.sessionManager.getSessionDir?.();
11615
+ if (typeof sessionDir === "string" && sessionDir.length > 0) {
11616
+ return join22(sessionDir, "session.jsonl");
11617
+ }
11618
+ return void 0;
11619
+ }
11620
+ function homeFromHostContext(context, home) {
11621
+ if (home !== void 0) return home;
11622
+ const sessionParent = sessionParentFromHostContext(context);
11623
+ return sessionParent !== void 0 ? tryHomeFromAkRolesPath(sessionParent) : void 0;
11624
+ }
11625
+ async function sealAcceptedSubmission(options) {
11626
+ const runId = runIdentity(options.context);
11627
+ const attemptId = attemptIdentity(options.context, runId);
11628
+ const sessionParent = sessionParentFromHostContext(options.context);
11629
+ const home = homeFromHostContext(options.context, options.home);
11630
+ const state = await restoreState(options.context.cwd, runId, {
11631
+ ...home === void 0 ? {} : { home },
11632
+ ...sessionParent === void 0 ? {} : { sessionParent }
11633
+ });
11634
+ const pointer = sitianReport({
11635
+ level: "event",
11636
+ kind: "sealed",
11637
+ subject: { runId, attemptId },
11638
+ ...state.prior === void 0 ? {} : { priorEventId: state.prior.identity },
11639
+ payload: {
11640
+ type: "sealed",
11641
+ attemptId,
11642
+ toolCallId: options.toolCallId,
11643
+ role: options.role,
11644
+ accepted: options.accepted
11645
+ },
11646
+ source: "role-runtime",
11647
+ cwd: options.context.cwd,
11648
+ ...home !== void 0 ? { home } : {},
11649
+ ...sessionParent === void 0 ? {} : { sessionParent }
11650
+ });
11651
+ state.prior = pointer;
11652
+ }
11286
11653
  function createSubmissionLedgerHost(host, outputTools, failInfrastructure2 = (error) => {
11287
11654
  throw error;
11288
11655
  }, projectClosure = () => void 0, options) {
11289
11656
  const states = /* @__PURE__ */ new Map();
11290
- const sessionParentFromContext = (context) => {
11291
- const runDirectory = runDirectoryFromHostContext(context);
11292
- if (runDirectory !== void 0) {
11293
- return join22(runDirectory, "session", "session.jsonl");
11294
- }
11295
- const sessionFile = context.sessionManager.getSessionFile?.();
11296
- if (typeof sessionFile === "string" && sessionFile.length > 0) return sessionFile;
11297
- const sessionDir = context.sessionManager.getSessionDir?.();
11298
- if (typeof sessionDir === "string" && sessionDir.length > 0) {
11299
- return join22(sessionDir, "session.jsonl");
11300
- }
11301
- return void 0;
11302
- };
11303
- const resolveHomeFromContext = (context) => {
11304
- if (options?.home !== void 0) return options.home;
11305
- const sessionParent = sessionParentFromContext(context);
11306
- return sessionParent !== void 0 ? tryHomeFromAkRolesPath(sessionParent) : void 0;
11307
- };
11657
+ const resolveHomeFromContext = (context) => homeFromHostContext(context, options?.home);
11308
11658
  const stateFor = (context, runId) => states.get(runId) ?? (() => {
11309
11659
  const home = resolveHomeFromContext(context);
11310
- const sessionParent = sessionParentFromContext(context);
11660
+ const sessionParent = sessionParentFromHostContext(context);
11311
11661
  const pending = restoreState(context.cwd, runId, {
11312
11662
  ...home === void 0 ? {} : { home },
11313
11663
  ...sessionParent === void 0 ? {} : { sessionParent }
@@ -11317,7 +11667,7 @@ function createSubmissionLedgerHost(host, outputTools, failInfrastructure2 = (er
11317
11667
  })();
11318
11668
  const appendFor = (state, context, runId, attemptId, event) => {
11319
11669
  const home = resolveHomeFromContext(context);
11320
- const sessionParent = sessionParentFromContext(context);
11670
+ const sessionParent = sessionParentFromHostContext(context);
11321
11671
  const pointer = sitianReport({
11322
11672
  level: "event",
11323
11673
  kind: event.type,
@@ -11668,12 +12018,12 @@ function createSystemCollectorClock() {
11668
12018
  return {
11669
12019
  wallNow: () => /* @__PURE__ */ new Date(),
11670
12020
  monoNow: () => Number(process.hrtime.bigint() - start) / 1e6,
11671
- sleep: (ms, signal) => new Promise((resolve21, reject) => {
12021
+ sleep: (ms, signal) => new Promise((resolve22, reject) => {
11672
12022
  if (signal?.aborted) {
11673
12023
  reject(signal.reason ?? new Error("aborted"));
11674
12024
  return;
11675
12025
  }
11676
- const timer = setTimeout(resolve21, ms);
12026
+ const timer = setTimeout(resolve22, ms);
11677
12027
  const onAbort = () => {
11678
12028
  clearTimeout(timer);
11679
12029
  reject(signal?.reason ?? new Error("aborted"));
@@ -13620,44 +13970,6 @@ var init_receipt_delivery_policy = __esm({
13620
13970
  }
13621
13971
  });
13622
13972
 
13623
- // src/public-command-renderer.ts
13624
- function isPublicCallableRole2(role) {
13625
- return PUBLIC_CALLABLE_ROLES3.has(role);
13626
- }
13627
- function renderPublicAkRoleCommand(target) {
13628
- if (!isPublicCallableRole2(target.role)) return void 0;
13629
- const role = target.role;
13630
- const metadata = packagedRoleMetadata(role);
13631
- if (metadata !== void 0 && "bareCommand" in metadata && metadata.bareCommand === false) {
13632
- return void 0;
13633
- }
13634
- if (target.phase === null || target.phase === void 0) {
13635
- return `ak-role ${role}`;
13636
- }
13637
- if (role === "coder" || role === "fixer") {
13638
- return `ak-role ${role} ${target.phase}`;
13639
- }
13640
- return `ak-role ${role}`;
13641
- }
13642
- var PUBLIC_CALLABLE_ROLES3;
13643
- var init_public_command_renderer = __esm({
13644
- "src/public-command-renderer.ts"() {
13645
- "use strict";
13646
- init_packaged_role_registry();
13647
- PUBLIC_CALLABLE_ROLES3 = new Set(
13648
- PACKAGED_ROLE_REGISTRY.map((entry) => entry.role)
13649
- );
13650
- }
13651
- });
13652
-
13653
- // src/public-cli/command-renderer.ts
13654
- var init_command_renderer = __esm({
13655
- "src/public-cli/command-renderer.ts"() {
13656
- "use strict";
13657
- init_public_command_renderer();
13658
- }
13659
- });
13660
-
13661
13973
  // src/public-cli/terminal.ts
13662
13974
  function encodeTerminalField(value) {
13663
13975
  return JSON.stringify(value);
@@ -13668,14 +13980,10 @@ function isLawfulTypedTerminalOutcome(outcome) {
13668
13980
  function exitCodeForTerminalOutcome(outcome) {
13669
13981
  return isLawfulTypedTerminalOutcome(outcome) ? 0 : 1;
13670
13982
  }
13671
- function recommendationNavigatorFact(input) {
13672
- const command = typeof input.modelCommand === "string" && input.modelCommand.trim() !== "" ? input.modelCommand : isPublicCallableRole2(input.next.role) ? renderPublicAkRoleCommand(input.next) : void 0;
13983
+ function adviceNavigatorFact(input) {
13673
13984
  return {
13674
- disposition: "recommendation",
13675
- next: input.next,
13676
- reason: input.reason,
13677
- ...command === void 0 ? {} : { command },
13678
- ...input.route === void 0 ? {} : { route: input.route },
13985
+ disposition: "advice",
13986
+ prose: input.prose,
13679
13987
  ...input.advisoryDiagnostic === void 0 ? {} : { advisoryDiagnostic: input.advisoryDiagnostic }
13680
13988
  };
13681
13989
  }
@@ -13703,14 +14011,8 @@ function formatTerminalResult(result) {
13703
14011
  if (result.navigator.advisoryDiagnostic !== void 0) {
13704
14012
  lines.push(`navigator-advisory ${encodeTerminalField(result.navigator.advisoryDiagnostic)}`);
13705
14013
  }
13706
- if (result.navigator.disposition === "recommendation") {
13707
- lines.push(
13708
- `next ${result.navigator.next.role} ${result.navigator.next.phase ?? "none"}`
13709
- );
13710
- lines.push(`reason ${encodeTerminalField(result.navigator.reason)}`);
13711
- if (result.navigator.command !== void 0) {
13712
- lines.push(`command ${encodeTerminalField(result.navigator.command)}`);
13713
- }
14014
+ if (result.navigator.disposition === "advice") {
14015
+ lines.push(`prose ${encodeTerminalField(result.navigator.prose)}`);
13714
14016
  } else if (result.navigator.disposition === "unavailable") {
13715
14017
  lines.push(
13716
14018
  `unavailable ${result.navigator.source} ${encodeTerminalField(result.navigator.reason)}`
@@ -13730,6 +14032,15 @@ function formatTerminalResult(result) {
13730
14032
  );
13731
14033
  }
13732
14034
  }
14035
+ if (result.reviewerChildOutcomes !== void 0) {
14036
+ for (const axis of ["completeness", "correctness"]) {
14037
+ const child = result.reviewerChildOutcomes[axis];
14038
+ lines.push(`reviewer-child ${axis} ${child.exitCode}`);
14039
+ if (child.stderr !== void 0 && child.stderr !== "") {
14040
+ lines.push(`reviewer-child-diagnostic ${axis} ${encodeTerminalField(child.stderr)}`);
14041
+ }
14042
+ }
14043
+ }
13733
14044
  if (result.resume !== void 0) {
13734
14045
  lines.push(`resume ${encodeTerminalField(result.resume.command)}`);
13735
14046
  } else if (result.runId !== void 0) {
@@ -13750,7 +14061,6 @@ function formatTerminalResult(result) {
13750
14061
  var init_terminal = __esm({
13751
14062
  "src/public-cli/terminal.ts"() {
13752
14063
  "use strict";
13753
- init_command_renderer();
13754
14064
  }
13755
14065
  });
13756
14066
 
@@ -14730,10 +15040,6 @@ async function appendRunAttemptHistory(source, outcome) {
14730
15040
  } catch {
14731
15041
  }
14732
15042
  }
14733
- function navigatorPhaseValue(value) {
14734
- if (value === "plan" || value === "apply") return value;
14735
- return null;
14736
- }
14737
15043
  function navigatorAttendanceCorrelatedWithBoundMarker(details, attendanceIndex, terminalIndex, marker) {
14738
15044
  if (attendanceIndex <= terminalIndex) return false;
14739
15045
  if (details.invocationId !== marker.invocationId) return false;
@@ -14742,29 +15048,33 @@ function navigatorAttendanceCorrelatedWithBoundMarker(details, attendanceIndex,
14742
15048
  function parseNavigatorAttendanceDetails(details) {
14743
15049
  const disposition = details.disposition;
14744
15050
  const advisoryDiagnostic = typeof details.routePlaybookReadFailure === "string" ? { advisoryDiagnostic: details.routePlaybookReadFailure } : {};
14745
- if (disposition === "recommendation") {
14746
- const next = details.next;
14747
- if (!isRecord11(next) || typeof next.role !== "string") {
15051
+ if (disposition === "advice" || disposition === "recommendation") {
15052
+ let prose;
15053
+ if (typeof details.prose === "string" && details.prose.trim() !== "") {
15054
+ prose = details.prose;
15055
+ } else {
15056
+ const next = isRecord11(details.next) && typeof details.next.role === "string" ? details.next.role : void 0;
15057
+ const reason = typeof details.reason === "string" && details.reason.trim() !== "" ? details.reason : void 0;
15058
+ const command = typeof details.command === "string" && details.command.trim() !== "" ? details.command : void 0;
15059
+ if (reason !== void 0 && next !== void 0) {
15060
+ prose = `${reason}\uFF08\u4E0B\u4E00\u6B65\uFF1A${next}\uFF09`;
15061
+ } else if (reason !== void 0) {
15062
+ prose = reason;
15063
+ } else if (next !== void 0) {
15064
+ prose = `\u4E0B\u4E00\u6B65\uFF1A${next}`;
15065
+ } else if (command !== void 0) {
15066
+ prose = command;
15067
+ }
15068
+ }
15069
+ if (prose === void 0 || prose.trim() === "") {
14748
15070
  return {
14749
- disposition: "unavailable",
14750
- source: "unknown",
14751
- reason: "navigator recommendation missing typed next role"
15071
+ disposition: "no-advice",
15072
+ ...advisoryDiagnostic
14752
15073
  };
14753
15074
  }
14754
- const reason = typeof details.reason === "string" ? details.reason : "";
14755
- const route = Array.isArray(details.route) ? details.route.filter(isRecord11).map((target) => ({
14756
- role: String(target.role),
14757
- phase: navigatorPhaseValue(target.phase)
14758
- })) : void 0;
14759
- return recommendationNavigatorFact({
14760
- ...advisoryDiagnostic,
14761
- next: {
14762
- role: next.role,
14763
- phase: navigatorPhaseValue(next.phase)
14764
- },
14765
- reason,
14766
- ...route === void 0 ? {} : { route },
14767
- ...typeof details.command === "string" ? { modelCommand: details.command } : {}
15075
+ return adviceNavigatorFact({
15076
+ prose,
15077
+ ...advisoryDiagnostic
14768
15078
  });
14769
15079
  }
14770
15080
  if (disposition === "unavailable") {
@@ -16190,10 +16500,10 @@ function presentFailureTerminal(terminal, io) {
16190
16500
  }
16191
16501
  function defaultNavigatorGraceSleep() {
16192
16502
  let timer;
16193
- const sleep = ((ms) => new Promise((resolve21) => {
16503
+ const sleep = ((ms) => new Promise((resolve22) => {
16194
16504
  timer = setTimeout(() => {
16195
16505
  timer = void 0;
16196
- resolve21();
16506
+ resolve22();
16197
16507
  }, ms);
16198
16508
  }));
16199
16509
  sleep.cancel = () => {
@@ -16205,7 +16515,7 @@ function defaultNavigatorGraceSleep() {
16205
16515
  return sleep;
16206
16516
  }
16207
16517
  function raceNavigatorGrace(work, graceMs = NAVIGATOR_POST_ROLE_GRACE_MS, sleep = defaultNavigatorGraceSleep()) {
16208
- return new Promise((resolve21, reject) => {
16518
+ return new Promise((resolve22, reject) => {
16209
16519
  let settled = false;
16210
16520
  const finish = (action) => {
16211
16521
  if (settled) return;
@@ -16214,11 +16524,11 @@ function raceNavigatorGrace(work, graceMs = NAVIGATOR_POST_ROLE_GRACE_MS, sleep
16214
16524
  action();
16215
16525
  };
16216
16526
  void work.then(
16217
- (value) => finish(() => resolve21({ status: "done", value })),
16527
+ (value) => finish(() => resolve22({ status: "done", value })),
16218
16528
  (error) => finish(() => reject(error))
16219
16529
  );
16220
16530
  void sleep(graceMs).then(() => {
16221
- finish(() => resolve21({ status: "timeout" }));
16531
+ finish(() => resolve22({ status: "timeout" }));
16222
16532
  });
16223
16533
  });
16224
16534
  }
@@ -17669,6 +17979,30 @@ async function recordBestEffortPostDispatchDiagnostic(admitted, env, diagnostic,
17669
17979
  }
17670
17980
  }
17671
17981
  }
17982
+ async function resolveResumeMethodMaterialAdapters(input) {
17983
+ if (input.shouldLoad === false) {
17984
+ return { kind: "continue", adapters: input.emptyAdapters };
17985
+ }
17986
+ try {
17987
+ const material = await input.loadMaterial();
17988
+ return { kind: "continue", adapters: input.adaptersWith(material) };
17989
+ } catch (error) {
17990
+ const terminal = await presentControlledFailure2(
17991
+ input.admitted,
17992
+ {
17993
+ timedOut: false,
17994
+ code: null,
17995
+ stderr: "",
17996
+ thrown: error,
17997
+ ...input.knownCause === void 0 ? {} : { knownCause: input.knownCause }
17998
+ },
17999
+ input.emptyAdapters,
18000
+ input.authority,
18001
+ input.io
18002
+ );
18003
+ return { kind: "terminal", ...terminal };
18004
+ }
18005
+ }
17672
18006
  async function presentControlledFailure2(admitted, failureInput, adapters, authority, io, persistRunState = true) {
17673
18007
  const hasThrown = Object.hasOwn(failureInput, "thrown");
17674
18008
  const resumeObservation = await resolveControlledFailureResumeObservation({
@@ -18219,6 +18553,8 @@ async function runPostAdmissionSeatResume(input) {
18219
18553
  }
18220
18554
  adapters = prepared.adapters;
18221
18555
  }
18556
+ let env = input.env;
18557
+ let preparedCleanup;
18222
18558
  const buildRequestAfterLease = async () => {
18223
18559
  let openCourtAttemptId;
18224
18560
  let admittedForBuild = loaded.admitted;
@@ -18269,7 +18605,12 @@ async function runPostAdmissionSeatResume(input) {
18269
18605
  return turnRequest;
18270
18606
  };
18271
18607
  try {
18272
- if (input.env.stationChild === true) {
18608
+ if (input.afterAdmittedPrepare !== void 0) {
18609
+ const prepared = await input.afterAdmittedPrepare(loaded.admitted);
18610
+ if (prepared.env !== void 0) env = prepared.env;
18611
+ preparedCleanup = prepared.cleanup;
18612
+ }
18613
+ if (env.stationChild === true) {
18273
18614
  let firstTurn;
18274
18615
  const stationAdapters = withOnceSuccessfulBeforeDispatch(adapters);
18275
18616
  const invocationScopeId = mintEngineDetourInvocationScope({
@@ -18277,14 +18618,14 @@ async function runPostAdmissionSeatResume(input) {
18277
18618
  });
18278
18619
  return await runWithAutoResumeLoop({
18279
18620
  admitted: loaded.admitted,
18280
- principalAuthority: input.env.principalAuthority,
18621
+ principalAuthority: env.principalAuthority,
18281
18622
  isPrincipalAvailable: resolveHostAwareSessionAvailability(
18282
- input.env.host,
18283
- input.env.principalAuthority
18623
+ env.host,
18624
+ env.principalAuthority
18284
18625
  ),
18285
18626
  io: input.io,
18286
- sessionAppender: input.env.sessionAppender,
18287
- autoResumeLimit: input.env.autoResumeLimit,
18627
+ sessionAppender: env.sessionAppender,
18628
+ autoResumeLimit: env.autoResumeLimit,
18288
18629
  buildInitialPayload: () => ({ resumeTurn: false }),
18289
18630
  buildResumePayload: () => ({ resumeTurn: true }),
18290
18631
  // Same as public manual resume: prior-court sealed acceptance is not a
@@ -18311,7 +18652,7 @@ async function runPostAdmissionSeatResume(input) {
18311
18652
  dispatch: async (turnRequest) => {
18312
18653
  const result = await dispatchPostAdmissionTurn({
18313
18654
  admitted: loaded.admitted,
18314
- env: input.env,
18655
+ env,
18315
18656
  io: attemptIo,
18316
18657
  request: turnRequest,
18317
18658
  lease,
@@ -18321,7 +18662,7 @@ async function runPostAdmissionSeatResume(input) {
18321
18662
  });
18322
18663
  return settleDeferredPersist(
18323
18664
  loaded.admitted,
18324
- input.env.principalAuthority,
18665
+ env.principalAuthority,
18325
18666
  stationAdapters,
18326
18667
  attemptIo,
18327
18668
  result
@@ -18332,7 +18673,7 @@ async function runPostAdmissionSeatResume(input) {
18332
18673
  }
18333
18674
  return await runPostAdmissionManualResume({
18334
18675
  admitted: loaded.admitted,
18335
- env: input.env,
18676
+ env,
18336
18677
  io: input.io,
18337
18678
  adapters,
18338
18679
  ...input.effectiveEngine === void 0 ? {} : { effectiveEngine: input.effectiveEngine },
@@ -18344,6 +18685,10 @@ async function runPostAdmissionSeatResume(input) {
18344
18685
  return { exitCode: 2 };
18345
18686
  }
18346
18687
  throw error;
18688
+ } finally {
18689
+ if (preparedCleanup !== void 0) {
18690
+ await preparedCleanup();
18691
+ }
18347
18692
  }
18348
18693
  }
18349
18694
  async function runPostAdmissionOneShot(input) {
@@ -18356,7 +18701,7 @@ async function runPostAdmissionOneShot(input) {
18356
18701
  ...input.request,
18357
18702
  continuation: {
18358
18703
  kind: "resume",
18359
- prompt: buildResumeContinuationPrompt({
18704
+ prompt: buildAutoResumeContinuationPrompt({
18360
18705
  packageRoot: input.env.packageRoot,
18361
18706
  ...pickEngineAxis({
18362
18707
  engine: input.effectiveEngine ?? input.env.engine,
@@ -18505,7 +18850,7 @@ var init_post_admission = __esm({
18505
18850
 
18506
18851
  // src/public-cli/turn-request.ts
18507
18852
  function projectRoleTurnRequest(admitted, roleDetails, options) {
18508
- const cwd = admitted.projectRoot ?? admitted.repoRoot ?? admitted.cwd;
18853
+ const cwd = options.cwd ?? admitted.projectRoot ?? admitted.repoRoot ?? admitted.cwd;
18509
18854
  if (cwd === void 0) throw new Error("admitted invocation missing working directory");
18510
18855
  if (admitted.principal === void 0) throw new Error("admitted invocation missing principal");
18511
18856
  return {
@@ -19228,7 +19573,7 @@ async function runPublicJudge(argv, env, io, parseJudgeArgv2) {
19228
19573
  ...admitted.correlationId === void 0 && env.correlationId === void 0 ? {} : { correlationId: admitted.correlationId ?? env.correlationId },
19229
19574
  continuation: {
19230
19575
  kind: "resume",
19231
- prompt: buildResumeContinuationPrompt({
19576
+ prompt: buildAutoResumeContinuationPrompt({
19232
19577
  packageRoot: env.packageRoot,
19233
19578
  ...pickEngineAxis(env)
19234
19579
  })
@@ -20009,31 +20354,361 @@ var init_countersign_run = __esm({
20009
20354
  }
20010
20355
  });
20011
20356
 
20012
- // src/public-role-summons.ts
20013
- var public_role_summons_exports = {};
20014
- __export(public_role_summons_exports, {
20015
- AK_ROLE_PACKAGE_ROOT_ENV: () => AK_ROLE_PACKAGE_ROOT_ENV,
20016
- resolveSummonsPackageRoot: () => resolveSummonsPackageRoot,
20017
- summonGateOfficer: () => summonGateOfficer,
20018
- summonPublicRole: () => summonPublicRole
20357
+ // src/public-cli/reviewer-run.ts
20358
+ var reviewer_run_exports = {};
20359
+ __export(reviewer_run_exports, {
20360
+ buildReviewerTurnRequest: () => buildReviewerTurnRequest,
20361
+ runPublicReviewer: () => runPublicReviewer,
20362
+ runPublicReviewerResume: () => runPublicReviewerResume
20019
20363
  });
20020
- import { existsSync as existsSync10 } from "node:fs";
20021
- import { join as join33 } from "node:path";
20022
- function createCapturingIo() {
20023
- const chunks = [];
20024
- return {
20025
- io: {
20026
- stdout() {
20027
- },
20028
- stderr(text) {
20029
- chunks.push(text);
20030
- }
20364
+ import { resolve as resolve14 } from "node:path";
20365
+ function reviewerMethods(packageRoot) {
20366
+ return [{ kind: "skill", path: resolvePackagedMethodSkillPath(packageRoot, "ak-cross-m-review") }];
20367
+ }
20368
+ async function runReviewerTurnInFreshCopy(env, projectRoot, io, body) {
20369
+ if (env.executionCwd !== void 0) {
20370
+ return body(env);
20371
+ }
20372
+ const { withEphemeralReviewerWorktree: withEphemeralReviewerWorktree2 } = await Promise.resolve().then(() => (init_public_role_summons(), public_role_summons_exports));
20373
+ return await withEphemeralReviewerWorktree2({
20374
+ projectRoot,
20375
+ onCleanupDiagnostic: (diagnostic) => {
20376
+ io.stderr(`${diagnostic}
20377
+ `);
20031
20378
  },
20032
- stderrText: () => chunks.join("")
20033
- };
20379
+ run: (executionCwd) => body({ ...env, executionCwd })
20380
+ });
20034
20381
  }
20035
- function parentDir(path) {
20036
- const end = path.endsWith("/") || path.endsWith("\\") ? path.slice(0, -1) : path;
20382
+ function buildReviewerTurnRequest(admitted, options) {
20383
+ return projectRoleTurnRequest(
20384
+ admitted,
20385
+ {
20386
+ activation: {
20387
+ role: "reviewer",
20388
+ baseRevision: admitted.baseRevision,
20389
+ lens: admitted.lens,
20390
+ authorityRefs: admitted.authorityRefs,
20391
+ ...admitted.ticketNumber === void 0 ? {} : { ticketNumber: admitted.ticketNumber }
20392
+ },
20393
+ methods: reviewerMethods(options.packageRoot)
20394
+ },
20395
+ options
20396
+ );
20397
+ }
20398
+ function reviewerAdapters(packageRoot, methodMaterial) {
20399
+ return {
20400
+ trySettle: (admitted, authority, scope) => methodMaterial === void 0 ? Promise.resolve(void 0) : trySettleReviewerTerminalResult(
20401
+ admitted,
20402
+ authority,
20403
+ {
20404
+ methodProvenance: methodMaterial.provenance,
20405
+ methodSkillPath: methodMaterial.skillPath,
20406
+ methodSkillConfiguredPath: resolvePackagedMethodSkillPath(
20407
+ packageRoot,
20408
+ "ak-cross-m-review"
20409
+ )
20410
+ },
20411
+ scope
20412
+ ),
20413
+ resolveRunnerKnownFailure: async ({ result, sessionFile }) => {
20414
+ const infrastructureFailure = await readEngineDetourInfrastructureFailure(sessionFile);
20415
+ return infrastructureFailure === void 0 ? result.knownFailure : {
20416
+ ...infrastructureFailure.cause === void 0 ? {} : { cause: infrastructureFailure.cause },
20417
+ diagnostic: infrastructureFailure.diagnostic,
20418
+ ...infrastructureFailure.identity === void 0 ? {} : { identity: infrastructureFailure.identity }
20419
+ };
20420
+ }
20421
+ };
20422
+ }
20423
+ async function loadReviewerMethodMaterial(packageRoot) {
20424
+ return await loadPackagedMethodSkillMaterial(packageRoot, "ak-cross-m-review");
20425
+ }
20426
+ function reviewerResumePrompt(env, message) {
20427
+ const lines = [RESUME_TRANSPORT_ENVELOPE];
20428
+ if (message !== void 0) lines.push("", message);
20429
+ return appendEngineSessionMaterial(
20430
+ lines,
20431
+ engineSessionMaterialFromOptions({
20432
+ ...pickEngineAxis(env),
20433
+ packageRoot: env.packageRoot
20434
+ })
20435
+ ).join("\n");
20436
+ }
20437
+ async function runPublicReviewer(argv, env, io, parseReviewerArgv2) {
20438
+ let parsed;
20439
+ try {
20440
+ parsed = parseReviewerArgv2(argv);
20441
+ } catch (error) {
20442
+ if (error instanceof CliUsageError) {
20443
+ presentStructuralRejection(error, io);
20444
+ return { exitCode: 2 };
20445
+ }
20446
+ throw error;
20447
+ }
20448
+ if (parsed.lens === void 0) {
20449
+ const { summonParallelReviewerLenses: summonParallelReviewerLenses2 } = await Promise.resolve().then(() => (init_public_role_summons(), public_role_summons_exports));
20450
+ const children = await summonParallelReviewerLenses2({
20451
+ argv,
20452
+ // Replay argv under the same cwd the single-axis entry would see (10a).
20453
+ // Do not substitute the resolved project path — relative --project must
20454
+ // not be re-resolved against a shifted cwd.
20455
+ cwd: env.cwd,
20456
+ projectRoot: resolve14(parsed.project ?? env.cwd),
20457
+ // Typed base from the public parse — precheck only; child argv stays verbatim.
20458
+ baseRevision: parsed.baseRevision,
20459
+ home: env.home,
20460
+ agentDir: env.agentDir,
20461
+ ...env.credentials === void 0 ? {} : { credentials: env.credentials },
20462
+ ...env.model === void 0 ? {} : { model: env.model },
20463
+ ...env.host === void 0 ? {} : { host: env.host },
20464
+ ...env.engine === void 0 ? {} : { engine: env.engine },
20465
+ ...env.engineModel === void 0 ? {} : { engineModel: env.engineModel },
20466
+ packageRoot: env.packageRoot,
20467
+ ...env.signal === void 0 ? {} : { signal: env.signal },
20468
+ ...env.correlationId === void 0 ? {} : { correlationId: env.correlationId },
20469
+ roleTurnHost: env.roleTurnHost,
20470
+ ...env.hostAdapters === void 0 ? {} : { hostAdapters: env.hostAdapters },
20471
+ principalAuthority: env.principalAuthority,
20472
+ ...env.timeoutMs === void 0 ? {} : { timeoutMs: env.timeoutMs }
20473
+ });
20474
+ const childResults = [children.completeness, children.correctness];
20475
+ const terminals = childResults.map((child) => child.terminal).filter((terminal2) => terminal2 !== void 0);
20476
+ const failedChildren = childResults.filter((child) => child.terminal === void 0 || !isLawfulTypedTerminalOutcome(child.terminal.roleOutcome)).length;
20477
+ const overlayExit = childResults.some((child) => child.exitCode !== 0);
20478
+ const failed = failedChildren > 0 || overlayExit;
20479
+ const overlayDiagnostics = [...new Set(
20480
+ childResults.map((child) => child.stderr).filter((text) => typeof text === "string" && text !== "")
20481
+ )];
20482
+ const terminal = {
20483
+ batch: "reviewer",
20484
+ roleOutcome: failed ? {
20485
+ kind: "failure",
20486
+ role: "reviewer",
20487
+ diagnostic: failedChildren > 0 ? "Reviewer batch child failure" : overlayDiagnostics[0] ?? "Reviewer batch infrastructure failure",
20488
+ decisiveFacts: { failedChildren },
20489
+ payloads: terminals
20490
+ } : { kind: "accepted", role: "reviewer", payloads: terminals },
20491
+ reviewerChildren: {
20492
+ ...children.completeness.terminal === void 0 ? {} : { completeness: children.completeness.terminal },
20493
+ ...children.correctness.terminal === void 0 ? {} : { correctness: children.correctness.terminal }
20494
+ },
20495
+ reviewerChildOutcomes: {
20496
+ completeness: { exitCode: children.completeness.exitCode, ...children.completeness.stderr === void 0 ? {} : { stderr: children.completeness.stderr } },
20497
+ correctness: { exitCode: children.correctness.exitCode, ...children.correctness.stderr === void 0 ? {} : { stderr: children.correctness.stderr } }
20498
+ },
20499
+ // Batch has no parent run and no own attendance; no-advice is affirmative
20500
+ // only (navigator-attendance.ts). Children carry their own navigator facts.
20501
+ navigator: {
20502
+ disposition: "unavailable",
20503
+ source: "unknown",
20504
+ reason: "Reviewer batch has no parent-run Navigator attendance"
20505
+ },
20506
+ artifacts: terminals.flatMap((item) => item.artifacts)
20507
+ };
20508
+ io.stdout(formatTerminalResult(terminal));
20509
+ return { exitCode: failed ? 1 : 0, terminal };
20510
+ }
20511
+ let admitted;
20512
+ try {
20513
+ admitted = await admitReviewerInvocation({
20514
+ home: env.home,
20515
+ principalAuthority: env.principalAuthority,
20516
+ cwd: env.cwd,
20517
+ instruction: parsed.instruction,
20518
+ attachmentPaths: parsed.attachmentPaths,
20519
+ baseRevision: parsed.baseRevision,
20520
+ lens: parsed.lens,
20521
+ authorityRefs: parsed.authorityRefs,
20522
+ ...parsed.project === void 0 ? {} : { project: parsed.project },
20523
+ ...env.createRunId === void 0 ? {} : { createRunId: env.createRunId },
20524
+ ...env.correlationId === void 0 ? {} : { correlationId: env.correlationId },
20525
+ ...env.model === void 0 ? {} : { model: env.model }
20526
+ });
20527
+ } catch (error) {
20528
+ if (error instanceof CliUsageError) {
20529
+ presentStructuralRejection(error, io);
20530
+ return { exitCode: 2 };
20531
+ }
20532
+ throw error;
20533
+ }
20534
+ await markRunAdmitted(admitted, env.principalAuthority);
20535
+ let methodMaterial;
20536
+ try {
20537
+ methodMaterial = await loadReviewerMethodMaterial(env.packageRoot);
20538
+ } catch (error) {
20539
+ return await presentControlledFailure2(
20540
+ admitted,
20541
+ {
20542
+ timedOut: false,
20543
+ code: null,
20544
+ stderr: "",
20545
+ thrown: error
20546
+ },
20547
+ reviewerAdapters(env.packageRoot),
20548
+ env.principalAuthority,
20549
+ io
20550
+ );
20551
+ }
20552
+ try {
20553
+ return await runReviewerTurnInFreshCopy(env, admitted.projectRoot, io, async (sandboxedEnv) => await runPostAdmissionResumable({
20554
+ admitted,
20555
+ env: sandboxedEnv,
20556
+ io,
20557
+ buildInitialRequest: () => buildReviewerTurnRequest(admitted, {
20558
+ packageRoot: sandboxedEnv.packageRoot,
20559
+ home: sandboxedEnv.home,
20560
+ agentDir: sandboxedEnv.agentDir,
20561
+ ...sandboxedEnv.model === void 0 ? {} : { model: sandboxedEnv.model },
20562
+ ...pickEngineAxis(sandboxedEnv),
20563
+ ...sandboxedEnv.timeoutMs === void 0 ? {} : { timeoutMs: sandboxedEnv.timeoutMs },
20564
+ ...admitted.correlationId === void 0 && sandboxedEnv.correlationId === void 0 ? {} : { correlationId: admitted.correlationId ?? sandboxedEnv.correlationId },
20565
+ // Ephemeral worktree cwd; durable projectRoot stays on admitted caller project.
20566
+ ...sandboxedEnv.executionCwd === void 0 ? {} : { cwd: sandboxedEnv.executionCwd },
20567
+ continuation: {
20568
+ kind: "initial",
20569
+ prompt: buildReviewerTransportPrompt(
20570
+ admitted,
20571
+ engineSessionMaterialFromOptions({
20572
+ ...pickEngineAxis(sandboxedEnv),
20573
+ packageRoot: sandboxedEnv.packageRoot
20574
+ })
20575
+ )
20576
+ }
20577
+ }),
20578
+ buildResumeRequest: () => buildReviewerTurnRequest(admitted, {
20579
+ packageRoot: sandboxedEnv.packageRoot,
20580
+ home: sandboxedEnv.home,
20581
+ agentDir: sandboxedEnv.agentDir,
20582
+ ...sandboxedEnv.model === void 0 ? {} : { model: sandboxedEnv.model },
20583
+ ...pickEngineAxis(sandboxedEnv),
20584
+ ...sandboxedEnv.timeoutMs === void 0 ? {} : { timeoutMs: sandboxedEnv.timeoutMs },
20585
+ ...admitted.correlationId === void 0 && sandboxedEnv.correlationId === void 0 ? {} : { correlationId: admitted.correlationId ?? sandboxedEnv.correlationId },
20586
+ // In-batch auto-resume keeps the same call's sandbox (dual-lens or single).
20587
+ ...sandboxedEnv.executionCwd === void 0 ? {} : { cwd: sandboxedEnv.executionCwd },
20588
+ continuation: {
20589
+ kind: "resume",
20590
+ prompt: reviewerResumePrompt(sandboxedEnv)
20591
+ }
20592
+ }),
20593
+ adapters: reviewerAdapters(sandboxedEnv.packageRoot, methodMaterial),
20594
+ ...sandboxedEnv.engine === void 0 ? {} : { effectiveEngine: sandboxedEnv.engine }
20595
+ }));
20596
+ } catch (error) {
20597
+ return await presentControlledFailure2(
20598
+ admitted,
20599
+ {
20600
+ timedOut: false,
20601
+ code: null,
20602
+ stderr: "",
20603
+ thrown: error
20604
+ },
20605
+ reviewerAdapters(env.packageRoot, methodMaterial),
20606
+ env.principalAuthority,
20607
+ io
20608
+ );
20609
+ }
20610
+ }
20611
+ async function runPublicReviewerResume(request, env, io) {
20612
+ const sandbox = {
20613
+ ...env.executionCwd === void 0 ? {} : { executionCwd: env.executionCwd }
20614
+ };
20615
+ return await runPostAdmissionSeatResume({
20616
+ request,
20617
+ env,
20618
+ io,
20619
+ load: (effective) => loadResumableReviewerRun(env.home, effective.runId, env.principalAuthority),
20620
+ buildTurnRequest: (admitted, effective) => {
20621
+ const activeEnv = sandbox.executionCwd === void 0 ? env : { ...env, executionCwd: sandbox.executionCwd };
20622
+ const base = resumeTurnRequestProjectionOptions(admitted, effective, activeEnv);
20623
+ return buildReviewerTurnRequest(admitted, {
20624
+ ...base,
20625
+ // Fresh copy at resume time; durable projectRoot unchanged.
20626
+ ...sandbox.executionCwd === void 0 ? {} : { cwd: sandbox.executionCwd },
20627
+ continuation: {
20628
+ kind: "resume",
20629
+ prompt: reviewerResumePrompt(activeEnv, effective.message)
20630
+ }
20631
+ });
20632
+ },
20633
+ adapters: reviewerAdapters(env.packageRoot),
20634
+ afterAdmittedLoad: async (admitted) => {
20635
+ return resolveResumeMethodMaterialAdapters({
20636
+ admitted,
20637
+ authority: env.principalAuthority,
20638
+ io,
20639
+ loadMaterial: () => loadReviewerMethodMaterial(env.packageRoot),
20640
+ adaptersWith: (material) => reviewerAdapters(env.packageRoot, material),
20641
+ emptyAdapters: reviewerAdapters(env.packageRoot)
20642
+ });
20643
+ },
20644
+ afterAdmittedPrepare: async (admitted) => {
20645
+ if (sandbox.executionCwd !== void 0) {
20646
+ return { env: { ...env, executionCwd: sandbox.executionCwd } };
20647
+ }
20648
+ const { openEphemeralReviewerWorktree: openEphemeralReviewerWorktree2 } = await Promise.resolve().then(() => (init_public_role_summons(), public_role_summons_exports));
20649
+ const opened = await openEphemeralReviewerWorktree2({
20650
+ projectRoot: admitted.projectRoot,
20651
+ onCleanupDiagnostic: (diagnostic) => {
20652
+ io.stderr(`${diagnostic}
20653
+ `);
20654
+ }
20655
+ });
20656
+ sandbox.executionCwd = opened.executionCwd;
20657
+ return {
20658
+ env: { ...env, executionCwd: opened.executionCwd },
20659
+ cleanup: opened.close
20660
+ };
20661
+ },
20662
+ ...env.engine === void 0 ? {} : { effectiveEngine: env.engine }
20663
+ });
20664
+ }
20665
+ var init_reviewer_run = __esm({
20666
+ "src/public-cli/reviewer-run.ts"() {
20667
+ "use strict";
20668
+ init_engine_material();
20669
+ init_method_skill();
20670
+ init_cli_errors();
20671
+ init_invocation();
20672
+ init_run_lifecycle();
20673
+ init_settlement();
20674
+ init_terminal();
20675
+ init_turn_request();
20676
+ init_post_admission();
20677
+ }
20678
+ });
20679
+
20680
+ // src/public-role-summons.ts
20681
+ var public_role_summons_exports = {};
20682
+ __export(public_role_summons_exports, {
20683
+ AK_ROLE_PACKAGE_ROOT_ENV: () => AK_ROLE_PACKAGE_ROOT_ENV,
20684
+ openEphemeralReviewerWorktree: () => openEphemeralReviewerWorktree,
20685
+ resolveSummonsPackageRoot: () => resolveSummonsPackageRoot,
20686
+ summonGateOfficer: () => summonGateOfficer,
20687
+ summonParallelReviewerLenses: () => summonParallelReviewerLenses,
20688
+ summonPublicRole: () => summonPublicRole,
20689
+ withEphemeralReviewerWorktree: () => withEphemeralReviewerWorktree
20690
+ });
20691
+ import { execFile as execFile3 } from "node:child_process";
20692
+ import { existsSync as existsSync10 } from "node:fs";
20693
+ import { mkdir as mkdir5, mkdtemp as mkdtemp4, realpath as realpath7, rm as rm4 } from "node:fs/promises";
20694
+ import { tmpdir as tmpdir4 } from "node:os";
20695
+ import { join as join33, relative as relative3, sep as sep5 } from "node:path";
20696
+ import { promisify as promisify3 } from "node:util";
20697
+ function createCapturingIo() {
20698
+ const chunks = [];
20699
+ return {
20700
+ io: {
20701
+ stdout() {
20702
+ },
20703
+ stderr(text) {
20704
+ chunks.push(text);
20705
+ }
20706
+ },
20707
+ stderrText: () => chunks.join("")
20708
+ };
20709
+ }
20710
+ function parentDir(path) {
20711
+ const end = path.endsWith("/") || path.endsWith("\\") ? path.slice(0, -1) : path;
20037
20712
  const idx = Math.max(end.lastIndexOf("/"), end.lastIndexOf("\\"));
20038
20713
  if (idx <= 0) return end;
20039
20714
  return end.slice(0, idx);
@@ -20106,13 +20781,14 @@ async function createSummonEnv(options, afterHost) {
20106
20781
  Promise.resolve().then(() => (init_role_turn_host_resolution(), role_turn_host_resolution_exports)),
20107
20782
  Promise.resolve().then(() => (init_config(), config_exports))
20108
20783
  ]);
20109
- const principalAuthority = piDurablePrincipalAuthority2;
20784
+ const principalAuthority = options.principalAuthority ?? piDurablePrincipalAuthority2;
20110
20785
  const roleTurnHost = resolveRoleTurnHost2(
20111
20786
  {
20112
20787
  packageRoot: options.packageRoot,
20113
20788
  ...options.roleTurnHost === void 0 ? {} : { roleTurnHost: options.roleTurnHost },
20114
20789
  ...options.hostAdapters === void 0 ? {} : { hostAdapters: options.hostAdapters },
20115
- ...options.extraPiArgs === void 0 || options.extraPiArgs.length === 0 ? {} : { extraPiArgs: options.extraPiArgs }
20790
+ ...options.extraPiArgs === void 0 || options.extraPiArgs.length === 0 ? {} : { extraPiArgs: options.extraPiArgs },
20791
+ ...options.timeoutMs === void 0 ? {} : { timeoutMs: options.timeoutMs }
20116
20792
  },
20117
20793
  { role: options.role, seat: options.seat, principalAuthority }
20118
20794
  );
@@ -20125,13 +20801,16 @@ async function createSummonEnv(options, afterHost) {
20125
20801
  };
20126
20802
  }
20127
20803
  const hostName = seatWithModel.host ?? "pi";
20128
- const { loadHostProvidersTable: loadHostProvidersTable2, projectHostFacingProvider: projectHostFacingProvider2 } = await Promise.resolve().then(() => (init_host_providers(), host_providers_exports));
20129
- const hostFacingSelection = projectHostFacingProvider2(
20130
- seatWithModel.selection,
20131
- hostName,
20132
- loadHostProvidersTable2(options.home),
20133
- options.home
20134
- );
20804
+ let hostFacingSelection = options.hostFacingModel;
20805
+ if (hostFacingSelection === void 0) {
20806
+ const { loadHostProvidersTable: loadHostProvidersTable2, projectHostFacingProvider: projectHostFacingProvider2 } = await Promise.resolve().then(() => (init_host_providers(), host_providers_exports));
20807
+ hostFacingSelection = projectHostFacingProvider2(
20808
+ seatWithModel.selection,
20809
+ hostName,
20810
+ loadHostProvidersTable2(options.home),
20811
+ options.home
20812
+ );
20813
+ }
20135
20814
  return {
20136
20815
  ok: true,
20137
20816
  env: {
@@ -20145,7 +20824,8 @@ async function createSummonEnv(options, afterHost) {
20145
20824
  credentials: options.credentials,
20146
20825
  ...hostFacingSelection === void 0 ? {} : { model: hostFacingSelection },
20147
20826
  ...projectSeatEngine(seatWithModel),
20148
- ...projectSeatHost(seatWithModel)
20827
+ ...projectSeatHost(seatWithModel),
20828
+ ...options.timeoutMs === void 0 ? {} : { timeoutMs: options.timeoutMs }
20149
20829
  }
20150
20830
  };
20151
20831
  }
@@ -20160,7 +20840,19 @@ async function summonPublicRole(options) {
20160
20840
  } = await Promise.resolve().then(() => (init_config(), config_exports));
20161
20841
  const credentials = options.credentials ?? await loadCredentialProviders2(agentDir);
20162
20842
  const config = await loadPublicCliConfig2(home);
20163
- const seat = resolveEffectiveSeat2(config, options.role, credentials);
20843
+ const resolvedSeat = resolveEffectiveSeat2(config, options.role, credentials);
20844
+ const inheritedSelection = options.model === void 0 ? void 0 : {
20845
+ provider: options.model.provider,
20846
+ model: options.model.model,
20847
+ ...options.model.thinking === void 0 ? {} : { thinking: options.model.thinking }
20848
+ };
20849
+ const seat = {
20850
+ ...resolvedSeat,
20851
+ ...inheritedSelection === void 0 ? {} : { selection: inheritedSelection, source: "invocation" },
20852
+ ...options.host === void 0 ? {} : { host: options.host, hostSource: "invocation" },
20853
+ ...options.engine === void 0 ? {} : { engine: options.engine, engineSource: "invocation" },
20854
+ ...options.engineModel === void 0 ? {} : { engineModel: options.engineModel }
20855
+ };
20164
20856
  const captured = options.io === void 0 ? createCapturingIo() : void 0;
20165
20857
  const io = options.io ?? captured.io;
20166
20858
  const summonEnvInput = {
@@ -20173,7 +20865,11 @@ async function summonPublicRole(options) {
20173
20865
  seat,
20174
20866
  ...options.extraPiArgs === void 0 ? {} : { extraPiArgs: options.extraPiArgs },
20175
20867
  ...options.roleTurnHost === void 0 ? {} : { roleTurnHost: options.roleTurnHost },
20176
- ...options.hostAdapters === void 0 ? {} : { hostAdapters: options.hostAdapters }
20868
+ ...options.hostAdapters === void 0 ? {} : { hostAdapters: options.hostAdapters },
20869
+ ...options.principalAuthority === void 0 ? {} : { principalAuthority: options.principalAuthority },
20870
+ ...options.timeoutMs === void 0 ? {} : { timeoutMs: options.timeoutMs },
20871
+ // Parent model is already host-facing; child must not project again.
20872
+ ...options.model === void 0 ? {} : { hostFacingModel: options.model }
20177
20873
  };
20178
20874
  async function prepareSummonEnv(afterHost) {
20179
20875
  try {
@@ -20185,7 +20881,9 @@ async function summonPublicRole(options) {
20185
20881
  ok: true,
20186
20882
  env: {
20187
20883
  ...built.env,
20188
- stationChild: true,
20884
+ // Nested court stations keep station-child semantics; dual-lens
20885
+ // ordinary Reviewer axes opt out (#946 / ADR 0082).
20886
+ ...options.stationChild === false ? {} : { stationChild: true },
20189
20887
  // Forward composition-root adapters so nested court stations (e.g.
20190
20888
  // countersign → diarist) select the same faux/production table (#924).
20191
20889
  ...options.hostAdapters === void 0 ? {} : { hostAdapters: options.hostAdapters },
@@ -20195,7 +20893,8 @@ async function summonPublicRole(options) {
20195
20893
  ...options.gateReviewInstruction === void 0 ? {} : { gateReviewInstruction: options.gateReviewInstruction },
20196
20894
  ...options.boundTicketNumber === void 0 ? {} : { boundTicketNumber: options.boundTicketNumber },
20197
20895
  ...options.correlationId === void 0 || options.correlationId.trim() === "" ? {} : { correlationId: options.correlationId },
20198
- ...options.createRunId === void 0 ? {} : { createRunId: options.createRunId }
20896
+ ...options.createRunId === void 0 ? {} : { createRunId: options.createRunId },
20897
+ ...options.executionCwd === void 0 ? {} : { executionCwd: options.executionCwd }
20199
20898
  }
20200
20899
  };
20201
20900
  } catch (error) {
@@ -20257,14 +20956,32 @@ async function summonPublicRole(options) {
20257
20956
  case "navigator":
20258
20957
  case "gatekeeper": {
20259
20958
  const seat2 = options.role;
20260
- const [{ runPublicInstructionSeat: runPublicInstructionSeat2 }, invocation] = await Promise.all([
20959
+ const [{ runPublicInstructionSeat: runPublicInstructionSeat2, runPublicInstructionSeatResume: runPublicInstructionSeatResume2 }, invocation] = await Promise.all([
20261
20960
  Promise.resolve().then(() => (init_instruction_seat_run(), instruction_seat_run_exports)),
20262
20961
  Promise.resolve().then(() => (init_invocation(), invocation_exports))
20263
20962
  ]);
20264
20963
  const parse = seat2 === "auditor" ? invocation.parseAuditorArgv : seat2 === "navigator" ? invocation.parseNavigatorArgv : invocation.parseGatekeeperArgv;
20265
- const stepped = await runPrepared(parse, (env, once) => runPublicInstructionSeat2(options.argv, env, io, seat2, once));
20266
- if ("fail" in stepped) return stepped.fail;
20267
- result = stepped.ok;
20964
+ const resumeRunId = typeof options.resumeRunId === "string" && options.resumeRunId.trim() !== "" ? options.resumeRunId.trim() : void 0;
20965
+ if (resumeRunId !== void 0) {
20966
+ const instruction = options.argv[0] ?? "";
20967
+ const stepped = await runPrepared(parse, (env) => runPublicInstructionSeatResume2(
20968
+ {
20969
+ runId: resumeRunId,
20970
+ summons: {
20971
+ instruction,
20972
+ instructionEmpty: instruction.trim() === ""
20973
+ }
20974
+ },
20975
+ env,
20976
+ io
20977
+ ));
20978
+ if ("fail" in stepped) return stepped.fail;
20979
+ result = stepped.ok;
20980
+ } else {
20981
+ const stepped = await runPrepared(parse, (env, once) => runPublicInstructionSeat2(options.argv, env, io, seat2, once));
20982
+ if ("fail" in stepped) return stepped.fail;
20983
+ result = stepped.ok;
20984
+ }
20268
20985
  break;
20269
20986
  }
20270
20987
  case "judge": {
@@ -20307,6 +21024,16 @@ async function summonPublicRole(options) {
20307
21024
  result = stepped.ok;
20308
21025
  break;
20309
21026
  }
21027
+ case "reviewer": {
21028
+ const [{ runPublicReviewer: runPublicReviewer2 }, { parseReviewerArgv: parseReviewerArgv2 }] = await Promise.all([
21029
+ Promise.resolve().then(() => (init_reviewer_run(), reviewer_run_exports)),
21030
+ Promise.resolve().then(() => (init_invocation(), invocation_exports))
21031
+ ]);
21032
+ const stepped = await runPrepared(parseReviewerArgv2, (env, once) => runPublicReviewer2(options.argv, env, io, once));
21033
+ if ("fail" in stepped) return stepped.fail;
21034
+ result = stepped.ok;
21035
+ break;
21036
+ }
20310
21037
  }
20311
21038
  const stderr = captured?.stderrText();
20312
21039
  const runDirectory = result.admitted?.runDirectory;
@@ -20318,6 +21045,296 @@ async function summonPublicRole(options) {
20318
21045
  ...stderr === void 0 || stderr === "" ? {} : { stderr }
20319
21046
  };
20320
21047
  }
21048
+ function withReviewerLens(argv, lens) {
21049
+ const separator = argv.indexOf("--");
21050
+ if (separator === -1) return [...argv, "--lens", lens];
21051
+ return [...argv.slice(0, separator), "--lens", lens, ...argv.slice(separator)];
21052
+ }
21053
+ async function resolveReviewerWorktreeRoots(projectRoot) {
21054
+ const callerProjectRoot = await realpath7(projectRoot);
21055
+ const sourceProjectRoot = await realpath7((await execFileAsync3(
21056
+ "git",
21057
+ ["rev-parse", "--show-toplevel"],
21058
+ { cwd: callerProjectRoot }
21059
+ )).stdout.trim());
21060
+ const callerRelative = relative3(sourceProjectRoot, callerProjectRoot);
21061
+ const projectRelative = callerRelative === "" || callerRelative === "." || callerRelative.startsWith(`..${sep5}`) || callerRelative === ".." ? "" : callerRelative;
21062
+ return { callerProjectRoot, sourceProjectRoot, projectRelative };
21063
+ }
21064
+ function reviewerSandboxPath(worktreeAxis, projectRelative) {
21065
+ return projectRelative === "" ? worktreeAxis : join33(worktreeAxis, projectRelative);
21066
+ }
21067
+ async function openEphemeralReviewerWorktree(options) {
21068
+ const { sourceProjectRoot, projectRelative } = await resolveReviewerWorktreeRoots(
21069
+ options.projectRoot
21070
+ );
21071
+ const { stdout: headStdout } = await execFileAsync3(
21072
+ "git",
21073
+ ["rev-parse", "--verify", "HEAD^{commit}"],
21074
+ { cwd: sourceProjectRoot }
21075
+ );
21076
+ const targetCommit = headStdout.trim();
21077
+ const root = await mkdtemp4(join33(tmpdir4(), "ak-reviewer-sandbox-"));
21078
+ const worktreeRoot = join33(root, "work");
21079
+ let registered = false;
21080
+ const rollback = async (cause) => {
21081
+ const cleanupErrors = [];
21082
+ if (registered) {
21083
+ try {
21084
+ await execFileAsync3("git", ["worktree", "remove", "--force", worktreeRoot], {
21085
+ cwd: sourceProjectRoot
21086
+ });
21087
+ } catch (error) {
21088
+ cleanupErrors.push(error);
21089
+ }
21090
+ }
21091
+ try {
21092
+ await rm4(root, { recursive: true, force: true });
21093
+ } catch (error) {
21094
+ cleanupErrors.push(error);
21095
+ }
21096
+ if (cleanupErrors.length > 0) {
21097
+ options.onCleanupDiagnostic?.([
21098
+ "reviewer worktree cleanup failed",
21099
+ ...cleanupErrors.map((error) => error instanceof Error ? error.message : String(error))
21100
+ ].join("\n"));
21101
+ }
21102
+ throw cause;
21103
+ };
21104
+ try {
21105
+ await execFileAsync3("git", ["worktree", "add", "--detach", worktreeRoot, targetCommit], {
21106
+ cwd: sourceProjectRoot
21107
+ });
21108
+ registered = true;
21109
+ if (projectRelative !== "") {
21110
+ await mkdir5(reviewerSandboxPath(worktreeRoot, projectRelative), { recursive: true });
21111
+ }
21112
+ } catch (error) {
21113
+ await rollback(error);
21114
+ }
21115
+ let closed = false;
21116
+ return {
21117
+ executionCwd: reviewerSandboxPath(worktreeRoot, projectRelative),
21118
+ close: async () => {
21119
+ if (closed) return;
21120
+ closed = true;
21121
+ const cleanupErrors = [];
21122
+ try {
21123
+ await execFileAsync3("git", ["worktree", "remove", worktreeRoot], {
21124
+ cwd: sourceProjectRoot
21125
+ });
21126
+ } catch (error) {
21127
+ cleanupErrors.push(error);
21128
+ }
21129
+ try {
21130
+ await rm4(root, { recursive: true, force: true });
21131
+ } catch (error) {
21132
+ cleanupErrors.push(error);
21133
+ }
21134
+ if (cleanupErrors.length > 0) {
21135
+ options.onCleanupDiagnostic?.([
21136
+ "reviewer worktree cleanup failed",
21137
+ ...cleanupErrors.map((error) => error instanceof Error ? error.message : String(error))
21138
+ ].join("\n"));
21139
+ }
21140
+ }
21141
+ };
21142
+ }
21143
+ async function withEphemeralReviewerWorktree(options) {
21144
+ const sandbox = await openEphemeralReviewerWorktree({
21145
+ projectRoot: options.projectRoot,
21146
+ ...options.onCleanupDiagnostic === void 0 ? {} : { onCleanupDiagnostic: options.onCleanupDiagnostic }
21147
+ });
21148
+ try {
21149
+ return await options.run(sandbox.executionCwd);
21150
+ } finally {
21151
+ await sandbox.close();
21152
+ }
21153
+ }
21154
+ async function summonParallelReviewerLenses(options) {
21155
+ const describeFailure = (error) => {
21156
+ if (error instanceof AggregateError) {
21157
+ return [error.message, ...error.errors.map(describeFailure)].join("\n");
21158
+ }
21159
+ return error instanceof Error ? error.message : String(error);
21160
+ };
21161
+ const failedResult = (error) => ({
21162
+ exitCode: 1,
21163
+ stderr: describeFailure(error)
21164
+ });
21165
+ const dualFailure = (error) => {
21166
+ const failure2 = failedResult(error);
21167
+ return { completeness: failure2, correctness: failure2 };
21168
+ };
21169
+ let sourceProjectRoot;
21170
+ let projectRelative;
21171
+ let targetCommit;
21172
+ const statusArgs = [
21173
+ "status",
21174
+ "--porcelain=v1",
21175
+ "--untracked-files=all",
21176
+ "--",
21177
+ ":/",
21178
+ ":(top,exclude).claude/worktrees/**"
21179
+ ];
21180
+ try {
21181
+ const roots = await resolveReviewerWorktreeRoots(options.projectRoot);
21182
+ sourceProjectRoot = roots.sourceProjectRoot;
21183
+ projectRelative = roots.projectRelative;
21184
+ const { stdout: statusStdout } = await execFileAsync3("git", statusArgs, {
21185
+ cwd: sourceProjectRoot
21186
+ });
21187
+ if (statusStdout !== "") {
21188
+ const diagnostic = [
21189
+ "Reviewer target status gate failed:",
21190
+ "git status --porcelain=v1 --untracked-files=all -- :/ ':(top,exclude).claude/worktrees/**'",
21191
+ statusStdout
21192
+ ].join("\n");
21193
+ return dualFailure(new Error(diagnostic));
21194
+ }
21195
+ const { stdout: targetStdout } = await execFileAsync3(
21196
+ "git",
21197
+ ["rev-parse", "--verify", "HEAD^{commit}"],
21198
+ { cwd: sourceProjectRoot }
21199
+ );
21200
+ targetCommit = targetStdout.trim();
21201
+ await execFileAsync3(
21202
+ "git",
21203
+ ["rev-parse", "--verify", `${options.baseRevision}^{commit}`],
21204
+ { cwd: sourceProjectRoot }
21205
+ );
21206
+ } catch (error) {
21207
+ return dualFailure(error);
21208
+ }
21209
+ const root = await mkdtemp4(join33(tmpdir4(), "ak-reviewer-lenses-"));
21210
+ const completenessRoot = join33(root, "completeness");
21211
+ const correctnessRoot = join33(root, "correctness");
21212
+ const worktrees = [completenessRoot, correctnessRoot];
21213
+ const created = /* @__PURE__ */ new Set();
21214
+ let results;
21215
+ const creation = await Promise.allSettled(
21216
+ worktrees.map(async (path) => {
21217
+ await execFileAsync3("git", ["worktree", "add", "--detach", path, targetCommit], {
21218
+ cwd: sourceProjectRoot
21219
+ });
21220
+ created.add(path);
21221
+ if (projectRelative !== "") {
21222
+ await mkdir5(reviewerSandboxPath(path, projectRelative), { recursive: true });
21223
+ }
21224
+ })
21225
+ );
21226
+ const creationFailures = creation.flatMap((result) => result.status === "rejected" ? [result.reason] : []);
21227
+ if (creationFailures.length > 0) {
21228
+ const failure2 = failedResult(new AggregateError(
21229
+ creationFailures,
21230
+ "parallel reviewer worktree creation failed"
21231
+ ));
21232
+ results = { completeness: failure2, correctness: failure2 };
21233
+ } else {
21234
+ const summon = (lens, worktreeAxis) => {
21235
+ const sandbox = reviewerSandboxPath(worktreeAxis, projectRelative);
21236
+ return summonPublicRole({
21237
+ role: "reviewer",
21238
+ argv: withReviewerLens(options.argv, lens),
21239
+ cwd: options.cwd,
21240
+ executionCwd: sandbox,
21241
+ // Ordinary single-axis public semantics — not a nested court station.
21242
+ stationChild: false,
21243
+ home: options.home,
21244
+ ...options.agentDir === void 0 ? {} : { agentDir: options.agentDir },
21245
+ ...options.credentials === void 0 ? {} : { credentials: options.credentials },
21246
+ ...options.model === void 0 ? {} : { model: options.model },
21247
+ ...options.host === void 0 ? {} : { host: options.host },
21248
+ ...options.engine === void 0 ? {} : { engine: options.engine },
21249
+ ...options.engineModel === void 0 ? {} : { engineModel: options.engineModel },
21250
+ ...options.signal === void 0 ? {} : { signal: options.signal },
21251
+ ...options.correlationId === void 0 ? {} : { correlationId: options.correlationId },
21252
+ ...options.packageRoot === void 0 ? {} : { packageRoot: options.packageRoot },
21253
+ ...options.roleTurnHost === void 0 ? {} : { roleTurnHost: options.roleTurnHost },
21254
+ ...options.hostAdapters === void 0 ? {} : { hostAdapters: options.hostAdapters },
21255
+ ...options.principalAuthority === void 0 ? {} : { principalAuthority: options.principalAuthority },
21256
+ ...options.timeoutMs === void 0 ? {} : { timeoutMs: options.timeoutMs }
21257
+ });
21258
+ };
21259
+ const settled = await Promise.allSettled([
21260
+ summon("completeness", completenessRoot),
21261
+ summon("correctness", correctnessRoot)
21262
+ ]);
21263
+ results = {
21264
+ completeness: settled[0].status === "fulfilled" ? settled[0].value : failedResult(settled[0].reason),
21265
+ correctness: settled[1].status === "fulfilled" ? settled[1].value : failedResult(settled[1].reason)
21266
+ };
21267
+ }
21268
+ let sealDiagnostic;
21269
+ try {
21270
+ const { stdout: headBeforeStdout } = await execFileAsync3(
21271
+ "git",
21272
+ ["rev-parse", "--verify", "HEAD^{commit}"],
21273
+ { cwd: sourceProjectRoot }
21274
+ );
21275
+ const { stdout: sealedStatusStdout } = await execFileAsync3("git", statusArgs, {
21276
+ cwd: sourceProjectRoot
21277
+ });
21278
+ const { stdout: headAfterStdout } = await execFileAsync3(
21279
+ "git",
21280
+ ["rev-parse", "--verify", "HEAD^{commit}"],
21281
+ { cwd: sourceProjectRoot }
21282
+ );
21283
+ const headBefore = headBeforeStdout.trim();
21284
+ const headAfter = headAfterStdout.trim();
21285
+ if (headBefore !== targetCommit || headAfter !== targetCommit || sealedStatusStdout !== "") {
21286
+ sealDiagnostic = [
21287
+ "Reviewer target final seal failed:",
21288
+ `HEAD before status => ${headBefore}`,
21289
+ `HEAD after status => ${headAfter}`,
21290
+ `expected PRE_HEAD ${targetCommit}`,
21291
+ "git status --porcelain=v1 --untracked-files=all -- :/ ':(top,exclude).claude/worktrees/**'",
21292
+ sealedStatusStdout
21293
+ ].join("\n");
21294
+ }
21295
+ } catch (error) {
21296
+ sealDiagnostic = `Reviewer target final seal failed:
21297
+ ${describeFailure(error)}`;
21298
+ }
21299
+ if (sealDiagnostic !== void 0) {
21300
+ const withSealFailure = (result) => ({
21301
+ ...result,
21302
+ exitCode: 1,
21303
+ stderr: [result.stderr, sealDiagnostic].filter(
21304
+ (text) => typeof text === "string" && text !== ""
21305
+ ).join("\n")
21306
+ });
21307
+ results = {
21308
+ completeness: withSealFailure(results.completeness),
21309
+ correctness: withSealFailure(results.correctness)
21310
+ };
21311
+ }
21312
+ const cleanup = await Promise.allSettled(
21313
+ [...created].map((path) => execFileAsync3("git", ["worktree", "remove", path], { cwd: sourceProjectRoot }))
21314
+ );
21315
+ const cleanupFailures = cleanup.flatMap((result) => result.status === "rejected" ? [result.reason] : []);
21316
+ if (cleanupFailures.length === 0) {
21317
+ const rootCleanup = await Promise.allSettled([rm4(root, { recursive: true, force: true })]);
21318
+ cleanupFailures.push(...rootCleanup.flatMap((result) => result.status === "rejected" ? [result.reason] : []));
21319
+ }
21320
+ if (cleanupFailures.length > 0) {
21321
+ const diagnostic = [
21322
+ "parallel reviewer worktree cleanup failed",
21323
+ ...cleanupFailures.map((failure2) => failure2 instanceof Error ? failure2.message : String(failure2))
21324
+ ].join("\n");
21325
+ const withCleanupDiagnostic = (result) => ({
21326
+ ...result,
21327
+ stderr: [result.stderr, diagnostic].filter(
21328
+ (text) => typeof text === "string" && text !== ""
21329
+ ).join("\n")
21330
+ });
21331
+ results = {
21332
+ completeness: withCleanupDiagnostic(results.completeness),
21333
+ correctness: withCleanupDiagnostic(results.correctness)
21334
+ };
21335
+ }
21336
+ return results;
21337
+ }
20321
21338
  async function summonGateOfficer(options) {
20322
21339
  let home = options.home;
20323
21340
  if (home === void 0) {
@@ -20367,12 +21384,13 @@ async function summonGateOfficer(options) {
20367
21384
  ...common
20368
21385
  });
20369
21386
  }
20370
- var AK_ROLE_PACKAGE_ROOT_ENV;
21387
+ var AK_ROLE_PACKAGE_ROOT_ENV, execFileAsync3;
20371
21388
  var init_public_role_summons = __esm({
20372
21389
  "src/public-role-summons.ts"() {
20373
21390
  "use strict";
20374
21391
  init_engine_material();
20375
21392
  AK_ROLE_PACKAGE_ROOT_ENV = "AK_ROLE_PACKAGE_ROOT";
21393
+ execFileAsync3 = promisify3(execFile3);
20376
21394
  }
20377
21395
  });
20378
21396
 
@@ -20594,7 +21612,7 @@ import {
20594
21612
  statSync as statSync3,
20595
21613
  writeFileSync as writeFileSync2
20596
21614
  } from "node:fs";
20597
- import { dirname as dirname18, resolve as resolve14, join as join35 } from "node:path";
21615
+ import { dirname as dirname18, resolve as resolve15, join as join35 } from "node:path";
20598
21616
  import { StringDecoder } from "node:string_decoder";
20599
21617
  import { SessionManager } from "@earendil-works/pi-coding-agent";
20600
21618
  function readCurrentSession(sessionDir) {
@@ -20702,8 +21720,8 @@ function parseSessionHeaderLine(line2) {
20702
21720
  };
20703
21721
  }
20704
21722
  function mostRecentNavigatorSessionFile(sessionDir, cwd) {
20705
- const absoluteSessionDir = resolve14(sessionDir);
20706
- const absoluteCwd = resolve14(cwd);
21723
+ const absoluteSessionDir = resolve15(sessionDir);
21724
+ const absoluteCwd = resolve15(cwd);
20707
21725
  let names;
20708
21726
  try {
20709
21727
  names = readdirSync2(absoluteSessionDir);
@@ -20738,7 +21756,7 @@ function mostRecentNavigatorSessionFile(sessionDir, cwd) {
20738
21756
  }
20739
21757
  if (header === void 0) continue;
20740
21758
  if (typeof header.cwd !== "string" || header.cwd.length === 0) continue;
20741
- if (resolve14(header.cwd) !== absoluteCwd) continue;
21759
+ if (resolve15(header.cwd) !== absoluteCwd) continue;
20742
21760
  matched.push({ path: filePath, mtimeMs: st.mtimeMs });
20743
21761
  }
20744
21762
  if (matched.length === 0) return void 0;
@@ -20768,8 +21786,8 @@ function resolveNavigatorNestContinuation(sessionDir, cwd) {
20768
21786
  }
20769
21787
  }
20770
21788
  function assertRecentFinalFileUnderSessionDir(sessionDir, recentFile) {
20771
- const absoluteSessionDir = resolve14(sessionDir);
20772
- const absoluteFile = resolve14(recentFile);
21789
+ const absoluteSessionDir = resolve15(sessionDir);
21790
+ const absoluteFile = resolve15(recentFile);
20773
21791
  if (absoluteFile !== absoluteSessionDir && !pathContainedIn(absoluteSessionDir, absoluteFile)) {
20774
21792
  throw new ActivationLedgerError(
20775
21793
  `archivist record session must be under the authorized nest (${sessionDir}): ${recentFile}`
@@ -20824,7 +21842,7 @@ function createRecordSessionOpen(options) {
20824
21842
  throw new Error("Durable record ownership requires a parent session inside the ledger home");
20825
21843
  } else {
20826
21844
  ledgerHome = resolveActivationLedgerHomeForPath(parentFile);
20827
- const parentResolved = resolve14(parentFile);
21845
+ const parentResolved = resolve15(parentFile);
20828
21846
  if (!physicallyContainedIn(ledgerHome, parentResolved)) {
20829
21847
  throw new Error("Durable record ownership requires a parent session inside the ledger home");
20830
21848
  }
@@ -20910,7 +21928,7 @@ var init_archivist_record_entry = __esm({
20910
21928
  });
20911
21929
 
20912
21930
  // src/headless-host/production-host.ts
20913
- import { randomUUID as randomUUID10 } from "node:crypto";
21931
+ import { randomUUID as randomUUID11 } from "node:crypto";
20914
21932
 
20915
21933
  // src/role-runtime-dependencies.ts
20916
21934
  import { readFile as readFile22 } from "node:fs/promises";
@@ -20991,12 +22009,13 @@ import { createHash as createHash9 } from "node:crypto";
20991
22009
  init_navigator_invocation_identity();
20992
22010
  init_packaged_role_registry();
20993
22011
  init_activation_ledger_topology();
20994
- import { resolve as resolve15 } from "node:path";
22012
+ import { resolve as resolve16 } from "node:path";
20995
22013
  import "@earendil-works/pi-coding-agent";
20996
22014
  import { Type as Type13 } from "typebox";
20997
22015
 
20998
22016
  // src/navigator-public-session.ts
20999
22017
  init_sitian_facade();
22018
+ import { basename as basename9 } from "node:path";
21000
22019
 
21001
22020
  // src/navigator-session-contracts.ts
21002
22021
  import { Type as Type12 } from "typebox";
@@ -21184,6 +22203,7 @@ async function resolveNavigatorSeatSelection(context) {
21184
22203
 
21185
22204
  // src/navigator-public-session.ts
21186
22205
  init_host_contracts();
22206
+ init_cli_errors();
21187
22207
  async function resolveNavigatorLedgerHome(context) {
21188
22208
  const { tryHomeFromAkRolesPath: tryHomeFromAkRolesPath2 } = await Promise.resolve().then(() => (init_activation_ledger_topology(), activation_ledger_topology_exports));
21189
22209
  const runDirectory = runDirectoryFromHostContext(context);
@@ -21198,7 +22218,42 @@ async function resolveNavigatorLedgerHome(context) {
21198
22218
  }
21199
22219
  return void 0;
21200
22220
  }
21201
- function createNativeNavigatorSessionFactory() {
22221
+ var NAVIGATOR_HOST_RUN_POINTER_ENTRY = "ak-navigator-host-run";
22222
+ function exactRecord2(value) {
22223
+ return typeof value === "object" && value !== null && !Array.isArray(value);
22224
+ }
22225
+ function runIdFromNavigatorDirectory(runDirectory) {
22226
+ const entry = basename9(runDirectory);
22227
+ const suffix = "@navigator";
22228
+ if (!entry.endsWith(suffix)) return void 0;
22229
+ const runId = entry.slice(0, entry.length - suffix.length);
22230
+ return runId.length > 0 ? runId : void 0;
22231
+ }
22232
+ function readNavigatorHostRunPointer(entries) {
22233
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
22234
+ const entry = entries[index];
22235
+ if (!exactRecord2(entry)) continue;
22236
+ if (entry.type === "custom" && entry.customType === NAVIGATOR_HOST_RUN_POINTER_ENTRY) {
22237
+ const data = entry.data;
22238
+ if (exactRecord2(data) && typeof data.runId === "string" && data.runId.trim() !== "") {
22239
+ return data.runId.trim();
22240
+ }
22241
+ }
22242
+ }
22243
+ return void 0;
22244
+ }
22245
+ async function navigatorHostRunResumable(home, runId) {
22246
+ const { piDurablePrincipalAuthority: piDurablePrincipalAuthority2 } = await Promise.resolve().then(() => (init_durable_principal(), durable_principal_exports));
22247
+ const { loadResumableInstructionSeatRun: loadResumableInstructionSeatRun2 } = await Promise.resolve().then(() => (init_run_lifecycle(), run_lifecycle_exports));
22248
+ try {
22249
+ const loaded = await loadResumableInstructionSeatRun2(home, runId, piDurablePrincipalAuthority2);
22250
+ return loaded.admitted.role === "navigator";
22251
+ } catch (error) {
22252
+ if (error instanceof CliUsageError) return false;
22253
+ throw error;
22254
+ }
22255
+ }
22256
+ function createNativeNavigatorSessionFactory(deps) {
21202
22257
  return async ({ context, subject, tool }) => {
21203
22258
  let thinkingLevel;
21204
22259
  const { createRecordSession: createRecordSession2, NAVIGATOR_RECORD_KIND: NAVIGATOR_RECORD_KIND2 } = await Promise.resolve().then(() => (init_archivist_record_entry(), archivist_record_entry_exports));
@@ -21214,6 +22269,11 @@ function createNativeNavigatorSessionFactory() {
21214
22269
  let noReceipt;
21215
22270
  let disposed = false;
21216
22271
  let inFlightPrompt;
22272
+ let hostRunId = readNavigatorHostRunPointer(sessionManager.getEntries());
22273
+ const summon = deps?.summonPublicRole ?? (async (options) => {
22274
+ const { summonPublicRole: summonPublicRole2 } = await Promise.resolve().then(() => (init_public_role_summons(), public_role_summons_exports));
22275
+ return summonPublicRole2(options);
22276
+ });
21217
22277
  return {
21218
22278
  prompt: async (text) => {
21219
22279
  if (disposed) {
@@ -21223,14 +22283,24 @@ function createNativeNavigatorSessionFactory() {
21223
22283
  noReceipt = void 0;
21224
22284
  const run = (async () => {
21225
22285
  try {
21226
- const { summonPublicRole: summonPublicRole2 } = await Promise.resolve().then(() => (init_public_role_summons(), public_role_summons_exports));
21227
22286
  const summonHome = await resolveNavigatorLedgerHome(context);
21228
- const summoned = await summonPublicRole2({
22287
+ const resumeRunId = hostRunId;
22288
+ const baseSummon = {
21229
22289
  role: "navigator",
21230
22290
  argv: [text],
21231
22291
  cwd: context.cwd,
21232
22292
  ...summonHome === void 0 ? {} : { home: summonHome }
21233
- });
22293
+ };
22294
+ const resumable = deps?.hostRunResumable ?? navigatorHostRunResumable;
22295
+ let summoned;
22296
+ if (resumeRunId === void 0 || summonHome === void 0) {
22297
+ summoned = await summon(baseSummon);
22298
+ } else if (await resumable(summonHome, resumeRunId)) {
22299
+ summoned = await summon({ ...baseSummon, resumeRunId });
22300
+ } else {
22301
+ hostRunId = void 0;
22302
+ summoned = await summon(baseSummon);
22303
+ }
21234
22304
  const outcome = summoned.terminal?.roleOutcome;
21235
22305
  if (outcome === void 0) {
21236
22306
  const detail = summoned.stderr?.trim() || `exit ${summoned.exitCode}`;
@@ -21253,21 +22323,31 @@ function createNativeNavigatorSessionFactory() {
21253
22323
  noReceipt = outcome;
21254
22324
  return;
21255
22325
  }
22326
+ const runDirectory = summoned.runDirectory ?? (typeof summoned.admitted?.runDirectory === "string" ? summoned.admitted.runDirectory : void 0);
22327
+ if (typeof runDirectory === "string" && runDirectory.trim() !== "") {
22328
+ const nextRunId = runIdFromNavigatorDirectory(runDirectory);
22329
+ if (nextRunId !== void 0) {
22330
+ hostRunId = nextRunId;
22331
+ sessionManager.appendCustomEntry(NAVIGATOR_HOST_RUN_POINTER_ENTRY, { runId: nextRunId });
22332
+ }
22333
+ }
21256
22334
  if (outcome.kind !== "accepted") {
21257
22335
  return;
21258
22336
  }
22337
+ const { navigatorProseFromUnknown: navigatorProseFromUnknown2 } = await Promise.resolve().then(() => (init_navigator_output(), navigator_output_exports));
22338
+ const proseParts = [];
21259
22339
  for (const payload of outcome.payloads ?? []) {
21260
- if (typeof payload !== "object" || payload === null || Array.isArray(payload)) continue;
21261
- const candidates = payload.candidates;
21262
- if (!Array.isArray(candidates)) continue;
21263
- await tool.execute(
21264
- "navigator-public-prepare",
21265
- { candidates },
21266
- void 0,
21267
- void 0,
21268
- context
21269
- );
22340
+ const prose = navigatorProseFromUnknown2(payload);
22341
+ if (prose !== void 0) proseParts.push(prose);
21270
22342
  }
22343
+ if (proseParts.length === 0) return;
22344
+ await tool.execute(
22345
+ "navigator-public-prepare",
22346
+ { prose: proseParts.join("\n\n") },
22347
+ void 0,
22348
+ void 0,
22349
+ context
22350
+ );
21271
22351
  } catch (error) {
21272
22352
  if (error instanceof NavigatorUnavailableError) throw error;
21273
22353
  const fact = navigatorProviderFailureFromError(error);
@@ -21321,9 +22401,9 @@ function createNativeNavigatorSessionFactory() {
21321
22401
 
21322
22402
  // src/navigator-attendance.ts
21323
22403
  init_sitian_facade();
21324
- init_public_command_renderer();
21325
22404
  init_work_subject_identity();
21326
22405
  init_receipt_delivery_policy();
22406
+ init_navigator_output();
21327
22407
  var NAVIGATOR_EVENT_TYPE = "ak-navigator-attendance";
21328
22408
  var NAVIGATOR_PREPARE_ACCEPTED_TEXT = "\u6E38\u5955\u4F7F\u51C6\u5907\u5DF2\u63A5\u53D7";
21329
22409
  function resolveNavigatorAuthorityMaterial(roleInput, fileAuthority) {
@@ -21333,107 +22413,40 @@ function resolveNavigatorAuthorityMaterial(roleInput, fileAuthority) {
21333
22413
  }
21334
22414
  var NAVIGATOR_TARGETS = PACKAGED_ROLE_REGISTRY.map(({ role, phases }) => ({ role, phases }));
21335
22415
  var prepareSchema = Type13.Object({
21336
- candidates: Type13.Optional(Type13.Unknown({
21337
- description: "\u65B9\u5411\u5019\u9009\uFF1Bcandidates[].next.role \u5FC5\u586B\uFF0Cphase \u53EF\u9009\uFF0Croute/matches/reason/command \u53EF\u9009\u4E0A\u4E0B\u6587\uFF0C\u975E\u53D7\u7406\u95F8"
22416
+ prose: Type13.Optional(Type13.Unknown({
22417
+ description: "\u6E38\u5955\u4F7F\u6563\u6587\u5EFA\u8BAE\uFF0C\u539F\u6837\u5448\u73B0\u3002\u4E0D\u8981\u6C42 candidates/next \u7ED3\u6784\u3002\u975E\u53D7\u7406\u95F8"
21338
22418
  }))
21339
22419
  }, { additionalProperties: true });
21340
- var ROUTE_ENTRY = "ak-navigator-route";
21341
22420
  var CONTEXT_ENTRY = "ak-navigator-context";
21342
22421
  var INVOCATION_ENTRY = NAVIGATOR_INVOCATION_ENTRY;
21343
22422
  var SETTLEMENT_ENTRY = "ak-navigator-settlement";
21344
- var targetRoles = new Set(NAVIGATOR_TARGETS.map(({ role }) => role));
21345
- function exactRecord2(value) {
22423
+ function exactRecord3(value) {
21346
22424
  return typeof value === "object" && value !== null && !Array.isArray(value);
21347
22425
  }
21348
22426
  function rejectedPrepareReason(entries, start) {
21349
22427
  const recent = entries.slice(start);
21350
22428
  const prepareCalls = /* @__PURE__ */ new Set();
21351
22429
  for (const entry of recent) {
21352
- if (!exactRecord2(entry) || entry.type !== "message" || !exactRecord2(entry.message) || entry.message.role !== "assistant" || !Array.isArray(entry.message.content)) continue;
22430
+ if (!exactRecord3(entry) || entry.type !== "message" || !exactRecord3(entry.message) || entry.message.role !== "assistant" || !Array.isArray(entry.message.content)) continue;
21353
22431
  for (const part of entry.message.content) {
21354
- if (exactRecord2(part) && part.type === "toolCall" && part.name === NAVIGATOR_PREPARE_TOOL_NAME && typeof part.id === "string") prepareCalls.add(part.id);
22432
+ if (exactRecord3(part) && part.type === "toolCall" && part.name === NAVIGATOR_PREPARE_TOOL_NAME && typeof part.id === "string") prepareCalls.add(part.id);
21355
22433
  }
21356
22434
  }
21357
22435
  let reason;
21358
22436
  for (const entry of recent) {
21359
- if (!exactRecord2(entry) || entry.type !== "message" || !exactRecord2(entry.message) || entry.message.role !== "toolResult" || entry.message.isError !== true) continue;
22437
+ if (!exactRecord3(entry) || entry.type !== "message" || !exactRecord3(entry.message) || entry.message.role !== "toolResult" || entry.message.isError !== true) continue;
21360
22438
  const callId = entry.message.toolCallId;
21361
22439
  if (entry.message.toolName !== NAVIGATOR_PREPARE_TOOL_NAME || typeof callId !== "string" || !prepareCalls.has(callId)) {
21362
22440
  return void 0;
21363
22441
  }
21364
22442
  const content = entry.message.content;
21365
- const text = Array.isArray(content) ? content.flatMap((part) => exactRecord2(part) && typeof part.text === "string" ? [part.text] : []).join("") : typeof content === "string" ? content : "";
22443
+ const text = Array.isArray(content) ? content.flatMap((part) => exactRecord3(part) && typeof part.text === "string" ? [part.text] : []).join("") : typeof content === "string" ? content : "";
21366
22444
  if (text.trim() !== "") reason = text.trim();
21367
22445
  }
21368
22446
  return reason;
21369
22447
  }
21370
- function targetIsValid(value) {
21371
- if (!exactRecord2(value) || !targetRoles.has(String(value.role))) return false;
21372
- const metadata = packagedRoleMetadata(String(value.role));
21373
- return metadata !== void 0 && metadata.phases.includes(value.phase);
21374
- }
21375
- function normalizeTarget(value) {
21376
- if (!exactRecord2(value)) return void 0;
21377
- const role = typeof value.role === "string" ? value.role.trim() : "";
21378
- if (role === "") return void 0;
21379
- if (value.phase === void 0 || value.phase === null) {
21380
- return { role, phase: null };
21381
- }
21382
- if (value.phase === "plan" || value.phase === "apply") {
21383
- return { role, phase: value.phase };
21384
- }
21385
- return { role, phase: null };
21386
- }
21387
- function normalizeMatches(value) {
21388
- if (!exactRecord2(value)) return void 0;
21389
- if (typeof value.role !== "string" || value.role.trim() === "") return void 0;
21390
- if (value.kind !== "accepted") return void 0;
21391
- let phase;
21392
- if (value.phase === void 0 || value.phase === null) phase = null;
21393
- else if (value.phase === "plan" || value.phase === "apply") phase = value.phase;
21394
- else return void 0;
21395
- if (value.statuses !== void 0) {
21396
- if (!Array.isArray(value.statuses) || value.statuses.some((status) => typeof status !== "string" || status.trim() === "")) {
21397
- return void 0;
21398
- }
21399
- return {
21400
- role: value.role,
21401
- phase,
21402
- kind: "accepted",
21403
- statuses: [...value.statuses]
21404
- };
21405
- }
21406
- return { role: value.role, phase, kind: "accepted" };
21407
- }
21408
- function normalizeCandidate(value) {
21409
- if (!exactRecord2(value)) return void 0;
21410
- const next = normalizeTarget(value.next);
21411
- const route = Array.isArray(value.route) ? value.route.map(normalizeTarget).filter((target) => target !== void 0) : void 0;
21412
- const matches = normalizeMatches(value.matches);
21413
- const id = typeof value.id === "string" && value.id.trim() !== "" ? value.id : void 0;
21414
- const reason = typeof value.reason === "string" && value.reason.trim() !== "" ? value.reason : void 0;
21415
- const command = typeof value.command === "string" ? value.command : void 0;
21416
- return {
21417
- ...id === void 0 ? {} : { id },
21418
- ...matches === void 0 ? {} : { matches },
21419
- ...route === void 0 || route.length === 0 ? {} : { route },
21420
- ...next === void 0 ? {} : { next },
21421
- ...reason === void 0 ? {} : { reason },
21422
- ...command === void 0 ? {} : { command }
21423
- };
21424
- }
21425
- function normalizePrepareOutput(value) {
21426
- if (!exactRecord2(value) || !Array.isArray(value.candidates)) return [];
21427
- return value.candidates.map(normalizeCandidate).filter((candidate) => candidate !== void 0);
21428
- }
21429
- function routeEqual(a, b) {
21430
- return a !== void 0 && a.length === b.length && a.every((target, index) => target.role === b[index].role && target.phase === b[index].phase);
21431
- }
21432
- function routeText(route) {
21433
- return route.map((target) => target.phase === null ? target.role : `${target.role} ${target.phase}`).join(" \u2192 ");
21434
- }
21435
- function targetText(target) {
21436
- return target.phase === null ? target.role : `${target.role} ${target.phase}`;
22448
+ function normalizePrepareProse(value) {
22449
+ return navigatorProseFromUnknown(value);
21437
22450
  }
21438
22451
  function navigatorSubjectKey(subjectRoot, subject, provenance = "role_input") {
21439
22452
  if (issueRoot(subjectRoot) !== void 0 || !subjectRoot.includes("/.ak/work/")) return subjectRoot;
@@ -21444,7 +22457,7 @@ function navigatorSubjectKey(subjectRoot, subject, provenance = "role_input") {
21444
22457
  }
21445
22458
  function navigatorSubjectKeyForInput(subjectRoot, reference, cwd = process.cwd()) {
21446
22459
  if (issueRoot(subjectRoot) !== void 0 || !subjectRoot.includes("/.ak/work/")) return subjectRoot;
21447
- const resolvedReference = resolve15(cwd, reference);
22460
+ const resolvedReference = resolve16(cwd, reference);
21448
22461
  const marker = "/runs/";
21449
22462
  if (resolvedReference.includes(marker)) {
21450
22463
  return subjectRoot;
@@ -21455,7 +22468,7 @@ function createNavigatorPrepareTool(onOutput) {
21455
22468
  return {
21456
22469
  name: NAVIGATOR_PREPARE_TOOL_NAME,
21457
22470
  label: "\u6E38\u5955\u4F7F\u51C6\u5907",
21458
- description: "\u63D0\u4EA4\u6E38\u5955\u4F7F\u65B9\u5411\u5EFA\u8BAE\u3002",
22471
+ description: "\u63D0\u4EA4\u6E38\u5955\u4F7F\u6563\u6587\u5EFA\u8BAE\u3002",
21459
22472
  parameters: prepareSchema,
21460
22473
  async execute(_id, value) {
21461
22474
  onOutput(value);
@@ -21463,34 +22476,6 @@ function createNavigatorPrepareTool(onOutput) {
21463
22476
  }
21464
22477
  };
21465
22478
  }
21466
- function selectNavigatorCandidate(candidates, settlement) {
21467
- if (settlement.kind !== "accepted") return void 0;
21468
- const usable = candidates.filter((candidate) => candidate.next !== void 0);
21469
- if (usable.length === 0) return void 0;
21470
- const rolePhaseMatched = usable.filter(
21471
- (candidate) => candidate.matches !== void 0 && candidate.matches.role === settlement.role && candidate.matches.phase === settlement.phase
21472
- );
21473
- if (rolePhaseMatched.length > 0) {
21474
- if (settlement.status !== void 0) {
21475
- const statusSpecific = rolePhaseMatched.find(
21476
- (candidate) => candidate.matches?.statuses !== void 0 && candidate.matches.statuses.includes(settlement.status)
21477
- );
21478
- if (statusSpecific !== void 0) {
21479
- return { candidate: statusSpecific, matchedToSettlement: true };
21480
- }
21481
- }
21482
- const rolePhaseGeneric = rolePhaseMatched.find(
21483
- (candidate) => candidate.matches?.statuses === void 0
21484
- );
21485
- if (rolePhaseGeneric !== void 0) {
21486
- return { candidate: rolePhaseGeneric, matchedToSettlement: true };
21487
- }
21488
- return void 0;
21489
- }
21490
- const unbound = usable.find((candidate) => candidate.matches === void 0);
21491
- if (unbound === void 0) return void 0;
21492
- return { candidate: unbound, matchedToSettlement: false };
21493
- }
21494
22479
  function formatNavigatorReport(report) {
21495
22480
  const playbookFailure = report.routePlaybookReadFailure === void 0 ? [] : [`\u8DEF\u4E66\u8BFB\u53D6\u5931\u8D25\uFF1A${report.routePlaybookReadFailure}`];
21496
22481
  if (report.disposition === "no-advice") return playbookFailure.join("\n");
@@ -21500,31 +22485,24 @@ function formatNavigatorReport(report) {
21500
22485
  if (report.disposition === "arrival") {
21501
22486
  return [...playbookFailure, ...report.arrivalMessage ? [report.arrivalMessage] : []].join("\n");
21502
22487
  }
21503
- return [
21504
- ...playbookFailure,
21505
- ...report.route === void 0 ? [] : [`\u8DEF\u7EBF\uFF1A${routeText(report.route)}`],
21506
- ...report.next === void 0 ? [] : [`\u4E0B\u4E00\u6B65\uFF1A${targetText(report.next)}`],
21507
- ...report.reason === void 0 || report.reason.trim() === "" ? [] : [`\u7406\u7531\uFF1A${report.reason}`],
21508
- ...report.command === void 0 || report.command.trim() === "" ? [] : [`\u547D\u4EE4\uFF1A${report.command}`]
21509
- ].join("\n");
22488
+ return [...playbookFailure, ...report.prose ? [report.prose] : []].join("\n");
21510
22489
  }
21511
22490
  function createNavigatorAttendance(options) {
21512
22491
  let preparation;
22492
+ let preparationInFlight = false;
21513
22493
  let sessionReady;
21514
22494
  let session;
21515
22495
  let subjectKey = options.subjectKey;
21516
22496
  let subject = options.subject;
21517
22497
  let authority = options.authority;
21518
22498
  let contextError = options.contextError;
21519
- let candidates;
22499
+ let preparedProse;
21520
22500
  const invocationPrincipal = options.invocationId ?? mintNavigatorInvocationId();
21521
22501
  let activeInvocationId = invocationPrincipal;
21522
- let previousRoute;
21523
22502
  let outputSink;
21524
22503
  let settlementTail = Promise.resolve();
21525
22504
  let settlementFailure;
21526
22505
  let preparationFailure;
21527
- let preparationNoReceipt = false;
21528
22506
  let routePlaybookReadFailure;
21529
22507
  let disposed = false;
21530
22508
  let warmedHelp;
@@ -21551,12 +22529,7 @@ function createNavigatorAttendance(options) {
21551
22529
  };
21552
22530
  let routePlaybookSettlement;
21553
22531
  let prepareBoundSettlement;
21554
- const prepare = async () => {
21555
- const boundSettlement = prepareBoundSettlement;
21556
- prepareBoundSettlement = void 0;
21557
- preparationNoReceipt = false;
21558
- const invocationId = invocationPrincipal;
21559
- activeInvocationId = invocationId;
22532
+ const loadMaterialsAndSession = async (invocationId) => {
21560
22533
  if (contextError !== void 0) throw navigatorUnavailableError("context", contextError);
21561
22534
  if (typeof authority !== "string" || authority.trim() === "") {
21562
22535
  throw navigatorUnavailableError(
@@ -21614,21 +22587,6 @@ function createNavigatorAttendance(options) {
21614
22587
  const helpContext = help.map(({ role, help: text }) => `<role_help role="${role}">
21615
22588
  ${text}
21616
22589
  </role_help>`).join("\n");
21617
- let output;
21618
- let prepareBatchRejected = false;
21619
- outputSink = (value) => {
21620
- if (output === void 0) {
21621
- output = value;
21622
- return;
21623
- }
21624
- const prior2 = output.candidates;
21625
- const next = value.candidates;
21626
- const merged = [
21627
- ...Array.isArray(prior2) ? prior2 : prior2 === void 0 ? [] : [prior2],
21628
- ...Array.isArray(next) ? next : next === void 0 ? [] : [next]
21629
- ];
21630
- output = { ...value, candidates: merged };
21631
- };
21632
22590
  const tool = createNavigatorPrepareTool((value) => {
21633
22591
  outputSink?.(value);
21634
22592
  });
@@ -21636,7 +22594,12 @@ ${text}
21636
22594
  sessionReady = (async () => {
21637
22595
  let created;
21638
22596
  try {
21639
- created = await options.createSession({ context: options.context, subject: subjectKey, ...options.modelSettingPath === void 0 ? {} : { modelSettingPath: options.modelSettingPath }, tool });
22597
+ created = await options.createSession({
22598
+ context: options.context,
22599
+ subject: subjectKey,
22600
+ ...options.modelSettingPath === void 0 ? {} : { modelSettingPath: options.modelSettingPath },
22601
+ tool
22602
+ });
21640
22603
  } catch (error) {
21641
22604
  throw navigatorUnavailableError("session", error);
21642
22605
  }
@@ -21667,26 +22630,63 @@ ${text}
21667
22630
  session.appendEntry(INVOCATION_ENTRY, { invocationId, role: options.role, phase: options.phase, subjectKey });
21668
22631
  }
21669
22632
  if (disposed) throw navigatorUnavailableError("session", new Error("Navigator attendance was disposed"));
21670
- const activeSession = session;
21671
- if (activeSession === void 0) throw new Error("Navigator session was not created");
21672
- const prior = activeSession.entries().filter((entry) => exactRecord2(entry) && entry.type === "custom" && entry.customType === ROUTE_ENTRY && exactRecord2(entry.data) && entry.data.subjectKey === subjectKey).at(-1)?.data;
21673
- if (exactRecord2(prior) && Array.isArray(prior.route) && prior.route.every((target) => targetIsValid(target))) {
21674
- previousRoute = prior.route.map((target) => ({ role: target.role, phase: target.phase }));
21675
- }
21676
- const publicSettlementHistory = activeSession.entries().filter((entry) => exactRecord2(entry) && entry.type === "custom" && entry.customType === SETTLEMENT_ENTRY && exactRecord2(entry.data)).map((entry) => entry.data);
22633
+ if (session === void 0) throw new Error("Navigator session was not created");
22634
+ return { soul, routePlaybook, helpContext, modelSetting, model, help, activeSession: session };
22635
+ };
22636
+ const prepare = async (materialsBundle) => {
22637
+ const boundSettlement = prepareBoundSettlement;
22638
+ prepareBoundSettlement = void 0;
22639
+ const invocationId = invocationPrincipal;
22640
+ activeInvocationId = invocationId;
22641
+ let output;
22642
+ let prepareBatchRejected = false;
22643
+ outputSink = (value) => {
22644
+ if (output === void 0) {
22645
+ output = value;
22646
+ return;
22647
+ }
22648
+ const prior = normalizePrepareProse(output) ?? "";
22649
+ const next = normalizePrepareProse(value) ?? "";
22650
+ const merged = [prior, next].filter((part) => part.trim() !== "").join("\n\n");
22651
+ output = { prose: merged };
22652
+ };
22653
+ const { soul, routePlaybook, helpContext, help, activeSession } = materialsBundle ?? await loadMaterialsAndSession(invocationId);
22654
+ const publicSettlementHistory = activeSession.entries().filter((entry) => exactRecord3(entry) && entry.type === "custom" && entry.customType === SETTLEMENT_ENTRY && exactRecord3(entry.data)).map((entry) => entry.data);
21677
22655
  const projection = {
21678
22656
  subjectKey,
21679
22657
  subject,
21680
22658
  authority,
21681
22659
  currentRole: { role: options.role, phase: options.phase },
21682
22660
  ...boundSettlement === void 0 ? {} : { currentSettlement: boundSettlement },
21683
- priorRoute: exactRecord2(prior) && Array.isArray(prior.route) && prior.route.every((target) => targetIsValid(target)) ? prior.route.map((target) => ({ role: target.role, phase: target.phase })) : null,
21684
22661
  publicSettlementHistory,
21685
22662
  liveRoleHelp: help
21686
22663
  };
21687
22664
  activeSession.appendEntry(CONTEXT_ENTRY, projection);
21688
- const request = [
21689
- "\u672C\u6B21\u5BFC\u822A\u6750\u6599\u5982\u4E0B\uFF1A",
22665
+ const request = boundSettlement === void 0 ? [
22666
+ "\u672C\u8F6E\u4E3A\u5F85\u547D\u8F6E\u3002",
22667
+ `<navigator_soul>
22668
+ ${soul}
22669
+ </navigator_soul>`,
22670
+ ...routePlaybookReadFailure === void 0 ? [`<route_playbook>
22671
+ ${routePlaybook}
22672
+ </route_playbook>`] : ["\u53EF\u9009\u8DEF\u7EBF\u624B\u518C\u672A\u80FD\u8BFB\u53D6\u3002"],
22673
+ `<work_subject>
22674
+ ${subject}
22675
+ </work_subject>`,
22676
+ `<controlling_authority>
22677
+ ${authority}
22678
+ </controlling_authority>`,
22679
+ `<current_role>
22680
+ ${JSON.stringify({ role: options.role, phase: options.phase })}
22681
+ </current_role>`,
22682
+ `<public_settlement_history>
22683
+ ${JSON.stringify(projection.publicSettlementHistory)}
22684
+ </public_settlement_history>`,
22685
+ `<live_role_help>
22686
+ ${helpContext}
22687
+ </live_role_help>`
22688
+ ].join("\n\n") : [
22689
+ "\u672C\u8F6E\u4E3A\u7ED3\u7B97\u6295\u5582\u8F6E\u3002",
21690
22690
  `<navigator_soul>
21691
22691
  ${soul}
21692
22692
  </navigator_soul>`,
@@ -21702,12 +22702,9 @@ ${authority}
21702
22702
  `<current_role>
21703
22703
  ${JSON.stringify({ role: options.role, phase: options.phase })}
21704
22704
  </current_role>`,
21705
- ...boundSettlement === void 0 ? [] : [`<current_settlement>
22705
+ `<current_settlement>
21706
22706
  ${JSON.stringify(boundSettlement)}
21707
- </current_settlement>`],
21708
- `<prior_route>
21709
- ${JSON.stringify(prior ?? null)}
21710
- </prior_route>`,
22707
+ </current_settlement>`,
21711
22708
  `<public_settlement_history>
21712
22709
  ${JSON.stringify(projection.publicSettlementHistory)}
21713
22710
  </public_settlement_history>`,
@@ -21748,33 +22745,47 @@ ${helpContext}
21748
22745
  if (deliveryRequest && output === void 0) delivery.recordDeliveryRequest();
21749
22746
  };
21750
22747
  await promptAllowingRejectedPrepare(request, false);
21751
- while (output === void 0 && delivery.nextAction() === "request-delivery") {
21752
- await promptAllowingRejectedPrepare(RECEIPT_DELIVERY_PROMPT, true);
21753
- }
21754
- if (output === void 0 && delivery.nextAction() === "no-receipt" && activeSession.providerFailure?.() === void 0) {
21755
- const facts = delivery.facts({ runPointer: activeSession.recordPointer(), attemptPointer: invocationId });
21756
- activeSession.appendEntry(NO_RECEIPT_LIFECYCLE_ENTRY_TYPE, facts);
21757
- preparationNoReceipt = true;
21758
- candidates = [];
21759
- return candidates;
22748
+ if (boundSettlement !== void 0) {
22749
+ while (output === void 0 && prepareBatchRejected && delivery.nextAction() === "request-delivery") {
22750
+ await promptAllowingRejectedPrepare(RECEIPT_DELIVERY_PROMPT, true);
22751
+ }
22752
+ if (output === void 0 && delivery.nextAction() === "request-delivery") {
22753
+ while (delivery.nextAction() === "request-delivery") {
22754
+ delivery.recordDeliveryRequest();
22755
+ }
22756
+ }
22757
+ if (output === void 0 && delivery.nextAction() === "no-receipt" && activeSession.providerFailure?.() === void 0) {
22758
+ const facts = delivery.facts({ runPointer: activeSession.recordPointer(), attemptPointer: invocationId });
22759
+ activeSession.appendEntry(NO_RECEIPT_LIFECYCLE_ENTRY_TYPE, facts);
22760
+ preparedProse = void 0;
22761
+ return void 0;
22762
+ }
21760
22763
  }
21761
22764
  } catch (error) {
21762
22765
  throw error instanceof NavigatorUnavailableError ? error : navigatorUnavailableError("transport", error);
21763
22766
  }
21764
22767
  if (output === void 0) {
22768
+ if (boundSettlement === void 0) {
22769
+ preparedProse = void 0;
22770
+ return void 0;
22771
+ }
21765
22772
  const nativeFailure = [...activeSession.entries()].reverse().find((entry) => {
21766
- if (!exactRecord2(entry) || entry.type !== "message" || !exactRecord2(entry.message)) return false;
22773
+ if (!exactRecord3(entry) || entry.type !== "message" || !exactRecord3(entry.message)) return false;
21767
22774
  return entry.message.role === "assistant" && typeof entry.message.errorMessage === "string" && entry.message.errorMessage.trim() !== "";
21768
22775
  });
21769
- const nativeMessage = exactRecord2(nativeFailure) && exactRecord2(nativeFailure.message) ? nativeFailure.message : void 0;
22776
+ const nativeMessage = exactRecord3(nativeFailure) && exactRecord3(nativeFailure.message) ? nativeFailure.message : void 0;
21770
22777
  const errorMessage = nativeMessage !== void 0 && typeof nativeMessage.errorMessage === "string" ? nativeMessage.errorMessage : "Navigator did not submit direction advice";
21771
22778
  const providerFailure = activeSession.providerFailure?.();
21772
22779
  const source = providerFailure?.source ?? "unknown";
21773
22780
  const cause = providerFailure?.cause ?? source;
21774
22781
  throw navigatorUnavailableError(source, errorMessage, cause);
21775
22782
  }
21776
- candidates = normalizePrepareOutput(output);
21777
- return candidates;
22783
+ if (boundSettlement === void 0) {
22784
+ preparedProse = void 0;
22785
+ return void 0;
22786
+ }
22787
+ preparedProse = normalizePrepareProse(output);
22788
+ return preparedProse;
21778
22789
  } finally {
21779
22790
  outputSink = void 0;
21780
22791
  }
@@ -21785,7 +22796,6 @@ ${helpContext}
21785
22796
  if (next.subjectKey !== subjectKey && session !== void 0) {
21786
22797
  const previous = session;
21787
22798
  session = void 0;
21788
- previousRoute = void 0;
21789
22799
  closing = previous.dispose();
21790
22800
  }
21791
22801
  subjectKey = next.subjectKey;
@@ -21807,13 +22817,16 @@ ${helpContext}
21807
22817
  prepare() {
21808
22818
  if (disposed || preparation !== void 0) return;
21809
22819
  preparationFailure = void 0;
21810
- preparation = prepare();
22820
+ preparationInFlight = true;
22821
+ preparation = prepare().finally(() => {
22822
+ preparationInFlight = false;
22823
+ });
21811
22824
  void preparation.catch((error) => {
21812
22825
  preparationFailure = error;
21813
22826
  });
21814
22827
  },
21815
22828
  isPreparing() {
21816
- return preparation !== void 0 || sessionReady !== void 0;
22829
+ return preparationInFlight;
21817
22830
  },
21818
22831
  knownRoutePlaybookReadFailure() {
21819
22832
  return routePlaybookReadFailure;
@@ -21837,81 +22850,70 @@ ${helpContext}
21837
22850
  if (disposed) return;
21838
22851
  const invocationId = activeInvocationId ?? invocationPrincipal;
21839
22852
  let report;
21840
- if (settlement.kind === "human_decision" || settlement.kind === "role_infrastructure_failure") {
21841
- if (sessionReady !== void 0) {
21842
- try {
21843
- await sessionReady;
21844
- } catch (error) {
21845
- preparationFailure ??= error;
21846
- }
22853
+ if (sessionReady !== void 0) {
22854
+ try {
22855
+ await sessionReady;
22856
+ } catch (error) {
22857
+ preparationFailure ??= error;
21847
22858
  }
21848
- if (preparation !== void 0) {
21849
- try {
21850
- await preparation;
21851
- } catch (error) {
21852
- preparationFailure ??= error;
21853
- }
22859
+ }
22860
+ if (preparation !== void 0) {
22861
+ try {
22862
+ await preparation;
22863
+ } catch (error) {
22864
+ preparationFailure ??= error;
21854
22865
  }
21855
- session?.appendEntry(SETTLEMENT_ENTRY, { invocationId, subjectKey, role: settlement.role, phase: settlement.phase, kind: settlement.kind, ...settlement.kind === "human_decision" ? { status: settlement.status } : {} });
22866
+ preparation = void 0;
22867
+ }
22868
+ const settlementFact = {
22869
+ invocationId,
22870
+ subjectKey,
22871
+ role: settlement.role,
22872
+ phase: settlement.phase,
22873
+ kind: settlement.kind,
22874
+ ..."status" in settlement && settlement.status !== void 0 ? { status: settlement.status } : {}
22875
+ };
22876
+ let drainedProse;
22877
+ if (settlement.kind === "arrival") {
22878
+ session?.appendEntry(SETTLEMENT_ENTRY, settlementFact);
21856
22879
  if (preparationFailure !== void 0) {
21857
22880
  report = unavailable(invocationId, preparationFailure);
21858
22881
  } else {
21859
- report = { disposition: "no-advice" };
22882
+ report = {
22883
+ disposition: "arrival",
22884
+ ...settlement.message === void 0 ? {} : { arrivalMessage: settlement.message }
22885
+ };
21860
22886
  }
21861
- } else if (settlement.kind === "arrival") {
21862
- if (sessionReady !== void 0) {
22887
+ } else {
22888
+ if (session !== void 0) preparationFailure = void 0;
22889
+ let coldMaterials;
22890
+ if (session === void 0 && preparationFailure === void 0) {
21863
22891
  try {
21864
- await sessionReady;
22892
+ coldMaterials = await loadMaterialsAndSession(invocationId);
21865
22893
  } catch (error) {
21866
- preparationFailure ??= error;
22894
+ preparationFailure = error;
21867
22895
  }
21868
22896
  }
21869
- if (preparation !== void 0) {
22897
+ session?.appendEntry(SETTLEMENT_ENTRY, settlementFact);
22898
+ if (preparationFailure === void 0) {
22899
+ prepareBoundSettlement = settlement;
22900
+ preparation = prepare(coldMaterials);
22901
+ void preparation.catch((error) => {
22902
+ preparationFailure = error;
22903
+ });
21870
22904
  try {
21871
- await preparation;
22905
+ drainedProse = await preparation;
21872
22906
  } catch (error) {
21873
22907
  preparationFailure ??= error;
21874
22908
  }
22909
+ preparation = void 0;
21875
22910
  }
21876
- report = preparationFailure === void 0 ? { disposition: "arrival", ...settlement.message === void 0 ? {} : { arrivalMessage: settlement.message } } : unavailable(invocationId, preparationFailure);
21877
- } else if (preparation === void 0) {
21878
- report = unavailable(invocationId, "Navigator preparation did not start");
21879
- } else {
21880
- try {
21881
- if (sessionReady !== void 0) await sessionReady;
21882
- let prepared = await preparation;
21883
- session?.appendEntry(SETTLEMENT_ENTRY, { invocationId, subjectKey, role: settlement.role, phase: settlement.phase, kind: settlement.kind, ...settlement.status === void 0 ? {} : { status: settlement.status } });
21884
- let selected = selectNavigatorCandidate(prepared, settlement);
21885
- if (selected?.candidate.next !== void 0 && !selected.matchedToSettlement) {
21886
- if (disposed) return;
21887
- prepareBoundSettlement = settlement;
21888
- prepared = await prepare();
21889
- if (disposed) return;
21890
- selected = selectNavigatorCandidate(prepared, settlement);
21891
- }
21892
- const selectedCandidate = selected?.candidate;
21893
- if (selectedCandidate?.next === void 0 && preparationNoReceipt) {
21894
- report = { disposition: "no-advice" };
21895
- } else if (selectedCandidate?.next === void 0) {
21896
- throw new Error("Navigator prepared no machine-usable next direction");
21897
- } else {
21898
- const selectedRoute = selectedCandidate.route;
21899
- const routeChanged = selectedRoute !== void 0 && !routeEqual(previousRoute, selectedRoute);
21900
- const command = typeof selectedCandidate.command === "string" && selectedCandidate.command.trim() !== "" ? selectedCandidate.command : renderPublicAkRoleCommand(selectedCandidate.next);
21901
- report = {
21902
- disposition: "recommendation",
21903
- ...routeChanged ? { route: selectedRoute } : {},
21904
- next: selectedCandidate.next,
21905
- ...selectedCandidate.reason === void 0 ? {} : { reason: selectedCandidate.reason },
21906
- ...command === void 0 ? {} : { command }
21907
- };
21908
- if (selectedRoute !== void 0) {
21909
- previousRoute = selectedRoute;
21910
- session?.appendEntry(ROUTE_ENTRY, { invocationId, subjectKey, route: selectedRoute });
21911
- }
21912
- }
21913
- } catch (error) {
21914
- report = unavailable(invocationId, error);
22911
+ if (preparationFailure !== void 0) {
22912
+ report = unavailable(invocationId, preparationFailure);
22913
+ } else if (typeof drainedProse === "string" && drainedProse.trim() !== "") {
22914
+ report = { disposition: "advice", prose: drainedProse };
22915
+ } else {
22916
+ report = { disposition: "no-advice" };
21915
22917
  }
21916
22918
  }
21917
22919
  await routePlaybookSettlement;
@@ -21925,10 +22927,7 @@ ${helpContext}
21925
22927
  role: options.role,
21926
22928
  phase: options.phase,
21927
22929
  subjectKey,
21928
- ...report.route === void 0 ? {} : { route: report.route },
21929
- ...report.next === void 0 ? {} : { next: report.next },
21930
- ...report.reason === void 0 ? {} : { reason: report.reason },
21931
- ...report.command === void 0 ? {} : { command: report.command },
22930
+ ...report.prose === void 0 ? {} : { prose: report.prose },
21932
22931
  ...report.unavailableReason === void 0 ? {} : { unavailableReason: report.unavailableReason },
21933
22932
  ...report.unavailableSource === void 0 ? {} : { unavailableSource: report.unavailableSource },
21934
22933
  ...report.unavailableCause === void 0 ? {} : { unavailableCause: report.unavailableCause },
@@ -21944,9 +22943,8 @@ ${helpContext}
21944
22943
  }
21945
22944
  preparation = void 0;
21946
22945
  sessionReady = void 0;
21947
- candidates = void 0;
22946
+ preparedProse = void 0;
21948
22947
  preparationFailure = void 0;
21949
- preparationNoReceipt = false;
21950
22948
  routePlaybookSettlement = void 0;
21951
22949
  routePlaybookReadFailure = void 0;
21952
22950
  }
@@ -21956,7 +22954,7 @@ ${helpContext}
21956
22954
  init_doctor_evidence();
21957
22955
  init_host_contracts();
21958
22956
  import { readFile as readFile20 } from "node:fs/promises";
21959
- import { resolve as resolve16 } from "node:path";
22957
+ import { resolve as resolve17 } from "node:path";
21960
22958
  init_notary_source_run();
21961
22959
  init_packaged_role_registry();
21962
22960
  init_invocation();
@@ -21964,7 +22962,7 @@ function navigatorInputReference(getFlag, role) {
21964
22962
  if (getFlag === void 0) return void 0;
21965
22963
  const name = packagedRoleInputFlag(role);
21966
22964
  const value = name === void 0 ? void 0 : getFlag(name);
21967
- return typeof value === "string" && value !== "" ? resolve16(value) : void 0;
22965
+ return typeof value === "string" && value !== "" ? resolve17(value) : void 0;
21968
22966
  }
21969
22967
  async function loadNavigatorWorkContext(options) {
21970
22968
  const reference = navigatorInputReference(options.getFlag, options.role);
@@ -21985,7 +22983,7 @@ async function loadNavigatorWorkContext(options) {
21985
22983
  }
21986
22984
  const publicRunDir = runDirectoryFromHostContext(options.context);
21987
22985
  const currentSessionDir = options.context.sessionManager.getSessionDir();
21988
- const isBoundPublicRun = publicRunDir !== void 0 && resolve16(currentSessionDir) === resolve16(publicRunDir, "session");
22986
+ const isBoundPublicRun = publicRunDir !== void 0 && resolve17(currentSessionDir) === resolve17(publicRunDir, "session");
21989
22987
  if (options.role === "judge" && isBoundPublicRun) {
21990
22988
  let admitted;
21991
22989
  try {
@@ -22018,9 +23016,9 @@ async function loadNavigatorWorkContext(options) {
22018
23016
  }
22019
23017
  const workRoot = subjectRoot.includes("/.ak/work/") ? subjectRoot : void 0;
22020
23018
  const authorityFiles = workRoot === void 0 ? [] : [
22021
- resolve16(workRoot, "authority.md"),
22022
- resolve16(workRoot, "authority.txt"),
22023
- resolve16(workRoot, "design-v2/owner-direction.md")
23019
+ resolve17(workRoot, "authority.md"),
23020
+ resolve17(workRoot, "authority.txt"),
23021
+ resolve17(workRoot, "design-v2/owner-direction.md")
22024
23022
  ];
22025
23023
  let authorityMaterial;
22026
23024
  for (const path of authorityFiles) {
@@ -22083,6 +23081,7 @@ init_host_contracts();
22083
23081
  init_sitian_facade();
22084
23082
  init_submission_ledger();
22085
23083
  init_collector_ledger();
23084
+ import { randomUUID as randomUUID8 } from "node:crypto";
22086
23085
  import { readFileSync as readFileSync6, writeSync as writeSync4 } from "node:fs";
22087
23086
  import { join as join39 } from "node:path";
22088
23087
  import { Value as Value4 } from "typebox/value";
@@ -22134,7 +23133,7 @@ import {
22134
23133
  openSync as openSync2,
22135
23134
  writeSync
22136
23135
  } from "node:fs";
22137
- import { dirname as dirname21, isAbsolute as isAbsolute10, resolve as resolve18 } from "node:path";
23136
+ import { dirname as dirname21, isAbsolute as isAbsolute10, resolve as resolve19 } from "node:path";
22138
23137
 
22139
23138
  // src/activation-ledger-session.ts
22140
23139
  init_activation_ledger_topology();
@@ -22144,7 +23143,7 @@ import {
22144
23143
  statSync as statSync4,
22145
23144
  writeFileSync as writeFileSync3
22146
23145
  } from "node:fs";
22147
- import { isAbsolute as isAbsolute9, resolve as resolve17 } from "node:path";
23146
+ import { isAbsolute as isAbsolute9, resolve as resolve18 } from "node:path";
22148
23147
  var ActivationSessionFileMissingError = class extends Error {
22149
23148
  code = "AK_ACTIVATION_SESSION_FILE_MISSING";
22150
23149
  path;
@@ -22189,7 +23188,7 @@ function durableSessionPointer(sessionManager) {
22189
23188
  `Workflow role activation requires an absolute durable session file path; got relative path: ${file}`
22190
23189
  );
22191
23190
  }
22192
- const resolvedFile = resolve17(file);
23191
+ const resolvedFile = resolve18(file);
22193
23192
  try {
22194
23193
  lstatSync2(resolvedFile);
22195
23194
  } catch (error) {
@@ -22281,8 +23280,8 @@ function appendActivationLedgerLine(ledgerPath, line2, options) {
22281
23280
  `activation ledger home must be absolute: ${options.ledgerHome}`
22282
23281
  );
22283
23282
  }
22284
- const resolvedLedger = resolve18(ledgerPath);
22285
- const resolvedHome = resolve18(options.ledgerHome);
23283
+ const resolvedLedger = resolve19(ledgerPath);
23284
+ const resolvedHome = resolve19(options.ledgerHome);
22286
23285
  const parent = dirname21(resolvedLedger);
22287
23286
  ensureRealDirectoryTree(resolvedHome, parent);
22288
23287
  assertLedgerFileInsideHome(resolvedLedger, resolvedHome);
@@ -22643,11 +23642,11 @@ init_collector_github();
22643
23642
 
22644
23643
  // src/collector-handbook.ts
22645
23644
  import { readFile as readFile21 } from "node:fs/promises";
22646
- import { join as join38, sep as sep5 } from "node:path";
23645
+ import { join as join38, sep as sep6 } from "node:path";
22647
23646
 
22648
23647
  // src/atomic-write.ts
22649
23648
  import { randomUUID as randomUUID7 } from "node:crypto";
22650
- import { rename as rename3, rm as rm4, writeFile as writeFile11 } from "node:fs/promises";
23649
+ import { rename as rename3, rm as rm5, writeFile as writeFile11 } from "node:fs/promises";
22651
23650
  import { dirname as dirname22, join as join37 } from "node:path";
22652
23651
  async function writeFileAtomically(destination, contents) {
22653
23652
  const parent = dirname22(destination);
@@ -22656,7 +23655,7 @@ async function writeFileAtomically(destination, contents) {
22656
23655
  await writeFile11(temporary, contents);
22657
23656
  await rename3(temporary, destination);
22658
23657
  } catch (error) {
22659
- await rm4(temporary, { force: true }).catch(() => void 0);
23658
+ await rm5(temporary, { force: true }).catch(() => void 0);
22660
23659
  throw error;
22661
23660
  }
22662
23661
  }
@@ -22757,7 +23756,7 @@ function resolveCollectorHandbookRoot(sessionPath) {
22757
23756
  if (typeof sessionPath !== "string" || sessionPath.trim().length === 0) {
22758
23757
  throw new Error("\u901A\u8FDB\u53F8\u624B\u518C\u8981\u6C42\u975E\u7A7A session \u8DEF\u5F84\uFF0C\u4E14\u4F4D\u4E8E books/<bookKey>/");
22759
23758
  }
22760
- const segments = sessionPath.split(sep5);
23759
+ const segments = sessionPath.split(sep6);
22761
23760
  let bookKey;
22762
23761
  for (let i = 0; i + 3 < segments.length; i += 1) {
22763
23762
  if (segments[i] === ".ak-roles" && segments[i + 1] === "books") {
@@ -23929,7 +24928,7 @@ init_navigator_output();
23929
24928
  var NAVIGATOR_TOOL_SPEC = {
23930
24929
  name: NAVIGATOR_OUTPUT_TOOL_NAME,
23931
24930
  label: "\u6E38\u5955\u4F7F\u5EFA\u8BAE",
23932
- description: "\u6E38\u5955\u4F7F\u7EC8\u5C40\u56DE\u6267\uFF1A\u6392\u597D\u5E8F\u7684\u4E0B\u4E00\u6B65\u89D2\u8272\u8DEF\u7EBF\u5EFA\u8BAE\u3002",
24931
+ description: "\u6E38\u5955\u4F7F\u7EC8\u5C40\u56DE\u6267\uFF1A\u6563\u6587\u5EFA\u8BAE\uFF0C\u539F\u6837\u5448\u73B0\u3002",
23933
24932
  promptSnippet: "\u6E38\u5955\u4F7F\u5EFA\u8BAE",
23934
24933
  parameters: navigatorOutputSchema
23935
24934
  };
@@ -24080,7 +25079,7 @@ var reviewerAmendmentsSchema = Type24.Object({
24080
25079
  }))
24081
25080
  }, {
24082
25081
  additionalProperties: true,
24083
- description: "\u6240\u9009 lens \u7684 amendments \u627F\u8F7D candidates\u3001\u9010\u6761\u5904\u7F6E\u4E0E verdict \u7684\u5B8C\u6574\u62A5\u544A\uFF08\u975E\u4EC5 verdict \u884C\uFF09\uFF1B\u672A\u9009 lens \u53EF\u7701\u7565\u3002hard-stop\uFF0Fusage error \u4E3A refused \u65F6\uFF0C\u5DF2\u4EA7\u51FA\u62A5\u544A\u4ECD\u7167\u5F55\u8FDB\u6240\u9009 lens \u5B57\u6BB5\u3002\u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\u3002"
25082
+ description: "\u5DF2\u8FD0\u884C lens \u7684 amendments \u627F\u8F7D candidates\u3001\u9010\u6761\u5904\u7F6E\u4E0E verdict \u7684\u5B8C\u6574\u62A5\u544A\uFF08\u975E\u4EC5 verdict \u884C\uFF09\uFF1B\u663E\u5F0F\u5355\u8F74\u65F6\u53E6\u4E00\u8F74\u53EF\u7701\u7565\u3002hard-stop\uFF0Fusage error \u4E3A refused \u65F6\uFF0C\u5DF2\u4EA7\u51FA\u62A5\u544A\u4ECD\u7167\u5F55\u5BF9\u5E94 lens \u5B57\u6BB5\u3002\u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\u3002"
24084
25083
  });
24085
25084
  var REVIEWER_STATUS_DESCRIPTION = "completed | refused \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\u3002\u4E24\u79CD\u6B63\u5E38 lens verdict\uFF08completeness / correctness\uFF09\u5747 completed\uFF1Bhard-stop \u4E0E usage error \u4E3A refused\uFF08\u5DF2\u4EA7\u51FA\u62A5\u544A\u4ECD\u7167\u5F55\u8FDB\u6240\u9009 lens amendments\uFF09\u3002";
24086
25085
  var reviewerOutputVariants = Type24.Union([
@@ -24156,7 +25155,7 @@ init_submission_errors();
24156
25155
  init_submission_errors();
24157
25156
  import { execFileSync as execFileSync4 } from "node:child_process";
24158
25157
  import { existsSync as existsSync12, lstatSync as lstatSync3, readdirSync as readdirSync3, readFileSync as readFileSync5, rmdirSync, rmSync } from "node:fs";
24159
- import { resolve as resolve19 } from "node:path";
25158
+ import { resolve as resolve20 } from "node:path";
24160
25159
  var WORKER_SUBMISSION_GATE_RECORD_KIND = WORKER_SUBMISSION_GATE_KIND;
24161
25160
  var WORKER_COMMIT_BASELINE_ENTRY_TYPE = "commit-baseline";
24162
25161
  var WORKER_COMMIT_REMINDER_BOUNCE_ENTRY_TYPE = "commit-reminder-bounce";
@@ -24205,7 +25204,7 @@ function escapeGitConfigValueRegex(value) {
24205
25204
  function unsetOwnedHooksPath(file) {
24206
25205
  const owned = [];
24207
25206
  for (const value of tryGetAll(file, "core.hooksPath")) {
24208
- if (!ownedHook(resolve19(value, HOOK_FILE))) continue;
25207
+ if (!ownedHook(resolve20(value, HOOK_FILE))) continue;
24209
25208
  try {
24210
25209
  gitFile(file, [
24211
25210
  "--unset-all",
@@ -24220,15 +25219,15 @@ function unsetOwnedHooksPath(file) {
24220
25219
  return owned;
24221
25220
  }
24222
25221
  function rmOwnedDir(dir) {
24223
- const hookPath = resolve19(dir, HOOK_FILE);
25222
+ const hookPath = resolve20(dir, HOOK_FILE);
24224
25223
  if (!ownedHook(hookPath)) return;
24225
25224
  rmSync(hookPath, { force: true });
24226
25225
  if (existsSync12(dir) && readdirSync3(dir).length === 0) rmdirSync(dir);
24227
25226
  }
24228
25227
  function linkedGitDirs(commonDir) {
24229
- const root = resolve19(commonDir, "worktrees");
25228
+ const root = resolve20(commonDir, "worktrees");
24230
25229
  if (!existsSync12(root)) return [];
24231
- return readdirSync3(root).map((name) => resolve19(root, name)).filter((dir) => lstatSync3(dir).isDirectory());
25230
+ return readdirSync3(root).map((name) => resolve20(root, name)).filter((dir) => lstatSync3(dir).isDirectory());
24232
25231
  }
24233
25232
  function uninstallPackageWorkerHooks(cwd) {
24234
25233
  let inside;
@@ -24242,14 +25241,14 @@ function uninstallPackageWorkerHooks(cwd) {
24242
25241
  const clear = (configFile) => {
24243
25242
  for (const hooks of unsetOwnedHooksPath(configFile)) rmOwnedDir(hooks);
24244
25243
  };
24245
- clear(resolve19(commonDir, "config"));
24246
- clear(resolve19(commonDir, "config.worktree"));
24247
- rmOwnedDir(resolve19(commonDir, HOOKS_DIR));
24248
- const legacy = resolve19(commonDir, "hooks", HOOK_FILE);
25244
+ clear(resolve20(commonDir, "config"));
25245
+ clear(resolve20(commonDir, "config.worktree"));
25246
+ rmOwnedDir(resolve20(commonDir, HOOKS_DIR));
25247
+ const legacy = resolve20(commonDir, "hooks", HOOK_FILE);
24249
25248
  if (ownedHook(legacy)) rmSync(legacy, { force: true });
24250
25249
  for (const gitDir of linkedGitDirs(commonDir)) {
24251
- clear(resolve19(gitDir, "config.worktree"));
24252
- rmOwnedDir(resolve19(gitDir, HOOKS_DIR));
25250
+ clear(resolve20(gitDir, "config.worktree"));
25251
+ rmOwnedDir(resolve20(gitDir, HOOKS_DIR));
24253
25252
  }
24254
25253
  }
24255
25254
  function isRecord13(value) {
@@ -24294,11 +25293,11 @@ function reliableWindow(cwd, baseline, head) {
24294
25293
  const raw = git2(cwd, ["log", "--format=%P%x1e%s", range]);
24295
25294
  if (raw.length === 0) return [];
24296
25295
  return raw.split("\n").flatMap((line2) => {
24297
- const sep6 = line2.indexOf("");
24298
- if (sep6 < 0) return [];
25296
+ const sep7 = line2.indexOf("");
25297
+ if (sep7 < 0) return [];
24299
25298
  return [{
24300
- subject: line2.slice(sep6 + 1),
24301
- merge: line2.slice(0, sep6).trim().includes(" ")
25299
+ subject: line2.slice(sep7 + 1),
25300
+ merge: line2.slice(0, sep7).trim().includes(" ")
24302
25301
  }];
24303
25302
  });
24304
25303
  }
@@ -24843,7 +25842,7 @@ var REVIEWER_TRANSPORT_FLAGS = Object.freeze([
24843
25842
  Object.freeze({
24844
25843
  name: "ak-review-lens",
24845
25844
  definition: Object.freeze({
24846
- description: "Caller-selected single review lens: completeness or correctness",
25845
+ description: "Single review lens: completeness or correctness",
24847
25846
  type: "string"
24848
25847
  })
24849
25848
  }),
@@ -25428,6 +26427,21 @@ function createCountersignRoleRuntime(roleHost, dependencies, hostActions) {
25428
26427
  dependencies
25429
26428
  );
25430
26429
  }
26430
+ function lastAssistantProse(messages) {
26431
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
26432
+ const message = messages[index];
26433
+ if (message?.role !== "assistant" || !Array.isArray(message.content)) continue;
26434
+ const texts = [];
26435
+ for (const part of message.content) {
26436
+ if (part.type === "text" && typeof part.text === "string" && part.text.length > 0) {
26437
+ texts.push(part.text);
26438
+ }
26439
+ }
26440
+ if (texts.length === 0) continue;
26441
+ return texts.join("");
26442
+ }
26443
+ return void 0;
26444
+ }
25431
26445
  function createRoleRuntimeExtension(dependencies) {
25432
26446
  return (envelopeHost) => {
25433
26447
  let projectClosedSubmission = async () => {
@@ -25486,10 +26500,6 @@ function createRoleRuntimeExtension(dependencies) {
25486
26500
  if (settlement === void 0 || attendance === void 0) return;
25487
26501
  const workContext = navigatorWorkContext;
25488
26502
  const pending = (async () => {
25489
- if (settlement.kind !== "accepted") {
25490
- await attendance.settle(settlement);
25491
- return;
25492
- }
25493
26503
  const settlePromise = attendance.settle(settlement);
25494
26504
  void settlePromise.catch(() => void 0);
25495
26505
  const raced = await raceNavigatorGrace(settlePromise, NAVIGATOR_POST_ROLE_GRACE_MS);
@@ -25690,10 +26700,8 @@ function createRoleRuntimeExtension(dependencies) {
25690
26700
  pendingSubmissionNonPassByToolCallId.delete(event.toolCallId);
25691
26701
  return { details: submissionNonPass, isError: true };
25692
26702
  }
25693
- if (event.isError) return;
25694
- return;
25695
26703
  });
25696
- roleHost.on("agent_end", (event, ctx) => {
26704
+ roleHost.on("agent_end", async (event, ctx) => {
25697
26705
  const lastMessage = event.messages.at(-1);
25698
26706
  if (lastMessage?.role === "assistant" && (lastMessage.stopReason === "error" || lastMessage.stopReason === "aborted")) {
25699
26707
  if (receiptDelivery.nextAction() !== "accepted") {
@@ -25701,6 +26709,47 @@ function createRoleRuntimeExtension(dependencies) {
25701
26709
  }
25702
26710
  return;
25703
26711
  }
26712
+ const role = selectedRole ?? roleHost.getFlag(ROLE_FLAG.name);
26713
+ if (role === "navigator" && receiptDelivery.nextAction() !== "accepted") {
26714
+ const prose = lastAssistantProse(event.messages);
26715
+ if (prose !== void 0 && prose.trim() !== "") {
26716
+ const accepted = { prose };
26717
+ await sealAcceptedSubmission({
26718
+ context: ctx,
26719
+ role: "navigator",
26720
+ accepted,
26721
+ toolCallId: `navigator-prose-exit:${randomUUID8()}`
26722
+ });
26723
+ await projectClosedSubmission(
26724
+ { role: "navigator", kind: "accepted", accepted },
26725
+ ctx
26726
+ );
26727
+ return;
26728
+ }
26729
+ if (!noReceiptRecorded) {
26730
+ const runPointer = runDirectoryFromHostContext(ctx);
26731
+ if (runPointer !== void 0) {
26732
+ noReceiptRecorded = true;
26733
+ while (receiptDelivery.nextAction() === "request-delivery") {
26734
+ receiptDelivery.recordDeliveryRequest();
26735
+ }
26736
+ const facts = receiptDelivery.facts({ runPointer, attemptPointer: `current:${runPointer}` });
26737
+ envelopeHost.appendEntry(NO_RECEIPT_LIFECYCLE_ENTRY_TYPE, facts);
26738
+ try {
26739
+ sitianReport({
26740
+ level: "event",
26741
+ kind: "no-receipt-lifecycle",
26742
+ cwd: ctx.cwd,
26743
+ sessionParent: ctx.sessionManager.getSessionFile(),
26744
+ payload: facts,
26745
+ source: "role-runtime"
26746
+ });
26747
+ } catch {
26748
+ }
26749
+ }
26750
+ }
26751
+ return;
26752
+ }
25704
26753
  if (receiptDelivery.nextAction() === "request-delivery") {
25705
26754
  receiptDelivery.recordDeliveryRequest();
25706
26755
  envelopeHost.appendEntry("ak-receipt-delivery-request");
@@ -26366,8 +27415,8 @@ function createRoleRuntimeDependencies(packageRoot) {
26366
27415
 
26367
27416
  // src/role-envelope.ts
26368
27417
  init_engine_detour();
26369
- import { randomUUID as randomUUID8 } from "node:crypto";
26370
- import { mkdir as mkdir6, writeFile as writeFile12 } from "node:fs/promises";
27418
+ import { randomUUID as randomUUID9 } from "node:crypto";
27419
+ import { appendFile as appendFile3, mkdir as mkdir7, writeFile as writeFile12 } from "node:fs/promises";
26371
27420
  import { createServer } from "node:net";
26372
27421
  import { dirname as dirname24, join as join42 } from "node:path";
26373
27422
  import { fileURLToPath as fileURLToPath2 } from "node:url";
@@ -26455,15 +27504,15 @@ async function requireGatekeeperPass(options) {
26455
27504
  }
26456
27505
 
26457
27506
  // src/host-native-method.ts
26458
- import { lstat as lstat7, mkdir as mkdir5, readlink, realpath as realpath7, symlink } from "node:fs/promises";
26459
- import { basename as basename9, dirname as dirname23, join as join41 } from "node:path";
27507
+ import { lstat as lstat7, mkdir as mkdir6, readlink, realpath as realpath8, symlink } from "node:fs/promises";
27508
+ import { basename as basename10, dirname as dirname23, join as join41 } from "node:path";
26460
27509
  var HOST_METHOD_PLUGIN_NAME = "ak-methods";
26461
27510
  var packagedMethodsDir = (root) => join41(root, "resources", "methods");
26462
27511
  var packagedMethodPluginDir = (root) => join41(root, "dist", "method-host-plugin");
26463
27512
  function hostMethodSkills(methods) {
26464
27513
  return Object.freeze(methods.flatMap((method) => {
26465
27514
  if (method.kind !== "skill") return [];
26466
- const name = basename9(dirname23(method.path));
27515
+ const name = basename10(dirname23(method.path));
26467
27516
  return name ? [Object.freeze({ name })] : [];
26468
27517
  }));
26469
27518
  }
@@ -26488,11 +27537,11 @@ function applyCodexSkillInvocation(methods, prompt) {
26488
27537
  );
26489
27538
  }
26490
27539
  async function installWorkspaceMethodSkills(cwd, packageRoot) {
26491
- const target = await realpath7(packagedMethodsDir(packageRoot));
27540
+ const target = await realpath8(packagedMethodsDir(packageRoot));
26492
27541
  const link = join41(cwd, ".agents", "skills");
26493
27542
  try {
26494
27543
  const stat2 = await lstat7(link);
26495
- if (!stat2.isSymbolicLink() || await realpath7(link) !== target) {
27544
+ if (!stat2.isSymbolicLink() || await realpath8(link) !== target) {
26496
27545
  const detail = stat2.isSymbolicLink() ? `symlink to ${await readlink(link)}` : "non-symlink entry";
26497
27546
  throw new Error(`workspace method catalog conflict at ${link}: ${detail}`);
26498
27547
  }
@@ -26500,12 +27549,12 @@ async function installWorkspaceMethodSkills(cwd, packageRoot) {
26500
27549
  } catch (error) {
26501
27550
  if (error.code !== "ENOENT") throw error;
26502
27551
  }
26503
- await mkdir5(dirname23(link), { recursive: true });
27552
+ await mkdir6(dirname23(link), { recursive: true });
26504
27553
  try {
26505
27554
  await symlink(target, link);
26506
27555
  } catch (error) {
26507
27556
  if (error.code !== "EEXIST") throw error;
26508
- if (await realpath7(link).catch(() => "") !== target) {
27557
+ if (await realpath8(link).catch(() => "") !== target) {
26509
27558
  throw new Error(`workspace method catalog conflict at ${link}`);
26510
27559
  }
26511
27560
  }
@@ -26517,11 +27566,11 @@ init_role_activation_flags();
26517
27566
  init_submission_correctable_error();
26518
27567
  init_navigator_invocation_identity();
26519
27568
  async function listen(server, path) {
26520
- await new Promise((resolve21, reject) => {
27569
+ await new Promise((resolve22, reject) => {
26521
27570
  server.once("error", reject);
26522
27571
  server.listen(path, () => {
26523
27572
  server.off("error", reject);
26524
- resolve21();
27573
+ resolve22();
26525
27574
  });
26526
27575
  });
26527
27576
  }
@@ -26554,10 +27603,10 @@ async function prepareRoleEnvelope(options) {
26554
27603
  let rejection;
26555
27604
  let infrastructureRoundFailure;
26556
27605
  const hostAbort = new AbortController();
26557
- const runId = request.runDirectory.split("/").filter(Boolean).at(-1) ?? randomUUID8();
26558
- await mkdir6(request.runDirectory, { recursive: true });
27606
+ const runId = request.runDirectory.split("/").filter(Boolean).at(-1) ?? randomUUID9();
27607
+ await mkdir7(request.runDirectory, { recursive: true });
26559
27608
  let sessionFile = options.sessionFile ?? join42(request.runDirectory, "session", "session.jsonl");
26560
- await mkdir6(dirname24(sessionFile), { recursive: true });
27609
+ await mkdir7(dirname24(sessionFile), { recursive: true });
26561
27610
  if (request.continuation.kind !== "resume") {
26562
27611
  try {
26563
27612
  await writeFile12(
@@ -26576,6 +27625,25 @@ async function prepareRoleEnvelope(options) {
26576
27625
  if (error.code !== "EEXIST") throw error;
26577
27626
  }
26578
27627
  }
27628
+ let durableWriteChain = Promise.resolve();
27629
+ let armDurableWriteFailure;
27630
+ const persistPackageSessionEntry = (entry) => {
27631
+ const customType = typeof entry.customType === "string" ? entry.customType : "unknown";
27632
+ const line2 = `${JSON.stringify({
27633
+ ...entry,
27634
+ id: typeof entry.id === "string" ? entry.id : randomUUID9(),
27635
+ timestamp: typeof entry.timestamp === "string" ? entry.timestamp : (/* @__PURE__ */ new Date()).toISOString()
27636
+ })}
27637
+ `;
27638
+ durableWriteChain = durableWriteChain.then(async () => {
27639
+ try {
27640
+ await appendFile3(sessionFile, line2, "utf8");
27641
+ } catch (error) {
27642
+ const diagnostic = error instanceof Error ? error.message : String(error);
27643
+ armDurableWriteFailure?.(customType, diagnostic);
27644
+ }
27645
+ });
27646
+ };
26579
27647
  const context = {
26580
27648
  cwd: request.cwd,
26581
27649
  mode: "print",
@@ -26598,6 +27666,7 @@ async function prepareRoleEnvelope(options) {
26598
27666
  const entry = { type: "custom", customType, data };
26599
27667
  sessionEntries.push(entry);
26600
27668
  customEntries.push({ customType, data });
27669
+ persistPackageSessionEntry(entry);
26601
27670
  }
26602
27671
  },
26603
27672
  abort() {
@@ -26611,6 +27680,7 @@ async function prepareRoleEnvelope(options) {
26611
27680
  const entry = { type: "custom_message", customType, ...payload, message: payload };
26612
27681
  sessionEntries.push(entry);
26613
27682
  customEntries.push({ customType, data: message.details ?? message.content });
27683
+ persistPackageSessionEntry(entry);
26614
27684
  };
26615
27685
  const emit = async (event, value) => {
26616
27686
  const results = [];
@@ -26690,7 +27760,7 @@ async function prepareRoleEnvelope(options) {
26690
27760
  }
26691
27761
  };
26692
27762
  createRoleRuntimeExtension(options.dependencies)(envelope);
26693
- const token = randomUUID8();
27763
+ const token = randomUUID9();
26694
27764
  const server = createServer((socket) => serveSocket(socket));
26695
27765
  function rememberProjectedRejection(details, toolCallId, content) {
26696
27766
  if (typeof details !== "object" || details === null) return;
@@ -26726,6 +27796,17 @@ async function prepareRoleEnvelope(options) {
26726
27796
  };
26727
27797
  hostAbort.abort();
26728
27798
  }
27799
+ armDurableWriteFailure = (customType, diagnostic) => {
27800
+ rememberInfrastructureFailure(
27801
+ {
27802
+ cause: "infrastructure",
27803
+ kind: "role_infrastructure_failure",
27804
+ code: "durable-session-write-failed",
27805
+ customType
27806
+ },
27807
+ [{ type: "text", text: `ak-role: durable session entry flush failed (${customType}): ${diagnostic}` }]
27808
+ );
27809
+ };
26729
27810
  function declareRoundInfrastructureFailure(error) {
26730
27811
  const diagnostic = error instanceof Error ? error.message : String(error);
26731
27812
  const content = [{ type: "text", text: diagnostic }];
@@ -26771,7 +27852,7 @@ async function prepareRoleEnvelope(options) {
26771
27852
  async function invokeAkTool(name, args) {
26772
27853
  const tool = tools.get(name);
26773
27854
  if (tool === void 0) throw new Error(`Unknown AK tool: ${name}`);
26774
- const toolCallId = randomUUID8();
27855
+ const toolCallId = randomUUID9();
26775
27856
  calls.push({ toolCallId, toolName: name });
26776
27857
  sessionEntries.push({
26777
27858
  type: "message",
@@ -26887,6 +27968,15 @@ async function prepareRoleEnvelope(options) {
26887
27968
  const relay = fileURLToPath2(new URL("./mcp-relay.mjs", import.meta.url));
26888
27969
  await listen(server, options.socketPath);
26889
27970
  let disposed = false;
27971
+ let durableFailureHandedToCloseRound = false;
27972
+ const settleDurableWrites = async () => {
27973
+ await durableWriteChain;
27974
+ if (infrastructureRoundFailure !== void 0) {
27975
+ durableFailureHandedToCloseRound = true;
27976
+ return { accepted: false, failure: infrastructureRoundFailure };
27977
+ }
27978
+ return void 0;
27979
+ };
26890
27980
  const dispose = async () => {
26891
27981
  if (disposed) return;
26892
27982
  disposed = true;
@@ -26896,11 +27986,25 @@ async function prepareRoleEnvelope(options) {
26896
27986
  } catch (error) {
26897
27987
  cleanupFailures.push(error);
26898
27988
  }
27989
+ try {
27990
+ const alreadyHanded = durableFailureHandedToCloseRound;
27991
+ const durableFailure = await settleDurableWrites();
27992
+ if (durableFailure !== void 0 && !alreadyHanded) {
27993
+ cleanupFailures.push(
27994
+ Object.assign(
27995
+ new Error(durableFailure.failure.diagnostic ?? "durable session entry flush failed"),
27996
+ { code: durableFailure.failure.identity?.code ?? "durable-session-write-failed" }
27997
+ )
27998
+ );
27999
+ }
28000
+ } catch (error) {
28001
+ cleanupFailures.push(error);
28002
+ }
26899
28003
  try {
26900
28004
  const closeAll = server.closeAllConnections;
26901
28005
  if (typeof closeAll === "function") closeAll.call(server);
26902
- await new Promise((resolve21, reject) => {
26903
- server.close((error) => error ? reject(error) : resolve21());
28006
+ await new Promise((resolve22, reject) => {
28007
+ server.close((error) => error ? reject(error) : resolve22());
26904
28008
  });
26905
28009
  } catch (error) {
26906
28010
  cleanupFailures.push(error);
@@ -26917,6 +28021,7 @@ async function prepareRoleEnvelope(options) {
26917
28021
  if (calls.some((call) => call.toolName === terminatingToolName)) return;
26918
28022
  await invokeAkTool(terminatingToolName, params ?? {});
26919
28023
  }
28024
+ ;
26920
28025
  const closeRound = async () => {
26921
28026
  if (calls.length > 0) {
26922
28027
  const roundCalls = [...calls];
@@ -26924,6 +28029,7 @@ async function prepareRoleEnvelope(options) {
26924
28029
  await emit("turn_end", { turnIndex: 0, calls: roundCalls });
26925
28030
  }
26926
28031
  if (infrastructureRoundFailure !== void 0) {
28032
+ durableFailureHandedToCloseRound = true;
26927
28033
  return { accepted: false, failure: infrastructureRoundFailure };
26928
28034
  }
26929
28035
  let closure;
@@ -26935,6 +28041,8 @@ async function prepareRoleEnvelope(options) {
26935
28041
  }
26936
28042
  if (closure !== void 0) {
26937
28043
  await emit("agent_settled", {});
28044
+ const durableFailure2 = await settleDurableWrites();
28045
+ if (durableFailure2 !== void 0) return durableFailure2;
26938
28046
  return { accepted: true };
26939
28047
  }
26940
28048
  if (rejection !== void 0) {
@@ -26944,9 +28052,13 @@ async function prepareRoleEnvelope(options) {
26944
28052
  message: rejection.message
26945
28053
  };
26946
28054
  rejection = void 0;
28055
+ const durableFailure2 = await settleDurableWrites();
28056
+ if (durableFailure2 !== void 0) return durableFailure2;
26947
28057
  return { accepted: false, retry };
26948
28058
  }
26949
28059
  await emit("agent_settled", {});
28060
+ const durableFailure = await settleDurableWrites();
28061
+ if (durableFailure !== void 0) return durableFailure;
26950
28062
  return { accepted: true };
26951
28063
  };
26952
28064
  try {
@@ -27047,10 +28159,11 @@ function headlessTurnArgs(options) {
27047
28159
  description.promptFlag,
27048
28160
  ...description.fixedArgs,
27049
28161
  description.systemPromptFlag,
27050
- options.systemPromptPath,
27051
- description.jsonSchemaFlag,
27052
- JSON.stringify(options.jsonSchema)
28162
+ options.systemPromptPath
27053
28163
  ];
28164
+ if (options.jsonSchema !== void 0) {
28165
+ args.push(description.jsonSchemaFlag, JSON.stringify(options.jsonSchema));
28166
+ }
27054
28167
  if (options.pluginDir) args.push("--plugin-dir", options.pluginDir);
27055
28168
  if (options.mcpConfigPath !== void 0 && options.mcpConfigPath !== "") {
27056
28169
  args.push(description.mcpConfigFlag, options.mcpConfigPath);
@@ -27261,7 +28374,9 @@ function codexTurnArgs(options) {
27261
28374
  }
27262
28375
  }
27263
28376
  args.push("-c", `model_instructions_file=${codexTomlString(options.systemPromptPath)}`);
27264
- args.push("--output-schema", options.outputSchemaPath);
28377
+ if (options.outputSchemaPath !== void 0) {
28378
+ args.push("--output-schema", options.outputSchemaPath);
28379
+ }
27265
28380
  args.push(...codexMcpConfigArgs(options.mcpServers));
27266
28381
  if (options.model !== void 0 && options.model !== "") {
27267
28382
  args.push("-m", options.model);
@@ -27292,10 +28407,10 @@ function headlessMcpConfigDocument(mcpServers) {
27292
28407
 
27293
28408
  // src/headless-host/role-turn-host.ts
27294
28409
  import { spawn as spawn4, spawnSync } from "node:child_process";
27295
- import { randomUUID as randomUUID9 } from "node:crypto";
28410
+ import { randomUUID as randomUUID10 } from "node:crypto";
27296
28411
  import { existsSync as existsSync13 } from "node:fs";
27297
28412
  import { writeFile as writeFile13 } from "node:fs/promises";
27298
- import { dirname as dirname25, isAbsolute as isAbsolute11, join as join44, resolve as resolve20 } from "node:path";
28413
+ import { dirname as dirname25, isAbsolute as isAbsolute11, join as join44, resolve as resolve21 } from "node:path";
27299
28414
 
27300
28415
  // src/external-host-turn-loop.ts
27301
28416
  init_host_contracts();
@@ -27414,6 +28529,7 @@ function reportHostSessionEvent(input) {
27414
28529
  }
27415
28530
 
27416
28531
  // src/headless-host/role-turn-host.ts
28532
+ init_navigator_output();
27417
28533
  function failure(cause, name, code, details, diagnostic) {
27418
28534
  return {
27419
28535
  code: null,
@@ -27543,10 +28659,10 @@ function resolveGitCommonDir(cwd) {
27543
28659
  if (raw === "") {
27544
28660
  throw new Error("git rev-parse --git-common-dir returned empty stdout");
27545
28661
  }
27546
- return isAbsolute11(raw) ? raw : resolve20(cwd, raw);
28662
+ return isAbsolute11(raw) ? raw : resolve21(cwd, raw);
27547
28663
  }
27548
28664
  function spawnHeadlessTurn(options) {
27549
- return new Promise((resolve21, reject) => {
28665
+ return new Promise((resolve22, reject) => {
27550
28666
  if (options.signal?.aborted) {
27551
28667
  reject(hostAbortedError("headless host aborted"));
27552
28668
  return;
@@ -27621,7 +28737,7 @@ function spawnHeadlessTurn(options) {
27621
28737
  reject(stdinDeliveryError);
27622
28738
  return;
27623
28739
  }
27624
- resolve21({ code, stdout: resultStdout, stderr, timedOut });
28740
+ resolve22({ code, stdout: resultStdout, stderr, timedOut });
27625
28741
  };
27626
28742
  const onAbort = () => {
27627
28743
  child.kill("SIGTERM");
@@ -27682,10 +28798,9 @@ function buildTurnArgs(options) {
27682
28798
  if (options.sessionKind === "resume" && !options.sessionId) {
27683
28799
  throw new Error("codex resume requires a bound thread_id");
27684
28800
  }
27685
- if (options.outputSchemaPath === void 0) throw new Error("codex requires an output schema path");
27686
28801
  return codexTurnArgs({
27687
28802
  systemPromptPath: options.systemPromptPath,
27688
- outputSchemaPath: options.outputSchemaPath,
28803
+ ...options.outputSchemaPath === void 0 ? {} : { outputSchemaPath: options.outputSchemaPath },
27689
28804
  mcpServers: options.mcpServers,
27690
28805
  ...options.model === void 0 ? {} : { model: options.model },
27691
28806
  ...options.effort === void 0 ? {} : { effort: options.effort },
@@ -27700,7 +28815,8 @@ function buildTurnArgs(options) {
27700
28815
  return headlessTurnArgs({
27701
28816
  description: options.description,
27702
28817
  systemPromptPath: options.systemPromptPath,
27703
- jsonSchema: options.jsonSchema,
28818
+ // #959: navigator omits --json-schema so free-form prose is a lawful exit.
28819
+ ...options.jsonSchema === void 0 ? {} : { jsonSchema: options.jsonSchema },
27704
28820
  mcpConfigPath: options.mcpConfigPath,
27705
28821
  ...options.model === void 0 ? {} : { model: options.model },
27706
28822
  ...options.effort === void 0 ? {} : { effort: options.effort },
@@ -27718,7 +28834,7 @@ function createHeadlessRoleTurnHost(config) {
27718
28834
  let sessionId = await config.sessionIdentity.load(request.principal);
27719
28835
  let sessionKind = request.continuation.kind === "resume" && sessionId !== void 0 && sessionId !== "" ? "resume" : "new";
27720
28836
  if (sessionKind === "new" && !codex) {
27721
- sessionId = randomUUID9();
28837
+ sessionId = randomUUID10();
27722
28838
  await config.sessionIdentity.bind(request.principal, sessionId);
27723
28839
  }
27724
28840
  const env = { ...process.env, ...config.env ?? {} };
@@ -27729,13 +28845,15 @@ function createHeadlessRoleTurnHost(config) {
27729
28845
  let pluginDir;
27730
28846
  let applyMethodPrompt = codex ? (prompt) => applyCodexSkillInvocation(request.methods, prompt) : (prompt) => prompt;
27731
28847
  if (codex) {
27732
- outputSchemaPath = join44(request.runDirectory, "headless-output-schema.json");
27733
- await writeFile13(
27734
- outputSchemaPath,
27735
- `${JSON.stringify(closeJsonSchemaForCodex(prepared.jsonSchema), null, 2)}
28848
+ if (prepared.terminatingToolName !== NAVIGATOR_OUTPUT_TOOL_NAME) {
28849
+ outputSchemaPath = join44(request.runDirectory, "headless-output-schema.json");
28850
+ await writeFile13(
28851
+ outputSchemaPath,
28852
+ `${JSON.stringify(closeJsonSchemaForCodex(prepared.jsonSchema), null, 2)}
27736
28853
  `,
27737
- "utf8"
27738
- );
28854
+ "utf8"
28855
+ );
28856
+ }
27739
28857
  } else {
27740
28858
  mcpConfigPath = join44(request.runDirectory, "headless-mcp-config.json");
27741
28859
  await writeFile13(
@@ -27767,7 +28885,8 @@ function createHeadlessRoleTurnHost(config) {
27767
28885
  args = buildTurnArgs({
27768
28886
  description: config.description,
27769
28887
  systemPromptPath,
27770
- jsonSchema: prepared.jsonSchema,
28888
+ // #959: navigator prose exit — no closed JSON schema on claude either.
28889
+ ...prepared.terminatingToolName === NAVIGATOR_OUTPUT_TOOL_NAME ? {} : { jsonSchema: prepared.jsonSchema },
27771
28890
  mcpServers: prepared.mcpServers,
27772
28891
  ...mcpConfigPath === void 0 ? {} : { mcpConfigPath },
27773
28892
  ...outputSchemaPath === void 0 ? {} : { outputSchemaPath },
@@ -27891,6 +29010,18 @@ function createHeadlessRoleTurnHost(config) {
27891
29010
  details: { sessionId, exitCode: spawned.code }
27892
29011
  });
27893
29012
  }
29013
+ if (prepared.terminatingToolName === NAVIGATOR_OUTPUT_TOOL_NAME) {
29014
+ if (observation.finalMessage.trim() === "") {
29015
+ return terminalFromSpawned(spawned, {
29016
+ cause: "output",
29017
+ identity: { name: "HeadlessEmptyOutput", code: "empty-stdout" },
29018
+ diagnostic: spawned.stderr.trim() || "codex exec produced empty agent_message",
29019
+ details: { sessionId, exitCode: spawned.code }
29020
+ });
29021
+ }
29022
+ await prepared.ingestStructuredOutput({ prose: observation.finalMessage });
29023
+ return { status: "delivered", stderr: spawned.stderr };
29024
+ }
27894
29025
  let receipt;
27895
29026
  try {
27896
29027
  receipt = JSON.parse(observation.finalMessage);
@@ -27935,6 +29066,8 @@ function createHeadlessRoleTurnHost(config) {
27935
29066
  }
27936
29067
  if (envelope.structured_output !== void 0) {
27937
29068
  await prepared.ingestStructuredOutput(envelope.structured_output);
29069
+ } else if (prepared.terminatingToolName === NAVIGATOR_OUTPUT_TOOL_NAME && typeof envelope.result === "string" && envelope.result.trim() !== "") {
29070
+ await prepared.ingestStructuredOutput({ prose: envelope.result });
27938
29071
  }
27939
29072
  return { status: "delivered", stderr: spawned.stderr };
27940
29073
  }
@@ -27973,7 +29106,7 @@ function createProductionHeadlessRoleTurnHost(options) {
27973
29106
  sessionFile: sessionIdentity.resolveSessionFile(request.principal),
27974
29107
  // Same MCP relay as ACP so intermediate AK tools stay reachable;
27975
29108
  // headless adapter projects the row into --mcp-config.
27976
- socketPath: `/tmp/ak-headless-mcp-${randomUUID10()}.sock`,
29109
+ socketPath: `/tmp/ak-headless-mcp-${randomUUID11()}.sock`,
27977
29110
  // Schema channel owns the terminating receipt; hide it from MCP list.
27978
29111
  listTerminatingToolOnMcp: false
27979
29112
  })