@akagilnc/pi-workflow-roles 0.1.5845 → 0.1.5853

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 (66) hide show
  1. package/README.md +4 -4
  2. package/README.zh-CN.md +4 -4
  3. package/dist/acp-host/production-host.js +348 -1254
  4. package/dist/acp-host/role-turn-host.js +4 -98
  5. package/dist/headless-host/production-host.js +15731 -16582
  6. package/dist/headless-host/role-turn-host.js +6 -31
  7. package/dist/migrate-book-topology.js +31 -16
  8. package/dist/navigator-attendance.js +54 -404
  9. package/dist/navigator-invocation-identity.js +0 -2
  10. package/dist/navigator-lookup-host.js +41 -0
  11. package/dist/navigator-lookup.js +68 -0
  12. package/dist/navigator-route-table.js +42 -0
  13. package/dist/package-contracts/navigator-output.js +3 -11
  14. package/dist/packaged-role-registry.js +3 -27
  15. package/dist/public-cli/instruction-seat-run.js +4 -1
  16. package/dist/public-cli/invocation.js +13 -26
  17. package/dist/public-cli/main.js +286 -114
  18. package/dist/public-cli/option-definitions.js +24 -4
  19. package/dist/public-cli/post-admission.js +0 -9
  20. package/dist/public-cli/role-seat-runtime.js +14 -0
  21. package/dist/public-cli/settlement.js +14 -40
  22. package/dist/public-cli/terminal.js +1 -8
  23. package/dist/public-cli/turn-request.js +0 -3
  24. package/dist/public-role-summons.js +0 -1
  25. package/dist/receipt-delivery-policy.js +0 -23
  26. package/dist/role-runtime-dependencies.js +4 -11
  27. package/dist/role-runtime.js +18 -194
  28. package/dist/submission-ledger.js +19 -15
  29. package/dist/ticket-progress.js +23 -5
  30. package/extensions/role-runtime.ts +0 -16
  31. package/package.json +1 -1
  32. package/scripts/build-package.mjs +3 -7
  33. package/src/acp-host/role-turn-host.ts +8 -97
  34. package/src/headless-host/description.ts +0 -2
  35. package/src/headless-host/role-turn-host.ts +7 -32
  36. package/src/host-contracts.ts +5 -7
  37. package/src/navigator-attendance.ts +86 -549
  38. package/src/navigator-invocation-identity.ts +0 -2
  39. package/src/navigator-lookup-host.ts +45 -0
  40. package/src/navigator-lookup.ts +98 -0
  41. package/src/navigator-route-table.ts +92 -0
  42. package/src/package-contracts/navigator-output.ts +4 -15
  43. package/src/packaged-role-registry.ts +3 -32
  44. package/src/public-cli/instruction-seat-run.ts +3 -0
  45. package/src/public-cli/invocation.ts +18 -30
  46. package/src/public-cli/option-definitions.ts +25 -4
  47. package/src/public-cli/post-admission.ts +0 -11
  48. package/src/public-cli/role-seat-runtime.ts +14 -0
  49. package/src/public-cli/settlement.ts +23 -51
  50. package/src/public-cli/terminal.ts +3 -18
  51. package/src/public-cli/turn-request.ts +0 -5
  52. package/src/public-role-summons.ts +0 -8
  53. package/src/receipt-delivery-policy.ts +0 -21
  54. package/src/role-runtime-dependencies.ts +4 -11
  55. package/src/role-runtime.ts +19 -210
  56. package/src/submission-ledger.ts +23 -16
  57. package/src/ticket-progress.ts +32 -5
  58. package/dist/navigator-public-session.js +0 -205
  59. package/dist/navigator-role.js +0 -6
  60. package/dist/navigator-session-contracts.js +0 -227
  61. package/dist/navigator-work-context.js +0 -72
  62. package/resources/navigator-route-playbook.md +0 -33
  63. package/src/navigator-public-session.ts +0 -305
  64. package/src/navigator-role.ts +0 -15
  65. package/src/navigator-session-contracts.ts +0 -320
  66. package/src/navigator-work-context.ts +0 -97
@@ -497,6 +497,24 @@ const DOCTOR_OPTIONS = [
497
497
  },
