@akagilnc/pi-workflow-roles 0.1.4586 → 0.1.4620

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +2 -2
  2. package/README.zh-CN.md +2 -2
  3. package/dist/acp-host/production-host.js +951 -497
  4. package/dist/archivist-record-topology.js +27 -35
  5. package/dist/headless-host/description.js +7 -4
  6. package/dist/headless-host/production-host.js +783 -393
  7. package/dist/migrate-book-topology.js +3 -6
  8. package/dist/navigator-attendance.js +146 -241
  9. package/dist/navigator-public-session.js +81 -15
  10. package/dist/package-contracts/navigator-output.js +30 -12
  11. package/dist/public-cli/judge-run.js +2 -2
  12. package/dist/public-cli/main.js +69 -94
  13. package/dist/public-cli/option-definitions.js +1 -1
  14. package/dist/public-cli/post-admission.js +2 -2
  15. package/dist/public-cli/run-lifecycle.js +29 -7
  16. package/dist/public-cli/settlement.js +46 -32
  17. package/dist/public-cli/terminal.js +8 -27
  18. package/dist/public-role-summons.js +22 -4
  19. package/dist/submission-ledger.js +56 -23
  20. package/package.json +1 -1
  21. package/resources/836-deleted-machine-instruction-inventory.md +2 -0
  22. package/resources/navigator-route-playbook.md +9 -0
  23. package/scripts/build-package.mjs +6 -1
  24. package/src/acp-host/role-turn-host.ts +129 -13
  25. package/src/headless-host/description.ts +17 -7
  26. package/src/headless-host/role-turn-host.ts +42 -11
  27. package/src/navigator-attendance.ts +290 -425
  28. package/src/navigator-public-session.ts +126 -25
  29. package/src/navigator-role.ts +2 -2
  30. package/src/package-contracts/navigator-output.ts +41 -25
  31. package/src/public-cli/coder-run.ts +2 -2
  32. package/src/public-cli/fixer-run.ts +2 -2
  33. package/src/public-cli/judge-run.ts +2 -2
  34. package/src/public-cli/merger-run.ts +2 -2
  35. package/src/public-cli/option-definitions.ts +1 -1
  36. package/src/public-cli/post-admission.ts +2 -1
  37. package/src/public-cli/run-lifecycle.ts +37 -7
  38. package/src/public-cli/settlement.ts +42 -33
  39. package/src/public-cli/terminal.ts +12 -37
  40. package/src/public-role-summons.ts +34 -5
  41. package/src/role-envelope.ts +89 -4
  42. package/src/role-runtime.ts +74 -14
  43. package/src/submission-ledger.ts +63 -21
  44. package/dist/public-cli/command-renderer.js +0 -5
  45. package/dist/public-command-renderer.js +0 -29
  46. package/src/public-cli/command-renderer.ts +0 -9
  47. package/src/public-command-renderer.ts +0 -55
@@ -1807,7 +1807,48 @@ var init_collector_output = __esm({
1807
1807
  });
1808
1808
 
1809
1809
  // src/package-contracts/navigator-output.ts
1810
+ var navigator_output_exports = {};
1811
+ __export(navigator_output_exports, {
1812
+ NAVIGATOR_ACCEPTED_TEXT: () => NAVIGATOR_ACCEPTED_TEXT,
1813
+ NAVIGATOR_OUTPUT_TOOL_NAME: () => NAVIGATOR_OUTPUT_TOOL_NAME,
1814
+ navigatorOutputSchema: () => navigatorOutputSchema,
1815
+ navigatorProseFromUnknown: () => navigatorProseFromUnknown,
1816
+ projectLawfulNavigatorOutput: () => projectLawfulNavigatorOutput,
1817
+ validateRecordedNavigatorOutput: () => validateRecordedNavigatorOutput
1818
+ });
1810
1819
  import { Type as Type5 } from "typebox";
1820
+ function projectLawfulNavigatorOutput(value) {
1821
+ if (value === void 0 || value === null) return void 0;
1822
+ if (typeof value === "string") return { prose: value };
1823
+ if (typeof value === "object" && !Array.isArray(value)) {
1824
+ const record4 = value;
1825
+ if (typeof record4.prose === "string") return { prose: record4.prose };
1826
+ if (record4.prose !== void 0 && record4.prose !== null) {
1827
+ return { prose: typeof record4.prose === "string" ? record4.prose : String(record4.prose) };
1828
+ }
1829
+ const keys = Object.keys(record4);
1830
+ if (keys.length === 0) return { prose: "" };
1831
+ try {
1832
+ return { prose: JSON.stringify(record4) };
1833
+ } catch {
1834
+ return { prose: String(record4) };
1835
+ }
1836
+ }
1837
+ return { prose: String(value) };
1838
+ }
1839
+ function validateRecordedNavigatorOutput(value) {
1840
+ const projected = projectLawfulNavigatorOutput(value);
1841
+ if (projected === void 0) {
1842
+ throw new Error("Navigator output is empty");
1843
+ }
1844
+ return projected;
1845
+ }
1846
+ function navigatorProseFromUnknown(value) {
1847
+ const projected = projectLawfulNavigatorOutput(value);
1848
+ if (projected === void 0) return void 0;
1849
+ const trimmed = projected.prose.trim();
1850
+ return trimmed === "" ? void 0 : projected.prose;
1851
+ }
1811
1852
  var NAVIGATOR_OUTPUT_TOOL_NAME, NAVIGATOR_ACCEPTED_TEXT, navigatorOutputSchema;
