@akagilnc/pi-workflow-roles 0.1.5015 → 0.1.5037

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.
@@ -3902,7 +3902,7 @@ var init_packaged_role_registry = __esm({
3902
3902
  activationStage: "load-and-install",
3903
3903
  receiptStatusKey: "status",
3904
3904
  // #924: 公用《票面法》三席同装
3905
- sessionMaterials: ["CLAUDE.md", "souls/countersign.md", "souls/ticket-law.md"]
3905
+ sessionMaterials: ["CLAUDE.md", "souls/countersign.md", "souls/ticket-law.md", "resources/countersign-ticket-issue.md"]
3906
3906
  },
3907
3907
  {
3908
3908
  role: "secretariat",
@@ -3910,7 +3910,7 @@ var init_packaged_role_registry = __esm({
3910
3910
  presentSettled: "always",
3911
3911
  summonResume: false,
3912
3912
  admission: "instruction",
3913
- sameParent: "court-diarist",
3913
+ sameParent: "none",
3914
3914
  phases: [null],
3915
3915
  outputTool: SECRETARIAT_OUTPUT_TOOL_NAME,
3916
3916
  settlement: "accepted",
@@ -3926,6 +3926,7 @@ var init_packaged_role_registry = __esm({
3926
3926
  "CLAUDE.md",
3927
3927
  "souls/secretariat.md",
3928
3928
  "souls/ticket-law.md",
3929
+ "resources/secretariat-ticket-identity.md",
3929
3930
  "souls/countersign.md",
3930
3931
  "souls/notary.md"
3931
3932
  ]
@@ -8156,7 +8157,7 @@ async function findLatestRunIdForSeatTicket(input) {
8156
8157
  const runId = entry.slice(0, entry.length - suffix.length);
8157
8158
  if (runId.length === 0) continue;
8158
8159
  const parentPath = await readRunParentPath(runDirectory);
8159
- if (parentPath !== input.parentRunPath) continue;
8160
+ if (parentPath !== input.parentRunPath && basename6(parentPath ?? "") !== basename6(input.parentRunPath)) continue;
8160
8161
  if (!await runHasFormedSessionPrincipal(runDirectory)) continue;
8161
8162
  if (best === void 0 || runId > best) best = runId;
8162
8163
  }
@@ -8218,7 +8219,7 @@ function restoredTicketFields(fields) {
8218
8219
  ...fields.courtTicketNumbers === void 0 ? {} : { courtTicketNumbers: fields.courtTicketNumbers }
8219
8220
  };
8220
8221
  }
8221
- async function loadResumableRunRecord(home, runId, authority) {
8222
+ async function loadResumableRunRecord(home, runId, authority, allowUnformedAdmitted = false) {
8222
8223
  const runDirectory = await findRunDirectoryById(home, runId);
8223
8224
  if (runDirectory === void 0) {
8224
8225
  throw new CliUsageError(`unknown role run id: ${runId}`);
@@ -8232,7 +8233,7 @@ async function loadResumableRunRecord(home, runId, authority) {
8232
8233
  throw new CliUsageError(`unknown role run id: ${runId}`);
8233
8234
  }
8234
8235
  const { run, principal } = materialized;
8235
- if (!await isDurablePrincipalAvailable(principal, authority)) {
8236
+ if (!(allowUnformedAdmitted && run.state === "admitted") && !await isDurablePrincipalAvailable(principal, authority)) {
8236
8237
  throw new CliUsageError(
8237
8238
  `role run Pi session principal is unavailable: ${runId}`
8238
8239
  );
@@ -8513,8 +8514,8 @@ async function peekRoleRunRole(home, runId) {
8513
8514
  const run = await readRoleRunIdentity(runDirectory);
8514
8515
  return run?.role;
8515
8516
  }
8516
- async function loadResumablePublicRole(home, runId, authority) {
8517
- const loaded = await loadResumableRunRecord(home, runId, authority);
8517
+ async function loadResumablePublicRole(home, runId, authority, allowUnformedAdmitted = false) {
8518
+ const loaded = await loadResumableRunRecord(home, runId, authority, allowUnformedAdmitted);
8518
8519
  return seatLoadedResult(loaded, admitResumedRole(loaded));
8519
8520
  }
8520
8521
  function admitResumedRole(loaded) {
@@ -10192,12 +10193,7 @@ async function persistAdmittedSourceRunPath(admitted, sourceRunPath) {
10192
10193
  );
10193
10194
  }
10194
10195
  async function bindAdmittedTicketNumber(admitted, ticketNumber) {
10195
- if (admitted.ticketNumber !== void 0) {
10196
- if (admitted.ticketNumber === ticketNumber) return;
10197
- throw new Error(
10198
- `bindAdmittedTicketNumber refuses to replace existing ticket #${admitted.ticketNumber} with #${ticketNumber}`
10199
- );
10200
- }
10196
+ if (admitted.ticketNumber === ticketNumber) return;
10201
10197
  await bindTicketNumberOnRunDirectory(admitted.runDirectory, ticketNumber);
10202
10198
  admitted.ticketNumber = ticketNumber;
10203
10199
  }
@@ -10281,6 +10277,7 @@ async function relocateAdmittedRunToTicket(admitted, authority, heldLease) {
10281
10277
  for (const childRunId of Array.isArray(childRunIds) ? childRunIds : []) {
10282
10278
  if (typeof childRunId !== "string") continue;
10283
10279
  const childDirectory = join17(dirname10(oldRunDirectory), `${childRunId}@diarist`);
10280
+ if (!existsSync4(childDirectory)) continue;
10284
10281
  const childTarget = roleRunPlacement(ledgerHome, {
10285
10282
  bookKey: admitted.bookKey,
10286
10283
  subject: { ticketNumber: admitted.ticketNumber },
@@ -10288,7 +10285,6 @@ async function relocateAdmittedRunToTicket(admitted, authority, heldLease) {
10288
10285
  role: "diarist"
10289
10286
  });
10290
10287
  authority.seal(childTarget);
10291
- if (!existsSync4(childDirectory) && existsSync4(childTarget.runDirectory)) continue;
10292
10288
  await bindTicketNumberOnRunDirectory(childDirectory, admitted.ticketNumber);
10293
10289
  await rehomeUnboundTicketProvenance(childDirectory, admitted.ticketNumber, admitted.projectRoot, homeFromRunDirectory(oldRunDirectory));
10294
10290
  ensureRoleRunDirectory(ledgerHome, dirname10(childTarget.runDirectory));
@@ -10338,25 +10334,8 @@ async function bindTicketNumberOnRunDirectory(runDirectory, ticketNumber) {
10338
10334
  "bindTicketNumberOnRunDirectory"
10339
10335
  );
10340
10336
  const admittedPath = join17(runDirectory, "admitted-request.json");
10341
- const invocationPath = join17(runDirectory, "invocation.json");
10342
10337
  const admitted = JSON.parse(await readFile12(admittedPath, "utf8"));
10343
- const existing = admitted.ticketNumber;
10344
- if (typeof existing === "number") {
10345
- if (existing === ticketNumber) return;
10346
- throw new Error(
10347
- `bindTicketNumberOnRunDirectory refuses to replace existing ticket #${existing} with #${ticketNumber}`
10348
- );
10349
- }
10350
- if (existsSync4(invocationPath)) {
10351
- const invocation = JSON.parse(
10352
- await readFile12(invocationPath, "utf8")
10353
- );
10354
- if (typeof invocation.ticketNumber === "number" && invocation.ticketNumber !== ticketNumber) {
10355
- throw new Error(
10356
- `bindTicketNumberOnRunDirectory refuses to replace invocation ticket #${invocation.ticketNumber} with #${ticketNumber}`
10357
- );
10358
- }
10359
- }
10338
+ if (admitted.ticketNumber === ticketNumber) return;
10360
10339
  await writeFile4(
10361
10340
  admittedPath,
10362
10341
  `${JSON.stringify({ ...admitted, ticketNumber }, null, 2)}
@@ -17213,8 +17192,9 @@ function withOnceSuccessfulBeforeDispatch(adapters) {
17213
17192
  ...adapters,
17214
17193
  beforeDispatch: async (admitted, lease) => {
17215
17194
  if (succeeded) return;
17216
- await hook(admitted, lease);
17195
+ const result = await hook(admitted, lease);
17217
17196
  succeeded = true;
17197
+ return result;
17218
17198
  }
17219
17199
  };
17220
17200
  }
@@ -17476,7 +17456,10 @@ async function dispatchPostAdmissionTurn(input) {
17476
17456
  await clearTypedProviderHttpObservation(admitted.runDirectory);
17477
17457
  if (adapters.beforeDispatch !== void 0) {
17478
17458
  try {
17479
- await adapters.beforeDispatch(admitted, lease);
17459
+ const paused = await adapters.beforeDispatch(admitted, lease);
17460
+ if (paused !== void 0) {
17461
+ return { exitCode: 0, admitted, terminal: paused, skipAutoResume: true };
17462
+ }
17480
17463
  } catch (error) {
17481
17464
  const settled2 = await presentControlledFailure2(
17482
17465
  admitted,
@@ -18249,11 +18232,6 @@ var init_turn_request = __esm({
18249
18232
  });
18250
18233
 
18251
18234
  // src/public-cli/countersign-run.ts
18252
- var countersign_run_exports = {};
18253
- __export(countersign_run_exports, {
18254
- invokeCourtDiarist: () => invokeCourtDiarist,
18255
- runCountersignCourtDiaristStation: () => runCountersignCourtDiaristStation
18256
- });
18257
18235
  function isRecord14(value) {
18258
18236
  return typeof value === "object" && value !== null && !Array.isArray(value);
18259
18237
  }
@@ -18353,7 +18331,8 @@ async function invokeCourtDiarist(input, env, io) {
18353
18331
  kind: "escalate",
18354
18332
  diagnostic: courtDiaristEscalateDiagnostic(roleOutcome, submissions)
18355
18333
  },
18356
- ...result.admitted === void 0 ? {} : { admitted: result.admitted }
18334
+ ...result.admitted === void 0 ? {} : { admitted: result.admitted },
18335
+ ...result.terminal === void 0 ? {} : { terminal: result.terminal }
18357
18336
  };
18358
18337
  }
18359
18338
  if (result.exitCode !== 0) {
@@ -18387,7 +18366,7 @@ async function invokeCourtDiarist(input, env, io) {
18387
18366
  ...result.admitted === void 0 ? {} : { admitted: result.admitted }
18388
18367
  };
18389
18368
  }
18390
- async function runCountersignCourtDiaristStation(admitted, env, io) {
18369
+ async function runCountersignCourtDiaristStation(admitted, env, io, afterTicketNumber) {
18391
18370
  if (env.runCourtDiaristStation !== void 0) {
18392
18371
  await env.runCourtDiaristStation(admitted);
18393
18372
  return;
@@ -18404,7 +18383,8 @@ async function runCountersignCourtDiaristStation(admitted, env, io) {
18404
18383
  } else {
18405
18384
  refreshTickets = [admitted.ticketNumber];
18406
18385
  }
18407
- for (const ticketNumber of refreshTickets) {
18386
+ const completedIndex = afterTicketNumber === void 0 ? -1 : refreshTickets.indexOf(afterTicketNumber);
18387
+ for (const ticketNumber of refreshTickets.slice(completedIndex + 1)) {
18408
18388
  const outcome = await invokeCourtDiarist(
18409
18389
  {
18410
18390
  instruction: `\u6574\u7406 #${ticketNumber} \u7684\u672C\u6848\u4F9D\u636E\u3002`,
@@ -18417,14 +18397,17 @@ async function runCountersignCourtDiaristStation(admitted, env, io) {
18417
18397
  env,
18418
18398
  io
18419
18399
  );
18420
- if (outcome.identity.kind === "escalate") {
18421
- throw new StationChildExhaustedError(outcome.identity.diagnostic);
18422
- }
18423
18400
  if (outcome.failedWithoutEscalate !== void 0) {
18424
18401
  throw new StationChildExhaustedError(
18425
18402
  outcome.failedWithoutEscalate.diagnostic
18426
18403
  );
18427
18404
  }
18405
+ if (outcome.identity.kind === "escalate" && outcome.terminal !== void 0) {
18406
+ return {
18407
+ terminal: outcome.terminal,
18408
+ ...outcome.admitted === void 0 ? {} : { childRunId: outcome.admitted.runId }
18409
+ };
18410
+ }
18428
18411
  }
18429
18412
  }
18430
18413
  var init_countersign_run = __esm({
@@ -18441,6 +18424,7 @@ var init_countersign_run = __esm({
18441
18424
  var instruction_seat_run_exports = {};
18442
18425
  __export(instruction_seat_run_exports, {
18443
18426
  buildInstructionSeatTurnRequest: () => buildInstructionSeatTurnRequest,
18427
+ continueParentAfterChild: () => continueParentAfterChild,
18444
18428
  runPublicInstructionSeat: () => runPublicInstructionSeat,
18445
18429
  runPublicInstructionSeatResume: () => runPublicInstructionSeatResume
18446
18430
  });
@@ -18666,7 +18650,7 @@ async function runCountersignBody(parsed, env, io) {
18666
18650
  projectRoot: resolve13(parsed.project ?? env.cwd),
18667
18651
  role: "countersign",
18668
18652
  parentRunPath: gateParentRunPath,
18669
- ...env.boundTicketNumber === void 0 ? {} : { ticketNumber: env.boundTicketNumber },
18653
+ ...isSafePositiveTicketNumber(env.boundTicketNumber) ? { ticketNumber: env.boundTicketNumber } : {},
18670
18654
  freshSummons: env.freshSummons,
18671
18655
  summons: {
18672
18656
  sourceRunPath: gateParentRunPath,
@@ -18703,14 +18687,16 @@ async function runCountersignBody(parsed, env, io) {
18703
18687
  let typedTicket;
18704
18688
  let typedCourtTicketNumbers;
18705
18689
  let identityDiaristRan = false;
18706
- let unboundDiaristRunId;
18707
- if (env.runCourtDiaristStation === void 0) {
18690
+ let childDiaristRunId;
18691
+ let pausedDiaristTerminal;
18692
+ if (gateParentRunPath === void 0 && env.runCourtDiaristStation === void 0) {
18708
18693
  let outcome;
18709
18694
  try {
18710
18695
  outcome = await invokeCourtDiarist({
18711
18696
  instruction: parsed.instruction ?? "",
18712
18697
  projectRoot: admitted.projectRoot,
18713
18698
  failureLabel: "unbound summons",
18699
+ correlationId: admitted.runId,
18714
18700
  ...env.boundTicketNumber === void 0 ? {} : { boundTicketNumber: env.boundTicketNumber }
18715
18701
  }, env, io);
18716
18702
  } catch (error) {
@@ -18726,15 +18712,16 @@ async function runCountersignBody(parsed, env, io) {
18726
18712
  }, seatAdapters(admitted, env), env.principalAuthority, io);
18727
18713
  }
18728
18714
  identityDiaristRan = true;
18715
+ if (outcome.identity.kind === "escalate") pausedDiaristTerminal = outcome.terminal;
18729
18716
  if (outcome.admitted?.runDirectory.includes(`${sep5}unbound${sep5}runs${sep5}`)) {
18730
- unboundDiaristRunId = outcome.admitted.runId;
18717
+ childDiaristRunId = outcome.admitted.runId;
18731
18718
  }
18732
- if (outcome.identity.kind === "escalate" || outcome.failedWithoutEscalate !== void 0) {
18733
- const diagnostic = outcome.identity.kind === "escalate" ? outcome.identity.diagnostic : outcome.failedWithoutEscalate?.diagnostic ?? "";
18719
+ if (outcome.failedWithoutEscalate !== void 0) {
18720
+ const diagnostic = outcome.failedWithoutEscalate.diagnostic;
18734
18721
  await materializeAdmission(
18735
18722
  isSafePositiveTicketNumber(env.boundTicketNumber) ? env.boundTicketNumber : void 0
18736
18723
  );
18737
- if (unboundDiaristRunId !== void 0) await recordChildDiaristRun(admitted, unboundDiaristRunId);
18724
+ if (childDiaristRunId !== void 0) await recordChildDiaristRun(admitted, childDiaristRunId);
18738
18725
  await markRunAdmitted(admitted, env.principalAuthority);
18739
18726
  return await presentControlledFailure2(admitted, {
18740
18727
  timedOut: false,
@@ -18744,16 +18731,18 @@ async function runCountersignBody(parsed, env, io) {
18744
18731
  }, seatAdapters(admitted, env), env.principalAuthority, io);
18745
18732
  }
18746
18733
  if (outcome.identity.kind === "ticket") {
18747
- typedTicket = isSafePositiveTicketNumber(env.boundTicketNumber) ? env.boundTicketNumber : outcome.identity.ticketNumber;
18734
+ typedTicket = outcome.identity.ticketNumber;
18748
18735
  typedCourtTicketNumbers = outcome.identity.courtTicketNumbers;
18749
- } else if (isSafePositiveTicketNumber(env.boundTicketNumber)) {
18750
- typedTicket = env.boundTicketNumber;
18751
18736
  }
18752
18737
  }
18753
18738
  await materializeAdmission(typedTicket);
18754
18739
  await markRunAdmitted(admitted, env.principalAuthority);
18755
- if (unboundDiaristRunId !== void 0) {
18756
- await recordChildDiaristRun(admitted, unboundDiaristRunId);
18740
+ if (childDiaristRunId !== void 0) {
18741
+ await recordChildDiaristRun(admitted, childDiaristRunId);
18742
+ }
18743
+ if (pausedDiaristTerminal !== void 0) {
18744
+ io.stdout(formatTerminalResult(pausedDiaristTerminal));
18745
+ return { exitCode: 0, admitted, terminal: pausedDiaristTerminal };
18757
18746
  }
18758
18747
  if (gateParentRunPath !== void 0) {
18759
18748
  await persistAdmittedSourceRunPath(admitted, gateParentRunPath);
@@ -18803,7 +18792,11 @@ async function runCountersignBody(parsed, env, io) {
18803
18792
  beforeDispatch: async (admittedSeat, lease) => {
18804
18793
  if (!packagedAdmitsCountersign(admittedSeat.role)) return;
18805
18794
  if (!identityDiaristRan || typedTicket !== void 0) {
18806
- await runCountersignCourtDiaristStation(admittedSeat, env, io);
18795
+ const refresh = await runCountersignCourtDiaristStation(admittedSeat, env, io);
18796
+ if (refresh !== void 0) {
18797
+ io.stdout(formatTerminalResult(refresh.terminal));
18798
+ return refresh.terminal;
18799
+ }
18807
18800
  }
18808
18801
  await relocateAdmittedRunToTicket(admittedSeat, env.principalAuthority, lease);
18809
18802
  Object.assign(turnRequest, buildInstructionSeatTurnRequest(admittedSeat, turnProjection));
@@ -18880,7 +18873,6 @@ async function runPublicInstructionSeat(argv, env, io, role, parseArgv2) {
18880
18873
  projectRoot,
18881
18874
  role,
18882
18875
  parentRunPath: sourceDirectory,
18883
- ...auditorTicket === void 0 ? {} : { ticketNumber: auditorTicket },
18884
18876
  freshSummons: env.freshSummons,
18885
18877
  summons,
18886
18878
  resume: (runId, materials) => runPublicInstructionSeatResume(
@@ -18906,7 +18898,6 @@ async function runPublicInstructionSeat(argv, env, io, role, parseArgv2) {
18906
18898
  projectRoot,
18907
18899
  role,
18908
18900
  parentRunPath,
18909
- ...env.boundTicketNumber === void 0 ? {} : { ticketNumber: env.boundTicketNumber },
18910
18901
  freshSummons: env.freshSummons,
18911
18902
  summons,
18912
18903
  resume: (runId, materials) => runPublicInstructionSeatResume(
@@ -18934,7 +18925,6 @@ async function runPublicInstructionSeat(argv, env, io, role, parseArgv2) {
18934
18925
  throw error;
18935
18926
  }
18936
18927
  const resumeInstruction = env.reviewReask ?? env.gateReviewInstruction;
18937
- const knownTicket = await readBoardTicketNumber(source.runDirectory) ?? env.boundTicketNumber;
18938
18928
  const summons = {
18939
18929
  sourceRunPath: source.runDirectory,
18940
18930
  sourceRun: source,
@@ -18945,7 +18935,6 @@ async function runPublicInstructionSeat(argv, env, io, role, parseArgv2) {
18945
18935
  projectRoot,
18946
18936
  role,
18947
18937
  parentRunPath: source.runDirectory,
18948
- ...knownTicket === void 0 ? {} : { ticketNumber: knownTicket },
18949
18938
  freshSummons: env.freshSummons,
18950
18939
  summons,
18951
18940
  resume: (runId, materials) => runPublicInstructionSeatResume(
@@ -18982,50 +18971,38 @@ async function runPublicInstructionSeat(argv, env, io, role, parseArgv2) {
18982
18971
  }
18983
18972
  const runAdmitted = async () => {
18984
18973
  await markRunAdmitted(admitted, env.principalAuthority);
18985
- if (record4.sameParent === "court-diarist") {
18986
- const { invokeCourtDiarist: invokeCourtDiarist2 } = await Promise.resolve().then(() => (init_countersign_run(), countersign_run_exports));
18987
- const outcome = await invokeCourtDiarist2({
18988
- instruction: parsed.instruction ?? "",
18989
- projectRoot: admitted.projectRoot,
18990
- failureLabel: "secretariat unbound summons",
18991
- attachmentPaths: admitted.attachments.map((attachment) => attachment.frozenPath),
18992
- correlationId: admitted.runId
18993
- }, {
18994
- cwd: env.cwd,
18995
- home: env.home,
18996
- agentDir: env.agentDir,
18997
- packageRoot: env.packageRoot,
18998
- ...env.credentials === void 0 ? {} : { credentials: env.credentials },
18999
- ...env.signal === void 0 ? {} : { signal: env.signal },
19000
- ...env.hostAdapters === void 0 ? {} : { hostAdapters: env.hostAdapters }
19001
- }, io);
18974
+ if (role === "secretariat") {
18975
+ let outcome;
18976
+ try {
18977
+ outcome = await invokeCourtDiarist({
18978
+ instruction: parsed.instruction ?? "",
18979
+ projectRoot: admitted.projectRoot,
18980
+ failureLabel: "secretariat unbound summons",
18981
+ attachmentPaths: admitted.attachments.map((attachment) => attachment.frozenPath),
18982
+ correlationId: admitted.runId
18983
+ }, env, io);
18984
+ } catch (error) {
18985
+ return await presentControlledFailure2(admitted, {
18986
+ timedOut: false,
18987
+ code: null,
18988
+ stderr: "",
18989
+ thrown: error
18990
+ }, seatAdapters(admitted, env), env.principalAuthority, io);
18991
+ }
19002
18992
  if (outcome.admitted?.runDirectory.includes(`${sep5}unbound${sep5}runs${sep5}`)) {
19003
18993
  await recordChildDiaristRun(admitted, outcome.admitted.runId);
19004
18994
  }
19005
- if (outcome.identity.kind === "escalate" || outcome.failedWithoutEscalate !== void 0) {
19006
- const diagnostic = outcome.identity.kind === "escalate" ? outcome.identity.diagnostic : outcome.failedWithoutEscalate?.diagnostic ?? "";
18995
+ if (outcome.failedWithoutEscalate !== void 0) {
19007
18996
  return await presentControlledFailure2(admitted, {
19008
18997
  timedOut: false,
19009
18998
  code: null,
19010
18999
  stderr: "",
19011
- thrown: new Error(diagnostic)
19000
+ thrown: new Error(outcome.failedWithoutEscalate.diagnostic)
19012
19001
  }, seatAdapters(admitted, env), env.principalAuthority, io);
19013
19002
  }
19014
- if (outcome.identity.kind === "ticket") {
19015
- try {
19016
- if (outcome.admitted === void 0) throw new Error("court diarist ticket has no admitted run");
19017
- await bindAdmittedTicketNumber(outcome.admitted, outcome.identity.ticketNumber);
19018
- await relocateAdmittedRunToTicket(outcome.admitted, env.principalAuthority);
19019
- await bindAdmittedTicketNumber(admitted, outcome.identity.ticketNumber);
19020
- await relocateAdmittedRunToTicket(admitted, env.principalAuthority);
19021
- } catch (error) {
19022
- return await presentControlledFailure2(admitted, {
19023
- timedOut: false,
19024
- code: null,
19025
- stderr: "",
19026
- thrown: error
19027
- }, seatAdapters(admitted, env), env.principalAuthority, io);
19028
- }
19003
+ if (outcome.identity.kind === "escalate" && outcome.terminal !== void 0) {
19004
+ io.stdout(formatTerminalResult(outcome.terminal));
19005
+ return { exitCode: 0, admitted, terminal: outcome.terminal };
19029
19006
  }
19030
19007
  }
19031
19008
  return dispatchAdmitted(admitted, env, io);
@@ -19089,6 +19066,21 @@ async function runPublicInstructionSeatResume(request, env, io) {
19089
19066
  ...env.engine === void 0 ? {} : { effectiveEngine: env.engine }
19090
19067
  });
19091
19068
  }
19069
+ async function continueParentAfterChild(parentRunId, child, env, io) {
19070
+ const loaded = await loadResumablePublicRole(env.home, parentRunId, env.principalAuthority, true);
19071
+ if (loaded.run.state !== "admitted") {
19072
+ return runPublicInstructionSeatResume({ runId: parentRunId }, env, io);
19073
+ }
19074
+ const admitted = loaded.admitted;
19075
+ if (admitted.role === "countersign" && admitted.ticketNumber !== void 0) {
19076
+ const refresh = await runCountersignCourtDiaristStation(admitted, env, io, child.ticketNumber);
19077
+ if (refresh !== void 0) {
19078
+ io.stdout(formatTerminalResult(refresh.terminal));
19079
+ return { exitCode: 0, admitted, terminal: refresh.terminal };
19080
+ }
19081
+ }
19082
+ return dispatchAdmitted(admitted, env, io);
19083
+ }
19092
19084
  var init_instruction_seat_run = __esm({
19093
19085
  "src/public-cli/instruction-seat-run.ts"() {
19094
19086
  "use strict";
@@ -22048,7 +22040,24 @@ async function runAkRole(argv, env) {
22048
22040
  }),
22049
22041
  io
22050
22042
  );
22051
- return cliResultFromRoleRun(result);
22043
+ let current = result;
22044
+ while (current.exitCode === 0 && current.admitted?.correlationId !== void 0 && current.terminal?.roleOutcome.kind === "accepted" && !courtDiaristEscalated(current.terminal.roleOutcome)) {
22045
+ const parentRunId = current.admitted.correlationId;
22046
+ const parentRole = await peekRoleRunRole(home, parentRunId);
22047
+ if (parentRole === void 0) break;
22048
+ const parentSeat = resolveEffectiveSeat(config, parentRole, credentials, invocationFromParsed(parsed));
22049
+ const parentEnv = createRoleEnvironment(env, {
22050
+ role: parentRole,
22051
+ home,
22052
+ agentDir,
22053
+ cwd,
22054
+ credentials,
22055
+ seat: parentSeat,
22056
+ config
22057
+ });
22058
+ current = await continueParentAfterChild(parentRunId, current.admitted, parentEnv, io);
22059
+ }
22060
+ return cliResultFromRoleRun(current);
22052
22061
  }
22053
22062
  if (parsed.command !== void 0 && isPublicCliSupportCommand(parsed.command)) {
22054
22063
  throw new CliUsageError(`unhandled support command: ${parsed.command}`);
@@ -22117,6 +22126,7 @@ var init_cli = __esm({
22117
22126
  init_invocation();
22118
22127
  init_option_definitions();
22119
22128
  init_instruction_seat_run();
22129
+ init_countersign_run();
22120
22130
  init_analyst_run();
22121
22131
  init_run_lifecycle();
22122
22132
  init_registry();
@@ -22416,7 +22426,10 @@ async function summonPublicRole(options) {
22416
22426
  result = stepped.ok;
22417
22427
  }
22418
22428
  const stderr = captured?.stderrText();
22419
- const runDirectory = result.admitted?.runDirectory;
22429
+ const runDirectory = result.terminal !== void 0 && result.terminal.roleOutcome.role !== options.role && typeof result.terminal.runId === "string" ? await (await Promise.resolve().then(() => (init_run_lifecycle(), run_lifecycle_exports))).findRunDirectoryById(
22430
+ home,
22431
+ result.terminal.runId
22432
+ ) : result.admitted?.runDirectory;
22420
22433
  return {
22421
22434
  exitCode: result.exitCode,
22422
22435
  ...result.terminal === void 0 ? {} : { terminal: result.terminal },
@@ -22620,8 +22633,10 @@ async function summonGateOfficer(options) {
22620
22633
  `countersign gate summon requires parent runId from sourceRunDirectory: ${options.sourceRunDirectory}`
22621
22634
  );
22622
22635
  }
22623
- const { readBoardTicketNumber: readBoardTicketNumber2 } = await Promise.resolve().then(() => (init_run_ticket_number(), run_ticket_number_exports));
22636
+ const { isSafePositiveTicketNumber: isSafePositiveTicketNumber2, readBoardTicketNumber: readBoardTicketNumber2 } = await Promise.resolve().then(() => (init_run_ticket_number(), run_ticket_number_exports));
22624
22637
  const parentTicket = await readBoardTicketNumber2(options.sourceRunDirectory);
22638
+ const submittedTicket = options.submission !== null && typeof options.submission === "object" && !Array.isArray(options.submission) ? options.submission.ticketNumber : void 0;
22639
+ const courtTicket = isSafePositiveTicketNumber2(submittedTicket) ? submittedTicket : parentTicket;
22625
22640
  const instruction = options.reask ?? gateReviewInstruction ?? "";
22626
22641
  return summonPublicRole({
22627
22642
  role: options.officer,
@@ -22629,7 +22644,7 @@ async function summonGateOfficer(options) {
22629
22644
  ...common,
22630
22645
  correlationId,
22631
22646
  parentRunPath: options.sourceRunDirectory,
22632
- ...parentTicket === void 0 ? {} : { boundTicketNumber: parentTicket }
22647
+ ...courtTicket === void 0 ? {} : { boundTicketNumber: courtTicket }
22633
22648
  });
22634
22649
  }
22635
22650
  return summonPublicRole({
@@ -14311,7 +14311,7 @@ var init_packaged_role_registry = __esm({
14311
14311
  activationStage: "load-and-install",
14312
14312
  receiptStatusKey: "status",
14313
14313
  // #924: 公用《票面法》三席同装
14314
- sessionMaterials: ["CLAUDE.md", "souls/countersign.md", "souls/ticket-law.md"]
14314
+ sessionMaterials: ["CLAUDE.md", "souls/countersign.md", "souls/ticket-law.md", "resources/countersign-ticket-issue.md"]
14315
14315
  },
14316
14316
  {
14317
14317
  role: "secretariat",
@@ -14319,7 +14319,7 @@ var init_packaged_role_registry = __esm({
14319
14319
  presentSettled: "always",
14320
14320
  summonResume: false,
14321
14321
  admission: "instruction",
14322
- sameParent: "court-diarist",
14322
+ sameParent: "none",
14323
14323
  phases: [null],
14324
14324
  outputTool: SECRETARIAT_OUTPUT_TOOL_NAME,
14325
14325
  settlement: "accepted",
@@ -14335,6 +14335,7 @@ var init_packaged_role_registry = __esm({
14335
14335
  "CLAUDE.md",
14336
14336
  "souls/secretariat.md",
14337
14337
  "souls/ticket-law.md",
14338
+ "resources/secretariat-ticket-identity.md",
14338
14339
  "souls/countersign.md",
14339
14340
  "souls/notary.md"
14340
14341
  ]
@@ -353,7 +353,7 @@ const PUBLIC_ROLE_RECORDS = [
353
353
  activationStage: "load-and-install",
354
354
  receiptStatusKey: "status",
355
355
  // #924: 公用《票面法》三席同装
356
- sessionMaterials: ["CLAUDE.md", "souls/countersign.md", "souls/ticket-law.md"]
356
+ sessionMaterials: ["CLAUDE.md", "souls/countersign.md", "souls/ticket-law.md", "resources/countersign-ticket-issue.md"]
357
357
  },
358
358
  {
359
359
  role: "secretariat",
@@ -361,7 +361,7 @@ const PUBLIC_ROLE_RECORDS = [
361
361
  presentSettled: "always",
362
362
  summonResume: false,
363
363
  admission: "instruction",
364
- sameParent: "court-diarist",
364
+ sameParent: "none",
365
365
  phases: [null],
366
366
  outputTool: SECRETARIAT_OUTPUT_TOOL_NAME,
367
367
  settlement: "accepted",
@@ -377,6 +377,7 @@ const PUBLIC_ROLE_RECORDS = [
377
377
  "CLAUDE.md",
378
378
  "souls/secretariat.md",
379
379
  "souls/ticket-law.md",
380
+ "resources/secretariat-ticket-identity.md",
380
381
  "souls/countersign.md",
381
382
  "souls/notary.md"
382
383
  ]
@@ -16,7 +16,8 @@ import { appendPiSessionCustomEntry } from "../pi/role-turn-host.js";
16
16
  import { composeRoleTurnHostAdapters, formatHostSelectionFailure, HostSelectionError, selectRoleTurnHost, } from "./role-turn-host-resolution.js";
17
17
  import { parseAnalystArgv, parsePublicSeatArgv, } from "./invocation.js";
18
18
  import { createTypedOptionConsumer, optionsForOwner, projectCommandHelp, projectOwnerOptions, PUBLIC_NAVIGATOR_HELP_NOTE, PUBLIC_ROLE_OPTION_OWNERS, renderHumanOwnerOptionLines, } from "./option-definitions.js";
19
- import { runPublicInstructionSeat, runPublicInstructionSeatResume } from "./instruction-seat-run.js";
19
+ import { continueParentAfterChild, runPublicInstructionSeat, runPublicInstructionSeatResume } from "./instruction-seat-run.js";
20
+ import { courtDiaristEscalated } from "./countersign-run.js";
20
21
  import { runPublicAnalyst } from "./analyst-run.js";
21
22
  import { AUTO_RESUME_LIMIT, peekRoleRunRole, } from "./run-lifecycle.js";
22
23
  import { INTERNAL_ROLE_ENTRYPOINT_RELATIVE, PUBLIC_CALLABLE_ROLES, isPublicCallableRole, isPublicCliSupportCommand, isPublicConfigurableSeat, listHelpCapabilities, } from "./registry.js";
@@ -832,7 +833,21 @@ export async function runAkRole(argv, env) {
832
833
  seat,
833
834
  config,
834
835
  }), io);
835
- return cliResultFromRoleRun(result);
836
+ let current = result;
837
+ while (current.exitCode === 0 && current.admitted?.correlationId !== undefined
838
+ && current.terminal?.roleOutcome.kind === "accepted"
839
+ && !courtDiaristEscalated(current.terminal.roleOutcome)) {
840
+ const parentRunId = current.admitted.correlationId;
841
+ const parentRole = await peekRoleRunRole(home, parentRunId);
842
+ if (parentRole === undefined)
843
+ break;
844
+ const parentSeat = resolveEffectiveSeat(config, parentRole, credentials, invocationFromParsed(parsed));
845
+ const parentEnv = createRoleEnvironment(env, {
846
+ role: parentRole, home, agentDir, cwd, credentials, seat: parentSeat, config,
847
+ });
848
+ current = await continueParentAfterChild(parentRunId, current.admitted, parentEnv, io);
849
+ }
850
+ return cliResultFromRoleRun(current);
836
851
  }
837
852
  if (parsed.command !== undefined &&
838
853
  isPublicCliSupportCommand(parsed.command)) {
@@ -62,7 +62,7 @@ function courtDiaristEscalateDiagnostic(roleOutcome, submissions) {
62
62
  * - Multiple submissions: last qualifying set wins.
63
63
  * Live path never shape-rejects the role turn; durable damage is a separate seam.
64
64
  */
65
- function courtTicketNumbersFromOutcome(roleOutcome, principalTicket, submissions) {
65
+ export function courtTicketNumbersFromOutcome(roleOutcome, principalTicket, submissions) {
66
66
  if (roleOutcome === undefined)
67
67
  return undefined;
68
68
  const payloads = courtDiaristPayloadRows(roleOutcome, submissions);
@@ -97,7 +97,7 @@ function courtTicketNumbersFromOutcome(roleOutcome, principalTicket, submissions
97
97
  return latest;
98
98
  }
99
99
  /** Routing boolean over the child's own typed sequence — does not pick or rewrite a sole row. */
100
- function courtDiaristEscalated(roleOutcome) {
100
+ export function courtDiaristEscalated(roleOutcome) {
101
101
  if (roleOutcome === undefined)
102
102
  return false;
103
103
  if (roleOutcome.kind === "audit_escalation")
@@ -164,6 +164,7 @@ export async function invokeCourtDiarist(input, env, io) {
164
164
  diagnostic: courtDiaristEscalateDiagnostic(roleOutcome, submissions),
165
165
  },
166
166
  ...(result.admitted === undefined ? {} : { admitted: result.admitted }),
167
+ ...(result.terminal === undefined ? {} : { terminal: result.terminal }),
167
168
  };
168
169
  }
169
170
  if (result.exitCode !== 0) {
@@ -204,10 +205,10 @@ export async function invokeCourtDiarist(input, env, io) {
204
205
  * Missing ticketNumber (true-unbound / identity deferred) skips the refresh
205
206
  * station — no diary is minted for a true-unbound run. First-entry identity
206
207
  * lives on the shared countersign entry (typed 起居郎 key for bind). Bound refresh:
207
- * 起居郎 failure propagates (失败诚实).
208
+ * technical failure propagates; LLM escalation remains a recorded conclusion.
208
209
  * Path delivery onto materials is not this station's job — post-admission owns it.
209
210
  */
210
- export async function runCountersignCourtDiaristStation(admitted, env, io) {
211
+ export async function runCountersignCourtDiaristStation(admitted, env, io, afterTicketNumber) {
211
212
  if (env.runCourtDiaristStation !== undefined) {
212
213
  await env.runCourtDiaristStation(admitted);
213
214
  return;
@@ -230,7 +231,8 @@ export async function runCountersignCourtDiaristStation(admitted, env, io) {
230
231
  else {
231
232
  refreshTickets = [admitted.ticketNumber];
232
233
  }
233
- for (const ticketNumber of refreshTickets) {
234
+ const completedIndex = afterTicketNumber === undefined ? -1 : refreshTickets.indexOf(afterTicketNumber);
235
+ for (const ticketNumber of refreshTickets.slice(completedIndex + 1)) {
234
236
  const outcome = await invokeCourtDiarist({
235
237
  instruction: `整理 #${ticketNumber} 的本案依据。`,
236
238
  projectRoot: admitted.projectRoot,
@@ -239,11 +241,14 @@ export async function runCountersignCourtDiaristStation(admitted, env, io) {
239
241
  // Refresh holds a typed key — hand it off so identity is bound before turn.
240
242
  boundTicketNumber: ticketNumber,
241
243
  }, env, io);
242
- if (outcome.identity.kind === "escalate") {
243
- throw new StationChildExhaustedError(outcome.identity.diagnostic);
244
- }
245
244
  if (outcome.failedWithoutEscalate !== undefined) {
246
245
  throw new StationChildExhaustedError(outcome.failedWithoutEscalate.diagnostic);
247
246
  }
247
+ if (outcome.identity.kind === "escalate" && outcome.terminal !== undefined) {
248
+ return {
249
+ terminal: outcome.terminal,
250
+ ...(outcome.admitted === undefined ? {} : { childRunId: outcome.admitted.runId }),
251
+ };
252
+ }
248
253
  }
249
254
  }