@akagilnc/pi-workflow-roles 0.1.4062 → 0.1.4196

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 (72) hide show
  1. package/dist/acp-host/production-host.js +2075 -1088
  2. package/dist/archivist-record-entry.js +204 -20
  3. package/dist/archivist-record-topology.js +36 -16
  4. package/dist/auditor-dossier-tool.js +2 -1
  5. package/dist/diarist-contracts.js +96 -0
  6. package/dist/doctor-evidence.js +3 -2
  7. package/dist/headless-host/production-host.js +2215 -1228
  8. package/dist/migrate-book-topology.js +278917 -0
  9. package/dist/navigator-public-session.js +22 -25
  10. package/dist/notary-source-run.js +7 -4
  11. package/dist/pi/durable-principal.js +9 -6
  12. package/dist/public-cli/auto-resume.js +2 -5
  13. package/dist/public-cli/diarist-run.js +27 -25
  14. package/dist/public-cli/instruction-seat-run.js +8 -11
  15. package/dist/public-cli/invocation.js +127 -63
  16. package/dist/public-cli/main.js +1507 -645
  17. package/dist/public-cli/option-definitions.js +2 -2
  18. package/dist/public-cli/post-admission.js +47 -12
  19. package/dist/public-cli/run-lifecycle.js +206 -58
  20. package/dist/public-cli/seat-ticket-binding.js +3 -6
  21. package/dist/public-cli/settlement.js +5 -3
  22. package/dist/role-run-placement.js +84 -0
  23. package/dist/role-run-relocation.js +358 -0
  24. package/dist/run-terminal-artifacts.js +2 -1
  25. package/dist/run-ticket-number.js +51 -32
  26. package/dist/sitian-appender.js +11 -26
  27. package/dist/submission-ledger.js +78 -19
  28. package/dist/ticket-provenance.js +3 -1
  29. package/package.json +3 -2
  30. package/scripts/build-package.mjs +34 -2
  31. package/souls/countersign.md +2 -2
  32. package/souls/fixer.md +3 -2
  33. package/src/analyst-ledger.ts +14 -15
  34. package/src/archivist-record-entry.ts +285 -38
  35. package/src/archivist-record-topology.ts +43 -18
  36. package/src/auditor-dossier-tool.ts +2 -1
  37. package/src/book-topology-migration-placement.ts +493 -0
  38. package/src/book-topology-migration.ts +220 -0
  39. package/src/book-topology-migrators-t11.ts +856 -0
  40. package/src/book-topology-mixed-volume-migrators.ts +470 -0
  41. package/src/book-topology-partition-migrators.ts +25 -0
  42. package/src/book-topology-record-class-migrators.ts +779 -0
  43. package/src/book-topology-runs-migrator.ts +244 -0
  44. package/src/diarist-contracts.ts +116 -0
  45. package/src/diarist-role.ts +6 -0
  46. package/src/diarist.ts +2 -0
  47. package/src/doctor-evidence.ts +4 -1
  48. package/src/doctor-role.ts +1 -1
  49. package/src/navigator-public-session.ts +33 -30
  50. package/src/notary-source-run.ts +9 -4
  51. package/src/pi/durable-principal.ts +9 -13
  52. package/src/public-cli/auto-resume.ts +2 -6
  53. package/src/public-cli/countersign-run.ts +182 -32
  54. package/src/public-cli/diarist-run.ts +34 -26
  55. package/src/public-cli/instruction-seat-run.ts +7 -11
  56. package/src/public-cli/invocation.ts +192 -58
  57. package/src/public-cli/option-definitions.ts +2 -2
  58. package/src/public-cli/post-admission.ts +73 -13
  59. package/src/public-cli/run-lifecycle.ts +255 -65
  60. package/src/public-cli/seat-ticket-binding.ts +3 -6
  61. package/src/public-cli/settlement.ts +6 -4
  62. package/src/role-run-placement.ts +128 -0
  63. package/src/role-run-relocation.ts +491 -0
  64. package/src/role-runtime.ts +11 -5
  65. package/src/run-terminal-artifacts.ts +3 -1
  66. package/src/run-ticket-number.ts +80 -20
  67. package/src/sitian-appender.ts +25 -28
  68. package/src/submission-ledger.ts +102 -19
  69. package/src/ticket-provenance.ts +4 -1
  70. package/src/ticket-trajectory.ts +22 -35
  71. package/src/worker-role.ts +4 -4
  72. package/src/worker-submission-gates.ts +6 -6
@@ -377,6 +377,146 @@ var init_activation_ledger_topology = __esm({
377
377
  }
378
378
  });
379
379
 
380
+ // src/run-ticket-number.ts
381
+ import { readFile } from "node:fs/promises";
382
+ import { join as join3 } from "node:path";
383
+ function isEnoent(error) {
384
+ return error instanceof Error && "code" in error && error.code === "ENOENT";
385
+ }
386
+ function isSafePositiveTicketNumber(value) {
387
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 1;
388
+ }
389
+ function requireSafePositiveTicketNumber(ticketNumber, context = "ticketNumber") {
390
+ if (!isSafePositiveTicketNumber(ticketNumber)) {
391
+ throw new Error(
392
+ `${context} requires a safe positive integer, got ${String(ticketNumber)}`
393
+ );
394
+ }
395
+ return ticketNumber;
396
+ }
397
+ function ticketFromRecord(record4) {
398
+ return isSafePositiveTicketNumber(record4.ticketNumber) ? record4.ticketNumber : void 0;
399
+ }
400
+ async function readJsonObject(path) {
401
+ try {
402
+ const raw = JSON.parse(await readFile(path, "utf8"));
403
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
404
+ return void 0;
405
+ }
406
+ return raw;
407
+ } catch (error) {
408
+ if (isEnoent(error)) return void 0;
409
+ throw error;
410
+ }
411
+ }
412
+ async function readBoardPageTicketNumber(runDirectory, page) {
413
+ const record4 = await readJsonObject(join3(runDirectory, page));
414
+ if (record4 === void 0) return void 0;
415
+ return ticketFromRecord(record4);
416
+ }
417
+ async function readBoardTicketNumber(runDirectory) {
418
+ return await readBoardPageTicketNumber(runDirectory, "admitted-request.json") ?? await readBoardPageTicketNumber(runDirectory, "invocation.json");
419
+ }
420
+ async function readMigrationDerivedTicketNumber(runDirectory) {
421
+ const record4 = await readJsonObject(
422
+ join3(runDirectory, MIGRATION_TICKET_DERIVATION_PAGE)
423
+ );
424
+ if (record4 === void 0) return void 0;
425
+ if (record4.derivation !== "worktree-path-basename") return void 0;
426
+ return ticketFromRecord(record4);
427
+ }
428
+ async function readRunTicketNumber(runDirectory) {
429
+ return await readBoardTicketNumber(runDirectory) ?? await readMigrationDerivedTicketNumber(runDirectory);
430
+ }
431
+ var MIGRATION_TICKET_DERIVATION_PAGE;
432
+ var init_run_ticket_number = __esm({
433
+ "src/run-ticket-number.ts"() {
434
+ "use strict";
435
+ MIGRATION_TICKET_DERIVATION_PAGE = "migration-ticket-derivation.json";
436
+ }
437
+ });
438
+
439
+ // src/role-run-placement.ts
440
+ import { readdir } from "node:fs/promises";
441
+ import { join as join4 } from "node:path";
442
+ function isMissingPathError(error) {
443
+ return error instanceof Error && "code" in error && error.code === "ENOENT";
444
+ }
445
+ async function listBookRunDirectories(bookDir) {
446
+ const out = [];
447
+ const seen = /* @__PURE__ */ new Set();
448
+ const collect = async (runsDir) => {
449
+ let entries;
450
+ try {
451
+ entries = await readdir(runsDir, { withFileTypes: true });
452
+ } catch (error) {
453
+ if (isMissingPathError(error)) return;
454
+ throw error;
455
+ }
456
+ for (const entry of entries) {
457
+ if (!entry.isDirectory()) continue;
458
+ const runDir = join4(runsDir, entry.name);
459
+ if (seen.has(runDir)) continue;
460
+ seen.add(runDir);
461
+ out.push(runDir);
462
+ }
463
+ };
464
+ await collect(join4(bookDir, "runs"));
465
+ let subjects;
466
+ try {
467
+ subjects = await readdir(bookDir, { withFileTypes: true });
468
+ } catch (error) {
469
+ if (isMissingPathError(error)) return out.sort();
470
+ throw error;
471
+ }
472
+ for (const subject of subjects) {
473
+ if (!subject.isDirectory() || subject.name === "runs") continue;
474
+ await collect(join4(bookDir, subject.name, "runs"));
475
+ }
476
+ return out.sort();
477
+ }
478
+ function roleRunPlacement(ledgerHome, input) {
479
+ const subjectDirectory = "ticketNumber" in input.subject ? String(requireSafePositiveTicketNumber(
480
+ input.subject.ticketNumber,
481
+ "roleRunPlacement subject.ticketNumber"
482
+ )) : "unbound";
483
+ const runDirectory = join4(
484
+ activationBookDirectory(ledgerHome, input.bookKey),
485
+ subjectDirectory,
486
+ "runs",
487
+ `${input.runId}@${input.role}`
488
+ );
489
+ const sessionDirectory = join4(runDirectory, "session");
490
+ return {
491
+ runDirectory,
492
+ sessionDirectory,
493
+ sessionFile: join4(sessionDirectory, "session.jsonl"),
494
+ artifactsDirectory: roleRunArtifactsDirectory(runDirectory),
495
+ attachmentsDirectory: join4(runDirectory, "attachments")
496
+ };
497
+ }
498
+ function roleRunArtifactsDirectory(runDirectory) {
499
+ return join4(runDirectory, "artifacts");
500
+ }
501
+ function ensureRoleRunDirectory(ledgerHome, directory) {
502
+ return ensureRealDirectoryTree(ledgerHome, directory);
503
+ }
504
+ function ensureRoleRunPlacement(ledgerHome, placement) {
505
+ for (const directory of [
506
+ placement.sessionDirectory,
507
+ placement.attachmentsDirectory
508
+ ]) {
509
+ ensureRoleRunDirectory(ledgerHome, directory);
510
+ }
511
+ }
512
+ var init_role_run_placement = __esm({
513
+ "src/role-run-placement.ts"() {
514
+ "use strict";
515
+ init_activation_ledger_topology();
516
+ init_run_ticket_number();
517
+ }
518
+ });
519
+
380
520
  // src/pi/durable-principal.ts
381
521
  var durable_principal_exports = {};
