@akagilnc/pi-workflow-roles 0.1.3671 → 0.1.3682

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.
@@ -1,16 +1,16 @@
1
1
  /**
2
2
  * Public 起居郎 (diarist) terminating receipt contracts — ADR 0075 `diarist-is-role`.
3
- * Lawful explicit release: completed, with empty or nonempty selections.
3
+ * Lawful explicit releases: completed (入录选择) | escalate (认不出本庭对象上抛).
4
4
  * Machine facts about the volume come from the mechanical sitian seam, never
5
5
  * from model self-report (锚定宪法); this module owns the receipt shape only.
6
6
  */
7
7
  export const DIARIST_OUTPUT_TOOL_NAME = "ak_diarist_output";
8
8
  export const DIARIST_ACCEPTED_TEXT = "起居郎回执已接受";
9
- /** Internal transport: frozen candidate-catalog path for this turn's ticket. */
9
+ /** Internal transport: frozen candidate-catalog path for this turn. */
10
10
  export const DIARIST_SOURCES_FLAG = {
11
11
  name: "ak-diarist-sources",
12
12
  definition: {
13
- description: "Frozen per-ticket source catalog the diarist selects from",
13
+ description: "Frozen source catalog the diarist selects from (may be unbound until LLM asserts ticketNumber)",
14
14
  type: "string",
15
15
  },
16
16
  };
@@ -25,7 +25,7 @@ export function validateRecordedDiaristOutput(value) {
25
25
  catch {
26
26
  throw new Error("Diarist output has no execution discriminator");
27
27
  }
28
- if (status === "completed") {
28
+ if (status === "completed" || status === "escalate") {
29
29
  return value;
30
30
  }
31
31
  throw new Error("Diarist output has no execution discriminator");
@@ -7,15 +7,21 @@ export { validateRecordedDiaristOutput };
7
7
  /** 起居郎交卷形状;形状指引,非 schema 闸。 */
8
8
  export const diaristOutputSchema = withInfrastructureFailureDeclaration(openToolObject(Type.Object({
9
9
  status: Type.Unknown({
10
- description: "completed — 形状指引,非 schema 闸",
10
+ description: "completed | escalate — 形状指引,非 schema 闸",
11
11
  }),
12
+ ticketNumber: Type.Optional(Type.Unknown({
13
+ description: "本庭对象票号(正整数)或 null/省略=真无票;机械验真后下游走 typed 键;认不出用 status=escalate,不洗成无录",
14
+ })),
15
+ reason: Type.Optional(Type.String({
16
+ description: "status 为 escalate 时:认不出本庭对象的原因",
17
+ })),
12
18
  selections: Type.Array(Type.Object({
13
19
  candidateIndex: Type.Number({ description: "候选目录中的整块序号" }),
14
20
  quotes: Type.Array(Type.String(), {
15
21
  description: "该块 transcript 内的连续原文;机械反验",
16
22
  }),
17
23
  note: Type.Optional(Type.String({ description: "该材料与本案的关系(人读)" })),
18
- }, { additionalProperties: true, description: "一条入录选择" }), { description: "入录选择;空列表合法完局" }),
24
+ }, { additionalProperties: true, description: "一条入录选择" }), { description: "入录选择;空列表合法完局;escalate 时可不交" }),
19
25
  })));
