@akagilnc/pi-workflow-roles 0.1.2397 → 0.1.2402

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 (37) hide show
  1. package/README.md +1 -1
  2. package/README.zh-CN.md +1 -1
  3. package/dist/doctor-contracts.js +2 -9
  4. package/dist/engine-detour-tool.js +10 -35
  5. package/dist/evidence-child-executor.js +11 -3
  6. package/dist/merger-contracts.js +2 -8
  7. package/dist/navigator-attendance.js +1 -9
  8. package/dist/notary-contracts.js +3 -8
  9. package/dist/package-contracts/judge-output.js +1 -4
  10. package/dist/package-contracts/reviewer-output.js +1 -7
  11. package/dist/package-contracts/terminating-tools.js +5 -10
  12. package/dist/public-cli/main.js +24 -101
  13. package/package.json +1 -1
  14. package/scripts/build-package.mjs +1 -2
  15. package/src/analyst-metric-families/acceptance-success-rework.ts +3 -6
  16. package/src/collector-role.ts +1 -8
  17. package/src/doctor-contracts.ts +3 -18
  18. package/src/doctor-role.ts +1 -5
  19. package/src/engine-detour-tool.ts +16 -51
  20. package/src/evidence-child-executor.ts +11 -3
  21. package/src/factory-board.ts +2 -4
  22. package/src/judge-role.ts +1 -7
  23. package/src/merger-contracts.ts +3 -17
  24. package/src/merger-role.ts +1 -8
  25. package/src/navigator-attendance.ts +1 -14
  26. package/src/notary-contracts.ts +4 -24
  27. package/src/notary-role.ts +1 -3
  28. package/src/package-contracts/judge-output.ts +2 -17
  29. package/src/package-contracts/reviewer-output.ts +2 -21
  30. package/src/package-contracts/terminating-tools.ts +4 -13
  31. package/src/package-contracts/worker-output.ts +2 -10
  32. package/src/public-cli/settlement.ts +8 -20
  33. package/src/reviewer-role.ts +2 -10
  34. package/src/role-runtime.ts +1 -28
  35. package/src/worker-role.ts +2 -14
  36. package/dist/engine-labor-fallback.js +0 -136
  37. package/src/engine-labor-fallback.ts +0 -270
@@ -20,7 +20,6 @@ import { randomUUID } from "node:crypto";
20
20
  import { lstat, mkdir, realpath, rename, rm, writeFile } from "node:fs/promises";
21
21
  import { basename, dirname, join, relative, resolve, sep } from "node:path";
22
22
 
