@akagilnc/pi-workflow-roles 0.1.5593 → 0.1.5614

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 (58) hide show
  1. package/README.md +1 -1
  2. package/README.zh-CN.md +1 -1
  3. package/dist/acp-host/production-host.js +521 -707
  4. package/dist/compliance-transport.js +2 -5
  5. package/dist/doctor-auditor.js +1 -1
  6. package/dist/gatekeeper-role.js +1 -1
  7. package/dist/headless-host/production-host.js +505 -691
  8. package/dist/merger-contracts.js +6 -2
  9. package/dist/migrate-book-topology.js +5142 -10735
  10. package/dist/navigator-public-session.js +4 -4
  11. package/dist/navigator-work-base.js +5 -30
  12. package/dist/package-contracts/worker-output.js +1 -6
  13. package/dist/packaged-role-registry.js +9 -6
  14. package/dist/pi/role-turn-host.js +10 -1
  15. package/dist/public-cli/instruction-seat-run.js +133 -38
  16. package/dist/public-cli/invocation.js +38 -74
  17. package/dist/public-cli/main.js +18155 -18235
  18. package/dist/public-cli/option-definitions.js +21 -2
  19. package/dist/public-cli/post-admission.js +25 -24
  20. package/dist/public-cli/run-lifecycle.js +4 -43
  21. package/dist/public-cli/turn-request.js +4 -9
  22. package/dist/public-role-summons.js +5 -3
  23. package/dist/role-run-placement.js +7 -1
  24. package/dist/role-run-relocation.js +3 -4
  25. package/package.json +1 -1
  26. package/scripts/build-package.mjs +2 -4
  27. package/src/audited-run-identity.ts +30 -0
  28. package/src/compliance-transport.ts +1 -4
  29. package/src/doctor-auditor.ts +1 -1
  30. package/src/gatekeeper-role.ts +1 -1
  31. package/src/host-contracts.ts +6 -4
  32. package/src/merger-contracts.ts +6 -2
  33. package/src/merger-role.ts +11 -1
  34. package/src/navigator-attendance.ts +2 -2
  35. package/src/navigator-public-session.ts +9 -5
  36. package/src/navigator-work-base.ts +19 -34
  37. package/src/notary-role.ts +12 -21
  38. package/src/package-contracts/worker-output.ts +0 -8
  39. package/src/packaged-role-registry.ts +8 -7
  40. package/src/pi/role-turn-host.ts +11 -1
  41. package/src/public-cli/instruction-seat-run.ts +162 -42
  42. package/src/public-cli/invocation.ts +55 -93
  43. package/src/public-cli/option-definitions.ts +22 -2
  44. package/src/public-cli/post-admission.ts +30 -24
  45. package/src/public-cli/run-lifecycle.ts +4 -56
  46. package/src/public-cli/turn-request.ts +9 -8
  47. package/src/public-role-summons.ts +17 -6
  48. package/src/role-envelope.ts +4 -0
  49. package/src/role-run-placement.ts +10 -1
  50. package/src/role-run-relocation.ts +3 -4
  51. package/src/role-runtime-dependencies.ts +0 -2
  52. package/src/role-runtime.ts +54 -47
  53. package/src/worker-role.ts +11 -78
  54. package/dist/auditor-dossier-tool.js +0 -47
  55. package/dist/package-contracts/fixer-packet.js +0 -77
  56. package/packets/fixer-prerequisites.json +0 -6
  57. package/src/auditor-dossier-tool.ts +0 -63
  58. package/src/package-contracts/fixer-packet.ts +0 -91
@@ -13,7 +13,6 @@ import { parseRunLeaf } from "./role-run-placement.js";
13
13
  import { CliUsageError } from "./public-cli/cli-errors.js";
14
14
  import { isNavigatorSeat } from "./packaged-role-registry.js";
15
15
  import {
16
- attachWorkContextPointer,
17
16
  navigatorWorkContextFile
18
17
  } from "./navigator-work-base.js";
19
18
  import { isRecord } from "./unknown-value.js";