20
26
  /**
21
27
  * 决定工具规格。生命周期装配归注册信封 owner——src/role-runtime.ts(ADR 0018)。
@@ -23,7 +29,7 @@ export const diaristOutputSchema = withInfrastructureFailureDeclaration(openTool
23
29
  export const DIARIST_TOOL_SPEC = {
24
30
  name: DIARIST_OUTPUT_TOOL_NAME,
25
31
  label: "起居郎输出",
26
- description: "起居郎入录选择。",
27
- promptSnippet: "起居郎入录选择",
32
+ description: "起居郎入录选择与本票身份断言;认不出本庭对象则 escalate。",
33
+ promptSnippet: "起居郎入录选择与本票身份",
28
34
  parameters: diaristOutputSchema,
29
35
  };
package/dist/diarist.js CHANGED
@@ -13,6 +13,81 @@ import { parseGitHubOriginRemote } from "./reviewer-pinned-git.js";
13
13
  import { appendIssueSourceFailureDiagnostic, appendQuoteVerifyFailureDiagnostic, appendTicketProvenanceEntry, ensureTicketProvenanceVolume, readOfferedIdentities, readTicketProvenance, recordOfferedIdentities, resolveTicketProvenanceVolume, ticketProvenanceEntryIdentity, writeTicketProvenanceHumanView, } from "./ticket-provenance.js";
14
14
  import { readSitianRecords } from "./sitian-facade.js";
15
15
  import { execFileSync } from "node:child_process";
16
+ /**
17
+ * Honest failure of mechanical ticket verification (ADR 0075).
18
+ * Must settle as failure — never wash into true-unbound / 无录.
19
+ */
20
+ export class DiaristTicketVerificationError extends Error {
21
+ code = "diarist-ticket-verification";
22
+ reason;
23
+ constructor(reason, message, options) {
24
+ super(message, options);
25
+ this.name = "DiaristTicketVerificationError";
26
+ this.reason = reason;
27
+ }
28
+ }
29
+ /**
30
+ * Decision-key exact identity: complete decimal number N appears in instruction.
31
+ * A longer number's digit substring (e.g. 82 inside 582) is not N.
32
+ * Verifies a typed claim — does not harvest candidates from prose.
33
+ */
34
+ export function instructionContainsTicketNumber(instruction, ticketNumber) {
35
+ if (!Number.isSafeInteger(ticketNumber) || ticketNumber < 1)
36
+ return false;
37
+ // Complete decimal token: not preceded or followed by another digit.
38
+ // Plain string (not template) so the digit-class backslash survives emit.
39
+ return new RegExp("(?<!\\d)" + String(ticketNumber) + "(?!\\d)").test(instruction);
40
+ }
41
+ /**
42
+ * Production live-ticket check over shared gh issue-body projection.
43
+ * Available issue face → exists; unavailable/invalid → missing.
44
+ */
45
+ export function createGhTicketExistenceChecker(options) {
46
+ const runner = options?.runner ?? createGhApiRunner();
47
+ return async (input) => {
48
+ const projected = await projectGhIssueBody(runner, {
49
+ owner: input.owner,
50
+ repo: input.repo,
51
+ ticketNumber: input.ticketNumber,
52
+ ...(input.signal === undefined ? {} : { signal: input.signal }),
53
+ });
54
+ return projected.status === "available";
55
+ };
56
+ }
57
+ /**
58
+ * Mechanical verify of an LLM typed ticket assertion (ADR 0075).
59
+ * Complete decimal of N must appear in the summons; ticket must exist live.
60
+ * Throws DiaristTicketVerificationError — caller must not wash into 无录.
61
+ */
62
+ export async function verifyAssertedTicketNumber(input) {
63
+ const n = input.ticketNumber;
64
+ if (!Number.isSafeInteger(n) || n < 1) {
65
+ throw new DiaristTicketVerificationError("assertion-uninterpretable", `diarist ticket assertion must be a safe integer >= 1, got ${String(n)}`);
66
+ }
67
+ if (!instructionContainsTicketNumber(input.instruction, n)) {
68
+ throw new DiaristTicketVerificationError("number-not-in-instruction", `diarist ticket assertion #${n} complete decimal number does not appear in accepted instruction`);
69
+ }
70
+ const origin = resolveDiaristGithubOrigin(input.projectRoot);
71
+ if (origin === undefined) {
72
+ throw new DiaristTicketVerificationError("origin-unresolved", `diarist ticket assertion #${n} requires a resolvable github.com origin remote for live verification`);
73
+ }
74
+ const checkExistence = input.checkExistence ?? createGhTicketExistenceChecker();
75
+ let exists;
76
+ try {
77
+ exists = await checkExistence({
78
+ owner: origin.owner,
79
+ repo: origin.repo,
80
+ ticketNumber: n,
81
+ ...(input.signal === undefined ? {} : { signal: input.signal }),
82
+ });
83
+ }
84
+ catch (error) {
85
+ throw new DiaristTicketVerificationError("ticket-missing", `diarist ticket assertion #${n} live verification failed`, { cause: error });
86
+ }
87
+ if (!exists) {
88
+ throw new DiaristTicketVerificationError("ticket-missing", `diarist ticket assertion #${n} does not exist as a live issue on ${origin.owner}/${origin.repo}`);
89
+ }
90
+ }
16
91
  /** Bound-ticket issue source failure — not a soft degrade to empty face. */
