@akagilnc/pi-workflow-roles 0.1.5583 → 0.1.5598

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 (41) hide show
  1. package/README.md +2 -0
  2. package/README.zh-CN.md +2 -0
  3. package/dist/acp-host/production-host.js +393 -854
  4. package/dist/collector-config.js +0 -44
  5. package/dist/headless-host/production-host.js +361 -822
  6. package/dist/merger-contracts.js +6 -2
  7. package/dist/migrate-book-topology.js +4855 -10472
  8. package/dist/package-contracts/worker-output.js +1 -6
  9. package/dist/packaged-role-registry.js +5 -4
  10. package/dist/public-cli/instruction-seat-run.js +8 -8
  11. package/dist/public-cli/invocation.js +93 -236
  12. package/dist/public-cli/main.js +18409 -18786
  13. package/dist/public-cli/option-definitions.js +7 -7
  14. package/dist/public-cli/post-admission.js +11 -40
  15. package/dist/public-cli/run-lifecycle.js +11 -43
  16. package/dist/public-role-summons.js +1 -1
  17. package/dist/role-run-relocation.js +14 -23
  18. package/package.json +1 -1
  19. package/scripts/build-package.mjs +0 -1
  20. package/src/collector-config.ts +0 -42
  21. package/src/collector-role.ts +10 -20
  22. package/src/host-contracts.ts +0 -3
  23. package/src/merger-contracts.ts +6 -2
  24. package/src/merger-role.ts +11 -1
  25. package/src/navigator-attendance.ts +2 -2
  26. package/src/package-contracts/worker-output.ts +0 -8
  27. package/src/packaged-role-registry.ts +4 -3
  28. package/src/public-cli/instruction-seat-run.ts +7 -8
  29. package/src/public-cli/invocation.ts +113 -351
  30. package/src/public-cli/option-definitions.ts +7 -7
  31. package/src/public-cli/post-admission.ts +12 -56
  32. package/src/public-cli/run-lifecycle.ts +11 -55
  33. package/src/public-role-summons.ts +1 -1
  34. package/src/role-run-placement.ts +0 -1
  35. package/src/role-run-relocation.ts +14 -25
  36. package/src/role-runtime-dependencies.ts +0 -2
  37. package/src/role-runtime.ts +0 -16
  38. package/src/worker-role.ts +11 -78
  39. package/dist/package-contracts/fixer-packet.js +0 -77
  40. package/packets/fixer-prerequisites.json +0 -6
  41. package/src/package-contracts/fixer-packet.ts +0 -91
@@ -344,7 +344,7 @@ const SHARED_PROJECT_SEMANTICS = {
344
344
  } as const satisfies Omit<PublicOptionDefinition, "owner">;
345
345
 
346
346
  /**
347
- * Immutable shared semantics for the common frozen-file `--attach` face.
347
+ * Immutable shared semantics for the common `--attach` face (#1165).
348
348
  * Role rows bind owner only. Reviewer has no attach face; analyst sweep attach
349
349
  * keeps its own modes/selectsMode/description and must not use this binding.
350
350
  */
@@ -357,8 +357,8 @@ const SHARED_ATTACH_SEMANTICS = {
357
357
  repeatable: true,
358
358
  form: "option" as const,
359
359
  description: {
360
- en: "Attach a regular file; frozen at admission (repeatable).",
361
- zh: "附加普通文件;受理即冻结(可重复)。",
360
+ en: "Caller file path passed as-is to the role (repeatable). Package does not read, copy, or validate; use an absolute path when cwd differs from --project.",
361
+ zh: "调用方文件路径原样递给衙门(可重复)。包不读、不复制、不校验;调用方当前目录与 --project 不同时请给绝对路径。",
362
362
  },
363
363
  } as const satisfies Omit<PublicOptionDefinition, "owner">;
364
364
 
@@ -463,8 +463,8 @@ const FIXER_OPTIONS = [
463
463
  repeatable: false,
464
464
  form: "option",
465
465
  description: {
466
- en: "JSON array of {id, requirement} prerequisite objects.",
467
- zh: "{id, requirement} 前置条件 JSON 数组路径。",
466
+ en: "Caller prerequisites path passed as-is to the role. Package does not read, copy, or validate; use an absolute path when cwd differs from --project.",
467
+ zh: "调用方前置条件文件路径原样递给衙门。包不读、不复制、不校验;调用方当前目录与 --project 不同时请给绝对路径。",
468
468
  },
469
469
  },