382
522
  __export(durable_principal_exports, {
@@ -384,25 +524,23 @@ __export(durable_principal_exports, {
384
524
  piDurablePrincipalAuthority: () => piDurablePrincipalAuthority
385
525
  });
386
526
  import { lstat } from "node:fs/promises";
387
- import { join as join3 } from "node:path";
527
+ import { join as join5 } from "node:path";
388
528
  function encode(coordinates) {
389
529
  return coordinates;
390
530
  }
391
531
  function issuePiDurablePrincipalCoordinates(request) {
392
532
  const ledgerHome = resolveActivationLedgerHome(request.home);
393
533
  const bookKey = resolveBookKeyFromGit(request.cwd);
394
- const runDirectory = join3(
395
- activationBookDirectory(ledgerHome, bookKey),
396
- "runs",
397
- `${request.runId}@${request.role}`
398
- );
399
- const sessionDirectory = join3(runDirectory, "session");
534
+ const placement = roleRunPlacement(ledgerHome, {
535
+ bookKey,
536
+ subject: { unbound: true },
537
+ runId: request.runId,
538
+ role: request.role
539
+ });
400
540
  return {
401
541
  ledgerHome,
402
542
  bookKey,
403
- runDirectory,
404
- sessionDirectory,
405
- sessionFile: join3(sessionDirectory, "session.jsonl")
543
+ ...placement
406
544
  };
407
545
  }
408
546
  var piDurablePrincipalAuthority;
@@ -411,6 +549,7 @@ var init_durable_principal = __esm({
411
549
  "use strict";
412
550
  init_activation_ledger_git();
413
551
  init_activation_ledger_topology();
552
+ init_role_run_placement();
414
553
  piDurablePrincipalAuthority = {
415
554
  issue(request) {
416
555
  const coordinates = issuePiDurablePrincipalCoordinates(request);
@@ -435,7 +574,7 @@ var init_durable_principal = __esm({
435
574
  }
436
575
  return {
437
576
  sessionDirectory: record4.sessionDirectory,
438
- sessionFile: typeof record4.sessionFile === "string" && record4.sessionFile.trim() !== "" ? record4.sessionFile : join3(record4.sessionDirectory, "session.jsonl")
577
+ sessionFile: typeof record4.sessionFile === "string" && record4.sessionFile.trim() !== "" ? record4.sessionFile : join5(record4.sessionDirectory, "session.jsonl")
439
578
  };
440
579
  },
441
580
  async isAvailable(principal) {
@@ -453,7 +592,7 @@ var init_durable_principal = __esm({
453
592
 
454
593
  // src/package-resources/engine-material.ts
455
594
  import { existsSync as existsSync2, readdirSync } from "node:fs";
456
- import { join as join4 } from "node:path";
595
+ import { join as join6 } from "node:path";
457
596
  function pickEngineAxis(source) {
458
597
  return {
459
598
  ...source.engine === void 0 ? {} : { engine: source.engine },
@@ -474,11 +613,11 @@ function isEngineNameSyntax(name) {
474
613
  return true;
475
614
  }
476
615
  function resolveEngineMaterialDirectory(packageRoot2) {
477
- return join4(packageRoot2, ENGINE_MATERIAL_RELATIVE_ROOT);
616
+ return join6(packageRoot2, ENGINE_MATERIAL_RELATIVE_ROOT);
478
617
  }
479
618
  function resolveEngineMaterialPath(packageRoot2, name) {
480
619
  const legal = assertLegalEngineName(name);
481
- return join4(resolveEngineMaterialDirectory(packageRoot2), `${legal}.md`);
620
+ return join6(resolveEngineMaterialDirectory(packageRoot2), `${legal}.md`);
482
621
  }
483
622
  function assertLegalEngineName(name) {
484
623
  if (!isEngineNameSyntax(name)) {
@@ -14710,10 +14849,84 @@ var init_auditor_output = __esm({
14710
14849
  });
14711
14850
 
14712
14851
  // src/diarist-contracts.ts
14852
+ function projectCourtTicketNumbers(raw, options) {
14853
+ if (!Array.isArray(raw)) return null;
14854
+ const out = [];
14855
+ const seen = /* @__PURE__ */ new Set();
14856
+ for (const item of raw) {
14857
+ if (!isSafePositiveTicketNumber(item)) continue;
14858
+ if (seen.has(item)) continue;
14859
+ seen.add(item);
14860
+ out.push(item);
14861
+ }
14862
+ const principal = options?.principalTicket;
14863
+ if (principal === void 0) return out;
14864
+ requireSafePositiveTicketNumber(principal, "projectCourtTicketNumbers principalTicket");
14865
+ if (seen.has(principal)) return out;
14866
+ return [principal, ...out];
14867
+ }
14868
+ function interpretDurableCourtTicketNumbers(record4, options) {
14869
+ if (!Object.hasOwn(record4, "courtTicketNumbers")) {
14870
+ return { kind: "absent" };
14871
+ }
14872
+ const raw = record4.courtTicketNumbers;
14873
+ if (!Array.isArray(raw)) {
14874
+ return {
14875
+ kind: "damage",
14876
+ reason: "courtTicketNumbers is present but not an array"
14877
+ };
14878
+ }
14879
+ if (raw.length === 0) {
14880
+ return {
14881
+ kind: "damage",
14882
+ reason: "courtTicketNumbers is present but empty"
14883
+ };
14884
+ }
14885
+ for (let i = 0; i < raw.length; i += 1) {
14886
+ const item = raw[i];
14887
+ if (!isSafePositiveTicketNumber(item)) {
14888
+ return {
14889
+ kind: "damage",
14890
+ reason: `courtTicketNumbers[${i}] is not a safe positive integer`
14891
+ };
14892
+ }
14893
+ }
14894
+ const tickets = projectCourtTicketNumbers(raw);
14895
+ if (tickets === null || tickets.length === 0) {
14896
+ return {
14897
+ kind: "damage",
14898
+ reason: "courtTicketNumbers projected empty after lawful members"
14899
+ };
14900
+ }
14901
+ const principal = options?.principalTicket;
14902
+ if (principal !== void 0) {
14903
+ if (!isSafePositiveTicketNumber(principal)) {
14904
+ return {
14905
+ kind: "damage",
14906
+ reason: "courtTicketNumbers principal ticket is not a safe positive integer"
14907
+ };
14908
+ }
14909
+ if (!tickets.includes(principal)) {
14910
+ return {
14911
+ kind: "damage",
14912
+ reason: `courtTicketNumbers is missing principal ticket #${principal}`
14913
+ };
14914
+ }
14915
+ }
14916
+ return { kind: "ok", tickets: Object.freeze([...tickets]) };
14917
+ }
14918
+ function sameCourtTicketNumbers(left, right) {
14919
+ if (left.length !== right.length) return false;
14920
+ for (let i = 0; i < left.length; i += 1) {
14921
+ if (left[i] !== right[i]) return false;
14922
+ }
14923
+ return true;
14924
+ }
14713
14925
  var DIARIST_OUTPUT_TOOL_NAME;
14714
14926
  var init_diarist_contracts = __esm({
14715
14927
  "src/diarist-contracts.ts"() {
14716
14928
  "use strict";
14929
+ init_run_ticket_number();
14717
14930
  DIARIST_OUTPUT_TOOL_NAME = "ak_diarist_output";
14718
14931
  }
14719
14932
  });
@@ -15229,8 +15442,8 @@ __export(config_exports, {
15229
15442
  setPersistentSeatHost: () => setPersistentSeatHost,
15230
15443
  validatePublicCliConfigAxes: () => validatePublicCliConfigAxes
15231
15444
  });
15232
- import { mkdir, readFile, writeFile } from "node:fs/promises";
15233
- import { dirname as dirname4, join as join5 } from "node:path";
15445
+ import { mkdir, readFile as readFile2, writeFile } from "node:fs/promises";
15446
+ import { dirname as dirname4, join as join7 } from "node:path";
15234
15447
  function isGateOfficerSeat(value) {
15235
15448
  return GATE_OFFICER_SEATS.includes(value);
15236
15449
  }
@@ -15238,12 +15451,12 @@ function publicCliConfigPath(home) {
15238
15451
  if (typeof home !== "string" || home.trim() === "") {
15239
15452
  throw new Error("home must be explicitly provided");
15240
15453
  }
15241
- return join5(home, ".ak-roles", "public-cli.json");
15454
+ return join7(home, ".ak-roles", "public-cli.json");
15242
15455
  }
15243
15456
  async function loadPublicCliConfig(home) {
15244
15457
  const path = publicCliConfigPath(home);
15245
15458
  try {
15246
- const raw = await readFile(path, "utf8");
15459
+ const raw = await readFile2(path, "utf8");
15247
15460
  return parsePublicCliConfig(JSON.parse(raw));
15248
15461
  } catch (error) {
15249
15462
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -15706,7 +15919,7 @@ function credentialProvidersFromAuthData(data) {
15706
15919
  }
15707
15920
  async function loadCredentialProviders(agentDir) {
15708
15921
  try {
15709
- const raw = await readFile(join5(agentDir, "auth.json"), "utf8");
15922
+ const raw = await readFile2(join7(agentDir, "auth.json"), "utf8");
15710
15923
  return credentialProvidersFromAuthData(JSON.parse(raw));
15711
15924
  } catch (error) {
15712
15925
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -15745,15 +15958,15 @@ __export(host_providers_exports, {
15745
15958
  renderHostProvidersTable: () => renderHostProvidersTable
15746
15959
  });
15747
15960
  import { readFileSync } from "node:fs";
15748
- import { join as join6 } from "node:path";
15961
+ import { join as join8 } from "node:path";
15749
15962
  function hostProvidersPath(home) {
15750
15963
  if (typeof home !== "string" || home.trim() === "") {
15751
15964
  throw new Error("home must be explicitly provided");
15752
15965
  }
15753
- return join6(home, ".ak-roles", "host-providers.json");
15966
+ return join8(home, ".ak-roles", "host-providers.json");
15754
15967
  }
15755
15968
  function hermesProviderModelsCachePath(home) {
15756
- return join6(home, ".hermes", "provider_models_cache.json");
15969
+ return join8(home, ".hermes", "provider_models_cache.json");
15757
15970
  }
15758
15971
  function parseHostProvidersTable(value) {
15759
15972
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
@@ -16065,7 +16278,7 @@ import {
16065
16278
  unlinkSync,
16066
16279
  writeFileSync
16067
16280
  } from "node:fs";
16068
- import { basename as basename3, dirname as dirname5, join as join7, resolve as resolve3 } from "node:path";
16281
+ import { dirname as dirname5, join as join9 } from "node:path";
16069
16282
  function isRecord(value) {
16070
16283
  return typeof value === "object" && value !== null && !Array.isArray(value);
16071
16284
  }
@@ -16192,38 +16405,23 @@ function resolveSitianVolumeCategory(kind) {
16192
16405
  }
16193
16406
  return kind;
16194
16407
  }
16195
- function safeBookKey(cwd) {
16196
- try {
16197
- return resolveBookKeyFromGit(cwd);
16198
- } catch {
16199
- return basename3(resolve3(cwd)) || "default";
16200
- }
16201
- }
16202
16408
  function resolveSitianRecordPathInLedger(input, ledgerHome) {
16203
- const cwd = input.cwd ?? process.cwd();
16204
16409
  const category = resolveSitianVolumeCategory(input.kind);
16410
+ const ticketNumber = category === "ticket-provenance" ? typeof input.subject === "string" && /^[1-9][0-9]*$/.test(input.subject) ? input.subject : typeof input.subject === "object" && typeof input.subject.ticketNumber === "number" && Number.isSafeInteger(input.subject.ticketNumber) && input.subject.ticketNumber > 0 ? String(input.subject.ticketNumber) : void 0 : void 0;
16205
16411
  let sessionDir;
16206
- if (input.sessionParent !== void 0 && input.sessionParent.length > 0 && physicallyContainedIn(ledgerHome, input.sessionParent)) {
16207
- sessionDir = join7(dirname5(input.sessionParent), category);
16412
+ if (ticketNumber !== void 0) {
16413
+ const bookDir = activationBookDirectory(
16414
+ ledgerHome,
16415
+ resolveBookKeyFromGit(input.cwd ?? process.cwd())
16416
+ );
16417
+ sessionDir = join9(bookDir, ticketNumber);
16208
16418
  } else {
16209
- const bookKey = safeBookKey(cwd);
16210
- const bookDir = activationBookDirectory(ledgerHome, bookKey);
16211
- if (input.subject !== void 0) {
16212
- let subjectStr;
16213
- if (typeof input.subject === "string") {
16214
- subjectStr = input.subject;
16215
- } else if (typeof input.subject.runId === "string" && input.subject.runId.length > 0) {
16216
- subjectStr = input.subject.runId;
16217
- } else {
16218
- subjectStr = JSON.stringify(input.subject);
16219
- }
16220
- const digest = createHash("sha256").update(subjectStr).digest("hex").slice(0, 32);
16221
- sessionDir = join7(bookDir, category, digest);
16222
- } else {
16223
- sessionDir = join7(bookDir, category);
16419
+ if (input.sessionParent === void 0 || input.sessionParent.length === 0 || !physicallyContainedIn(ledgerHome, input.sessionParent)) {
16420
+ throw new Error("Sitian record ownership requires a parent session inside the ledger home");
16224
16421
  }
16422
+ sessionDir = join9(dirname5(input.sessionParent), category);
16225
16423
  }
16226
- const recordFile = join7(sessionDir, "records.jsonl");
16424
+ const recordFile = join9(sessionDir, "records.jsonl");
16227
16425
  return { sessionDir, recordFile, ledgerHome };
16228
16426
  }
16229
16427
  function resolveSitianRecordPath(input) {
@@ -16281,7 +16479,7 @@ var init_sitian_appender = __esm({
16281
16479
 
16282
16480
  // src/sitian-reader.ts
16283
16481
  import { existsSync as existsSync4 } from "node:fs";
16284
- import { readFile as readFile2 } from "node:fs/promises";
16482
+ import { readFile as readFile3 } from "node:fs/promises";
16285
16483
  function isRecord2(value) {
16286
16484
  return typeof value === "object" && value !== null && !Array.isArray(value);
16287
16485
  }
@@ -16289,7 +16487,7 @@ async function readSitianRecords(recordFile) {
16289
16487
  if (!existsSync4(recordFile)) {
16290
16488
  return { records: [], diagnostics: [] };
16291
16489
  }
16292
- const text = await readFile2(recordFile, "utf8");
16490
+ const text = await readFile3(recordFile, "utf8");
16293
16491
  const lines = text.split("\n");
16294
16492
  const records = [];
16295
16493
  const diagnostics = [];
@@ -16354,13 +16552,13 @@ __export(role_turn_host_exports, {
16354
16552
  });
16355
16553
  import { execFile, spawn } from "node:child_process";
16356
16554
  import { constants } from "node:fs";
16357
- import { access, appendFile, readFile as readFile3, realpath } from "node:fs/promises";
16358
- import { basename as basename4, delimiter as delimiter2, dirname as dirname6, isAbsolute as isAbsolute3, join as join8, resolve as resolve4 } from "node:path";
16555
+ import { access, appendFile, readFile as readFile4, realpath } from "node:fs/promises";
16556
+ import { basename as basename3, delimiter as delimiter2, dirname as dirname6, isAbsolute as isAbsolute3, join as join10, resolve as resolve3 } from "node:path";
16359
16557
  import { platform } from "node:process";
16360
16558
  import { promisify } from "node:util";
16361
16559
  import { randomUUID as randomUUID2 } from "node:crypto";
16362
16560
  function resolveInternalRoleEntrypoint(packageRoot2) {
16363
- return join8(packageRoot2, INTERNAL_ROLE_ENTRYPOINT_RELATIVE2);
16561
+ return join10(packageRoot2, INTERNAL_ROLE_ENTRYPOINT_RELATIVE2);
16364
16562
  }
16365
16563
  function buildExplicitInternalActivationArgs(selectedRoleEntry, extraArgs = []) {
16366
16564
  return ["--no-extensions", "-e", selectedRoleEntry, ...extraArgs];
@@ -16396,7 +16594,7 @@ function buildMethodArgs(methods) {
16396
16594
  function applyPiNativeSkillInvocation(methods, prompt) {
16397
16595
  const skills = methods.filter((method) => method.kind === "skill");
16398
16596
  if (skills.length !== 1) return prompt;
16399
- const name = basename4(dirname6(skills[0].path));
16597
+ const name = basename3(dirname6(skills[0].path));
16400
16598
  if (name.length === 0) return prompt;
16401
16599
  const token = `/skill:${name}`;
16402
16600
  const trimmed = prompt.trimStart();
@@ -16441,7 +16639,7 @@ function piUserDialogueBody(request) {
16441
16639
  }
16442
16640
  async function resolveSelectedPi(command, cwd, env) {
16443
16641
  const searchPath = env.PATH ?? (platform === "win32" ? process.env.PATH ?? "" : "/usr/bin:/bin");
16444
- const candidates = isAbsolute3(command) || command.includes("/") ? [resolve4(cwd, command)] : searchPath.split(delimiter2).map((dir) => resolve4(cwd, dir, command));
16642
+ const candidates = isAbsolute3(command) || command.includes("/") ? [resolve3(cwd, command)] : searchPath.split(delimiter2).map((dir) => resolve3(cwd, dir, command));
16445
16643
  for (const candidate of candidates) {
16446
16644
  try {
16447
16645
  await access(candidate, constants.X_OK);
@@ -16633,7 +16831,7 @@ ${paths.join("\n")}`
16633
16831
  }
16634
16832
  async function appendPiSessionCustomEntry(authority, principal, customType, data) {
16635
16833
  const { sessionFile } = authority.decode(principal);
16636
- const text = await readFile3(sessionFile, "utf8");
16834
+ const text = await readFile4(sessionFile, "utf8");
16637
16835
  let parentId = null;
16638
16836
  for (const line2 of text.trim().split("\n").filter(Boolean)) {
16639
16837
  const entry = JSON.parse(line2);
@@ -16683,48 +16881,12 @@ var init_role_turn_host = __esm({
16683
16881
  }
16684
16882
  });
16685
16883
 
16686
- // src/run-ticket-number.ts
16687
- import { readFile as readFile4 } from "node:fs/promises";
16688
- import { join as join9 } from "node:path";
16689
- function isEnoent(error) {
16690
- return error instanceof Error && "code" in error && error.code === "ENOENT";
16691
- }
16692
- function ticketFromRecord(record4) {
16693
- const ticketNumber = record4.ticketNumber;
16694
- if (typeof ticketNumber === "number" && Number.isSafeInteger(ticketNumber) && ticketNumber >= 1) {
16695
- return ticketNumber;
16696
- }
16697
- return void 0;
16698
- }
16699
- async function readPageTicketNumber(runDirectory, page) {
16700
- try {
16701
- const raw = JSON.parse(await readFile4(join9(runDirectory, page), "utf8"));
16702
- if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
16703
- return void 0;
16704
- }
16705
- return ticketFromRecord(raw);
16706
- } catch (error) {
16707
- if (isEnoent(error)) return void 0;
16708
- throw error;
16709
- }
16710
- }
16711
- async function readRunTicketNumber(runDirectory) {
16712
- return await readPageTicketNumber(runDirectory, "admitted-request.json") ?? await readPageTicketNumber(runDirectory, "invocation.json");
16713
- }
16714
- var init_run_ticket_number = __esm({
16715
- "src/run-ticket-number.ts"() {
16716
- "use strict";
16717
- }
16718
- });
16719
-
16720
- // src/sha256.ts
16721
- import { createHash as createHash2 } from "node:crypto";
16722
- function sha256Hex(bytes) {
16723
- return createHash2("sha256").update(bytes).digest("hex");
16724
- }
16725
- var init_sha256 = __esm({
16726
- "src/sha256.ts"() {
16884
+ // src/auditor-dossier-tool.ts
16885
+ var init_auditor_dossier_tool = __esm({
16886
+ "src/auditor-dossier-tool.ts"() {
16727
16887
  "use strict";
16888
+ init_role_run_placement();
16889
+ init_build();
16728
16890
  }
16729
16891
  });
16730
16892
 
@@ -16754,6 +16916,402 @@ var init_submission_errors = __esm({
16754
16916
  }
16755
16917
  });
16756
16918
 
16919
+ // src/gatekeeper-role.ts
16920
+ var init_gatekeeper_role = __esm({
16921
+ "src/gatekeeper-role.ts"() {
16922
+ "use strict";
16923
+ init_auditor_dossier_tool();
16924
+ init_submission_errors();
16925
+ init_inspector_contracts();
16926
+ init_gatekeeper_output();
16927
+ init_submission_errors();
16928
+ }
16929
+ });
16930
+
16931
+ // src/compliance-transport.ts
16932
+ var AUDITOR_PARENT_ATTEMPT_BINDING_ENTRY_TYPE, AUDITOR_COMPLIANCE_FAILURE_ENTRY_TYPE;
16933
+ var init_compliance_transport = __esm({
16934
+ "src/compliance-transport.ts"() {
16935
+ "use strict";
16936
+ init_auditor_dossier_tool();
16937
+ init_gatekeeper_role();
16938
+ AUDITOR_PARENT_ATTEMPT_BINDING_ENTRY_TYPE = "ak_auditor_parent_attempt_binding";
16939
+ AUDITOR_COMPLIANCE_FAILURE_ENTRY_TYPE = "ak_auditor_compliance_failure";
16940
+ }
16941
+ });
16942
+
16943
+ // src/role-run-relocation.ts
16944
+ import { existsSync as existsSync5 } from "node:fs";
16945
+ import { readdir as readdir2, readFile as readFile5, writeFile as writeFile2 } from "node:fs/promises";
16946
+ import { join as join11, sep as sep2 } from "node:path";
16947
+ function isEnoent2(error) {
16948
+ return error instanceof Error && "code" in error && error.code === "ENOENT";
16949
+ }
16950
+ function rewriteRunDirectoryPathValue(value, oldRunDirectory, newRunDirectory) {
16951
+ if (typeof value !== "string") return value;
16952
+ if (value === oldRunDirectory) return newRunDirectory;
16953
+ const prefix = `${oldRunDirectory}${sep2}`;
16954
+ if (value.startsWith(prefix)) {
16955
+ return `${newRunDirectory}${value.slice(oldRunDirectory.length)}`;
16956
+ }
16957
+ return value;
16958
+ }
16959
+ function rewriteRunDirectoryPathValueAgainstRewrites(value, rewrites) {
16960
+ if (typeof value !== "string" || rewrites.length === 0) return value;
16961
+ let best;
16962
+ for (const rewrite of rewrites) {
16963
+ if (value === rewrite.oldRunDirectory || value.startsWith(`${rewrite.oldRunDirectory}${sep2}`)) {
16964
+ if (best === void 0 || rewrite.oldRunDirectory.length > best.oldRunDirectory.length) {
16965
+ best = rewrite;
16966
+ }
16967
+ }
16968
+ }
16969
+ if (best === void 0) return value;
16970
+ return rewriteRunDirectoryPathValue(
16971
+ value,
16972
+ best.oldRunDirectory,
16973
+ best.newRunDirectory
16974
+ );
16975
+ }
16976
+ function rewriteRunDirectoryPathFields(record4, fields, oldRunDirectory, newRunDirectory) {
16977
+ rewriteRunDirectoryPathFieldsAgainstRewrites(record4, fields, [
16978
+ { oldRunDirectory, newRunDirectory }
16979
+ ]);
16980
+ }
16981
+ function rewriteRunDirectoryPathFieldsAgainstRewrites(record4, fields, rewrites) {
16982
+ for (const field of fields) {
16983
+ if (field in record4) {
16984
+ record4[field] = rewriteRunDirectoryPathValueAgainstRewrites(
16985
+ record4[field],
16986
+ rewrites
16987
+ );
16988
+ }
16989
+ }
16990
+ }
16991
+ function collectRewrites(input) {
16992
+ const own = {
16993
+ oldRunDirectory: input.oldRunDirectory,
16994
+ newRunDirectory: input.newRunDirectory
16995
+ };
16996
+ if (input.crossRunRewrites === void 0 || input.crossRunRewrites.length === 0) {
16997
+ return [own];
16998
+ }
16999
+ const seen = /* @__PURE__ */ new Set([own.oldRunDirectory]);
17000
+ const out = [own];
17001
+ for (const rewrite of input.crossRunRewrites) {
17002
+ if (seen.has(rewrite.oldRunDirectory)) continue;
17003
+ seen.add(rewrite.oldRunDirectory);
17004
+ out.push(rewrite);
17005
+ }
17006
+ return out;
17007
+ }
17008
+ function isPlainObject(value) {
17009
+ return value !== null && typeof value === "object" && !Array.isArray(value);
17010
+ }
17011
+ function rewriteSourceRunLocator(value, rewrites) {
17012
+ if (!isPlainObject(value)) return;
17013
+ rewriteRunDirectoryPathFieldsAgainstRewrites(
17014
+ value,
17015
+ SOURCE_RUN_LOCATOR_FIELDS,
17016
+ rewrites
17017
+ );
17018
+ }
17019
+ function rewriteSummonsMaterials(value, rewrites) {
17020
+ if (!isPlainObject(value)) return;
17021
+ rewriteRunDirectoryPathFieldsAgainstRewrites(
17022
+ value,
17023
+ SUMMONS_PATH_FIELDS,
17024
+ rewrites
17025
+ );
17026
+ rewriteSourceRunLocator(value.sourceRun, rewrites);
17027
+ if (Array.isArray(value.attachmentPaths)) {
17028
+ value.attachmentPaths = value.attachmentPaths.map(
17029
+ (path) => rewriteRunDirectoryPathValueAgainstRewrites(path, rewrites)
17030
+ );
17031
+ }
17032
+ }
17033
+ async function rewriteJsonObjectFile(path, fields, rewrites) {
17034
+ if (!existsSync5(path)) return;
17035
+ const page = JSON.parse(await readFile5(path, "utf8"));
17036
+ if (!isPlainObject(page)) return;
17037
+ rewriteRunDirectoryPathFieldsAgainstRewrites(page, fields, rewrites);
17038
+ await writeFile2(path, `${JSON.stringify(page, null, 2)}
17039
+ `, "utf8");
17040
+ }
17041
+ async function rewriteOfficerPointerFile(path, rewrites) {
17042
+ if (!existsSync5(path)) return;
17043
+ const page = JSON.parse(await readFile5(path, "utf8"));
17044
+ if (!isPlainObject(page)) return;
17045
+ if (page.kind !== "direct-officer-run-pointer") return;
17046
+ rewriteRunDirectoryPathFieldsAgainstRewrites(
17047
+ page,
17048
+ OFFICER_POINTER_FIELDS,
17049
+ rewrites
17050
+ );
17051
+ await writeFile2(path, `${JSON.stringify(page)}
17052
+ `, "utf8");
17053
+ }
17054
+ async function rewriteSitianRecordsJsonl(path, rewrites) {
17055
+ if (!existsSync5(path)) return;
17056
+ const raw = await readFile5(path, "utf8");
17057
+ if (raw.length === 0) return;
17058
+ const endsWithNewline = raw.endsWith("\n");
17059
+ const lines = raw.split("\n");
17060
+ let changed = false;
17061
+ const out = [];
17062
+ for (let i = 0; i < lines.length; i += 1) {
17063
+ const line2 = lines[i];
17064
+ if (line2 === "" && i === lines.length - 1 && endsWithNewline) {
17065
+ out.push("");
17066
+ continue;
17067
+ }
17068
+ if (line2.trim() === "") {
17069
+ out.push(line2);
17070
+ continue;
17071
+ }
17072
+ let parsed;
17073
+ try {
17074
+ parsed = JSON.parse(line2);
17075
+ } catch {
17076
+ out.push(line2);
17077
+ continue;
17078
+ }
17079
+ if (!isPlainObject(parsed)) {
17080
+ out.push(line2);
17081
+ continue;
17082
+ }
17083
+ if (!("sessionParent" in parsed)) {
17084
+ out.push(line2);
17085
+ continue;
17086
+ }
17087
+ const before = parsed.sessionParent;
17088
+ rewriteRunDirectoryPathFieldsAgainstRewrites(
17089
+ parsed,
17090
+ SITIAN_RECORD_FIELDS,
17091
+ rewrites
17092
+ );
17093
+ if (parsed.sessionParent !== before) changed = true;
17094
+ out.push(JSON.stringify(parsed));
17095
+ }
17096
+ if (!changed) return;
17097
+ const body = out.join("\n");
17098
+ await writeFile2(
17099
+ path,
17100
+ endsWithNewline && !body.endsWith("\n") ? `${body}
17101
+ ` : body,
17102
+ "utf8"
17103
+ );
17104
+ }
17105
+ async function rewriteSessionTranscriptBindings(path, rewrites) {
17106
+ if (!existsSync5(path)) return;
17107
+ const raw = await readFile5(path, "utf8");
17108
+ if (raw.length === 0) return;
17109
+ const endsWithNewline = raw.endsWith("\n");
17110
+ const lines = raw.split("\n");
17111
+ let changed = false;
17112
+ const out = [];
17113
+ for (let i = 0; i < lines.length; i += 1) {
17114
+ const line2 = lines[i];
17115
+ if (line2 === "" && i === lines.length - 1 && endsWithNewline) {
17116
+ out.push("");
17117
+ continue;
17118
+ }
17119
+ if (line2.trim() === "") {
17120
+ out.push(line2);
17121
+ continue;
17122
+ }
17123
+ let parsed;
17124
+ try {
17125
+ parsed = JSON.parse(line2);
17126
+ } catch {
17127
+ out.push(line2);
17128
+ continue;
17129
+ }
17130
+ if (!isPlainObject(parsed)) {
17131
+ out.push(line2);
17132
+ continue;
17133
+ }
17134
+ let lineChanged = false;
17135
+ if (parsed.type === "session" && "parentSession" in parsed) {
17136
+ const before = parsed.parentSession;
17137
+ rewriteRunDirectoryPathFieldsAgainstRewrites(
17138
+ parsed,
17139
+ SESSION_HEADER_FIELDS,
17140
+ rewrites
17141
+ );
17142
+ if (parsed.parentSession !== before) lineChanged = true;
17143
+ } else if (parsed.type === "custom" && parsed.customType === AUDITOR_PARENT_ATTEMPT_BINDING_ENTRY_TYPE && isPlainObject(parsed.data) && isPlainObject(parsed.data.parent)) {
17144
+ const parent = parsed.data.parent;
17145
+ const before = parent.sessionFile;
17146
+ rewriteRunDirectoryPathFieldsAgainstRewrites(
17147
+ parent,
17148
+ BINDING_PARENT_FIELDS,
17149
+ rewrites
17150
+ );
17151
+ if (parent.sessionFile !== before) lineChanged = true;
17152
+ }
17153
+ if (lineChanged) changed = true;
17154
+ out.push(lineChanged ? JSON.stringify(parsed) : line2);
17155
+ }
17156
+ if (!changed) return;
17157
+ const body = out.join("\n");
17158
+ await writeFile2(
17159
+ path,
17160
+ endsWithNewline && !body.endsWith("\n") ? `${body}
17161
+ ` : body,
17162
+ "utf8"
17163
+ );
17164
+ }
17165
+ async function rewriteNestedMachinePathPages(pagesDirectory, rewrites) {
17166
+ const sessionRoot = join11(pagesDirectory, "session");
17167
+ async function walk(directory) {
17168
+ let entries;
17169
+ try {
17170
+ entries = await readdir2(directory, { withFileTypes: true });
17171
+ } catch (error) {
17172
+ if (isEnoent2(error)) return;
17173
+ throw error;
17174
+ }
17175
+ for (const entry of entries) {
17176
+ const path = join11(directory, entry.name);
17177
+ if (entry.isDirectory()) {
17178
+ await walk(path);
17179
+ continue;
17180
+ }
17181
+ if (!entry.isFile()) continue;
17182
+ if (entry.name === "current-session.json") {
17183
+ await rewriteJsonObjectFile(path, CURRENT_SESSION_FIELDS, rewrites);
17184
+ } else if (entry.name.endsWith(".pointer.json")) {
17185
+ await rewriteOfficerPointerFile(path, rewrites);
17186
+ } else if (entry.name === "records.jsonl") {
17187
+ await rewriteSitianRecordsJsonl(path, rewrites);
17188
+ } else if (entry.name.endsWith(".jsonl")) {
17189
+ await rewriteSessionTranscriptBindings(path, rewrites);
17190
+ }
17191
+ }
17192
+ }
17193
+ await walk(sessionRoot);
17194
+ }
17195
+ async function rewriteRoleRunDurablePages(input) {
17196
+ const { pagesDirectory } = input;
17197
+ const rewrites = collectRewrites(input);
17198
+ const admittedPath = join11(pagesDirectory, "admitted-request.json");
17199
+ if (existsSync5(admittedPath)) {
17200
+ const page = JSON.parse(await readFile5(admittedPath, "utf8"));
17201
+ rewriteRunDirectoryPathFieldsAgainstRewrites(
17202
+ page,
17203
+ ADMITTED_PAGE_FIELDS,
17204
+ rewrites
17205
+ );
17206
+ rewriteSourceRunLocator(page.sourceRun, rewrites);
17207
+ if (Array.isArray(page.attachments)) {
17208
+ for (const attachment of page.attachments) {
17209
+ if (isPlainObject(attachment)) {
17210
+ rewriteRunDirectoryPathFieldsAgainstRewrites(
17211
+ attachment,
17212
+ ["frozenPath"],
17213
+ rewrites
17214
+ );
17215
+ }
17216
+ }
17217
+ }
17218
+ if (isPlainObject(page.principal)) {
17219
+ rewriteRunDirectoryPathFieldsAgainstRewrites(
17220
+ page.principal,
17221
+ ["sessionDirectory", "sessionFile"],
17222
+ rewrites
17223
+ );
17224
+ }
17225
+ await writeFile2(admittedPath, `${JSON.stringify(page, null, 2)}
17226
+ `, "utf8");
17227
+ }
17228
+ const invocationPath = join11(pagesDirectory, "invocation.json");
17229
+ if (existsSync5(invocationPath)) {
17230
+ const page = JSON.parse(await readFile5(invocationPath, "utf8"));
17231
+ rewriteRunDirectoryPathFieldsAgainstRewrites(
17232
+ page,
17233
+ INVOCATION_PAGE_FIELDS,
17234
+ rewrites
17235
+ );
17236
+ await writeFile2(
17237
+ invocationPath,
17238
+ `${JSON.stringify(page, null, 2)}
17239
+ `,
17240
+ "utf8"
17241
+ );
17242
+ }
17243
+ const statePath = join11(pagesDirectory, "run-state.json");
17244
+ if (existsSync5(statePath)) {
17245
+ const page = JSON.parse(await readFile5(statePath, "utf8"));
17246
+ rewriteRunDirectoryPathFieldsAgainstRewrites(
17247
+ page,
17248
+ RUN_STATE_PAGE_FIELDS,
17249
+ rewrites
17250
+ );
17251
+ if (isPlainObject(page.principal)) {
17252
+ rewriteRunDirectoryPathFieldsAgainstRewrites(
17253
+ page.principal,
17254
+ ["sessionDirectory", "sessionFile"],
17255
+ rewrites
17256
+ );
17257
+ }
17258
+ if (isPlainObject(page.currentCourt)) {
17259
+ rewriteSummonsMaterials(page.currentCourt.summons, rewrites);
17260
+ }
17261
+ await writeFile2(statePath, `${JSON.stringify(page, null, 2)}
17262
+ `, "utf8");
17263
+ }
17264
+ await rewriteNestedMachinePathPages(pagesDirectory, rewrites);
17265
+ }
17266
+ var ADMITTED_PAGE_FIELDS, INVOCATION_PAGE_FIELDS, RUN_STATE_PAGE_FIELDS, SOURCE_RUN_LOCATOR_FIELDS, SUMMONS_PATH_FIELDS, CURRENT_SESSION_FIELDS, OFFICER_POINTER_FIELDS, SITIAN_RECORD_FIELDS, SESSION_HEADER_FIELDS, BINDING_PARENT_FIELDS;
17267
+ var init_role_run_relocation = __esm({
17268
+ "src/role-run-relocation.ts"() {
17269
+ "use strict";
17270
+ init_compliance_transport();
17271
+ ADMITTED_PAGE_FIELDS = [
17272
+ "runDirectory",
17273
+ "admittedRequestPath",
17274
+ "sessionDirectory",
17275
+ "sessionFile",
17276
+ "taskPath",
17277
+ "packetPath",
17278
+ "prerequisitesPath",
17279
+ "requestManifestPath",
17280
+ "mergerInputPath",
17281
+ "sourceRunPath"
17282
+ ];
17283
+ INVOCATION_PAGE_FIELDS = [
17284
+ "runDirectory",
17285
+ "sessionDirectory",
17286
+ "sessionFile"
17287
+ ];
17288
+ RUN_STATE_PAGE_FIELDS = [
17289
+ "runDirectory",
17290
+ "admittedRequestPath",
17291
+ "sessionDirectory",
17292
+ "sessionFile"
17293
+ ];
17294
+ SOURCE_RUN_LOCATOR_FIELDS = ["runDirectory"];
17295
+ SUMMONS_PATH_FIELDS = ["sourceRunPath"];
17296
+ CURRENT_SESSION_FIELDS = ["sessionFile"];
17297
+ OFFICER_POINTER_FIELDS = ["sessionFile", "runDirectory"];
17298
+ SITIAN_RECORD_FIELDS = ["sessionParent"];
17299
+ SESSION_HEADER_FIELDS = ["parentSession"];
17300
+ BINDING_PARENT_FIELDS = ["sessionFile"];
17301
+ }
17302
+ });
17303
+
17304
+ // src/sha256.ts
17305
+ import { createHash as createHash2 } from "node:crypto";
17306
+ function sha256Hex(bytes) {
17307
+ return createHash2("sha256").update(bytes).digest("hex");
17308
+ }
17309
+ var init_sha256 = __esm({
17310
+ "src/sha256.ts"() {
17311
+ "use strict";
17312
+ }
17313
+ });
17314
+
16757
17315
  // src/submission-correctable-error.ts
16758
17316
  var correctableSubmissionErrorBrand, CorrectableSubmissionError;
16759
17317
  var init_submission_correctable_error = __esm({
@@ -16844,16 +17402,16 @@ var init_terminating_tools = __esm({
16844
17402
  });
16845
17403
 
16846
17404
  // src/doctor-evidence.ts
16847
- import { readdir, readFile as readFile5, realpath as realpath2, stat } from "node:fs/promises";
16848
- import { dirname as dirname7, relative as relative2, resolve as resolve5, sep as sep2 } from "node:path";
17405
+ import { readdir as readdir3, readFile as readFile6, realpath as realpath2, stat } from "node:fs/promises";
17406
+ import { dirname as dirname7, relative as relative2, resolve as resolve4, sep as sep3 } from "node:path";
16849
17407
  function record2(value) {
16850
17408
  return typeof value === "object" && value !== null && !Array.isArray(value);
16851
17409
  }
16852
17410
  async function discoverCaseFiles(root) {
16853
17411
  const found = [];
16854
17412
  async function walk(dir, depth) {
16855
- for (const item of await readdir(dir, { withFileTypes: true })) {
16856
- const path = resolve5(dir, item.name);
17413
+ for (const item of await readdir3(dir, { withFileTypes: true })) {
17414
+ const path = resolve4(dir, item.name);
16857
17415
  if (item.isDirectory()) {
16858
17416
  await walk(path, depth + 1);
16859
17417
  } else if (item.isFile() && (item.name.endsWith(".jsonl") || item.name === "stderr.log" && depth === 1)) found.push(path);
@@ -16872,17 +17430,17 @@ function accumulate(metric, value, source) {
16872
17430
  function timestamp(row) {
16873
17431
  return typeof row.timestamp === "string" && Number.isFinite(Date.parse(row.timestamp)) ? row.timestamp : void 0;
16874
17432
  }
16875
- function isMissingPathError(error) {
17433
+ function isMissingPathError2(error) {
16876
17434
  return error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR");
16877
17435
  }
16878
17436
  async function stableRunsIdentity(root) {
16879
17437
  let cursor = root;
16880
17438
  while (true) {
16881
17439
  try {
16882
- const git2 = await stat(resolve5(cursor, ".git"));
16883
- if (git2.isDirectory() || git2.isFile()) return relative2(cursor, root).split(sep2).join("/");
17440
+ const git2 = await stat(resolve4(cursor, ".git"));
17441
+ if (git2.isDirectory() || git2.isFile()) return relative2(cursor, root).split(sep3).join("/");
16884
17442
  } catch (error) {
16885
- if (!isMissingPathError(error)) throw error;
17443
+ if (!isMissingPathError2(error)) throw error;
16886
17444
  }
16887
17445
  const parent = dirname7(cursor);
16888
17446
  if (parent === cursor) return root;
@@ -16954,13 +17512,13 @@ function deriveSession(content, id) {
16954
17512
  }
16955
17513
  async function loadDoctorCase(runsPath) {
16956
17514
  const root = await realpath2(runsPath);
16957
- const match = root.split(sep2).join("/").match(/\/\.ak-roles\/books\/[^/]+\/issues\/([1-9]\d*)\/runs$/);
16958
- if (!match) throw new Error("Doctor case must be an .ak-roles/books/<book>/issues/<n>/runs directory");
17515
+ const match = root.split(sep3).join("/").match(/\/\.ak-roles\/books\/[^/]+\/(?:issues\/)?([1-9]\d*)\/runs$/);
17516
+ if (!match) throw new Error("Doctor case must be an .ak-roles/books/<book>/<n>/runs directory");
16959
17517
  const evidence = [], sessions = [], statuses = [], commits = [];
16960
17518
  const turns = { count: 0, sources: [] }, calls = { count: 0, sources: [] }, tokens = { count: 0, sources: [] };
16961
17519
  for (const path of await discoverCaseFiles(root)) {
16962
- const id = relative2(root, path).split(sep2).join("/");
16963
- const bytes = await readFile5(path);
17520
+ const id = relative2(root, path).split(sep3).join("/");
17521
+ const bytes = await readFile6(path);
16964
17522
  const content = bytes.toString("utf8");
16965
17523
  const kind = id.endsWith(".jsonl") ? "session" : "stderr";
16966
17524
  evidence.push({ id, kind, byteLength: bytes.byteLength, contentLength: content.length, sha256: sha256Hex(bytes), content });
@@ -16973,7 +17531,7 @@ async function loadDoctorCase(runsPath) {
16973
17531
  accumulate(calls, result2.calls, id);
16974
17532
  accumulate(tokens, result2.tokens, id);
16975
17533
  }
16976
- const runDirs = (await readdir(root, { withFileTypes: true })).filter((item) => item.isDirectory()).map((item) => item.name).sort();
17534
+ const runDirs = (await readdir3(root, { withFileTypes: true })).filter((item) => item.isDirectory()).map((item) => item.name).sort();
16977
17535
  const legs = evidence.filter((entry) => entry.kind === "session").map((entry) => entry.id);
16978
17536
  const retryDirs = runDirs.filter((name) => /(?:^|[-_])retry(?:[-_]|$)/i.test(name));
16979
17537
  const rawBytes = evidence.filter((entry) => entry.kind === "session").reduce((sum, entry) => sum + entry.byteLength, 0);
@@ -16990,7 +17548,7 @@ var init_doctor_evidence = __esm({
16990
17548
 
16991
17549
  // src/collector-config.ts
16992
17550
  import { createHash as createHash3 } from "node:crypto";
16993
- import { readFile as readFile6 } from "node:fs/promises";
17551
+ import { readFile as readFile7 } from "node:fs/promises";
16994
17552
  function fail3(message, cause) {
16995
17553
  throw new Error(message, cause === void 0 ? void 0 : { cause });
16996
17554
  }
@@ -17033,7 +17591,7 @@ function emptyCollectorManifest() {
17033
17591
  async function loadCollectorManifest(path) {
17034
17592
  let bytes;
17035
17593
  try {
17036
- bytes = await readFile6(path);
17594
+ bytes = await readFile7(path);
17037
17595
  } catch (error) {
17038
17596
  fail3(`Collector request manifest is unreadable at ${path}`, error);
17039
17597
  }
@@ -17137,7 +17695,7 @@ async function listPullRequestNumbersByCommit(runner, input) {
17137
17695
  function createGhApiRunner(options = {}) {
17138
17696
  const spawnImpl = options.spawnImpl ?? spawn2;
17139
17697
  return async (args, runOptions = {}) => {
17140
- return await new Promise((resolve11, reject) => {
17698
+ return await new Promise((resolve10, reject) => {
17141
17699
  const signal = runOptions.signal;
17142
17700
  if (signal?.aborted) {
17143
17701
  reject(signal.reason ?? new Error("aborted"));
@@ -17210,11 +17768,11 @@ function createGhApiRunner(options = {}) {
17210
17768
  const value = line2.slice(idx + 1).trim();
17211
17769
  headers[name] = value;
17212
17770
  }
17213
- resolve11({ status, headers, bodyText });
17771
+ resolve10({ status, headers, bodyText });
17214
17772
  return;
17215
17773
  }
17216
17774
  if (code === 0) {
17217
- resolve11({ status: 200, headers: {}, bodyText: stdout });
17775
+ resolve10({ status: 200, headers: {}, bodyText: stdout });
17218
17776
  return;
17219
17777
  }
17220
17778
  const failure = new Error(
@@ -17424,9 +17982,9 @@ var init_git_object_id = __esm({
17424
17982
 
17425
17983
  // src/merger-git-state.ts
17426
17984
  import { execFile as execFile2 } from "node:child_process";
17427
- import { access as access2, readFile as readFile7 } from "node:fs/promises";
17985
+ import { access as access2, readFile as readFile8 } from "node:fs/promises";
17428
17986
  import { constants as fsConstants } from "node:fs";
17429
- import { isAbsolute as isAbsolute4, resolve as resolve6 } from "node:path";
17987
+ import { isAbsolute as isAbsolute4, resolve as resolve5 } from "node:path";
17430
17988
  import { promisify as promisify2 } from "node:util";
17431
17989
  async function git(cwd, args) {
17432
17990
  const { stdout } = await execFileAsync2("git", args, { cwd, encoding: "buffer", maxBuffer: 16 * 1024 * 1024 });
@@ -17491,10 +18049,10 @@ function createProductionMergerGitState(repositoryRoot = process.cwd()) {
17491
18049
  await requireInsideWorkTree(repositoryRoot);
17492
18050
  const targetObjectId = await resolveHeadMaterial(repositoryRoot);
17493
18051
  const mergeHeadReported = line(await git(repositoryRoot, ["rev-parse", "--git-path", "MERGE_HEAD"]), "Git MERGE_HEAD path");
17494
- const mergeHeadPath = isAbsolute4(mergeHeadReported) ? mergeHeadReported : resolve6(repositoryRoot, mergeHeadReported);
18052
+ const mergeHeadPath = isAbsolute4(mergeHeadReported) ? mergeHeadReported : resolve5(repositoryRoot, mergeHeadReported);
17495
18053
  let sourceObjectId = "";
17496
18054
  if (await pathExists(mergeHeadPath)) {
17497
- const raw = exactUtf8(await readFile7(mergeHeadPath), "Git MERGE_HEAD");
18055
+ const raw = exactUtf8(await readFile8(mergeHeadPath), "Git MERGE_HEAD");
17498
18056
  const mergeHeads = raw.trim().split(/\r?\n/).map((row) => row.trim()).filter(Boolean);
17499
18057
  if (mergeHeads.length === 0) throw new Error("Git MERGE_HEAD is empty");
17500
18058
  if (mergeHeads.length !== 1) throw new Error("Assigned repository does not have one ordinary in-progress merge");
@@ -17546,10 +18104,10 @@ var init_uuidv7 = __esm({
17546
18104
  });
17547
18105
 
17548
18106
  // src/typed-provider-http.ts
17549
- import { readFile as readFile8, unlink, writeFile as writeFile2 } from "node:fs/promises";
17550
- import { join as join10 } from "node:path";
18107
+ import { readFile as readFile9, unlink, writeFile as writeFile3 } from "node:fs/promises";
18108
+ import { join as join12 } from "node:path";
17551
18109
  function typedProviderHttpPath(runDirectory) {
17552
- return join10(runDirectory, TYPED_HTTP_FILE);
18110
+ return join12(runDirectory, TYPED_HTTP_FILE);
17553
18111
  }
17554
18112
  async function clearTypedProviderHttpObservation(runDirectory) {
17555
18113
  try {
@@ -17564,7 +18122,7 @@ async function clearTypedProviderHttpObservation(runDirectory) {
17564
18122
  async function readLatestTypedProviderHttpObservation(runDirectory) {
17565
18123
  let text;
17566
18124
  try {
17567
- text = await readFile8(typedProviderHttpPath(runDirectory), "utf8");
18125
+ text = await readFile9(typedProviderHttpPath(runDirectory), "utf8");
17568
18126
  } catch (error) {
17569
18127
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
17570
18128
  return void 0;
@@ -17593,8 +18151,8 @@ var init_typed_provider_http = __esm({
17593
18151
  });
17594
18152
 
17595
18153
  // src/public-cli/run-lifecycle.ts
17596
- import { chmod, open, readdir as readdir2, readFile as readFile9, unlink as unlink2, writeFile as writeFile3 } from "node:fs/promises";
17597
- import { join as join11 } from "node:path";
18154
+ import { chmod, lstat as lstat2, open, readdir as readdir4, readFile as readFile10, unlink as unlink2, writeFile as writeFile4 } from "node:fs/promises";
18155
+ import { basename as basename4, join as join13 } from "node:path";
17598
18156
  function selectResumeContinuationPrompt(message, engineMaterial) {
17599
18157
  const lines = message !== void 0 ? [message] : [];
17600
18158
  return appendEngineSessionMaterial(lines, engineMaterial).join("\n");
@@ -17623,8 +18181,8 @@ function renderResumeCommand(runId) {
17623
18181
  }
17624
18182
  async function writeRoleRunState(runDirectory, record4) {
17625
18183
  const payload = { ...record4, runDirectory };
17626
- await writeFile3(
17627
- join11(runDirectory, RUN_STATE_FILE),
18184
+ await writeFile4(
18185
+ join13(runDirectory, RUN_STATE_FILE),
17628
18186
  `${JSON.stringify(payload, null, 2)}
17629
18187
  `,
17630
18188
  "utf8"
@@ -17674,7 +18232,7 @@ function parseCurrentCourtState(raw) {
17674
18232
  async function readRoleRunStateDisk(runDirectory) {
17675
18233
  let raw;
17676
18234
  try {
17677
- raw = JSON.parse(await readFile9(join11(runDirectory, RUN_STATE_FILE), "utf8"));
18235
+ raw = JSON.parse(await readFile10(join13(runDirectory, RUN_STATE_FILE), "utf8"));
17678
18236
  } catch (error) {
17679
18237
  if (errorCodeOf2(error) === "ENOENT") return void 0;
17680
18238
  throw error;
@@ -17741,8 +18299,8 @@ async function writeRoleRunStateDisk(runDirectory, disk) {
17741
18299
  ...disk.resumable === void 0 ? {} : { resumable: disk.resumable },
17742
18300
  ...disk.currentCourt === void 0 ? {} : { currentCourt: disk.currentCourt }
17743
18301
  };
17744
- await writeFile3(
17745
- join11(runDirectory, RUN_STATE_FILE),
18302
+ await writeFile4(
18303
+ join13(runDirectory, RUN_STATE_FILE),
17746
18304
  `${JSON.stringify(payload, null, 2)}
17747
18305
  `,
17748
18306
  "utf8"
@@ -17909,15 +18467,19 @@ function isProcessAlive(pid) {
17909
18467
  async function autopsyWriterLock(lockPath) {
17910
18468
  let content;
17911
18469
  try {
17912
- content = await readFile9(lockPath, "utf8");
18470
+ content = await readFile10(lockPath, "utf8");
17913
18471
  } catch (error) {
17914
18472
  if (errorCodeOf2(error) === "ENOENT") return { verdict: "absent" };
17915
- return { verdict: "absent", readFailure: error };
18473
+ return { verdict: "unknown", reason: "unreadable", readFailure: error };
17916
18474
  }
17917
18475
  const normalized = content.trim();
17918
- if (!/^[1-9]\d*$/.test(normalized)) return { verdict: "absent" };
18476
+ if (!/^[1-9]\d*$/.test(normalized)) {
18477
+ return { verdict: "unknown", reason: "unparseable", content };
18478
+ }
17919
18479
  const pid = Number.parseInt(normalized, 10);
17920
- if (!Number.isSafeInteger(pid) || pid <= 0) return { verdict: "absent" };
18480
+ if (!Number.isSafeInteger(pid) || pid <= 0) {
18481
+ return { verdict: "unknown", reason: "unparseable", content };
18482
+ }
17921
18483
  return isProcessAlive(pid) ? { verdict: "alive", pid } : { verdict: "dead", pid };
17922
18484
  }
17923
18485
  function describeAutopsy(autopsy) {
@@ -17927,7 +18489,9 @@ function describeAutopsy(autopsy) {
17927
18489
  case "dead":
17928
18490
  return `dead pid ${autopsy.pid}`;
17929
18491
  case "absent":
17930
- return autopsy.readFailure !== void 0 ? "unreadable lock" : "absent or unparseable holder";
18492
+ return "absent holder";
18493
+ case "unknown":
18494
+ return autopsy.reason === "unreadable" ? "unreadable lock" : "unparseable holder";
17931
18495
  }
17932
18496
  }
17933
18497
  async function reclaimStaleWriterLock(lockPath, runDirectory) {
@@ -17954,24 +18518,32 @@ async function createWriterLease(lockPath, runDirectory, reportCleanupFailure) {
17954
18518
  throw error;
17955
18519
  }
17956
18520
  let released = false;
18521
+ let currentRunDirectory = runDirectory;
18522
+ let currentLockPath = lockPath;
17957
18523
  return {
17958
- lockPath,
18524
+ get lockPath() {
18525
+ return currentLockPath;
18526
+ },
18527
+ relocate(nextRunDirectory) {
18528
+ currentRunDirectory = nextRunDirectory;
18529
+ currentLockPath = join13(nextRunDirectory, WRITER_LOCK_FILE);
18530
+ },
17959
18531
  async release() {
17960
18532
  if (released) return;
17961
18533
  released = true;
17962
18534
  await handle.close().catch(() => void 0);
17963
18535
  try {
17964
- await unlink2(lockPath);
18536
+ await unlink2(currentLockPath);
17965
18537
  } catch (error) {
17966
18538
  if (errorCodeOf2(error) === "EACCES") {
17967
18539
  try {
17968
- await chmod(runDirectory, 493);
17969
- await unlink2(lockPath);
18540
+ await chmod(currentRunDirectory, 493);
18541
+ await unlink2(currentLockPath);
17970
18542
  } catch (retryError) {
17971
- reportCleanupFailure(retryError);
18543
+ reportCleanupFailure(retryError, currentLockPath);
17972
18544
  }
17973
18545
  } else {
17974
- reportCleanupFailure(error);
18546
+ reportCleanupFailure(error, currentLockPath);
17975
18547
  }
17976
18548
  }
17977
18549
  }
@@ -17986,17 +18558,17 @@ async function acquireRunWriterLease(runDirectory, onCleanupFailure) {
17986
18558
  } catch {
17987
18559
  }
17988
18560
  };
17989
- const reportCleanupFailure = (error) => {
18561
+ const reportCleanupFailure = (error, lockPath2) => {
17990
18562
  reportDiagnostic(
17991
- `writer lease lock cleanup failed (release is best-effort; residual lock left in place) at ${join11(runDirectory, WRITER_LOCK_FILE)}: ${describeErrorIdentity(error)}`
18563
+ `writer lease lock cleanup failed (release is best-effort; residual lock left in place) at ${lockPath2}: ${describeErrorIdentity(error)}`
17992
18564
  );
17993
18565
  };
17994
18566
  const reportReadFailure = (error) => {
17995
18567
  reportDiagnostic(
17996
- `writer lease lock read failed (holder liveness unverifiable; lock left in place) at ${join11(runDirectory, WRITER_LOCK_FILE)}: ${describeErrorIdentity(error)}`
18568
+ `writer lease lock read failed (holder liveness unverifiable; lock left in place) at ${join13(runDirectory, WRITER_LOCK_FILE)}: ${describeErrorIdentity(error)}`
17997
18569
  );
17998
18570
  };
17999
- const lockPath = join11(runDirectory, WRITER_LOCK_FILE);
18571
+ const lockPath = join13(runDirectory, WRITER_LOCK_FILE);
18000
18572
  let lastAutopsy = { verdict: "absent" };
18001
18573
  let lastReclaimFailure;
18002
18574
  for (let reclaimsLeft = WRITER_LEASE_RECLAIM_ROUNDS; ; reclaimsLeft -= 1) {
@@ -18006,7 +18578,7 @@ async function acquireRunWriterLease(runDirectory, onCleanupFailure) {
18006
18578
  if (errorCodeOf2(error) !== "EEXIST") throw error;
18007
18579
  }
18008
18580
  lastAutopsy = await autopsyWriterLock(lockPath);
18009
- if (lastAutopsy.verdict === "absent" && lastAutopsy.readFailure !== void 0) {
18581
+ if (lastAutopsy.verdict === "unknown" && lastAutopsy.reason === "unreadable") {
18010
18582
  reportReadFailure(lastAutopsy.readFailure);
18011
18583
  }
18012
18584
  if (lastAutopsy.verdict === "alive") {
@@ -18014,9 +18586,14 @@ async function acquireRunWriterLease(runDirectory, onCleanupFailure) {
18014
18586
  `role run writer lease is already held by live pid ${lastAutopsy.pid} at ${lockPath}`
18015
18587
  );
18016
18588
  }
18589
+ if (lastAutopsy.verdict === "unknown") {
18590
+ throw new RunWriterLeaseHeldError(
18591
+ lastAutopsy.reason === "unreadable" ? `role run writer lease lock is unreadable at ${lockPath}: ${describeErrorIdentity(lastAutopsy.readFailure)}; holder liveness unverifiable, lock left in place` : `role run writer lease lock at ${lockPath} has no verifiable holder pid (empty or unparseable); holder liveness unverifiable, lock left in place`
18592
+ );
18593
+ }
18017
18594
  if (lastAutopsy.verdict === "absent") {
18018
18595
  throw new RunWriterLeaseHeldError(
18019
- lastAutopsy.readFailure !== void 0 ? `role run writer lease lock is unreadable at ${lockPath}: ${describeErrorIdentity(lastAutopsy.readFailure)}; holder liveness unverifiable, lock left in place` : `role run writer lease lock at ${lockPath} has no verifiable holder pid (empty or unparseable); holder liveness unverifiable, lock left in place`
18596
+ `role run writer lease disappeared before holder autopsy at ${lockPath}`
18020
18597
  );
18021
18598
  }
18022
18599
  if (reclaimsLeft <= 0) break;
@@ -18043,31 +18620,40 @@ async function acquireRunWriterLease(runDirectory, onCleanupFailure) {
18043
18620
  lastReclaimFailure !== void 0 ? `role run writer lease stayed contested at ${lockPath} after ${WRITER_LEASE_RECLAIM_ROUNDS} reclaims (last autopsy: ${describeAutopsy(lastAutopsy)}; last reclaim failure: ${describeErrorIdentity(lastReclaimFailure)})` : `role run writer lease stayed contested at ${lockPath} after ${WRITER_LEASE_RECLAIM_ROUNDS} reclaims (last autopsy: ${describeAutopsy(lastAutopsy)})`
18044
18621
  );
18045
18622
  }
18046
- async function findRunDirectoryById(home, runId) {
18623
+ async function findRunDirectoryById(home, runId, onlyBookKey, onlyRole) {
18047
18624
  if (runId.trim() === "") return void 0;
18048
18625
  const ledgerHome = resolveActivationLedgerHome(home);
18049
- const booksRoot = join11(ledgerHome, "books");
18626
+ const booksRoot = join13(ledgerHome, "books");
18050
18627
  let bookKeys;
18051
18628
  try {
18052
- bookKeys = await readdir2(booksRoot);
18053
- } catch {
18054
- return void 0;
18629
+ bookKeys = await readdir4(booksRoot);
18630
+ } catch (error) {
18631
+ if (errorCodeOf2(error) === "ENOENT") return void 0;
18632
+ throw error;
18055
18633
  }
18634
+ const matches = [];
18056
18635
  for (const bookKey of bookKeys) {
18057
- const runsDir = join11(activationBookDirectory(ledgerHome, bookKey), "runs");
18058
- let entries;
18636
+ if (onlyBookKey !== void 0 && bookKey !== onlyBookKey) continue;
18637
+ const bookDir = activationBookDirectory(ledgerHome, bookKey);
18638
+ let runDirectories;
18059
18639
  try {
18060
- entries = await readdir2(runsDir);
18061
- } catch {
18062
- continue;
18640
+ runDirectories = await listBookRunDirectories(bookDir);
18641
+ } catch (error) {
18642
+ if (errorCodeOf2(error) === "ENOENT") continue;
18643
+ throw error;
18063
18644
  }
18064
- for (const entry of entries) {
18065
- if (entry === `${runId}@judge` || entry.startsWith(`${runId}@`)) {
18066
- return join11(runsDir, entry);
18645
+ for (const runDirectory of runDirectories) {
18646
+ const entry = basename4(runDirectory);
18647
+ if (onlyRole === void 0 && (entry === `${runId}@judge` || entry.startsWith(`${runId}@`)) || entry === `${runId}@${onlyRole}`) {
18648
+ matches.push(runDirectory);
18067
18649
  }
18068
18650
  }
18069
18651
  }
18070
- return void 0;
18652
+ if (matches.length === 0) return void 0;
18653
+ if (matches.length === 1) return matches[0];
18654
+ throw new Error(
18655
+ `ambiguous role run id ${runId}: ${matches.join(", ")}`
18656
+ );
18071
18657
  }
18072
18658
  function parentRunPathFromGatePointerInstruction(instruction) {
18073
18659
  if (!instruction.startsWith(GATE_DOSSIER_POINTER_PREFIX)) return void 0;
@@ -18078,7 +18664,7 @@ async function readRunParentPath(runDirectory) {
18078
18664
  let raw;
18079
18665
  try {
18080
18666
  raw = JSON.parse(
18081
- await readFile9(join11(runDirectory, "admitted-request.json"), "utf8")
18667
+ await readFile10(join13(runDirectory, "admitted-request.json"), "utf8")
18082
18668
  );
18083
18669
  } catch (error) {
18084
18670
  if (errorCodeOf2(error) === "ENOENT") return void 0;
@@ -18096,51 +18682,104 @@ async function readRunParentPath(runDirectory) {
18096
18682
  }
18097
18683
  return void 0;
18098
18684
  }
18685
+ async function runHasFormedSessionPrincipal(runDirectory) {
18686
+ const disk = await readRoleRunStateDisk(runDirectory);
18687
+ if (disk === void 0) return false;
18688
+ const sessionFile = typeof disk.principalWire.sessionFile === "string" && disk.principalWire.sessionFile.trim() !== "" ? disk.principalWire.sessionFile : join13(disk.principalWire.sessionDirectory, "session.jsonl");
18689
+ try {
18690
+ const stat2 = await lstat2(sessionFile);
18691
+ return stat2.isFile() && !stat2.isSymbolicLink();
18692
+ } catch (error) {
18693
+ if (errorCodeOf2(error) === "ENOENT") return false;
18694
+ throw error;
18695
+ }
18696
+ }
18099
18697
  async function findLatestRunIdForSeatTicket(input) {
18698
+ if (input.ticketNumber === void 0 && input.parentRunPath === void 0) {
18699
+ return void 0;
18700
+ }
18100
18701
  const ledgerHome = resolveActivationLedgerHome(input.home);
18101
- const runsDir = join11(
18102
- activationBookDirectory(ledgerHome, input.bookKey),
18103
- "runs"
18104
- );
18105
- let entries;
18702
+ const bookDir = activationBookDirectory(ledgerHome, input.bookKey);
18703
+ let runDirectories;
18106
18704
  try {
18107
- entries = await readdir2(runsDir);
18705
+ runDirectories = await listBookRunDirectories(bookDir);
18108
18706
  } catch (error) {
18109
18707
  if (errorCodeOf2(error) === "ENOENT") return void 0;
18110
18708
  throw error;
18111
18709
  }
18112
18710
  const suffix = `@${input.role}`;
18113
18711
  let best;
18114
- for (const entry of entries) {
18712
+ for (const runDirectory of runDirectories) {
18713
+ const entry = basename4(runDirectory);
18115
18714
  if (!entry.endsWith(suffix)) continue;
18116
18715
  const runId = entry.slice(0, entry.length - suffix.length);
18117
18716
  if (runId.length === 0) continue;
18118
- const runDirectory = join11(runsDir, entry);
18119
18717
  if (input.parentRunPath !== void 0) {
18120
18718
  const parentPath = await readRunParentPath(runDirectory);
18121
18719
  if (parentPath !== input.parentRunPath) continue;
18122
18720
  } else if (input.ticketNumber !== void 0) {
18123
- const ticketNumber = await readRunTicketNumber(runDirectory);
18721
+ const ticketNumber = await readBoardTicketNumber(runDirectory);
18124
18722
  if (ticketNumber !== input.ticketNumber) continue;
18125
- } else {
18126
- continue;
18127
18723
  }
18724
+ if (!await runHasFormedSessionPrincipal(runDirectory)) continue;
18128
18725
  if (best === void 0 || runId > best) best = runId;
18129
18726
  }
18130
18727
  return best;
18131
18728
  }
18132
18729
  function parsePersistedTicketIdentity(record4) {
18133
18730
  const correlationId = typeof record4.correlationId === "string" && record4.correlationId.trim() !== "" ? record4.correlationId : void 0;
18134
- const ticketNumber = typeof record4.ticketNumber === "number" && Number.isSafeInteger(record4.ticketNumber) && record4.ticketNumber >= 1 ? record4.ticketNumber : void 0;
18731
+ const ticketNumber = isSafePositiveTicketNumber(record4.ticketNumber) ? record4.ticketNumber : void 0;
18135
18732
  return {
18136
18733
  ...correlationId === void 0 ? {} : { correlationId },
18137
18734
  ...ticketNumber === void 0 ? {} : { ticketNumber }
18138
18735
  };
18139
18736
  }
18737
+ function readDurableCourtTicketNumbersPage(record4, principalTicket, pageLabel) {
18738
+ const interpreted = interpretDurableCourtTicketNumbers(record4, {
18739
+ ...principalTicket === void 0 ? {} : { principalTicket }
18740
+ });
18741
+ if (interpreted.kind === "damage") {
18742
+ return {
18743
+ kind: "damage",
18744
+ reason: `role run ${pageLabel} courtTicketNumbers is damaged: ${interpreted.reason}`
18745
+ };
18746
+ }
18747
+ if (interpreted.kind === "ok") {
18748
+ return { kind: "ok", tickets: interpreted.tickets };
18749
+ }
18750
+ return { kind: "absent" };
18751
+ }
18752
+ function mergeDurableCourtTicketNumbers(input) {
18753
+ const fromAdmitted = input.admittedRecord === void 0 ? { kind: "absent" } : readDurableCourtTicketNumbersPage(
18754
+ input.admittedRecord,
18755
+ input.principalTicket,
18756
+ "admitted-request"
18757
+ );
18758
+ const fromInvocation = input.invocationRecord === void 0 ? { kind: "absent" } : readDurableCourtTicketNumbersPage(
18759
+ input.invocationRecord,
18760
+ input.principalTicket,
18761
+ "invocation"
18762
+ );
18763
+ if (fromAdmitted.kind === "damage") return fromAdmitted;
18764
+ if (fromInvocation.kind === "damage") return fromInvocation;
18765
+ if (fromAdmitted.kind === "ok" && fromInvocation.kind === "ok") {
18766
+ if (!sameCourtTicketNumbers(fromAdmitted.tickets, fromInvocation.tickets)) {
18767
+ return {
18768
+ kind: "damage",
18769
+ reason: "role run courtTicketNumbers differs between admitted-request and invocation"
18770
+ };
18771
+ }
18772
+ return { kind: "ok", tickets: fromAdmitted.tickets };
18773
+ }
18774
+ if (fromAdmitted.kind === "ok") return { kind: "ok", tickets: fromAdmitted.tickets };
18775
+ if (fromInvocation.kind === "ok") return { kind: "ok", tickets: fromInvocation.tickets };
18776
+ return { kind: "ok" };
18777
+ }
18140
18778
  function restoredTicketFields(fields) {
18141
18779
  return {
18142
18780
  ...fields.correlationId === void 0 ? {} : { correlationId: fields.correlationId },
18143
- ...fields.ticketNumber === void 0 ? {} : { ticketNumber: fields.ticketNumber }
18781
+ ...fields.ticketNumber === void 0 ? {} : { ticketNumber: fields.ticketNumber },
18782
+ ...fields.courtTicketNumbers === void 0 ? {} : { courtTicketNumbers: fields.courtTicketNumbers }
18144
18783
  };
18145
18784
  }
18146
18785
  async function loadResumableRunRecord(home, runId, authority) {
@@ -18176,6 +18815,10 @@ async function loadResumableRunRecord(home, runId, authority) {
18176
18815
  let derived;
18177
18816
  let correlationId;
18178
18817
  let ticketNumber;
18818
+ let courtTicketNumbers;
18819
+ let courtTicketNumbersDamage;
18820
+ let admittedIdentityRecord;
18821
+ let invocationIdentityRecord;
18179
18822
  let prNumber;
18180
18823
  let repository;
18181
18824
  let repositoryDisplay;
@@ -18189,7 +18832,7 @@ async function loadResumableRunRecord(home, runId, authority) {
18189
18832
  let sourceRun;
18190
18833
  try {
18191
18834
  const raw = JSON.parse(
18192
- await readFile9(run.admittedRequestPath, "utf8")
18835
+ await readFile10(run.admittedRequestPath, "utf8")
18193
18836
  );
18194
18837
  if (raw !== null && typeof raw === "object" && !Array.isArray(raw)) {
18195
18838
  const record4 = raw;
@@ -18289,6 +18932,7 @@ async function loadResumableRunRecord(home, runId, authority) {
18289
18932
  };
18290
18933
  }
18291
18934
  }
18935
+ admittedIdentityRecord = record4;
18292
18936
  const fromAdmitted = parsePersistedTicketIdentity(record4);
18293
18937
  correlationId = fromAdmitted.correlationId;
18294
18938
  ticketNumber = fromAdmitted.ticketNumber;
@@ -18303,10 +18947,11 @@ async function loadResumableRunRecord(home, runId, authority) {
18303
18947
  let model;
18304
18948
  try {
18305
18949
  const invocationRaw = JSON.parse(
18306
- await readFile9(join11(run.runDirectory, "invocation.json"), "utf8")
18950
+ await readFile10(join13(run.runDirectory, "invocation.json"), "utf8")
18307
18951
  );
18308
18952
  if (invocationRaw !== null && typeof invocationRaw === "object" && !Array.isArray(invocationRaw)) {
18309
18953
  const rec = invocationRaw;
18954
+ invocationIdentityRecord = rec;
18310
18955
  if (typeof rec.provider === "string" && typeof rec.model === "string") {
18311
18956
  model = {
18312
18957
  provider: rec.provider,
@@ -18321,6 +18966,9 @@ async function loadResumableRunRecord(home, runId, authority) {
18321
18966
  }
18322
18967
  }
18323
18968
  } catch (error) {
18969
+ if (error instanceof CliUsageError) {
18970
+ throw error;
18971
+ }
18324
18972
  if (!(error instanceof Error && "code" in error && error.code === "ENOENT")) {
18325
18973
  throw new CliUsageError(
18326
18974
  `role run invocation identity is unreadable: ${runId}`,
@@ -18328,6 +18976,16 @@ async function loadResumableRunRecord(home, runId, authority) {
18328
18976
  );
18329
18977
  }
18330
18978
  }
18979
+ const mergedSet = mergeDurableCourtTicketNumbers({
18980
+ admittedRecord: admittedIdentityRecord,
18981
+ invocationRecord: invocationIdentityRecord,
18982
+ principalTicket: ticketNumber
18983
+ });
18984
+ if (mergedSet.kind === "damage") {
18985
+ courtTicketNumbersDamage = mergedSet.reason;
18986
+ } else if (mergedSet.tickets !== void 0) {
18987
+ courtTicketNumbers = mergedSet.tickets;
18988
+ }
18331
18989
  return {
18332
18990
  run,
18333
18991
  principal,
@@ -18347,6 +19005,8 @@ async function loadResumableRunRecord(home, runId, authority) {
18347
19005
  ...derived === void 0 ? {} : { derived },
18348
19006
  ...correlationId === void 0 ? {} : { correlationId },
18349
19007
  ...ticketNumber === void 0 ? {} : { ticketNumber },
19008
+ ...courtTicketNumbers === void 0 ? {} : { courtTicketNumbers },
19009
+ ...courtTicketNumbersDamage === void 0 ? {} : { courtTicketNumbersDamage },
18350
19010
  ...prNumber === void 0 ? {} : { prNumber },
18351
19011
  ...repository === void 0 ? {} : { repository },
18352
19012
  ...repositoryDisplay === void 0 ? {} : { repositoryDisplay },
@@ -18494,9 +19154,14 @@ async function loadResumableCountersignRun(home, runId, authority) {
18494
19154
  `role run ${runId} belongs to ${loaded.run.role}, not countersign`
18495
19155
  );
18496
19156
  }
19157
+ const base = resumedBaseAdmitted(loaded);
18497
19158
  const admitted = {
18498
19159
  role: "countersign",
18499
- ...resumedBaseAdmitted(loaded)
19160
+ ...base,
19161
+ ...base.courtTicketNumbers === void 0 ? {} : { courtTicketNumbers: base.courtTicketNumbers },
19162
+ ...loaded.admittedFields.courtTicketNumbersDamage === void 0 ? {} : {
19163
+ courtTicketNumbersDamage: loaded.admittedFields.courtTicketNumbersDamage
19164
+ }
18500
19165
  };
18501
19166
  return seatLoadedResult(loaded, admitted);
18502
19167
  }
@@ -18683,11 +19348,13 @@ var init_run_lifecycle = __esm({
18683
19348
  "src/public-cli/run-lifecycle.ts"() {
18684
19349
  "use strict";
18685
19350
  init_activation_ledger_topology();
19351
+ init_role_run_placement();
18686
19352
  init_run_ticket_number();
18687
19353
  init_cli_errors();
18688
19354
  init_typed_provider_http();
18689
19355
  init_typed_provider_http();
18690
19356
  init_collector_config();
19357
+ init_diarist_contracts();
18691
19358
  init_engine_material();
18692
19359
  init_invocation();
18693
19360
  V1_RESUMABLE_PROVIDERS = ["openai-codex", "xai"];
@@ -18714,8 +19381,8 @@ __export(notary_source_run_exports, {
18714
19381
  loadNotarySourceRunLocator: () => loadNotarySourceRunLocator,
18715
19382
  resolveNotarySourceRunLocator: () => resolveNotarySourceRunLocator
18716
19383
  });
18717
- import { dirname as dirname8, isAbsolute as isAbsolute6, join as join12, resolve as resolve7, basename as basename5 } from "node:path";
18718
- import { lstat as lstat2, realpath as realpath3 } from "node:fs/promises";
19384
+ import { dirname as dirname8, isAbsolute as isAbsolute6, join as join14, resolve as resolve6, basename as basename5 } from "node:path";
19385
+ import { lstat as lstat3, realpath as realpath3 } from "node:fs/promises";
18719
19386
  function parseRunDirectoryName(name) {
18720
19387
  const match = RUN_DIR_NAME.exec(name);
18721
19388
  if (match === null) return void 0;
@@ -18733,7 +19400,7 @@ async function requireRunDirectory(candidate, display) {
18733
19400
  }
18734
19401
  let stat2;
18735
19402
  try {
18736
- stat2 = await lstat2(real);
19403
+ stat2 = await lstat3(real);
18737
19404
  } catch (error) {
18738
19405
  throw new NotarySourceRunError(
18739
19406
  `notary --source-run is not a readable run directory: ${display}`,
@@ -18760,19 +19427,20 @@ async function resolveNotarySourceRunLocator(options) {
18760
19427
  }
18761
19428
  const ledgerHome = resolveActivationLedgerHome(options.home);
18762
19429
  const bookKey = resolveBookKeyFromGit(options.projectRoot);
18763
- const bookRunsRoot = join12(activationBookDirectory(ledgerHome, bookKey), "runs");
19430
+ const bookRunsRoot = join14(activationBookDirectory(ledgerHome, bookKey), "runs");
18764
19431
  let candidate;
18765
19432
  const bare = parseRunDirectoryName(raw);
18766
19433
  if (bare !== void 0 && !raw.includes("/") && !raw.includes("\\")) {
18767
- candidate = join12(bookRunsRoot, `${bare.runId}@${bare.role}`);
19434
+ candidate = await findRunDirectoryById(options.home, bare.runId, bookKey, bare.role) ?? join14(bookRunsRoot, `${bare.runId}@${bare.role}`);
18768
19435
  } else {
18769
- candidate = isAbsolute6(raw) ? raw : resolve7(options.projectRoot, raw);
19436
+ candidate = isAbsolute6(raw) ? raw : resolve6(options.projectRoot, raw);
18770
19437
  }
18771
19438
  const real = await requireRunDirectory(candidate, raw);
18772
19439
  const identity = parseRunDirectoryName(basename5(real));
18773
- const runsRootIdentity = physicalPathIdentity(bookRunsRoot);
19440
+ const bookIdentity = physicalPathIdentity(activationBookDirectory(ledgerHome, bookKey));
18774
19441
  const parentIdentity = physicalPathIdentity(dirname8(real));
18775
- if (parentIdentity !== runsRootIdentity) {
19442
+ const subjectBookIdentity = physicalPathIdentity(dirname8(dirname8(dirname8(real))));
19443
+ if (parentIdentity !== physicalPathIdentity(bookRunsRoot) && !(basename5(dirname8(real)) === "runs" && subjectBookIdentity === bookIdentity)) {
18776
19444
  throw new NotarySourceRunError(
18777
19445
  "notary --source-run must resolve to a retained run under the project machine-ledger book"
18778
19446
  );
@@ -19483,8 +20151,8 @@ var init_option_definitions = __esm({
19483
20151
  repeatable: false,
19484
20152
  form: "option",
19485
20153
  description: {
19486
- en: "Optional project-relative .ak-roles/books/<book>/issues/<n>/runs override matching --issue.",
19487
- zh: "\u53EF\u9009\u9879\u76EE\u76F8\u5BF9 .ak-roles/books/<book>/issues/<n>/runs \u8986\u76D6\uFF0C\u4E14\u987B\u5339\u914D --issue\u3002"
20154
+ en: "Optional project-relative .ak-roles/books/<book>/<n>/runs override matching --issue.",
20155
+ zh: "\u53EF\u9009\u9879\u76EE\u76F8\u5BF9 .ak-roles/books/<book>/<n>/runs \u8986\u76D6\uFF0C\u4E14\u987B\u5339\u914D --issue\u3002"
19488
20156
  }
19489
20157
  }
19490
20158
  ];
@@ -19919,6 +20587,7 @@ __export(invocation_exports, {
19919
20587
  admitNotaryInvocation: () => admitNotaryInvocation,
19920
20588
  admitReviewerInvocation: () => admitReviewerInvocation,
19921
20589
  bindAdmittedTicketNumber: () => bindAdmittedTicketNumber,
20590
+ bindCourtTicketNumbersOnAdmitted: () => bindCourtTicketNumbersOnAdmitted,
19922
20591
  bindTicketNumberOnRunDirectory: () => bindTicketNumberOnRunDirectory,
19923
20592
  buildCoderTransportPrompt: () => buildCoderTransportPrompt,
19924
20593
  buildCollectorTransportPrompt: () => buildCollectorTransportPrompt,
@@ -19963,31 +20632,34 @@ __export(invocation_exports, {
19963
20632
  recordEffectiveInvocationModel: () => recordEffectiveInvocationModel,
19964
20633
  recordLaunchedPiIdentity: () => recordLaunchedPiIdentity,
19965
20634
  recordLaunchedRolePackageIdentity: () => recordLaunchedRolePackageIdentity,
20635
+ relocateAdmittedRunToTicket: () => relocateAdmittedRunToTicket,
19966
20636
  requireAuthorityRef: () => requireAuthorityRef,
19967
20637
  resolveDoctorCaseRunsPath: () => resolveDoctorCaseRunsPath,
19968
20638
  resolveGitHubRemoteRepository: () => resolveGitHubRemoteRepository
19969
20639
  });
19970
20640
  import { execFileSync as execFileSync3 } from "node:child_process";
19971
- import { existsSync as existsSync5 } from "node:fs";
20641
+ import { existsSync as existsSync6 } from "node:fs";
19972
20642
  import {
19973
- lstat as lstat3,
19974
- mkdir as mkdir2,
19975
- readFile as readFile10,
20643
+ lstat as lstat4,
20644
+ readFile as readFile11,
19976
20645
  realpath as realpath4,
19977
- writeFile as writeFile4
20646
+ rename,
20647
+ writeFile as writeFile5
19978
20648
  } from "node:fs/promises";
19979
- import { basename as basename6, isAbsolute as isAbsolute7, join as join13, resolve as resolve8, sep as sep3 } from "node:path";
20649
+ import { basename as basename6, dirname as dirname9, isAbsolute as isAbsolute7, join as join15, resolve as resolve7, sep as sep4 } from "node:path";
19980
20650
  function issueAdmissionPlacement(authority, request) {
19981
- const principal = authority.issue(request);
19982
- const { sessionDirectory, sessionFile } = authority.decode(principal);
19983
- const runDirectory = join13(sessionDirectory, "..");
19984
20651
  const ledgerHome = resolveActivationLedgerHome(request.home);
19985
20652
  const bookKey = resolveBookKeyFromGit(request.cwd);
20653
+ const placement = roleRunPlacement(ledgerHome, {
20654
+ bookKey,
20655
+ subject: request.subject,
20656
+ runId: request.runId,
20657
+ role: request.role
20658
+ });
20659
+ ensureRoleRunPlacement(ledgerHome, placement);
19986
20660
  return {
19987
- principal,
19988
- sessionDirectory,
19989
- sessionFile,
19990
- runDirectory,
20661
+ principal: authority.seal(placement),
20662
+ ...placement,
19991
20663
  ledgerHome,
19992
20664
  bookKey
19993
20665
  };
@@ -19999,7 +20671,7 @@ async function writeAdmittedRequestPersistence(admittedRequestPath, body, coordi
19999
20671
  sessionDirectory: coordinates.sessionDirectory,
20000
20672
  sessionFile: coordinates.sessionFile
20001
20673
  };
20002
- await writeFile4(
20674
+ await writeFile5(
20003
20675
  admittedRequestPath,
20004
20676
  `${JSON.stringify(projection, null, 2)}
20005
20677
  `,
@@ -20027,16 +20699,16 @@ async function writeRoleInvocationLedger(source, role, effectiveModel) {
20027
20699
  ...source.ticketNumber === void 0 ? {} : { ticketNumber: source.ticketNumber },
20028
20700
  ...effectiveModelLedgerFields(effectiveModel)
20029
20701
  };
20030
- await writeFile4(
20031
- join13(source.runDirectory, "invocation.json"),
20702
+ await writeFile5(
20703
+ join15(source.runDirectory, "invocation.json"),
20032
20704
  `${JSON.stringify(identity, null, 2)}
20033
20705
  `,
20034
20706
  "utf8"
20035
20707
  );
20036
20708
  }
20037
20709
  async function recordEffectiveInvocationModel(runDirectory, model, engine, host, engineModel) {
20038
- const ledgerPath = join13(runDirectory, "invocation.json");
20039
- const current = JSON.parse(await readFile10(ledgerPath, "utf8"));
20710
+ const ledgerPath = join15(runDirectory, "invocation.json");
20711
+ const current = JSON.parse(await readFile11(ledgerPath, "utf8"));
20040
20712
  const next = { ...current };
20041
20713
  if (model !== void 0) {
20042
20714
  next.provider = model.provider;
@@ -20060,7 +20732,7 @@ async function recordEffectiveInvocationModel(runDirectory, model, engine, host,
20060
20732
  if (host !== void 0) {
20061
20733
  next.host = host;
20062
20734
  }
20063
- await writeFile4(
20735
+ await writeFile5(
20064
20736
  ledgerPath,
20065
20737
  `${JSON.stringify(next, null, 2)}
20066
20738
  `,
@@ -20068,9 +20740,9 @@ async function recordEffectiveInvocationModel(runDirectory, model, engine, host,
20068
20740
  );
20069
20741
  }
20070
20742
  async function mergeInvocationIdentityPage(runDirectory, fields) {
20071
- const ledgerPath = join13(runDirectory, "invocation.json");
20072
- const current = JSON.parse(await readFile10(ledgerPath, "utf8"));
20073
- await writeFile4(
20743
+ const ledgerPath = join15(runDirectory, "invocation.json");
20744
+ const current = JSON.parse(await readFile11(ledgerPath, "utf8"));
20745
+ await writeFile5(
20074
20746
  ledgerPath,
20075
20747
  `${JSON.stringify({
20076
20748
  ...current,
@@ -20085,14 +20757,14 @@ async function persistAdmittedSourceRunPath(admitted, sourceRunPath) {
20085
20757
  throw new Error("persistAdmittedSourceRunPath requires a non-empty sourceRunPath");
20086
20758
  }
20087
20759
  const admittedPath = admitted.admittedRequestPath;
20088
- const current = JSON.parse(await readFile10(admittedPath, "utf8"));
20760
+ const current = JSON.parse(await readFile11(admittedPath, "utf8"));
20089
20761
  if (typeof current.sourceRunPath === "string") {
20090
20762
  if (current.sourceRunPath === sourceRunPath) return;
20091
20763
  throw new Error(
20092
20764
  `persistAdmittedSourceRunPath refuses to replace ${current.sourceRunPath} with ${sourceRunPath}`
20093
20765
  );
20094
20766
  }
20095
- await writeFile4(
20767
+ await writeFile5(
20096
20768
  admittedPath,
20097
20769
  `${JSON.stringify({ ...current, sourceRunPath }, null, 2)}
20098
20770
  `,
@@ -20100,35 +20772,103 @@ async function persistAdmittedSourceRunPath(admitted, sourceRunPath) {
20100
20772
  );
20101
20773
  }
20102
20774
  async function bindAdmittedTicketNumber(admitted, ticketNumber) {
20103
- if (!Number.isSafeInteger(ticketNumber) || ticketNumber < 1) {
20104
- throw new Error(`bindAdmittedTicketNumber requires a safe positive integer, got ${String(ticketNumber)}`);
20105
- }
20106
20775
  if (admitted.ticketNumber !== void 0) {
20107
20776
  if (admitted.ticketNumber === ticketNumber) return;
20108
20777
  throw new Error(
20109
20778
  `bindAdmittedTicketNumber refuses to replace existing ticket #${admitted.ticketNumber} with #${ticketNumber}`
20110
20779
  );
20111
20780
  }
20781
+ await bindTicketNumberOnRunDirectory(admitted.runDirectory, ticketNumber);
20112
20782
  admitted.ticketNumber = ticketNumber;
20113
- await mergeInvocationIdentityPage(admitted.runDirectory, { ticketNumber });
20783
+ }
20784
+ async function bindCourtTicketNumbersOnAdmitted(admitted, courtTicketNumbers) {
20785
+ if (admitted.ticketNumber === void 0) {
20786
+ throw new Error(
20787
+ "bindCourtTicketNumbersOnAdmitted requires a bound principal ticketNumber"
20788
+ );
20789
+ }
20790
+ const principal = requireSafePositiveTicketNumber(
20791
+ admitted.ticketNumber,
20792
+ "bindCourtTicketNumbersOnAdmitted principal ticketNumber"
20793
+ );
20794
+ for (const item of courtTicketNumbers) {
20795
+ if (!isSafePositiveTicketNumber(item)) {
20796
+ throw new Error(
20797
+ `bindCourtTicketNumbersOnAdmitted requires safe positive integers, got ${String(item)}`
20798
+ );
20799
+ }
20800
+ }
20801
+ const projected = projectCourtTicketNumbers(courtTicketNumbers, {
20802
+ principalTicket: principal
20803
+ });
20804
+ if (projected === null || projected.length === 0) {
20805
+ throw new Error("bindCourtTicketNumbersOnAdmitted requires a non-empty ticket set");
20806
+ }
20807
+ const frozen = Object.freeze([...projected]);
20114
20808
  const admittedPath = admitted.admittedRequestPath;
20115
- const current = JSON.parse(await readFile10(admittedPath, "utf8"));
20116
- await writeFile4(
20809
+ const current = JSON.parse(await readFile11(admittedPath, "utf8"));
20810
+ await writeFile5(
20117
20811
  admittedPath,
20118
- `${JSON.stringify({ ...current, ticketNumber }, null, 2)}
20812
+ `${JSON.stringify({ ...current, courtTicketNumbers: frozen }, null, 2)}
20119
20813
  `,
20120
20814
  "utf8"
20121
20815
  );
20816
+ await mergeInvocationIdentityPage(admitted.runDirectory, {
20817
+ courtTicketNumbers: frozen
20818
+ });
20819
+ admitted.courtTicketNumbers = frozen;
20122
20820
  }
20123
- async function bindTicketNumberOnRunDirectory(runDirectory, ticketNumber) {
20124
- if (!Number.isSafeInteger(ticketNumber) || ticketNumber < 1) {
20125
- throw new Error(
20126
- `bindTicketNumberOnRunDirectory requires a safe positive integer, got ${String(ticketNumber)}`
20821
+ async function relocateAdmittedRunToTicket(admitted, authority, heldLease) {
20822
+ if (admitted.ticketNumber === void 0 || !admitted.runDirectory.includes(`${sep4}unbound${sep4}runs${sep4}`)) return;
20823
+ const oldRunDirectory = admitted.runDirectory;
20824
+ const ledgerHome = resolveActivationLedgerHome(homeFromRunDirectory(oldRunDirectory));
20825
+ const target = roleRunPlacement(ledgerHome, {
20826
+ bookKey: admitted.bookKey,
20827
+ subject: { ticketNumber: admitted.ticketNumber },
20828
+ runId: admitted.runId,
20829
+ role: admitted.role
20830
+ });
20831
+ ensureRoleRunDirectory(ledgerHome, dirname9(target.runDirectory));
20832
+ await rename(oldRunDirectory, target.runDirectory);
20833
+ heldLease?.relocate(target.runDirectory);
20834
+ const admittedRecord = admitted;
20835
+ rewriteRunDirectoryPathFields(
20836
+ admittedRecord,
20837
+ [
20838
+ "runDirectory",
20839
+ "admittedRequestPath",
20840
+ "taskPath",
20841
+ "packetPath",
20842
+ "prerequisitesPath",
20843
+ "requestManifestPath",
20844
+ "mergerInputPath"
20845
+ ],
20846
+ oldRunDirectory,
20847
+ target.runDirectory
20848
+ );
20849
+ for (const attachment of admitted.attachments) {
20850
+ attachment.frozenPath = rewriteRunDirectoryPathValue(
20851
+ attachment.frozenPath,
20852
+ oldRunDirectory,
20853
+ target.runDirectory
20127
20854
  );
20128
20855
  }
20129
- const admittedPath = join13(runDirectory, "admitted-request.json");
20130
- const invocationPath = join13(runDirectory, "invocation.json");
20131
- const admitted = JSON.parse(await readFile10(admittedPath, "utf8"));
20856
+ const principal = authority.seal(target);
20857
+ admitted.principal = principal;
20858
+ await rewriteRoleRunDurablePages({
20859
+ pagesDirectory: target.runDirectory,
20860
+ oldRunDirectory,
20861
+ newRunDirectory: target.runDirectory
20862
+ });
20863
+ }
20864
+ async function bindTicketNumberOnRunDirectory(runDirectory, ticketNumber) {
20865
+ requireSafePositiveTicketNumber(
20866
+ ticketNumber,
20867
+ "bindTicketNumberOnRunDirectory"
20868
+ );
20869
+ const admittedPath = join15(runDirectory, "admitted-request.json");
20870
+ const invocationPath = join15(runDirectory, "invocation.json");
20871
+ const admitted = JSON.parse(await readFile11(admittedPath, "utf8"));
20132
20872
  const existing = admitted.ticketNumber;
20133
20873
  if (typeof existing === "number") {
20134
20874
  if (existing === ticketNumber) return;
@@ -20136,9 +20876,9 @@ async function bindTicketNumberOnRunDirectory(runDirectory, ticketNumber) {
20136
20876
  `bindTicketNumberOnRunDirectory refuses to replace existing ticket #${existing} with #${ticketNumber}`
20137
20877
  );
20138
20878
  }
20139
- if (existsSync5(invocationPath)) {
20879
+ if (existsSync6(invocationPath)) {
20140
20880
  const invocation = JSON.parse(
20141
- await readFile10(invocationPath, "utf8")
20881
+ await readFile11(invocationPath, "utf8")
20142
20882
  );
20143
20883
  if (typeof invocation.ticketNumber === "number" && invocation.ticketNumber !== ticketNumber) {
20144
20884
  throw new Error(
@@ -20146,7 +20886,7 @@ async function bindTicketNumberOnRunDirectory(runDirectory, ticketNumber) {
20146
20886
  );
20147
20887
  }
20148
20888
  }
20149
- await writeFile4(
20889
+ await writeFile5(
20150
20890
  admittedPath,
20151
20891
  `${JSON.stringify({ ...admitted, ticketNumber }, null, 2)}
20152
20892
  `,
@@ -20163,7 +20903,7 @@ async function recordLaunchedPiIdentity(runDirectory, identity) {
20163
20903
  async function observeLaunchedRolePackageIdentity(packageRoot2, selectedRoleEntry) {
20164
20904
  const rolePackageRoot = packageRoot2;
20165
20905
  const raw = JSON.parse(
20166
- await readFile10(join13(rolePackageRoot, "package.json"), "utf8")
20906
+ await readFile11(join15(rolePackageRoot, "package.json"), "utf8")
20167
20907
  );
20168
20908
  if (typeof raw.version !== "string" || raw.version.trim() === "") {
20169
20909
  throw new Error(
@@ -20404,10 +21144,10 @@ function parseFixerArgv(args) {
20404
21144
  };
20405
21145
  }
20406
21146
  async function freezeRegularFileAttachment(sourcePath, destinationDir, index) {
20407
- const absolute = isAbsolute7(sourcePath) ? sourcePath : resolve8(sourcePath);
21147
+ const absolute = isAbsolute7(sourcePath) ? sourcePath : resolve7(sourcePath);
20408
21148
  let st;
20409
21149
  try {
20410
- st = await lstat3(absolute);
21150
+ st = await lstat4(absolute);
20411
21151
  } catch (error) {
20412
21152
  throw new CliUsageError(
20413
21153
  `attachment is not a readable regular file: ${sourcePath}`,
@@ -20419,10 +21159,10 @@ async function freezeRegularFileAttachment(sourcePath, destinationDir, index) {
20419
21159
  `attachment must be a regular file (not a directory or symlink): ${sourcePath}`
20420
21160
  );
20421
21161
  }
20422
- const bytes = await readFile10(absolute);
21162
+ const bytes = await readFile11(absolute);
20423
21163
  const name = `${String(index).padStart(2, "0")}-${basename6(absolute)}`;
20424
- const frozenPath = join13(destinationDir, name);
20425
- await writeFile4(frozenPath, bytes);
21164
+ const frozenPath = join15(destinationDir, name);
21165
+ await writeFile5(frozenPath, bytes);
20426
21166
  return {
20427
21167
  attachment: {
20428
21168
  provenancePath: absolute,
@@ -20449,35 +21189,41 @@ async function freezeAttachments(attachmentPaths, attachmentsDirectory) {
20449
21189
  async function freezeAttachmentsIntoRun(attachmentPaths, runDirectory, summonsKey = `s-${Date.now().toString(36)}`) {
20450
21190
  if (attachmentPaths.length === 0) return [];
20451
21191
  const ledgerHome = resolveActivationLedgerHome(homeFromRunDirectory(runDirectory));
20452
- const attachmentsDirectory = join13(runDirectory, "attachments", summonsKey);
21192
+ const attachmentsDirectory = join15(runDirectory, "attachments", summonsKey);
20453
21193
  ensureRealDirectoryTree(ledgerHome, attachmentsDirectory);
20454
21194
  return freezeAttachments(attachmentPaths, attachmentsDirectory);
20455
21195
  }
20456
21196
  function ticketAdmissionFields(ticketNumber) {
20457
- return ticketNumber === void 0 ? {} : { ticketNumber };
21197
+ if (ticketNumber === void 0) return {};
21198
+ return {
21199
+ ticketNumber: requireSafePositiveTicketNumber(
21200
+ ticketNumber,
21201
+ "assertedTicketNumber"
21202
+ )
21203
+ };
20458
21204
  }
20459
21205
  async function admitStandardMaterialInvocation(role, options) {
20460
21206
  if (options.project !== void 0) {
20461
21207
  requireOptionPath("--project", options.project);
20462
21208
  }
20463
- const projectRoot = resolve8(options.project ?? options.cwd);
21209
+ const projectRoot = resolve7(options.project ?? options.cwd);
20464
21210
  const runId = (options.createRunId ?? uuidv7)();
21211
+ const ticketFields = ticketAdmissionFields(options.assertedTicketNumber);
20465
21212
  const {
20466
21213
  principal,
20467
21214
  sessionDirectory,
20468
21215
  sessionFile,
20469
21216
  runDirectory,
21217
+ attachmentsDirectory,
20470
21218
  ledgerHome,
20471
21219
  bookKey
20472
21220
  } = issueAdmissionPlacement(options.principalAuthority, {
20473
21221
  cwd: projectRoot,
20474
21222
  runId,
20475
21223
  role,
21224
+ subject: ticketFields.ticketNumber === void 0 ? { unbound: true } : { ticketNumber: ticketFields.ticketNumber },
20476
21225
  home: options.home
20477
21226
  });
20478
- const attachmentsDirectory = join13(runDirectory, "attachments");
20479
- ensureRealDirectoryTree(ledgerHome, sessionDirectory);
20480
- ensureRealDirectoryTree(ledgerHome, attachmentsDirectory);
20481
21227
  const attachments = await freezeAttachments(options.attachmentPaths, attachmentsDirectory);
20482
21228
  const correlationFields = options.correlationId === void 0 ? {} : { correlationId: options.correlationId };
20483
21229
  const instruction = options.instruction;
@@ -20498,9 +21244,10 @@ async function admitStandardMaterialInvocation(role, options) {
20498
21244
  byteLength: a.byteLength,
20499
21245
  sha256: a.sha256,
20500
21246
  mediaKind: a.mediaKind
20501
- }))
21247
+ })),
21248
+ ...ticketFields
20502
21249
  };
20503
- const admittedRequestPath = join13(runDirectory, "admitted-request.json");
21250
+ const admittedRequestPath = join15(runDirectory, "admitted-request.json");
20504
21251
  await writeAdmittedRequestPersistence(admittedRequestPath, admitted, {
20505
21252
  sessionDirectory,
20506
21253
  sessionFile
@@ -20521,7 +21268,8 @@ async function admitStandardMaterialInvocation(role, options) {
20521
21268
  runDirectory,
20522
21269
  principal,
20523
21270
  admittedRequestPath,
20524
- ...correlationFields
21271
+ ...correlationFields,
21272
+ ...ticketFields
20525
21273
  };
20526
21274
  }
20527
21275
  async function admitJudgeInvocation(options) {
@@ -20563,24 +21311,23 @@ async function admitCountersignInvocation(options) {
20563
21311
  if (options.project !== void 0) {
20564
21312
  requireOptionPath("--project", options.project);
20565
21313
  }
20566
- const projectRoot = resolve8(options.project ?? options.cwd);
21314
+ const projectRoot = resolve7(options.project ?? options.cwd);
20567
21315
  const runId = (options.createRunId ?? uuidv7)();
20568
21316
  const {
20569
21317
  principal,
20570
21318
  sessionDirectory,
20571
21319
  sessionFile,
20572
21320
  runDirectory,
21321
+ attachmentsDirectory,
20573
21322
  ledgerHome,
20574
21323
  bookKey
20575
21324
  } = issueAdmissionPlacement(options.principalAuthority, {
20576
21325
  cwd: projectRoot,
20577
21326
  runId,
20578
21327
  role: "countersign",
21328
+ subject: { unbound: true },
20579
21329
  home: options.home
20580
21330
  });
20581
- const attachmentsDirectory = join13(runDirectory, "attachments");
20582
- ensureRealDirectoryTree(ledgerHome, sessionDirectory);
20583
- ensureRealDirectoryTree(ledgerHome, attachmentsDirectory);
20584
21331
  const attachments = await freezeAttachments(options.attachmentPaths, attachmentsDirectory);
20585
21332
  const instruction = options.instruction;
20586
21333
  const instructionEmpty = instruction.trim() === "";
@@ -20602,7 +21349,7 @@ async function admitCountersignInvocation(options) {
20602
21349
  mediaKind: a.mediaKind
20603
21350
  }))
20604
21351
  };
20605
- const admittedRequestPath = join13(runDirectory, "admitted-request.json");
21352
+ const admittedRequestPath = join15(runDirectory, "admitted-request.json");
20606
21353
  await writeAdmittedRequestPersistence(admittedRequestPath, admitted, {
20607
21354
  sessionDirectory,
20608
21355
  sessionFile
@@ -20628,7 +21375,7 @@ function buildCountersignTransportPrompt(admitted, engineMaterial) {
20628
21375
  async function loadAdmittedJudgeRequest(runDirectory) {
20629
21376
  try {
20630
21377
  const raw = JSON.parse(
20631
- await readFile10(join13(runDirectory, "admitted-request.json"), "utf8")
21378
+ await readFile11(join15(runDirectory, "admitted-request.json"), "utf8")
20632
21379
  );
20633
21380
  if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return void 0;
20634
21381
  const record4 = raw;
@@ -20646,9 +21393,11 @@ async function loadAdmittedJudgeRequest(runDirectory) {
20646
21393
  }
20647
21394
  }
20648
21395
  async function ensureRunArtifactsDir(runDirectory) {
20649
- const dir = join13(runDirectory, "artifacts");
20650
- await mkdir2(dir, { recursive: true });
20651
- return dir;
21396
+ const directory = roleRunArtifactsDirectory(runDirectory);
21397
+ return ensureRoleRunDirectory(
21398
+ resolveActivationLedgerHome(homeFromRunDirectory(runDirectory)),
21399
+ directory
21400
+ );
20652
21401
  }
20653
21402
  async function admitCoderInvocation(options) {
20654
21403
  if (options.project !== void 0) {
@@ -20663,27 +21412,26 @@ async function admitCoderInvocation(options) {
20663
21412
  if (options.phase !== "plan" && options.phase !== "apply") {
20664
21413
  throw new CliUsageError("coder phase must be plan or apply");
20665
21414
  }
20666
- const projectRoot = resolve8(options.project ?? options.cwd);
21415
+ const projectRoot = resolve7(options.project ?? options.cwd);
20667
21416
  const runId = (options.createRunId ?? uuidv7)();
20668
21417
  const {
20669
21418
  principal,
20670
21419
  sessionDirectory,
20671
21420
  sessionFile,
20672
21421
  runDirectory,
21422
+ attachmentsDirectory,
20673
21423
  ledgerHome,
20674
21424
  bookKey
20675
21425
  } = issueAdmissionPlacement(options.principalAuthority, {
20676
21426
  cwd: projectRoot,
20677
21427
  runId,
20678
21428
  role: "coder",
21429
+ subject: { unbound: true },
20679
21430
  home: options.home
20680
21431
  });
20681
- const attachmentsDirectory = join13(runDirectory, "attachments");
20682
- ensureRealDirectoryTree(ledgerHome, sessionDirectory);
20683
- ensureRealDirectoryTree(ledgerHome, attachmentsDirectory);
20684
21432
  const attachments = await freezeAttachments(options.attachmentPaths, attachmentsDirectory);
20685
- const taskPath = join13(runDirectory, "task.md");
20686
- await writeFile4(taskPath, instruction, "utf8");
21433
+ const taskPath = join15(runDirectory, "task.md");
21434
+ await writeFile5(taskPath, instruction, "utf8");
20687
21435
  const admitted = {
20688
21436
  role: "coder",
20689
21437
  phase: options.phase,
@@ -20703,7 +21451,7 @@ async function admitCoderInvocation(options) {
20703
21451
  mediaKind: a.mediaKind
20704
21452
  }))
20705
21453
  };
20706
- const admittedRequestPath = join13(runDirectory, "admitted-request.json");
21454
+ const admittedRequestPath = join15(runDirectory, "admitted-request.json");
20707
21455
  await writeAdmittedRequestPersistence(admittedRequestPath, admitted, {
20708
21456
  sessionDirectory,
20709
21457
  sessionFile
@@ -20751,9 +21499,9 @@ async function admitFixerInvocation(options) {
20751
21499
  let prerequisites = Object.freeze([]);
20752
21500
  let prerequisitesSource;
20753
21501
  if (options.prerequisitesPath !== void 0) {
20754
- const absolutePrereq = isAbsolute7(options.prerequisitesPath) ? options.prerequisitesPath : resolve8(options.prerequisitesPath);
21502
+ const absolutePrereq = isAbsolute7(options.prerequisitesPath) ? options.prerequisitesPath : resolve7(options.prerequisitesPath);
20755
21503
  try {
20756
- prerequisitesSource = await readFile10(absolutePrereq, "utf8");
21504
+ prerequisitesSource = await readFile11(absolutePrereq, "utf8");
20757
21505
  } catch (error) {
20758
21506
  throw new CliUsageError(
20759
21507
  `fixer prerequisites path is unreadable: ${options.prerequisitesPath}`,
@@ -20769,37 +21517,36 @@ async function admitFixerInvocation(options) {
20769
21517
  throw error;
20770
21518
  }
20771
21519
  }
20772
- const projectRoot = resolve8(options.project ?? options.cwd);
21520
+ const projectRoot = resolve7(options.project ?? options.cwd);
20773
21521
  const runId = (options.createRunId ?? uuidv7)();
20774
21522
  const {
20775
21523
  principal,
20776
21524
  sessionDirectory,
20777
21525
  sessionFile,
20778
21526
  runDirectory,
21527
+ attachmentsDirectory,
20779
21528
  ledgerHome,
20780
21529
  bookKey
20781
21530
  } = issueAdmissionPlacement(options.principalAuthority, {
20782
21531
  cwd: projectRoot,
20783
21532
  runId,
20784
21533
  role: "fixer",
21534
+ subject: { unbound: true },
20785
21535
  home: options.home
20786
21536
  });
20787
- const attachmentsDirectory = join13(runDirectory, "attachments");
20788
- ensureRealDirectoryTree(ledgerHome, sessionDirectory);
20789
- ensureRealDirectoryTree(ledgerHome, attachmentsDirectory);
20790
21537
  const attachments = await freezeAttachments(options.attachmentPaths, attachmentsDirectory);
20791
21538
  let prerequisitesPath;
20792
21539
  if (prerequisitesSource !== void 0) {
20793
- prerequisitesPath = join13(runDirectory, "prerequisites.json");
20794
- await writeFile4(
21540
+ prerequisitesPath = join15(runDirectory, "prerequisites.json");
21541
+ await writeFile5(
20795
21542
  prerequisitesPath,
20796
21543
  `${JSON.stringify(prerequisites, null, 2)}
20797
21544
  `,
20798
21545
  "utf8"
20799
21546
  );
20800
21547
  }
20801
- const packetPath = join13(runDirectory, "fix-packet.md");
20802
- await writeFile4(packetPath, instruction, "utf8");
21548
+ const packetPath = join15(runDirectory, "fix-packet.md");
21549
+ await writeFile5(packetPath, instruction, "utf8");
20803
21550
  const admitted = {
20804
21551
  role: "fixer",
20805
21552
  phase: options.phase,
@@ -20824,7 +21571,7 @@ async function admitFixerInvocation(options) {
20824
21571
  mediaKind: a.mediaKind
20825
21572
  }))
20826
21573
  };
20827
- const admittedRequestPath = join13(runDirectory, "admitted-request.json");
21574
+ const admittedRequestPath = join15(runDirectory, "admitted-request.json");
20828
21575
  await writeAdmittedRequestPersistence(admittedRequestPath, admitted, {
20829
21576
  sessionDirectory,
20830
21577
  sessionFile
@@ -20994,7 +21741,7 @@ async function admitCollectorInvocation(options) {
20994
21741
  throw new CliUsageError(detail, { cause: error });
20995
21742
  }
20996
21743
  }
20997
- const projectRoot = resolve8(options.project ?? options.cwd);
21744
+ const projectRoot = resolve7(options.project ?? options.cwd);
20998
21745
  let repository;
20999
21746
  if (options.repo !== void 0) {
21000
21747
  try {
@@ -21023,17 +21770,16 @@ async function admitCollectorInvocation(options) {
21023
21770
  sessionDirectory,
21024
21771
  sessionFile,
21025
21772
  runDirectory,
21773
+ attachmentsDirectory,
21026
21774
  ledgerHome,
21027
21775
  bookKey
21028
21776
  } = issueAdmissionPlacement(options.principalAuthority, {
21029
21777
  cwd: projectRoot,
21030
21778
  runId,
21031
21779
  role: "collector",
21780
+ subject: { unbound: true },
21032
21781
  home: options.home
21033
21782
  });
21034
- const attachmentsDirectory = join13(runDirectory, "attachments");
21035
- ensureRealDirectoryTree(ledgerHome, sessionDirectory);
21036
- ensureRealDirectoryTree(ledgerHome, attachmentsDirectory);
21037
21783
  const attachments = await freezeAttachments(options.attachmentPaths ?? [], attachmentsDirectory);
21038
21784
  const instruction = options.instruction ?? "";
21039
21785
  const instructionEmpty = instruction.trim() === "";
@@ -21045,8 +21791,8 @@ async function admitCollectorInvocation(options) {
21045
21791
  const prNumber = target.kind === "bound" ? target.prNumber : void 0;
21046
21792
  let requestManifestPath;
21047
21793
  if (manifestCanonicalJson !== void 0) {
21048
- requestManifestPath = join13(runDirectory, "request-manifest.json");
21049
- await writeFile4(requestManifestPath, manifestCanonicalJson, "utf8");
21794
+ requestManifestPath = join15(runDirectory, "request-manifest.json");
21795
+ await writeFile5(requestManifestPath, manifestCanonicalJson, "utf8");
21050
21796
  }
21051
21797
  const admitted = {
21052
21798
  role: "collector",
@@ -21071,7 +21817,7 @@ async function admitCollectorInvocation(options) {
21071
21817
  mediaKind: a.mediaKind
21072
21818
  }))
21073
21819
  };
21074
- const admittedRequestPath = join13(runDirectory, "admitted-request.json");
21820
+ const admittedRequestPath = join15(runDirectory, "admitted-request.json");
21075
21821
  await writeAdmittedRequestPersistence(admittedRequestPath, admitted, {
21076
21822
  sessionDirectory,
21077
21823
  sessionFile
@@ -21169,9 +21915,8 @@ function parseDoctorArgv(args) {
21169
21915
  }
21170
21916
  async function resolveDoctorCaseRunsPath(options) {
21171
21917
  const ledgerHome = resolveActivationLedgerHome(options.home);
21172
- const defaultRuns = join13(
21918
+ const defaultRuns = join15(
21173
21919
  activationBookDirectory(ledgerHome, options.bookKey),
21174
- "issues",
21175
21920
  String(options.issueNumber),
21176
21921
  "runs"
21177
21922
  );
@@ -21187,7 +21932,7 @@ async function resolveDoctorCaseRunsPath(options) {
21187
21932
  "doctor --runs must be a project-relative path"
21188
21933
  );
21189
21934
  }
21190
- const resolved = resolve8(options.projectRoot, raw);
21935
+ const resolved = resolve7(options.projectRoot, raw);
21191
21936
  if (resolved !== options.projectRoot && !pathContainedIn(options.projectRoot, resolved)) {
21192
21937
  throw new CliUsageError(
21193
21938
  "doctor --runs escapes the project root"
@@ -21203,11 +21948,11 @@ async function resolveDoctorCaseRunsPath(options) {
21203
21948
  { cause: error }
21204
21949
  );
21205
21950
  }
21206
- const normalized = real.split(sep3).join("/");
21951
+ const normalized = real.split(sep4).join("/");
21207
21952
  const match = normalized.match(DOCTOR_CASE_RUNS_PATH_PATTERN);
21208
21953
  if (!match) {
21209
21954
  throw new CliUsageError(
21210
- "doctor --runs must be an .ak-roles/books/<book>/issues/<n>/runs directory"
21955
+ "doctor --runs must be an .ak-roles/books/<book>/<n>/runs directory"
21211
21956
  );
21212
21957
  }
21213
21958
  if (Number(match[1]) !== options.issueNumber) {
@@ -21226,19 +21971,21 @@ async function admitDoctorInvocation(options) {
21226
21971
  `doctor --issue must be a positive integer, got ${options.issueNumber}`
21227
21972
  );
21228
21973
  }
21229
- const projectRoot = resolve8(options.project ?? options.cwd);
21974
+ const projectRoot = resolve7(options.project ?? options.cwd);
21230
21975
  const runId = (options.createRunId ?? uuidv7)();
21231
21976
  const {
21232
21977
  principal,
21233
21978
  sessionDirectory,
21234
21979
  sessionFile,
21235
21980
  runDirectory,
21981
+ attachmentsDirectory,
21236
21982
  ledgerHome,
21237
21983
  bookKey
21238
21984
  } = issueAdmissionPlacement(options.principalAuthority, {
21239
21985
  cwd: projectRoot,
21240
21986
  runId,
21241
21987
  role: "doctor",
21988
+ subject: { unbound: true },
21242
21989
  home: options.home
21243
21990
  });
21244
21991
  let caseRunsPath;
@@ -21276,9 +22023,6 @@ async function admitDoctorInvocation(options) {
21276
22023
  { cause: error }
21277
22024
  );
21278
22025
  }
21279
- const attachmentsDirectory = join13(runDirectory, "attachments");
21280
- ensureRealDirectoryTree(ledgerHome, sessionDirectory);
21281
- ensureRealDirectoryTree(ledgerHome, attachmentsDirectory);
21282
22026
  const attachments = await freezeAttachments(options.attachmentPaths ?? [], attachmentsDirectory);
21283
22027
  const instruction = options.instruction ?? "";
21284
22028
  const instructionEmpty = instruction.trim() === "";
@@ -21302,7 +22046,7 @@ async function admitDoctorInvocation(options) {
21302
22046
  mediaKind: a.mediaKind
21303
22047
  }))
21304
22048
  };
21305
- const admittedRequestPath = join13(runDirectory, "admitted-request.json");
22049
+ const admittedRequestPath = join15(runDirectory, "admitted-request.json");
21306
22050
  await writeAdmittedRequestPersistence(admittedRequestPath, admitted, {
21307
22051
  sessionDirectory,
21308
22052
  sessionFile
@@ -21387,7 +22131,7 @@ async function admitNotaryInvocation(options) {
21387
22131
  if (options.project !== void 0) {
21388
22132
  requireOptionPath("--project", options.project);
21389
22133
  }
21390
- const projectRoot = resolve8(options.project ?? options.cwd);
22134
+ const projectRoot = resolve7(options.project ?? options.cwd);
21391
22135
  let sourceRun;
21392
22136
  try {
21393
22137
  sourceRun = await resolveNotarySourceRunLocator({
@@ -21401,24 +22145,24 @@ async function admitNotaryInvocation(options) {
21401
22145
  }
21402
22146
  throw error;
21403
22147
  }
22148
+ const inheritedTicketNumber = await readBoardTicketNumber(sourceRun.runDirectory);
21404
22149
  const runId = options.createRunId?.() ?? uuidv7();
21405
22150
  const {
21406
22151
  principal,
21407
22152
  sessionDirectory,
21408
22153
  sessionFile,
21409
22154
  runDirectory,
22155
+ attachmentsDirectory,
21410
22156
  ledgerHome,
21411
22157
  bookKey
21412
22158
  } = issueAdmissionPlacement(options.principalAuthority, {
21413
22159
  cwd: projectRoot,
21414
22160
  runId,
21415
22161
  role: "notary",
22162
+ subject: inheritedTicketNumber === void 0 ? { unbound: true } : { ticketNumber: inheritedTicketNumber },
21416
22163
  home: options.home
21417
22164
  });
21418
- ensureRealDirectoryTree(ledgerHome, sessionDirectory);
21419
- const ticketFields = ticketAdmissionFields(
21420
- await readRunTicketNumber(sourceRun.runDirectory)
21421
- );
22165
+ const ticketFields = ticketAdmissionFields(inheritedTicketNumber);
21422
22166
  const admitted = {
21423
22167
  role: "notary",
21424
22168
  runId,
@@ -21434,7 +22178,7 @@ async function admitNotaryInvocation(options) {
21434
22178
  ...ticketFields,
21435
22179
  ...options.correlationId === void 0 ? {} : { correlationId: options.correlationId }
21436
22180
  };
21437
- const admittedRequestPath = join13(runDirectory, "admitted-request.json");
22181
+ const admittedRequestPath = join15(runDirectory, "admitted-request.json");
21438
22182
  await writeAdmittedRequestPersistence(admittedRequestPath, admitted, {
21439
22183
  sessionDirectory,
21440
22184
  sessionFile
@@ -21505,22 +22249,23 @@ async function admitGleanerLeftInvocation(options) {
21505
22249
  if (options.baseRevision.trim() === "") {
21506
22250
  throw new CliUsageError("--base requires a nonempty revision");
21507
22251
  }
21508
- const projectRoot = resolve8(options.project ?? options.cwd);
22252
+ const projectRoot = resolve7(options.project ?? options.cwd);
21509
22253
  const runId = (options.createRunId ?? uuidv7)();
21510
22254
  const {
21511
22255
  principal,
21512
22256
  sessionDirectory,
21513
22257
  sessionFile,
21514
22258
  runDirectory,
22259
+ attachmentsDirectory,
21515
22260
  ledgerHome,
21516
22261
  bookKey
21517
22262
  } = issueAdmissionPlacement(options.principalAuthority, {
21518
22263
  cwd: projectRoot,
21519
22264
  runId,
21520
22265
  role: "gleaner-left",
22266
+ subject: { unbound: true },
21521
22267
  home: options.home
21522
22268
  });
21523
- ensureRealDirectoryTree(ledgerHome, sessionDirectory);
21524
22269
  const instruction = options.instruction;
21525
22270
  const instructionEmpty = instruction.trim() === "";
21526
22271
  const admitted = {
@@ -21536,7 +22281,7 @@ async function admitGleanerLeftInvocation(options) {
21536
22281
  attachments: [],
21537
22282
  ...options.correlationId === void 0 ? {} : { correlationId: options.correlationId }
21538
22283
  };
21539
- const admittedRequestPath = join13(runDirectory, "admitted-request.json");
22284
+ const admittedRequestPath = join15(runDirectory, "admitted-request.json");
21540
22285
  await writeAdmittedRequestPersistence(admittedRequestPath, admitted, {
21541
22286
  sessionDirectory,
21542
22287
  sessionFile
@@ -21626,24 +22371,23 @@ async function admitReviewerInvocation(options) {
21626
22371
  const authorityRefs = Object.freeze(
21627
22372
  (options.authorityRefs ?? []).map((ref) => requireAuthorityRef(ref))
21628
22373
  );
21629
- const projectRoot = resolve8(options.project ?? options.cwd);
22374
+ const projectRoot = resolve7(options.project ?? options.cwd);
21630
22375
  const runId = (options.createRunId ?? uuidv7)();
21631
22376
  const {
21632
22377
  principal,
21633
22378
  sessionDirectory,
21634
22379
  sessionFile,
21635
22380
  runDirectory,
22381
+ attachmentsDirectory,
21636
22382
  ledgerHome,
21637
22383
  bookKey
21638
22384
  } = issueAdmissionPlacement(options.principalAuthority, {
21639
22385
  cwd: projectRoot,
21640
22386
  runId,
21641
22387
  role: "reviewer",
22388
+ subject: { unbound: true },
21642
22389
  home: options.home
21643
22390
  });
21644
- const attachmentsDirectory = join13(runDirectory, "attachments");
21645
- ensureRealDirectoryTree(ledgerHome, sessionDirectory);
21646
- ensureRealDirectoryTree(ledgerHome, attachmentsDirectory);
21647
22391
  const attachments = await freezeAttachments(options.attachmentPaths, attachmentsDirectory);
21648
22392
  const instruction = options.instruction;
21649
22393
  const instructionEmpty = instruction.trim() === "";
@@ -21666,7 +22410,7 @@ async function admitReviewerInvocation(options) {
21666
22410
  mediaKind: a.mediaKind
21667
22411
  }))
21668
22412
  };
21669
- const admittedRequestPath = join13(runDirectory, "admitted-request.json");
22413
+ const admittedRequestPath = join15(runDirectory, "admitted-request.json");
21670
22414
  await writeAdmittedRequestPersistence(admittedRequestPath, admitted, {
21671
22415
  sessionDirectory,
21672
22416
  sessionFile
@@ -21765,7 +22509,7 @@ async function admitMergerInvocation(options) {
21765
22509
  if (instruction.trim() === "") {
21766
22510
  throw new CliUsageError("merger requires a nonblank task instruction");
21767
22511
  }
21768
- const projectRoot = resolve8(options.project ?? options.cwd);
22512
+ const projectRoot = resolve7(options.project ?? options.cwd);
21769
22513
  const derived = await deriveMergerEnvelopeFromActiveMerge(
21770
22514
  projectRoot,
21771
22515
  options.gitState ?? createProductionMergerGitState(projectRoot)
@@ -21776,17 +22520,16 @@ async function admitMergerInvocation(options) {
21776
22520
  sessionDirectory,
21777
22521
  sessionFile,
21778
22522
  runDirectory,
22523
+ attachmentsDirectory,
21779
22524
  ledgerHome,
21780
22525
  bookKey
21781
22526
  } = issueAdmissionPlacement(options.principalAuthority, {
21782
22527
  cwd: projectRoot,
21783
22528
  runId,
21784
22529
  role: "merger",
22530
+ subject: { unbound: true },
21785
22531
  home: options.home
21786
22532
  });
21787
- const attachmentsDirectory = join13(runDirectory, "attachments");
21788
- ensureRealDirectoryTree(ledgerHome, sessionDirectory);
21789
- ensureRealDirectoryTree(ledgerHome, attachmentsDirectory);
21790
22533
  const attachments = await freezeAttachments(options.attachmentPaths, attachmentsDirectory);
21791
22534
  const targetLabel = derived.targetObjectId === "" ? "(none observed)" : derived.targetObjectId;
21792
22535
  const sourceLabel = derived.sourceObjectId === "" ? "(none observed)" : derived.sourceObjectId;
@@ -21812,8 +22555,8 @@ async function admitMergerInvocation(options) {
21812
22555
  resolutionScope: [...derived.resolutionScope],
21813
22556
  authorizedChecks: []
21814
22557
  });
21815
- const mergerInputPath = join13(runDirectory, "merger-input.json");
21816
- await writeFile4(
22558
+ const mergerInputPath = join15(runDirectory, "merger-input.json");
22559
+ await writeFile5(
21817
22560
  mergerInputPath,
21818
22561
  `${JSON.stringify(mergerInput, null, 2)}
21819
22562
  `,
@@ -21843,7 +22586,7 @@ async function admitMergerInvocation(options) {
21843
22586
  mediaKind: a.mediaKind
21844
22587
  }))
21845
22588
  };
21846
- const admittedRequestPath = join13(runDirectory, "admitted-request.json");
22589
+ const admittedRequestPath = join15(runDirectory, "admitted-request.json");
21847
22590
  await writeAdmittedRequestPersistence(admittedRequestPath, admitted, {
21848
22591
  sessionDirectory,
21849
22592
  sessionFile
@@ -21897,11 +22640,11 @@ function parseAnalystCohortIssueToken(raw, flag) {
21897
22640
  `${flag} requires a comma-separated list of N or book:N`
21898
22641
  );
21899
22642
  }
21900
- const sep4 = trimmed.lastIndexOf(":");
21901
- if (sep4 > 0) {
21902
- const rhs = trimmed.slice(sep4 + 1);
22643
+ const sep5 = trimmed.lastIndexOf(":");
22644
+ if (sep5 > 0) {
22645
+ const rhs = trimmed.slice(sep5 + 1);
21903
22646
  if (ANALYST_TICKET_NUMBER_PATTERN.test(rhs)) {
21904
- const bookKey = trimmed.slice(0, sep4);
22647
+ const bookKey = trimmed.slice(0, sep5);
21905
22648
  if (bookKey.trim() === "") {
21906
22649
  throw new CliUsageError(
21907
22650
  `${flag} book:N requires a non-empty book key, got ${raw}`
@@ -22101,8 +22844,11 @@ var init_invocation = __esm({
22101
22844
  "use strict";
22102
22845
  init_activation_ledger_topology();
22103
22846
  init_activation_ledger_git();
22847
+ init_role_run_placement();
22104
22848
  init_run_ticket_number();
22849
+ init_role_run_relocation();
22105
22850
  init_doctor_evidence();
22851
+ init_diarist_contracts();
22106
22852
  init_collector_config();
22107
22853
  init_collector_target();
22108
22854
  init_github_remote();
@@ -22117,23 +22863,23 @@ var init_invocation = __esm({
22117
22863
  init_cli_errors();
22118
22864
  init_option_definitions();
22119
22865
  DOCTOR_ISSUE_NUMBER_PATTERN = /^[1-9]\d*$/;
22120
- DOCTOR_CASE_RUNS_PATH_PATTERN = /\/\.ak-roles\/books\/[^/]+\/issues\/([1-9]\d*)\/runs$/;
22866
+ DOCTOR_CASE_RUNS_PATH_PATTERN = /\/\.ak-roles\/books\/[^/]+\/(?:issues\/)?([1-9]\d*)\/runs$/;
22121
22867
  ANALYST_TICKET_NUMBER_PATTERN = /^[1-9]\d*$/;
22122
22868
  }
22123
22869
  });
22124
22870
 
22125
22871
  // src/public-cli/load-production-acp-host.ts
22126
- import { existsSync as existsSync6 } from "node:fs";
22127
- import { join as join14 } from "node:path";
22872
+ import { existsSync as existsSync7 } from "node:fs";
22873
+ import { join as join16 } from "node:path";
22128
22874
  import { pathToFileURL } from "node:url";
22129
22875
  async function loadProductionAcpHostFactory(packageRoot2, host) {
22130
22876
  const description = lookupHostDescription(host);
22131
22877
  if (description === void 0) {
22132
22878
  throw new Error(`unregistered host: ${host}`);
22133
22879
  }
22134
- const built = join14(packageRoot2, "dist/acp-host/production-host.js");
22135
- const source = join14(packageRoot2, "src/acp-host/production-host.ts");
22136
- const target = existsSync6(built) ? built : source;
22880
+ const built = join16(packageRoot2, "dist/acp-host/production-host.js");
22881
+ const source = join16(packageRoot2, "src/acp-host/production-host.ts");
22882
+ const target = existsSync7(built) ? built : source;
22137
22883
  const href = pathToFileURL(target).href;
22138
22884
  const mod = await import(href);
22139
22885
  const create = mod.createProductionAcpRoleTurnHost;
@@ -22147,17 +22893,17 @@ var init_load_production_acp_host = __esm({
22147
22893
  });
22148
22894
 
22149
22895
  // src/public-cli/load-production-headless-host.ts
22150
- import { existsSync as existsSync7 } from "node:fs";
22151
- import { join as join15 } from "node:path";
22896
+ import { existsSync as existsSync8 } from "node:fs";
22897
+ import { join as join17 } from "node:path";
22152
22898
  import { pathToFileURL as pathToFileURL2 } from "node:url";
22153
22899
  async function loadProductionHeadlessHostFactory(packageRoot2, host) {
22154
22900
  const description = lookupHeadlessHostDescription(host);
22155
22901
  if (description === void 0) {
22156
22902
  throw new Error(`unregistered headless host: ${host}`);
22157
22903
  }
22158
- const built = join15(packageRoot2, "dist/headless-host/production-host.js");
22159
- const source = join15(packageRoot2, "src/headless-host/production-host.ts");
22160
- const target = existsSync7(built) ? built : source;
22904
+ const built = join17(packageRoot2, "dist/headless-host/production-host.js");
22905
+ const source = join17(packageRoot2, "src/headless-host/production-host.ts");
22906
+ const target = existsSync8(built) ? built : source;
22161
22907
  const href = pathToFileURL2(target).href;
22162
22908
  const mod = await import(href);
22163
22909
  const create = mod.createProductionHeadlessRoleTurnHost;
@@ -22283,8 +23029,8 @@ var init_role_turn_host_resolution = __esm({
22283
23029
 
22284
23030
  // src/package-resources/method-skill.ts
22285
23031
  import { createHash as createHash4 } from "node:crypto";
22286
- import { readFile as readFile11, realpath as realpath5 } from "node:fs/promises";
22287
- import { join as join16 } from "node:path";
23032
+ import { readFile as readFile12, realpath as realpath5 } from "node:fs/promises";
23033
+ import { join as join18 } from "node:path";
22288
23034
  function gitBlobOid(bytes) {
22289
23035
  const body = typeof bytes === "string" ? Buffer.from(bytes, "utf8") : Buffer.from(bytes);
22290
23036
  const header = Buffer.from(`blob ${body.byteLength}\0`, "utf8");
@@ -22301,10 +23047,10 @@ function packagedMethodSkillRelativeDirectory(name) {
22301
23047
  return `${METHOD_SKILL_RELATIVE_ROOT}/${name}`;
22302
23048
  }
22303
23049
  function resolvePackagedMethodSkillRoot(packageRoot2, name) {
22304
- return join16(packageRoot2, packagedMethodSkillRelativeDirectory(name));
23050
+ return join18(packageRoot2, packagedMethodSkillRelativeDirectory(name));
22305
23051
  }
22306
23052
  function resolvePackagedMethodSkillPath(packageRoot2, name) {
22307
- return join16(resolvePackagedMethodSkillRoot(packageRoot2, name), "SKILL.md");
23053
+ return join18(resolvePackagedMethodSkillRoot(packageRoot2, name), "SKILL.md");
22308
23054
  }
22309
23055
  function isRecord4(value) {
22310
23056
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -22398,11 +23144,11 @@ function parseProvenance(raw, expectedName) {
22398
23144
  }
22399
23145
  async function loadPackagedMethodSkillMaterial(packageRoot2, name) {
22400
23146
  const rootDirectory = resolvePackagedMethodSkillRoot(packageRoot2, name);
22401
- const skillPathConfigured = join16(rootDirectory, "SKILL.md");
22402
- const provenancePath = join16(rootDirectory, "provenance.json");
23147
+ const skillPathConfigured = join18(rootDirectory, "SKILL.md");
23148
+ const provenancePath = join18(rootDirectory, "provenance.json");
22403
23149
  let provenanceRaw;
22404
23150
  try {
22405
- provenanceRaw = await readFile11(provenancePath, "utf8");
23151
+ provenanceRaw = await readFile12(provenancePath, "utf8");
22406
23152
  } catch (error) {
22407
23153
  throw new PackagedMethodSkillUnavailableError(name, provenancePath, error);
22408
23154
  }
@@ -22416,10 +23162,10 @@ async function loadPackagedMethodSkillMaterial(packageRoot2, name) {
22416
23162
  }
22417
23163
  const provenance = parseProvenance(provenanceJson, name);
22418
23164
  for (const [rel, expected] of Object.entries(provenance.files)) {
22419
- const absolute = join16(rootDirectory, rel);
23165
+ const absolute = join18(rootDirectory, rel);
22420
23166
  let bytes;
22421
23167
  try {
22422
- bytes = await readFile11(absolute);
23168
+ bytes = await readFile12(absolute);
22423
23169
  } catch (error) {
22424
23170
  throw new PackagedMethodSkillUnavailableError(name, absolute, error);
22425
23171
  }
@@ -22435,7 +23181,7 @@ async function loadPackagedMethodSkillMaterial(packageRoot2, name) {
22435
23181
  let raw;
22436
23182
  try {
22437
23183
  skillPath = await realpath5(skillPathConfigured);
22438
- raw = await readFile11(skillPath, "utf8");
23184
+ raw = await readFile12(skillPath, "utf8");
22439
23185
  } catch (error) {
22440
23186
  throw new PackagedMethodSkillUnavailableError(name, skillPathConfigured, error);
22441
23187
  }
@@ -22513,45 +23259,13 @@ var init_method_skill = __esm({
22513
23259
  }
22514
23260
  });
22515
23261
 
22516
- // src/auditor-dossier-tool.ts
22517
- var init_auditor_dossier_tool = __esm({
22518
- "src/auditor-dossier-tool.ts"() {
22519
- "use strict";
22520
- init_build();
22521
- }
22522
- });
22523
-
22524
- // src/gatekeeper-role.ts
22525
- var init_gatekeeper_role = __esm({
22526
- "src/gatekeeper-role.ts"() {
22527
- "use strict";
22528
- init_auditor_dossier_tool();
22529
- init_submission_errors();
22530
- init_inspector_contracts();
22531
- init_gatekeeper_output();
22532
- init_submission_errors();
22533
- }
22534
- });
22535
-
22536
- // src/compliance-transport.ts
22537
- var AUDITOR_PARENT_ATTEMPT_BINDING_ENTRY_TYPE, AUDITOR_COMPLIANCE_FAILURE_ENTRY_TYPE;
22538
- var init_compliance_transport = __esm({
22539
- "src/compliance-transport.ts"() {
22540
- "use strict";
22541
- init_auditor_dossier_tool();
22542
- init_gatekeeper_role();
22543
- AUDITOR_PARENT_ATTEMPT_BINDING_ENTRY_TYPE = "ak_auditor_parent_attempt_binding";
22544
- AUDITOR_COMPLIANCE_FAILURE_ENTRY_TYPE = "ak_auditor_compliance_failure";
22545
- }
22546
- });
22547
-
22548
23262
  // src/ledger-session-read.ts
22549
- import { readFile as readFile12 } from "node:fs/promises";
23263
+ import { readFile as readFile13 } from "node:fs/promises";
22550
23264
  function isRecord5(value) {
22551
23265
  return typeof value === "object" && value !== null && !Array.isArray(value);
22552
23266
  }
22553
23267
  async function readLedgerSessionJsonl(path) {
22554
- const text = await readFile12(path, "utf8");
23268
+ const text = await readFile13(path, "utf8");
22555
23269
  const lines = text.split("\n");
22556
23270
  const rows = [];
22557
23271
  for (let index = 0; index < lines.length; index += 1) {
@@ -22725,8 +23439,8 @@ var init_ledger_session_read = __esm({
22725
23439
  });
22726
23440
 
22727
23441
  // src/analyst-gate-cycles-read.ts
22728
- import { readdir as readdir3 } from "node:fs/promises";
22729
- import { join as join17 } from "node:path";
23442
+ import { readdir as readdir5 } from "node:fs/promises";
23443
+ import { join as join19 } from "node:path";
22730
23444
  function isRecord6(value) {
22731
23445
  return typeof value === "object" && value !== null && !Array.isArray(value);
22732
23446
  }
@@ -22941,10 +23655,10 @@ function pairGateRounds(volumes) {
22941
23655
  return rounds.sort((a, b) => a.officerStartedAt.localeCompare(b.officerStartedAt)).map((round, index) => ({ ...round, roundIndex: index + 1 }));
22942
23656
  }
22943
23657
  async function resolveOfficerSessionFromPointerFile(pointerPath) {
22944
- const { readFile: readFile24 } = await import("node:fs/promises");
23658
+ const { readFile: readFile25 } = await import("node:fs/promises");
22945
23659
  let raw;
22946
23660
  try {
22947
- raw = JSON.parse(await readFile24(pointerPath, "utf8"));
23661
+ raw = JSON.parse(await readFile25(pointerPath, "utf8"));
22948
23662
  } catch (error) {
22949
23663
  throw new Error(
22950
23664
  `direct officer run pointer unreadable in ${pointerPath}: ${error instanceof Error ? error.message : String(error)}`,
@@ -22967,7 +23681,7 @@ async function readAnalystGateCyclesFromAuditorRoles(auditorRolesDirectory, opti
22967
23681
  for (const directory of directories) {
22968
23682
  let names;
22969
23683
  try {
22970
- const entries = await readdir3(directory, { withFileTypes: true });
23684
+ const entries = await readdir5(directory, { withFileTypes: true });
22971
23685
  names = entries.filter(
22972
23686
  (e) => e.isFile() && (e.name.endsWith(".jsonl") || e.name.endsWith(".pointer.json"))
22973
23687
  ).map((e) => e.name).sort();
@@ -22976,7 +23690,7 @@ async function readAnalystGateCyclesFromAuditorRoles(auditorRolesDirectory, opti
22976
23690
  throw error;
22977
23691
  }
22978
23692
  for (const name of names) {
22979
- const path = join17(directory, name);
23693
+ const path = join19(directory, name);
22980
23694
  const fromPointer = name.endsWith(".pointer.json");
22981
23695
  const sessionPath = fromPointer ? await resolveOfficerSessionFromPointerFile(path) : path;
22982
23696
  if (sessionPath === void 0) continue;
@@ -23027,9 +23741,9 @@ var init_audit_escalation = __esm({
23027
23741
  });
23028
23742
 
23029
23743
  // src/run-terminal-artifacts.ts
23030
- import { readdir as readdir4, readFile as readFile13 } from "node:fs/promises";
23031
- import { basename as basename7, dirname as dirname9, join as join18 } from "node:path";
23032
- function isMissingPathError2(error) {
23744
+ import { readdir as readdir6, readFile as readFile14 } from "node:fs/promises";
23745
+ import { basename as basename7, dirname as dirname10, join as join20 } from "node:path";
23746
+ function isMissingPathError3(error) {
23033
23747
  return error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR");
23034
23748
  }
23035
23749
  function errorText2(error) {
@@ -23059,9 +23773,9 @@ function readUsableTerminalArtifactBody(body) {
23059
23773
  async function readTerminalArtifactAtPath(path, file) {
23060
23774
  let raw;
23061
23775
  try {
23062
- raw = await readFile13(path, "utf8");
23776
+ raw = await readFile14(path, "utf8");
23063
23777
  } catch (error) {
23064
- if (isMissingPathError2(error)) return void 0;
23778
+ if (isMissingPathError3(error)) return void 0;
23065
23779
  return {
23066
23780
  status: "unreadable",
23067
23781
  file,
@@ -23096,14 +23810,14 @@ async function listUniqueErrorFallbackPaths(directories) {
23096
23810
  for (const dir of directories) {
23097
23811
  let names;
23098
23812
  try {
23099
- names = await readdir4(dir);
23813
+ names = await readdir6(dir);
23100
23814
  } catch (error) {
23101
- if (isMissingPathError2(error)) continue;
23815
+ if (isMissingPathError3(error)) continue;
23102
23816
  throw error;
23103
23817
  }
23104
23818
  for (const name of names.sort((a, b) => a.localeCompare(b))) {
23105
23819
  if (!UNIQUE_ERROR_FALLBACK_NAME.test(name)) continue;
23106
- found.push(join18(dir, name));
23820
+ found.push(join20(dir, name));
23107
23821
  }
23108
23822
  }
23109
23823
  return found;
@@ -23119,14 +23833,14 @@ function presentUniqueFallbackBoundToRun(body, expectedRunId) {
23119
23833
  return typeof body.runId === "string" && body.runId === expectedRunId;
23120
23834
  }
23121
23835
  async function readRunTerminalArtifact(runDirectory) {
23122
- const artifactsDir = join18(runDirectory, "artifacts");
23836
+ const artifactsDir = roleRunArtifactsDirectory(runDirectory);
23123
23837
  for (const file of RUN_TERMINAL_ARTIFACT_FILES) {
23124
- const path = join18(artifactsDir, file);
23838
+ const path = join20(artifactsDir, file);
23125
23839
  const read = await readTerminalArtifactAtPath(path, file);
23126
23840
  if (read !== void 0) return read;
23127
23841
  }
23128
23842
  for (const relative3 of RUN_TERMINAL_ERROR_FALLBACK_RELATIVE_PATHS) {
23129
- const path = join18(runDirectory, relative3);
23843
+ const path = join20(runDirectory, relative3);
23130
23844
  const read = await readTerminalArtifactAtPath(path, "error.json");
23131
23845
  if (read !== void 0) return read;
23132
23846
  }
@@ -23135,7 +23849,7 @@ async function readRunTerminalArtifact(runDirectory) {
23135
23849
  if (read !== void 0) return read;
23136
23850
  }
23137
23851
  const expectedRunId = runIdFromRunDirectory(runDirectory);
23138
- for (const path of await listUniqueErrorFallbackPaths([dirname9(runDirectory)])) {
23852
+ for (const path of await listUniqueErrorFallbackPaths([dirname10(runDirectory)])) {
23139
23853
  const read = await readTerminalArtifactAtPath(path, "error.json");
23140
23854
  if (read === void 0) continue;
23141
23855
  if (read.status === "present") {
@@ -23149,6 +23863,7 @@ var RUN_TERMINAL_ARTIFACT_FILES, RUN_TERMINAL_ERROR_FALLBACK_RELATIVE_PATHS, UNI
23149
23863
  var init_run_terminal_artifacts = __esm({
23150
23864
  "src/run-terminal-artifacts.ts"() {
23151
23865
  "use strict";
23866
+ init_role_run_placement();
23152
23867
  RUN_TERMINAL_ARTIFACT_FILES = [
23153
23868
  "report.json",
23154
23869
  "error.json",
@@ -23163,21 +23878,34 @@ var init_run_terminal_artifacts = __esm({
23163
23878
  });
23164
23879
 
23165
23880
  // src/submission-ledger.ts
23166
- function submissionRecordFile(cwd, runId, home) {
23167
- const ledgerHome = resolveActivationLedgerHome(home);
23881
+ import { join as join21 } from "node:path";
23882
+ async function submissionRecordFile(cwd, runId, scope) {
23883
+ const ledgerHome = resolveActivationLedgerHome(scope.home);
23884
+ let sessionParent = scope.sessionParent;
23885
+ if (sessionParent === void 0) {
23886
+ const discoveredRun = await findRunDirectoryById(scope.home, runId);
23887
+ if (discoveredRun === void 0) return void 0;
23888
+ sessionParent = join21(discoveredRun, "session", "session.jsonl");
23889
+ }
23168
23890
  return resolveSitianRecordPathInLedger({
23169
23891
  level: "event",
23170
23892
  kind: "candidate",
23171
23893
  subject: { runId },
23172
- cwd
23894
+ cwd,
23895
+ sessionParent
23173
23896
  }, ledgerHome).recordFile;
23174
23897
  }
23175
- async function readOwnedSubmissionRecords(cwd, runId, home) {
23176
- const file = submissionRecordFile(cwd, runId, home);
23898
+ async function readOwnedSubmissionRecords(cwd, runId, scope = {}) {
23899
+ const file = await submissionRecordFile(cwd, runId, scope);
23900
+ if (file === void 0) {
23901
+ return { file: void 0, owned: [] };
23902
+ }
23177
23903
  const { records } = await readSitianRecords(file);
23178
23904
  return {
23179
23905
  file,
23180
- owned: records.filter((record4) => typeof record4.subject === "object" && record4.subject !== null && record4.subject.runId === runId)
23906
+ owned: records.filter(
23907
+ (record4) => typeof record4.subject === "object" && record4.subject !== null && record4.subject.runId === runId
23908
+ )
23181
23909
  };
23182
23910
  }
23183
23911
  function resolveReadScope(homeOrScope) {
@@ -23200,8 +23928,8 @@ function recordAttemptId(record4) {
23200
23928
  }
23201
23929
  return void 0;
23202
23930
  }
23203
- async function hasFreshAttemptSubmission(cwd, runId, attemptId, home) {
23204
- const { owned } = await readOwnedSubmissionRecords(cwd, runId, home);
23931
+ async function hasFreshAttemptSubmission(cwd, runId, attemptId, homeOrScope) {
23932
+ const { owned } = await readOwnedSubmissionRecords(cwd, runId, resolveReadScope(homeOrScope));
23205
23933
  return owned.some((record4) => {
23206
23934
  if (recordAttemptId(record4) !== attemptId) return false;
23207
23935
  if (record4.kind === "sealed") return true;
@@ -23312,13 +24040,17 @@ function mapOwnedToSubmissionRows(owned) {
23312
24040
  }
23313
24041
  async function readRecordedSubmissionRows(cwd, runId, homeOrScope) {
23314
24042
  const scope = resolveReadScope(homeOrScope);
23315
- const { owned } = await readOwnedSubmissionRecords(cwd, runId, scope.home);
24043
+ const { owned } = await readOwnedSubmissionRecords(cwd, runId, scope);
23316
24044
  const scoped = recordsForAttempt(owned, scope.attemptId);
23317
24045
  return mapOwnedToSubmissionRows(scoped);
23318
24046
  }
23319
24047
  async function readAttemptScopedSubmissionRows(cwd, runId, attemptId, home) {
23320
24048
  if (attemptId.length === 0) return [];
23321
- const { owned } = await readOwnedSubmissionRecords(cwd, runId, home);
24049
+ const { owned } = await readOwnedSubmissionRecords(
24050
+ cwd,
24051
+ runId,
24052
+ home === void 0 ? {} : { home }
24053
+ );
23322
24054
  return mapOwnedToSubmissionRows(owned.filter((record4) => recordAttemptId(record4) === attemptId));
23323
24055
  }
23324
24056
  async function readRecordedSubmissions(cwd, runId, homeOrScope) {
@@ -23332,30 +24064,31 @@ var init_submission_ledger = __esm({
23332
24064
  init_audit_escalation();
23333
24065
  init_run_terminal_artifacts();
23334
24066
  init_sitian_facade();
24067
+ init_run_lifecycle();
23335
24068
  init_submission_correctable_error();
23336
24069
  init_terminating_infrastructure();
23337
24070
  }
23338
24071
  });
23339
24072
 
23340
24073
  // src/session-opening-materials.ts
23341
- import { existsSync as existsSync8 } from "node:fs";
23342
- import { readFile as readFile14 } from "node:fs/promises";
23343
- import { dirname as dirname10, join as join19 } from "node:path";
24074
+ import { existsSync as existsSync9 } from "node:fs";
24075
+ import { readFile as readFile15 } from "node:fs/promises";
24076
+ import { dirname as dirname11, join as join22 } from "node:path";
23344
24077
  import { fileURLToPath, pathToFileURL as pathToFileURL3 } from "node:url";
23345
24078
  function resolvePackageRootDir(moduleUrl = import.meta.url) {
23346
- let dir = dirname10(fileURLToPath(moduleUrl));
24079
+ let dir = dirname11(fileURLToPath(moduleUrl));
23347
24080
  for (let i = 0; i < 8; i += 1) {
23348
- if (existsSync8(join19(dir, "package.json")) && existsSync8(join19(dir, "souls"))) {
24081
+ if (existsSync9(join22(dir, "package.json")) && existsSync9(join22(dir, "souls"))) {
23349
24082
  return dir;
23350
24083
  }
23351
- const parent = dirname10(dir);
24084
+ const parent = dirname11(dir);
23352
24085
  if (parent === dir) break;
23353
24086
  dir = parent;
23354
24087
  }
23355
24088
  return fileURLToPath(new URL("..", moduleUrl));
23356
24089
  }
23357
24090
  async function readPackageMaterial(relativePath) {
23358
- return readFile14(fileURLToPath(new URL(relativePath, packageRootUrl)), "utf8");
24091
+ return readFile15(fileURLToPath(new URL(relativePath, packageRootUrl)), "utf8");
23359
24092
  }
23360
24093
  async function joinPackageMaterials(relativePaths) {
23361
24094
  const chunks = [];
@@ -23597,13 +24330,13 @@ var init_reviewer_dispatch = __esm({
23597
24330
  });
23598
24331
 
23599
24332
  // src/public-cli/reviewer-dispatch-rejection.ts
23600
- import { readFile as readFile15, unlink as unlink3 } from "node:fs/promises";
23601
- import { join as join20 } from "node:path";
24333
+ import { readFile as readFile16, unlink as unlink3 } from "node:fs/promises";
24334
+ import { join as join23 } from "node:path";
23602
24335
  function isReviewerPreflightViolation(value) {
23603
24336
  return typeof value === "string" && REVIEWER_PREFLIGHT_VIOLATIONS.includes(value);
23604
24337
  }
23605
24338
  function reviewerDispatchRejectionPath(runDirectory) {
23606
- return join20(runDirectory, REVIEWER_DISPATCH_REJECTION_FILE);
24339
+ return join23(runDirectory, REVIEWER_DISPATCH_REJECTION_FILE);
23607
24340
  }
23608
24341
  async function clearReviewerDispatchRejection(runDirectory) {
23609
24342
  try {
@@ -23618,7 +24351,7 @@ async function clearReviewerDispatchRejection(runDirectory) {
23618
24351
  async function readReviewerDispatchRejection(runDirectory) {
23619
24352
  let raw;
23620
24353
  try {
23621
- raw = await readFile15(reviewerDispatchRejectionPath(runDirectory), "utf8");
24354
+ raw = await readFile16(reviewerDispatchRejectionPath(runDirectory), "utf8");
23622
24355
  } catch (error) {
23623
24356
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
23624
24357
  return void 0;
@@ -23975,14 +24708,15 @@ var init_terminal = __esm({
23975
24708
 
23976
24709
  // src/public-cli/settlement.ts
23977
24710
  import { randomUUID as randomUUID3 } from "node:crypto";
23978
- import { appendFile as appendFile2, readFile as readFile16, readdir as readdir5, writeFile as writeFile5 } from "node:fs/promises";
23979
- import { dirname as dirname11, join as join21 } from "node:path";
24711
+ import { appendFile as appendFile2, readFile as readFile17, readdir as readdir7, writeFile as writeFile6 } from "node:fs/promises";
24712
+ import { dirname as dirname12, join as join24 } from "node:path";
23980
24713
  function sealedLedgerHome(admitted) {
23981
24714
  return homeFromRunDirectory(admitted.runDirectory);
23982
24715
  }
23983
24716
  function ledgerReadScope(admitted, scope) {
23984
24717
  return {
23985
24718
  home: sealedLedgerHome(admitted),
24719
+ sessionParent: join24(admitted.runDirectory, "session", "session.jsonl"),
23986
24720
  ...scope?.courtAttemptId === void 0 || scope.courtAttemptId.length === 0 ? {} : { attemptId: scope.courtAttemptId }
23987
24721
  };
23988
24722
  }
@@ -24022,7 +24756,7 @@ async function attemptProducedFreshSubmission(admitted, scope) {
24022
24756
  admitted.projectRoot,
24023
24757
  admitted.runId,
24024
24758
  scope.courtAttemptId,
24025
- sealedLedgerHome(admitted)
24759
+ ledgerReadScope(admitted, scope)
24026
24760
  );
24027
24761
  }
24028
24762
  async function recordedSubmissionPayloads(admitted, scope) {
@@ -24117,10 +24851,10 @@ function presentControlledFailure(failure, io) {
24117
24851
  }
24118
24852
  async function inspectJudgeSession(sessionFile) {
24119
24853
  try {
24120
- await readFile16(sessionFile, "utf8");
24854
+ await readFile17(sessionFile, "utf8");
24121
24855
  return { state: "present" };
24122
24856
  } catch (error) {
24123
- if (isMissingPathError3(error)) return { state: "missing" };
24857
+ if (isMissingPathError4(error)) return { state: "missing" };
24124
24858
  return {
24125
24859
  state: "unreadable",
24126
24860
  diagnostic: error instanceof Error ? error.message || error.name : String(error)
@@ -24320,7 +25054,7 @@ function explicitInternalKnownFailureClassificationInput(failure) {
24320
25054
  ...failure.details === void 0 ? {} : { knownDetails: failure.details }
24321
25055
  };
24322
25056
  }
24323
- function isMissingPathError3(error) {
25057
+ function isMissingPathError4(error) {
24324
25058
  return error instanceof Error && "code" in error && error.code === "ENOENT";
24325
25059
  }
24326
25060
  function sessionReadFailure(error, fallbackMessage) {
@@ -24349,7 +25083,7 @@ function sessionReadFailure(error, fallbackMessage) {
24349
25083
  return failed;
24350
25084
  }
24351
25085
  async function readBoundSessionEntries(sessionFile) {
24352
- const text = await readFile16(sessionFile, "utf8");
25086
+ const text = await readFile17(sessionFile, "utf8");
24353
25087
  const entries = [];
24354
25088
  for (const line2 of text.trim().split("\n").filter(Boolean)) {
24355
25089
  try {
@@ -24410,7 +25144,7 @@ async function readSitianRetainedAuditorProviderStop(sessionFile) {
24410
25144
  kind: "auditor",
24411
25145
  sessionParent: sessionFile,
24412
25146
  // Path is driven by sessionParent when under ledger home; cwd is a fallback only.
24413
- cwd: dirname11(sessionFile)
25147
+ cwd: dirname12(sessionFile)
24414
25148
  });
24415
25149
  const { records } = await readSitianRecords(recordFile);
24416
25150
  for (let i = records.length - 1; i >= 0; i -= 1) {
@@ -24436,18 +25170,18 @@ async function readSessionProviderStop(sessionFile) {
24436
25170
  }
24437
25171
  }
24438
25172
  async function readBoundEvidenceChildKnownFailure(sessionFile) {
24439
- const childDirectory = join21(dirname11(sessionFile), "evidence-children");
25173
+ const childDirectory = join24(dirname12(sessionFile), "evidence-children");
24440
25174
  let names;
24441
25175
  try {
24442
- names = await readdir5(childDirectory);
25176
+ names = await readdir7(childDirectory);
24443
25177
  } catch (error) {
24444
- if (isMissingPathError3(error)) return void 0;
25178
+ if (isMissingPathError4(error)) return void 0;
24445
25179
  throw sessionReadFailure(error, "failed to read bound evidence-child session directory");
24446
25180
  }
24447
25181
  for (const file of names.filter((name) => name.endsWith(".jsonl")).sort().reverse()) {
24448
25182
  let entries;
24449
25183
  try {
24450
- entries = await readBoundSessionEntries(join21(childDirectory, file));
25184
+ entries = await readBoundSessionEntries(join24(childDirectory, file));
24451
25185
  } catch (error) {
24452
25186
  throw sessionReadFailure(error, "failed to read discovered evidence-child session");
24453
25187
  }
@@ -24471,7 +25205,7 @@ async function loadBoundAuditorVolumes(sessionFile) {
24471
25205
  try {
24472
25206
  parentEntries = await readBoundSessionEntries(sessionFile);
24473
25207
  } catch (error) {
24474
- if (isMissingPathError3(error)) return void 0;
25208
+ if (isMissingPathError4(error)) return void 0;
24475
25209
  throw sessionReadFailure(error, "failed to read parent session for auditor binding");
24476
25210
  }
24477
25211
  const parentId = parentEntries.find((entry) => entry.type === "session")?.id;
@@ -24502,22 +25236,22 @@ async function loadBoundAuditorVolumes(sessionFile) {
24502
25236
  latestParentUserIndex = i;
24503
25237
  break;
24504
25238
  }
24505
- const childDirectories = [join21(dirname11(sessionFile), "auditor-roles")];
25239
+ const childDirectories = [join24(dirname12(sessionFile), "auditor-roles")];
24506
25240
  const valid = [];
24507
25241
  let sawAnyDirectory = false;
24508
25242
  for (const childDirectory of childDirectories) {
24509
25243
  let names;
24510
25244
  try {
24511
- names = await readdir5(childDirectory);
25245
+ names = await readdir7(childDirectory);
24512
25246
  sawAnyDirectory = true;
24513
25247
  } catch (error) {
24514
- if (isMissingPathError3(error)) continue;
25248
+ if (isMissingPathError4(error)) continue;
24515
25249
  throw sessionReadFailure(error, "failed to read bound auditor session directory");
24516
25250
  }
24517
25251
  for (const file of names.filter((name) => name.endsWith(".jsonl")).sort().reverse()) {
24518
25252
  let entries;
24519
25253
  try {
24520
- entries = await readBoundSessionEntries(join21(childDirectory, file));
25254
+ entries = await readBoundSessionEntries(join24(childDirectory, file));
24521
25255
  } catch (error) {
24522
25256
  throw sessionReadFailure(error, "failed to read discovered auditor session");
24523
25257
  }
@@ -24675,7 +25409,7 @@ async function resolveAuditedRunnerFailureResolution(input) {
24675
25409
  );
24676
25410
  if (terminatingFailure !== void 0) return resolutionOf(terminatingFailure);
24677
25411
  } catch (error) {
24678
- if (!isMissingPathError3(error)) {
25412
+ if (!isMissingPathError4(error)) {
24679
25413
  const failure = sessionReadFailure(error, "failed to recover typed terminating-tool failure");
24680
25414
  return resolutionOf({
24681
25415
  cause: "session",
@@ -25022,8 +25756,8 @@ function projectTerminalGateFact(rounds) {
25022
25756
  };
25023
25757
  }
25024
25758
  async function extractGateFactFromSessionDirectory(sessionDirectory, options = {}) {
25025
- const directories = [join21(sessionDirectory, "auditor-roles")];
25026
- const parentSessionFile = options.parentSessionFile ?? join21(sessionDirectory, "session.jsonl");
25759
+ const directories = [join24(sessionDirectory, "auditor-roles")];
25760
+ const parentSessionFile = options.parentSessionFile ?? join24(sessionDirectory, "session.jsonl");
25027
25761
  const rounds = await readAnalystGateCyclesFromAuditorRoles(directories, {
25028
25762
  parentSessionFile
25029
25763
  });
@@ -25104,7 +25838,7 @@ async function extractNavigatorFactFromAdmittedSession(sessionFile) {
25104
25838
  const entries = await readBoundSessionEntries(sessionFile);
25105
25839
  return extractNavigatorFact(entries);
25106
25840
  } catch (error) {
25107
- if (isMissingPathError3(error)) {
25841
+ if (isMissingPathError4(error)) {
25108
25842
  return {
25109
25843
  disposition: "unavailable",
25110
25844
  source: "unknown",
@@ -25121,9 +25855,9 @@ async function extractNavigatorFactFromAdmittedSession(sessionFile) {
25121
25855
  async function publishJudgeArtifacts(admitted, roleOutcome, coordinates) {
25122
25856
  await appendRunAttemptHistory({ role: admitted.role, runId: admitted.runId, sessionFile: coordinates.sessionFile }, roleOutcome);
25123
25857
  const artifactsDir = await ensureRunArtifactsDir(admitted.runDirectory);
25124
- const reportPath = join21(artifactsDir, "report.json");
25125
- const evidencePath = join21(artifactsDir, "evidence.json");
25126
- await writeFile5(
25858
+ const reportPath = join24(artifactsDir, "report.json");
25859
+ const evidencePath = join24(artifactsDir, "evidence.json");
25860
+ await writeFile6(
25127
25861
  reportPath,
25128
25862
  `${JSON.stringify(
25129
25863
  {
@@ -25137,7 +25871,7 @@ async function publishJudgeArtifacts(admitted, roleOutcome, coordinates) {
25137
25871
  `,
25138
25872
  "utf8"
25139
25873
  );
25140
- await writeFile5(
25874
+ await writeFile6(
25141
25875
  evidencePath,
25142
25876
  `${JSON.stringify(
25143
25877
  {
@@ -25166,9 +25900,9 @@ async function publishJudgeArtifacts(admitted, roleOutcome, coordinates) {
25166
25900
  async function publishCoderArtifacts(admitted, roleOutcome, coordinates, options = {}) {
25167
25901
  await appendRunAttemptHistory({ role: admitted.role, runId: admitted.runId, sessionFile: coordinates.sessionFile }, roleOutcome);
25168
25902
  const artifactsDir = await ensureRunArtifactsDir(admitted.runDirectory);
25169
- const reportPath = join21(artifactsDir, "report.json");
25170
- const evidencePath = join21(artifactsDir, "evidence.json");
25171
- await writeFile5(
25903
+ const reportPath = join24(artifactsDir, "report.json");
25904
+ const evidencePath = join24(artifactsDir, "evidence.json");
25905
+ await writeFile6(
25172
25906
  reportPath,
25173
25907
  `${JSON.stringify(
25174
25908
  {
@@ -25183,7 +25917,7 @@ async function publishCoderArtifacts(admitted, roleOutcome, coordinates, options
25183
25917
  `,
25184
25918
  "utf8"
25185
25919
  );
25186
- await writeFile5(
25920
+ await writeFile6(
25187
25921
  evidencePath,
25188
25922
  `${JSON.stringify(
25189
25923
  {
@@ -25217,7 +25951,7 @@ async function readLawfulSettlementEntries(sessionFile) {
25217
25951
  try {
25218
25952
  return await readBoundSessionEntries(sessionFile);
25219
25953
  } catch (error) {
25220
- if (isMissingPathError3(error)) return void 0;
25954
+ if (isMissingPathError4(error)) return void 0;
25221
25955
  throw error instanceof Error && error.knownCause === "session" ? error : sessionReadFailure(error, "session unreadable");
25222
25956
  }
25223
25957
  }
@@ -25304,9 +26038,9 @@ function extractFixerMethodInvocations(entries, options) {
25304
26038
  async function publishFixerArtifacts(admitted, roleOutcome, coordinates, options) {
25305
26039
  await appendRunAttemptHistory({ role: admitted.role, runId: admitted.runId, sessionFile: coordinates.sessionFile }, roleOutcome);
25306
26040
  const artifactsDir = await ensureRunArtifactsDir(admitted.runDirectory);
25307
- const reportPath = join21(artifactsDir, "report.json");
25308
- const evidencePath = join21(artifactsDir, "evidence.json");
25309
- await writeFile5(
26041
+ const reportPath = join24(artifactsDir, "report.json");
26042
+ const evidencePath = join24(artifactsDir, "evidence.json");
26043
+ await writeFile6(
25310
26044
  reportPath,
25311
26045
  `${JSON.stringify(
25312
26046
  {
@@ -25321,7 +26055,7 @@ async function publishFixerArtifacts(admitted, roleOutcome, coordinates, options
25321
26055
  `,
25322
26056
  "utf8"
25323
26057
  );
25324
- await writeFile5(
26058
+ await writeFile6(
25325
26059
  evidencePath,
25326
26060
  `${JSON.stringify(
25327
26061
  {
@@ -25392,9 +26126,9 @@ async function settleLawfulFixerTerminalResult(admitted, authority, options, sco
25392
26126
  async function publishCollectorArtifacts(admitted, roleOutcome, coordinates) {
25393
26127
  await appendRunAttemptHistory({ role: admitted.role, runId: admitted.runId, sessionFile: coordinates.sessionFile }, roleOutcome);
25394
26128
  const artifactsDir = await ensureRunArtifactsDir(admitted.runDirectory);
25395
- const reportPath = join21(artifactsDir, "report.json");
25396
- const evidencePath = join21(artifactsDir, "evidence.json");
25397
- await writeFile5(
26129
+ const reportPath = join24(artifactsDir, "report.json");
26130
+ const evidencePath = join24(artifactsDir, "evidence.json");
26131
+ await writeFile6(
25398
26132
  reportPath,
25399
26133
  `${JSON.stringify(
25400
26134
  {
@@ -25408,7 +26142,7 @@ async function publishCollectorArtifacts(admitted, roleOutcome, coordinates) {
25408
26142
  `,
25409
26143
  "utf8"
25410
26144
  );
25411
- await writeFile5(
26145
+ await writeFile6(
25412
26146
  evidencePath,
25413
26147
  `${JSON.stringify(
25414
26148
  {
@@ -25510,9 +26244,9 @@ function extractDoctorCandidateAuditNoReceiptFact(entries) {
25510
26244
  async function publishDoctorArtifacts(admitted, roleOutcome, coordinates, options = {}) {
25511
26245
  await appendRunAttemptHistory({ role: admitted.role, runId: admitted.runId, sessionFile: coordinates.sessionFile }, roleOutcome);
25512
26246
  const artifactsDir = await ensureRunArtifactsDir(admitted.runDirectory);
25513
- const reportPath = join21(artifactsDir, "report.json");
25514
- const evidencePath = join21(artifactsDir, "evidence.json");
25515
- await writeFile5(
26247
+ const reportPath = join24(artifactsDir, "report.json");
26248
+ const evidencePath = join24(artifactsDir, "evidence.json");
26249
+ await writeFile6(
25516
26250
  reportPath,
25517
26251
  `${JSON.stringify(
25518
26252
  {
@@ -25528,7 +26262,7 @@ async function publishDoctorArtifacts(admitted, roleOutcome, coordinates, option
25528
26262
  `,
25529
26263
  "utf8"
25530
26264
  );
25531
- await writeFile5(
26265
+ await writeFile6(
25532
26266
  evidencePath,
25533
26267
  `${JSON.stringify(
25534
26268
  {
@@ -25766,9 +26500,9 @@ function extractReviewerMethodInvocations(entries, options) {
25766
26500
  async function publishReviewerArtifacts(admitted, roleOutcome, coordinates, options) {
25767
26501
  await appendRunAttemptHistory({ role: admitted.role, runId: admitted.runId, sessionFile: coordinates.sessionFile }, roleOutcome);
25768
26502
  const artifactsDir = await ensureRunArtifactsDir(admitted.runDirectory);
25769
- const reportPath = join21(artifactsDir, "report.json");
25770
- const evidencePath = join21(artifactsDir, "evidence.json");
25771
- await writeFile5(
26503
+ const reportPath = join24(artifactsDir, "report.json");
26504
+ const evidencePath = join24(artifactsDir, "evidence.json");
26505
+ await writeFile6(
25772
26506
  reportPath,
25773
26507
  `${JSON.stringify(
25774
26508
  {
@@ -25782,7 +26516,7 @@ async function publishReviewerArtifacts(admitted, roleOutcome, coordinates, opti
25782
26516
  `,
25783
26517
  "utf8"
25784
26518
  );
25785
- await writeFile5(
26519
+ await writeFile6(
25786
26520
  evidencePath,
25787
26521
  `${JSON.stringify(
25788
26522
  {
@@ -25871,9 +26605,9 @@ function extractMergerMethodInvocations(entries, options) {
25871
26605
  async function publishMergerArtifacts(admitted, roleOutcome, coordinates, options) {
25872
26606
  await appendRunAttemptHistory({ role: admitted.role, runId: admitted.runId, sessionFile: coordinates.sessionFile }, roleOutcome);
25873
26607
  const artifactsDir = await ensureRunArtifactsDir(admitted.runDirectory);
25874
- const reportPath = join21(artifactsDir, "report.json");
25875
- const evidencePath = join21(artifactsDir, "evidence.json");
25876
- await writeFile5(
26608
+ const reportPath = join24(artifactsDir, "report.json");
26609
+ const evidencePath = join24(artifactsDir, "evidence.json");
26610
+ await writeFile6(
25877
26611
  reportPath,
25878
26612
  `${JSON.stringify(
25879
26613
  {
@@ -25887,7 +26621,7 @@ async function publishMergerArtifacts(admitted, roleOutcome, coordinates, option
25887
26621
  `,
25888
26622
  "utf8"
25889
26623
  );
25890
- await writeFile5(
26624
+ await writeFile6(
25891
26625
  evidencePath,
25892
26626
  `${JSON.stringify(
25893
26627
  {
@@ -25991,13 +26725,13 @@ function publicationAttemptFromError(path, error) {
25991
26725
  }
25992
26726
  function uniqueFailureFallbackDirs(runDirectory, baseDir) {
25993
26727
  const dirs = [];
25994
- for (const dir of [baseDir, runDirectory, dirname11(runDirectory)]) {
26728
+ for (const dir of [baseDir, runDirectory, dirname12(runDirectory)]) {
25995
26729
  if (!dirs.includes(dir)) dirs.push(dir);
25996
26730
  }
25997
26731
  return dirs;
25998
26732
  }
25999
26733
  async function resolveFailureArtifactsBase(runDirectory) {
26000
- const artifactsDir = join21(runDirectory, "artifacts");
26734
+ const artifactsDir = roleRunArtifactsDirectory(runDirectory);
26001
26735
  try {
26002
26736
  await ensureRunArtifactsDir(runDirectory);
26003
26737
  return { baseDir: artifactsDir };
@@ -26013,13 +26747,13 @@ async function writeFailureJsonRetainingCause(preferredCandidates, uniqueFallbac
26013
26747
  const candidates = [
26014
26748
  ...preferredCandidates,
26015
26749
  // One unique name per fallback dir — collisions on fixed names cannot exhaust this.
26016
- ...uniqueFallbackDirs.map((dir) => join21(dir, `${stem}.${randomUUID3()}.json`))
26750
+ ...uniqueFallbackDirs.map((dir) => join24(dir, `${stem}.${randomUUID3()}.json`))
26017
26751
  ];
26018
26752
  for (let i = 0; i < candidates.length; i += 1) {
26019
26753
  const path = candidates[i];
26020
26754
  const payload = issues.length === 0 ? basePayload : { ...basePayload, publicationIssues: issues };
26021
26755
  try {
26022
- await writeFile5(
26756
+ await writeFile6(
26023
26757
  path,
26024
26758
  `${JSON.stringify(payload, null, 2)}
26025
26759
  `,
@@ -26058,26 +26792,26 @@ async function publishFailureArtifacts(admitted, failure, authority) {
26058
26792
  } catch (error) {
26059
26793
  priorIssues.push(publicationAttemptFromError(sessionFile, error));
26060
26794
  }
26061
- const underArtifacts = baseDir === join21(admitted.runDirectory, "artifacts");
26795
+ const underArtifacts = baseDir === roleRunArtifactsDirectory(admitted.runDirectory);
26062
26796
  const uniqueFallbackDirs = uniqueFailureFallbackDirs(
26063
26797
  admitted.runDirectory,
26064
26798
  baseDir
26065
26799
  );
26066
26800
  const errorCandidates = underArtifacts ? [
26067
- join21(baseDir, "error.json"),
26068
- join21(baseDir, "error.settlement.json"),
26069
- join21(admitted.runDirectory, "error.settlement.json")
26801
+ join24(baseDir, "error.json"),
26802
+ join24(baseDir, "error.settlement.json"),
26803
+ join24(admitted.runDirectory, "error.settlement.json")
26070
26804
  ] : [
26071
- join21(baseDir, "error.settlement.json"),
26072
- join21(baseDir, "error.json")
26805
+ join24(baseDir, "error.settlement.json"),
26806
+ join24(baseDir, "error.json")
26073
26807
  ];
26074
26808
  const evidenceCandidates = underArtifacts ? [
26075
- join21(baseDir, "evidence.json"),
26076
- join21(baseDir, "evidence.settlement.json"),
26077
- join21(admitted.runDirectory, "evidence.settlement.json")
26809
+ join24(baseDir, "evidence.json"),
26810
+ join24(baseDir, "evidence.settlement.json"),
26811
+ join24(admitted.runDirectory, "evidence.settlement.json")
26078
26812
  ] : [
26079
- join21(baseDir, "evidence.settlement.json"),
26080
- join21(baseDir, "evidence.json")
26813
+ join24(baseDir, "evidence.settlement.json"),
26814
+ join24(baseDir, "evidence.json")
26081
26815
  ];
26082
26816
  const errorPayloadBase = {
26083
26817
  kind: "error",
@@ -26272,6 +27006,7 @@ var init_settlement = __esm({
26272
27006
  init_method_skill();
26273
27007
  init_navigator_invocation_identity();
26274
27008
  init_receipt_delivery_policy();
27009
+ init_role_run_placement();
26275
27010
  init_invocation();
26276
27011
  init_terminal();
26277
27012
  COLLECTOR_INFRASTRUCTURE_TOOLS = /* @__PURE__ */ new Set([
@@ -26327,17 +27062,17 @@ var init_turn_request = __esm({
26327
27062
  });
26328
27063
 
26329
27064
  // src/session-identity.ts
26330
- import { mkdir as mkdir4, readFile as readFile17, rename, writeFile as writeFile6 } from "node:fs/promises";
26331
- import { dirname as dirname12, join as join22 } from "node:path";
27065
+ import { mkdir as mkdir3, readFile as readFile18, rename as rename2, writeFile as writeFile7 } from "node:fs/promises";
27066
+ import { dirname as dirname13, join as join25 } from "node:path";
26332
27067
  function createSessionIdentityAuthority(authority, sessionBindingFile) {
26333
- const bindingPath = (principal) => join22(authority.decode(principal).sessionDirectory, sessionBindingFile);
27068
+ const bindingPath = (principal) => join25(authority.decode(principal).sessionDirectory, sessionBindingFile);
26334
27069
  return {
26335
27070
  resolveSessionFile(principal) {
26336
27071
  return authority.decode(principal).sessionFile;
26337
27072
  },
26338
27073
  async load(principal) {
26339
27074
  try {
26340
- const value = JSON.parse(await readFile17(bindingPath(principal), "utf8"));
27075
+ const value = JSON.parse(await readFile18(bindingPath(principal), "utf8"));
26341
27076
  if (typeof value !== "object" || value === null || typeof value.sessionId !== "string") {
26342
27077
  throw new Error("durable session binding is invalid");
26343
27078
  }
@@ -26349,11 +27084,11 @@ function createSessionIdentityAuthority(authority, sessionBindingFile) {
26349
27084
  },
26350
27085
  async bind(principal, sessionId) {
26351
27086
  const target = bindingPath(principal);
26352
- await mkdir4(dirname12(target), { recursive: true });
27087
+ await mkdir3(dirname13(target), { recursive: true });
26353
27088
  const temporary = `${target}.${process.pid}.tmp`;
26354
- await writeFile6(temporary, `${JSON.stringify({ sessionId })}
27089
+ await writeFile7(temporary, `${JSON.stringify({ sessionId })}
26355
27090
  `, { encoding: "utf8", mode: 384 });
26356
- await rename(temporary, target);
27091
+ await rename2(temporary, target);
26357
27092
  }
26358
27093
  };
26359
27094
  }
@@ -26386,9 +27121,9 @@ var init_ticket_provenance_contracts = __esm({
26386
27121
  });
26387
27122
 
26388
27123
  // src/ticket-provenance.ts
26389
- import { join as join23 } from "node:path";
27124
+ import { join as join26 } from "node:path";
26390
27125
  function ticketProvenanceSubject(ticketNumber) {
26391
- if (!Number.isSafeInteger(ticketNumber) || ticketNumber < 1) {
27126
+ if (!isSafePositiveTicketNumber(ticketNumber)) {
26392
27127
  throw new Error(`ticket-provenance subject requires a positive ticket number, got ${String(ticketNumber)}`);
26393
27128
  }
26394
27129
  return String(ticketNumber);
@@ -26404,21 +27139,22 @@ function resolveTicketProvenanceVolume(ticketNumber, cwd, home) {
26404
27139
  return {
26405
27140
  recordFile: path.recordFile,
26406
27141
  volumeDir: path.sessionDir,
26407
- humanViewFile: join23(path.sessionDir, TICKET_PROVENANCE_HUMAN_VIEW)
27142
+ humanViewFile: join26(path.sessionDir, TICKET_PROVENANCE_HUMAN_VIEW)
26408
27143
  };
26409
27144
  }
26410
27145
  var init_ticket_provenance = __esm({
26411
27146
  "src/ticket-provenance.ts"() {
26412
27147
  "use strict";
26413
27148
  init_sitian_facade();
27149
+ init_run_ticket_number();
26414
27150
  init_ticket_provenance_contracts();
26415
27151
  }
26416
27152
  });
26417
27153
 
26418
27154
  // src/public-cli/case-dossier-delivery.ts
26419
- import { mkdtemp, readFile as readFile18, rm, writeFile as writeFile7 } from "node:fs/promises";
27155
+ import { mkdtemp, readFile as readFile19, rm, writeFile as writeFile8 } from "node:fs/promises";
26420
27156
  import { tmpdir } from "node:os";
26421
- import { join as join24 } from "node:path";
27157
+ import { join as join27 } from "node:path";
26422
27158
  function describeDossierFile(path) {
26423
27159
  return path;
26424
27160
  }
@@ -26444,10 +27180,10 @@ async function deliverCaseDossierAsAttachment(input) {
26444
27180
  home: input.home
26445
27181
  });
26446
27182
  if (section === void 0) return void 0;
26447
- const stagingDir = await mkdtemp(join24(tmpdir(), "ak-case-dossier-"));
27183
+ const stagingDir = await mkdtemp(join27(tmpdir(), "ak-case-dossier-"));
26448
27184
  try {
26449
- const stagingPath = join24(stagingDir, CASE_DOSSIER_ATTACH_FILE);
26450
- await writeFile7(stagingPath, `${section}
27185
+ const stagingPath = join27(stagingDir, CASE_DOSSIER_ATTACH_FILE);
27186
+ await writeFile8(stagingPath, `${section}
26451
27187
  `, "utf8");
26452
27188
  return await freezeAttachmentsIntoRun(
26453
27189
  [stagingPath],
@@ -26471,9 +27207,9 @@ var init_case_dossier_delivery = __esm({
26471
27207
  });
26472
27208
 
26473
27209
  // src/host-transition-prior-native.ts
26474
- import { access as access3, readdir as readdir6 } from "node:fs/promises";
26475
- import { dirname as dirname13, join as join25 } from "node:path";
26476
- function isEnoent2(error) {
27210
+ import { access as access3, readdir as readdir8 } from "node:fs/promises";
27211
+ import { dirname as dirname14, join as join28 } from "node:path";
27212
+ function isEnoent3(error) {
26477
27213
  return typeof error === "object" && error !== null && error.code === "ENOENT";
26478
27214
  }
26479
27215
  async function listPiNativeRecordPaths(sessionFile) {
@@ -26481,28 +27217,28 @@ async function listPiNativeRecordPaths(sessionFile) {
26481
27217
  await access3(sessionFile);
26482
27218
  return [sessionFile];
26483
27219
  } catch (error) {
26484
- if (isEnoent2(error)) return [];
27220
+ if (isEnoent3(error)) return [];
26485
27221
  throw error;
26486
27222
  }
26487
27223
  }
26488
27224
  async function listSitianRecordPaths(sessionParent) {
26489
- const sessionRoot = dirname13(sessionParent);
27225
+ const sessionRoot = dirname14(sessionParent);
26490
27226
  let entries;
26491
27227
  try {
26492
- entries = await readdir6(sessionRoot, { withFileTypes: true });
27228
+ entries = await readdir8(sessionRoot, { withFileTypes: true });
26493
27229
  } catch (error) {
26494
- if (isEnoent2(error)) return [];
27230
+ if (isEnoent3(error)) return [];
26495
27231
  throw error;
26496
27232
  }
26497
27233
  const recordPaths = [];
26498
27234
  for (const entry of entries) {
26499
27235
  if (!entry.isDirectory()) continue;
26500
- const recordFile = join25(sessionRoot, entry.name, "records.jsonl");
27236
+ const recordFile = join28(sessionRoot, entry.name, "records.jsonl");
26501
27237
  try {
26502
27238
  await access3(recordFile);
26503
27239
  recordPaths.push(recordFile);
26504
27240
  } catch (error) {
26505
- if (!isEnoent2(error)) throw error;
27241
+ if (!isEnoent3(error)) throw error;
26506
27242
  }
26507
27243
  }
26508
27244
  recordPaths.sort();
@@ -26566,8 +27302,8 @@ var init_public_run_credentials = __esm({
26566
27302
  // src/public-cli/auto-resume.ts
26567
27303
  import { constants as fsConstants2 } from "node:fs";
26568
27304
  import { randomUUID as randomUUID4 } from "node:crypto";
26569
- import { lstat as lstat5, mkdir as mkdir5, open as open2 } from "node:fs/promises";
26570
- import { join as join26 } from "node:path";
27305
+ import { lstat as lstat6, mkdir as mkdir4, open as open2 } from "node:fs/promises";
27306
+ import { join as join29 } from "node:path";
26571
27307
  async function persistReturnedRunState(admitted, authority, options) {
26572
27308
  if (options?.lawful === true) {
26573
27309
  await markRunTerminal(admitted.runDirectory);
@@ -26602,24 +27338,21 @@ async function finalizeExceptionRunBestEffort(runDirectory, io) {
26602
27338
  );
26603
27339
  }
26604
27340
  }
26605
- function runArtifactsDirectory(runDirectory) {
26606
- return join26(runDirectory, "artifacts");
26607
- }
26608
27341
  async function ensureRealArtifactsDirectory(runDirectory) {
26609
- const runStat = await lstat5(runDirectory);
27342
+ const runStat = await lstat6(runDirectory);
26610
27343
  if (runStat.isSymbolicLink() || !runStat.isDirectory()) {
26611
27344
  throw new Error("run artifact retention: run directory is not a real directory");
26612
27345
  }
26613
- const artifactsDir = runArtifactsDirectory(runDirectory);
27346
+ const artifactsDir = roleRunArtifactsDirectory(runDirectory);
26614
27347
  try {
26615
- const existing = await lstat5(artifactsDir);
27348
+ const existing = await lstat6(artifactsDir);
26616
27349
  if (existing.isSymbolicLink() || !existing.isDirectory()) {
26617
27350
  throw new Error("run artifact retention: artifacts path is not a real directory");
26618
27351
  }
26619
27352
  } catch (error) {
26620
- if (!isMissingPathError4(error)) throw error;
26621
- await mkdir5(artifactsDir, { recursive: true });
26622
- const created = await lstat5(artifactsDir);
27353
+ if (!isMissingPathError5(error)) throw error;
27354
+ await mkdir4(artifactsDir, { recursive: true });
27355
+ const created = await lstat6(artifactsDir);
26623
27356
  if (created.isSymbolicLink() || !created.isDirectory()) {
26624
27357
  throw new Error("run artifact retention: artifacts directory is not a real directory");
26625
27358
  }
@@ -26649,7 +27382,7 @@ function serializeThrownValue(value, depth = 0, seen = /* @__PURE__ */ new WeakS
26649
27382
  }
26650
27383
  return value;
26651
27384
  }
26652
- function isMissingPathError4(error) {
27385
+ function isMissingPathError5(error) {
26653
27386
  return error instanceof Error && "code" in error && error.code === "ENOENT";
26654
27387
  }
26655
27388
  function transferNestedValue(value, depth, seen) {
@@ -26685,7 +27418,7 @@ function jsonSafeReplacer() {
26685
27418
  };
26686
27419
  }
26687
27420
  async function writeHardenedArtifactFile(artifactsDir, namePrefix, payload) {
26688
- const filePath = join26(artifactsDir, `${namePrefix}-${randomUUID4()}.json`);
27421
+ const filePath = join29(artifactsDir, `${namePrefix}-${randomUUID4()}.json`);
26689
27422
  const body = `${JSON.stringify(payload, jsonSafeReplacer(), 2)}
26690
27423
  `;
26691
27424
  const noFollowFlag = typeof fsConstants2.O_NOFOLLOW === "number" ? fsConstants2.O_NOFOLLOW : 0;
@@ -26934,6 +27667,7 @@ var dummyIo, TurnDispatchedFailure, DISPATCH_ERROR_RETENTION_ENTRY_TYPE;
26934
27667
  var init_auto_resume = __esm({
26935
27668
  "src/public-cli/auto-resume.ts"() {
26936
27669
  "use strict";
27670
+ init_role_run_placement();
26937
27671
  init_run_lifecycle();
26938
27672
  init_config2();
26939
27673
  init_terminal();
@@ -26956,8 +27690,8 @@ var init_auto_resume = __esm({
26956
27690
 
26957
27691
  // src/public-cli/post-admission.ts
26958
27692
  import { randomUUID as randomUUID5 } from "node:crypto";
26959
- import { readFile as readFile19, writeFile as writeFile8 } from "node:fs/promises";
26960
- import { isAbsolute as isAbsolute8, join as join27, resolve as resolve9 } from "node:path";
27693
+ import { readFile as readFile20, writeFile as writeFile9 } from "node:fs/promises";
27694
+ import { isAbsolute as isAbsolute8, join as join30, resolve as resolve8 } from "node:path";
26961
27695
  function describeCaughtError(error) {
26962
27696
  if (error instanceof Error) {
26963
27697
  const code = error.code;
@@ -26980,9 +27714,9 @@ function withOnceSuccessfulBeforeDispatch(adapters) {
26980
27714
  let succeeded = false;
26981
27715
  return {
26982
27716
  ...adapters,
26983
- beforeDispatch: async (admitted) => {
27717
+ beforeDispatch: async (admitted, lease) => {
26984
27718
  if (succeeded) return;
26985
- await hook(admitted);
27719
+ await hook(admitted, lease);
26986
27720
  succeeded = true;
26987
27721
  }
26988
27722
  };
@@ -27001,8 +27735,8 @@ async function recordBestEffortPostDispatchDiagnostic(admitted, env, diagnostic,
27001
27735
  } catch (appendError) {
27002
27736
  try {
27003
27737
  const artifactsDir = await ensureRealArtifactsDirectory(admitted.runDirectory);
27004
- await writeFile8(
27005
- join27(artifactsDir, `post-admission-diagnostic-${randomUUID5()}.json`),
27738
+ await writeFile9(
27739
+ join30(artifactsDir, `post-admission-diagnostic-${randomUUID5()}.json`),
27006
27740
  `${JSON.stringify({ version: 1, ...payload }, null, 2)}
27007
27741
  `,
27008
27742
  { encoding: "utf8", flag: "wx" }
@@ -27018,7 +27752,7 @@ async function recordBestEffortPostDispatchDiagnostic(admitted, env, diagnostic,
27018
27752
  }
27019
27753
  async function readInvocationHost(runDirectory) {
27020
27754
  try {
27021
- const raw = JSON.parse(await readFile19(join27(runDirectory, "invocation.json"), "utf8"));
27755
+ const raw = JSON.parse(await readFile20(join30(runDirectory, "invocation.json"), "utf8"));
27022
27756
  return typeof raw.host === "string" && raw.host.trim() !== "" ? raw.host : void 0;
27023
27757
  } catch (error) {
27024
27758
  if (error.code === "ENOENT") return void 0;
@@ -27136,6 +27870,44 @@ async function dispatchPostAdmissionTurn(input) {
27136
27870
  const persistRunState = input.persistRunState !== false;
27137
27871
  const deferredPersist = persistRunState ? {} : { needsPersist: true };
27138
27872
  const shouldPresent = adapters.shouldPresentSettled ?? ((terminal) => isLawfulTypedTerminalOutcome(terminal.roleOutcome));
27873
+ let afterDispatchApplied = false;
27874
+ const finishAfterTurn = async (result2) => {
27875
+ if (adapters.afterDispatch === void 0 || afterDispatchApplied) return result2;
27876
+ afterDispatchApplied = true;
27877
+ try {
27878
+ await adapters.afterDispatch(admitted, lease);
27879
+ return result2;
27880
+ } catch (error) {
27881
+ const primaryFailure = result2.terminal !== void 0 && !isLawfulTypedTerminalOutcome(result2.terminal.roleOutcome);
27882
+ if (primaryFailure) {
27883
+ await recordBestEffortPostDispatchDiagnostic(
27884
+ admitted,
27885
+ env,
27886
+ `afterDispatch failed beside primary terminal (best-effort continue): ${describeErrorIdentity(error)}`,
27887
+ io
27888
+ );
27889
+ return result2;
27890
+ }
27891
+ return {
27892
+ ...await presentControlledFailure2(
27893
+ admitted,
27894
+ {
27895
+ timedOut: false,
27896
+ code: null,
27897
+ stderr: "",
27898
+ thrown: error
27899
+ },
27900
+ adapters,
27901
+ env.principalAuthority,
27902
+ io,
27903
+ persistRunState
27904
+ ),
27905
+ ...result2.turnDispatched === true ? { turnDispatched: true } : {},
27906
+ ...result2.skipAutoResume === true ? { skipAutoResume: true } : {},
27907
+ ...deferredPersist
27908
+ };
27909
+ }
27910
+ };
27139
27911
  try {
27140
27912
  const missingCredential = missingCredentialPreDispatchFailure(
27141
27913
  env.model,
@@ -27187,7 +27959,7 @@ async function dispatchPostAdmissionTurn(input) {
27187
27959
  await clearReviewerDispatchRejection(admitted.runDirectory);
27188
27960
  if (adapters.beforeDispatch !== void 0) {
27189
27961
  try {
27190
- await adapters.beforeDispatch(admitted);
27962
+ await adapters.beforeDispatch(admitted, lease);
27191
27963
  } catch (error) {
27192
27964
  const settled2 = await presentControlledFailure2(
27193
27965
  admitted,
@@ -27262,12 +28034,12 @@ async function dispatchPostAdmissionTurn(input) {
27262
28034
  io,
27263
28035
  persistRunState
27264
28036
  );
27265
- return { ...settled2, turnDispatched: true, ...deferredPersist };
28037
+ return await finishAfterTurn({ ...settled2, turnDispatched: true, ...deferredPersist });
27266
28038
  }
27267
28039
  let stderrLogWriteFailure;
27268
28040
  try {
27269
- await writeFile8(
27270
- join27(admitted.runDirectory, "stderr.log"),
28041
+ await writeFile9(
28042
+ join30(admitted.runDirectory, "stderr.log"),
27271
28043
  result2.stderr,
27272
28044
  "utf8"
27273
28045
  );
@@ -27341,7 +28113,7 @@ async function dispatchPostAdmissionTurn(input) {
27341
28113
  io,
27342
28114
  persistRunState
27343
28115
  );
27344
- return { ...settledFailure, turnDispatched: true, ...deferredPersist };
28116
+ return await finishAfterTurn({ ...settledFailure, turnDispatched: true, ...deferredPersist });
27345
28117
  }
27346
28118
  if (settledOutcome !== void 0) {
27347
28119
  if (persistRunState) {
@@ -27362,10 +28134,10 @@ async function dispatchPostAdmissionTurn(input) {
27362
28134
  io,
27363
28135
  persistRunState
27364
28136
  );
27365
- return { ...failed, turnDispatched: true, ...deferredPersist };
28137
+ return await finishAfterTurn({ ...failed, turnDispatched: true, ...deferredPersist });
27366
28138
  }
27367
28139
  }
27368
- return { ...settledOutcome, ...deferredPersist };
28140
+ return await finishAfterTurn({ ...settledOutcome, ...deferredPersist });
27369
28141
  }
27370
28142
  if (hostSignalFailed) {
27371
28143
  const resolutionInput = controlledFailureInputFromResolution(resolution);
@@ -27392,7 +28164,7 @@ async function dispatchPostAdmissionTurn(input) {
27392
28164
  io,
27393
28165
  persistRunState
27394
28166
  );
27395
- return { ...failed, turnDispatched: true, ...deferredPersist };
28167
+ return await finishAfterTurn({ ...failed, turnDispatched: true, ...deferredPersist });
27396
28168
  }
27397
28169
  if (stderrLogWriteFailure !== void 0) {
27398
28170
  const failed = await settleAfterTurnStarted(
@@ -27408,7 +28180,7 @@ async function dispatchPostAdmissionTurn(input) {
27408
28180
  io,
27409
28181
  persistRunState
27410
28182
  );
27411
- return { ...failed, turnDispatched: true, ...deferredPersist };
28183
+ return await finishAfterTurn({ ...failed, turnDispatched: true, ...deferredPersist });
27412
28184
  }
27413
28185
  const noReceipt = await attachRecordedSubmissions(
27414
28186
  admitted,
@@ -27433,16 +28205,16 @@ async function dispatchPostAdmissionTurn(input) {
27433
28205
  io,
27434
28206
  persistRunState
27435
28207
  );
27436
- return { ...failed, turnDispatched: true, ...deferredPersist };
28208
+ return await finishAfterTurn({ ...failed, turnDispatched: true, ...deferredPersist });
27437
28209
  }
27438
28210
  }
27439
- return {
28211
+ return await finishAfterTurn({
27440
28212
  exitCode: exitCodeForTerminalOutcome(noReceipt.roleOutcome),
27441
28213
  admitted,
27442
28214
  terminal: noReceipt,
27443
28215
  turnDispatched: true,
27444
28216
  ...deferredPersist
27445
- };
28217
+ });
27446
28218
  } finally {
27447
28219
  try {
27448
28220
  await lease.release();
@@ -27513,8 +28285,8 @@ async function dispatchAfterWriterLease(input) {
27513
28285
  }
27514
28286
  }
27515
28287
  function isAlreadyFrozenSummonsAttachment(runDirectory, attachmentPath) {
27516
- const absolute = isAbsolute8(attachmentPath) ? attachmentPath : resolve9(attachmentPath);
27517
- return pathContainedIn(join27(runDirectory, "attachments"), absolute);
28288
+ const absolute = isAbsolute8(attachmentPath) ? attachmentPath : resolve8(attachmentPath);
28289
+ return pathContainedIn(join30(runDirectory, "attachments"), absolute);
27518
28290
  }
27519
28291
  async function prepareSummonsResumeMaterials(runDirectory, summons) {
27520
28292
  if (summons === void 0) return void 0;
@@ -28163,7 +28935,7 @@ async function runPublicInstructionSeat(argv, env, io, role, parseArgv2) {
28163
28935
  home: env.home
28164
28936
  });
28165
28937
  auditorSourceRun = resolved.runDirectory;
28166
- auditorSourceTicket = await readRunTicketNumber(resolved.runDirectory);
28938
+ auditorSourceTicket = await readBoardTicketNumber(resolved.runDirectory);
28167
28939
  } catch (error) {
28168
28940
  presentStructuralRejection(
28169
28941
  new CliUsageError(error instanceof Error ? error.message : String(error)),
@@ -28211,7 +28983,8 @@ async function runPublicInstructionSeat(argv, env, io, role, parseArgv2) {
28211
28983
  ...parsed.project === void 0 ? {} : { project: parsed.project },
28212
28984
  ...env.createRunId === void 0 ? {} : { createRunId: env.createRunId },
28213
28985
  ...env.model === void 0 ? {} : { model: env.model },
28214
- ...env.correlationId === void 0 ? {} : { correlationId: env.correlationId }
28986
+ ...env.correlationId === void 0 ? {} : { correlationId: env.correlationId },
28987
+ ...auditorSourceTicket === void 0 ? {} : { assertedTicketNumber: auditorSourceTicket }
28215
28988
  });
28216
28989
  } catch (error) {
28217
28990
  if (error instanceof CliUsageError) {
@@ -28253,13 +29026,7 @@ async function runPublicInstructionSeat(argv, env, io, role, parseArgv2) {
28253
29026
  env,
28254
29027
  io,
28255
29028
  request: turnRequest,
28256
- adapters: instructionSeatAdapters({
28257
- beforeDispatch: async (admittedSeat) => {
28258
- if (auditorSourceTicket !== void 0) {
28259
- await bindAdmittedTicketNumber(admittedSeat, auditorSourceTicket);
28260
- }
28261
- }
28262
- }),
29029
+ adapters: instructionSeatAdapters(),
28263
29030
  ...env.engine === void 0 ? {} : { effectiveEngine: env.engine }
28264
29031
  });
28265
29032
  }
@@ -28983,10 +29750,26 @@ function buildDiaristTurnRequest(admitted, options) {
28983
29750
  options
28984
29751
  );
28985
29752
  }
28986
- function diaristAdapters() {
29753
+ async function bindAndRelocateDiaristIfBoardBound(admitted, authority, lease) {
29754
+ const boardTicket = await readBoardTicketNumber(admitted.runDirectory);
29755
+ if (boardTicket === void 0) return;
29756
+ if (admitted.ticketNumber === void 0) {
29757
+ await bindAdmittedTicketNumber(admitted, boardTicket);
29758
+ }
29759
+ await relocateAdmittedRunToTicket(admitted, authority, lease);
29760
+ }
29761
+ function diaristAdapters(env) {
28987
29762
  return {
28988
29763
  trySettle: (admitted, authority, scope) => trySettleDiaristTerminalResult(admitted, authority, scope),
28989
- shouldPresentSettled: () => true
29764
+ shouldPresentSettled: () => true,
29765
+ // Resume interrupted state: board ticket already on pages, run still under unbound/.
29766
+ beforeDispatch: async (admitted, lease) => {
29767
+ await bindAndRelocateDiaristIfBoardBound(admitted, env.principalAuthority, lease);
29768
+ },
29769
+ // First post-turn assert: accept hook wrote board pages; relocate before lease release.
29770
+ afterDispatch: async (admitted, lease) => {
29771
+ await bindAndRelocateDiaristIfBoardBound(admitted, env.principalAuthority, lease);
29772
+ }
28990
29773
  };
28991
29774
  }
28992
29775
  async function runPublicDiarist(argv, env, io, parseDiaristArgv2) {
@@ -29034,7 +29817,8 @@ async function runPublicDiarist(argv, env, io, parseDiaristArgv2) {
29034
29817
  ...parsed.project === void 0 ? {} : { project: parsed.project },
29035
29818
  ...env.createRunId === void 0 ? {} : { createRunId: env.createRunId },
29036
29819
  ...env.model === void 0 ? {} : { model: env.model },
29037
- ...env.correlationId === void 0 ? {} : { correlationId: env.correlationId }
29820
+ ...env.correlationId === void 0 ? {} : { correlationId: env.correlationId },
29821
+ ...handoffTicket === void 0 ? {} : { assertedTicketNumber: handoffTicket }
29038
29822
  });
29039
29823
  } catch (error) {
29040
29824
  if (error instanceof CliUsageError) {
@@ -29044,9 +29828,6 @@ async function runPublicDiarist(argv, env, io, parseDiaristArgv2) {
29044
29828
  throw error;
29045
29829
  }
29046
29830
  await markRunAdmitted(admitted, env.principalAuthority);
29047
- if (typeof handoffTicket === "number" && Number.isSafeInteger(handoffTicket) && handoffTicket >= 1) {
29048
- await bindAdmittedTicketNumber(admitted, handoffTicket);
29049
- }
29050
29831
  const turnProjection = {
29051
29832
  packageRoot: env.packageRoot,
29052
29833
  home: env.home,
@@ -29072,19 +29853,8 @@ async function runPublicDiarist(argv, env, io, parseDiaristArgv2) {
29072
29853
  env,
29073
29854
  io,
29074
29855
  request: turnRequest,
29075
- adapters: diaristAdapters(),
29856
+ adapters: diaristAdapters(env),
29076
29857
  ...env.engine === void 0 ? {} : { effectiveEngine: env.engine }
29077
- }).then(async (result2) => {
29078
- if (admitted.ticketNumber === void 0 && result2.admitted !== void 0) {
29079
- const fromPages = await readRunTicketNumber(admitted.runDirectory);
29080
- if (fromPages !== void 0) {
29081
- await bindAdmittedTicketNumber(admitted, fromPages);
29082
- if (result2.admitted.ticketNumber === void 0) {
29083
- result2.admitted.ticketNumber = fromPages;
29084
- }
29085
- }
29086
- }
29087
- return result2;
29088
29858
  });
29089
29859
  }
29090
29860
  async function runPublicDiaristResume(request, env, io) {
@@ -29108,7 +29878,7 @@ async function runPublicDiaristResume(request, env, io) {
29108
29878
  )
29109
29879
  );
29110
29880
  },
29111
- adapters: diaristAdapters(),
29881
+ adapters: diaristAdapters(env),
29112
29882
  ...env.engine === void 0 ? {} : { effectiveEngine: env.engine }
29113
29883
  });
29114
29884
  }
@@ -29135,8 +29905,8 @@ __export(public_role_summons_exports, {
29135
29905
  summonGateOfficer: () => summonGateOfficer,
29136
29906
  summonPublicRole: () => summonPublicRole
29137
29907
  });
29138
- import { existsSync as existsSync9 } from "node:fs";
29139
- import { join as join28 } from "node:path";
29908
+ import { existsSync as existsSync10 } from "node:fs";
29909
+ import { join as join31 } from "node:path";
29140
29910
  function createCapturingIo() {
29141
29911
  const chunks = [];
29142
29912
  return {
@@ -29159,7 +29929,7 @@ function parentDir(path) {
29159
29929
  function walkPackageRoot(start) {
29160
29930
  let dir = start;
29161
29931
  for (let i = 0; i < 12; i += 1) {
29162
- if (existsSync9(join28(dir, "package.json")) && existsSync9(join28(dir, "souls"))) {
29932
+ if (existsSync10(join31(dir, "package.json")) && existsSync10(join31(dir, "souls"))) {
29163
29933
  return dir;
29164
29934
  }
29165
29935
  const parent = parentDir(dir);
@@ -29253,7 +30023,7 @@ async function createSummonEnv(options) {
29253
30023
  async function summonPublicRole(options) {
29254
30024
  const packageRoot2 = resolveSummonsPackageRoot(options.packageRoot);
29255
30025
  const home = await resolveSummonHome(options);
29256
- const agentDir = options.agentDir ?? process.env.PI_CODING_AGENT_DIR ?? join28(home, ".pi", "agent");
30026
+ const agentDir = options.agentDir ?? process.env.PI_CODING_AGENT_DIR ?? join31(home, ".pi", "agent");
29257
30027
  const {
29258
30028
  loadCredentialProviders: loadCredentialProviders2,
29259
30029
  loadPublicCliConfig: loadPublicCliConfig2,
@@ -29469,6 +30239,30 @@ function buildCountersignTurnRequest(admitted, options) {
29469
30239
  options
29470
30240
  );
29471
30241
  }
30242
+ function courtTicketNumbersFromOutcome(roleOutcome, principalTicket) {
30243
+ if (roleOutcome === void 0) return void 0;
30244
+ const payloads = roleOutcome.kind === "accepted" || roleOutcome.kind === "audit_escalation" || roleOutcome.kind === "failure" ? roleOutcome.payloads ?? [] : [];
30245
+ let latest;
30246
+ for (const payload of payloads) {
30247
+ if (typeof payload !== "object" || payload === null || Array.isArray(payload)) {
30248
+ continue;
30249
+ }
30250
+ const record4 = payload;
30251
+ if (!Object.hasOwn(record4, "courtTicketNumbers")) continue;
30252
+ const raw = record4.courtTicketNumbers;
30253
+ if (!Array.isArray(raw)) continue;
30254
+ const members = projectCourtTicketNumbers(raw);
30255
+ if (members === null) continue;
30256
+ if (members.length === 0) {
30257
+ if (raw.length === 0) {
30258
+ latest = projectCourtTicketNumbers([], { principalTicket }) ?? void 0;
30259
+ }
30260
+ continue;
30261
+ }
30262
+ latest = projectCourtTicketNumbers(raw, { principalTicket }) ?? void 0;
30263
+ }
30264
+ return latest;
30265
+ }
29472
30266
  function courtDiaristEscalated(roleOutcome) {
29473
30267
  if (roleOutcome === void 0) return false;
29474
30268
  if (roleOutcome.kind === "audit_escalation") return true;
@@ -29519,9 +30313,14 @@ async function invokeCourtDiarist(input, env, io) {
29519
30313
  };
29520
30314
  }
29521
30315
  const asserted = result2.admitted?.ticketNumber;
29522
- if (typeof asserted === "number" && Number.isSafeInteger(asserted) && asserted >= 1) {
30316
+ if (isSafePositiveTicketNumber(asserted)) {
30317
+ const courtTicketNumbers = courtTicketNumbersFromOutcome(roleOutcome, asserted);
29523
30318
  return {
29524
- identity: { kind: "ticket", ticketNumber: asserted }
30319
+ identity: {
30320
+ kind: "ticket",
30321
+ ticketNumber: asserted,
30322
+ ...courtTicketNumbers === void 0 ? {} : { courtTicketNumbers }
30323
+ }
29525
30324
  };
29526
30325
  }
29527
30326
  return {
@@ -29534,24 +30333,37 @@ async function runCountersignCourtDiaristStation(admitted, env, io) {
29534
30333
  return;
29535
30334
  }
29536
30335
  if (admitted.ticketNumber === void 0) return;
29537
- const outcome = await invokeCourtDiarist(
29538
- {
29539
- instruction: `\u6574\u7406 #${admitted.ticketNumber} \u7684\u672C\u6848\u4F9D\u636E\u3002`,
29540
- projectRoot: admitted.projectRoot,
29541
- failureLabel: `ticket #${admitted.ticketNumber}`,
29542
- // Refresh holds a typed key — hand it off so identity is bound before turn.
29543
- boundTicketNumber: admitted.ticketNumber
29544
- },
29545
- env,
29546
- io
29547
- );
29548
- if (outcome.identity.kind === "escalate") {
29549
- throw new StationChildExhaustedError(
29550
- "court diarist station escalated (cannot identify court target)"
29551
- );
30336
+ let refreshTickets;
30337
+ if (admitted.courtTicketNumbers !== void 0) {
30338
+ if (admitted.courtTicketNumbers.length === 0 || !admitted.courtTicketNumbers.includes(admitted.ticketNumber)) {
30339
+ throw new StationChildExhaustedError(
30340
+ `court diarist station: courtTicketNumbers is damaged (empty or missing principal #${admitted.ticketNumber})`
30341
+ );
30342
+ }
30343
+ refreshTickets = admitted.courtTicketNumbers;
30344
+ } else {
30345
+ refreshTickets = [admitted.ticketNumber];
29552
30346
  }
29553
- if (outcome.failedWithoutEscalate !== void 0) {
29554
- throw new StationChildExhaustedError(outcome.failedWithoutEscalate.diagnostic);
30347
+ for (const ticketNumber of refreshTickets) {
30348
+ const outcome = await invokeCourtDiarist(
30349
+ {
30350
+ instruction: `\u6574\u7406 #${ticketNumber} \u7684\u672C\u6848\u4F9D\u636E\u3002`,
30351
+ projectRoot: admitted.projectRoot,
30352
+ failureLabel: `ticket #${ticketNumber}`,
30353
+ // Refresh holds a typed key — hand it off so identity is bound before turn.
30354
+ boundTicketNumber: ticketNumber
30355
+ },
30356
+ env,
30357
+ io
30358
+ );
30359
+ if (outcome.identity.kind === "escalate") {
30360
+ throw new StationChildExhaustedError(
30361
+ "court diarist station escalated (cannot identify court target)"
30362
+ );
30363
+ }
30364
+ if (outcome.failedWithoutEscalate !== void 0) {
30365
+ throw new StationChildExhaustedError(outcome.failedWithoutEscalate.diagnostic);
30366
+ }
29555
30367
  }
29556
30368
  }
29557
30369
  async function runPublicCountersign(argv, env, io, parseCountersignArgv2) {
@@ -29587,6 +30399,7 @@ async function runPublicCountersign(argv, env, io, parseCountersignArgv2) {
29587
30399
  }
29588
30400
  await markRunAdmitted(admitted, env.principalAuthority);
29589
30401
  let typedTicket;
30402
+ let typedCourtTicketNumbers;
29590
30403
  let identityDiaristRan = false;
29591
30404
  if (env.runCourtDiaristStation === void 0) {
29592
30405
  const outcome = await invokeCourtDiarist(
@@ -29630,7 +30443,9 @@ async function runPublicCountersign(argv, env, io, parseCountersignArgv2) {
29630
30443
  );
29631
30444
  }
29632
30445
  if (outcome.identity.kind === "ticket") {
29633
- typedTicket = outcome.identity.ticketNumber;
30446
+ const assertedTicket = outcome.identity.ticketNumber;
30447
+ typedTicket = assertedTicket;
30448
+ typedCourtTicketNumbers = outcome.identity.courtTicketNumbers;
29634
30449
  const summons = {
29635
30450
  instruction: parsed.instruction,
29636
30451
  instructionEmpty: parsed.instruction.trim() === "",
@@ -29644,13 +30459,18 @@ async function runPublicCountersign(argv, env, io, parseCountersignArgv2) {
29644
30459
  freshSummons: env.freshSummons,
29645
30460
  summons,
29646
30461
  resume: async (runId, materials) => {
30462
+ await bindAdmittedTicketNumber(admitted, assertedTicket);
30463
+ await relocateAdmittedRunToTicket(admitted, env.principalAuthority);
29647
30464
  await markRunTerminal(admitted.runDirectory);
29648
30465
  return await runPublicCountersignResume(
29649
30466
  {
29650
30467
  runId,
29651
30468
  ...materials === void 0 ? {} : { summons: materials }
29652
30469
  },
29653
- env,
30470
+ {
30471
+ ...env,
30472
+ ...typedCourtTicketNumbers === void 0 ? {} : { pendingCourtTicketNumbers: typedCourtTicketNumbers }
30473
+ },
29654
30474
  io
29655
30475
  );
29656
30476
  }
@@ -29660,6 +30480,29 @@ async function runPublicCountersign(argv, env, io, parseCountersignArgv2) {
29660
30480
  }
29661
30481
  }
29662
30482
  }
30483
+ if (identityDiaristRan && typedTicket !== void 0) {
30484
+ try {
30485
+ await bindAdmittedTicketNumber(admitted, typedTicket);
30486
+ await relocateAdmittedRunToTicket(admitted, env.principalAuthority);
30487
+ await bindCourtTicketNumbersOnAdmitted(
30488
+ admitted,
30489
+ typedCourtTicketNumbers ?? [typedTicket]
30490
+ );
30491
+ } catch (error) {
30492
+ return await presentControlledFailure2(
30493
+ admitted,
30494
+ {
30495
+ timedOut: false,
30496
+ code: null,
30497
+ stderr: "",
30498
+ thrown: error
30499
+ },
30500
+ countersignAdapters(),
30501
+ env.principalAuthority,
30502
+ io
30503
+ );
30504
+ }
30505
+ }
29663
30506
  const turnProjection = {
29664
30507
  packageRoot: env.packageRoot,
29665
30508
  home: env.home,
@@ -29680,19 +30523,23 @@ async function runPublicCountersign(argv, env, io, parseCountersignArgv2) {
29680
30523
  }
29681
30524
  };
29682
30525
  const turnRequest = buildCountersignTurnRequest(admitted, turnProjection);
29683
- return await runPostAdmissionOneShot({
30526
+ const result2 = await runPostAdmissionOneShot({
29684
30527
  admitted,
29685
30528
  env,
29686
30529
  io,
29687
30530
  request: turnRequest,
29688
30531
  adapters: countersignAdapters({
29689
- beforeDispatch: async (admittedSeat) => {
30532
+ beforeDispatch: async (admittedSeat, lease) => {
29690
30533
  if (!identityDiaristRan) {
29691
30534
  await runCountersignCourtDiaristStation(admittedSeat, env, io);
29692
30535
  } else if (typedTicket !== void 0) {
29693
- await bindAdmittedTicketNumber(admittedSeat, typedTicket);
29694
30536
  await runCountersignCourtDiaristStation(admittedSeat, env, io);
29695
30537
  }
30538
+ await relocateAdmittedRunToTicket(
30539
+ admittedSeat,
30540
+ env.principalAuthority,
30541
+ lease
30542
+ );
29696
30543
  Object.assign(
29697
30544
  turnRequest,
29698
30545
  buildCountersignTurnRequest(admittedSeat, turnProjection)
@@ -29701,6 +30548,8 @@ async function runPublicCountersign(argv, env, io, parseCountersignArgv2) {
29701
30548
  }),
29702
30549
  ...env.engine === void 0 ? {} : { effectiveEngine: env.engine }
29703
30550
  });
30551
+ await relocateAdmittedRunToTicket(admitted, env.principalAuthority);
30552
+ return result2;
29704
30553
  }
29705
30554
  function countersignAdapters(options) {
29706
30555
  return {
@@ -29737,6 +30586,15 @@ async function runPublicCountersignResume(request, env, io) {
29737
30586
  },
29738
30587
  adapters: countersignAdapters({
29739
30588
  beforeDispatch: async (admitted) => {
30589
+ if (admitted.courtTicketNumbersDamage !== void 0) {
30590
+ throw new StationChildExhaustedError(admitted.courtTicketNumbersDamage);
30591
+ }
30592
+ if (env.pendingCourtTicketNumbers !== void 0) {
30593
+ await bindCourtTicketNumbersOnAdmitted(
30594
+ admitted,
30595
+ env.pendingCourtTicketNumbers
30596
+ );
30597
+ }
29740
30598
  await runCountersignCourtDiaristStation(admitted, env, io);
29741
30599
  }
29742
30600
  }),
@@ -29748,6 +30606,8 @@ var init_countersign_run = __esm({
29748
30606
  "use strict";
29749
30607
  init_engine_material();
29750
30608
  init_cli_errors();
30609
+ init_diarist_contracts();
30610
+ init_run_ticket_number();
29751
30611
  init_invocation();
29752
30612
  init_post_admission();
29753
30613
  init_run_lifecycle();
@@ -30403,14 +31263,14 @@ var init_analyst_book_key = __esm({
30403
31263
 
30404
31264
  // src/atomic-write.ts
30405
31265
  import { randomUUID as randomUUID6 } from "node:crypto";
30406
- import { rename as rename2, rm as rm2, writeFile as writeFile9 } from "node:fs/promises";
30407
- import { dirname as dirname14, join as join29 } from "node:path";
31266
+ import { rename as rename3, rm as rm2, writeFile as writeFile10 } from "node:fs/promises";
31267
+ import { dirname as dirname15, join as join32 } from "node:path";
30408
31268
  async function writeFileAtomically(destination, contents) {
30409
- const parent = dirname14(destination);
30410
- const temporary = join29(parent, `.atomic-write-${randomUUID6()}.tmp`);
31269
+ const parent = dirname15(destination);
31270
+ const temporary = join32(parent, `.atomic-write-${randomUUID6()}.tmp`);
30411
31271
  try {
30412
- await writeFile9(temporary, contents);
30413
- await rename2(temporary, destination);
31272
+ await writeFile10(temporary, contents);
31273
+ await rename3(temporary, destination);
30414
31274
  } catch (error) {
30415
31275
  await rm2(temporary, { force: true }).catch(() => void 0);
30416
31276
  throw error;
@@ -30423,17 +31283,17 @@ var init_atomic_write = __esm({
30423
31283
  });
30424
31284
 
30425
31285
  // src/analyst-index.ts
30426
- import { open as open3, readFile as readFile20, unlink as unlink4 } from "node:fs/promises";
30427
- import { dirname as dirname15, join as join30 } from "node:path";
31286
+ import { open as open3, readFile as readFile21, unlink as unlink4 } from "node:fs/promises";
31287
+ import { dirname as dirname16, join as join33 } from "node:path";
30428
31288
  function sleep(ms) {
30429
- return new Promise((resolve11) => {
30430
- setTimeout(resolve11, ms);
31289
+ return new Promise((resolve10) => {
31290
+ setTimeout(resolve10, ms);
30431
31291
  });
30432
31292
  }
30433
31293
  async function withAnalystLibraryIndexLock(ledgerHome, fn) {
30434
31294
  const indexPath = analystLibraryIndexPath(ledgerHome);
30435
- ensureRealDirectoryTree(ledgerHome, dirname15(indexPath));
30436
- const lockPath = join30(dirname15(indexPath), LIBRARY_INDEX_LOCK_NAME);
31295
+ ensureRealDirectoryTree(ledgerHome, dirname16(indexPath));
31296
+ const lockPath = join33(dirname16(indexPath), LIBRARY_INDEX_LOCK_NAME);
30437
31297
  assertLedgerFileInsideHome(lockPath, ledgerHome);
30438
31298
  const startedAt = Date.now();
30439
31299
  while (true) {
@@ -30460,7 +31320,7 @@ async function withAnalystLibraryIndexLock(ledgerHome, fn) {
30460
31320
  }
30461
31321
  }
30462
31322
  function analystLibraryIndexPath(ledgerHome) {
30463
- return join30(ledgerHome, "analyst", "library-index.json");
31323
+ return join33(ledgerHome, "analyst", "library-index.json");
30464
31324
  }
30465
31325
  function rowFromIssueMetricsPage(page) {
30466
31326
  return {
@@ -30551,7 +31411,7 @@ async function readAnalystLibraryIndexPage(ledgerHome) {
30551
31411
  const path = analystLibraryIndexPath(ledgerHome);
30552
31412
  let raw;
30553
31413
  try {
30554
- raw = await readFile20(path, "utf8");
31414
+ raw = await readFile21(path, "utf8");
30555
31415
  } catch (error) {
30556
31416
  if (error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR")) {
30557
31417
  return void 0;
@@ -30569,7 +31429,7 @@ async function readAnalystLibraryIndexPage(ledgerHome) {
30569
31429
  }
30570
31430
  async function writeAnalystLibraryIndexPage(ledgerHome, page) {
30571
31431
  const path = analystLibraryIndexPath(ledgerHome);
30572
- ensureRealDirectoryTree(ledgerHome, dirname15(path));
31432
+ ensureRealDirectoryTree(ledgerHome, dirname16(path));
30573
31433
  assertLedgerFileInsideHome(path, ledgerHome);
30574
31434
  await writeFileAtomically(path, `${JSON.stringify(page, null, 2)}
30575
31435
  `);
@@ -30755,9 +31615,9 @@ var init_analyst_cohort = __esm({
30755
31615
  });
30756
31616
 
30757
31617
  // src/analyst-ledger.ts
30758
- import { readdir as readdir7, readFile as readFile21 } from "node:fs/promises";
30759
- import { join as join31 } from "node:path";
30760
- function isMissingPathError5(error) {
31618
+ import { readdir as readdir9, readFile as readFile22 } from "node:fs/promises";
31619
+ import { basename as basename8, join as join34 } from "node:path";
31620
+ function isMissingPathError6(error) {
30761
31621
  return error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR");
30762
31622
  }
30763
31623
  function errorText3(error) {
@@ -30769,7 +31629,7 @@ function isRecord10(value) {
30769
31629
  async function readExistingRunLifecycleState(runDirectory) {
30770
31630
  try {
30771
31631
  const raw = JSON.parse(
30772
- await readFile21(join31(runDirectory, "run-state.json"), "utf8")
31632
+ await readFile22(join34(runDirectory, "run-state.json"), "utf8")
30773
31633
  );
30774
31634
  if (!isRecord10(raw) || typeof raw.state !== "string") return void 0;
30775
31635
  return raw.state;
@@ -30791,19 +31651,19 @@ function tryResolveBookKeyFromProjectRoot(projectRoot) {
30791
31651
  }
30792
31652
  async function listLedgerBookNames(booksRoot) {
30793
31653
  try {
30794
- const entries = await readdir7(booksRoot, { withFileTypes: true });
31654
+ const entries = await readdir9(booksRoot, { withFileTypes: true });
30795
31655
  return entries.filter((e) => e.isDirectory()).map((e) => e.name).sort();
30796
31656
  } catch (error) {
30797
- if (isMissingPathError5(error)) return [];
31657
+ if (isMissingPathError6(error)) return [];
30798
31658
  throw error;
30799
31659
  }
30800
31660
  }
30801
31661
  async function readInvocationScopeFields(runDirectory) {
30802
31662
  let raw;
30803
31663
  try {
30804
- raw = await readFile21(join31(runDirectory, "invocation.json"), "utf8");
31664
+ raw = await readFile22(join34(runDirectory, "invocation.json"), "utf8");
30805
31665
  } catch (error) {
30806
- if (isMissingPathError5(error)) return void 0;
31666
+ if (isMissingPathError6(error)) return void 0;
30807
31667
  throw error;
30808
31668
  }
30809
31669
  const parsed = JSON.parse(raw);
@@ -30812,8 +31672,9 @@ async function readInvocationScopeFields(runDirectory) {
30812
31672
  return void 0;
30813
31673
  }
30814
31674
  const projectRoot = parsed.projectRoot;
30815
- if (typeof parsed.ticketNumber === "number" && Number.isInteger(parsed.ticketNumber) && parsed.ticketNumber >= 1) {
30816
- return { projectRoot, ticketNumber: parsed.ticketNumber };
31675
+ const ticketNumber = await readRunTicketNumber(runDirectory);
31676
+ if (ticketNumber !== void 0) {
31677
+ return { projectRoot, ticketNumber };
30817
31678
  }
30818
31679
  return { projectRoot };
30819
31680
  }
@@ -30833,15 +31694,15 @@ function decideIssueScope(input) {
30833
31694
  }
30834
31695
  async function resolveSessionFile(runDirectory) {
30835
31696
  try {
30836
- const raw = await readFile21(join31(runDirectory, "invocation.json"), "utf8");
31697
+ const raw = await readFile22(join34(runDirectory, "invocation.json"), "utf8");
30837
31698
  const parsed = JSON.parse(raw);
30838
31699
  if (isRecord10(parsed) && typeof parsed.sessionFile === "string" && parsed.sessionFile.trim() !== "") {
30839
31700
  return parsed.sessionFile;
30840
31701
  }
30841
31702
  } catch (error) {
30842
- if (!isMissingPathError5(error)) throw error;
31703
+ if (!isMissingPathError6(error)) throw error;
30843
31704
  }
30844
- return join31(runDirectory, "session", "session.jsonl");
31705
+ return join34(runDirectory, "session", "session.jsonl");
30845
31706
  }
30846
31707
  function attributeSessionRowsForRun(input) {
30847
31708
  if (pathContainedIn(input.runDirectory, input.sessionFile)) {
@@ -31013,9 +31874,9 @@ async function classifyScopedRun(input) {
31013
31874
  }
31014
31875
  let gateCycles;
31015
31876
  try {
31016
- const parentSessionFile = join31(input.runDirectory, "session", "session.jsonl");
31877
+ const parentSessionFile = join34(input.runDirectory, "session", "session.jsonl");
31017
31878
  gateCycles = await readAnalystGateCyclesFromAuditorRoles(
31018
- join31(input.runDirectory, "session", "auditor-roles"),
31879
+ join34(input.runDirectory, "session", "auditor-roles"),
31019
31880
  { parentSessionFile }
31020
31881
  );
31021
31882
  } catch (error) {
@@ -31048,7 +31909,7 @@ async function classifyScopedRun(input) {
31048
31909
  async function scanAnalystIssueRuns(input) {
31049
31910
  const ledgerHome = resolveActivationLedgerHome(input.home);
31050
31911
  const scopeTicketNumber = input.ticketNumber;
31051
- const booksRoot = join31(ledgerHome, "books");
31912
+ const booksRoot = join34(ledgerHome, "books");
31052
31913
  let wholeBook = false;
31053
31914
  let scopeRootIdentity;
31054
31915
  let bookNames;
@@ -31080,19 +31941,18 @@ async function scanAnalystIssueRuns(input) {
31080
31941
  const unreadable = [];
31081
31942
  const scopeConflicts = [];
31082
31943
  for (const book of bookNames) {
31083
- const runsDir = join31(booksRoot, book, "runs");
31084
- let runNames;
31944
+ const bookDir = join34(booksRoot, book);
31945
+ let runDirectories;
31085
31946
  try {
31086
- const entries = await readdir7(runsDir, { withFileTypes: true });
31087
- runNames = entries.filter((e) => e.isDirectory()).map((e) => e.name).sort();
31947
+ runDirectories = await listBookRunDirectories(bookDir);
31088
31948
  } catch (error) {
31089
- if (isMissingPathError5(error)) continue;
31949
+ if (isMissingPathError6(error)) continue;
31090
31950
  throw error;
31091
31951
  }
31092
- for (const runName of runNames) {
31952
+ for (const runDirectory of runDirectories) {
31953
+ const runName = basename8(runDirectory);
31093
31954
  const parsed = parseRunDirectoryName2(runName);
31094
31955
  if (parsed === void 0) continue;
31095
- const runDirectory = join31(runsDir, runName);
31096
31956
  let scopeFields;
31097
31957
  try {
31098
31958
  scopeFields = await readInvocationScopeFields(runDirectory);
@@ -31132,6 +31992,8 @@ var init_analyst_ledger = __esm({
31132
31992
  "use strict";
31133
31993
  init_activation_ledger_git();
31134
31994
  init_activation_ledger_topology();
31995
+ init_role_run_placement();
31996
+ init_run_ticket_number();
31135
31997
  init_ledger_session_read();
31136
31998
  init_run_terminal_artifacts();
31137
31999
  init_analyst_gate_cycles_read();
@@ -31946,7 +32808,7 @@ var init_analyst_metric_family = __esm({
31946
32808
 
31947
32809
  // src/analyst-page.ts
31948
32810
  import { createHash as createHash5 } from "node:crypto";
31949
- import { dirname as dirname16, join as join32 } from "node:path";
32811
+ import { dirname as dirname17, join as join35 } from "node:path";
31950
32812
  function analystIssuePageKey(address) {
31951
32813
  const parts = ["book", address.bookKey];
31952
32814
  if (address.issueNumber !== void 0) {
@@ -31957,7 +32819,7 @@ function analystIssuePageKey(address) {
31957
32819
  return createHash5("sha256").update(parts.join("\0")).digest("hex").slice(0, 32);
31958
32820
  }
31959
32821
  function analystIssuePagePath(ledgerHome, address) {
31960
- return join32(ledgerHome, "analyst", "issues", `${analystIssuePageKey(address)}.json`);
32822
+ return join35(ledgerHome, "analyst", "issues", `${analystIssuePageKey(address)}.json`);
31961
32823
  }
31962
32824
  function analystIssuePageAddressFromPage(page) {
31963
32825
  return {
@@ -32076,7 +32938,7 @@ async function buildAnalystIssueMetricsPage(input) {
32076
32938
  }
32077
32939
  async function writeAnalystIssueMetricsPage(ledgerHome, page) {
32078
32940
  const path = analystIssuePagePath(ledgerHome, analystIssuePageAddressFromPage(page));
32079
- ensureRealDirectoryTree(ledgerHome, dirname16(path));
32941
+ ensureRealDirectoryTree(ledgerHome, dirname17(path));
32080
32942
  assertLedgerFileInsideHome(path, ledgerHome);
32081
32943
  await writeFileAtomically(path, `${JSON.stringify(page, null, 2)}
32082
32944
  `);
@@ -32093,8 +32955,8 @@ var init_analyst_page = __esm({
32093
32955
  });
32094
32956
 
32095
32957
  // src/analyst-entry.ts
32096
- import { readFile as readFile22 } from "node:fs/promises";
32097
- function isMissingPathError6(error) {
32958
+ import { readFile as readFile23 } from "node:fs/promises";
32959
+ function isMissingPathError7(error) {
32098
32960
  return error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR");
32099
32961
  }
32100
32962
  function cachedPageMatchesRequestedScope(page, input) {
@@ -32123,13 +32985,13 @@ async function readOrComputeAnalystIssuePage(input, options) {
32123
32985
  ...issueNumber === void 0 && input.bookKey === void 0 ? { scopeRootIdentity: projectRoot } : {}
32124
32986
  });
32125
32987
  try {
32126
- const raw = await readFile22(pagePath, "utf8");
32988
+ const raw = await readFile23(pagePath, "utf8");
32127
32989
  const page = JSON.parse(raw);
32128
32990
  if (cachedPageMatchesRequestedScope(page, { bookKey, ...input })) {
32129
32991
  return { mode: "issue", page, pagePath };
32130
32992
  }
32131
32993
  } catch (error) {
32132
- if (!isMissingPathError6(error)) {
32994
+ if (!isMissingPathError7(error)) {
32133
32995
  throw new AnalystIssueComputeError({
32134
32996
  bookKey,
32135
32997
  projectRoot,
@@ -32218,10 +33080,10 @@ async function runAnalystModelGroupsMode(input, home) {
32218
33080
  scopeRootIdentity: projectRoot
32219
33081
  });
32220
33082
  try {
32221
- const raw = await readFile22(pagePath, "utf8");
33083
+ const raw = await readFile23(pagePath, "utf8");
32222
33084
  JSON.parse(raw);
32223
33085
  } catch (error) {
32224
- if (!isMissingPathError6(error)) {
33086
+ if (!isMissingPathError7(error)) {
32225
33087
  throw new AnalystIssueComputeError({ bookKey, projectRoot, cause: error });
32226
33088
  }
32227
33089
  try {
@@ -32317,8 +33179,8 @@ var init_analyst_entry = __esm({
32317
33179
  });
32318
33180
 
32319
33181
  // src/public-cli/analyst-run.ts
32320
- import { readFile as readFile23 } from "node:fs/promises";
32321
- import { isAbsolute as isAbsolute10, resolve as resolve10 } from "node:path";
33182
+ import { readFile as readFile24 } from "node:fs/promises";
33183
+ import { isAbsolute as isAbsolute10, resolve as resolve9 } from "node:path";
32322
33184
  function resolveAnalystIssueBookKeyFromCwd(cwd = process.cwd()) {
32323
33185
  try {
32324
33186
  return resolveBookKeyFromGit(cwd);
@@ -32367,10 +33229,10 @@ async function buildAnalystSweepModeInputFromAttachmentPaths(attachmentPaths) {
32367
33229
  );
32368
33230
  }
32369
33231
  const sourcePath = attachmentPaths[0];
32370
- const absolute = isAbsolute10(sourcePath) ? sourcePath : resolve10(sourcePath);
33232
+ const absolute = isAbsolute10(sourcePath) ? sourcePath : resolve9(sourcePath);
32371
33233
  let bytes;
32372
33234
  try {
32373
- bytes = await readFile23(absolute);
33235
+ bytes = await readFile24(absolute);
32374
33236
  } catch (error) {
32375
33237
  throw new CliUsageError(
32376
33238
  `analyst sweep attachment is not a readable regular file: ${sourcePath}`,
@@ -32490,7 +33352,7 @@ __export(cli_exports, {
32490
33352
  runAkRole: () => runAkRole
32491
33353
  });
32492
33354
  import { realpath as realpath6 } from "node:fs/promises";
32493
- import { join as join33 } from "node:path";
33355
+ import { join as join36 } from "node:path";
32494
33356
  function takePublicGlobalFlag(argv, index, options) {
32495
33357
  const tokens = argv.slice(index);
32496
33358
  const taken = options.takeDashed(tokens);
@@ -32587,7 +33449,7 @@ function resolveHome(env) {
32587
33449
  return env.home ?? packageMachineHome();
32588
33450
  }
32589
33451
  function resolveAgentDir(env, home) {
32590
- return env.agentDir ?? process.env.PI_CODING_AGENT_DIR ?? join33(home, ".pi", "agent");
33452
+ return env.agentDir ?? process.env.PI_CODING_AGENT_DIR ?? join36(home, ".pi", "agent");
32591
33453
  }
32592
33454
  function parseThinking(value) {
32593
33455
  return value;
@@ -33601,8 +34463,8 @@ var init_cli = __esm({
33601
34463
  });
33602
34464
 
33603
34465
  // src/public-cli/main.ts
33604
- import { existsSync as existsSync10 } from "node:fs";
33605
- import { dirname as dirname17, join as join34 } from "node:path";
34466
+ import { existsSync as existsSync11 } from "node:fs";
34467
+ import { dirname as dirname18, join as join37 } from "node:path";
33606
34468
  import { fileURLToPath as fileURLToPath2 } from "node:url";
33607
34469
 
33608
34470
  // src/public-cli/host-pi-runtime.ts
@@ -33689,10 +34551,10 @@ function linkPackage(packageRoot2, name, targetDir) {
33689
34551
  }
33690
34552
 
33691
34553
  // src/public-cli/main.ts
33692
- var here = dirname17(fileURLToPath2(import.meta.url));
34554
+ var here = dirname18(fileURLToPath2(import.meta.url));
33693
34555
  function resolvePackageRoot(binDir) {
33694
- const canonical = join34(binDir, "..", "..");
33695
- if (existsSync10(join34(canonical, "package.json"))) {
34556
+ const canonical = join37(binDir, "..", "..");
34557
+ if (existsSync11(join37(canonical, "package.json"))) {
33696
34558
  return canonical;
33697
34559
  }
33698
34560
  return binDir;