498
498
  },
499
499
  ];
500
+ /** 游奕使: structured target seat for the lookup; instruction prose is never parsed (#1192). */
501
+ const NAVIGATOR_OPTIONS = [
502
+ ...projectAndAttach("navigator"),
503
+ {
504
+ id: "role",
505
+ owner: "navigator",
506
+ canonical: "--role",
507
+ aliases: [],
508
+ valueMetavar: "role",
509
+ required: false,
510
+ repeatable: false,
511
+ form: "option",
512
+ description: {
513
+ en: "Optional seat whose status → advice rows to show; omitted shows the whole table. The instruction text is not read.",
514
+ zh: "可选衙门角色:只显示该衙门的 status → 建议;缺省显示整张表。instruction 正文不读。",
515
+ },
516
+ },
517
+ ];
500
518
  const NOTARY_OPTIONS = [
501
519
  bindOwner("notary", SHARED_PROJECT_SEMANTICS),
502
520
  {
@@ -696,6 +714,7 @@ const SEAT_OPTION_ROWS = {
696
714
  notary: NOTARY_OPTIONS,
697
715
  auditor: AUDITOR_OPTIONS,
698
716
  inspector: INSPECTOR_OPTIONS,
717
+ navigator: NAVIGATOR_OPTIONS,
699
718
  };
700
719
  function seatOptionRows(role) {
701
720
  return SEAT_OPTION_ROWS[role] ?? projectAndAttach(role);
@@ -892,7 +911,7 @@ export function allRejectedSpellingTokens() {
892
911
  * attendance is orthogonal to callability — the direct command face lives on
893
912
  * the role list like every other role).
894
913
  */
895
- export const PUBLIC_NAVIGATOR_HELP_NOTE = "Navigator also attends automatically on top-level public entry legs; that sidecar is unchanged by direct `ak-role navigator` calls.";
914
+ export const PUBLIC_NAVIGATOR_HELP_NOTE = "Navigator also attends automatically on top-level public entry legs; the sidecar and direct `ak-role navigator` calls read the same status → advice table, with no model call.";
896
915
  const TOP_LEVEL_HELP = {
897
916
  command: "top",
898
917
  summary: "public role CLI",
@@ -1006,10 +1025,11 @@ const ROLE_COMMAND_HELP = {
1006
1025
  },
1007
1026
  navigator: {
1008
1027
  command: "navigator",
1009
- summary: "Direct Navigator (游奕使) free-form prose route advice.",
1010
- usage: ["ak-role navigator [options] [instruction]"],
1028
+ summary: "Direct Navigator (游奕使) status → next-station advice table lookup; no model call.",
1029
+ usage: ["ak-role navigator [--role <role>] [options] [instruction]"],
1011
1030
  examples: [
1012
- 'ak-role navigator "刚完成 coder apply 收敛,下一步?"',
1031
+ "ak-role navigator",
1032
+ "ak-role navigator --role coder",
1013
1033
  ],
1014
1034
  },
1015
1035
  auditor: {
@@ -806,9 +806,6 @@ export async function dispatchPostAdmissionTurn(input) {
806
806
  if (env.stationChild !== undefined) {
807
807
  turnRequest = { ...turnRequest, stationChild: env.stationChild };
808
808
  }
809
- if (env.navigatorByStatusPrepare === true) {
810
- turnRequest = { ...turnRequest, navigatorByStatusPrepare: true };
811
- }
812
809
  // Selected host axis rides the shared Host envelope for in-turn tools
813
810
  // (detour usage ledger) — never a pre-spawn current.json reread.
814
811
  if (typeof env.host === "string" && env.host.trim() !== "") {
@@ -1113,9 +1110,6 @@ export function resumeTurnRequestProjectionOptions(admitted, request, env, summo
1113
1110
  prompt,
1114
1111
  },
1115
1112
  ...(env.stationChild === undefined ? {} : { stationChild: env.stationChild }),
1116
- ...(env.navigatorByStatusPrepare === true
1117
- ? { navigatorByStatusPrepare: true }
1118
- : {}),
1119
1113
  // #1132: one configured ceiling, already resolved by the caller (#422).
1120
1114
  deliveryRequestLimit: deliveryLimitFromConfig(env.autoResumeLimit),
1121
1115
  };
@@ -1131,9 +1125,6 @@ export function roleTurnOptions(env, admitted, continuation) {
1131
1125
  : { correlationId }),
1132
1126
  continuation,
1133
1127
  ...(env.stationChild === undefined ? {} : { stationChild: env.stationChild }),
1134
- ...(env.navigatorByStatusPrepare === true
1135
- ? { navigatorByStatusPrepare: true }
1136
- : {}),
1137
1128
  // #1132: one configured ceiling, already resolved by the caller (#422).
1138
1129
  deliveryRequestLimit: deliveryLimitFromConfig(env.autoResumeLimit),
1139
1130
  };
@@ -4,10 +4,24 @@
4
4
  * then host-facing provider projection. Callers own how a missing model is shown.
5
5
  */
6
6
  import { pickEngineAxis } from "../package-resources/engine-material.js";
7
+ import { createNavigatorLookupHost, NAVIGATOR_LOOKUP_HOST } from "../navigator-lookup-host.js";
8
+ import { isNavigatorSeat } from "../packaged-role-registry.js";
7
9
  import { resolvedSeatWithModel, } from "./config.js";
8
10
  import { loadHostProvidersTable, projectHostFacingProvider, } from "./host-providers.js";
9
11
  import { composeRoleTurnHostAdapters, selectRoleTurnHost, } from "./role-turn-host-resolution.js";
10
12
  export function openRoleSeatRuntime(input) {
13
+ // #1192: the navigator is a table lookup, not a model seat. Its seat axes
14
+ // (model / host / engine) are accepted and never consulted, so a mismatched
15
+ // or absent pair cannot stop it and no host session is started.
16
+ if (isNavigatorSeat(input.role)) {
17
+ input.afterHost?.();
18
+ return {
19
+ ok: true,
20
+ roleTurnHost: createNavigatorLookupHost(),
21
+ hostAdapters: [],
22
+ host: NAVIGATOR_LOOKUP_HOST,
23
+ };
24
+ }
11
25
  const hostAdapters = composeRoleTurnHostAdapters(input.resolution, input.principalAuthority);
12
26
  const roleTurnHost = selectRoleTurnHost(hostAdapters, {
13
27
  role: input.role,
@@ -18,8 +18,8 @@ import { describeErrorIdentity } from "./run-lifecycle.js";
18
18
  import { readEngineDetourToolUsage, readInvocationEngineMounted, runDirectoryFromSessionDirectory, sessionFileFromSessionDirectory, withEngineDetourToolUsageFact, } from "../engine-detour-usage.js";
19
19
  import { DOCTOR_CANDIDATE_ENTRY_TYPE } from "../dossier-resolution.js";
20
20
  import { homeFromRunDirectory, } from "./invocation.js";
21
- import { findLatestDurablePackagedRoleTerminal, NAVIGATOR_ROUTE_PLAYBOOK_FAILURE_ENTRY, } from "../navigator-invocation-identity.js";
22
- import { packagedRoleAcceptedOutputTool, packagedRoleMetadata, } from "../packaged-role-registry.js";
21
+ import { findLatestDurablePackagedRoleTerminal } from "../navigator-invocation-identity.js";
22
+ import { isNavigatorSeat, packagedRoleAcceptedOutputTool, packagedRoleMetadata, } from "../packaged-role-registry.js";
23
23
  import { NO_RECEIPT_LIFECYCLE_ENTRY_TYPE, noReceiptLifecycleFacts, parseNoReceiptLifecycleFacts, priorReceiptContinuation, receiptAttemptPointer, } from "../receipt-delivery-policy.js";
24
24
  import { readStateRowsSync, runCurrentPath } from "../run-dossier.js";
25
25
  import { reportRunRecord } from "../sitian-facade.js";
@@ -292,7 +292,9 @@ async function settleNoReceiptTerminal(admitted, authority, scope, facts) {
292
292
  }
293
293
  return attachEngineDetourToolUsage({
294
294
  roleOutcome,
295
- navigator: await extractNavigatorFactFromAdmittedSession(coordinates.sessionFile, admitted.runDirectory, scope),
295
+ navigator: isNavigatorSeat(admitted.role)
296
+ ? NAVIGATOR_SEAT_OWN_FACT
297
+ : await extractNavigatorFactFromAdmittedSession(coordinates.sessionFile, admitted.runDirectory, scope),
296
298
  artifacts: [],
297
299
  runId: admitted.runId,
298
300
  }, coordinates.sessionDirectory, detourUsageContext(admitted, scope));
@@ -660,9 +662,6 @@ export async function appendRunAttemptHistory(source, outcome) {
660
662
  }
661
663
  function parseNavigatorAttendanceDetails(details) {
662
664
  const disposition = details.disposition;
663
- const advisoryDiagnostic = typeof details.routePlaybookReadFailure === "string"
664
- ? { advisoryDiagnostic: details.routePlaybookReadFailure }
665
- : {};
666
665
  // #959: advice prose is presented as-is. Legacy "recommendation" with next/reason/
667
666
  // command is projected into prose so historical sessions still render — never wash
668
667
  // a real recommendation into no-advice when any advice body is recoverable.
@@ -697,20 +696,13 @@ function parseNavigatorAttendanceDetails(details) {
697
696
  }
698
697
  if (prose === undefined || prose.trim() === "") {
699
698
  // Attended but empty body is affirmative no-advice, not unavailable (#959).
700
- return {
701
- disposition: "no-advice",
702
- ...advisoryDiagnostic,
703
- };
699
+ return { disposition: "no-advice" };
704
700
  }
705
- return adviceNavigatorFact({
706
- prose,
707
- ...advisoryDiagnostic,
708
- });
701
+ return adviceNavigatorFact({ prose });
709
702
  }
710
703
  if (disposition === "unavailable") {
711
704
  return {
712
705
  disposition: "unavailable",
713
- ...advisoryDiagnostic,
714
706
  source: typeof details.unavailableSource === "string"
715
707
  ? details.unavailableSource
716
708
  : "unknown",
@@ -721,10 +713,7 @@ function parseNavigatorAttendanceDetails(details) {
721
713
  }
722
714
  // arrival and legacy silence both mean affirmative lawful no next-role advice.
723
715
  if (disposition === "no-advice" || disposition === "arrival" || disposition === "silence") {
724
- return {
725
- disposition: "no-advice",
726
- ...advisoryDiagnostic,
727
- };
716
+ return { disposition: "no-advice" };
728
717
  }
729
718
  return {
730
719
  disposition: "unavailable",
@@ -793,26 +782,7 @@ function detourUsageContext(admitted, scope) {
793
782
  ...(scope?.notePackageFault === undefined ? {} : { notePackageFault: scope.notePackageFault }),
794
783
  };
795
784
  }
796
- function routePlaybookFailureMessage(entries) {
797
- for (let i = entries.length - 1; i >= 0; i -= 1) {
798
- const entry = entries[i];
799
- if (entry?.type !== "custom" || entry.customType !== NAVIGATOR_ROUTE_PLAYBOOK_FAILURE_ENTRY)
800
- continue;
801
- const data = entry.data;
802
- if (!isRecord(data) || typeof data.message !== "string" || data.message.trim() === "")
803
- return undefined;
804
- return data.message;
805
- }
806
- return undefined;
807
- }
808
785
  export function extractNavigatorFact(entries) {
809
- const fact = extractNavigatorAttendanceFact(entries);
810
- if (fact.advisoryDiagnostic !== undefined)
811
- return fact;
812
- const message = routePlaybookFailureMessage(entries);
813
- return message === undefined ? fact : { ...fact, advisoryDiagnostic: message };
814
- }
815
- function extractNavigatorAttendanceFact(entries) {
816
786
  // Affirmative attendance only. Missing / unparseable is never no-advice.
817
787
  // The shared lifecycle places the settled event on this submission's closure;
818
788
  // an unrelated attendance message cannot supply another call's result.
@@ -845,6 +815,8 @@ function extractNavigatorAttendanceFact(entries) {
845
815
  * Never infers no-advice from omission; session read failures stay typed unavailable
846
816
  * so the controlled-failure Terminal itself still settles.
847
817
  */
818
+ /** The navigator run is the advice itself; it has no attendance of its own (#1192). */
819
+ const NAVIGATOR_SEAT_OWN_FACT = { disposition: "no-advice" };
848
820
  async function extractNavigatorFactFromAdmittedSession(sessionFile, runDirectory, scope) {
849
821
  try {
850
822
  const entries = await readBoundSessionEntries(sessionFile);
@@ -991,7 +963,7 @@ async function finishLawfulSeat(admitted, coordinates, entries, roleOutcome, sco
991
963
  : await publishDeclaredSeatTerminal(admitted, roleOutcome, coordinates, entries, scope);
992
964
  const terminal = await attachEngineDetourToolUsage({
993
965
  roleOutcome,
994
- navigator: extractNavigatorFact(entries),
966
+ navigator: isNavigatorSeat(admitted.role) ? NAVIGATOR_SEAT_OWN_FACT : extractNavigatorFact(entries),
995
967
  artifacts,
996
968
  runId: admitted.runId,
997
969
  ...(submissionToolCallId === undefined || submissionToolCallId.length === 0
@@ -1145,7 +1117,9 @@ export async function settleFailureTerminalResult(admitted, failure, authority,
1145
1117
  const coordinates = coordinatesFromAdmitted(authority, admitted);
1146
1118
  const { sessionDirectory, sessionFile } = coordinates;
1147
1119
  // Exact-session attendance only — never infer no-advice from caller omission.
1148
- const navigator = await extractNavigatorFactFromAdmittedSession(sessionFile, admitted.runDirectory, options);
1120
+ const navigator = isNavigatorSeat(admitted.role)
1121
+ ? NAVIGATOR_SEAT_OWN_FACT
1122
+ : await extractNavigatorFactFromAdmittedSession(sessionFile, admitted.runDirectory, options);
1149
1123
  let artifacts = [];
1150
1124
  if (options.previewOnly !== true) {
1151
1125
  try {
@@ -26,11 +26,7 @@ export function currentReplyRows(terminal) {
26
26
  * code does not parse route/next or judge usability.
27
27
  */
28
28
  export function adviceNavigatorFact(input) {
29
- return {
30
- disposition: "advice",
31
- prose: input.prose,
32
- ...(input.advisoryDiagnostic === undefined ? {} : { advisoryDiagnostic: input.advisoryDiagnostic }),
33
- };
29
+ return { disposition: "advice", prose: input.prose };
34
30
  }
35
31
  /**
36
32
  * Present one Terminal result for humans. Labels, row order, wording, and layout
@@ -72,9 +68,6 @@ export function formatTerminalResult(result) {
72
68
  }
73
69
  }
74
70
  lines.push(`navigator\t${result.navigator.disposition}`);
75
- if (result.navigator.advisoryDiagnostic !== undefined) {
76
- lines.push(`navigator-advisory\t${encodeTerminalField(result.navigator.advisoryDiagnostic)}`);
77
- }
78
71
  if (result.navigator.disposition === "advice") {
79
72
  // #959: present navigator prose as-is — no next/reason/command parsing.
80
73
  lines.push(`prose\t${encodeTerminalField(result.navigator.prose)}`);
@@ -45,9 +45,6 @@ export function projectRoleTurnRequest(admitted, roleDetails, options) {
45
45
  ? {}
46
46
  : { invocationScopeId: options.invocationScopeId }),
47
47
  ...(options.stationChild === undefined ? {} : { stationChild: options.stationChild }),
48
- ...(options.navigatorByStatusPrepare === undefined
49
- ? {}
50
- : { navigatorByStatusPrepare: options.navigatorByStatusPrepare }),
51
48
  ...(options.deliveryRequestLimit === undefined
52
49
  ? {}
53
50
  : { deliveryRequestLimit: options.deliveryRequestLimit }),
@@ -187,7 +187,6 @@ async function summonPublicRole(options) {
187
187
  // Nested court stations keep station-child semantics; dual-lens
188
188
  // ordinary Reviewer axes opt out (#946 / ADR 0082).
189
189
  ...options.stationChild === false ? {} : { stationChild: true },
190
- ...options.navigatorByStatusPrepare === true ? { navigatorByStatusPrepare: true } : {},
191
190
  // Forward composition-root adapters so nested stations (e.g.
192
191
  // secretariat → diarist) select the same faux/production table (#924).
193
192
  ...options.hostAdapters === void 0 ? {} : { hostAdapters: options.hostAdapters },
@@ -87,29 +87,6 @@ function createReceiptDeliveryPolicy(limit) {
87
87
  deliveryTurns += 1;
88
88
  spend();
89
89
  },
90
- /**
91
- * Stop asking. The issued count stays whatever was actually sent (#1132 —
92
- * do not fill the remainder up to the ceiling).
93
- */
94
- closeBudget() {
95
- closed = true;
96
- },
97
- /**
98
- * A nested session settled without an accepted receipt. Close so this layer
99
- * does not open another prompt on that session. The issued count stays the
100
- * larger of the two seams: a nested zero must not wipe prompts this layer
101
- * already sent, and adding the two counts would bill one send twice.
102
- */
103
- recordNestedNoReceipt(facts) {
104
- if (typeof facts.terminalToolCalled === "boolean") {
105
- terminalToolCalled = terminalToolCalled || facts.terminalToolCalled;
106
- }
107
- if (facts.rejectedReceipts !== void 0) {
108
- rejectedReceipts.push(...facts.rejectedReceipts);
109
- }
110
- if (facts.deliveryTurns !== void 0) deliveryTurns = Math.max(deliveryTurns, facts.deliveryTurns);
111
- closed = true;
112
- },
113
90
  nextAction() {
114
91
  if (accepted) return "accepted";
115
92
  if (closed) return "no-receipt";
@@ -1,8 +1,8 @@
1
1
  import { readFile } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
3
  import { loadDoctorCase } from "./doctor-evidence.js";
4
- import { createNativeNavigatorSessionFactory, createNavigatorAttendance } from "./navigator-attendance.js";
5
- import { loadNavigatorWorkContext } from "./navigator-work-context.js";
4
+ import { createNavigatorAttendance } from "./navigator-attendance.js";
5
+ import { createNavigatorLookup } from "./navigator-lookup.js";
6
6
  import { loadNotarySourceRunLocator } from "./notary-source-run.js";
7
7
  import {} from "./role-runtime.js";
8
8
  import { loadAuditorReferenceMaterialsFromSubjectInput, loadAuditorSoulFromSubjectInput, } from "./auditor-soul.js";
@@ -29,7 +29,7 @@ export function createRoleRuntimeDependencies(packageRoot) {
29
29
  // packageRoot is the install root (resources/ lives there). Never resolve via
30
30
  // import.meta.url — headless/acp production-host bundles live under dist/*/
31
31
  // and would otherwise look for dist/resources/ (#962).
32
- const navigatorSessionFactory = createNativeNavigatorSessionFactory();
32
+ const navigatorLookup = createNavigatorLookup();
33
33
  return {
34
34
  packageRoot,
35
35
  loadRoleReferenceMaterials: loadPackagedRoleReferenceMaterials,
@@ -37,20 +37,13 @@ export function createRoleRuntimeDependencies(packageRoot) {
37
37
  loadDoctorCase,
38
38
  loadNotarySourceRun: loadNotarySourceRunLocator,
39
39
  loadMergerInput: async (path) => JSON.parse(await readFile(path, "utf8")),
40
- loadNavigatorWorkContext: (options) => loadNavigatorWorkContext({
41
- context: options.context,
42
- role: options.role,
43
- ...(options.getFlag === undefined ? {} : { getFlag: options.getFlag }),
44
- }),
45
40
  createNavigatorAttendance: (options) => createNavigatorAttendance({
46
41
  context: options.context,
47
42
  role: options.role,
48
43
  phase: options.phase,
49
44
  subjectKey: options.subjectKey,
50
45
  invocationId: options.invocationId,
51
- createSession: navigatorSessionFactory,
52
- ...(options.deliveryRequestLimit === undefined ? {} : { deliveryRequestLimit: options.deliveryRequestLimit }),
53
- ...(options.contextError === undefined ? {} : { contextError: options.contextError }),
46
+ lookup: navigatorLookup,
54
47
  onEvent: options.onEvent,
55
48
  }),
56
49
  };