17
92
  export class DiaristIssueSourceError extends Error {
18
93
  code = "diarist-issue-source";
@@ -181,26 +256,36 @@ function loadSourceBlocks(input) {
181
256
  }
182
257
  /**
183
258
  * Mechanical half A — source enumeration into a frozen catalog.
184
- * Establishes the per-ticket volume + human view for every bound run (ADR 0075
185
- * `ticket-provenance-file` 每票一份起居录), then offers only blocks whose entry
186
- * identity is not already on the volume or the offered watermark (增量幂等).
259
+ * When ticketNumber is known: establishes the per-ticket volume + human view
260
+ * (ADR 0075 `ticket-provenance-file` 每票一份起居录) and offers only blocks not
261
+ * yet on the volume / offered watermark (增量幂等).
262
+ * When ticketNumber is absent (first summons): offers session candidates without
263
+ * minting a volume — the LLM turn asserts identity; accept verifies and mints.
187
264
  */
188
265
  export async function prepareDiaristSourceCatalog(input) {
189
- ensureTicketProvenanceVolume(input.ticketNumber, input.cwd, input.home);
190
- const volume = await readTicketProvenance(input.ticketNumber, input.cwd, input.home);
191
- writeTicketProvenanceHumanView({
192
- ticketNumber: input.ticketNumber,
193
- cwd: input.cwd,
194
- ...(input.home === undefined ? {} : { home: input.home }),
195
- entries: volume.entries,
196
- });
266
+ const known = input.ticketNumber;
267
+ if (known !== undefined) {
268
+ ensureTicketProvenanceVolume(known, input.cwd, input.home);
269
+ const volume = await readTicketProvenance(known, input.cwd, input.home);
270
+ writeTicketProvenanceHumanView({
271
+ ticketNumber: known,
272
+ cwd: input.cwd,
273
+ ...(input.home === undefined ? {} : { home: input.home }),
274
+ entries: volume.entries,
275
+ });
276
+ }
197
277
  const rawBlocks = loadSourceBlocks(input);
198
278
  // Safeguard only (notify filter + dedupe) — never prose-based exclusion.
199
279
  const safeguarded = mechanicalSafeguardPipeline(rawBlocks);
200
- const seen = await loadSeenEntryIdentities(input.ticketNumber, input.cwd, input.home);
201
- const fresh = safeguarded.filter((block) => !seen.has(blockEntryIdentity(input.ticketNumber, block)));
280
+ const seen = known === undefined
281
+ ? new Set()
282
+ : await loadSeenEntryIdentities(known, input.cwd, input.home);
283
+ const fresh = safeguarded.filter((block) => known === undefined || !seen.has(blockEntryIdentity(known, block)));
202
284
  return {
203
- ticketNumber: input.ticketNumber,
285
+ ...(known === undefined ? {} : { ticketNumber: known }),
286
+ instruction: input.instruction,
287
+ runDirectory: input.runDirectory,
288
+ projectRoot: input.projectRoot,
204
289
  cwd: input.cwd,
205
290
  ...(input.home === undefined ? {} : { home: input.home }),
206
291
  candidates: fresh.map((block, candidateIndex) => ({ ...block, candidateIndex })),
@@ -216,8 +301,23 @@ export function loadDiaristSourceCatalog(path) {
216
301
  throw new Error(`diarist source catalog is not an object (${path})`);
217
302
  }
218
303
  const record = parsed;
219
- if (typeof record.ticketNumber !== "number" || typeof record.cwd !== "string") {
220
- throw new Error(`diarist source catalog is missing ticket coordinates (${path})`);
304
+ if (typeof record.cwd !== "string") {
305
+ throw new Error(`diarist source catalog is missing cwd (${path})`);
306
+ }
307
+ if (typeof record.instruction !== "string") {
308
+ throw new Error(`diarist source catalog is missing instruction (${path})`);
309
+ }
310
+ if (typeof record.runDirectory !== "string") {
311
+ throw new Error(`diarist source catalog is missing runDirectory (${path})`);
312
+ }
313
+ if (typeof record.projectRoot !== "string") {
314
+ throw new Error(`diarist source catalog is missing projectRoot (${path})`);
315
+ }
316
+ if (record.ticketNumber !== undefined &&
317
+ (typeof record.ticketNumber !== "number" ||
318
+ !Number.isSafeInteger(record.ticketNumber) ||
319
+ record.ticketNumber < 1)) {
320
+ throw new Error(`diarist source catalog ticketNumber is not a safe ticket (${path})`);
221
321
  }
222
322
  if (!Array.isArray(record.candidates)) {
223
323
  throw new Error(`diarist source catalog is missing candidates (${path})`);
@@ -231,7 +331,11 @@ export function loadDiaristSourceCatalog(path) {
231
331
  * never bounces the receipt (第 0 条) and never enters the volume as an entry.
232
332
  */
233
333
  export async function commitDiaristSelections(input) {
234
- const { ticketNumber, cwd } = input.catalog;
334
+ const ticketNumber = input.catalog.ticketNumber;
335
+ if (ticketNumber === undefined) {
336
+ throw new Error("commitDiaristSelections requires a bound ticketNumber on the catalog");
337
+ }
338
+ const { cwd } = input.catalog;
235
339
  const homeOpt = input.catalog.home === undefined ? {} : { home: input.catalog.home };
236
340
  const volumePaths = ensureTicketProvenanceVolume(ticketNumber, cwd, input.catalog.home);
237
341
  const anchors = buildDiaristAnchors({ ticketNumber });
@@ -123,7 +123,7 @@ export function validateAcceptedDetails(toolName, details) {
123
123
  [GATEKEEPER_OUTPUT_TOOL_NAME]: ["dispatch", "pass"],
124
124
  [NAVIGATOR_OUTPUT_TOOL_NAME]: ["advice"],
125
125
  [AUDITOR_OUTPUT_TOOL_NAME]: ["pass", "bounce", "escalate"],
126
- [DIARIST_OUTPUT_TOOL_NAME]: ["completed"],
126
+ [DIARIST_OUTPUT_TOOL_NAME]: ["completed", "escalate"],
127
127
  };
128
128
  const collectorDiscriminator = toolName === COLLECTOR_OUTPUT_TOOL && Array.isArray(candidate?.groups);
129
129
  const baseDiscriminator = discriminator;
@@ -1,6 +1,6 @@
1
1
  import { engineSessionMaterialFromOptions } from "../package-resources/engine-material.js";
2
2
  import { CliUsageError } from "./cli-errors.js";
3
- import { bindReusedTicketNumber, resolveKnownTicketNumber, tryResumeSameTicketSeatRun, } from "./seat-ticket-binding.js";
3
+ import { tryResumeSameTicketSeatRun } from "./seat-ticket-binding.js";
4
4
  import { admitInspectorInvocation, buildInspectorTransportPrompt, } from "./invocation.js";
5
5
  import { prepareSummonsResumeMaterials, runPostAdmissionOneShot, runPostAdmissionSeatResume, resumeTurnRequestProjectionOptions, } from "./post-admission.js";
6
6
  import { loadResumableInspectorRun, markRunAdmitted, parentRunPathFromGatePointerInstruction, } from "./run-lifecycle.js";
@@ -27,14 +27,9 @@ export async function runPublicInspector(argv, env, io, parseInspectorArgv) {
27
27
  throw error;
28
28
  }
29
29
  // #747: same parent (卷宗指针) → resume prior inspector run with this summons' materials.
30
- // #709: ticket identity is reused from records this book already holds — no seat model call.
30
+ // #771: no mechanical ticket match against instruction text; parent-run path only.
31
31
  // No bare catch→fresh: lookup/resume failures surface; only true absence mints new.
32
32
  const projectRoot = parsed.project ?? env.cwd;
33
- const reusedTicketNumber = await resolveKnownTicketNumber({
34
- instruction: parsed.instruction,
35
- projectRoot,
36
- home: env.home,
37
- });
38
33
  const parentRunPath = parentRunPathFromGatePointerInstruction(parsed.instruction);
39
34
  if (parentRunPath !== undefined) {
40
35
  const summons = {
@@ -100,12 +95,7 @@ export async function runPublicInspector(argv, env, io, parseInspectorArgv) {
100
95
  env,
101
96
  io,
102
97
  request: turnRequest,
103
- adapters: inspectorAdapters({
104
- beforeDispatch: async (admittedSeat) => {
105
- // #635/#709: bind the reused identity inside the controlled-failure boundary.
106
- await bindReusedTicketNumber(admittedSeat, reusedTicketNumber);
107
- },
108
- }),
98
+ adapters: inspectorAdapters(),
109
99
  ...(env.engine === undefined ? {} : { effectiveEngine: env.engine }),
110
100
  });
111
101
  }
@@ -4,7 +4,7 @@ import { CliUsageError } from "./cli-errors.js";
4
4
  import { admitAuditorInvocation, admitGatekeeperInvocation, admitNavigatorInvocation, bindAdmittedTicketNumber, buildInstructionTransportPrompt, persistAdmittedSourceRunPath, } from "./invocation.js";
5
5
  import { prepareSummonsResumeMaterials, runPostAdmissionOneShot, runPostAdmissionSeatResume, resumeTurnRequestProjectionOptions, } from "./post-admission.js";
6
6
  import { loadResumableInstructionSeatRun, markRunAdmitted, } from "./run-lifecycle.js";
7
- import { bindReusedTicketNumber, resolveKnownTicketNumber, tryResumeSameTicketSeatRun, } from "./seat-ticket-binding.js";
7
+ import { tryResumeSameTicketSeatRun } from "./seat-ticket-binding.js";
8
8
  import { presentStructuralRejection, readEngineDetourInfrastructureFailure, trySettleAuditorTerminalResult, trySettleGatekeeperTerminalResult, trySettleNavigatorTerminalResult, } from "./settlement.js";
9
9
  import { projectRoleTurnRequest, } from "./turn-request.js";
10
10
  /** Project an admitted instruction-seat invocation onto the host-neutral turn request. */
@@ -119,10 +119,10 @@ export async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
119
119
  let auditorSubject;
120
120
  let auditorSourceRun;
121
121
  let auditorSourceTicket;
122
- let reusedTicketNumber;
123
- // #637 / #747: resume prior seat run with this summons' materials.
124
- // Auditor (#747): parent --source-run path is the lookup key.
125
- // Other instruction seats: reuse known ticket (#709). No bare catch→fresh.
122
+ // #637 / #747 / #771: resume prior seat run with this summons' materials.
123
+ // Auditor (#747): parent --source-run path is the lookup key (typed inherit).
124
+ // Other instruction seats: no mechanical ticket match against instruction text.
125
+ // No bare catch→fresh.
126
126
  const projectRoot = parsed.project ?? env.cwd;
127
127
  if (role === "auditor") {
128
128
  if (parsed.subject !== "judge" && parsed.subject !== "doctor") {
@@ -150,13 +150,6 @@ export async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
150
150
  return { exitCode: 2 };
151
151
  }
152
152
  }
153
- else {
154
- reusedTicketNumber = await resolveKnownTicketNumber({
155
- instruction: parsed.instruction,
156
- projectRoot,
157
- home: env.home,
158
- });
159
- }
160
153
  const summons = {
161
154
  instruction: parsed.instruction,
162
155
  instructionEmpty: parsed.instruction.trim() === "",
@@ -179,19 +172,6 @@ export async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
179
172
  if (resumed !== undefined)
180
173
  return resumed;
181
174
  }
182
- else if (reusedTicketNumber !== undefined) {
183
- const resumed = await tryResumeSameTicketSeatRun({
184
- home: env.home,
185
- projectRoot,
186
- role,
187
- ticketNumber: reusedTicketNumber,
188
- freshSummons: env.freshSummons,
189
- summons,
190
- resume: (runId, materials) => runPublicInstructionSeatResume({ runId, ...(materials === undefined ? {} : { summons: materials }) }, env, io),
191
- });
192
- if (resumed !== undefined)
193
- return resumed;
194
- }
195
175
  let admitted;
196
176
  try {
197
177
  admitted = await admitInstructionSeat(role, {
@@ -248,15 +228,10 @@ export async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
248
228
  request: turnRequest,
249
229
  adapters: instructionSeatAdapters({
250
230
  beforeDispatch: async (admittedSeat) => {
251
- // #635/#709: ticket bind inside controlled-failure boundary.
252
- // Auditor inherits source-run ticket (notary face).
253
- // Other seats: reuse known ticket identity.
231
+ // Auditor inherits source-run ticket (notary face) — typed, not prose match.
254
232
  if (auditorSourceTicket !== undefined) {
255
233
  await bindAdmittedTicketNumber(admittedSeat, auditorSourceTicket);
256
234
  }
257
- else {
258
- await bindReusedTicketNumber(admittedSeat, reusedTicketNumber);
259
- }
260
235
  },
261
236
  }),
262
237
  ...(env.engine === undefined ? {} : { effectiveEngine: env.engine }),
@@ -3,6 +3,7 @@
3
3
  * Attachments, project default/override (ADR 0052 / #106).
4
4
  */
5
5
  import { execFileSync } from "node:child_process";
6
+ import { existsSync } from "node:fs";
6
7
  import { lstat, mkdir, readFile, realpath, writeFile, } from "node:fs/promises";
7
8
  import { basename, isAbsolute, join, resolve, sep } from "node:path";
8
9
  import { activationBookDirectory, ensureRealDirectoryTree, homeFromRunDirectory, pathContainedIn, resolveActivationLedgerHome, } from "../activation-ledger-topology.js";
@@ -164,6 +165,37 @@ export async function bindAdmittedTicketNumber(admitted, ticketNumber) {
164
165
  const current = JSON.parse(await readFile(admittedPath, "utf8"));
165
166
  await writeFile(admittedPath, `${JSON.stringify({ ...current, ticketNumber }, null, 2)}\n`, "utf8");
166
167
  }
168
+ /**
169
+ * Bind ticket identity onto a run directory's durable pages when the admitted
170
+ * object is not in hand (起居郎 accept hook after LLM assertion, #771).
171
+ * Idempotent when the same number is already on the pages.
172
+ */
173
+ export async function bindTicketNumberOnRunDirectory(runDirectory, ticketNumber) {
174
+ if (!Number.isSafeInteger(ticketNumber) || ticketNumber < 1) {
175
+ throw new Error(`bindTicketNumberOnRunDirectory requires a safe positive integer, got ${String(ticketNumber)}`);
176
+ }
177
+ const admittedPath = join(runDirectory, "admitted-request.json");
178
+ const invocationPath = join(runDirectory, "invocation.json");
179
+ const admitted = JSON.parse(await readFile(admittedPath, "utf8"));
180
+ const existing = admitted.ticketNumber;
181
+ if (typeof existing === "number") {
182
+ if (existing === ticketNumber)
183
+ return;
184
+ throw new Error(`bindTicketNumberOnRunDirectory refuses to replace existing ticket #${existing} with #${ticketNumber}`);
185
+ }
186
+ // Conflict guard before any write: crash window of bindAdmittedTicketNumber
187
+ // can leave invocation bound while admitted-request is still unbound — refuse
188
+ // silent rebind. Read-before-merge; never check the page just overwritten.
189
+ if (existsSync(invocationPath)) {
190
+ const invocation = JSON.parse(await readFile(invocationPath, "utf8"));
191
+ if (typeof invocation.ticketNumber === "number" &&
192
+ invocation.ticketNumber !== ticketNumber) {
193
+ throw new Error(`bindTicketNumberOnRunDirectory refuses to replace invocation ticket #${invocation.ticketNumber} with #${ticketNumber}`);
194
+ }
195
+ }
196
+ await writeFile(admittedPath, `${JSON.stringify({ ...admitted, ticketNumber }, null, 2)}\n`, "utf8");
197
+ await mergeInvocationIdentityPage(runDirectory, { ticketNumber });
198
+ }
167
199
  /** Add the identity returned by the production Pi launch seam to its existing ledger page. */
168
200
  export async function recordLaunchedPiIdentity(runDirectory, identity) {
169
201
  await mergeInvocationIdentityPage(runDirectory, {
@@ -1,7 +1,6 @@
1
1
  import { engineSessionMaterialFromOptions } from "../package-resources/engine-material.js";
2
2
  import { CliUsageError } from "./cli-errors.js";
3
3
  import { admitJudgeInvocation, buildJudgeTransportPrompt, } from "./invocation.js";
4
- import { resolveSeatTicketBinding } from "./seat-ticket-binding.js";
5
4
  import { loadResumableJudgeRun, markRunAdmitted, buildResumeContinuationPrompt, } from "./run-lifecycle.js";
6
5
  import { presentStructuralRejection, readEngineDetourInfrastructureFailure, trySettleJudgeTerminalResult, } from "./settlement.js";
7
6
  import { projectRoleTurnRequest, } from "./turn-request.js";
@@ -91,12 +90,7 @@ export async function runPublicJudge(argv, env, io, parseJudgeArgv) {
91
90
  }),
92
91
  },
93
92
  }),
94
- adapters: {
95
- ...judgeAdapters(),
96
- beforeDispatch: async (admittedSeat) => {
97
- await resolveSeatTicketBinding(admittedSeat, env);
98
- },
99
- },
93
+ adapters: judgeAdapters(),
100
94
  ...(env.engine === undefined ? {} : { effectiveEngine: env.engine }),
101
95
  });
102
96
  }