23
- import { seatFallbackBaseStatus } from "./engine-labor-fallback.ts";
24
23
  import {
25
24
  formatDurationZh,
26
25
  formatLocalDateTime,
@@ -177,8 +176,7 @@ export function decideTicketCurrentState(input: {
177
176
  const latest = sortRunsByStart(input.runs).at(-1)!;
178
177
  if (!latest.hasResult) return unacceptedBand(latest.mtimeMs, input.now.getTime());
179
178
  // Escalate is an awaiting overlay: same placement and sort band, distinct state.
180
- // Seat-fallback taint (`escalate-by-fallback`) keeps escalate base semantics.
181
- if (seatFallbackBaseStatus(latest.resultStatus) === "escalate") return "escalate-awaiting";
179
+ if ((latest.resultStatus) === "escalate") return "escalate-awaiting";
182
180
  return "accepted-awaiting";
183
181
  }
184
182
 
@@ -847,7 +845,7 @@ function buildBreadcrumbSteps(runs: readonly TicketTrajectoryRun[]): BreadcrumbS
847
845
  const isRejected = group.runs.some(
848
846
  (run) =>
849
847
  run.hasResult &&
850
- REJECTED_RESULT_STATUSES.has(seatFallbackBaseStatus(run.resultStatus)),
848
+ REJECTED_RESULT_STATUSES.has((run.resultStatus)),
851
849
  );
852
850
  steps.push({
853
851
  station: group.station,
package/src/judge-role.ts CHANGED
@@ -8,10 +8,6 @@ import { Type, type Static } from "typebox";
8
8
 
9
9
  import { disposeComplianceDecision } from "./audit-escalation.ts";
10
10
  import type { ComplianceDecision } from "./compliance-transport.ts";
11
- import {
12
- readActivationEngineLaborFallbackField,
13
- withEngineLaborFallbackField,
14
- } from "./engine-labor-fallback.ts";
15
11
  import { requireGatekeeperPass, type GatekeeperPassHostActions } from "./gatekeeper-role.ts";
16
12
 
17
13
  import {
@@ -137,9 +133,7 @@ export function createJudgeRoleRuntime(
137
133
  } catch (error) {
138
134
  hostActions.failInfrastructure(error, ctx, toolCallId);
139
135
  }
140
- // #380: attach sole-built engineLaborFallback when detour fell back to seat labor.
141
- const laborFallback = readActivationEngineLaborFallbackField();
142
- const acceptedDetails = withEngineLaborFallbackField(verdict, laborFallback);
136
+ const acceptedDetails = verdict;
143
137
  return disposeComplianceDecision<AgentToolResult<unknown>>(
144
138
  audit,
145
139
  {
@@ -1,11 +1,6 @@
1
1
  import { Type, type Static } from "typebox";
2
2
  import { isFullGitObjectId } from "./git-object-id.ts";
3
3
  import { exactUtf8 } from "./exact-utf8.ts";
4
- import {
5
- seatFallbackBaseStatus,
6
- seatFallbackStatusHasLawfulEvidence,
7
- type WithEngineLaborFallback,
8
- } from "./engine-labor-fallback.ts";
9
4
  import { sha256Hex } from "./sha256.ts";
10
5
  import { openToolObjectFromUnion } from "./open-tool-schema.ts";
11
6
 
@@ -29,13 +24,9 @@ export const mergerOutputSchema = openToolObjectFromUnion(mergerOutputVariants);
29
24
  export type DeepReadonly<T> = T extends (...args: never[]) => unknown ? T : T extends readonly (infer U)[] ? readonly DeepReadonly<U>[] : T extends object ? { readonly [K in keyof T]: DeepReadonly<T[K]> } : T;
30
25
  export type MergerMaterial = DeepReadonly<Static<typeof materialSchema>>;
31
26
  export type MergerInput = DeepReadonly<Static<typeof mergerInputSchema>>;
32
- type MergerOutputClean =
27
+ export type MergerOutput =
33
28
  | { status: "completed"; attemptId: string; report: string; mergeCommitId: string }
34
29
  | { status: "escalate"; attemptId: string; diagnosis: string; report: string };
35
- /** Clean submission shape or seat-fallback tainted accepted receipt (ADR 0071). */
36
- export type MergerOutput =
37
- | MergerOutputClean
38
- | WithEngineLaborFallback<MergerOutputClean>;
39
30
  export const MERGER_OUTPUT_TOOL_NAME = "ak_merger_output";
40
31
  export const MERGER_ACCEPTED_TEXT = "Merger output accepted";
41
32
 
@@ -75,12 +66,7 @@ export function validateMergerInput(value: unknown): MergerInput {
75
66
  export function validateMergerOutput(value: unknown, expectedAttemptId?: string): MergerOutput {
76
67
  if (!record(value) || (expectedAttemptId !== undefined && value.attemptId !== expectedAttemptId)) throw new Error("Merger output attempt mismatch");
77
68
  const status = typeof value.status === "string" ? value.status : undefined;
78
- const statusBase = status !== undefined ? seatFallbackBaseStatus(status) : undefined;
79
- // ADR 0071: tainted status requires latch-shaped engineLaborFallback evidence.
80
- if (status !== undefined && !seatFallbackStatusHasLawfulEvidence(status, value)) {
81
- throw new Error("Merger output has no recognized execution discriminator");
82
- }
83
- if (statusBase === "completed" && isFullGitObjectId(value.mergeCommitId)) return structuredClone(value) as MergerOutput;
84
- if (statusBase === "escalate") return structuredClone(value) as MergerOutput;
69
+ if (status === "completed" && isFullGitObjectId(value.mergeCommitId)) return structuredClone(value) as MergerOutput;
70
+ if (status === "escalate") return structuredClone(value) as MergerOutput;
85
71
  throw new Error("Merger output has no recognized execution discriminator");
86
72
  }
@@ -1,8 +1,4 @@
1
1
  import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
2
- import {
3
- readActivationEngineLaborFallbackField,
4
- withEngineLaborFallbackField,
5
- } from "./engine-labor-fallback.ts";
6
2
  import { MERGER_ACCEPTED_TEXT, MERGER_OUTPUT_TOOL_NAME, mergerOutputSchema, validateMergerInput, validateMergerOutput, type MergerInput } from "./merger-contracts.ts";
7
3
  import type { MergerGitState } from "./merger-git-state.ts";
8
4
  import { exactUtf8 } from "./exact-utf8.ts";
@@ -51,10 +47,7 @@ export function createMergerRoleRuntime(pi: ExtensionAPI, dependencies: MergerRo
51
47
  if (state.mergeCommitId !== output.mergeCommitId || !same(state.parentObjectIds, [activation.input.targetObjectId, activation.input.sourceObjectId]) || state.unmergedPaths.length !== 0 || !state.worktreeClean || state.resolutionChangedPaths.some(path => !scope.has(path))) host.failInfrastructure(new Error("Merger completed-state verification failed"), ctx, id);
52
48
  }
53
49
  accepted = true;
54
- const acceptedDetails = withEngineLaborFallbackField(
55
- output,
56
- readActivationEngineLaborFallbackField(),
57
- );
50
+ const acceptedDetails = output;
58
51
  return { content: [{ type: "text" as const, text: MERGER_ACCEPTED_TEXT }], details: acceptedDetails, terminate: true as const };
59
52
  } });
60
53
  pi.on("before_agent_start", event => { if (!activation) throw new Error("Merger is not activated"); const admitted = { attemptId: activation.input.attemptId, targetObjectId: activation.input.targetObjectId, sourceObjectId: activation.input.sourceObjectId, task: materialText(activation.input, "task"), authority: materialText(activation.input, "authority"), targetIntent: materialText(activation.input, "targetIntent"), sourceIntent: materialText(activation.input, "sourceIntent"), expectedConflictPaths: activation.input.expectedConflictPaths, resolutionScope: activation.input.resolutionScope, authorizedChecks: activation.input.authorizedChecks }; return { systemPrompt: `${event.systemPrompt}\n\n<merger_soul>\n${activation.soul}\n</merger_soul>\n\n<merger_assignment>\n${JSON.stringify(admitted)}\n</merger_assignment>` }; });
@@ -8,7 +8,6 @@ import { createAssistantMessageEventStream } from "@earendil-works/pi-ai";
8
8
  import { Type, type Static } from "typebox";
9
9
  import { Value } from "typebox/value";
10
10
 
11
- import { seatFallbackBaseStatus } from "./engine-labor-fallback.ts";
12
11
  import {
13
12
  NAVIGATOR_INVOCATION_ENTRY,
14
13
  mintNavigatorInvocationId,
@@ -462,18 +461,6 @@ export type NavigatorCandidateSelection = {
462
461
  readonly matchedToSettlement: boolean;
463
462
  };
464
463
 
465
- /** Match route-playbook statuses against settlement, treating seat-fallback taint as base-equivalent. */
466
- function statusListMatchesSettlement(
467
- candidateStatuses: readonly string[],
468
- settlementStatus: string,
469
- ): boolean {
470
- if (candidateStatuses.includes(settlementStatus)) return true;
471
- const settlementBase = seatFallbackBaseStatus(settlementStatus);
472
- return candidateStatuses.some(
473
- (status) => seatFallbackBaseStatus(status) === settlementBase,
474
- );
475
- }
476
-
477
464
  export function selectNavigatorCandidate(
478
465
  candidates: readonly NavigatorCandidate[],
479
466
  settlement: NavigatorSettlement,
@@ -492,7 +479,7 @@ export function selectNavigatorCandidate(
492
479
  const statusSpecific = rolePhaseMatched.find(
493
480
  (candidate) =>
494
481
  candidate.matches?.statuses !== undefined &&
495
- statusListMatchesSettlement(candidate.matches.statuses, settlement.status!),
482
+ candidate.matches.statuses.includes(settlement.status!),
496
483
  );
497
484
  if (statusSpecific !== undefined) {
498
485
  return { candidate: statusSpecific, matchedToSettlement: true };
@@ -5,13 +5,6 @@
5
5
  */
6
6
  import { Type } from "typebox";
7
7
 
8
- import {
9
- readActivationEngineLaborFallbackField,
10
- seatFallbackBaseStatus,
11
- seatFallbackStatusHasLawfulEvidence,
12
- withEngineLaborFallbackField,
13
- type WithEngineLaborFallback,
14
- } from "./engine-labor-fallback.ts";
15
8
  import { openToolObject } from "./open-tool-schema.ts";
16
9
 
17
10
  export const NOTARY_OUTPUT_TOOL_NAME = "ak_notary_output";
@@ -45,7 +38,7 @@ export type NotarySourceRunLocator = {
45
38
  readonly role: string;
46
39
  };
47
40
 
48
- type NotaryOutputClean =
41
+ export type NotaryOutput =
49
42
  | { readonly status: "pass"; readonly findings: readonly string[] }
50
43
  | {
51
44
  readonly status: "bounce";
@@ -53,11 +46,6 @@ type NotaryOutputClean =
53
46
  readonly findings: readonly string[];
54
47
  };
55
48
 
56
- /** Clean submission or seat-fallback tainted accepted receipt (ADR 0071). */
57
- export type NotaryOutput =
58
- | NotaryOutputClean
59
- | WithEngineLaborFallback<NotaryOutputClean>;
60
-
61
49
  function isRecord(value: unknown): value is Record<string, unknown> {
62
50
  return typeof value === "object" && value !== null && !Array.isArray(value);
63
51
  }
@@ -76,10 +64,10 @@ export function validateNotaryOutput(value: unknown): NotaryOutput {
76
64
  throw new Error("Notary output has no recognized execution discriminator");
77
65
  }
78
66
  const statusRaw = typeof value.status === "string" ? value.status : undefined;
79
- if (statusRaw === undefined || !seatFallbackStatusHasLawfulEvidence(statusRaw, value)) {
67
+ if (statusRaw === undefined) {
80
68
  throw new Error("Notary output has no recognized execution discriminator");
81
69
  }
82
- const status = seatFallbackBaseStatus(statusRaw);
70
+ const status = statusRaw;
83
71
  if (status === "bounce") {
84
72
  const clone = structuredClone(value) as Record<string, unknown>;
85
73
  if (clone.disposition === undefined) clone.disposition = "rewrite";
@@ -94,20 +82,12 @@ export function validateNotaryOutput(value: unknown): NotaryOutput {
94
82
  throw new Error("Notary output has no recognized execution discriminator");
95
83
  }
96
84
 
97
- /** Shape check for recorded accepted details (may include engineLaborFallback). */
98
85
  export function validateRecordedNotaryOutput(value: unknown): NotaryOutput {
99
86
  return validateNotaryOutput(value);
100
87
  }
101
88
 
102
- export function withNotaryAcceptedDetails(output: NotaryOutput): NotaryOutput {
103
- return withEngineLaborFallbackField(
104
- output,
105
- readActivationEngineLaborFallbackField(),
106
- ) as NotaryOutput;
107
- }
108
-
109
89
  export function notaryDecisiveFacts(output: NotaryOutput): Record<string, unknown> {
110
- const status = seatFallbackBaseStatus(String(output.status));
90
+ const status = String(output.status);
111
91
  const facts: Record<string, unknown> = { status, officer: "notary" };
112
92
  if (status === "pass" || status === "bounce") {
113
93
  const findings = (output as { findings?: unknown }).findings;
@@ -14,7 +14,6 @@ import {
14
14
  NOTARY_SOURCE_RUN_FLAG,
15
15
  notaryOutputSchema,
16
16
  validateNotaryOutput,
17
- withNotaryAcceptedDetails,
18
17
  type NotarySourceRunLocator,
19
18
  } from "./notary-contracts.ts";
20
19
 
@@ -114,10 +113,9 @@ export function createNotaryRoleRuntime(
114
113
  ? error
115
114
  : new Error(String(error));
116
115
  }
117
- const acceptedDetails = withNotaryAcceptedDetails(output);
118
116
  return {
119
117
  content: [{ type: "text" as const, text: NOTARY_ACCEPTED_TEXT }],
120
- details: acceptedDetails,
118
+ details: output,
121
119
  terminate: true as const,
122
120
  };
123
121
  },
@@ -1,11 +1,5 @@
1
1
  /** Package-owned Judge output leaf — no role registration surface. */
2
2
 
3
- import {
4
- seatFallbackBaseStatus,
5
- seatFallbackStatusHasLawfulEvidence,
6
- type SeatFallbackTaintedStatus,
7
- type WithEngineLaborFallback,
8
- } from "../engine-labor-fallback.ts";
9
3
 
10
4
  export const JUDGE_OUTPUT_TOOL_NAME = "ak_judge_output";
11
5
  export const JUDGE_ACCEPTED_TEXT = "Judge verdict accepted";
@@ -17,7 +11,7 @@ export type JudgeClass = {
17
11
  disposition: string;
18
12
  };
19
13
 
20
- type JudgeVerdictClean =
14
+ export type JudgeVerdict =
21
15
  | { judgeStatus: "converged"; note?: string; evidence?: unknown }
22
16
  | {
23
17
  judgeStatus: "continue";
@@ -33,11 +27,6 @@ type JudgeVerdictClean =
33
27
  evidence?: unknown;
34
28
  };
35
29
 
36
- /** Clean submission shape or seat-fallback tainted accepted receipt (ADR 0071). */
37
- export type JudgeVerdict =
38
- | JudgeVerdictClean
39
- | WithEngineLaborFallback<JudgeVerdictClean>;
40
-
41
30
  export function validateAcceptedJudgeDetails(verdict: unknown): JudgeVerdict {
42
31
  if (verdict === null || typeof verdict !== "object" || Array.isArray(verdict)) throw new Error("Judge verdict has no execution discriminator");
43
32
  let judgeStatus: unknown;
@@ -49,12 +38,8 @@ export function validateAcceptedJudgeDetails(verdict: unknown): JudgeVerdict {
49
38
  if (typeof judgeStatus !== "string") {
50
39
  throw new Error("Judge verdict has no execution discriminator");
51
40
  }
52
- const base = seatFallbackBaseStatus(judgeStatus) as SeatFallbackTaintedStatus<
53
- "converged" | "continue" | "escalate"
54
- >;
55
41
  if (
56
- ["converged", "continue", "escalate"].includes(base) &&
57
- seatFallbackStatusHasLawfulEvidence(judgeStatus, verdict)
42
+ ["converged", "continue", "escalate"].includes(judgeStatus)
58
43
  ) {
59
44
  return verdict as JudgeVerdict;
60
45
  }
@@ -1,11 +1,5 @@
1
1
  /** Package-owned Reviewer intent and runtime-receipt leaves — no role registration surface. */
2
2
 
3
- import {
4
- seatFallbackBaseStatus,
5
- seatFallbackStatusHasLawfulEvidence,
6
- type SeatFallbackTaintedStatus,
7
- type WithEngineLaborFallback,
8
- } from "../engine-labor-fallback.ts";
9
3
  import type { ReviewerAcceptedEvidence, ReviewerFailureClassification, ReviewerWorkspaceDisposition } from "../reviewer-execution-ledger.ts";
10
4
 
11
5
  export const REVIEWER_OUTPUT_TOOL_NAME = "ak_reviewer_output";
@@ -36,7 +30,7 @@ export type RuntimeReviewerAcceptedBatch = Readonly<{
36
30
  }>;
37
31
  /** Honest Spec-child disposition on the receipt face. */
38
32
  export type RuntimeReviewerSpecDisposition = "launched" | "skipped-missing";
39
- type RuntimeReviewerReceiptV2Clean = Readonly<{
33
+ export type RuntimeReviewerReceiptV2 = Readonly<{
40
34
  version: 2;
41
35
  status: "completed" | "refused";
42
36
  diagnostic?: string;
@@ -55,14 +49,6 @@ type RuntimeReviewerReceiptV2Clean = Readonly<{
55
49
  target?: ReviewerAcceptedEvidence["target"];
56
50
  }>;
57
51
  }>;
58
- /** Clean runtime receipt or seat-fallback tainted accepted receipt (ADR 0071). */
59
- export type RuntimeReviewerReceiptV2 =
60
- | RuntimeReviewerReceiptV2Clean
61
- | WithEngineLaborFallback<
62
- Omit<RuntimeReviewerReceiptV2Clean, "status"> & {
63
- status: SeatFallbackTaintedStatus<"completed" | "refused">;
64
- }
65
- >;
66
52
 
67
53
  function isRecord(value: unknown): value is Record<string, unknown> {
68
54
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -102,10 +88,6 @@ export function validateReviewerIntent(output: unknown): ReviewerIntent {
102
88
  /** Validate runtime-owned facts at their real identity seams (target pins + plain text). */
103
89
  export function validateRuntimeReviewerReceipt(output: unknown): RuntimeReviewerReceiptV2 {
104
90
  const status = read(output, "status");
105
- // ADR 0071: tainted top-level status requires latch-shaped engineLaborFallback evidence.
106
- if (typeof status === "string" && !seatFallbackStatusHasLawfulEvidence(status, output)) {
107
- throw new Error("Reviewer receipt has no recognized execution discriminator");
108
- }
109
91
  const acceptedBatch = read(output, "acceptedBatch");
110
92
  const identities = read(output, "identities");
111
93
  const construction = read(identities, "construction");
@@ -173,8 +155,7 @@ export function projectReviewerIntentToReceipt(intentValue: unknown, receiptValu
173
155
  const intent = validateReviewerIntent(intentValue);
174
156
  const receipt = validateRuntimeReviewerReceipt(receiptValue);
175
157
  const receiptStatus = String(receipt.status);
176
- const receiptBase = seatFallbackBaseStatus(receiptStatus);
177
- if (receiptBase !== intent.status || (intent.status === "completed" ? receipt.diagnostic !== undefined : receipt.diagnostic !== intent.diagnostic)) {
158
+ if (receiptStatus !== intent.status || (intent.status === "completed" ? receipt.diagnostic !== undefined : receipt.diagnostic !== intent.diagnostic)) {
178
159
  throw new Error("Reviewer intent and runtime receipt disagree");
179
160
  }
180
161
  return receipt;
@@ -25,10 +25,6 @@ import {
25
25
  type RuntimeReviewerReceiptV2,
26
26
  } from "./reviewer-output.ts";
27
27
  import { isAuditEscalationResult } from "../audit-escalation.ts";
28
- import {
29
- seatFallbackBaseStatus,
30
- seatFallbackStatusHasLawfulEvidence,
31
- } from "../engine-labor-fallback.ts";
32
28
  import { DOCTOR_OUTPUT_TOOL_NAME, validateDoctorSubmissionShape, validateRecordedDoctorOutput, type DoctorOutput, type DoctorSubmission } from "../doctor-contracts.ts";
33
29
  import { MERGER_ACCEPTED_TEXT, MERGER_OUTPUT_TOOL_NAME, validateMergerOutput, type MergerOutput } from "../merger-contracts.ts";
34
30
  import { NOTARY_ACCEPTED_TEXT, NOTARY_OUTPUT_TOOL_NAME, validateRecordedNotaryOutput, type NotaryOutput } from "../notary-contracts.ts";
@@ -171,16 +167,11 @@ export function validateAcceptedDetails(
171
167
  [NOTARY_OUTPUT_TOOL_NAME]: ["pass", "bounce"],
172
168
  };
173
169
  const collectorDiscriminator = toolName === COLLECTOR_OUTPUT_TOOL && Array.isArray(candidate?.groups);
174
- const baseDiscriminator = typeof discriminator === "string" ? seatFallbackBaseStatus(discriminator) : discriminator;
175
- // ADR 0071: `-by-fallback` is not independently lawful — require latch-shaped evidence.
176
- const taintedWithoutEvidence =
177
- typeof discriminator === "string" &&
178
- !seatFallbackStatusHasLawfulEvidence(discriminator, details);
170
+ const baseDiscriminator = discriminator;
179
171
  const runtimeBindingMissing =
180
172
  (toolName === DOCTOR_OUTPUT_TOOL_NAME && baseDiscriminator === "completed" && !(candidate?.cost !== null && typeof candidate?.cost === "object")) ||
181
173
  (toolName === REVIEWER_OUTPUT_TOOL_NAME && candidate?.version !== 2);
182
174
  if (
183
- taintedWithoutEvidence ||
184
175
  runtimeBindingMissing ||
185
176
  (!collectorDiscriminator && (typeof discriminator !== "string" || !lawfulStatuses[toolName].includes(baseDiscriminator as string)))
186
177
  ) {
@@ -219,12 +210,12 @@ export function validateAcceptedLifecycle(
219
210
  const details = validateAcceptedDetails(toolName, detailsValue);
220
211
  if (toolName === DOCTOR_OUTPUT_TOOL_NAME) {
221
212
  const testimony = validateDoctorSubmissionShape(argumentsValue);
222
- if (seatFallbackBaseStatus(String(testimony.status)) === "refused") {
213
+ if ((String(testimony.status)) === "refused") {
223
214
  if (!deepEqual(testimony, details)) throw new Error("accepted tool lifecycle details mismatch");
224
215
  return details;
225
216
  }
226
217
  const receipt = details as DoctorOutput & { cost?: unknown };
227
- if (seatFallbackBaseStatus(String(receipt.status)) !== "completed") {
218
+ if ((String(receipt.status)) !== "completed") {
228
219
  throw new Error("accepted tool lifecycle details mismatch");
229
220
  }
230
221
  const { cost: _runtimeCost, ...projected } = receipt;
@@ -253,7 +244,7 @@ export function acceptedFacts(toolName: TerminatingToolName, details: AcceptedDe
253
244
  case MERGER_OUTPUT_TOOL_NAME: {
254
245
  const output = details as unknown as Record<string, unknown>;
255
246
  const status = output.status as string;
256
- return { status, ...(seatFallbackBaseStatus(status) === "completed" && typeof output.mergeCommitId === "string" ? { commit: output.mergeCommitId } : {}) };
247
+ return { status, ...(status === "completed" && typeof output.mergeCommitId === "string" ? { commit: output.mergeCommitId } : {}) };
257
248
  }
258
249
  case COLLECTOR_OUTPUT_TOOL:
259
250
  return { status: "collected" };
@@ -15,24 +15,16 @@ export type {
15
15
  } from "./fixer-output.ts";
16
16
  export { fixerPrerequisiteSchema, fixerPrerequisitesSchema, parseFixerPrerequisites, validateFixerPrerequisites } from "./fixer-packet.ts";
17
17
  export type { FixerInvocationInput, FixerPrerequisite } from "./fixer-packet.ts";
18
- import type { WithEngineLaborFallback } from "../engine-labor-fallback.ts";
19
18
  import { validateFixerOutput, type FixerOutput } from "./fixer-output.ts";
20
19
 
21
20
  export const CODER_OUTPUT_TOOL_NAME = "ak_coder_output";
22
21
  export const CODER_ACCEPTED_TEXT = "Coder report accepted";
23
22
  export type WorkerRoleLabel = "Coder" | "Fixer";
24
- type CoderOutputClean =
23
+ export type CoderOutput =
25
24
  | { status: "planned"; report: string }
26
25
  | { status: "completed" | "refused"; report: string }
27
26
  | { status: "unfinished"; report: string; remainingScope: string; reason?: string };
28
- /** Clean submission shape or seat-fallback tainted accepted receipt (ADR 0071). */
29
- export type CoderOutput =
30
- | CoderOutputClean
31
- | WithEngineLaborFallback<CoderOutputClean>;
32
- export type WorkerOutput =
33
- | CoderOutput
34
- | FixerOutput
35
- | WithEngineLaborFallback<FixerOutput>;
27
+ export type WorkerOutput = CoderOutput | FixerOutput;
36
28
 
37
29
  export function validateAcceptedCoderDetails(output: unknown): CoderOutput {
38
30
  return output as CoderOutput;
@@ -39,11 +39,6 @@ import {
39
39
  COLLECTOR_WAIT_TOOL,
40
40
  } from "../collector-ledger.ts";
41
41
  import { ENGINE_DETOUR_TOOL_NAME } from "../engine-detour.ts";
42
- import {
43
- readEngineLaborFallbackFieldFrom,
44
- seatFallbackBaseStatus,
45
- seatFallbackStatusHasLawfulEvidence,
46
- } from "../engine-labor-fallback.ts";
47
42
  import {
48
43
  JUDGE_OUTPUT_TOOL_NAME,
49
44
  type JudgeVerdict,
@@ -1170,10 +1165,8 @@ function judgeDecisiveFacts(
1170
1165
  const facts: Record<string, unknown> = {
1171
1166
  judgeStatus,
1172
1167
  ...auditNoReceiptDecisiveFact(verdict),
1173
- // #380: spread sole-built field; do not re-key here (S1).
1174
- ...readEngineLaborFallbackFieldFrom(verdict),
1175
1168
  };
1176
- const statusBase = seatFallbackBaseStatus(judgeStatus);
1169
+ const statusBase = judgeStatus;
1177
1170
  if (statusBase === "continue") {
1178
1171
  const fix = safelyRead(verdict, "fix");
1179
1172
  if (fix.readable && isRecord(fix.value)) {
@@ -1227,7 +1220,7 @@ function coderDecisiveFacts(output: CoderOutput): Record<string, unknown> {
1227
1220
  if (status.readable && typeof status.value === "string") facts.coderStatus = status.value;
1228
1221
  const statusBase =
1229
1222
  status.readable && typeof status.value === "string"
1230
- ? seatFallbackBaseStatus(status.value)
1223
+ ? (status.value)
1231
1224
  : undefined;
1232
1225
  const remainingScope = safelyRead(candidate, "remainingScope");
1233
1226
  if (statusBase === "unfinished" && remainingScope.readable && typeof remainingScope.value === "string") facts.remainingScope = remainingScope.value;
@@ -1247,7 +1240,7 @@ function fixerDecisiveFacts(output: FixerOutput): Record<string, unknown> {
1247
1240
  if (status.readable && typeof status.value === "string") facts.fixerStatus = status.value;
1248
1241
  const statusBase =
1249
1242
  status.readable && typeof status.value === "string"
1250
- ? seatFallbackBaseStatus(status.value)
1243
+ ? (status.value)
1251
1244
  : undefined;
1252
1245
  const remainingScope = safelyRead(candidate, "remainingScope");
1253
1246
  if ((statusBase === "unfinished" || statusBase === "refused") && remainingScope.readable && typeof remainingScope.value === "string") facts.remainingScope = remainingScope.value;
@@ -1340,7 +1333,7 @@ function doctorDecisiveFacts(output: DoctorOutput): Record<string, unknown> {
1340
1333
  if (status.readable && typeof status.value === "string") facts.doctorStatus = status.value;
1341
1334
  const statusBase =
1342
1335
  status.readable && typeof status.value === "string"
1343
- ? seatFallbackBaseStatus(status.value)
1336
+ ? (status.value)
1344
1337
  : undefined;
1345
1338
  if (statusBase === "refused") {
1346
1339
  const reason = safelyRead(candidate, "reason");
@@ -1389,8 +1382,6 @@ function reviewerDecisiveFacts(
1389
1382
  amendmentAxes,
1390
1383
  acceptedBatchPresent: acceptedBatch.readable && acceptedBatch.value !== undefined,
1391
1384
  ...auditNoReceiptDecisiveFact(candidate),
1392
- // #380: spread sole-built field; do not re-key here (S1).
1393
- ...readEngineLaborFallbackFieldFrom(candidate),
1394
1385
  };
1395
1386
  if (status.readable && typeof status.value === "string") facts.reviewerStatus = status.value;
1396
1387
  if (
@@ -1402,7 +1393,7 @@ function reviewerDecisiveFacts(
1402
1393
  const diagnostic = safelyRead(candidate, "diagnostic");
1403
1394
  const statusBase =
1404
1395
  status.readable && typeof status.value === "string"
1405
- ? seatFallbackBaseStatus(status.value)
1396
+ ? (status.value)
1406
1397
  : undefined;
1407
1398
  if (statusBase === "refused" && diagnostic.readable) {
1408
1399
  facts.diagnosticPresent = typeof diagnostic.value === "string" && diagnostic.value.trim().length > 0;
@@ -1903,10 +1894,8 @@ export function extractJudgeRoleOutcome(
1903
1894
  const statusRead = safelyRead(details, "judgeStatus");
1904
1895
  if (!statusRead.readable || typeof statusRead.value !== "string") continue;
1905
1896
  const judgeStatus = statusRead.value;
1906
- const statusBase = seatFallbackBaseStatus(judgeStatus);
1897
+ const statusBase = judgeStatus;
1907
1898
  if (statusBase !== "converged" && statusBase !== "continue" && statusBase !== "escalate") continue;
1908
- // ADR 0071: `-by-fallback` without latch-shaped evidence is not a lawful terminal.
1909
- if (!seatFallbackStatusHasLawfulEvidence(judgeStatus, details)) continue;
1910
1899
  return {
1911
1900
  kind: "accepted",
1912
1901
  role: "judge",
@@ -3012,10 +3001,9 @@ async function settleLawfulDoctorTerminalResult(
3012
3001
  const extracted = extractDoctorRoleOutcome(entries);
3013
3002
  if (extracted === undefined) return undefined;
3014
3003
  // Bind completed receipt case identity to the admitted Issue evidence case.
3015
- // Seat-fallback may taint status; base semantics still require case binding.
3016
3004
  if (
3017
3005
  extracted.output !== undefined &&
3018
- seatFallbackBaseStatus(String(extracted.output.status)) === "completed"
3006
+ (String(extracted.output.status)) === "completed"
3019
3007
  ) {
3020
3008
  const completedCase = (
3021
3009
  extracted.output as {
@@ -3466,7 +3454,7 @@ function mergerDecisiveFacts(output: MergerOutput): Record<string, unknown> {
3466
3454
  if (attemptId.readable && attemptId.value !== undefined) facts.attemptId = attemptId.value;
3467
3455
  const statusBase =
3468
3456
  status.readable && typeof status.value === "string"
3469
- ? seatFallbackBaseStatus(status.value)
3457
+ ? (status.value)
3470
3458
  : undefined;
3471
3459
  const decisiveKey = statusBase === "completed" ? "mergeCommitId" : "diagnosis";
3472
3460
  const decisive = safelyRead(candidate, decisiveKey);
@@ -7,10 +7,6 @@ export type { CanonicalSkillBinding };
7
7
  import { disposeComplianceDecision } from "./audit-escalation.ts";
8
8
  import type { ComplianceDecision } from "./compliance-transport.ts";
9
9
  import { appendActiveSessionCustomEntry } from "./compliance-transport.ts";
10
- import {
11
- readActivationEngineLaborFallbackField,
12
- withEngineLaborFallbackField,
13
- } from "./engine-labor-fallback.ts";
14
10
  import { REVIEWER_CANDIDATE_ENTRY_TYPE } from "./dossier-resolution.ts";
15
11
  import { type ReviewerSpecDisposition } from "./reviewer-construction.ts";
16
12
  import { createReviewerDispatcher, type AcceptedReviewerDispatch, type AcceptedReviewerExecution, type ReviewerIssueFetcher, type ReviewerPinnedGitReader } from "./reviewer-dispatch.ts";
@@ -160,15 +156,11 @@ export function createReviewerRoleRuntime(
160
156
  const output = validateReviewerIntent(parameters);
161
157
  let record: ReviewerExecutionRecord;
162
158
  try { record = ledger.recordForAudit(output.status); } catch (error) { if ((error as any)?.fatalReviewerInfrastructure) hostActions.failInfrastructure(error, toolCtx, id); throw error; }
163
- const candidate = withEngineLaborFallbackField(
164
- assembleRuntimeReviewerReceipt({
159
+ const candidate = assembleRuntimeReviewerReceipt({
165
160
  intent: output,
166
161
  record,
167
162
  canonicalSkillText: binding.snapshot.raw,
168
- }),
169
- // #380: sole-built declaration when any leg detour fell back to seat labor.
170
- readActivationEngineLaborFallbackField(),
171
- );
163
+ });
172
164
  // First-record-then-audit: candidate lands on the parent session books
173
165
  // before the auditor is spawned (zero hand-delivery).
174
166
  try {
@@ -23,13 +23,6 @@ import {
23
23
  } from "./tool-execution-observation.ts";
24
24
  import { ENGINE_DETOUR_TOOL_NAME } from "./engine-detour.ts";
25
25
  import { registerEngineDetourTool } from "./engine-detour-tool.ts";
26
- import {
27
- createEngineLaborFallbackLatch,
28
- installActivationEngineLaborFallbackLatch,
29
- restoreEngineLaborFallbackFromSessionEntries,
30
- seatFallbackBaseStatus,
31
- seatFallbackStatusHasLawfulEvidence,
32
- } from "./engine-labor-fallback.ts";
33
26
  import { createReceiptDeliveryPolicy, NO_RECEIPT_LIFECYCLE_ENTRY_TYPE, RECEIPT_DELIVERY_PROMPT } from "./receipt-delivery-policy.ts";
34
27
  import { createOAuthKeepalive, type OAuthKeepaliveOptions } from "./oauth-keepalive.ts";
35
28
 
@@ -614,12 +607,7 @@ export function publicNavigatorSettlement(role: string, phase: NavigatorPhase, e
614
607
  const status = typeof details.status === "string"
615
608
  ? details.status
616
609
  : typeof details.judgeStatus === "string" ? details.judgeStatus : undefined;
617
- // ADR 0071: `-by-fallback` without latch-shaped evidence is not a lawful terminal.
618
- if (status !== undefined && !seatFallbackStatusHasLawfulEvidence(status, event.details)) {
619
- return undefined;
620
- }
621
- // Seat-fallback taint keeps escalate semantics (base) while preserving the polluted token.
622
- if (status !== undefined && seatFallbackBaseStatus(status) === "escalate") {
610
+ if (status !== undefined && status === "escalate") {
623
611
  return { kind: "human_decision", role, phase, status };
624
612
  }
625
613
  return { kind: "accepted", role, phase, ...(status === undefined ? {} : { status }) };
@@ -652,9 +640,7 @@ export function createRoleRuntimeExtension(
652
640
  const pendingInfrastructureFailures = new Map<string, PendingInfrastructureFailure>();
653
641
  // Envelope-owned execute→tool_result bridge for Gatekeeper non-pass (ADR 0018).
654
642
  const pendingGatekeeperNonPassByToolCallId = new Map<string, GatekeeperNonPassResult>();
655
- // #357 T2 / #378 / #380 / #391: engine detour once-latch + seat-fallback latch (any role+engine).
656
643
  let engineDetourRegistration: ReturnType<typeof registerEngineDetourTool> | undefined;
657
- let engineLaborFallbackLatch = createEngineLaborFallbackLatch();
658
644
  // #288 primary-session thin adapter. The policy is the sole budget owner;
659
645
  // terminating-tool rejections and mechanical delivery requests share two turns.
660
646
  let receiptDelivery = createReceiptDeliveryPolicy();
@@ -1140,18 +1126,6 @@ export function createRoleRuntimeExtension(
1140
1126
  pendingNavigatorSettlement = undefined;
1141
1127
  pendingInfrastructureFailures.clear();
1142
1128
  pendingGatekeeperNonPassByToolCallId.clear();
1143
- engineLaborFallbackLatch = createEngineLaborFallbackLatch();
1144
- // #380 resume: restore sole-built fallback from durable same-session detour results.
1145
- const sessionEntries =
1146
- typeof ctx.sessionManager?.getEntries === "function"
1147
- ? ctx.sessionManager.getEntries()
1148
- : [];
1149
- restoreEngineLaborFallbackFromSessionEntries(
1150
- engineLaborFallbackLatch,
1151
- sessionEntries,
1152
- ENGINE_DETOUR_TOOL_NAME,
1153
- );
1154
- installActivationEngineLaborFallbackLatch(engineLaborFallbackLatch);
1155
1129
  engineDetourRegistration?.resetLatch();
1156
1130
  navigatorWorkContext = undefined;
1157
1131
  // #351: OAuth keepalive is orthogonal to --ak-role; start before role early-return
@@ -1267,7 +1241,6 @@ export function createRoleRuntimeExtension(
1267
1241
  await executeActivationStage(entry.role, activationStage(entry.role, runtime), { clock, writeTrace });
1268
1242
  // #357 T2 / #378 / #380 / #391: any role+engine activation registers the package detour tool once.
1269
1243
  // Gate is env presence only — no per-engine execute branch; no role-module spawn.
1270
- // Seat-fallback latch is activation-scoped (installed at session_start) so legs share it.
1271
1244
  if (engineDetourRegistration === undefined) {
1272
1245
  engineDetourRegistration = registerEngineDetourTool(pi, hostActions);
1273
1246
  if (!engineDetourRegistration.registered) {