1812
1853
  var init_navigator_output = __esm({
1813
1854
  "src/package-contracts/navigator-output.ts"() {
@@ -1819,11 +1860,8 @@ var init_navigator_output = __esm({
1819
1860
  navigatorOutputSchema = withTerminatingOutputDeclarations(
1820
1861
  openToolObject(
1821
1862
  Type5.Object({
1822
- status: Type5.Unknown({
1823
- description: "advice \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8"
1824
- }),
1825
- candidates: Type5.Unknown({
1826
- 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"
1863
+ prose: Type5.Unknown({
1864
+ 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"
1827
1865
  })
1828
1866
  })
1829
1867
  )
@@ -5420,6 +5458,56 @@ var init_typed_provider_http = __esm({
5420
5458
  });
5421
5459
 
5422
5460
  // src/public-cli/run-lifecycle.ts
5461
+ var run_lifecycle_exports = {};
5462
+ __export(run_lifecycle_exports, {
5463
+ AUTO_RESUME_LIMIT: () => AUTO_RESUME_LIMIT,
5464
+ GATE_DOSSIER_POINTER_PREFIX: () => GATE_DOSSIER_POINTER_PREFIX,
5465
+ RESUME_TRANSPORT_ENVELOPE: () => RESUME_TRANSPORT_ENVELOPE,
5466
+ RunWriterLeaseHeldError: () => RunWriterLeaseHeldError,
5467
+ V1_RESUMABLE_PROVIDERS: () => V1_RESUMABLE_PROVIDERS,
5468
+ acquireRunWriterLease: () => acquireRunWriterLease,
5469
+ autopsyWriterLock: () => autopsyWriterLock,
5470
+ buildAutoResumeContinuationPrompt: () => buildAutoResumeContinuationPrompt,
5471
+ buildResumeContinuationPrompt: () => buildResumeContinuationPrompt,
5472
+ clearCurrentCourt: () => clearCurrentCourt,
5473
+ clearTypedProviderHttpObservation: () => clearTypedProviderHttpObservation,
5474
+ describeErrorIdentity: () => describeErrorIdentity,
5475
+ findLatestRunIdForSeatTicket: () => findLatestRunIdForSeatTicket,
5476
+ findRunDirectoryById: () => findRunDirectoryById,
5477
+ isDurablePrincipalAvailable: () => isDurablePrincipalAvailable,
5478
+ isV1ResumableProvider: () => isV1ResumableProvider,
5479
+ loadResumableCoderRun: () => loadResumableCoderRun,
5480
+ loadResumableCollectorRun: () => loadResumableCollectorRun,
5481
+ loadResumableCountersignRun: () => loadResumableCountersignRun,
5482
+ loadResumableDiaristRun: () => loadResumableDiaristRun,
5483
+ loadResumableDoctorRun: () => loadResumableDoctorRun,
5484
+ loadResumableFixerRun: () => loadResumableFixerRun,
5485
+ loadResumableGleanerLeftRun: () => loadResumableGleanerLeftRun,
5486
+ loadResumableInspectorRun: () => loadResumableInspectorRun,
5487
+ loadResumableInstructionSeatRun: () => loadResumableInstructionSeatRun,
5488
+ loadResumableJudgeRun: () => loadResumableJudgeRun,
5489
+ loadResumableMergerRun: () => loadResumableMergerRun,
5490
+ loadResumableNotaryRun: () => loadResumableNotaryRun,
5491
+ loadResumableReviewerRun: () => loadResumableReviewerRun,
5492
+ loadResumableSecretariatRun: () => loadResumableSecretariatRun,
5493
+ markRunAdmitted: () => markRunAdmitted,
5494
+ markRunResumable: () => markRunResumable,
5495
+ markRunRunning: () => markRunRunning,
5496
+ markRunTerminal: () => markRunTerminal,
5497
+ parentRunPathFromGatePointerInstruction: () => parentRunPathFromGatePointerInstruction,
5498
+ peekRoleRunRole: () => peekRoleRunRole,
5499
+ readCurrentCourt: () => readCurrentCourt,
5500
+ readLatestTypedProviderHttpObservation: () => readLatestTypedProviderHttpObservation,
5501
+ readRoleRunIdentity: () => readRoleRunIdentity,
5502
+ readRoleRunState: () => readRoleRunState,
5503
+ readRunParentPath: () => readRunParentPath,
5504
+ readTypedHttp429Observation: () => readTypedHttp429Observation,
5505
+ recordCurrentCourt: () => recordCurrentCourt,
5506
+ recordTypedProviderHttpStatus: () => recordTypedProviderHttpStatus,
5507
+ renderResumeCommand: () => renderResumeCommand,
5508
+ selectResumeContinuationPrompt: () => selectResumeContinuationPrompt,
5509
+ writeRoleRunState: () => writeRoleRunState
5510
+ });
5423
5511
  import { chmod, lstat as lstat2, open, readdir as readdir4, readFile as readFile9, unlink as unlink2, writeFile as writeFile4 } from "node:fs/promises";
5424
5512
  import { basename as basename4, join as join15 } from "node:path";
5425
5513
  function selectResumeContinuationPrompt(message, engineMaterial) {
@@ -5435,6 +5523,15 @@ function buildResumeContinuationPrompt(options) {
5435
5523
  })
5436
5524
  );
5437
5525
  }
5526
+ function buildAutoResumeContinuationPrompt(options) {
5527
+ return selectResumeContinuationPrompt(
5528
+ RESUME_TRANSPORT_ENVELOPE,
5529
+ engineSessionMaterialFromOptions({
5530
+ packageRoot: options.packageRoot,
5531
+ ...pickEngineAxis(options)
5532
+ })
5533
+ );
5534
+ }
5438
5535
  function isV1ResumableProvider(provider) {
5439
5536
  return V1_RESUMABLE_PROVIDERS.includes(provider);
5440
5537
  }
@@ -5598,6 +5695,11 @@ function materializeRoleRunFromDisk(disk, authority) {
5598
5695
  return void 0;
5599
5696
  }
5600
5697
  }
5698
+ async function readRoleRunState(runDirectory, authority) {
5699
+ const disk = await readRoleRunStateDisk(runDirectory);
5700
+ if (disk === void 0) return void 0;
5701
+ return materializeRoleRunFromDisk(disk, authority)?.run;
5702
+ }
5601
5703
  async function readRoleRunIdentity(runDirectory) {
5602
5704
  const disk = await readRoleRunStateDisk(runDirectory);
5603
5705
  if (disk === void 0) return void 0;
@@ -6331,6 +6433,75 @@ async function loadResumableJudgeRun(home, runId, authority) {
6331
6433
  };
6332
6434
  return seatLoadedResult(loaded, admitted);
6333
6435
  }
6436
+ async function loadResumableCoderRun(home, runId, authority) {
6437
+ const loaded = await loadResumableRunRecord(home, runId, authority);
6438
+ if (loaded.run.role !== "coder") {
6439
+ throw new CliUsageError(
6440
+ `role run ${runId} belongs to ${loaded.run.role}, not coder`
6441
+ );
6442
+ }
6443
+ const phase = loaded.admittedFields.phase ?? loaded.run.phase;
6444
+ if (phase !== "plan" && phase !== "apply") {
6445
+ throw new CliUsageError(
6446
+ `role run admitted coder phase is missing: ${runId}`
6447
+ );
6448
+ }
6449
+ const taskPath = loaded.admittedFields.taskPath;
6450
+ if (taskPath === void 0) {
6451
+ throw new CliUsageError(
6452
+ `role run admitted coder task path is missing: ${runId}`
6453
+ );
6454
+ }
6455
+ if (loaded.admittedFields.instruction.trim() === "") {
6456
+ throw new CliUsageError(
6457
+ `role run admitted coder task is blank: ${runId}`
6458
+ );
6459
+ }
6460
+ const admitted = {
6461
+ role: "coder",
6462
+ phase,
6463
+ ...resumedBaseAdmitted(loaded),
6464
+ instructionEmpty: false,
6465
+ taskPath
6466
+ };
6467
+ return seatLoadedResult(loaded, admitted);
6468
+ }
6469
+ async function loadResumableFixerRun(home, runId, authority) {
6470
+ const loaded = await loadResumableRunRecord(home, runId, authority);
6471
+ if (loaded.run.role !== "fixer") {
6472
+ throw new CliUsageError(
6473
+ `role run ${runId} belongs to ${loaded.run.role}, not fixer`
6474
+ );
6475
+ }
6476
+ const phase = loaded.admittedFields.phase ?? loaded.run.phase;
6477
+ if (phase !== "plan" && phase !== "apply") {
6478
+ throw new CliUsageError(
6479
+ `role run admitted fixer phase is missing: ${runId}`
6480
+ );
6481
+ }
6482
+ const packetPath = loaded.admittedFields.packetPath;
6483
+ if (packetPath === void 0) {
6484
+ throw new CliUsageError(
6485
+ `role run admitted fixer packet path is missing: ${runId}`
6486
+ );
6487
+ }
6488
+ if (loaded.admittedFields.instruction.trim() === "") {
6489
+ throw new CliUsageError(
6490
+ `role run admitted fixer instruction is blank: ${runId}`
6491
+ );
6492
+ }
6493
+ const prerequisites = loaded.admittedFields.prerequisites ?? Object.freeze([]);
6494
+ const admitted = {
6495
+ role: "fixer",
6496
+ phase,
6497
+ ...resumedBaseAdmitted(loaded),
6498
+ instructionEmpty: false,
6499
+ packetPath,
6500
+ ...loaded.admittedFields.prerequisitesPath === void 0 ? {} : { prerequisitesPath: loaded.admittedFields.prerequisitesPath },
6501
+ prerequisites
6502
+ };
6503
+ return seatLoadedResult(loaded, admitted);
6504
+ }
6334
6505
  async function loadResumableReviewerRun(home, runId, authority) {
6335
6506
  const loaded = await loadResumableRunRecord(home, runId, authority);
6336
6507
  if (loaded.run.role !== "reviewer") {
@@ -6404,6 +6575,26 @@ async function loadResumableInstructionSeatRun(home, runId, authority) {
6404
6575
  };
6405
6576
  return seatLoadedResult(loaded, admitted);
6406
6577
  }
6578
+ async function loadResumableGleanerLeftRun(home, runId, authority) {
6579
+ const loaded = await loadResumableRunRecord(home, runId, authority);
6580
+ if (loaded.run.role !== "gleaner-left") {
6581
+ throw new CliUsageError(
6582
+ `role run ${runId} belongs to ${loaded.run.role}, not gleaner-left`
6583
+ );
6584
+ }
6585
+ const baseRevision = loaded.admittedFields.baseRevision;
6586
+ if (baseRevision === void 0 || baseRevision.trim() === "") {
6587
+ throw new CliUsageError(
6588
+ `role run admitted gleaner-left base revision is missing: ${runId}`
6589
+ );
6590
+ }
6591
+ const admitted = {
6592
+ role: "gleaner-left",
6593
+ ...resumedBaseAdmitted(loaded),
6594
+ baseRevision
6595
+ };
6596
+ return seatLoadedResult(loaded, admitted);
6597
+ }
6407
6598
  async function loadResumableDiaristRun(home, runId, authority) {
6408
6599
  const loaded = await loadResumableRunRecord(home, runId, authority);
6409
6600
  if (loaded.run.role !== "diarist") {
@@ -6417,6 +6608,88 @@ async function loadResumableDiaristRun(home, runId, authority) {
6417
6608
  };
6418
6609
  return seatLoadedResult(loaded, admitted);
6419
6610
  }
6611
+ async function loadResumableSecretariatRun(home, runId, authority) {
6612
+ const loaded = await loadResumableRunRecord(home, runId, authority);
6613
+ if (loaded.run.role !== "secretariat") {
6614
+ throw new CliUsageError(
6615
+ `role run ${runId} belongs to ${loaded.run.role}, not secretariat`
6616
+ );
6617
+ }
6618
+ const admitted = {
6619
+ role: "secretariat",
6620
+ ...resumedBaseAdmitted(loaded)
6621
+ };
6622
+ return seatLoadedResult(loaded, admitted);
6623
+ }
6624
+ async function loadResumableMergerRun(home, runId, authority) {
6625
+ const loaded = await loadResumableRunRecord(home, runId, authority);
6626
+ if (loaded.run.role !== "merger") {
6627
+ throw new CliUsageError(
6628
+ `role run ${runId} belongs to ${loaded.run.role}, not merger`
6629
+ );
6630
+ }
6631
+ const mergerInputPath = loaded.admittedFields.mergerInputPath;
6632
+ if (mergerInputPath === void 0) {
6633
+ throw new CliUsageError(
6634
+ `role run admitted merger input path is missing: ${runId}`
6635
+ );
6636
+ }
6637
+ const derived = loaded.admittedFields.derived;
6638
+ if (derived === void 0) {
6639
+ throw new CliUsageError(
6640
+ `role run admitted merger envelope is missing: ${runId}`
6641
+ );
6642
+ }
6643
+ if (loaded.admittedFields.instruction.trim() === "") {
6644
+ throw new CliUsageError(
6645
+ `role run admitted merger task is blank: ${runId}`
6646
+ );
6647
+ }
6648
+ const admitted = {
6649
+ role: "merger",
6650
+ ...resumedBaseAdmitted(loaded),
6651
+ instructionEmpty: false,
6652
+ mergerInputPath,
6653
+ derived
6654
+ };
6655
+ return seatLoadedResult(loaded, admitted);
6656
+ }
6657
+ async function loadResumableCollectorRun(home, runId, authority) {
6658
+ const loaded = await loadResumableRunRecord(home, runId, authority);
6659
+ if (loaded.run.role !== "collector") {
6660
+ throw new CliUsageError(
6661
+ `role run ${runId} belongs to ${loaded.run.role}, not collector`
6662
+ );
6663
+ }
6664
+ const { prNumber, repository, repositoryDisplay, manifestDigest } = loaded.admittedFields;
6665
+ if (repository === void 0 || repositoryDisplay === void 0 || manifestDigest === void 0) {
6666
+ throw new CliUsageError(
6667
+ `role run admitted collector repository identity is missing: ${runId}`
6668
+ );
6669
+ }
6670
+ let parsedRepository;
6671
+ try {
6672
+ parsedRepository = parseCollectorRepository(repositoryDisplay);
6673
+ } catch (error) {
6674
+ const detail = error instanceof Error ? error.message : String(error);
6675
+ throw new CliUsageError(detail, { cause: error });
6676
+ }
6677
+ if (parsedRepository.canonical !== repository) {
6678
+ throw new CliUsageError(
6679
+ `role run admitted collector repository does not match its canonical form: ${runId}`
6680
+ );
6681
+ }
6682
+ const admitted = {
6683
+ role: "collector",
6684
+ ...resumedBaseAdmitted(loaded),
6685
+ ...prNumber === void 0 ? {} : { prNumber },
6686
+ repository: parsedRepository,
6687
+ ...loaded.admittedFields.requestManifestPath === void 0 ? {} : { requestManifestPath: loaded.admittedFields.requestManifestPath },
6688
+ ...loaded.admittedFields.waitWindowMs === void 0 ? {} : { waitWindowMs: loaded.admittedFields.waitWindowMs },
6689
+ manifestDigest
6690
+ };
6691
+ return seatLoadedResult(loaded, admitted);
6692
+ }
6420
6693
  async function loadResumableDoctorRun(home, runId, authority) {
6421
6694
  const loaded = await loadResumableRunRecord(home, runId, authority);
6422
6695
  if (loaded.run.role !== "doctor") {
@@ -6474,6 +6747,12 @@ async function loadResumableInspectorRun(home, runId, authority) {
6474
6747
  };
6475
6748
  return seatLoadedResult(loaded, admitted);
6476
6749
  }
6750
+ async function peekRoleRunRole(home, runId) {
6751
+ const runDirectory = await findRunDirectoryById(home, runId);
6752
+ if (runDirectory === void 0) return void 0;
6753
+ const run = await readRoleRunIdentity(runDirectory);
6754
+ return run?.role;
6755
+ }
6477
6756
  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;
6478
6757
  var init_run_lifecycle = __esm({
6479
6758
  "src/public-cli/run-lifecycle.ts"() {
@@ -6490,7 +6769,7 @@ var init_run_lifecycle = __esm({
6490
6769
  init_invocation();
6491
6770
  V1_RESUMABLE_PROVIDERS = ["openai-codex", "xai"];
6492
6771
  AUTO_RESUME_LIMIT = 2;
6493
- RESUME_TRANSPORT_ENVELOPE = "[ak-role:resume-continue]";
6772
+ RESUME_TRANSPORT_ENVELOPE = "\u7EE7\u7EED\u3002";
6494
6773
  RUN_STATE_FILE = "run-state.json";
6495
6774
  WRITER_LOCK_FILE = "writer.lock";
6496
6775
  RunWriterLeaseHeldError = class extends Error {
@@ -7545,7 +7824,7 @@ var init_option_definitions = __esm({
7545
7824
  },
7546
7825
  navigator: {
7547
7826
  command: "navigator",
7548
- summary: "Direct Navigator (\u6E38\u5955\u4F7F) route advice: ordered next-role candidates.",
7827
+ summary: "Direct Navigator (\u6E38\u5955\u4F7F) free-form prose route advice.",
7549
7828
  usage: ["ak-role navigator [options] [instruction]"],
7550
7829
  examples: [
7551
7830
  'ak-role navigator "\u521A\u5B8C\u6210 coder apply \u6536\u655B\uFF0C\u4E0B\u4E00\u6B65\uFF1F"'
@@ -11835,31 +12114,58 @@ async function restoreState(cwd, runId, scope) {
11835
12114
  }, 0)
11836
12115
  };
11837
12116
  }
12117
+ function sessionParentFromHostContext(context) {
12118
+ const runDirectory = runDirectoryFromHostContext(context);
12119
+ if (runDirectory !== void 0) return join24(runDirectory, "session", "session.jsonl");
12120
+ const sessionFile = context.sessionManager.getSessionFile?.();
12121
+ if (typeof sessionFile === "string" && sessionFile.length > 0) return sessionFile;
12122
+ const sessionDir = context.sessionManager.getSessionDir?.();
12123
+ if (typeof sessionDir === "string" && sessionDir.length > 0) {
12124
+ return join24(sessionDir, "session.jsonl");
12125
+ }
12126
+ return void 0;
12127
+ }
12128
+ function homeFromHostContext(context, home) {
12129
+ if (home !== void 0) return home;
12130
+ const sessionParent = sessionParentFromHostContext(context);
12131
+ return sessionParent !== void 0 ? tryHomeFromAkRolesPath(sessionParent) : void 0;
12132
+ }
12133
+ async function sealAcceptedSubmission(options) {
12134
+ const runId = runIdentity(options.context);
12135
+ const attemptId = attemptIdentity(options.context, runId);
12136
+ const sessionParent = sessionParentFromHostContext(options.context);
12137
+ const home = homeFromHostContext(options.context, options.home);
12138
+ const state = await restoreState(options.context.cwd, runId, {
12139
+ ...home === void 0 ? {} : { home },
12140
+ ...sessionParent === void 0 ? {} : { sessionParent }
12141
+ });
12142
+ const pointer = sitianReport({
12143
+ level: "event",
12144
+ kind: "sealed",
12145
+ subject: { runId, attemptId },
12146
+ ...state.prior === void 0 ? {} : { priorEventId: state.prior.identity },
12147
+ payload: {
12148
+ type: "sealed",
12149
+ attemptId,
12150
+ toolCallId: options.toolCallId,
12151
+ role: options.role,
12152
+ accepted: options.accepted
12153
+ },
12154
+ source: "role-runtime",
12155
+ cwd: options.context.cwd,
12156
+ ...home !== void 0 ? { home } : {},
12157
+ ...sessionParent === void 0 ? {} : { sessionParent }
12158
+ });
12159
+ state.prior = pointer;
12160
+ }
11838
12161
  function createSubmissionLedgerHost(host, outputTools, failInfrastructure2 = (error) => {
11839
12162
  throw error;
11840
12163
  }, projectClosure = () => void 0, options) {
11841
12164
  const states = /* @__PURE__ */ new Map();
11842
- const sessionParentFromContext = (context) => {
11843
- const runDirectory = runDirectoryFromHostContext(context);
11844
- if (runDirectory !== void 0) {
11845
- return join24(runDirectory, "session", "session.jsonl");
11846
- }
11847
- const sessionFile = context.sessionManager.getSessionFile?.();
11848
- if (typeof sessionFile === "string" && sessionFile.length > 0) return sessionFile;
11849
- const sessionDir = context.sessionManager.getSessionDir?.();
11850
- if (typeof sessionDir === "string" && sessionDir.length > 0) {
11851
- return join24(sessionDir, "session.jsonl");
11852
- }
11853
- return void 0;
11854
- };
11855
- const resolveHomeFromContext = (context) => {
11856
- if (options?.home !== void 0) return options.home;
11857
- const sessionParent = sessionParentFromContext(context);
11858
- return sessionParent !== void 0 ? tryHomeFromAkRolesPath(sessionParent) : void 0;
11859
- };
12165
+ const resolveHomeFromContext = (context) => homeFromHostContext(context, options?.home);
11860
12166
  const stateFor = (context, runId) => states.get(runId) ?? (() => {
11861
12167
  const home = resolveHomeFromContext(context);
11862
- const sessionParent = sessionParentFromContext(context);
12168
+ const sessionParent = sessionParentFromHostContext(context);
11863
12169
  const pending = restoreState(context.cwd, runId, {
11864
12170
  ...home === void 0 ? {} : { home },
11865
12171
  ...sessionParent === void 0 ? {} : { sessionParent }
@@ -11869,7 +12175,7 @@ function createSubmissionLedgerHost(host, outputTools, failInfrastructure2 = (er
11869
12175
  })();
11870
12176
  const appendFor = (state, context, runId, attemptId, event) => {
11871
12177
  const home = resolveHomeFromContext(context);
11872
- const sessionParent = sessionParentFromContext(context);
12178
+ const sessionParent = sessionParentFromHostContext(context);
11873
12179
  const pointer = sitianReport({
11874
12180
  level: "event",
11875
12181
  kind: event.type,
@@ -14197,44 +14503,6 @@ var init_receipt_delivery_policy = __esm({
14197
14503
  }
14198
14504
  });
14199
14505
 
14200
- // src/public-command-renderer.ts
14201
- function isPublicCallableRole2(role) {
14202
- return PUBLIC_CALLABLE_ROLES3.has(role);
14203
- }
14204
- function renderPublicAkRoleCommand(target) {
14205
- if (!isPublicCallableRole2(target.role)) return void 0;
14206
- const role = target.role;
14207
- const metadata = packagedRoleMetadata(role);
14208
- if (metadata !== void 0 && "bareCommand" in metadata && metadata.bareCommand === false) {
14209
- return void 0;
14210
- }
14211
- if (target.phase === null || target.phase === void 0) {
14212
- return `ak-role ${role}`;
14213
- }
14214
- if (role === "coder" || role === "fixer") {
14215
- return `ak-role ${role} ${target.phase}`;
14216
- }
14217
- return `ak-role ${role}`;
14218
- }
14219
- var PUBLIC_CALLABLE_ROLES3;
14220
- var init_public_command_renderer = __esm({
14221
- "src/public-command-renderer.ts"() {
14222
- "use strict";
14223
- init_packaged_role_registry();
14224
- PUBLIC_CALLABLE_ROLES3 = new Set(
14225
- PACKAGED_ROLE_REGISTRY.map((entry) => entry.role)
14226
- );
14227
- }
14228
- });
14229
-
14230
- // src/public-cli/command-renderer.ts
14231
- var init_command_renderer = __esm({
14232
- "src/public-cli/command-renderer.ts"() {
14233
- "use strict";
14234
- init_public_command_renderer();
14235
- }
14236
- });
14237
-
14238
14506
  // src/public-cli/terminal.ts
14239
14507
  function encodeTerminalField(value) {
14240
14508
  return JSON.stringify(value);
@@ -14245,14 +14513,10 @@ function isLawfulTypedTerminalOutcome(outcome) {
14245
14513
  function exitCodeForTerminalOutcome(outcome) {
14246
14514
  return isLawfulTypedTerminalOutcome(outcome) ? 0 : 1;
14247
14515
  }
14248
- function recommendationNavigatorFact(input) {
14249
- const command = typeof input.modelCommand === "string" && input.modelCommand.trim() !== "" ? input.modelCommand : isPublicCallableRole2(input.next.role) ? renderPublicAkRoleCommand(input.next) : void 0;
14516
+ function adviceNavigatorFact(input) {
14250
14517
  return {
14251
- disposition: "recommendation",
14252
- next: input.next,
14253
- reason: input.reason,
14254
- ...command === void 0 ? {} : { command },
14255
- ...input.route === void 0 ? {} : { route: input.route },
14518
+ disposition: "advice",
14519
+ prose: input.prose,
14256
14520
  ...input.advisoryDiagnostic === void 0 ? {} : { advisoryDiagnostic: input.advisoryDiagnostic }
14257
14521
  };
14258
14522
  }
@@ -14280,14 +14544,8 @@ function formatTerminalResult(result) {
14280
14544
  if (result.navigator.advisoryDiagnostic !== void 0) {
14281
14545
  lines.push(`navigator-advisory ${encodeTerminalField(result.navigator.advisoryDiagnostic)}`);
14282
14546
  }
14283
- if (result.navigator.disposition === "recommendation") {
14284
- lines.push(
14285
- `next ${result.navigator.next.role} ${result.navigator.next.phase ?? "none"}`
14286
- );
14287
- lines.push(`reason ${encodeTerminalField(result.navigator.reason)}`);
14288
- if (result.navigator.command !== void 0) {
14289
- lines.push(`command ${encodeTerminalField(result.navigator.command)}`);
14290
- }
14547
+ if (result.navigator.disposition === "advice") {
14548
+ lines.push(`prose ${encodeTerminalField(result.navigator.prose)}`);
14291
14549
  } else if (result.navigator.disposition === "unavailable") {
14292
14550
  lines.push(
14293
14551
  `unavailable ${result.navigator.source} ${encodeTerminalField(result.navigator.reason)}`
@@ -14336,7 +14594,6 @@ function formatTerminalResult(result) {
14336
14594
  var init_terminal = __esm({
14337
14595
  "src/public-cli/terminal.ts"() {
14338
14596
  "use strict";
14339
- init_command_renderer();
14340
14597
  }
14341
14598
  });
14342
14599
 
@@ -15316,10 +15573,6 @@ async function appendRunAttemptHistory(source, outcome) {
15316
15573
  } catch {
15317
15574
  }
15318
15575
  }
15319
- function navigatorPhaseValue(value) {
15320
- if (value === "plan" || value === "apply") return value;
15321
- return null;
15322
- }
15323
15576
  function navigatorAttendanceCorrelatedWithBoundMarker(details, attendanceIndex, terminalIndex, marker) {
15324
15577
  if (attendanceIndex <= terminalIndex) return false;
15325
15578
  if (details.invocationId !== marker.invocationId) return false;
@@ -15328,29 +15581,33 @@ function navigatorAttendanceCorrelatedWithBoundMarker(details, attendanceIndex,
15328
15581
  function parseNavigatorAttendanceDetails(details) {
15329
15582
  const disposition = details.disposition;
15330
15583
  const advisoryDiagnostic = typeof details.routePlaybookReadFailure === "string" ? { advisoryDiagnostic: details.routePlaybookReadFailure } : {};
15331
- if (disposition === "recommendation") {
15332
- const next = details.next;
15333
- if (!isRecord11(next) || typeof next.role !== "string") {
15584
+ if (disposition === "advice" || disposition === "recommendation") {
15585
+ let prose;
15586
+ if (typeof details.prose === "string" && details.prose.trim() !== "") {
15587
+ prose = details.prose;
15588
+ } else {
15589
+ const next = isRecord11(details.next) && typeof details.next.role === "string" ? details.next.role : void 0;
15590
+ const reason = typeof details.reason === "string" && details.reason.trim() !== "" ? details.reason : void 0;
15591
+ const command = typeof details.command === "string" && details.command.trim() !== "" ? details.command : void 0;
15592
+ if (reason !== void 0 && next !== void 0) {
15593
+ prose = `${reason}\uFF08\u4E0B\u4E00\u6B65\uFF1A${next}\uFF09`;
15594
+ } else if (reason !== void 0) {
15595
+ prose = reason;
15596
+ } else if (next !== void 0) {
15597
+ prose = `\u4E0B\u4E00\u6B65\uFF1A${next}`;
15598
+ } else if (command !== void 0) {
15599
+ prose = command;
15600
+ }
15601
+ }
15602
+ if (prose === void 0 || prose.trim() === "") {
15334
15603
  return {
15335
- disposition: "unavailable",
15336
- source: "unknown",
15337
- reason: "navigator recommendation missing typed next role"
15604
+ disposition: "no-advice",
15605
+ ...advisoryDiagnostic
15338
15606
  };
15339
15607
  }
15340
- const reason = typeof details.reason === "string" ? details.reason : "";
15341
- const route = Array.isArray(details.route) ? details.route.filter(isRecord11).map((target) => ({
15342
- role: String(target.role),
15343
- phase: navigatorPhaseValue(target.phase)
15344
- })) : void 0;
15345
- return recommendationNavigatorFact({
15346
- ...advisoryDiagnostic,
15347
- next: {
15348
- role: next.role,
15349
- phase: navigatorPhaseValue(next.phase)
15350
- },
15351
- reason,
15352
- ...route === void 0 ? {} : { route },
15353
- ...typeof details.command === "string" ? { modelCommand: details.command } : {}
15608
+ return adviceNavigatorFact({
15609
+ prose,
15610
+ ...advisoryDiagnostic
15354
15611
  });
15355
15612
  }
15356
15613
  if (disposition === "unavailable") {
@@ -18977,7 +19234,7 @@ async function runPostAdmissionOneShot(input) {
18977
19234
  ...input.request,
18978
19235
  continuation: {
18979
19236
  kind: "resume",
18980
- prompt: buildResumeContinuationPrompt({
19237
+ prompt: buildAutoResumeContinuationPrompt({
18981
19238
  packageRoot: input.env.packageRoot,
18982
19239
  ...pickEngineAxis({
18983
19240
  engine: input.effectiveEngine ?? input.env.engine,
@@ -19849,7 +20106,7 @@ async function runPublicJudge(argv, env, io, parseJudgeArgv2) {
19849
20106
  ...admitted.correlationId === void 0 && env.correlationId === void 0 ? {} : { correlationId: admitted.correlationId ?? env.correlationId },
19850
20107
  continuation: {
19851
20108
  kind: "resume",
19852
- prompt: buildResumeContinuationPrompt({
20109
+ prompt: buildAutoResumeContinuationPrompt({
19853
20110
  packageRoot: env.packageRoot,
19854
20111
  ...pickEngineAxis(env)
19855
20112
  })
@@ -21232,14 +21489,32 @@ async function summonPublicRole(options) {
21232
21489
  case "navigator":
21233
21490
  case "gatekeeper": {
21234
21491
  const seat2 = options.role;
21235
- const [{ runPublicInstructionSeat: runPublicInstructionSeat2 }, invocation] = await Promise.all([
21492
+ const [{ runPublicInstructionSeat: runPublicInstructionSeat2, runPublicInstructionSeatResume: runPublicInstructionSeatResume2 }, invocation] = await Promise.all([
21236
21493
  Promise.resolve().then(() => (init_instruction_seat_run(), instruction_seat_run_exports)),
21237
21494
  Promise.resolve().then(() => (init_invocation(), invocation_exports))
21238
21495
  ]);
21239
21496
  const parse = seat2 === "auditor" ? invocation.parseAuditorArgv : seat2 === "navigator" ? invocation.parseNavigatorArgv : invocation.parseGatekeeperArgv;
21240
- const stepped = await runPrepared(parse, (env, once) => runPublicInstructionSeat2(options.argv, env, io, seat2, once));
21241
- if ("fail" in stepped) return stepped.fail;
21242
- result = stepped.ok;
21497
+ const resumeRunId = typeof options.resumeRunId === "string" && options.resumeRunId.trim() !== "" ? options.resumeRunId.trim() : void 0;
21498
+ if (resumeRunId !== void 0) {
21499
+ const instruction = options.argv[0] ?? "";
21500
+ const stepped = await runPrepared(parse, (env) => runPublicInstructionSeatResume2(
21501
+ {
21502
+ runId: resumeRunId,
21503
+ summons: {
21504
+ instruction,
21505
+ instructionEmpty: instruction.trim() === ""
21506
+ }
21507
+ },
21508
+ env,
21509
+ io
21510
+ ));
21511
+ if ("fail" in stepped) return stepped.fail;
21512
+ result = stepped.ok;
21513
+ } else {
21514
+ const stepped = await runPrepared(parse, (env, once) => runPublicInstructionSeat2(options.argv, env, io, seat2, once));
21515
+ if ("fail" in stepped) return stepped.fail;
21516
+ result = stepped.ok;
21517
+ }
21243
21518
  break;
21244
21519
  }
21245
21520
  case "judge": {
@@ -21653,12 +21928,12 @@ var init_public_role_summons = __esm({
21653
21928
  });
21654
21929
 
21655
21930
  // src/acp-host/production-host.ts
21656
- import { randomUUID as randomUUID9 } from "node:crypto";
21931
+ import { randomUUID as randomUUID10 } from "node:crypto";
21657
21932
 
21658
21933
  // src/role-envelope.ts
21659
21934
  init_engine_detour();
21660
- import { randomUUID as randomUUID8 } from "node:crypto";
21661
- import { mkdir as mkdir7, writeFile as writeFile12 } from "node:fs/promises";
21935
+ import { randomUUID as randomUUID9 } from "node:crypto";
21936
+ import { appendFile as appendFile3, mkdir as mkdir7, writeFile as writeFile12 } from "node:fs/promises";
21662
21937
  import { createServer } from "node:net";
21663
21938
  import { dirname as dirname22, join as join41 } from "node:path";
21664
21939
  import { fileURLToPath as fileURLToPath2 } from "node:url";
@@ -21788,6 +22063,7 @@ init_host_contracts();
21788
22063
  init_sitian_facade();
21789
22064
  init_submission_ledger();
21790
22065
  init_collector_ledger();
22066
+ import { randomUUID as randomUUID8 } from "node:crypto";
21791
22067
  import { readFileSync as readFileSync6, writeSync as writeSync4 } from "node:fs";
21792
22068
  import { join as join40 } from "node:path";
21793
22069
  import { Value as Value4 } from "typebox/value";
@@ -23634,7 +23910,7 @@ init_navigator_output();
23634
23910
  var NAVIGATOR_TOOL_SPEC = {
23635
23911
  name: NAVIGATOR_OUTPUT_TOOL_NAME,
23636
23912
  label: "\u6E38\u5955\u4F7F\u5EFA\u8BAE",
23637
- description: "\u6E38\u5955\u4F7F\u7EC8\u5C40\u56DE\u6267\uFF1A\u6392\u597D\u5E8F\u7684\u4E0B\u4E00\u6B65\u89D2\u8272\u8DEF\u7EBF\u5EFA\u8BAE\u3002",
23913
+ description: "\u6E38\u5955\u4F7F\u7EC8\u5C40\u56DE\u6267\uFF1A\u6563\u6587\u5EFA\u8BAE\uFF0C\u539F\u6837\u5448\u73B0\u3002",
23638
23914
  promptSnippet: "\u6E38\u5955\u4F7F\u5EFA\u8BAE",
23639
23915
  parameters: navigatorOutputSchema
23640
23916
  };
@@ -23665,6 +23941,7 @@ import { Type as Type22 } from "typebox";
23665
23941
 
23666
23942
  // src/navigator-public-session.ts
23667
23943
  init_sitian_facade();
23944
+ import { basename as basename10 } from "node:path";
23668
23945
 
23669
23946
  // src/navigator-session-contracts.ts
23670
23947
  import { Type as Type21 } from "typebox";
@@ -23852,6 +24129,7 @@ async function resolveNavigatorSeatSelection(context) {
23852
24129
 
23853
24130
  // src/navigator-public-session.ts
23854
24131
  init_host_contracts();
24132
+ init_cli_errors();
23855
24133
  async function resolveNavigatorLedgerHome(context) {
23856
24134
  const { tryHomeFromAkRolesPath: tryHomeFromAkRolesPath2 } = await Promise.resolve().then(() => (init_activation_ledger_topology(), activation_ledger_topology_exports));
23857
24135
  const runDirectory = runDirectoryFromHostContext(context);
@@ -23866,7 +24144,42 @@ async function resolveNavigatorLedgerHome(context) {
23866
24144
  }
23867
24145
  return void 0;
23868
24146
  }
23869
- function createNativeNavigatorSessionFactory() {
24147
+ var NAVIGATOR_HOST_RUN_POINTER_ENTRY = "ak-navigator-host-run";
24148
+ function exactRecord2(value) {
24149
+ return typeof value === "object" && value !== null && !Array.isArray(value);
24150
+ }
24151
+ function runIdFromNavigatorDirectory(runDirectory) {
24152
+ const entry = basename10(runDirectory);
24153
+ const suffix = "@navigator";
24154
+ if (!entry.endsWith(suffix)) return void 0;
24155
+ const runId = entry.slice(0, entry.length - suffix.length);
24156
+ return runId.length > 0 ? runId : void 0;
24157
+ }
24158
+ function readNavigatorHostRunPointer(entries) {
24159
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
24160
+ const entry = entries[index];
24161
+ if (!exactRecord2(entry)) continue;
24162
+ if (entry.type === "custom" && entry.customType === NAVIGATOR_HOST_RUN_POINTER_ENTRY) {
24163
+ const data = entry.data;
24164
+ if (exactRecord2(data) && typeof data.runId === "string" && data.runId.trim() !== "") {
24165
+ return data.runId.trim();
24166
+ }
24167
+ }
24168
+ }
24169
+ return void 0;
24170
+ }
24171
+ async function navigatorHostRunResumable(home, runId) {
24172
+ const { piDurablePrincipalAuthority: piDurablePrincipalAuthority2 } = await Promise.resolve().then(() => (init_durable_principal(), durable_principal_exports));
24173
+ const { loadResumableInstructionSeatRun: loadResumableInstructionSeatRun2 } = await Promise.resolve().then(() => (init_run_lifecycle(), run_lifecycle_exports));
24174
+ try {
24175
+ const loaded = await loadResumableInstructionSeatRun2(home, runId, piDurablePrincipalAuthority2);
24176
+ return loaded.admitted.role === "navigator";
24177
+ } catch (error) {
24178
+ if (error instanceof CliUsageError) return false;
24179
+ throw error;
24180
+ }
24181
+ }
24182
+ function createNativeNavigatorSessionFactory(deps) {
23870
24183
  return async ({ context, subject, tool }) => {
23871
24184
  let thinkingLevel;
23872
24185
  const { createRecordSession: createRecordSession2, NAVIGATOR_RECORD_KIND: NAVIGATOR_RECORD_KIND2 } = await Promise.resolve().then(() => (init_archivist_record_entry(), archivist_record_entry_exports));
@@ -23882,6 +24195,11 @@ function createNativeNavigatorSessionFactory() {
23882
24195
  let noReceipt;
23883
24196
  let disposed = false;
23884
24197
  let inFlightPrompt;
24198
+ let hostRunId = readNavigatorHostRunPointer(sessionManager.getEntries());
24199
+ const summon = deps?.summonPublicRole ?? (async (options) => {
24200
+ const { summonPublicRole: summonPublicRole2 } = await Promise.resolve().then(() => (init_public_role_summons(), public_role_summons_exports));
24201
+ return summonPublicRole2(options);
24202
+ });
23885
24203
  return {
23886
24204
  prompt: async (text) => {
23887
24205
  if (disposed) {
@@ -23891,14 +24209,24 @@ function createNativeNavigatorSessionFactory() {
23891
24209
  noReceipt = void 0;
23892
24210
  const run = (async () => {
23893
24211
  try {
23894
- const { summonPublicRole: summonPublicRole2 } = await Promise.resolve().then(() => (init_public_role_summons(), public_role_summons_exports));
23895
24212
  const summonHome = await resolveNavigatorLedgerHome(context);
23896
- const summoned = await summonPublicRole2({
24213
+ const resumeRunId = hostRunId;
24214
+ const baseSummon = {
23897
24215
  role: "navigator",
23898
24216
  argv: [text],
23899
24217
  cwd: context.cwd,
23900
24218
  ...summonHome === void 0 ? {} : { home: summonHome }
23901
- });
24219
+ };
24220
+ const resumable = deps?.hostRunResumable ?? navigatorHostRunResumable;
24221
+ let summoned;
24222
+ if (resumeRunId === void 0 || summonHome === void 0) {
24223
+ summoned = await summon(baseSummon);
24224
+ } else if (await resumable(summonHome, resumeRunId)) {
24225
+ summoned = await summon({ ...baseSummon, resumeRunId });
24226
+ } else {
24227
+ hostRunId = void 0;
24228
+ summoned = await summon(baseSummon);
24229
+ }
23902
24230
  const outcome = summoned.terminal?.roleOutcome;
23903
24231
  if (outcome === void 0) {
23904
24232
  const detail = summoned.stderr?.trim() || `exit ${summoned.exitCode}`;
@@ -23921,21 +24249,31 @@ function createNativeNavigatorSessionFactory() {
23921
24249
  noReceipt = outcome;
23922
24250
  return;
23923
24251
  }
24252
+ const runDirectory = summoned.runDirectory ?? (typeof summoned.admitted?.runDirectory === "string" ? summoned.admitted.runDirectory : void 0);
24253
+ if (typeof runDirectory === "string" && runDirectory.trim() !== "") {
24254
+ const nextRunId = runIdFromNavigatorDirectory(runDirectory);
24255
+ if (nextRunId !== void 0) {
24256
+ hostRunId = nextRunId;
24257
+ sessionManager.appendCustomEntry(NAVIGATOR_HOST_RUN_POINTER_ENTRY, { runId: nextRunId });
24258
+ }
24259
+ }
23924
24260
  if (outcome.kind !== "accepted") {
23925
24261
  return;
23926
24262
  }
24263
+ const { navigatorProseFromUnknown: navigatorProseFromUnknown2 } = await Promise.resolve().then(() => (init_navigator_output(), navigator_output_exports));
24264
+ const proseParts = [];
23927
24265
  for (const payload of outcome.payloads ?? []) {
23928
- if (typeof payload !== "object" || payload === null || Array.isArray(payload)) continue;
23929
- const candidates = payload.candidates;
23930
- if (!Array.isArray(candidates)) continue;
23931
- await tool.execute(
23932
- "navigator-public-prepare",
23933
- { candidates },
23934
- void 0,
23935
- void 0,
23936
- context
23937
- );
24266
+ const prose = navigatorProseFromUnknown2(payload);
24267
+ if (prose !== void 0) proseParts.push(prose);
23938
24268
  }
24269
+ if (proseParts.length === 0) return;
24270
+ await tool.execute(
24271
+ "navigator-public-prepare",
24272
+ { prose: proseParts.join("\n\n") },
24273
+ void 0,
24274
+ void 0,
24275
+ context
24276
+ );
23939
24277
  } catch (error) {
23940
24278
  if (error instanceof NavigatorUnavailableError) throw error;
23941
24279
  const fact = navigatorProviderFailureFromError(error);
@@ -23989,9 +24327,9 @@ function createNativeNavigatorSessionFactory() {
23989
24327
 
23990
24328
  // src/navigator-attendance.ts
23991
24329
  init_sitian_facade();
23992
- init_public_command_renderer();
23993
24330
  init_work_subject_identity();
23994
24331
  init_receipt_delivery_policy();
24332
+ init_navigator_output();
23995
24333
  var NAVIGATOR_EVENT_TYPE = "ak-navigator-attendance";
23996
24334
  var NAVIGATOR_PREPARE_ACCEPTED_TEXT = "\u6E38\u5955\u4F7F\u51C6\u5907\u5DF2\u63A5\u53D7";
23997
24335
  function resolveNavigatorAuthorityMaterial(roleInput, fileAuthority) {
@@ -24001,107 +24339,40 @@ function resolveNavigatorAuthorityMaterial(roleInput, fileAuthority) {
24001
24339
  }
24002
24340
  var NAVIGATOR_TARGETS = PACKAGED_ROLE_REGISTRY.map(({ role, phases }) => ({ role, phases }));
24003
24341
  var prepareSchema = Type22.Object({
24004
- candidates: Type22.Optional(Type22.Unknown({
24005
- 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"
24342
+ prose: Type22.Optional(Type22.Unknown({
24343
+ 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"
24006
24344
  }))
24007
24345
  }, { additionalProperties: true });
24008
- var ROUTE_ENTRY = "ak-navigator-route";
24009
24346
  var CONTEXT_ENTRY = "ak-navigator-context";
24010
24347
  var INVOCATION_ENTRY = NAVIGATOR_INVOCATION_ENTRY;
24011
24348
  var SETTLEMENT_ENTRY = "ak-navigator-settlement";
24012
- var targetRoles = new Set(NAVIGATOR_TARGETS.map(({ role }) => role));
24013
- function exactRecord2(value) {
24349
+ function exactRecord3(value) {
24014
24350
  return typeof value === "object" && value !== null && !Array.isArray(value);
24015
24351
  }
24016
24352
  function rejectedPrepareReason(entries, start) {
24017
24353
  const recent = entries.slice(start);
24018
24354
  const prepareCalls = /* @__PURE__ */ new Set();
24019
24355
  for (const entry of recent) {
24020
- if (!exactRecord2(entry) || entry.type !== "message" || !exactRecord2(entry.message) || entry.message.role !== "assistant" || !Array.isArray(entry.message.content)) continue;
24356
+ if (!exactRecord3(entry) || entry.type !== "message" || !exactRecord3(entry.message) || entry.message.role !== "assistant" || !Array.isArray(entry.message.content)) continue;
24021
24357
  for (const part of entry.message.content) {
24022
- if (exactRecord2(part) && part.type === "toolCall" && part.name === NAVIGATOR_PREPARE_TOOL_NAME && typeof part.id === "string") prepareCalls.add(part.id);
24358
+ if (exactRecord3(part) && part.type === "toolCall" && part.name === NAVIGATOR_PREPARE_TOOL_NAME && typeof part.id === "string") prepareCalls.add(part.id);
24023
24359
  }
24024
24360
  }
24025
24361
  let reason;
24026
24362
  for (const entry of recent) {
24027
- if (!exactRecord2(entry) || entry.type !== "message" || !exactRecord2(entry.message) || entry.message.role !== "toolResult" || entry.message.isError !== true) continue;
24363
+ if (!exactRecord3(entry) || entry.type !== "message" || !exactRecord3(entry.message) || entry.message.role !== "toolResult" || entry.message.isError !== true) continue;
24028
24364
  const callId = entry.message.toolCallId;
24029
24365
  if (entry.message.toolName !== NAVIGATOR_PREPARE_TOOL_NAME || typeof callId !== "string" || !prepareCalls.has(callId)) {
24030
24366
  return void 0;
24031
24367
  }
24032
24368
  const content = entry.message.content;
24033
- const text = Array.isArray(content) ? content.flatMap((part) => exactRecord2(part) && typeof part.text === "string" ? [part.text] : []).join("") : typeof content === "string" ? content : "";
24369
+ const text = Array.isArray(content) ? content.flatMap((part) => exactRecord3(part) && typeof part.text === "string" ? [part.text] : []).join("") : typeof content === "string" ? content : "";
24034
24370
  if (text.trim() !== "") reason = text.trim();
24035
24371
  }
24036
24372
  return reason;
24037
24373
  }
24038
- function targetIsValid(value) {
24039
- if (!exactRecord2(value) || !targetRoles.has(String(value.role))) return false;
24040
- const metadata = packagedRoleMetadata(String(value.role));
24041
- return metadata !== void 0 && metadata.phases.includes(value.phase);
24042
- }
24043
- function normalizeTarget(value) {
24044
- if (!exactRecord2(value)) return void 0;
24045
- const role = typeof value.role === "string" ? value.role.trim() : "";
24046
- if (role === "") return void 0;
24047
- if (value.phase === void 0 || value.phase === null) {
24048
- return { role, phase: null };
24049
- }
24050
- if (value.phase === "plan" || value.phase === "apply") {
24051
- return { role, phase: value.phase };
24052
- }
24053
- return { role, phase: null };
24054
- }
24055
- function normalizeMatches(value) {
24056
- if (!exactRecord2(value)) return void 0;
24057
- if (typeof value.role !== "string" || value.role.trim() === "") return void 0;
24058
- if (value.kind !== "accepted") return void 0;
24059
- let phase;
24060
- if (value.phase === void 0 || value.phase === null) phase = null;
24061
- else if (value.phase === "plan" || value.phase === "apply") phase = value.phase;
24062
- else return void 0;
24063
- if (value.statuses !== void 0) {
24064
- if (!Array.isArray(value.statuses) || value.statuses.some((status) => typeof status !== "string" || status.trim() === "")) {
24065
- return void 0;
24066
- }
24067
- return {
24068
- role: value.role,
24069
- phase,
24070
- kind: "accepted",
24071
- statuses: [...value.statuses]
24072
- };
24073
- }
24074
- return { role: value.role, phase, kind: "accepted" };
24075
- }
24076
- function normalizeCandidate(value) {
24077
- if (!exactRecord2(value)) return void 0;
24078
- const next = normalizeTarget(value.next);
24079
- const route = Array.isArray(value.route) ? value.route.map(normalizeTarget).filter((target) => target !== void 0) : void 0;
24080
- const matches = normalizeMatches(value.matches);
24081
- const id = typeof value.id === "string" && value.id.trim() !== "" ? value.id : void 0;
24082
- const reason = typeof value.reason === "string" && value.reason.trim() !== "" ? value.reason : void 0;
24083
- const command = typeof value.command === "string" ? value.command : void 0;
24084
- return {
24085
- ...id === void 0 ? {} : { id },
24086
- ...matches === void 0 ? {} : { matches },
24087
- ...route === void 0 || route.length === 0 ? {} : { route },
24088
- ...next === void 0 ? {} : { next },
24089
- ...reason === void 0 ? {} : { reason },
24090
- ...command === void 0 ? {} : { command }
24091
- };
24092
- }
24093
- function normalizePrepareOutput(value) {
24094
- if (!exactRecord2(value) || !Array.isArray(value.candidates)) return [];
24095
- return value.candidates.map(normalizeCandidate).filter((candidate) => candidate !== void 0);
24096
- }
24097
- function routeEqual(a, b) {
24098
- return a !== void 0 && a.length === b.length && a.every((target, index) => target.role === b[index].role && target.phase === b[index].phase);
24099
- }
24100
- function routeText(route) {
24101
- return route.map((target) => target.phase === null ? target.role : `${target.role} ${target.phase}`).join(" \u2192 ");
24102
- }
24103
- function targetText(target) {
24104
- return target.phase === null ? target.role : `${target.role} ${target.phase}`;
24374
+ function normalizePrepareProse(value) {
24375
+ return navigatorProseFromUnknown(value);
24105
24376
  }
24106
24377
  function navigatorSubjectKey(subjectRoot, subject, provenance = "role_input") {
24107
24378
  if (issueRoot(subjectRoot) !== void 0 || !subjectRoot.includes("/.ak/work/")) return subjectRoot;
@@ -24123,7 +24394,7 @@ function createNavigatorPrepareTool(onOutput) {
24123
24394
  return {
24124
24395
  name: NAVIGATOR_PREPARE_TOOL_NAME,
24125
24396
  label: "\u6E38\u5955\u4F7F\u51C6\u5907",
24126
- description: "\u63D0\u4EA4\u6E38\u5955\u4F7F\u65B9\u5411\u5EFA\u8BAE\u3002",
24397
+ description: "\u63D0\u4EA4\u6E38\u5955\u4F7F\u6563\u6587\u5EFA\u8BAE\u3002",
24127
24398
  parameters: prepareSchema,
24128
24399
  async execute(_id, value) {
24129
24400
  onOutput(value);
@@ -24131,34 +24402,6 @@ function createNavigatorPrepareTool(onOutput) {
24131
24402
  }
24132
24403
  };
24133
24404
  }
24134
- function selectNavigatorCandidate(candidates, settlement) {
24135
- if (settlement.kind !== "accepted") return void 0;
24136
- const usable = candidates.filter((candidate) => candidate.next !== void 0);
24137
- if (usable.length === 0) return void 0;
24138
- const rolePhaseMatched = usable.filter(
24139
- (candidate) => candidate.matches !== void 0 && candidate.matches.role === settlement.role && candidate.matches.phase === settlement.phase
24140
- );
24141
- if (rolePhaseMatched.length > 0) {
24142
- if (settlement.status !== void 0) {
24143
- const statusSpecific = rolePhaseMatched.find(
24144
- (candidate) => candidate.matches?.statuses !== void 0 && candidate.matches.statuses.includes(settlement.status)
24145
- );
24146
- if (statusSpecific !== void 0) {
24147
- return { candidate: statusSpecific, matchedToSettlement: true };
24148
- }
24149
- }
24150
- const rolePhaseGeneric = rolePhaseMatched.find(
24151
- (candidate) => candidate.matches?.statuses === void 0
24152
- );
24153
- if (rolePhaseGeneric !== void 0) {
24154
- return { candidate: rolePhaseGeneric, matchedToSettlement: true };
24155
- }
24156
- return void 0;
24157
- }
24158
- const unbound = usable.find((candidate) => candidate.matches === void 0);
24159
- if (unbound === void 0) return void 0;
24160
- return { candidate: unbound, matchedToSettlement: false };
24161
- }
24162
24405
  function formatNavigatorReport(report) {
24163
24406
  const playbookFailure = report.routePlaybookReadFailure === void 0 ? [] : [`\u8DEF\u4E66\u8BFB\u53D6\u5931\u8D25\uFF1A${report.routePlaybookReadFailure}`];
24164
24407
  if (report.disposition === "no-advice") return playbookFailure.join("\n");
@@ -24168,31 +24411,24 @@ function formatNavigatorReport(report) {
24168
24411
  if (report.disposition === "arrival") {
24169
24412
  return [...playbookFailure, ...report.arrivalMessage ? [report.arrivalMessage] : []].join("\n");
24170
24413
  }
24171
- return [
24172
- ...playbookFailure,
24173
- ...report.route === void 0 ? [] : [`\u8DEF\u7EBF\uFF1A${routeText(report.route)}`],
24174
- ...report.next === void 0 ? [] : [`\u4E0B\u4E00\u6B65\uFF1A${targetText(report.next)}`],
24175
- ...report.reason === void 0 || report.reason.trim() === "" ? [] : [`\u7406\u7531\uFF1A${report.reason}`],
24176
- ...report.command === void 0 || report.command.trim() === "" ? [] : [`\u547D\u4EE4\uFF1A${report.command}`]
24177
- ].join("\n");
24414
+ return [...playbookFailure, ...report.prose ? [report.prose] : []].join("\n");
24178
24415
  }
24179
24416
  function createNavigatorAttendance(options) {
24180
24417
  let preparation;
24418
+ let preparationInFlight = false;
24181
24419
  let sessionReady;
24182
24420
  let session;
24183
24421
  let subjectKey = options.subjectKey;
24184
24422
  let subject = options.subject;
24185
24423
  let authority = options.authority;
24186
24424
  let contextError = options.contextError;
24187
- let candidates;
24425
+ let preparedProse;
24188
24426
  const invocationPrincipal = options.invocationId ?? mintNavigatorInvocationId();
24189
24427
  let activeInvocationId = invocationPrincipal;
24190
- let previousRoute;
24191
24428
  let outputSink;
24192
24429
  let settlementTail = Promise.resolve();
24193
24430
  let settlementFailure;
24194
24431
  let preparationFailure;
24195
- let preparationNoReceipt = false;
24196
24432
  let routePlaybookReadFailure;
24197
24433
  let disposed = false;
24198
24434
  let warmedHelp;
@@ -24219,12 +24455,7 @@ function createNavigatorAttendance(options) {
24219
24455
  };
24220
24456
  let routePlaybookSettlement;
24221
24457
  let prepareBoundSettlement;
24222
- const prepare = async () => {
24223
- const boundSettlement = prepareBoundSettlement;
24224
- prepareBoundSettlement = void 0;
24225
- preparationNoReceipt = false;
24226
- const invocationId = invocationPrincipal;
24227
- activeInvocationId = invocationId;
24458
+ const loadMaterialsAndSession = async (invocationId) => {
24228
24459
  if (contextError !== void 0) throw navigatorUnavailableError("context", contextError);
24229
24460
  if (typeof authority !== "string" || authority.trim() === "") {
24230
24461
  throw navigatorUnavailableError(
@@ -24282,21 +24513,6 @@ function createNavigatorAttendance(options) {
24282
24513
  const helpContext = help.map(({ role, help: text }) => `<role_help role="${role}">
24283
24514
  ${text}
24284
24515
  </role_help>`).join("\n");
24285
- let output;
24286
- let prepareBatchRejected = false;
24287
- outputSink = (value) => {
24288
- if (output === void 0) {
24289
- output = value;
24290
- return;
24291
- }
24292
- const prior2 = output.candidates;
24293
- const next = value.candidates;
24294
- const merged = [
24295
- ...Array.isArray(prior2) ? prior2 : prior2 === void 0 ? [] : [prior2],
24296
- ...Array.isArray(next) ? next : next === void 0 ? [] : [next]
24297
- ];
24298
- output = { ...value, candidates: merged };
24299
- };
24300
24516
  const tool = createNavigatorPrepareTool((value) => {
24301
24517
  outputSink?.(value);
24302
24518
  });
@@ -24304,7 +24520,12 @@ ${text}
24304
24520
  sessionReady = (async () => {
24305
24521
  let created;
24306
24522
  try {
24307
- created = await options.createSession({ context: options.context, subject: subjectKey, ...options.modelSettingPath === void 0 ? {} : { modelSettingPath: options.modelSettingPath }, tool });
24523
+ created = await options.createSession({
24524
+ context: options.context,
24525
+ subject: subjectKey,
24526
+ ...options.modelSettingPath === void 0 ? {} : { modelSettingPath: options.modelSettingPath },
24527
+ tool
24528
+ });
24308
24529
  } catch (error) {
24309
24530
  throw navigatorUnavailableError("session", error);
24310
24531
  }
@@ -24335,26 +24556,63 @@ ${text}
24335
24556
  session.appendEntry(INVOCATION_ENTRY, { invocationId, role: options.role, phase: options.phase, subjectKey });
24336
24557
  }
24337
24558
  if (disposed) throw navigatorUnavailableError("session", new Error("Navigator attendance was disposed"));
24338
- const activeSession = session;
24339
- if (activeSession === void 0) throw new Error("Navigator session was not created");
24340
- 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;
24341
- if (exactRecord2(prior) && Array.isArray(prior.route) && prior.route.every((target) => targetIsValid(target))) {
24342
- previousRoute = prior.route.map((target) => ({ role: target.role, phase: target.phase }));
24343
- }
24344
- const publicSettlementHistory = activeSession.entries().filter((entry) => exactRecord2(entry) && entry.type === "custom" && entry.customType === SETTLEMENT_ENTRY && exactRecord2(entry.data)).map((entry) => entry.data);
24559
+ if (session === void 0) throw new Error("Navigator session was not created");
24560
+ return { soul, routePlaybook, helpContext, modelSetting, model, help, activeSession: session };
24561
+ };
24562
+ const prepare = async (materialsBundle) => {
24563
+ const boundSettlement = prepareBoundSettlement;
24564
+ prepareBoundSettlement = void 0;
24565
+ const invocationId = invocationPrincipal;
24566
+ activeInvocationId = invocationId;
24567
+ let output;
24568
+ let prepareBatchRejected = false;
24569
+ outputSink = (value) => {
24570
+ if (output === void 0) {
24571
+ output = value;
24572
+ return;
24573
+ }
24574
+ const prior = normalizePrepareProse(output) ?? "";
24575
+ const next = normalizePrepareProse(value) ?? "";
24576
+ const merged = [prior, next].filter((part) => part.trim() !== "").join("\n\n");
24577
+ output = { prose: merged };
24578
+ };
24579
+ const { soul, routePlaybook, helpContext, help, activeSession } = materialsBundle ?? await loadMaterialsAndSession(invocationId);
24580
+ const publicSettlementHistory = activeSession.entries().filter((entry) => exactRecord3(entry) && entry.type === "custom" && entry.customType === SETTLEMENT_ENTRY && exactRecord3(entry.data)).map((entry) => entry.data);
24345
24581
  const projection = {
24346
24582
  subjectKey,
24347
24583
  subject,
24348
24584
  authority,
24349
24585
  currentRole: { role: options.role, phase: options.phase },
24350
24586
  ...boundSettlement === void 0 ? {} : { currentSettlement: boundSettlement },
24351
- priorRoute: exactRecord2(prior) && Array.isArray(prior.route) && prior.route.every((target) => targetIsValid(target)) ? prior.route.map((target) => ({ role: target.role, phase: target.phase })) : null,
24352
24587
  publicSettlementHistory,
24353
24588
  liveRoleHelp: help
24354
24589
  };
24355
24590
  activeSession.appendEntry(CONTEXT_ENTRY, projection);
24356
- const request = [
24357
- "\u672C\u6B21\u5BFC\u822A\u6750\u6599\u5982\u4E0B\uFF1A",
24591
+ const request = boundSettlement === void 0 ? [
24592
+ "\u672C\u8F6E\u4E3A\u5F85\u547D\u8F6E\u3002",
24593
+ `<navigator_soul>
24594
+ ${soul}
24595
+ </navigator_soul>`,
24596
+ ...routePlaybookReadFailure === void 0 ? [`<route_playbook>
24597
+ ${routePlaybook}
24598
+ </route_playbook>`] : ["\u53EF\u9009\u8DEF\u7EBF\u624B\u518C\u672A\u80FD\u8BFB\u53D6\u3002"],
24599
+ `<work_subject>
24600
+ ${subject}
24601
+ </work_subject>`,
24602
+ `<controlling_authority>
24603
+ ${authority}
24604
+ </controlling_authority>`,
24605
+ `<current_role>
24606
+ ${JSON.stringify({ role: options.role, phase: options.phase })}
24607
+ </current_role>`,
24608
+ `<public_settlement_history>
24609
+ ${JSON.stringify(projection.publicSettlementHistory)}
24610
+ </public_settlement_history>`,
24611
+ `<live_role_help>
24612
+ ${helpContext}
24613
+ </live_role_help>`
24614
+ ].join("\n\n") : [
24615
+ "\u672C\u8F6E\u4E3A\u7ED3\u7B97\u6295\u5582\u8F6E\u3002",
24358
24616
  `<navigator_soul>
24359
24617
  ${soul}
24360
24618
  </navigator_soul>`,
@@ -24370,12 +24628,9 @@ ${authority}
24370
24628
  `<current_role>
24371
24629
  ${JSON.stringify({ role: options.role, phase: options.phase })}
24372
24630
  </current_role>`,
24373
- ...boundSettlement === void 0 ? [] : [`<current_settlement>
24631
+ `<current_settlement>
24374
24632
  ${JSON.stringify(boundSettlement)}
24375
- </current_settlement>`],
24376
- `<prior_route>
24377
- ${JSON.stringify(prior ?? null)}
24378
- </prior_route>`,
24633
+ </current_settlement>`,
24379
24634
  `<public_settlement_history>
24380
24635
  ${JSON.stringify(projection.publicSettlementHistory)}
24381
24636
  </public_settlement_history>`,
@@ -24416,33 +24671,47 @@ ${helpContext}
24416
24671
  if (deliveryRequest && output === void 0) delivery.recordDeliveryRequest();
24417
24672
  };
24418
24673
  await promptAllowingRejectedPrepare(request, false);
24419
- while (output === void 0 && delivery.nextAction() === "request-delivery") {
24420
- await promptAllowingRejectedPrepare(RECEIPT_DELIVERY_PROMPT, true);
24421
- }
24422
- if (output === void 0 && delivery.nextAction() === "no-receipt" && activeSession.providerFailure?.() === void 0) {
24423
- const facts = delivery.facts({ runPointer: activeSession.recordPointer(), attemptPointer: invocationId });
24424
- activeSession.appendEntry(NO_RECEIPT_LIFECYCLE_ENTRY_TYPE, facts);
24425
- preparationNoReceipt = true;
24426
- candidates = [];
24427
- return candidates;
24674
+ if (boundSettlement !== void 0) {
24675
+ while (output === void 0 && prepareBatchRejected && delivery.nextAction() === "request-delivery") {
24676
+ await promptAllowingRejectedPrepare(RECEIPT_DELIVERY_PROMPT, true);
24677
+ }
24678
+ if (output === void 0 && delivery.nextAction() === "request-delivery") {
24679
+ while (delivery.nextAction() === "request-delivery") {
24680
+ delivery.recordDeliveryRequest();
24681
+ }
24682
+ }
24683
+ if (output === void 0 && delivery.nextAction() === "no-receipt" && activeSession.providerFailure?.() === void 0) {
24684
+ const facts = delivery.facts({ runPointer: activeSession.recordPointer(), attemptPointer: invocationId });
24685
+ activeSession.appendEntry(NO_RECEIPT_LIFECYCLE_ENTRY_TYPE, facts);
24686
+ preparedProse = void 0;
24687
+ return void 0;
24688
+ }
24428
24689
  }
24429
24690
  } catch (error) {
24430
24691
  throw error instanceof NavigatorUnavailableError ? error : navigatorUnavailableError("transport", error);
24431
24692
  }
24432
24693
  if (output === void 0) {
24694
+ if (boundSettlement === void 0) {
24695
+ preparedProse = void 0;
24696
+ return void 0;
24697
+ }
24433
24698
  const nativeFailure = [...activeSession.entries()].reverse().find((entry) => {
24434
- if (!exactRecord2(entry) || entry.type !== "message" || !exactRecord2(entry.message)) return false;
24699
+ if (!exactRecord3(entry) || entry.type !== "message" || !exactRecord3(entry.message)) return false;
24435
24700
  return entry.message.role === "assistant" && typeof entry.message.errorMessage === "string" && entry.message.errorMessage.trim() !== "";
24436
24701
  });
24437
- const nativeMessage = exactRecord2(nativeFailure) && exactRecord2(nativeFailure.message) ? nativeFailure.message : void 0;
24702
+ const nativeMessage = exactRecord3(nativeFailure) && exactRecord3(nativeFailure.message) ? nativeFailure.message : void 0;
24438
24703
  const errorMessage = nativeMessage !== void 0 && typeof nativeMessage.errorMessage === "string" ? nativeMessage.errorMessage : "Navigator did not submit direction advice";
24439
24704
  const providerFailure = activeSession.providerFailure?.();
24440
24705
  const source = providerFailure?.source ?? "unknown";
24441
24706
  const cause = providerFailure?.cause ?? source;
24442
24707
  throw navigatorUnavailableError(source, errorMessage, cause);
24443
24708
  }
24444
- candidates = normalizePrepareOutput(output);
24445
- return candidates;
24709
+ if (boundSettlement === void 0) {
24710
+ preparedProse = void 0;
24711
+ return void 0;
24712
+ }
24713
+ preparedProse = normalizePrepareProse(output);
24714
+ return preparedProse;
24446
24715
  } finally {
24447
24716
  outputSink = void 0;
24448
24717
  }
@@ -24453,7 +24722,6 @@ ${helpContext}
24453
24722
  if (next.subjectKey !== subjectKey && session !== void 0) {
24454
24723
  const previous = session;
24455
24724
  session = void 0;
24456
- previousRoute = void 0;
24457
24725
  closing = previous.dispose();
24458
24726
  }
24459
24727
  subjectKey = next.subjectKey;
@@ -24475,13 +24743,16 @@ ${helpContext}
24475
24743
  prepare() {
24476
24744
  if (disposed || preparation !== void 0) return;
24477
24745
  preparationFailure = void 0;
24478
- preparation = prepare();
24746
+ preparationInFlight = true;
24747
+ preparation = prepare().finally(() => {
24748
+ preparationInFlight = false;
24749
+ });
24479
24750
  void preparation.catch((error) => {
24480
24751
  preparationFailure = error;
24481
24752
  });
24482
24753
  },
24483
24754
  isPreparing() {
24484
- return preparation !== void 0 || sessionReady !== void 0;
24755
+ return preparationInFlight;
24485
24756
  },
24486
24757
  knownRoutePlaybookReadFailure() {
24487
24758
  return routePlaybookReadFailure;
@@ -24505,81 +24776,70 @@ ${helpContext}
24505
24776
  if (disposed) return;
24506
24777
  const invocationId = activeInvocationId ?? invocationPrincipal;
24507
24778
  let report;
24508
- if (settlement.kind === "human_decision" || settlement.kind === "role_infrastructure_failure") {
24509
- if (sessionReady !== void 0) {
24510
- try {
24511
- await sessionReady;
24512
- } catch (error) {
24513
- preparationFailure ??= error;
24514
- }
24779
+ if (sessionReady !== void 0) {
24780
+ try {
24781
+ await sessionReady;
24782
+ } catch (error) {
24783
+ preparationFailure ??= error;
24515
24784
  }
24516
- if (preparation !== void 0) {
24517
- try {
24518
- await preparation;
24519
- } catch (error) {
24520
- preparationFailure ??= error;
24521
- }
24785
+ }
24786
+ if (preparation !== void 0) {
24787
+ try {
24788
+ await preparation;
24789
+ } catch (error) {
24790
+ preparationFailure ??= error;
24522
24791
  }
24523
- session?.appendEntry(SETTLEMENT_ENTRY, { invocationId, subjectKey, role: settlement.role, phase: settlement.phase, kind: settlement.kind, ...settlement.kind === "human_decision" ? { status: settlement.status } : {} });
24792
+ preparation = void 0;
24793
+ }
24794
+ const settlementFact = {
24795
+ invocationId,
24796
+ subjectKey,
24797
+ role: settlement.role,
24798
+ phase: settlement.phase,
24799
+ kind: settlement.kind,
24800
+ ..."status" in settlement && settlement.status !== void 0 ? { status: settlement.status } : {}
24801
+ };
24802
+ let drainedProse;
24803
+ if (settlement.kind === "arrival") {
24804
+ session?.appendEntry(SETTLEMENT_ENTRY, settlementFact);
24524
24805
  if (preparationFailure !== void 0) {
24525
24806
  report = unavailable(invocationId, preparationFailure);
24526
24807
  } else {
24527
- report = { disposition: "no-advice" };
24808
+ report = {
24809
+ disposition: "arrival",
24810
+ ...settlement.message === void 0 ? {} : { arrivalMessage: settlement.message }
24811
+ };
24528
24812
  }
24529
- } else if (settlement.kind === "arrival") {
24530
- if (sessionReady !== void 0) {
24813
+ } else {
24814
+ if (session !== void 0) preparationFailure = void 0;
24815
+ let coldMaterials;
24816
+ if (session === void 0 && preparationFailure === void 0) {
24531
24817
  try {
24532
- await sessionReady;
24818
+ coldMaterials = await loadMaterialsAndSession(invocationId);
24533
24819
  } catch (error) {
24534
- preparationFailure ??= error;
24820
+ preparationFailure = error;
24535
24821
  }
24536
24822
  }
24537
- if (preparation !== void 0) {
24823
+ session?.appendEntry(SETTLEMENT_ENTRY, settlementFact);
24824
+ if (preparationFailure === void 0) {
24825
+ prepareBoundSettlement = settlement;
24826
+ preparation = prepare(coldMaterials);
24827
+ void preparation.catch((error) => {
24828
+ preparationFailure = error;
24829
+ });
24538
24830
  try {
24539
- await preparation;
24831
+ drainedProse = await preparation;
24540
24832
  } catch (error) {
24541
24833
  preparationFailure ??= error;
24542
24834
  }
24835
+ preparation = void 0;
24543
24836
  }
24544
- report = preparationFailure === void 0 ? { disposition: "arrival", ...settlement.message === void 0 ? {} : { arrivalMessage: settlement.message } } : unavailable(invocationId, preparationFailure);
24545
- } else if (preparation === void 0) {
24546
- report = unavailable(invocationId, "Navigator preparation did not start");
24547
- } else {
24548
- try {
24549
- if (sessionReady !== void 0) await sessionReady;
24550
- let prepared = await preparation;
24551
- session?.appendEntry(SETTLEMENT_ENTRY, { invocationId, subjectKey, role: settlement.role, phase: settlement.phase, kind: settlement.kind, ...settlement.status === void 0 ? {} : { status: settlement.status } });
24552
- let selected = selectNavigatorCandidate(prepared, settlement);
24553
- if (selected?.candidate.next !== void 0 && !selected.matchedToSettlement) {
24554
- if (disposed) return;
24555
- prepareBoundSettlement = settlement;
24556
- prepared = await prepare();
24557
- if (disposed) return;
24558
- selected = selectNavigatorCandidate(prepared, settlement);
24559
- }
24560
- const selectedCandidate = selected?.candidate;
24561
- if (selectedCandidate?.next === void 0 && preparationNoReceipt) {
24562
- report = { disposition: "no-advice" };
24563
- } else if (selectedCandidate?.next === void 0) {
24564
- throw new Error("Navigator prepared no machine-usable next direction");
24565
- } else {
24566
- const selectedRoute = selectedCandidate.route;
24567
- const routeChanged = selectedRoute !== void 0 && !routeEqual(previousRoute, selectedRoute);
24568
- const command = typeof selectedCandidate.command === "string" && selectedCandidate.command.trim() !== "" ? selectedCandidate.command : renderPublicAkRoleCommand(selectedCandidate.next);
24569
- report = {
24570
- disposition: "recommendation",
24571
- ...routeChanged ? { route: selectedRoute } : {},
24572
- next: selectedCandidate.next,
24573
- ...selectedCandidate.reason === void 0 ? {} : { reason: selectedCandidate.reason },
24574
- ...command === void 0 ? {} : { command }
24575
- };
24576
- if (selectedRoute !== void 0) {
24577
- previousRoute = selectedRoute;
24578
- session?.appendEntry(ROUTE_ENTRY, { invocationId, subjectKey, route: selectedRoute });
24579
- }
24580
- }
24581
- } catch (error) {
24582
- report = unavailable(invocationId, error);
24837
+ if (preparationFailure !== void 0) {
24838
+ report = unavailable(invocationId, preparationFailure);
24839
+ } else if (typeof drainedProse === "string" && drainedProse.trim() !== "") {
24840
+ report = { disposition: "advice", prose: drainedProse };
24841
+ } else {
24842
+ report = { disposition: "no-advice" };
24583
24843
  }
24584
24844
  }
24585
24845
  await routePlaybookSettlement;
@@ -24593,10 +24853,7 @@ ${helpContext}
24593
24853
  role: options.role,
24594
24854
  phase: options.phase,
24595
24855
  subjectKey,
24596
- ...report.route === void 0 ? {} : { route: report.route },
24597
- ...report.next === void 0 ? {} : { next: report.next },
24598
- ...report.reason === void 0 ? {} : { reason: report.reason },
24599
- ...report.command === void 0 ? {} : { command: report.command },
24856
+ ...report.prose === void 0 ? {} : { prose: report.prose },
24600
24857
  ...report.unavailableReason === void 0 ? {} : { unavailableReason: report.unavailableReason },
24601
24858
  ...report.unavailableSource === void 0 ? {} : { unavailableSource: report.unavailableSource },
24602
24859
  ...report.unavailableCause === void 0 ? {} : { unavailableCause: report.unavailableCause },
@@ -24612,9 +24869,8 @@ ${helpContext}
24612
24869
  }
24613
24870
  preparation = void 0;
24614
24871
  sessionReady = void 0;
24615
- candidates = void 0;
24872
+ preparedProse = void 0;
24616
24873
  preparationFailure = void 0;
24617
- preparationNoReceipt = false;
24618
24874
  routePlaybookSettlement = void 0;
24619
24875
  routePlaybookReadFailure = void 0;
24620
24876
  }
@@ -26101,6 +26357,21 @@ function createCountersignRoleRuntime(roleHost, dependencies, hostActions) {
26101
26357
  dependencies
26102
26358
  );
26103
26359
  }
26360
+ function lastAssistantProse(messages) {
26361
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
26362
+ const message = messages[index];
26363
+ if (message?.role !== "assistant" || !Array.isArray(message.content)) continue;
26364
+ const texts = [];
26365
+ for (const part of message.content) {
26366
+ if (part.type === "text" && typeof part.text === "string" && part.text.length > 0) {
26367
+ texts.push(part.text);
26368
+ }
26369
+ }
26370
+ if (texts.length === 0) continue;
26371
+ return texts.join("");
26372
+ }
26373
+ return void 0;
26374
+ }
26104
26375
  function createRoleRuntimeExtension(dependencies) {
26105
26376
  return (envelopeHost) => {
26106
26377
  let projectClosedSubmission = async () => {
@@ -26159,10 +26430,6 @@ function createRoleRuntimeExtension(dependencies) {
26159
26430
  if (settlement === void 0 || attendance === void 0) return;
26160
26431
  const workContext = navigatorWorkContext;
26161
26432
  const pending = (async () => {
26162
- if (settlement.kind !== "accepted") {
26163
- await attendance.settle(settlement);
26164
- return;
26165
- }
26166
26433
  const settlePromise = attendance.settle(settlement);
26167
26434
  void settlePromise.catch(() => void 0);
26168
26435
  const raced = await raceNavigatorGrace(settlePromise, NAVIGATOR_POST_ROLE_GRACE_MS);
@@ -26363,10 +26630,8 @@ function createRoleRuntimeExtension(dependencies) {
26363
26630
  pendingSubmissionNonPassByToolCallId.delete(event.toolCallId);
26364
26631
  return { details: submissionNonPass, isError: true };
26365
26632
  }
26366
- if (event.isError) return;
26367
- return;
26368
26633
  });
26369
- roleHost.on("agent_end", (event, ctx) => {
26634
+ roleHost.on("agent_end", async (event, ctx) => {
26370
26635
  const lastMessage = event.messages.at(-1);
26371
26636
  if (lastMessage?.role === "assistant" && (lastMessage.stopReason === "error" || lastMessage.stopReason === "aborted")) {
26372
26637
  if (receiptDelivery.nextAction() !== "accepted") {
@@ -26374,6 +26639,47 @@ function createRoleRuntimeExtension(dependencies) {
26374
26639
  }
26375
26640
  return;
26376
26641
  }
26642
+ const role = selectedRole ?? roleHost.getFlag(ROLE_FLAG.name);
26643
+ if (role === "navigator" && receiptDelivery.nextAction() !== "accepted") {
26644
+ const prose = lastAssistantProse(event.messages);
26645
+ if (prose !== void 0 && prose.trim() !== "") {
26646
+ const accepted = { prose };
26647
+ await sealAcceptedSubmission({
26648
+ context: ctx,
26649
+ role: "navigator",
26650
+ accepted,
26651
+ toolCallId: `navigator-prose-exit:${randomUUID8()}`
26652
+ });
26653
+ await projectClosedSubmission(
26654
+ { role: "navigator", kind: "accepted", accepted },
26655
+ ctx
26656
+ );
26657
+ return;
26658
+ }
26659
+ if (!noReceiptRecorded) {
26660
+ const runPointer = runDirectoryFromHostContext(ctx);
26661
+ if (runPointer !== void 0) {
26662
+ noReceiptRecorded = true;
26663
+ while (receiptDelivery.nextAction() === "request-delivery") {
26664
+ receiptDelivery.recordDeliveryRequest();
26665
+ }
26666
+ const facts = receiptDelivery.facts({ runPointer, attemptPointer: `current:${runPointer}` });
26667
+ envelopeHost.appendEntry(NO_RECEIPT_LIFECYCLE_ENTRY_TYPE, facts);
26668
+ try {
26669
+ sitianReport({
26670
+ level: "event",
26671
+ kind: "no-receipt-lifecycle",
26672
+ cwd: ctx.cwd,
26673
+ sessionParent: ctx.sessionManager.getSessionFile(),
26674
+ payload: facts,
26675
+ source: "role-runtime"
26676
+ });
26677
+ } catch {
26678
+ }
26679
+ }
26680
+ }
26681
+ return;
26682
+ }
26377
26683
  if (receiptDelivery.nextAction() === "request-delivery") {
26378
26684
  receiptDelivery.recordDeliveryRequest();
26379
26685
  envelopeHost.appendEntry("ak-receipt-delivery-request");
@@ -27008,7 +27314,7 @@ async function prepareRoleEnvelope(options) {
27008
27314
  let rejection;
27009
27315
  let infrastructureRoundFailure;
27010
27316
  const hostAbort = new AbortController();
27011
- const runId = request.runDirectory.split("/").filter(Boolean).at(-1) ?? randomUUID8();
27317
+ const runId = request.runDirectory.split("/").filter(Boolean).at(-1) ?? randomUUID9();
27012
27318
  await mkdir7(request.runDirectory, { recursive: true });
27013
27319
  let sessionFile = options.sessionFile ?? join41(request.runDirectory, "session", "session.jsonl");
27014
27320
  await mkdir7(dirname22(sessionFile), { recursive: true });
@@ -27030,6 +27336,25 @@ async function prepareRoleEnvelope(options) {
27030
27336
  if (error.code !== "EEXIST") throw error;
27031
27337
  }
27032
27338
  }
27339
+ let durableWriteChain = Promise.resolve();
27340
+ let armDurableWriteFailure;
27341
+ const persistPackageSessionEntry = (entry) => {
27342
+ const customType = typeof entry.customType === "string" ? entry.customType : "unknown";
27343
+ const line2 = `${JSON.stringify({
27344
+ ...entry,
27345
+ id: typeof entry.id === "string" ? entry.id : randomUUID9(),
27346
+ timestamp: typeof entry.timestamp === "string" ? entry.timestamp : (/* @__PURE__ */ new Date()).toISOString()
27347
+ })}
27348
+ `;
27349
+ durableWriteChain = durableWriteChain.then(async () => {
27350
+ try {
27351
+ await appendFile3(sessionFile, line2, "utf8");
27352
+ } catch (error) {
27353
+ const diagnostic = error instanceof Error ? error.message : String(error);
27354
+ armDurableWriteFailure?.(customType, diagnostic);
27355
+ }
27356
+ });
27357
+ };
27033
27358
  const context = {
27034
27359
  cwd: request.cwd,
27035
27360
  mode: "print",
@@ -27052,6 +27377,7 @@ async function prepareRoleEnvelope(options) {
27052
27377
  const entry = { type: "custom", customType, data };
27053
27378
  sessionEntries.push(entry);
27054
27379
  customEntries.push({ customType, data });
27380
+ persistPackageSessionEntry(entry);
27055
27381
  }
27056
27382
  },
27057
27383
  abort() {
@@ -27065,6 +27391,7 @@ async function prepareRoleEnvelope(options) {
27065
27391
  const entry = { type: "custom_message", customType, ...payload, message: payload };
27066
27392
  sessionEntries.push(entry);
27067
27393
  customEntries.push({ customType, data: message.details ?? message.content });
27394
+ persistPackageSessionEntry(entry);
27068
27395
  };
27069
27396
  const emit = async (event, value) => {
27070
27397
  const results = [];
@@ -27144,7 +27471,7 @@ async function prepareRoleEnvelope(options) {
27144
27471
  }
27145
27472
  };
27146
27473
  createRoleRuntimeExtension(options.dependencies)(envelope);
27147
- const token = randomUUID8();
27474
+ const token = randomUUID9();
27148
27475
  const server = createServer((socket) => serveSocket(socket));
27149
27476
  function rememberProjectedRejection(details, toolCallId, content) {
27150
27477
  if (typeof details !== "object" || details === null) return;
@@ -27180,6 +27507,17 @@ async function prepareRoleEnvelope(options) {
27180
27507
  };
27181
27508
  hostAbort.abort();
27182
27509
  }
27510
+ armDurableWriteFailure = (customType, diagnostic) => {
27511
+ rememberInfrastructureFailure(
27512
+ {
27513
+ cause: "infrastructure",
27514
+ kind: "role_infrastructure_failure",
27515
+ code: "durable-session-write-failed",
27516
+ customType
27517
+ },
27518
+ [{ type: "text", text: `ak-role: durable session entry flush failed (${customType}): ${diagnostic}` }]
27519
+ );
27520
+ };
27183
27521
  function declareRoundInfrastructureFailure(error) {
27184
27522
  const diagnostic = error instanceof Error ? error.message : String(error);
27185
27523
  const content = [{ type: "text", text: diagnostic }];
@@ -27225,7 +27563,7 @@ async function prepareRoleEnvelope(options) {
27225
27563
  async function invokeAkTool(name, args) {
27226
27564
  const tool = tools.get(name);
27227
27565
  if (tool === void 0) throw new Error(`Unknown AK tool: ${name}`);
27228
- const toolCallId = randomUUID8();
27566
+ const toolCallId = randomUUID9();
27229
27567
  calls.push({ toolCallId, toolName: name });
27230
27568
  sessionEntries.push({
27231
27569
  type: "message",
@@ -27341,6 +27679,15 @@ async function prepareRoleEnvelope(options) {
27341
27679
  const relay = fileURLToPath2(new URL("./mcp-relay.mjs", import.meta.url));
27342
27680
  await listen(server, options.socketPath);
27343
27681
  let disposed = false;
27682
+ let durableFailureHandedToCloseRound = false;
27683
+ const settleDurableWrites = async () => {
27684
+ await durableWriteChain;
27685
+ if (infrastructureRoundFailure !== void 0) {
27686
+ durableFailureHandedToCloseRound = true;
27687
+ return { accepted: false, failure: infrastructureRoundFailure };
27688
+ }
27689
+ return void 0;
27690
+ };
27344
27691
  const dispose = async () => {
27345
27692
  if (disposed) return;
27346
27693
  disposed = true;
@@ -27350,6 +27697,20 @@ async function prepareRoleEnvelope(options) {
27350
27697
  } catch (error) {
27351
27698
  cleanupFailures.push(error);
27352
27699
  }
27700
+ try {
27701
+ const alreadyHanded = durableFailureHandedToCloseRound;
27702
+ const durableFailure = await settleDurableWrites();
27703
+ if (durableFailure !== void 0 && !alreadyHanded) {
27704
+ cleanupFailures.push(
27705
+ Object.assign(
27706
+ new Error(durableFailure.failure.diagnostic ?? "durable session entry flush failed"),
27707
+ { code: durableFailure.failure.identity?.code ?? "durable-session-write-failed" }
27708
+ )
27709
+ );
27710
+ }
27711
+ } catch (error) {
27712
+ cleanupFailures.push(error);
27713
+ }
27353
27714
  try {
27354
27715
  const closeAll = server.closeAllConnections;
27355
27716
  if (typeof closeAll === "function") closeAll.call(server);
@@ -27371,6 +27732,7 @@ async function prepareRoleEnvelope(options) {
27371
27732
  if (calls.some((call) => call.toolName === terminatingToolName)) return;
27372
27733
  await invokeAkTool(terminatingToolName, params ?? {});
27373
27734
  }
27735
+ ;
27374
27736
  const closeRound = async () => {
27375
27737
  if (calls.length > 0) {
27376
27738
  const roundCalls = [...calls];
@@ -27378,6 +27740,7 @@ async function prepareRoleEnvelope(options) {
27378
27740
  await emit("turn_end", { turnIndex: 0, calls: roundCalls });
27379
27741
  }
27380
27742
  if (infrastructureRoundFailure !== void 0) {
27743
+ durableFailureHandedToCloseRound = true;
27381
27744
  return { accepted: false, failure: infrastructureRoundFailure };
27382
27745
  }
27383
27746
  let closure;
@@ -27389,6 +27752,8 @@ async function prepareRoleEnvelope(options) {
27389
27752
  }
27390
27753
  if (closure !== void 0) {
27391
27754
  await emit("agent_settled", {});
27755
+ const durableFailure2 = await settleDurableWrites();
27756
+ if (durableFailure2 !== void 0) return durableFailure2;
27392
27757
  return { accepted: true };
27393
27758
  }
27394
27759
  if (rejection !== void 0) {
@@ -27398,9 +27763,13 @@ async function prepareRoleEnvelope(options) {
27398
27763
  message: rejection.message
27399
27764
  };
27400
27765
  rejection = void 0;
27766
+ const durableFailure2 = await settleDurableWrites();
27767
+ if (durableFailure2 !== void 0) return durableFailure2;
27401
27768
  return { accepted: false, retry };
27402
27769
  }
27403
27770
  await emit("agent_settled", {});
27771
+ const durableFailure = await settleDurableWrites();
27772
+ if (durableFailure !== void 0) return durableFailure;
27404
27773
  return { accepted: true };
27405
27774
  };
27406
27775
  try {
@@ -27914,6 +28283,9 @@ function reportHostSessionEvent(input) {
27914
28283
  });
27915
28284
  }
27916
28285
 
28286
+ // src/acp-host/role-turn-host.ts
28287
+ init_navigator_output();
28288
+
27917
28289
  // src/agent-start-materials.ts
27918
28290
  function renderAgentStartMaterials(body, materials) {
27919
28291
  if (materials.length === 0) return body;
@@ -27926,7 +28298,42 @@ function renderSystemPromptOverride(authority) {
27926
28298
  }
27927
28299
 
27928
28300
  // src/acp-host/role-turn-host.ts
27929
- function failure(cause, name, code, details) {
28301
+ function acpAgentTextChunk(params) {
28302
+ let kind;
28303
+ let content;
28304
+ let textFallback;
28305
+ const nested = params.update;
28306
+ if (typeof nested === "object" && nested !== null && !Array.isArray(nested)) {
28307
+ const record4 = nested;
28308
+ kind = record4.sessionUpdate;
28309
+ content = record4.content;
28310
+ textFallback = record4.text;
28311
+ } else {
28312
+ kind = params.sessionUpdate ?? nested;
28313
+ content = params.content;
28314
+ textFallback = params.text;
28315
+ }
28316
+ if (kind !== "agent_message_chunk" && kind !== "agent_message") return void 0;
28317
+ if (typeof content === "string" && content.length > 0) return content;
28318
+ if (typeof content === "object" && content !== null && !Array.isArray(content)) {
28319
+ const record4 = content;
28320
+ if (typeof record4.text === "string" && record4.text.length > 0) return record4.text;
28321
+ }
28322
+ if (Array.isArray(content)) {
28323
+ const parts = [];
28324
+ for (const part of content) {
28325
+ if (typeof part === "string" && part.length > 0) parts.push(part);
28326
+ else if (typeof part === "object" && part !== null) {
28327
+ const record4 = part;
28328
+ if (typeof record4.text === "string" && record4.text.length > 0) parts.push(record4.text);
28329
+ }
28330
+ }
28331
+ if (parts.length > 0) return parts.join("");
28332
+ }
28333
+ if (typeof textFallback === "string" && textFallback.length > 0) return textFallback;
28334
+ return void 0;
28335
+ }
28336
+ function failure(cause, name, code, details, diagnostic) {
27930
28337
  return {
27931
28338
  code: null,
27932
28339
  stderr: "",
@@ -27934,10 +28341,24 @@ function failure(cause, name, code, details) {
27934
28341
  knownFailure: {
27935
28342
  cause,
27936
28343
  identity: { name, code },
28344
+ ...diagnostic === void 0 ? {} : { diagnostic },
27937
28345
  ...details === void 0 ? {} : { details }
27938
28346
  }
27939
28347
  };
27940
28348
  }
28349
+ function withCleanupFailure(outcome, cleanupError) {
28350
+ const message = cleanupError instanceof Error ? cleanupError.message : String(cleanupError);
28351
+ if (outcome.knownFailure === void 0) {
28352
+ return failure("session", "AcpDisposeFailure", "dispose-failed", { cleanupError: message }, message);
28353
+ }
28354
+ return {
28355
+ ...outcome,
28356
+ knownFailure: {
28357
+ ...outcome.knownFailure,
28358
+ details: { ...outcome.knownFailure.details ?? {}, cleanupError: message }
28359
+ }
28360
+ };
28361
+ }
27941
28362
  function acpError(code, message, cause) {
27942
28363
  return Object.assign(new Error(message, cause === void 0 ? void 0 : { cause }), { code });
27943
28364
  }
@@ -28049,137 +28470,168 @@ function createAcpRoleTurnHost(config) {
28049
28470
  let connection;
28050
28471
  let sessionId;
28051
28472
  let accepted = false;
28473
+ let outcome = failure("session", "AcpNoOutcome", "no-outcome");
28052
28474
  try {
28053
28475
  if (prepared.mcpServers.length === 0) {
28054
- return failure("activation", "UncontrolledAcpSession", "ak-config-missing");
28055
- }
28056
- connection = await config.connect(request);
28057
- const sessionParent = config.sessionIdentity.resolveSessionFile(request.principal);
28058
- const recordAbort = new AbortController();
28059
- let hostSessionRecordFailure;
28060
- const hostSessionRecordResult = () => ({
28061
- code: null,
28062
- stderr: "",
28063
- timedOut: false,
28064
- knownFailure: hostSessionRecordFailure
28065
- });
28066
- const noteHostSessionRecordFailure = (error) => {
28067
- if (hostSessionRecordFailure !== void 0) return;
28068
- hostSessionRecordFailure = {
28069
- cause: "session",
28070
- identity: { name: "HostSessionRecordFailure", code: "host-session-record-failed" },
28071
- diagnostic: error instanceof Error ? error.message : String(error)
28072
- };
28073
- try {
28074
- recordAbort.abort();
28075
- } catch {
28076
- }
28077
- };
28078
- const rpc = (method, params) => raceAgainstHostAbort(connection.request(method, params), recordAbort.signal, "host-session-record-failed");
28079
- connection.onNotification?.((method, params) => {
28080
- if (method !== "session/update" || hostSessionRecordFailure !== void 0) return;
28081
- try {
28082
- reportHostSessionEvent({
28083
- host: config.hostName,
28084
- cwd: request.cwd,
28085
- sessionParent,
28086
- source: "acp-host",
28087
- event: { method, params }
28088
- });
28089
- } catch (error) {
28090
- noteHostSessionRecordFailure(error);
28091
- }
28092
- });
28093
- try {
28094
- const initialized = await rpc("initialize", {
28095
- protocolVersion: 1,
28096
- clientCapabilities: {}
28476
+ outcome = failure("activation", "UncontrolledAcpSession", "ak-config-missing");
28477
+ } else {
28478
+ connection = await config.connect(request);
28479
+ const sessionParent = config.sessionIdentity.resolveSessionFile(request.principal);
28480
+ const recordAbort = new AbortController();
28481
+ let hostSessionRecordFailure;
28482
+ const hostSessionRecordResult = () => ({
28483
+ code: null,
28484
+ stderr: "",
28485
+ timedOut: false,
28486
+ knownFailure: hostSessionRecordFailure
28097
28487
  });
28098
- const initializeMeta = initialized._meta;
28099
- const availableModels = Array.isArray(initializeMeta?.modelState?.availableModels) ? initializeMeta.modelState.availableModels : void 0;
28100
- if (request.model !== void 0 && availableModels !== void 0 && !availableModels.some((entry) => typeof entry === "object" && entry !== null && entry.modelId === acpModelId(config.modelPassing, request.model))) {
28101
- return failure("activation", "AcpHostModelMismatch", "host-model-mismatch", {
28102
- provider: request.model.provider,
28103
- model: request.model.model
28104
- });
28105
- }
28106
- const sessionBindParams = {
28107
- cwd: request.cwd,
28108
- mcpServers: prepared.mcpServers,
28109
- _meta: { systemPromptOverride, yoloMode: false }
28110
- };
28111
- const loadSession = async (bindSessionId) => {
28112
- const loaded = await rpc("session/load", {
28113
- sessionId: bindSessionId,
28114
- ...sessionBindParams
28115
- });
28116
- return typeof loaded.sessionId === "string" && loaded.sessionId !== "" ? loaded.sessionId : bindSessionId;
28488
+ const noteHostSessionRecordFailure = (error) => {
28489
+ if (hostSessionRecordFailure !== void 0) return;
28490
+ hostSessionRecordFailure = {
28491
+ cause: "session",
28492
+ identity: { name: "HostSessionRecordFailure", code: "host-session-record-failed" },
28493
+ diagnostic: error instanceof Error ? error.message : String(error)
28494
+ };
28495
+ try {
28496
+ recordAbort.abort();
28497
+ } catch {
28498
+ }
28117
28499
  };
28118
- if (request.continuation.kind === "resume" && config.boundResume === "session/load") {
28119
- const boundSessionId = await config.sessionIdentity.load(request.principal);
28120
- if (boundSessionId !== void 0 && boundSessionId !== "") {
28121
- sessionId = await loadSession(boundSessionId);
28500
+ const rpc = (method, params) => raceAgainstHostAbort(connection.request(method, params), recordAbort.signal, "host-session-record-failed");
28501
+ const agentProseChunks = [];
28502
+ let collectAgentProse = false;
28503
+ connection.onNotification?.((method, params) => {
28504
+ if (method !== "session/update" || hostSessionRecordFailure !== void 0) return;
28505
+ if (collectAgentProse) {
28506
+ const chunk = acpAgentTextChunk(params);
28507
+ if (chunk !== void 0) agentProseChunks.push(chunk);
28122
28508
  }
28123
- }
28124
- if (sessionId === void 0) {
28125
- const session = await rpc("session/new", sessionBindParams);
28126
- sessionId = typeof session.sessionId === "string" ? session.sessionId : void 0;
28127
- if (sessionId === void 0 || sessionId === "") {
28128
- return failure("session", "AcpSessionFailure", "session-id-missing");
28509
+ try {
28510
+ reportHostSessionEvent({
28511
+ host: config.hostName,
28512
+ cwd: request.cwd,
28513
+ sessionParent,
28514
+ source: "acp-host",
28515
+ event: { method, params }
28516
+ });
28517
+ } catch (error) {
28518
+ noteHostSessionRecordFailure(error);
28129
28519
  }
28130
- await config.sessionIdentity.bind(request.principal, sessionId);
28131
- }
28132
- if (config.modelPassing === "set_model" && request.model !== void 0 && sessionId !== void 0) {
28133
- await rpc("session/set_model", {
28134
- sessionId,
28135
- modelId: acpModelId(config.modelPassing, request.model)
28520
+ });
28521
+ try {
28522
+ const initialized = await rpc("initialize", {
28523
+ protocolVersion: 1,
28524
+ clientCapabilities: {}
28136
28525
  });
28137
- sessionId = await loadSession(sessionId);
28138
- }
28139
- const activeConnection = connection;
28140
- const activeSessionId = sessionId;
28141
- const turnResult = await driveExternalRoleTurnRounds(prepared, request, {
28142
- roundLimitName: "AcpRoundLimit",
28143
- currentSessionId: () => sessionId,
28144
- async runRound({ prompt, abortSignal }) {
28145
- if (hostSessionRecordFailure !== void 0) return { status: "terminal", result: hostSessionRecordResult() };
28146
- const abortParts = [recordAbort.signal];
28147
- if (abortSignal !== void 0) abortParts.push(abortSignal);
28148
- const combinedAbort = AbortSignal.any(abortParts);
28149
- let result;
28150
- try {
28151
- result = await raceAgainstHostAbort(
28152
- activeConnection.request("session/prompt", {
28153
- sessionId: activeSessionId,
28154
- prompt: [{ type: "text", text: prompt }]
28155
- }),
28156
- combinedAbort,
28157
- "ACP host aborted"
28158
- );
28159
- } catch (error) {
28160
- if (hostSessionRecordFailure !== void 0) {
28161
- return { status: "terminal", result: hostSessionRecordResult() };
28526
+ const initializeMeta = initialized._meta;
28527
+ const availableModels = Array.isArray(initializeMeta?.modelState?.availableModels) ? initializeMeta.modelState.availableModels : void 0;
28528
+ if (request.model !== void 0 && availableModels !== void 0 && !availableModels.some((entry) => typeof entry === "object" && entry !== null && entry.modelId === acpModelId(config.modelPassing, request.model))) {
28529
+ outcome = failure("activation", "AcpHostModelMismatch", "host-model-mismatch", {
28530
+ provider: request.model.provider,
28531
+ model: request.model.model
28532
+ });
28533
+ } else {
28534
+ const sessionBindParams = {
28535
+ cwd: request.cwd,
28536
+ mcpServers: prepared.mcpServers,
28537
+ _meta: { systemPromptOverride, yoloMode: false }
28538
+ };
28539
+ const loadSession = async (bindSessionId) => {
28540
+ const loaded = await rpc("session/load", {
28541
+ sessionId: bindSessionId,
28542
+ ...sessionBindParams
28543
+ });
28544
+ return typeof loaded.sessionId === "string" && loaded.sessionId !== "" ? loaded.sessionId : bindSessionId;
28545
+ };
28546
+ if (request.continuation.kind === "resume" && config.boundResume === "session/load") {
28547
+ const boundSessionId = await config.sessionIdentity.load(request.principal);
28548
+ if (boundSessionId !== void 0 && boundSessionId !== "") {
28549
+ sessionId = await loadSession(boundSessionId);
28162
28550
  }
28163
- throw error;
28164
28551
  }
28165
- if (result.stopReason === "refusal") {
28166
- return {
28167
- status: "terminal",
28168
- result: failure("output", "AcpRefusal", "refusal", { sessionId })
28169
- };
28552
+ let sessionReady = true;
28553
+ if (sessionId === void 0) {
28554
+ const session = await rpc("session/new", sessionBindParams);
28555
+ sessionId = typeof session.sessionId === "string" ? session.sessionId : void 0;
28556
+ if (sessionId === void 0 || sessionId === "") {
28557
+ outcome = failure("session", "AcpSessionFailure", "session-id-missing");
28558
+ sessionReady = false;
28559
+ } else {
28560
+ await config.sessionIdentity.bind(request.principal, sessionId);
28561
+ }
28562
+ }
28563
+ if (sessionReady) {
28564
+ if (config.modelPassing === "set_model" && request.model !== void 0 && sessionId !== void 0) {
28565
+ await rpc("session/set_model", {
28566
+ sessionId,
28567
+ modelId: acpModelId(config.modelPassing, request.model)
28568
+ });
28569
+ sessionId = await loadSession(sessionId);
28570
+ }
28571
+ const activeConnection = connection;
28572
+ const activeSessionId = sessionId;
28573
+ const turnResult = await driveExternalRoleTurnRounds(prepared, request, {
28574
+ roundLimitName: "AcpRoundLimit",
28575
+ currentSessionId: () => sessionId,
28576
+ async runRound({ prompt, abortSignal }) {
28577
+ if (hostSessionRecordFailure !== void 0) return { status: "terminal", result: hostSessionRecordResult() };
28578
+ const abortParts = [recordAbort.signal];
28579
+ if (abortSignal !== void 0) abortParts.push(abortSignal);
28580
+ const combinedAbort = AbortSignal.any(abortParts);
28581
+ let result;
28582
+ agentProseChunks.length = 0;
28583
+ collectAgentProse = prepared.terminatingToolName === NAVIGATOR_OUTPUT_TOOL_NAME;
28584
+ try {
28585
+ result = await raceAgainstHostAbort(
28586
+ activeConnection.request("session/prompt", {
28587
+ sessionId: activeSessionId,
28588
+ prompt: [{ type: "text", text: prompt }]
28589
+ }),
28590
+ combinedAbort,
28591
+ "ACP host aborted"
28592
+ );
28593
+ } catch (error) {
28594
+ collectAgentProse = false;
28595
+ agentProseChunks.length = 0;
28596
+ if (hostSessionRecordFailure !== void 0) {
28597
+ return { status: "terminal", result: hostSessionRecordResult() };
28598
+ }
28599
+ throw error;
28600
+ }
28601
+ collectAgentProse = false;
28602
+ if (result.stopReason === "refusal") {
28603
+ agentProseChunks.length = 0;
28604
+ return {
28605
+ status: "terminal",
28606
+ result: failure("output", "AcpRefusal", "refusal", { sessionId })
28607
+ };
28608
+ }
28609
+ if (prepared.terminatingToolName === NAVIGATOR_OUTPUT_TOOL_NAME) {
28610
+ const prose = agentProseChunks.join("");
28611
+ agentProseChunks.length = 0;
28612
+ if (navigatorProseFromUnknown(prose) !== void 0) {
28613
+ await prepared.ingestStructuredOutput({ prose });
28614
+ }
28615
+ } else {
28616
+ agentProseChunks.length = 0;
28617
+ }
28618
+ return { status: "delivered", stderr: activeConnection.stderr?.() ?? "" };
28619
+ },
28620
+ async afterAccepted() {
28621
+ await rpc("session/close", { sessionId: activeSessionId });
28622
+ accepted = true;
28623
+ }
28624
+ });
28625
+ outcome = hostSessionRecordFailure !== void 0 ? hostSessionRecordResult() : turnResult;
28170
28626
  }
28171
- return { status: "delivered", stderr: activeConnection.stderr?.() ?? "" };
28172
- },
28173
- async afterAccepted() {
28174
- await rpc("session/close", { sessionId: activeSessionId });
28175
- accepted = true;
28176
28627
  }
28177
- });
28178
- if (hostSessionRecordFailure !== void 0) return hostSessionRecordResult();
28179
- return turnResult;
28180
- } catch (error) {
28181
- if (hostSessionRecordFailure !== void 0) return hostSessionRecordResult();
28182
- throw error;
28628
+ } catch (error) {
28629
+ if (hostSessionRecordFailure !== void 0) {
28630
+ outcome = hostSessionRecordResult();
28631
+ } else {
28632
+ throw error;
28633
+ }
28634
+ }
28183
28635
  }
28184
28636
  } finally {
28185
28637
  if (connection !== void 0) {
@@ -28196,9 +28648,11 @@ function createAcpRoleTurnHost(config) {
28196
28648
  }
28197
28649
  try {
28198
28650
  await prepared.dispose?.();
28199
- } catch {
28651
+ } catch (cleanupError) {
28652
+ outcome = withCleanupFailure(outcome, cleanupError);
28200
28653
  }
28201
28654
  }
28655
+ return outcome;
28202
28656
  });
28203
28657
  }
28204
28658
 
@@ -28269,7 +28723,7 @@ function createComposedAcpRoleTurnHost(config) {
28269
28723
  request,
28270
28724
  dependencies: config.roleRuntimeDependencies,
28271
28725
  sessionFile: config.sessionIdentity.resolveSessionFile(request.principal),
28272
- socketPath: config.socketPath?.(request) ?? `/tmp/ak-acp-mcp-${randomUUID9()}.sock`
28726
+ socketPath: config.socketPath?.(request) ?? `/tmp/ak-acp-mcp-${randomUUID10()}.sock`
28273
28727
  })
28274
28728
  });
28275
28729
  }