@akagilnc/pi-workflow-roles 0.1.2383 → 0.1.2397

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.
@@ -6,7 +6,6 @@
6
6
  * extra rows or shift column boundaries (note / fix.summary / decision question / reason).
7
7
  */
8
8
  import { renderPublicAkRoleCommand } from "./command-renderer.ts";
9
- import type { ComplianceAuditIncomplete } from "../compliance-transport.ts";
10
9
  import type { NavigatorPhase } from "../navigator-attendance.ts";
11
10
  import type { NoReceiptLifecycleFacts } from "../receipt-delivery-policy.ts";
12
11
 
@@ -41,9 +40,10 @@ export type TerminalRoleName =
41
40
  | "merger"
42
41
  | "notary";
43
42
 
43
+ /** Merger/Collector residual only — Notary/audit residual abolished (#475). */
44
44
  export type ResidualIncompleteTerminalOutcome = {
45
45
  kind: "incomplete";
46
- role: "merger" | "collector" | "notary";
46
+ role: "merger" | "collector";
47
47
  status: "incomplete";
48
48
  decision: "no-usable-result";
49
49
  candidate: unknown;
@@ -52,35 +52,6 @@ export type ResidualIncompleteTerminalOutcome = {
52
52
  decisiveFacts: Readonly<Record<string, unknown>>;
53
53
  };
54
54
 
55
- export type AuditIncompleteTerminalOutcome = {
56
- kind: "audit_incomplete";
57
- role: TerminalRoleName;
58
- status: "audit-incomplete";
59
- decision: "no-usable-decision";
60
- /** The original role submission arguments, retained independently. */
61
- roleCandidate: unknown;
62
- /** The malformed auditor candidate and observation retained by compliance transport. */
63
- audit: ComplianceAuditIncomplete;
64
- acceptedReceipt: false;
65
- decisiveFacts: Readonly<Record<string, unknown>>;
66
- };
67
-
68
- /** JSON-safe public stand-in for an omitted tool-call `arguments` member. */
69
- export const JSON_SAFE_UNDEFINED_ARGUMENT = Object.freeze({
70
- kind: "json-safe-sentinel",
71
- type: "undefined",
72
- } as const);
73
-
74
- export type AuditIncompleteResidual = {
75
- readonly roleCandidate: unknown;
76
- readonly audit: ComplianceAuditIncomplete;
77
- readonly acceptedReceipt: false;
78
- };
79
-
80
- export function jsonSafeComplianceCandidate(value: unknown): unknown {
81
- return value === undefined ? JSON_SAFE_UNDEFINED_ARGUMENT : value;
82
- }
83
-
84
55
  export type NoReceiptTerminalOutcome = NoReceiptLifecycleFacts & {
85
56
  kind: "no_receipt";
86
57
  role: TerminalRoleName;
@@ -102,7 +73,6 @@ export type TerminalRoleOutcome =
102
73
  status: "audit_escalation";
103
74
  decisiveFacts: Readonly<Record<string, unknown>>;
104
75
  }
105
- | AuditIncompleteTerminalOutcome
106
76
  | ResidualIncompleteTerminalOutcome
107
77
  | NoReceiptTerminalOutcome
108
78
  | {
@@ -113,8 +83,6 @@ export type TerminalRoleOutcome =
113
83
  /** Original diagnostic identity retained for the caller. */
114
84
  diagnostic: string;
115
85
  decisiveFacts: Readonly<Record<string, unknown>>;
116
- /** Retained audit residual when publication itself failed. */
117
- auditResidual?: AuditIncompleteResidual;
118
86
  };
119
87
 
120
88
  /** Lawful typed terminal results exit zero (including audit_escalation). */
@@ -131,7 +99,7 @@ export function exitCodeForTerminalOutcome(
131
99
  }
132
100
 
133
101
  export function buildResidualIncompleteTerminalOutcome(input: {
134
- role: "merger" | "collector" | "notary";
102
+ role: "merger" | "collector";
135
103
  candidate: unknown;
136
104
  diagnostic: string;
137
105
  }): ResidualIncompleteTerminalOutcome {
@@ -152,42 +120,6 @@ export function buildResidualIncompleteTerminalOutcome(input: {
152
120
  };
153
121
  }
154
122
 
155
- export function buildAuditIncompleteTerminalOutcome(input: {
156
- role: TerminalRoleName;
157
- roleCandidate: unknown;
158
- audit: ComplianceAuditIncomplete;
159
- }): AuditIncompleteTerminalOutcome {
160
- const roleCandidate = jsonSafeComplianceCandidate(input.roleCandidate);
161
- const audit = {
162
- ...input.audit,
163
- candidate: jsonSafeComplianceCandidate(input.audit.candidate),
164
- };
165
- return {
166
- kind: "audit_incomplete",
167
- role: input.role,
168
- status: "audit-incomplete",
169
- decision: "no-usable-decision",
170
- roleCandidate,
171
- audit,
172
- acceptedReceipt: false,
173
- decisiveFacts: {
174
- decision: "no-usable-decision",
175
- roleCandidate,
176
- auditCandidate: audit.candidate,
177
- auditObservation: audit.observation,
178
- observationKind: audit.observation.kind,
179
- observationType: audit.observation.kind === "non-object-arguments"
180
- ? audit.observation.type
181
- : audit.observation.kind === "object-status-unreadable"
182
- ? audit.observation.status
183
- : audit.observation.kind === "missing-subject"
184
- ? audit.observation.subject
185
- : audit.observation.kind,
186
- acceptedReceipt: false,
187
- },
188
- };
189
- }
190
-
191
123
  export type TerminalNavigatorFact =
192
124
  | {
193
125
  disposition: "recommendation";
@@ -10,8 +10,8 @@ import {
10
10
  } from "./compliance-transport.ts";
11
11
  import {
12
12
  readReviewerAuditSubjects,
13
+ requireAuditMaterials,
13
14
  resolveAuditDossier,
14
- toAuditIncomplete,
15
15
  } from "./dossier-resolution.ts";
16
16
 
17
17
  export const REVIEWER_AUDIT_TOOL_NAME = "ak_reviewer_audit_decision";
@@ -35,9 +35,9 @@ export function createPiReviewerAuditor(
35
35
  ): (options: ReviewerAuditOptions) => Promise<ComplianceDecision> {
36
36
  return async (options) => {
37
37
  const dossier = resolveAuditDossier();
38
- if (dossier.status === "incomplete") return toAuditIncomplete(dossier.observation);
38
+ requireAuditMaterials(dossier);
39
39
  const subjects = readReviewerAuditSubjects(options.context);
40
- if (subjects.status === "incomplete") return toAuditIncomplete(subjects.observation);
40
+ requireAuditMaterials(subjects);
41
41
 
42
42
  return runComplianceAudit({
43
43
  tool: reviewerDecisionTool,
@@ -210,7 +210,6 @@ export function createReviewerRoleRuntime(
210
210
  try { await dependencies.shutdownAgent?.(); } catch (error) { hostActions.failInfrastructure(ledger.recordInfrastructureFailure(error), toolCtx, id); }
211
211
  return result;
212
212
  },
213
- auditIncomplete: (result) => result,
214
213
  },
215
214
  candidate,
216
215
  );
@@ -50,6 +50,7 @@ import { decorateSettlementWithNavigation, formatNavigatorReport, NAVIGATOR_EVEN
50
50
  import {
51
51
  buildNavigatorInfrastructureFailureFact,
52
52
  classifyPackagedRoleTerminalResult,
53
+ NAVIGATOR_INFRASTRUCTURE_FAILURE_EVIDENCE_KEYS,
53
54
  NAVIGATOR_INVOCATION_ENTRY,
54
55
  resolveLifecycleInvocationPrincipal,
55
56
  } from "./navigator-invocation-identity.ts";
@@ -220,9 +221,11 @@ import { createMergerRoleRuntime, type MergerRoleDependencies } from "./merger-r
220
221
  export {
221
222
  buildNavigatorInfrastructureFailureFact,
222
223
  classifyPackagedRoleTerminalResult,
224
+ hasNavigatorInfrastructureFailureBase,
223
225
  isAcceptedPackagedRoleTerminalResult,
224
226
  isDurablePackagedRoleTerminalResult,
225
227
  isNavigatorInfrastructureFailureFact,
228
+ NAVIGATOR_INFRASTRUCTURE_FAILURE_EVIDENCE_KEYS,
226
229
  NAVIGATOR_INFRASTRUCTURE_FAILURE_KIND,
227
230
  type NavigatorInfrastructureFailureFact,
228
231
  type PackagedRoleTerminalClassification,
@@ -550,6 +553,35 @@ function failInfrastructure(error: unknown, ctx: ExtensionContext): never {
550
553
  throw error;
551
554
  }
552
555
 
556
+ /**
557
+ * Envelope-owned pending infrastructure failure: closed fact + original Error evidence.
558
+ * tool_result projects once from this record; settlement consumes durable details as-is.
559
+ */
560
+ type PendingInfrastructureFailure = {
561
+ readonly details: Record<string, unknown>;
562
+ };
563
+
564
+ function extractInfrastructureFailureEvidence(error: unknown): Record<string, unknown> {
565
+ if (typeof error !== "object" || error === null) return {};
566
+ const record = error as Record<string, unknown>;
567
+ const evidence: Record<string, unknown> = {};
568
+ for (const key of NAVIGATOR_INFRASTRUCTURE_FAILURE_EVIDENCE_KEYS) {
569
+ if (!Object.hasOwn(record, key)) continue;
570
+ // undefined → null so JSON durable details retain the empty-candidate key.
571
+ evidence[key] = record[key] === undefined ? null : record[key];
572
+ }
573
+ return evidence;
574
+ }
575
+
576
+ function buildPendingInfrastructureFailure(error: unknown): PendingInfrastructureFailure {
577
+ return {
578
+ details: {
579
+ ...buildNavigatorInfrastructureFailureFact(),
580
+ ...extractInfrastructureFailureEvidence(error),
581
+ },
582
+ };
583
+ }
584
+
553
585
  function navigatorPhase(pi: ExtensionAPI, role: string): NavigatorPhase {
554
586
  const metadata = packagedRoleMetadata(role);
555
587
  if (metadata === undefined || metadata.phases[0] === null) return null;
@@ -616,7 +648,8 @@ export function createRoleRuntimeExtension(
616
648
  let pendingNavigatorPresentation: { event: import("./navigator-attendance.ts").NavigatorEvent; report: import("./navigator-attendance.ts").NavigatorReport } | undefined;
617
649
  let pendingNavigatorSettlement: Promise<void> | undefined;
618
650
  let navigatorWorkContext: NavigatorWorkContext | undefined;
619
- const pendingInfrastructureToolCallIds = new Set<string>();
651
+ /** toolCallId → fact+evidence; one-shot projected onto durable tool_result (#475). */
652
+ const pendingInfrastructureFailures = new Map<string, PendingInfrastructureFailure>();
620
653
  // Envelope-owned execute→tool_result bridge for Gatekeeper non-pass (ADR 0018).
621
654
  const pendingGatekeeperNonPassByToolCallId = new Map<string, GatekeeperNonPassResult>();
622
655
  // #357 T2 / #378 / #380 / #391: engine detour once-latch + seat-fallback latch (any role+engine).
@@ -705,11 +738,11 @@ export function createRoleRuntimeExtension(
705
738
  pi.on("tool_result", async (event) => {
706
739
  const role = selectedRole;
707
740
  if (role === undefined) return;
708
- const isRoleInfrastructureFailure = pendingInfrastructureToolCallIds.delete(event.toolCallId);
709
- // Overlay typed infra fact so live settlement and durable session entry agree.
710
- const infrastructureDetails = isRoleInfrastructureFailure
711
- ? buildNavigatorInfrastructureFailureFact()
712
- : undefined;
741
+ const pendingInfra = pendingInfrastructureFailures.get(event.toolCallId);
742
+ const isRoleInfrastructureFailure = pendingInfra !== undefined;
743
+ if (pendingInfra !== undefined) pendingInfrastructureFailures.delete(event.toolCallId);
744
+ // One-shot project fact + typed evidence so live settlement and durable session agree.
745
+ const infrastructureDetails = pendingInfra?.details;
713
746
  const classified = infrastructureDetails === undefined
714
747
  ? event
715
748
  : { ...event, details: infrastructureDetails };
@@ -878,7 +911,7 @@ export function createRoleRuntimeExtension(
878
911
  navigatorAttendance?.dispose();
879
912
  navigatorAttendance = undefined;
880
913
  pendingNavigatorSettlement = undefined;
881
- pendingInfrastructureToolCallIds.clear();
914
+ pendingInfrastructureFailures.clear();
882
915
  pendingGatekeeperNonPassByToolCallId.clear();
883
916
  observationFace.reset();
884
917
  });
@@ -886,7 +919,7 @@ export function createRoleRuntimeExtension(
886
919
  const hostActions = {
887
920
  failInfrastructure(error: unknown, ctx: ExtensionContext, toolCallId?: string): never {
888
921
  if (toolCallId !== undefined) {
889
- pendingInfrastructureToolCallIds.add(toolCallId);
922
+ pendingInfrastructureFailures.set(toolCallId, buildPendingInfrastructureFailure(error));
890
923
  }
891
924
  failInfrastructure(error, ctx);
892
925
  },
@@ -1105,7 +1138,7 @@ export function createRoleRuntimeExtension(
1105
1138
  observationFace.reset();
1106
1139
  pendingNavigatorPresentation = undefined;
1107
1140
  pendingNavigatorSettlement = undefined;
1108
- pendingInfrastructureToolCallIds.clear();
1141
+ pendingInfrastructureFailures.clear();
1109
1142
  pendingGatekeeperNonPassByToolCallId.clear();
1110
1143
  engineLaborFallbackLatch = createEngineLaborFallbackLatch();
1111
1144
  // #380 resume: restore sole-built fallback from durable same-session detour results.