470
470
  ] as const satisfies readonly PublicOptionDefinition[];
@@ -556,8 +556,8 @@ const COLLECTOR_OPTIONS = [
556
556
  repeatable: false,
557
557
  form: "option",
558
558
  description: {
559
- en: "Optional request manifest JSON path ({requests:[{id,body}]}). Parsed for semantics and passed to the Collector as materials — not a machine collection directive.",
560
- zh: "可选 request manifest JSON 路径({requests:[{id,body}]})。按语义解析后作为材料递给通进司,不是机器代收 finding 的指令。",
559
+ en: "Caller path to a request manifest JSON file, passed as-is. Package does not read, copy, or validate; use an absolute path when cwd differs from --project.",
560
+ zh: "调用方 request manifest JSON 路径,原样传递。包不读、不复制、不校验;调用方当前目录与 --project 不同时请给绝对路径。",
561
561
  },
562
562
  },
563
563
  ] as const satisfies readonly PublicOptionDefinition[];
@@ -7,7 +7,6 @@
7
7
  */
8
8
  import { randomUUID } from "node:crypto";
9
9
  import { writeFile } from "node:fs/promises";
10
- import { isAbsolute, join, resolve } from "node:path";
11
10
 
12
11
  import {
13
12
  buildAutoResumeContinuationPrompt,
@@ -22,12 +21,10 @@ import { projectPublicTurnAxes, type RoleTurnRequestProjectionOptions } from "./
22
21
  import {
23
22
  bindAdmittedTicketNumber,
24
23
  buildInstructionTransportPrompt,
25
- freezeAttachmentsIntoRun,
26
24
  relocateAdmittedRunToTicket,
27
25
  } from "./invocation.ts";
28
26
  import { readRecordedSubmissionRows } from "../submission-ledger.ts";
29
27
  import { parseTicketNumber, readDeclaredTicketNumber } from "../run-ticket-number.ts";
30
- import { pathContainedIn } from "../activation-ledger-topology.ts";
31
28
  import { readStoredHostSessionId } from "../session-identity.ts";
32
29
  import { reportRunRecord } from "../sitian-facade.ts";
33
30
  import {
@@ -135,10 +132,11 @@ function projectRelocatedTurnIdentity(
135
132
  mutableRequest.principal = admitted.principal;
136
133
  const activation = mutableRequest.activation;
137
134
  if (isRecord(activation)) {
138
- for (const field of ["taskPath", "packetPath", "prerequisitesPath", "inputPath", "requestManifestPath"] as const) {
135
+ for (const field of ["inputPath"] as const) {
139
136
  const record = activation as Record<string, unknown>;
140
137
  if (field in record) record[field] = rewrite(record[field]);
141
138
  }
139
+ // #1165/#1168: caller file-flag paths are not activation fields to rewrite.
142
140
  }
143
141
  if (result.terminal !== undefined) {
144
142
  for (const artifact of result.terminal.artifacts) {
@@ -1476,7 +1474,7 @@ export function resumeTurnRequestProjectionOptions(
1476
1474
  summonsPrepared?: {
1477
1475
  readonly instruction: string;
1478
1476
  readonly instructionEmpty: boolean;
1479
- readonly attachments: readonly { frozenPath: string }[];
1477
+ readonly attachments: readonly { path: string }[];
1480
1478
  },
1481
1479
  ): RoleTurnRequestProjectionOptions {
1482
1480
  // #879: officer dialogue content is caller/peer words only — no「请重读」,
@@ -1487,7 +1485,7 @@ export function resumeTurnRequestProjectionOptions(
1487
1485
  if (request.message !== undefined) {
1488
1486
  if (summonsPrepared !== undefined) {
1489
1487
  // #755: same-ticket review / open-court — caller words.
1490
- // #879 station-child officer: words only (attachments are independent freeze).
1488
+ // #879 station-child officer: words only (paths remain on summons materials).
1491
1489
  prompt = officerDialogue
1492
1490
  ? request.message
1493
1491
  : buildInstructionTransportPrompt({
@@ -1504,8 +1502,10 @@ export function resumeTurnRequestProjectionOptions(
1504
1502
  } else if (summonsPrepared !== undefined) {
1505
1503
  // #879 station-child officer: instruction bytes === peer body/reask (no wrap).
1506
1504
  // Other seats keep #755 instruction + optional attachment path listing.
1505
+ // #1165 J3: officer dialogue is raw instruction bytes; do not gate on
1506
+ // instructionEmpty metadata (resume of older admitted pages).
1507
1507
  prompt = officerDialogue
1508
- ? (summonsPrepared.instructionEmpty ? "" : summonsPrepared.instruction)
1508
+ ? summonsPrepared.instruction
1509
1509
  : buildInstructionTransportPrompt(summonsPrepared);
1510
1510
  } else if (request.summons !== undefined) {
1511
1511
  // #879: same-ticket summons with no instruction (e.g. notary source-run binding
@@ -1634,31 +1634,17 @@ async function runSettledAutoResumeLoop<
1634
1634
  });
1635
1635
  }
1636
1636
 
1637
- function isAlreadyFrozenSummonsAttachment(
1638
- runDirectory: string,
1639
- attachmentPath: string,
1640
- ): boolean {
1641
- const absolute = isAbsolute(attachmentPath)
1642
- ? attachmentPath
1643
- : resolve(attachmentPath);
1644
- return pathContainedIn(join(runDirectory, "attachments"), absolute);
1645
- }
1646
-
1647
1637
  /**
1648
- * Freeze same-ticket summons attachments into the retained run directory (#637).
1649
- * No-op materials (no paths / instruction-only) skip the freeze.
1650
- * Paths already under this run's attachments/ are the accepted freeze identity —
1651
- * reuse them for the same internal re-summons flow.
1652
- * Manual resume never calls this — old attachment semantics stay intact.
1638
+ * Same-ticket summons materials: caller paths as-is (#1165). No copy or freeze.
1653
1639
  */
1654
1640
  export async function prepareSummonsResumeMaterials(
1655
- runDirectory: string,
1641
+ _runDirectory: string,
1656
1642
  summons: SameTicketSummonsMaterials | undefined,
1657
1643
  ): Promise<
1658
1644
  | {
1659
1645
  readonly instruction: string;
1660
1646
  readonly instructionEmpty: boolean;
1661
- readonly attachments: readonly { frozenPath: string }[];
1647
+ readonly attachments: readonly { path: string }[];
1662
1648
  }
1663
1649
  | undefined
1664
1650
  > {
@@ -1668,16 +1654,8 @@ export async function prepareSummonsResumeMaterials(
1668
1654
  }
1669
1655
  const instruction = summons.instruction ?? "";
1670
1656
  const instructionEmpty =
1671
- summons.instructionEmpty ?? instruction.trim() === "";
1672
- let attachments: readonly { frozenPath: string }[] = [];
1673
- if (summons.attachmentPaths !== undefined && summons.attachmentPaths.length > 0) {
1674
- const alreadyFrozen = summons.attachmentPaths.every((path) =>
1675
- isAlreadyFrozenSummonsAttachment(runDirectory, path),
1676
- );
1677
- attachments = alreadyFrozen
1678
- ? summons.attachmentPaths.map((frozenPath) => ({ frozenPath }))
1679
- : await freezeAttachmentsIntoRun(summons.attachmentPaths, runDirectory);
1680
- }
1657
+ summons.instructionEmpty ?? instruction.length === 0;
1658
+ const attachments = (summons.attachmentPaths ?? []).map((path) => ({ path }));
1681
1659
  return { instruction, instructionEmpty, attachments };
1682
1660
  }
1683
1661
 
@@ -1778,28 +1756,6 @@ export async function runPostAdmissionSeatResume<
1778
1756
  }
1779
1757
  }
1780
1758
 
1781
- // Internal re-summons freezes external paths once and records that identity.
1782
- if (request.summons !== undefined) {
1783
- const prepared = await prepareSummonsResumeMaterials(
1784
- admittedForBuild.runDirectory,
1785
- request.summons,
1786
- );
1787
- if (
1788
- prepared !== undefined &&
1789
- (request.summons.attachmentPaths?.length ?? 0) > 0
1790
- ) {
1791
- request = {
1792
- ...request,
1793
- summons: {
1794
- ...request.summons,
1795
- attachmentPaths: prepared.attachments.map(
1796
- (attachment) => attachment.frozenPath,
1797
- ),
1798
- },
1799
- };
1800
- }
1801
- }
1802
-
1803
1759
  // Public explicit resume: attach the stored native id when the caller
1804
1760
  // left it unset (399c3c8c). In-call auto-resume / 催交 / gate retry omit
1805
1761
  // the field; those load inside the host adapter (host-contracts).
@@ -20,7 +20,6 @@ import { findRoleRunDirectory, listBookRunDirectories, parseRunLeaf, sessionFile
20
20
  import { isSafePositiveTicketNumber } from "../run-ticket-number.ts";
21
21
  import { CliUsageError } from "./cli-errors.ts";
22
22
  import type { FixerPhase } from "../package-contracts/fixer-output.ts";
23
- import type { FixerPrerequisite } from "../package-contracts/fixer-packet.ts";
24
23
  import { parseCollectorRepository } from "../collector-config.ts";
25
24
  import type { DoctorCaseIdentity } from "../doctor-contracts.ts";
26
25
  import type { NotarySourceRunLocator } from "../notary-contracts.ts";
@@ -53,6 +52,7 @@ import {
53
52
  type AdmittedRoleInvocation,
54
53
  type CoderPhase,
55
54
  type DerivedMergerEnvelope,
55
+ normalizeAdmittedAttachment,
56
56
  type FrozenAttachment,
57
57
  type InvocationEffectiveModel,
58
58
  type ReviewerLens,
@@ -183,7 +183,7 @@ function parseSameTicketSummonsMaterials(
183
183
  const instructionEmpty =
184
184
  typeof record.instructionEmpty === "boolean" ? record.instructionEmpty : undefined;
185
185
  const attachmentPaths = Array.isArray(record.attachmentPaths)
186
- ? record.attachmentPaths.filter((p): p is string => typeof p === "string" && p.length > 0)
186
+ ? record.attachmentPaths.filter((p): p is string => typeof p === "string")
187
187
  : undefined;
188
188
  const sourceRunPath =
189
189
  typeof record.sourceRunPath === "string" && record.sourceRunPath.trim() !== ""
@@ -991,10 +991,7 @@ type LoadedAdmittedRequestFields = {
991
991
  readonly instructionEmpty: boolean;
992
992
  readonly attachments: FrozenAttachment[];
993
993
  readonly phase?: CoderPhase | FixerPhase;
994
- readonly taskPath?: string;
995
- readonly packetPath?: string;
996
994
  readonly prerequisitesPath?: string;
997
- readonly prerequisites?: readonly FixerPrerequisite[];
998
995
  readonly baseRevision?: string;
999
996
  readonly lens?: ReviewerLens;
1000
997
  readonly authorityRefs?: readonly string[];
@@ -1007,7 +1004,6 @@ type LoadedAdmittedRequestFields = {
1007
1004
  readonly repository?: string;
1008
1005
  readonly repositoryDisplay?: string;
1009
1006
  readonly requestManifestPath?: string;
1010
- readonly manifestDigest?: string;
1011
1007
  /** Collector wait-window ms restored on resume (#678). */
1012
1008
  readonly waitWindowMs?: number;
1013
1009
  /** Doctor — admitted single-case identity restored on resume (#633). */
@@ -1081,10 +1077,7 @@ async function loadResumableRunRecord(
1081
1077
  let instructionEmpty = true;
1082
1078
  let attachments: FrozenAttachment[] = [];
1083
1079
  let phase: CoderPhase | FixerPhase | undefined;
1084
- let taskPath: string | undefined;
1085
- let packetPath: string | undefined;
1086
1080
  let prerequisitesPath: string | undefined;
1087
- let prerequisites: readonly FixerPrerequisite[] | undefined;
1088
1081
  let baseRevision: string | undefined;
1089
1082
  let lens: ReviewerLens | undefined;
1090
1083
  let authorityRefs: readonly string[] | undefined;
@@ -1096,7 +1089,6 @@ async function loadResumableRunRecord(
1096
1089
  let repository: string | undefined;
1097
1090
  let repositoryDisplay: string | undefined;
1098
1091
  let requestManifestPath: string | undefined;
1099
- let manifestDigest: string | undefined;
1100
1092
  let waitWindowMs: number | undefined;
1101
1093
  let issueNumber: number | undefined;
1102
1094
  let caseRunsPath: string | undefined;
@@ -1122,26 +1114,17 @@ async function loadResumableRunRecord(
1122
1114
  instructionEmpty = record.instructionEmpty;
1123
1115
  }
1124
1116
  if (Array.isArray(record.attachments)) {
1125
- attachments = record.attachments as FrozenAttachment[];
1117
+ attachments = record.attachments
1118
+ .map((item) => normalizeAdmittedAttachment(item))
1119
+ .filter((item): item is FrozenAttachment => item !== undefined);
1126
1120
  }
1127
1121
  if (record.phase === "plan" || record.phase === "apply") {
1128
1122
  phase = record.phase;
1129
1123
  }
1130
- if (typeof record.taskPath === "string" && record.taskPath.trim() !== "") {
1131
- taskPath = record.taskPath;
1132
- }
1133
- if (typeof record.packetPath === "string" && record.packetPath.trim() !== "") {
1134
- packetPath = record.packetPath;
1135
- }
1136
- if (
1137
- typeof record.prerequisitesPath === "string" &&
1138
- record.prerequisitesPath.trim() !== ""
1139
- ) {
1124
+ // #1168: opaque caller path on resume — do not trim-filter provided values.
1125
+ if (typeof record.prerequisitesPath === "string") {
1140
1126
  prerequisitesPath = record.prerequisitesPath;
1141
1127
  }
1142
- if (Array.isArray(record.prerequisites)) {
1143
- prerequisites = record.prerequisites as FixerPrerequisite[];
1144
- }
1145
1128
  if (
1146
1129
  typeof record.baseRevision === "string" &&
1147
1130
  record.baseRevision.trim() !== ""
@@ -1161,12 +1144,10 @@ async function loadResumableRunRecord(
1161
1144
  if (typeof record.repositoryDisplay === "string" && record.repositoryDisplay.trim() !== "") {
1162
1145
  repositoryDisplay = record.repositoryDisplay;
1163
1146
  }
1164
- if (typeof record.requestManifestPath === "string" && record.requestManifestPath.trim() !== "") {
1147
+ // #1165: opaque caller path on resume — do not trim-filter provided values.
1148
+ if (typeof record.requestManifestPath === "string") {
1165
1149
  requestManifestPath = record.requestManifestPath;
1166
1150
  }
1167
- if (typeof record.manifestDigest === "string" && record.manifestDigest.trim() !== "") {
1168
- manifestDigest = record.manifestDigest;
1169
- }
1170
1151
  if (typeof record.waitWindowMs === "number" && Number.isSafeInteger(record.waitWindowMs) && record.waitWindowMs >= 1) {
1171
1152
  waitWindowMs = record.waitWindowMs;
1172
1153
  }
@@ -1320,10 +1301,7 @@ async function loadResumableRunRecord(
1320
1301
  instructionEmpty,
1321
1302
  attachments,
1322
1303
  ...(phase === undefined ? {} : { phase }),
1323
- ...(taskPath === undefined ? {} : { taskPath }),
1324
- ...(packetPath === undefined ? {} : { packetPath }),
1325
1304
  ...(prerequisitesPath === undefined ? {} : { prerequisitesPath }),
1326
- ...(prerequisites === undefined ? {} : { prerequisites }),
1327
1305
  ...(baseRevision === undefined ? {} : { baseRevision }),
1328
1306
  ...(lens === undefined ? {} : { lens }),
1329
1307
  ...(authorityRefs === undefined ? {} : { authorityRefs }),
@@ -1335,7 +1313,6 @@ async function loadResumableRunRecord(
1335
1313
  ...(repository === undefined ? {} : { repository }),
1336
1314
  ...(repositoryDisplay === undefined ? {} : { repositoryDisplay }),
1337
1315
  ...(requestManifestPath === undefined ? {} : { requestManifestPath }),
1338
- ...(manifestDigest === undefined ? {} : { manifestDigest }),
1339
1316
  ...(waitWindowMs === undefined ? {} : { waitWindowMs }),
1340
1317
  ...(issueNumber === undefined ? {} : { issueNumber }),
1341
1318
  ...(caseRunsPath === undefined ? {} : { caseRunsPath }),
@@ -1455,12 +1432,6 @@ function admitResumedRole(loaded: {
1455
1432
  }
1456
1433
  case "worker-task": {
1457
1434
  const phase = resumedWorkerPhase(fields.phase ?? loaded.run.phase, record.phases, role, runId);
1458
- const taskPath = fields.taskPath;
1459
- if (taskPath === undefined) {
1460
- throw new CliUsageError(
1461
- `role run admitted coder task path is missing: ${runId}`,
1462
- );
1463
- }
1464
1435
  if (fields.instruction.trim() === "") {
1465
1436
  throw new CliUsageError(
1466
1437
  `role run admitted coder task is blank: ${runId}`,
@@ -1471,34 +1442,24 @@ function admitResumedRole(loaded: {
1471
1442
  phase,
1472
1443
  ...base,
1473
1444
  instructionEmpty: false,
1474
- taskPath,
1475
1445
  };
1476
1446
  return admitted;
1477
1447
  }
1478
1448
  case "worker-packet": {
1479
1449
  const phase = resumedWorkerPhase(fields.phase ?? loaded.run.phase, record.phases, role, runId);
1480
- const packetPath = fields.packetPath;
1481
- if (packetPath === undefined) {
1482
- throw new CliUsageError(
1483
- `role run admitted fixer packet path is missing: ${runId}`,
1484
- );
1485
- }
1486
1450
  if (fields.instruction.trim() === "") {
1487
1451
  throw new CliUsageError(
1488
1452
  `role run admitted fixer instruction is blank: ${runId}`,
1489
1453
  );
1490
1454
  }
1491
- const prerequisites = fields.prerequisites ?? Object.freeze([]);
1492
1455
  const admitted: AdmittedFixerInvocation = {
1493
1456
  role: "fixer",
1494
1457
  phase,
1495
1458
  ...base,
1496
1459
  instructionEmpty: false,
1497
- packetPath,
1498
1460
  ...(fields.prerequisitesPath === undefined
1499
1461
  ? {}
1500
1462
  : { prerequisitesPath: fields.prerequisitesPath }),
1501
- prerequisites,
1502
1463
  };
1503
1464
  return admitted;
1504
1465
  }
@@ -1575,12 +1536,8 @@ function admitResumedRole(loaded: {
1575
1536
  return admitted;
1576
1537
  }
1577
1538
  case "collect-target": {
1578
- const { prNumber, repository, repositoryDisplay, manifestDigest } = fields;
1579
- if (
1580
- repository === undefined ||
1581
- repositoryDisplay === undefined ||
1582
- manifestDigest === undefined
1583
- ) {
1539
+ const { prNumber, repository, repositoryDisplay } = fields;
1540
+ if (repository === undefined || repositoryDisplay === undefined) {
1584
1541
  throw new CliUsageError(
1585
1542
  `role run admitted collector repository identity is missing: ${runId}`,
1586
1543
  );
@@ -1606,7 +1563,6 @@ function admitResumedRole(loaded: {
1606
1563
  ? {}
1607
1564
  : { requestManifestPath: fields.requestManifestPath }),
1608
1565
  ...(fields.waitWindowMs === undefined ? {} : { waitWindowMs: fields.waitWindowMs }),
1609
- manifestDigest,
1610
1566
  };
1611
1567
  return admitted;
1612
1568
  }
@@ -496,7 +496,7 @@ export async function summonPublicRole(
496
496
  runId: resumeRunId,
497
497
  summons: {
498
498
  instruction,
499
- instructionEmpty: instruction.trim() === "",
499
+ instructionEmpty: instruction.length === 0,
500
500
  },
501
501
  },
502
502
  env as never,
@@ -170,6 +170,5 @@ export function ensureRoleRunPlacement(
170
170
  ledgerHome: string,
171
171
  placement: RoleRunPlacement,
172
172
  ): void {
173
- // attachments/ appears only when something is frozen into it.
174
173
  ensureRoleRunDirectory(ledgerHome, placement.sessionDirectory);
175
174
  }
@@ -23,10 +23,9 @@ const ADMITTED_PAGE_FIELDS = [
23
23
  "admittedRequestPath", // pre-#1161 pages only
24
24
  "sessionDirectory",
25
25
  "sessionFile",
26
- "taskPath",
27
- "packetPath",
28
- "prerequisitesPath",
29
- "requestManifestPath",
26
+ // #1165/#1168: caller file-flag paths (requestManifestPath, prerequisitesPath)
27
+ // stay as given. Obsolete copy fields (taskPath/packetPath) are not rewritten —
28
+ // stock volumes keep their bytes; live relocate no longer maintains them.
30
29
  "mergerInputPath",
31
30
  "sourceRunPath",
32
31
  ] as const;
@@ -202,7 +201,7 @@ function rewriteSourceRunLocator(
202
201
  );
203
202
  }
204
203
 
205
- /** Same-ticket summons materials: typed source-run + frozen attachment pointers. */
204
+ /** Same-ticket summons materials: typed source-run; caller attach paths stay as-is (#1165). */
206
205
  function rewriteSummonsMaterials(
207
206
  value: unknown,
208
207
  rewrites: readonly RunDirectoryPathRewrite[],
@@ -214,12 +213,7 @@ function rewriteSummonsMaterials(
214
213
  rewrites,
215
214
  );
216
215
  rewriteSourceRunLocator(value.sourceRun, rewrites);
217
- // Bare-resume frozen attachment pointers (string[]), not free text / bytes.
218
- if (Array.isArray(value.attachmentPaths)) {
219
- value.attachmentPaths = value.attachmentPaths.map((path) =>
220
- rewriteRunDirectoryPathValueAgainstRewrites(path, rewrites),
221
- );
222
- }
216
+ // #1165: summons.attachmentPaths are caller paths — do not rewrite.
223
217
  }
224
218
 
225
219
  /** Project one admitted page in memory after its containing run moved. */
@@ -229,13 +223,7 @@ export function rewriteAdmittedRoleRunPage(
229
223
  ): void {
230
224
  rewriteRunDirectoryPathFieldsAgainstRewrites(page, ADMITTED_PAGE_FIELDS, rewrites);
231
225
  rewriteSourceRunLocator(page.sourceRun, rewrites);
232
- if (Array.isArray(page.attachments)) {
233
- for (const attachment of page.attachments) {
234
- if (isRecord(attachment)) {
235
- rewriteRunDirectoryPathFieldsAgainstRewrites(attachment, ["frozenPath"], rewrites);
236
- }
237
- }
238
- }
226
+ // #1165: admitted attachments are caller paths outside the run directory — do not rewrite.
239
227
  if (isRecord(page.principal)) {
240
228
  rewriteRunDirectoryPathFieldsAgainstRewrites(
241
229
  page.principal,
@@ -432,12 +420,13 @@ async function rewriteNestedMachinePathPages(
432
420
  }
433
421
 
434
422
  /**
435
- * Rewrite the admitted / invocation / runState fact rows (path fields: attachment
436
- * frozenPath / summons.attachmentPaths pointers only), then nested package-owned
437
- * session seams. Callers may rewrite before or after the filesystem move/copy:
438
- * `pagesDirectory` is where the pages currently live on disk; path strings that
439
- * still name `oldRunDirectory` become `newRunDirectory`. `crossRunRewrites`
440
- * covers officer/parent pointers that landed under a different final placement.
423
+ * Rewrite the admitted / invocation / runState fact rows (typed run placement
424
+ * paths only; caller --attach / --request-manifest paths stay as-is, #1165),
425
+ * then nested package-owned session seams. Callers may rewrite before or after
426
+ * the filesystem move/copy: `pagesDirectory` is where the pages currently live
427
+ * on disk; path strings that still name `oldRunDirectory` become
428
+ * `newRunDirectory`. `crossRunRewrites` covers officer/parent pointers that
429
+ * landed under a different final placement.
441
430
  */
442
431
  export async function rewriteRoleRunDurablePages(input: {
443
432
  readonly pagesDirectory: string;
@@ -462,7 +451,7 @@ export async function rewriteRoleRunDurablePages(input: {
462
451
  rewrites,
463
452
  );
464
453
  }
465
- // Open court summons: source-run locators + frozen attachment path pointers.
454
+ // Open court summons: source-run locators only; caller attach paths stay (#1165).
466
455
  if (isRecord(page.currentCourt)) {
467
456
  rewriteSummonsMaterials(page.currentCourt.summons, rewrites);
468
457
  }
@@ -45,8 +45,6 @@ export function createRoleRuntimeDependencies(packageRoot: string): RoleRuntimeD
45
45
  packageRoot,
46
46
  loadRoleReferenceMaterials: loadPackagedRoleReferenceMaterials,
47
47
  loadRoleSoul: loadRegisteredRoleSoul,
48
- loadFixPacket: (path) => readFile(path, "utf8"),
49
- loadCoderTask: (path) => readFile(path, "utf8"),
50
48
  loadDoctorCase,
51
49
  loadNotarySourceRun: loadNotarySourceRunLocator,
52
50
  loadMergerInput: async (path) => JSON.parse(await readFile(path, "utf8")),
@@ -346,8 +346,6 @@ export {
346
346
  } from "./worker-role.ts";
347
347
  export { fixerOutputSchema, validateFixerOutput } from "./package-contracts/fixer-output.ts";
348
348
  export type { FixerBlocker, FixerClassResult, FixerPhase, FixerTestEvidence } from "./package-contracts/fixer-output.ts";
349
- export { fixerPrerequisiteSchema, fixerPrerequisitesSchema, parseFixerPrerequisites, validateFixerPrerequisites } from "./package-contracts/fixer-packet.ts";
350
- export type { FixerInvocationInput, FixerPrerequisite } from "./package-contracts/fixer-packet.ts";
351
349
  export {
352
350
  AUDITOR_SOUL_ROLES,
353
351
  AK_ROLE_AUDITOR_SUBJECT_ENV,
@@ -460,8 +458,6 @@ export type RoleRuntimeDependencies = {
460
458
  loadRoleReferenceMaterials?(role: PackagedRole): Promise<string>;
461
459
  /** One soul loader. The role argument selects the registry record. */
462
460
  loadRoleSoul(role: PackagedRole): Promise<string>;
463
- loadFixPacket?(path: string): Promise<string>;
464
- loadCoderTask?(path: string): Promise<string>;
465
461
  loadNotarySourceRun?(path: string): Promise<import("./notary-contracts.ts").NotarySourceRunLocator>;
466
462
  loadDoctorCase?(path: string): Promise<import("./doctor-contracts.ts").DoctorCase>;
467
463
  loadMergerInput?(path: string): Promise<unknown>;
@@ -1459,12 +1455,6 @@ export function createRoleRuntimeExtension(
1459
1455
  roleHost,
1460
1456
  {
1461
1457
  loadSoul: () => requireRoleSoul("fixer"),
1462
- async loadPacket(path) {
1463
- if (dependencies.loadFixPacket === undefined) {
1464
- throw new Error("Fixer packet loader is not configured");
1465
- }
1466
- return dependencies.loadFixPacket(path);
1467
- },
1468
1458
  },
1469
1459
  hostActions,
1470
1460
  { unfinishedReasonBounceLimit: deliveryLimit },
@@ -1473,12 +1463,6 @@ export function createRoleRuntimeExtension(
1473
1463
  roleHost,
1474
1464
  {
1475
1465
  loadSoul: () => requireRoleSoul("coder"),
1476
- async loadTask(path) {
1477
- if (dependencies.loadCoderTask === undefined) {
1478
- throw new Error("Coder task loader is not configured");
1479
- }
1480
- return dependencies.loadCoderTask(path);
1481
- },
1482
1466
  },
1483
1467
  hostActions,
1484
1468
  { unfinishedReasonBounceLimit: deliveryLimit },