@@ -95,13 +94,14 @@ function createNativeNavigatorSessionFactory(deps) {
95
94
  if (disposed) return;
96
95
  const resumeRunId = hostRunId;
97
96
  const workContextPath = navigatorWorkContextFile(sessionManager.getSessionDir());
98
- const argvText = existsSync(workContextPath) ? attachWorkContextPointer(text, workContextPath) : text;
97
+ const workContextLocator = existsSync(workContextPath) ? workContextPath : void 0;
99
98
  const baseSummon = {
100
99
  role: "navigator",
101
- argv: [argvText],
100
+ argv: [text],
102
101
  cwd: context.cwd,
103
102
  ...summonHome === void 0 ? {} : { home: summonHome },
104
- ...context.signal === void 0 ? {} : { signal: context.signal }
103
+ ...context.signal === void 0 ? {} : { signal: context.signal },
104
+ ...workContextLocator === void 0 ? {} : { navigatorWorkContextPath: workContextLocator }
105
105
  };
106
106
  const resumable = deps?.hostRunResumable ?? navigatorHostRunResumable;
107
107
  let summoned;
@@ -4,6 +4,7 @@ import { basename, dirname, join, resolve } from "node:path";
4
4
  import { writeFileAtomically } from "./atomic-write.js";
5
5
  import { isEnoent, isRecord } from "./unknown-value.js";
6
6
  const NAVIGATOR_WORK_CONTEXT_BASENAME = "work-context.json";
7
+ const AK_ROLE_NAVIGATOR_WORK_CONTEXT_ENV = "AK_ROLE_NAVIGATOR_WORK_CONTEXT";
7
8
  function navigatorWorkContextFile(sessionDir) {
8
9
  return join(sessionDir, NAVIGATOR_WORK_CONTEXT_BASENAME);
9
10
  }
@@ -60,33 +61,8 @@ async function readNavigatorWorkBase(path) {
60
61
  if (record.authority.trim() === "") return void 0;
61
62
  return { subject: record.subject, authority: record.authority };
62
63
  }
63
- function jsonObjectFromPrompt(prompt) {
64
- const head = prompt.trimStart().split("\n\n", 1)[0] ?? "";
65
- if (!head.startsWith("{")) return void 0;
66
- try {
67
- const parsed = JSON.parse(head);
68
- if (!isRecord(parsed)) return void 0;
69
- return parsed;
70
- } catch {
71
- return void 0;
72
- }
73
- }
74
- function workContextPathFromPrompt(prompt) {
75
- const record = jsonObjectFromPrompt(prompt);
76
- const path = record?.workContextPath;
77
- if (typeof path !== "string" || path.trim() === "") return void 0;
78
- return isNavigatorWorkContextFile(path) ? path : void 0;
79
- }
80
- function attachWorkContextPointer(text, workContextPath) {
81
- const record = jsonObjectFromPrompt(text);
82
- if (record === void 0) return text;
83
- if (typeof record.workContextPath === "string" && record.workContextPath.trim() !== "") return text;
84
- const head = text.trimStart().split("\n\n", 1)[0] ?? "";
85
- const rest = text.trimStart().slice(head.length);
86
- return `${JSON.stringify({ ...record, workContextPath })}${rest}`;
87
- }
88
- async function loadNavigatorWorkBaseSuffix(prompt) {
89
- const path = workContextPathFromPrompt(prompt);
64
+ async function loadNavigatorWorkBaseSuffix(sessionDir, locatorPath) {
65
+ const path = typeof locatorPath === "string" && locatorPath.trim() !== "" ? locatorPath.trim() : typeof process.env[AK_ROLE_NAVIGATOR_WORK_CONTEXT_ENV] === "string" && process.env[AK_ROLE_NAVIGATOR_WORK_CONTEXT_ENV].trim() !== "" ? process.env[AK_ROLE_NAVIGATOR_WORK_CONTEXT_ENV].trim() : sessionDir !== void 0 && sessionDir.trim() !== "" ? navigatorWorkContextFile(sessionDir) : void 0;
90
66
  if (path === void 0) return void 0;
91
67
  const body = await readNavigatorWorkBase(path);
92
68
  if (body === void 0) return void 0;
@@ -99,12 +75,11 @@ ${body.authority}
99
75
  </controlling_authority>`;
100
76
  }
101
77
  export {
78
+ AK_ROLE_NAVIGATOR_WORK_CONTEXT_ENV,
102
79
  NAVIGATOR_WORK_CONTEXT_BASENAME,
103
- attachWorkContextPointer,
104
80
  isNavigatorWorkContextFile,
105
81
  loadNavigatorWorkBaseSuffix,
106
82
  navigatorWorkContextFile,
107
83
  persistNavigatorWorkBase,
108
- readNavigatorWorkBase,
109
- workContextPathFromPrompt
84
+ readNavigatorWorkBase
110
85
  };
@@ -6,7 +6,6 @@ import {
6
6
  PARTIALLY_COMPLETED_DEFINITION,
7
7
  validateFixerOutput
8
8
  } from "./fixer-output.js";
9
- import { fixerPrerequisiteSchema, fixerPrerequisitesSchema, parseFixerPrerequisites, validateFixerPrerequisites } from "./fixer-packet.js";
10
9
  import { withTerminatingOutputDeclarations } from "./terminating-infrastructure.js";
11
10
  const CODER_OUTPUT_TOOL_NAME = "ak_coder_output";
12
11
  function validateAcceptedCoderDetails(output) {
@@ -32,11 +31,7 @@ export {
32
31
  FIXER_OUTPUT_TOOL_NAME,
33
32
  coderOutputSchema,
34
33
  fixerOutputSchema,
35
- fixerPrerequisiteSchema,
36
- fixerPrerequisitesSchema,
37
- parseFixerPrerequisites,
38
34
  validateAcceptedCoderDetails,
39
35
  validateAcceptedWorkerDetails,
40
- validateFixerOutput,
41
- validateFixerPrerequisites
36
+ validateFixerOutput
42
37
  };
@@ -91,10 +91,10 @@ const PUBLIC_ROLE_RECORDS = [
91
91
  reportPhase: true
92
92
  },
93
93
  boardPlacement: "marshal",
94
+ /** #1168: dispatch is first message; navigator reads admitted instruction. */
95
+ navigatorSubject: "public-instruction",
94
96
  activationFlags: [
95
- { field: "packetPath", flag: "ak-fix-packet", binds: "input" },
96
- { field: "phase", flag: "ak-fixer-phase", binds: "phase" },
97
- { field: "prerequisitesPath", flag: "ak-fixer-prerequisites" }
97
+ { field: "phase", flag: "ak-fixer-phase", binds: "phase" }
98
98
  ],
99
99
  activationStage: "load-and-install",
100
100
  sessionMaterials: [
@@ -121,8 +121,9 @@ const PUBLIC_ROLE_RECORDS = [
121
121
  artifactFace: {
122
122
  reportPhase: true
123
123
  },
124
+ /** #1168: dispatch is first message; navigator reads admitted instruction. */
125
+ navigatorSubject: "public-instruction",
124
126
  activationFlags: [
125
- { field: "taskPath", flag: "ak-coder-task", binds: "input" },
126
127
  { field: "phase", flag: "ak-coder-phase", binds: "phase" }
127
128
  ],
128
129
  activationStage: "load-and-install",
@@ -362,7 +363,8 @@ const PUBLIC_ROLE_RECORDS = [
362
363
  presentSettled: "always",
363
364
  summonResume: false,
364
365
  admission: "instruction",
365
- sameParent: "gate-pointer",
366
+ /** Structured --source-run only; instruction stays opaque caller/peer bytes (#1166). */
367
+ sameParent: "source-run",
366
368
  /** Resume restores an optional source-run path onto the admitted face. */
367
369
  resumeSourcePath: true,
368
370
  /** 台院 is a review officer and inherits the gatekeeper model. */
@@ -375,11 +377,12 @@ const PUBLIC_ROLE_RECORDS = [
375
377
  /** Court reask replaces the initial prompt. */
376
378
  reaskPrompt: true,
377
379
  gateStageLabel: "\u53F0\u9662",
380
+ /** Gate summon binds --source-run; identity is startup material (#1166). */
381
+ gateSummon: "source-run",
378
382
  activationFlags: [
379
383
  {
380
384
  field: "sourceRun",
381
385
  from: "sourceRunPath",
382
- fallback: "gate-pointer",
383
386
  flag: "ak-inspector-source-run",
384
387
  binds: "input"
385
388
  }
@@ -339,7 +339,7 @@ export function createPiRoleTurnHost(config) {
339
339
  else
340
340
  env[RECEIPT_DELIVERY_LIMIT_ENV] = String(request.deliveryRequestLimit);
341
341
  applyEngineChildEnv(env, request.engine);
342
- // Nested auditor dossier tool binds the parent run pointer when published.
342
+ // Nested auditor binds the audited source-run for identity / soul selection.
343
343
  if (typeof process.env.AK_ROLE_AUDITOR_SOURCE_RUN === "string"
344
344
  && process.env.AK_ROLE_AUDITOR_SOURCE_RUN.trim() !== "") {
345
345
  env.AK_ROLE_AUDITOR_SOURCE_RUN = process.env.AK_ROLE_AUDITOR_SOURCE_RUN;
@@ -349,6 +349,15 @@ export function createPiRoleTurnHost(config) {
349
349
  && process.env.AK_ROLE_AUDITOR_SUBJECT.trim() !== "") {
350
350
  env.AK_ROLE_AUDITOR_SUBJECT = process.env.AK_ROLE_AUDITOR_SUBJECT;
351
351
  }
352
+ // Navigator nest work-context locator for startup materials (#1166) —
353
+ // child-process scoped only from this turn request; never parent process.env.
354
+ if (typeof request.navigatorWorkContextPath === "string"
355
+ && request.navigatorWorkContextPath.trim() !== "") {
356
+ env.AK_ROLE_NAVIGATOR_WORK_CONTEXT = request.navigatorWorkContextPath.trim();
357
+ }
358
+ else {
359
+ delete env.AK_ROLE_NAVIGATOR_WORK_CONTEXT;
360
+ }
352
361
  if (config.recordLaunchedRolePackageIdentity !== undefined &&
353
362
  config.observeLaunchedRolePackageIdentity !== undefined) {
354
363
  await config.recordLaunchedRolePackageIdentity(request.runDirectory, await config.observeLaunchedRolePackageIdentity(config.packageRoot, roleEntry));
@@ -4,8 +4,7 @@
4
4
  * starts two ordinary single-axis runs here.
5
5
  */
6
6
  import { dirname, resolve } from "node:path";
7
- import { isUnboundRunDirectory } from "../role-run-placement.js";
8
- import { AUDITOR_DOSSIER_PROMPT } from "../compliance-transport.js";
7
+ import { isUnboundRunDirectory, sessionFileOf } from "../role-run-placement.js";
9
8
  import { bookDirectOfficerRunPointer, readDirectOfficerRunPointer } from "../archivist-record-pointer.js";
10
9
  import { createPiDoctorAuditor } from "../doctor-auditor.js";
11
10
  import { officerConclusionReask, gateOfficerForSubject } from "../gatekeeper-role.js";
@@ -27,10 +26,10 @@ import { NotarySourceRunError, resolveNotarySourceRunLocator } from "../notary-s
27
26
  import { packagedAdmitsCountersign, packagedBindsBoardTicket, packagedRebindSourceOnResume, packagedRoleMetadata, } from "../packaged-role-registry.js";
28
27
  import { readAuditorResumeBinding } from "../auditor-soul.js";
29
28
  import { CliUsageError } from "./cli-errors.js";
30
- import { admitPublicRole, bindAdmittedTicketNumber, buildInstructionTransportPrompt, materializeCountersignInvocation, persistAdmittedSourceRunPath, recordAdmittedCorrelation, recordChildDiaristRun, relocateAdmittedRunToTicket, } from "./invocation.js";
29
+ import { admitPublicRole, bindAdmittedTicketNumber, appendCallerFileFlagPaths, buildInstructionTransportPrompt, materializeCountersignInvocation, persistAdmittedSourceRunPath, recordAdmittedCorrelation, recordChildDiaristRun, relocateAdmittedRunToTicket, } from "./invocation.js";
31
30
  import { bindDiaristAssertedTicketNumber, presentControlledFailure, packageFaultNoteFor, prepareSummonsResumeMaterials, roleTurnOptions, runPostAdmissionOneShot, runPostAdmissionResumable, runPostAdmissionSeatResume, showResumeErrorPointer, resumeTurnRequestProjectionOptions, } from "./post-admission.js";
32
31
  import { presentTerminal } from "./auto-resume.js";
33
- import { buildAutoResumeContinuationPrompt, loadResumablePublicRole, markRunAdmitted, parentRunPathFromGatePointerInstruction, readCurrentCourt, } from "./run-lifecycle.js";
32
+ import { buildAutoResumeContinuationPrompt, loadResumablePublicRole, markRunAdmitted, readCurrentCourt, } from "./run-lifecycle.js";
34
33
  import { tryResumeSameTicketSeatRun } from "./seat-ticket-binding.js";
35
34
  import { presentStructuralRejection, readBoundSessionEntries, attachPostAuditCountersignFact, trySettlePublicSeat, } from "./settlement.js";
36
35
  import { warnMissingMethodSkills } from "./machine-method-skills.js";
@@ -168,11 +167,69 @@ function roleRecord(role) {
168
167
  export function buildInstructionSeatTurnRequest(admitted, options) {
169
168
  return projectRoleTurnRequest(admitted, admittedSeatTurnDetails(admitted, options.home, options.host), options);
170
169
  }
171
- function initialPrompt(admitted, env) {
172
- const record = roleRecord(admitted.role);
173
- const reask = env.reviewReask ?? env.gateReviewInstruction;
174
- if (reask !== undefined && "reaskPrompt" in record && record.reaskPrompt === true) {
170
+ /**
171
+ * Direct review-seat call: reconnect ledger peer-body delivery (ADR 0085 / #1166).
172
+ * Gate summons already ride gateReviewInstruction; direct --source-run must not
173
+ * leave a blank fixed-kickoff.
174
+ */
175
+ async function loadLedgerPeerBody(sourceRunDirectory, projectRoot, home) {
176
+ const runId = runIdFromRunDirectory(sourceRunDirectory);
177
+ if (runId === undefined)
178
+ return undefined;
179
+ // Bind to the already-resolved source directory — never re-discover by runId
180
+ // alone (another book may lawfully share the same id; #637 / #1166).
181
+ const rows = await readRecordedSubmissionRows(projectRoot, runId, {
182
+ home,
183
+ sessionParent: sessionFileOf(sourceRunDirectory),
184
+ });
185
+ // ADR 0085 / #1166 J10: ledger already keeps original words for every class —
186
+ // present the latest row as-is. Never filter current manuscript by accepted /
187
+ // terminal outcome kind (that resurrects a prior sealed draft).
188
+ const latest = rows.at(-1);
189
+ if (latest === undefined)
190
+ return undefined;
191
+ return readableGateItem(latest.accepted);
192
+ }
193
+ /**
194
+ * One delivery rule for review-seat dialogue on new turns and same-parent resume
195
+ * (#1166 / ADR 0085 / ADR 0087): explicit reask → non-empty caller dispatch →
196
+ * source-only ledger peer body. Identity stays in startup materials.
197
+ */
198
+ async function resolveReviewSeatDialogueBody(input) {
199
+ const reask = input.reask;
200
+ if (reask !== undefined && reask.length > 0)
175
201
  return reask;
202
+ const caller = input.callerInstruction ?? "";
203
+ if (caller.length > 0)
204
+ return caller;
205
+ const sourceRunPath = input.sourceRunPath?.trim() ?? "";
206
+ if (sourceRunPath === "")
207
+ return undefined;
208
+ return await loadLedgerPeerBody(sourceRunPath, input.projectRoot, input.home);
209
+ }
210
+ function admittedSourceRunPath(admitted) {
211
+ return "sourceRunPath" in admitted
212
+ && typeof admitted.sourceRunPath === "string"
213
+ ? admitted.sourceRunPath.trim()
214
+ : "";
215
+ }
216
+ async function resolveInitialPrompt(admitted, env) {
217
+ const record = roleRecord(admitted.role);
218
+ if ("reaskPrompt" in record && record.reaskPrompt === true) {
219
+ const sourceRunPath = admittedSourceRunPath(admitted);
220
+ const reask = env.reviewReask ?? env.gateReviewInstruction;
221
+ const body = await resolveReviewSeatDialogueBody({
222
+ ...(reask === undefined ? {} : { reask }),
223
+ callerInstruction: admitted.instruction,
224
+ ...(sourceRunPath === "" ? {} : { sourceRunPath }),
225
+ projectRoot: admitted.projectRoot,
226
+ home: env.home,
227
+ });
228
+ // #1166 J11: merge existing file-flag delivery — never early-return body alone
229
+ // when caller attach paths were admitted. Gate with no file flags stays body-only.
230
+ if (body !== undefined) {
231
+ return appendCallerFileFlagPaths(body, admitted.attachments);
232
+ }
176
233
  }
177
234
  return buildInstructionTransportPrompt(admitted);
178
235
  }
@@ -271,13 +328,17 @@ async function dispatchAdmitted(admitted, env, io) {
271
328
  if (activeEnv.correlationId !== undefined && activeEnv.correlationId.trim() !== "") {
272
329
  await recordAdmittedCorrelation(admitted, activeEnv.correlationId);
273
330
  }
331
+ const initialPromptText = await resolveInitialPrompt(admitted, activeEnv);
274
332
  const auto = "inCallAutoResume" in record && record.inCallAutoResume === true;
275
333
  if (auto) {
276
334
  return await runPostAdmissionResumable({
277
335
  admitted,
278
336
  env: activeEnv,
279
337
  io: turnIo,
280
- buildInitialRequest: () => buildInstructionSeatTurnRequest(admitted, roleTurnOptions(activeEnv, admitted, { kind: "initial", prompt: initialPrompt(admitted, activeEnv) })),
338
+ buildInitialRequest: () => buildInstructionSeatTurnRequest(admitted, roleTurnOptions(activeEnv, admitted, {
339
+ kind: "initial",
340
+ prompt: initialPromptText,
341
+ })),
281
342
  buildResumeRequest: () => buildInstructionSeatTurnRequest(admitted, roleTurnOptions(activeEnv, admitted, {
282
343
  kind: "resume",
283
344
  prompt: buildAutoResumeContinuationPrompt(),
@@ -290,7 +351,10 @@ async function dispatchAdmitted(admitted, env, io) {
290
351
  admitted,
291
352
  env: activeEnv,
292
353
  io: turnIo,
293
- request: buildInstructionSeatTurnRequest(admitted, roleTurnOptions(activeEnv, admitted, { kind: "initial", prompt: initialPrompt(admitted, activeEnv) })),
354
+ request: buildInstructionSeatTurnRequest(admitted, roleTurnOptions(activeEnv, admitted, {
355
+ kind: "initial",
356
+ prompt: initialPromptText,
357
+ })),
294
358
  adapters,
295
359
  ...(activeEnv.engine === undefined ? {} : { effectiveEngine: activeEnv.engine }),
296
360
  });
@@ -400,12 +464,23 @@ function resumeSameParentInstructionSeat(input) {
400
464
  resume: (runId, materials) => runPublicInstructionSeatResume({ runId, ...(materials === undefined ? {} : { summons: materials }) }, input.env, input.io),
401
465
  });
402
466
  }
403
- /** Re-ask words when the parent supplied them; otherwise the caller's own instruction. */
404
- function sameParentInstruction(env, fallback) {
405
- const resumeInstruction = env.reviewReask ?? env.gateReviewInstruction;
406
- if (resumeInstruction === undefined)
407
- return fallback;
408
- return { instruction: resumeInstruction, instructionEmpty: false };
467
+ /**
468
+ * Same delivery rule as resolveInitialPrompt for same-parent resume summons.
469
+ * Reask / explicit caller text / source-only ledger peer — one authority.
470
+ */
471
+ async function sameParentDialogue(env, fallback, sourceRunPath, projectRoot) {
472
+ const reask = env.reviewReask ?? env.gateReviewInstruction;
473
+ const body = await resolveReviewSeatDialogueBody({
474
+ ...(reask === undefined ? {} : { reask }),
475
+ callerInstruction: fallback.instruction,
476
+ sourceRunPath,
477
+ projectRoot,
478
+ home: env.home,
479
+ });
480
+ if (body !== undefined) {
481
+ return { instruction: body, instructionEmpty: false };
482
+ }
483
+ return fallback;
409
484
  }
410
485
  /**
411
486
  * Countersign on the shared entry: gate parent resume, deferred materialization,
@@ -430,6 +505,9 @@ async function runCountersignBody(parsed, env, io) {
430
505
  sourceRunPath: gateParentRunPath,
431
506
  instruction: resumeInstruction,
432
507
  instructionEmpty: resumeInstruction.length === 0,
508
+ // #1166 J11: same-parent resume delivers this call's file-flag paths
509
+ // through the shared summons → appendCallerFileFlagPaths rule.
510
+ attachmentPaths: parsed.attachmentPaths ?? [],
433
511
  },
434
512
  });
435
513
  if (resumed != null)
@@ -462,10 +540,14 @@ async function runCountersignBody(parsed, env, io) {
462
540
  await persistAdmittedSourceRunPath(admitted, gateParentRunPath);
463
541
  admitted = { ...admitted, sourceRunPath: gateParentRunPath };
464
542
  }
543
+ // #1166 J11: review-body branch must merge the same file-flag delivery as
544
+ // resolveInitialPrompt / resumeTurnRequestProjectionOptions — never body alone.
545
+ const reviewBody = env.reviewReask ?? env.gateReviewInstruction;
465
546
  const turnProjection = roleTurnOptions(env, admitted, {
466
547
  kind: "initial",
467
- prompt: (env.reviewReask ?? env.gateReviewInstruction)
468
- ?? buildInstructionTransportPrompt(admitted),
548
+ prompt: reviewBody !== undefined
549
+ ? appendCallerFileFlagPaths(reviewBody, admitted.attachments)
550
+ : buildInstructionTransportPrompt(admitted),
469
551
  });
470
552
  const turnRequest = buildInstructionSeatTurnRequest(admitted, turnProjection);
471
553
  const result = await runPostAdmissionOneShot({
@@ -555,10 +637,10 @@ export async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
555
637
  return { exitCode: 2 };
556
638
  const sourceDirectory = auditorSource;
557
639
  const summons = {
558
- ...sameParentInstruction(env, {
640
+ ...(await sameParentDialogue(env, {
559
641
  instruction: parsed.instruction ?? "",
560
642
  instructionEmpty: (parsed.instruction ?? "").length === 0,
561
- }),
643
+ }, sourceDirectory, projectRoot)),
562
644
  attachmentPaths: parsed.attachmentPaths ?? [],
563
645
  };
564
646
  const resumed = await withAuditorSoulEnv({
@@ -576,15 +658,30 @@ export async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
576
658
  if (resumed != null)
577
659
  return resumed;
578
660
  }
579
- if (record.sameParent === "gate-pointer") {
580
- const parentRunPath = parentRunPathFromGatePointerInstruction(parsed.instruction ?? "");
581
- if (parentRunPath !== undefined) {
661
+ if (record.sameParent === "source-run") {
662
+ // #1166: structured --source-run only. Instruction bytes stay opaque caller/peer text.
663
+ if (parsed.sourceRun !== undefined) {
664
+ let parentRunPath;
665
+ try {
666
+ parentRunPath = (await resolveNotarySourceRunLocator({
667
+ projectRoot,
668
+ sourceRun: parsed.sourceRun,
669
+ home: env.home,
670
+ })).runDirectory;
671
+ }
672
+ catch (error) {
673
+ if (error instanceof NotarySourceRunError) {
674
+ presentStructuralRejection(new CliUsageError(error.message, { cause: error }), io);
675
+ return { exitCode: 2 };
676
+ }
677
+ throw error;
678
+ }
582
679
  const summons = {
583
680
  sourceRunPath: parentRunPath,
584
- ...sameParentInstruction(env, {
681
+ ...(await sameParentDialogue(env, {
585
682
  instruction: parsed.instruction ?? "",
586
683
  instructionEmpty: (parsed.instruction ?? "").length === 0,
587
- }),
684
+ }, parentRunPath, projectRoot)),
588
685
  attachmentPaths: parsed.attachmentPaths ?? [],
589
686
  };
590
687
  const resumed = await resumeSameParentInstructionSeat({
@@ -615,13 +712,10 @@ export async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
615
712
  }
616
713
  throw error;
617
714
  }
618
- const resumeInstruction = env.reviewReask ?? env.gateReviewInstruction;
619
715
  const summons = {
620
716
  sourceRunPath: source.runDirectory,
621
717
  sourceRun: source,
622
- ...(resumeInstruction === undefined
623
- ? {}
624
- : { instruction: resumeInstruction, instructionEmpty: false }),
718
+ ...(await sameParentDialogue(env, { instruction: "", instructionEmpty: true }, source.runDirectory, projectRoot)),
625
719
  };
626
720
  resolvedNotarySource = source;
627
721
  const resumed = await resumeSameParentInstructionSeat({
@@ -649,16 +743,18 @@ export async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
649
743
  return rejected;
650
744
  throw error;
651
745
  }
652
- if (record.sameParent === "gate-pointer") {
653
- const parentRunPath = parentRunPathFromGatePointerInstruction(parsed.instruction ?? "");
654
- if (parentRunPath !== undefined) {
655
- await persistAdmittedSourceRunPath(admitted, parentRunPath);
656
- const sourcePatch = { sourceRunPath: parentRunPath };
657
- admitted = { ...admitted, ...sourcePatch };
658
- }
746
+ if (record.sameParent === "source-run" && parsed.sourceRun !== undefined) {
747
+ const parentRunPath = (await resolveNotarySourceRunLocator({
748
+ projectRoot,
749
+ sourceRun: parsed.sourceRun,
750
+ home: env.home,
751
+ })).runDirectory;
752
+ await persistAdmittedSourceRunPath(admitted, parentRunPath);
753
+ admitted = { ...admitted, sourceRunPath: parentRunPath };
659
754
  }
660
755
  if (record.sameParent === "subject-source" && auditorSource !== undefined) {
661
756
  await persistAdmittedSourceRunPath(admitted, auditorSource, auditorSubject);
757
+ admitted = { ...admitted, sourceRunPath: auditorSource };
662
758
  }
663
759
  const runAdmitted = async () => {
664
760
  await markRunAdmitted(admitted, env.principalAuthority);
@@ -997,8 +1093,7 @@ async function auditSubmittedRole(turn, env, io, resumedOfficer, passedReceipt)
997
1093
  summonAuditor: async (subject, sourceRunDirectory, signal, reask, submission) => {
998
1094
  const summoned = await summonPublicRole({
999
1095
  role: "auditor",
1000
- argv: ["--subject", subject, "--source-run", sourceRunDirectory,
1001
- `${AUDITOR_DOSSIER_PROMPT}${sourceRunDirectory}`],
1096
+ argv: ["--subject", subject, "--source-run", sourceRunDirectory],
1002
1097
  cwd: admitted.projectRoot, home: env.home, packageRoot: env.packageRoot,
1003
1098
  principalAuthority: env.principalAuthority,
1004
1099
  correlationId: admitted.runId,