@akagilnc/pi-workflow-roles 0.1.4923 → 0.1.4932

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.
@@ -7778,7 +7778,9 @@ async function findLatestRunIdForSeatTicket(input) {
7778
7778
  const bookDir = activationBookDirectory(ledgerHome, input.bookKey);
7779
7779
  let runDirectories;
7780
7780
  try {
7781
- runDirectories = await listBookRunDirectories(bookDir);
7781
+ runDirectories = await listBookRunDirectories(
7782
+ input.ticketNumber === void 0 ? bookDir : join16(bookDir, String(input.ticketNumber))
7783
+ );
7782
7784
  } catch (error) {
7783
7785
  if (errorCodeOf2(error) === "ENOENT") return void 0;
7784
7786
  throw error;
@@ -13465,6 +13467,17 @@ var init_known_failure = __esm({
13465
13467
  }
13466
13468
  });
13467
13469
 
13470
+ // src/serialize-thrown-value.ts
13471
+ import { inspect } from "node:util";
13472
+ function serializeThrownValue(value) {
13473
+ return inspect(value, { depth: 10, showHidden: true, customInspect: false });
13474
+ }
13475
+ var init_serialize_thrown_value = __esm({
13476
+ "src/serialize-thrown-value.ts"() {
13477
+ "use strict";
13478
+ }
13479
+ });
13480
+
13468
13481
  // src/engine-detour-usage.ts
13469
13482
  import { randomUUID as randomUUID3 } from "node:crypto";
13470
13483
  import { readFileSync as readFileSync4 } from "node:fs";
@@ -14510,18 +14523,23 @@ function projectThrownFailureLeaf(error) {
14510
14523
  cause: error.knownCause,
14511
14524
  diagnostic: error.message || error.name || "exception",
14512
14525
  identity,
14513
- ...error.details === void 0 ? {} : { details: error.details }
14526
+ details: {
14527
+ ...typeof error.details === "object" && error.details !== null ? error.details : error.details === void 0 ? {} : { priorDetails: error.details },
14528
+ error: serializeThrownValue(error)
14529
+ }
14514
14530
  };
14515
14531
  }
14516
14532
  if (error instanceof Error) {
14517
14533
  const identity = thrownIdentity(error);
14518
14534
  return {
14519
14535
  diagnostic: error.message || error.name || "exception",
14520
- identity
14536
+ identity,
14537
+ details: { error: serializeThrownValue(error) }
14521
14538
  };
14522
14539
  }
14523
14540
  return {
14524
- diagnostic: String(error)
14541
+ diagnostic: error !== null && typeof error === "object" ? "non-Error throw" : String(error),
14542
+ details: { error: serializeThrownValue(error) }
14525
14543
  };
14526
14544
  }
14527
14545
  function classifyThrownFailure(error) {
@@ -16244,6 +16262,7 @@ var init_settlement = __esm({
16244
16262
  init_audit_escalation();
16245
16263
  init_auditor_soul();
16246
16264
  init_known_failure();
16265
+ init_serialize_thrown_value();
16247
16266
  init_run_lifecycle();
16248
16267
  init_compliance_transport();
16249
16268
  init_collector_ledger();
@@ -17266,53 +17285,9 @@ async function ensureRealArtifactsDirectory(runDirectory) {
17266
17285
  }
17267
17286
  return artifactsDir;
17268
17287
  }
17269
- function serializeThrownValue(value, depth = 0, seen = /* @__PURE__ */ new WeakSet()) {
17270
- if (value instanceof Error) {
17271
- if (seen.has(value)) return "[circular]";
17272
- seen.add(value);
17273
- const transferred = {};
17274
- for (const key of Object.getOwnPropertyNames(value)) {
17275
- transferred[key] = transferNestedValue(
17276
- value[key],
17277
- depth + 1,
17278
- seen
17279
- );
17280
- }
17281
- return {
17282
- errorKind: "Error",
17283
- constructorName: value.constructor?.name,
17284
- ...transferred,
17285
- ...value.cause === void 0 ? {} : {
17286
- causeChain: depth >= 10 ? "[cause-chain-depth-limit]" : serializeThrownValue(value.cause, depth + 1, seen)
17287
- }
17288
- };
17289
- }
17290
- return value;
17291
- }
17292
17288
  function isMissingPathError5(error) {
17293
17289
  return error instanceof Error && "code" in error && error.code === "ENOENT";
17294
17290
  }
17295
- function transferNestedValue(value, depth, seen) {
17296
- if (value instanceof Error) return serializeThrownValue(value, depth, seen);
17297
- if (depth >= 10) return "[nested-depth-limit]";
17298
- if (Array.isArray(value)) {
17299
- return value.map((item) => transferNestedValue(item, depth + 1, seen));
17300
- }
17301
- if (value !== null && typeof value === "object") {
17302
- if (seen.has(value)) return "[circular]";
17303
- seen.add(value);
17304
- const transferred = {};
17305
- for (const key of Object.getOwnPropertyNames(value)) {
17306
- transferred[key] = transferNestedValue(
17307
- value[key],
17308
- depth + 1,
17309
- seen
17310
- );
17311
- }
17312
- return transferred;
17313
- }
17314
- return value;
17315
- }
17316
17291
  function jsonSafeReplacer() {
17317
17292
  const seen = /* @__PURE__ */ new WeakSet();
17318
17293
  return (_key, value) => {
@@ -17594,6 +17569,7 @@ var init_auto_resume = __esm({
17594
17569
  init_process_cancel();
17595
17570
  init_terminal();
17596
17571
  init_settlement();
17572
+ init_serialize_thrown_value();
17597
17573
  dummyIo = { stdout: () => {
17598
17574
  }, stderr: () => {
17599
17575
  } };
@@ -18615,7 +18591,8 @@ async function tryResumeSameTicketSeatRun(input) {
18615
18591
  home: input.home,
18616
18592
  bookKey: resolveBookKeyFromGit(input.projectRoot),
18617
18593
  role: input.role,
18618
- parentRunPath: input.parentRunPath
18594
+ parentRunPath: input.parentRunPath,
18595
+ ...input.ticketNumber === void 0 ? {} : { ticketNumber: input.ticketNumber }
18619
18596
  });
18620
18597
  if (previousRunId === void 0) return void 0;
18621
18598
  return await input.resume(previousRunId, input.summons);
@@ -19132,6 +19109,7 @@ async function runCountersignBody(parsed, env, io) {
19132
19109
  projectRoot: resolve14(parsed.project ?? env.cwd),
19133
19110
  role: "countersign",
19134
19111
  parentRunPath: gateParentRunPath,
19112
+ ...env.boundTicketNumber === void 0 ? {} : { ticketNumber: env.boundTicketNumber },
19135
19113
  freshSummons: env.freshSummons,
19136
19114
  summons: {
19137
19115
  sourceRunPath: gateParentRunPath,
@@ -19337,6 +19315,7 @@ async function runPublicInstructionSeat(argv, env, io, role, parseArgv2) {
19337
19315
  projectRoot,
19338
19316
  role,
19339
19317
  parentRunPath: sourceDirectory,
19318
+ ...auditorTicket === void 0 ? {} : { ticketNumber: auditorTicket },
19340
19319
  freshSummons: env.freshSummons,
19341
19320
  summons,
19342
19321
  resume: (runId, materials) => runPublicInstructionSeatResume(
@@ -19362,6 +19341,7 @@ async function runPublicInstructionSeat(argv, env, io, role, parseArgv2) {
19362
19341
  projectRoot,
19363
19342
  role,
19364
19343
  parentRunPath,
19344
+ ...env.boundTicketNumber === void 0 ? {} : { ticketNumber: env.boundTicketNumber },
19365
19345
  freshSummons: env.freshSummons,
19366
19346
  summons,
19367
19347
  resume: (runId, materials) => runPublicInstructionSeatResume(
@@ -19389,6 +19369,7 @@ async function runPublicInstructionSeat(argv, env, io, role, parseArgv2) {
19389
19369
  throw error;
19390
19370
  }
19391
19371
  const resumeInstruction = env.reviewReask ?? env.gateReviewInstruction;
19372
+ const knownTicket = await readBoardTicketNumber(source.runDirectory) ?? env.boundTicketNumber;
19392
19373
  const summons = {
19393
19374
  sourceRunPath: source.runDirectory,
19394
19375
  sourceRun: source,
@@ -19399,6 +19380,7 @@ async function runPublicInstructionSeat(argv, env, io, role, parseArgv2) {
19399
19380
  projectRoot,
19400
19381
  role,
19401
19382
  parentRunPath: source.runDirectory,
19383
+ ...knownTicket === void 0 ? {} : { ticketNumber: knownTicket },
19402
19384
  freshSummons: env.freshSummons,
19403
19385
  summons,
19404
19386
  resume: (runId, materials) => runPublicInstructionSeatResume(
@@ -28431,6 +28413,7 @@ function createRoleRuntimeExtension(dependencies) {
28431
28413
  init_role_activation_flags();
28432
28414
  init_submission_correctable_error();
28433
28415
  init_navigator_invocation_identity();
28416
+ init_serialize_thrown_value();
28434
28417
  async function listen(server, path) {
28435
28418
  await new Promise((resolve22, reject) => {
28436
28419
  server.once("error", reject);
@@ -28690,7 +28673,8 @@ async function prepareRoleEnvelope(options) {
28690
28673
  ...buildNavigatorInfrastructureFailureFact(),
28691
28674
  ...extractInfrastructureFailureEvidence(error),
28692
28675
  cause: "infrastructure",
28693
- code: errorCode
28676
+ code: errorCode,
28677
+ error: serializeThrownValue(error)
28694
28678
  };
28695
28679
  rememberInfrastructureFailure(details, content);
28696
28680
  return { content, details };
@@ -7235,7 +7235,9 @@ async function findLatestRunIdForSeatTicket(input) {
7235
7235
  const bookDir = activationBookDirectory(ledgerHome, input.bookKey);
7236
7236
  let runDirectories;
7237
7237
  try {
7238
- runDirectories = await listBookRunDirectories(bookDir);
7238
+ runDirectories = await listBookRunDirectories(
7239
+ input.ticketNumber === void 0 ? bookDir : join14(bookDir, String(input.ticketNumber))
7240
+ );
7239
7241
  } catch (error) {
7240
7242
  if (errorCodeOf2(error) === "ENOENT") return void 0;
7241
7243
  throw error;
@@ -12922,6 +12924,17 @@ var init_known_failure = __esm({
12922
12924
  }
12923
12925
  });
12924
12926
 
12927
+ // src/serialize-thrown-value.ts
12928
+ import { inspect } from "node:util";
12929
+ function serializeThrownValue(value) {
12930
+ return inspect(value, { depth: 10, showHidden: true, customInspect: false });
12931
+ }
12932
+ var init_serialize_thrown_value = __esm({
12933
+ "src/serialize-thrown-value.ts"() {
12934
+ "use strict";
12935
+ }
12936
+ });
12937
+
12925
12938
  // src/engine-detour-usage.ts
12926
12939
  import { randomUUID as randomUUID3 } from "node:crypto";
12927
12940
  import { readFileSync as readFileSync3 } from "node:fs";
@@ -13967,18 +13980,23 @@ function projectThrownFailureLeaf(error) {
13967
13980
  cause: error.knownCause,
13968
13981
  diagnostic: error.message || error.name || "exception",
13969
13982
  identity,
13970
- ...error.details === void 0 ? {} : { details: error.details }
13983
+ details: {
13984
+ ...typeof error.details === "object" && error.details !== null ? error.details : error.details === void 0 ? {} : { priorDetails: error.details },
13985
+ error: serializeThrownValue(error)
13986
+ }
13971
13987
  };
13972
13988
  }
13973
13989
  if (error instanceof Error) {
13974
13990
  const identity = thrownIdentity(error);
13975
13991
  return {
13976
13992
  diagnostic: error.message || error.name || "exception",
13977
- identity
13993
+ identity,
13994
+ details: { error: serializeThrownValue(error) }
13978
13995
  };
13979
13996
  }
13980
13997
  return {
13981
- diagnostic: String(error)
13998
+ diagnostic: error !== null && typeof error === "object" ? "non-Error throw" : String(error),
13999
+ details: { error: serializeThrownValue(error) }
13982
14000
  };
13983
14001
  }
13984
14002
  function classifyThrownFailure(error) {
@@ -15701,6 +15719,7 @@ var init_settlement = __esm({
15701
15719
  init_audit_escalation();
15702
15720
  init_auditor_soul();
15703
15721
  init_known_failure();
15722
+ init_serialize_thrown_value();
15704
15723
  init_run_lifecycle();
15705
15724
  init_compliance_transport();
15706
15725
  init_collector_ledger();
@@ -16723,53 +16742,9 @@ async function ensureRealArtifactsDirectory(runDirectory) {
16723
16742
  }
16724
16743
  return artifactsDir;
16725
16744
  }
16726
- function serializeThrownValue(value, depth = 0, seen = /* @__PURE__ */ new WeakSet()) {
16727
- if (value instanceof Error) {
16728
- if (seen.has(value)) return "[circular]";
16729
- seen.add(value);
16730
- const transferred = {};
16731
- for (const key of Object.getOwnPropertyNames(value)) {
16732
- transferred[key] = transferNestedValue(
16733
- value[key],
16734
- depth + 1,
16735
- seen
16736
- );
16737
- }
16738
- return {
16739
- errorKind: "Error",
16740
- constructorName: value.constructor?.name,
16741
- ...transferred,
16742
- ...value.cause === void 0 ? {} : {
16743
- causeChain: depth >= 10 ? "[cause-chain-depth-limit]" : serializeThrownValue(value.cause, depth + 1, seen)
16744
- }
16745
- };
16746
- }
16747
- return value;
16748
- }
16749
16745
  function isMissingPathError5(error) {
16750
16746
  return error instanceof Error && "code" in error && error.code === "ENOENT";
16751
16747
  }
16752
- function transferNestedValue(value, depth, seen) {
16753
- if (value instanceof Error) return serializeThrownValue(value, depth, seen);
16754
- if (depth >= 10) return "[nested-depth-limit]";
16755
- if (Array.isArray(value)) {
16756
- return value.map((item) => transferNestedValue(item, depth + 1, seen));
16757
- }
16758
- if (value !== null && typeof value === "object") {
16759
- if (seen.has(value)) return "[circular]";
16760
- seen.add(value);
16761
- const transferred = {};
16762
- for (const key of Object.getOwnPropertyNames(value)) {
16763
- transferred[key] = transferNestedValue(
16764
- value[key],
16765
- depth + 1,
16766
- seen
16767
- );
16768
- }
16769
- return transferred;
16770
- }
16771
- return value;
16772
- }
16773
16748
  function jsonSafeReplacer() {
16774
16749
  const seen = /* @__PURE__ */ new WeakSet();
16775
16750
  return (_key, value) => {
@@ -17051,6 +17026,7 @@ var init_auto_resume = __esm({
17051
17026
  init_process_cancel();
17052
17027
  init_terminal();
17053
17028
  init_settlement();
17029
+ init_serialize_thrown_value();
17054
17030
  dummyIo = { stdout: () => {
17055
17031
  }, stderr: () => {
17056
17032
  } };
@@ -18072,7 +18048,8 @@ async function tryResumeSameTicketSeatRun(input) {
18072
18048
  home: input.home,
18073
18049
  bookKey: resolveBookKeyFromGit(input.projectRoot),
18074
18050
  role: input.role,
18075
- parentRunPath: input.parentRunPath
18051
+ parentRunPath: input.parentRunPath,
18052
+ ...input.ticketNumber === void 0 ? {} : { ticketNumber: input.ticketNumber }
18076
18053
  });
18077
18054
  if (previousRunId === void 0) return void 0;
18078
18055
  return await input.resume(previousRunId, input.summons);
@@ -18589,6 +18566,7 @@ async function runCountersignBody(parsed, env, io) {
18589
18566
  projectRoot: resolve13(parsed.project ?? env.cwd),
18590
18567
  role: "countersign",
18591
18568
  parentRunPath: gateParentRunPath,
18569
+ ...env.boundTicketNumber === void 0 ? {} : { ticketNumber: env.boundTicketNumber },
18592
18570
  freshSummons: env.freshSummons,
18593
18571
  summons: {
18594
18572
  sourceRunPath: gateParentRunPath,
@@ -18794,6 +18772,7 @@ async function runPublicInstructionSeat(argv, env, io, role, parseArgv2) {
18794
18772
  projectRoot,
18795
18773
  role,
18796
18774
  parentRunPath: sourceDirectory,
18775
+ ...auditorTicket === void 0 ? {} : { ticketNumber: auditorTicket },
18797
18776
  freshSummons: env.freshSummons,
18798
18777
  summons,
18799
18778
  resume: (runId, materials) => runPublicInstructionSeatResume(
@@ -18819,6 +18798,7 @@ async function runPublicInstructionSeat(argv, env, io, role, parseArgv2) {
18819
18798
  projectRoot,
18820
18799
  role,
18821
18800
  parentRunPath,
18801
+ ...env.boundTicketNumber === void 0 ? {} : { ticketNumber: env.boundTicketNumber },
18822
18802
  freshSummons: env.freshSummons,
18823
18803
  summons,
18824
18804
  resume: (runId, materials) => runPublicInstructionSeatResume(
@@ -18846,6 +18826,7 @@ async function runPublicInstructionSeat(argv, env, io, role, parseArgv2) {
18846
18826
  throw error;
18847
18827
  }
18848
18828
  const resumeInstruction = env.reviewReask ?? env.gateReviewInstruction;
18829
+ const knownTicket = await readBoardTicketNumber(source.runDirectory) ?? env.boundTicketNumber;
18849
18830
  const summons = {
18850
18831
  sourceRunPath: source.runDirectory,
18851
18832
  sourceRun: source,
@@ -18856,6 +18837,7 @@ async function runPublicInstructionSeat(argv, env, io, role, parseArgv2) {
18856
18837
  projectRoot,
18857
18838
  role,
18858
18839
  parentRunPath: source.runDirectory,
18840
+ ...knownTicket === void 0 ? {} : { ticketNumber: knownTicket },
18859
18841
  freshSummons: env.freshSummons,
18860
18842
  summons,
18861
18843
  resume: (runId, materials) => runPublicInstructionSeatResume(
@@ -28668,6 +28650,7 @@ init_packaged_role_registry();
28668
28650
  init_role_activation_flags();
28669
28651
  init_submission_correctable_error();
28670
28652
  init_navigator_invocation_identity();
28653
+ init_serialize_thrown_value();
28671
28654
  async function listen(server, path) {
28672
28655
  await new Promise((resolve22, reject) => {
28673
28656
  server.once("error", reject);
@@ -28927,7 +28910,8 @@ async function prepareRoleEnvelope(options) {
28927
28910
  ...buildNavigatorInfrastructureFailureFact(),
28928
28911
  ...extractInfrastructureFailureEvidence(error),
28929
28912
  cause: "infrastructure",
28930
- code: errorCode
28913
+ code: errorCode,
28914
+ error: serializeThrownValue(error)
28931
28915
  };
28932
28916
  rememberInfrastructureFailure(details, content);
28933
28917
  return { content, details };
@@ -21,6 +21,7 @@ import { parseAutoResumeLimit } from "./config.js";
21
21
  import { processCancelSignalName } from "./process-cancel.js";
22
22
  import { isLawfulTypedTerminalOutcome, formatTerminalResult } from "./terminal.js";
23
23
  import { attachRecordedSubmissions, presentFailureTerminal, resolveControlledFailureResumeObservation, } from "./settlement.js";
24
+ import { serializeThrownValue } from "../serialize-thrown-value.js";
24
25
  const dummyIo = { stdout: () => { }, stderr: () => { } };
25
26
  /**
26
27
  * Persist run-state after a host-turn result, outside the retried dispatch try.
@@ -122,69 +123,12 @@ export async function ensureRealArtifactsDirectory(runDirectory) {
122
123
  }
123
124
  return artifactsDir;
124
125
  }
125
- /**
126
- * Whole-object transfer of a thrown value (owner 2026-08-23: 「记录所有错误信息。
127
- * 不能丢详细情况」). Every own property of the Error object — enumerable or not,
128
- * which is how message/stack and any attached identity land verbatim — plus the
129
- * constructor name and the full cause chain. No field list is prescribed or
130
- * filtered: whatever the exception object carries goes into the file as-is.
131
- */
132
- function serializeThrownValue(value, depth = 0, seen = new WeakSet()) {
133
- if (value instanceof Error) {
134
- if (seen.has(value))
135
- return "[circular]";
136
- seen.add(value);
137
- const transferred = {};
138
- for (const key of Object.getOwnPropertyNames(value)) {
139
- transferred[key] = transferNestedValue(value[key], depth + 1, seen);
140
- }
141
- return {
142
- errorKind: "Error",
143
- constructorName: value.constructor?.name,
144
- ...transferred,
145
- ...(value.cause === undefined
146
- ? {}
147
- : {
148
- causeChain: depth >= 10
149
- ? "[cause-chain-depth-limit]"
150
- : serializeThrownValue(value.cause, depth + 1, seen),
151
- }),
152
- };
153
- }
154
- return value;
155
- }
156
126
  /** ENOENT identity shared with settlement.ts's hardened audit-artifact path. */
157
127
  function isMissingPathError(error) {
158
128
  return (error instanceof Error &&
159
129
  "code" in error &&
160
130
  error.code === "ENOENT");
161
131
  }
162
- /**
163
- * Recursive Error-property transfer (#426 review: nested Errors must not be
164
- * passed raw to JSON.stringify — their non-enumerable message/stack would
165
- * serialize as {}). Depth-limited; cycle-safe via the seen set so the recursive
166
- * construction itself cannot diverge before stringify runs.
167
- */
168
- function transferNestedValue(value, depth, seen) {
169
- if (value instanceof Error)
170
- return serializeThrownValue(value, depth, seen);
171
- if (depth >= 10)
172
- return "[nested-depth-limit]";
173
- if (Array.isArray(value)) {
174
- return value.map((item) => transferNestedValue(item, depth + 1, seen));
175
- }
176
- if (value !== null && typeof value === "object") {
177
- if (seen.has(value))
178
- return "[circular]";
179
- seen.add(value);
180
- const transferred = {};
181
- for (const key of Object.getOwnPropertyNames(value)) {
182
- transferred[key] = transferNestedValue(value[key], depth + 1, seen);
183
- }
184
- return transferred;
185
- }
186
- return value;
187
- }
188
132
  /** Cycle- and bigint-safe JSON replacer so serialization itself cannot drop data. */
189
133
  function jsonSafeReplacer() {
190
134
  const seen = new WeakSet();
@@ -258,6 +258,9 @@ async function runCountersignBody(parsed, env, io) {
258
258
  projectRoot: resolve(parsed.project ?? env.cwd),
259
259
  role: "countersign",
260
260
  parentRunPath: gateParentRunPath,
261
+ ...(env.boundTicketNumber === undefined
262
+ ? {}
263
+ : { ticketNumber: env.boundTicketNumber }),
261
264
  freshSummons: env.freshSummons,
262
265
  summons: {
263
266
  sourceRunPath: gateParentRunPath,
@@ -474,6 +477,7 @@ export async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
474
477
  projectRoot,
475
478
  role,
476
479
  parentRunPath: sourceDirectory,
480
+ ...(auditorTicket === undefined ? {} : { ticketNumber: auditorTicket }),
477
481
  freshSummons: env.freshSummons,
478
482
  summons,
479
483
  resume: (runId, materials) => runPublicInstructionSeatResume({ runId, ...(materials === undefined ? {} : { summons: materials }) }, env, io),
@@ -498,6 +502,7 @@ export async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
498
502
  projectRoot,
499
503
  role,
500
504
  parentRunPath,
505
+ ...(env.boundTicketNumber === undefined ? {} : { ticketNumber: env.boundTicketNumber }),
501
506
  freshSummons: env.freshSummons,
502
507
  summons,
503
508
  resume: (runId, materials) => runPublicInstructionSeatResume({ runId, ...(materials === undefined ? {} : { summons: materials }) }, env, io),
@@ -523,6 +528,7 @@ export async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
523
528
  throw error;
524
529
  }
525
530
  const resumeInstruction = env.reviewReask ?? env.gateReviewInstruction;
531
+ const knownTicket = (await readBoardTicketNumber(source.runDirectory)) ?? env.boundTicketNumber;
526
532
  const summons = {
527
533
  sourceRunPath: source.runDirectory,
528
534
  sourceRun: source,
@@ -533,6 +539,7 @@ export async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
533
539
  projectRoot,
534
540
  role,
535
541
  parentRunPath: source.runDirectory,
542
+ ...(knownTicket === undefined ? {} : { ticketNumber: knownTicket }),
536
543
  freshSummons: env.freshSummons,
537
544
  summons,
538
545
  resume: (runId, materials) => runPublicInstructionSeatResume({ runId, ...(materials === undefined ? {} : { summons: materials }) }, env, io),
@@ -19222,7 +19222,9 @@ async function findLatestRunIdForSeatTicket(input) {
19222
19222
  const bookDir = activationBookDirectory(ledgerHome, input.bookKey);
19223
19223
  let runDirectories;
19224
19224
  try {
19225
- runDirectories = await listBookRunDirectories(bookDir);
19225
+ runDirectories = await listBookRunDirectories(
19226
+ input.ticketNumber === void 0 ? bookDir : join14(bookDir, String(input.ticketNumber))
19227
+ );
19226
19228
  } catch (error) {
19227
19229
  if (errorCodeOf2(error) === "ENOENT") return void 0;
19228
19230
  throw error;
@@ -24377,6 +24379,17 @@ var init_known_failure = __esm({
24377
24379
  }
24378
24380
  });
24379
24381
 
24382
+ // src/serialize-thrown-value.ts
24383
+ import { inspect } from "node:util";
24384
+ function serializeThrownValue(value) {
24385
+ return inspect(value, { depth: 10, showHidden: true, customInspect: false });
24386
+ }
24387
+ var init_serialize_thrown_value = __esm({
24388
+ "src/serialize-thrown-value.ts"() {
24389
+ "use strict";
24390
+ }
24391
+ });
24392
+
24380
24393
  // src/dossier-resolution.ts
24381
24394
  var DOCTOR_CANDIDATE_ENTRY_TYPE;
24382
24395
  var init_dossier_resolution = __esm({
@@ -24784,18 +24797,23 @@ function projectThrownFailureLeaf(error) {
24784
24797
  cause: error.knownCause,
24785
24798
  diagnostic: error.message || error.name || "exception",
24786
24799
  identity,
24787
- ...error.details === void 0 ? {} : { details: error.details }
24800
+ details: {
24801
+ ...typeof error.details === "object" && error.details !== null ? error.details : error.details === void 0 ? {} : { priorDetails: error.details },
24802
+ error: serializeThrownValue(error)
24803
+ }
24788
24804
  };
24789
24805
  }
24790
24806
  if (error instanceof Error) {
24791
24807
  const identity = thrownIdentity(error);
24792
24808
  return {
24793
24809
  diagnostic: error.message || error.name || "exception",
24794
- identity
24810
+ identity,
24811
+ details: { error: serializeThrownValue(error) }
24795
24812
  };
24796
24813
  }
24797
24814
  return {
24798
- diagnostic: String(error)
24815
+ diagnostic: error !== null && typeof error === "object" ? "non-Error throw" : String(error),
24816
+ details: { error: serializeThrownValue(error) }
24799
24817
  };
24800
24818
  }
24801
24819
  function classifyThrownFailure(error) {
@@ -26518,6 +26536,7 @@ var init_settlement = __esm({
26518
26536
  init_audit_escalation();
26519
26537
  init_auditor_soul();
26520
26538
  init_known_failure();
26539
+ init_serialize_thrown_value();
26521
26540
  init_run_lifecycle();
26522
26541
  init_compliance_transport();
26523
26542
  init_collector_ledger();
@@ -26637,53 +26656,9 @@ async function ensureRealArtifactsDirectory(runDirectory) {
26637
26656
  }
26638
26657
  return artifactsDir;
26639
26658
  }
26640
- function serializeThrownValue(value, depth = 0, seen = /* @__PURE__ */ new WeakSet()) {
26641
- if (value instanceof Error) {
26642
- if (seen.has(value)) return "[circular]";
26643
- seen.add(value);
26644
- const transferred = {};
26645
- for (const key of Object.getOwnPropertyNames(value)) {
26646
- transferred[key] = transferNestedValue(
26647
- value[key],
26648
- depth + 1,
26649
- seen
26650
- );
26651
- }
26652
- return {
26653
- errorKind: "Error",
26654
- constructorName: value.constructor?.name,
26655
- ...transferred,
26656
- ...value.cause === void 0 ? {} : {
26657
- causeChain: depth >= 10 ? "[cause-chain-depth-limit]" : serializeThrownValue(value.cause, depth + 1, seen)
26658
- }
26659
- };
26660
- }
26661
- return value;
26662
- }
26663
26659
  function isMissingPathError5(error) {
26664
26660
  return error instanceof Error && "code" in error && error.code === "ENOENT";
26665
26661
  }
26666
- function transferNestedValue(value, depth, seen) {
26667
- if (value instanceof Error) return serializeThrownValue(value, depth, seen);
26668
- if (depth >= 10) return "[nested-depth-limit]";
26669
- if (Array.isArray(value)) {
26670
- return value.map((item) => transferNestedValue(item, depth + 1, seen));
26671
- }
26672
- if (value !== null && typeof value === "object") {
26673
- if (seen.has(value)) return "[circular]";
26674
- seen.add(value);
26675
- const transferred = {};
26676
- for (const key of Object.getOwnPropertyNames(value)) {
26677
- transferred[key] = transferNestedValue(
26678
- value[key],
26679
- depth + 1,
26680
- seen
26681
- );
26682
- }
26683
- return transferred;
26684
- }
26685
- return value;
26686
- }
26687
26662
  function jsonSafeReplacer() {
26688
26663
  const seen = /* @__PURE__ */ new WeakSet();
26689
26664
  return (_key, value) => {
@@ -26965,6 +26940,7 @@ var init_auto_resume = __esm({
26965
26940
  init_process_cancel();
26966
26941
  init_terminal();
26967
26942
  init_settlement();
26943
+ init_serialize_thrown_value();
26968
26944
  dummyIo = { stdout: () => {
26969
26945
  }, stderr: () => {
26970
26946
  } };
@@ -27986,7 +27962,8 @@ async function tryResumeSameTicketSeatRun(input) {
27986
27962
  home: input.home,
27987
27963
  bookKey: resolveBookKeyFromGit(input.projectRoot),
27988
27964
  role: input.role,
27989
- parentRunPath: input.parentRunPath
27965
+ parentRunPath: input.parentRunPath,
27966
+ ...input.ticketNumber === void 0 ? {} : { ticketNumber: input.ticketNumber }
27990
27967
  });
27991
27968
  if (previousRunId === void 0) return void 0;
27992
27969
  return await input.resume(previousRunId, input.summons);
@@ -29015,6 +28992,7 @@ async function runCountersignBody(parsed, env, io) {
29015
28992
  projectRoot: resolve9(parsed.project ?? env.cwd),
29016
28993
  role: "countersign",
29017
28994
  parentRunPath: gateParentRunPath,
28995
+ ...env.boundTicketNumber === void 0 ? {} : { ticketNumber: env.boundTicketNumber },
29018
28996
  freshSummons: env.freshSummons,
29019
28997
  summons: {
29020
28998
  sourceRunPath: gateParentRunPath,
@@ -29220,6 +29198,7 @@ async function runPublicInstructionSeat(argv2, env, io, role, parseArgv2) {
29220
29198
  projectRoot,
29221
29199
  role,
29222
29200
  parentRunPath: sourceDirectory,
29201
+ ...auditorTicket === void 0 ? {} : { ticketNumber: auditorTicket },
29223
29202
  freshSummons: env.freshSummons,
29224
29203
  summons,
29225
29204
  resume: (runId, materials) => runPublicInstructionSeatResume(
@@ -29245,6 +29224,7 @@ async function runPublicInstructionSeat(argv2, env, io, role, parseArgv2) {
29245
29224
  projectRoot,
29246
29225
  role,
29247
29226
  parentRunPath,
29227
+ ...env.boundTicketNumber === void 0 ? {} : { ticketNumber: env.boundTicketNumber },
29248
29228
  freshSummons: env.freshSummons,
29249
29229
  summons,
29250
29230
  resume: (runId, materials) => runPublicInstructionSeatResume(
@@ -29272,6 +29252,7 @@ async function runPublicInstructionSeat(argv2, env, io, role, parseArgv2) {
29272
29252
  throw error;
29273
29253
  }
29274
29254
  const resumeInstruction = env.reviewReask ?? env.gateReviewInstruction;
29255
+ const knownTicket = await readBoardTicketNumber(source.runDirectory) ?? env.boundTicketNumber;
29275
29256
  const summons = {
29276
29257
  sourceRunPath: source.runDirectory,
29277
29258
  sourceRun: source,
@@ -29282,6 +29263,7 @@ async function runPublicInstructionSeat(argv2, env, io, role, parseArgv2) {
29282
29263
  projectRoot,
29283
29264
  role,
29284
29265
  parentRunPath: source.runDirectory,
29266
+ ...knownTicket === void 0 ? {} : { ticketNumber: knownTicket },
29285
29267
  freshSummons: env.freshSummons,
29286
29268
  summons,
29287
29269
  resume: (runId, materials) => runPublicInstructionSeatResume(
@@ -822,7 +822,11 @@ export async function findLatestRunIdForSeatTicket(input) {
822
822
  const bookDir = activationBookDirectory(ledgerHome, input.bookKey);
823
823
  let runDirectories;
824
824
  try {
825
- runDirectories = await listBookRunDirectories(bookDir);
825
+ // A typed ticket narrows the existing walk surface to that ticket's runs;
826
+ // same-parent matching below still selects the actual prior leg.
827
+ runDirectories = await listBookRunDirectories(input.ticketNumber === undefined
828
+ ? bookDir
829
+ : join(bookDir, String(input.ticketNumber)));
826
830
  }
827
831
  catch (error) {
828
832
  if (errorCodeOf(error) === "ENOENT")
@@ -30,6 +30,9 @@ export async function tryResumeSameTicketSeatRun(input) {
30
30
  bookKey: resolveBookKeyFromGit(input.projectRoot),
31
31
  role: input.role,
32
32
  parentRunPath: input.parentRunPath,
33
+ ...(input.ticketNumber === undefined
34
+ ? {}
35
+ : { ticketNumber: input.ticketNumber }),
33
36
  });
34
37
  if (previousRunId === undefined)
35
38
  return undefined;
@@ -12,6 +12,7 @@ import { hasFreshAttemptSubmission, readAttemptScopedSubmissionRows, readRecorde
12
12
  import { isAuditEscalationResult } from "../audit-escalation.js";
13
13
  import { AUDITOR_SOUL_ROLES } from "../auditor-soul.js";
14
14
  import { knownFailureFromProviderStop } from "../pi/known-failure.js";
15
+ import { serializeThrownValue } from "../serialize-thrown-value.js";
15
16
  import { isV1ResumableProvider, readLatestTypedProviderHttpObservation, readTypedHttp429Observation, } from "./run-lifecycle.js";
16
17
  import { AUDITOR_COMPLIANCE_FAILURE_ENTRY_TYPE, AUDITOR_PARENT_ATTEMPT_BINDING_ENTRY_TYPE, COMPLIANCE_RESPONSE_ENTRY_TYPE, readComplianceCandidate, } from "../compliance-transport.js";
17
18
  // COMPLIANCE_RESPONSE_ENTRY_TYPE remains for boundRetainedAuditResponse (call/result
@@ -272,7 +273,12 @@ export function projectThrownFailureLeaf(error) {
272
273
  cause: error.knownCause,
273
274
  diagnostic: error.message || error.name || "exception",
274
275
  identity,
275
- ...(error.details === undefined ? {} : { details: error.details }),
276
+ details: {
277
+ ...(typeof error.details === "object" && error.details !== null
278
+ ? error.details
279
+ : error.details === undefined ? {} : { priorDetails: error.details }),
280
+ error: serializeThrownValue(error),
281
+ },
276
282
  };
277
283
  }
278
284
  if (error instanceof Error) {
@@ -281,10 +287,12 @@ export function projectThrownFailureLeaf(error) {
281
287
  return {
282
288
  diagnostic: error.message || error.name || "exception",
283
289
  identity,
290
+ details: { error: serializeThrownValue(error) },
284
291
  };
285
292
  }
286
293
  return {
287
- diagnostic: String(error),
294
+ diagnostic: error !== null && typeof error === "object" ? "non-Error throw" : String(error),
295
+ details: { error: serializeThrownValue(error) },
288
296
  };
289
297
  }
290
298
  /**
@@ -0,0 +1,5 @@
1
+ import { inspect } from "node:util";
2
+ /** Record the whole thrown value without invoking its getters or custom formatter. */
3
+ export function serializeThrownValue(value) {
4
+ return inspect(value, { depth: 10, showHidden: true, customInspect: false });
5
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akagilnc/pi-workflow-roles",
3
- "version": "0.1.4923",
3
+ "version": "0.1.4932",
4
4
  "description": "Soul-bound workflow roles for Pi",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -2,3 +2,4 @@
2
2
 
3
3
  提交:标题冠 ak-roles: 在最前;forward commit,严禁 amend——改错就再提交一笔,不改历史。
4
4
  交卷回执:改动清单与票面逐项对得上;验证证据附命令与结果原文。
5
+ 新造通用件:回执写明仓内、语言标准库、包生态各搜了什么、为什么不用。
@@ -2,3 +2,4 @@
2
2
 
3
3
  提交:标题冠 ak-roles: 在最前;forward commit,严禁 amend——改错就再提交一笔,不改历史。
4
4
  交卷回执:逐 finding 报处置;验证证据按仓级 CLAUDE.md 证据条款:指针(runId/toolCallId)或摘抄结论皆合格,以读者能直接核为准。
5
+ 新造通用件:回执写明仓内、语言标准库、包生态各搜了什么、为什么不用。
@@ -8,6 +8,8 @@
8
8
 
9
9
  取舍位次:过测试 → 显意图 → 无重复 → 最少元素。
10
10
 
11
+ 生态里已有的不自己造:仓内、语言标准库、包生态有现成件而另写一份,即复杂度缺陷。新造的通用件(序列化、重试、锁、diff、路径处理之类)须答得出搜了这三处各是什么、为什么不用;答不出即封驳。
12
+
11
13
  ## 先搜,再想简单的(owner 2026-09-20)
12
14
 
13
15
  > 逐字:「请你们思考实现方式的时候。多搜搜互联网,多想简单的方式,不是在那加加加,加一堆烂机制最终还要烧我的token来删!」
@@ -40,6 +40,7 @@ import {
40
40
  resolveControlledFailureResumeObservation,
41
41
  } from "./settlement.ts";
42
42
  import type { CliIo } from "./cli-io.ts";
43
+ import { serializeThrownValue } from "../serialize-thrown-value.ts";
43
44
 
44
45
  const dummyIo: CliIo = { stdout: () => {}, stderr: () => {} };
45
46
 
@@ -176,42 +177,6 @@ export async function ensureRealArtifactsDirectory(runDirectory: string): Promis
176
177
  return artifactsDir;
177
178
  }
178
179
 
179
- /**
180
- * Whole-object transfer of a thrown value (owner 2026-08-23: 「记录所有错误信息。
181
- * 不能丢详细情况」). Every own property of the Error object — enumerable or not,
182
- * which is how message/stack and any attached identity land verbatim — plus the
183
- * constructor name and the full cause chain. No field list is prescribed or
184
- * filtered: whatever the exception object carries goes into the file as-is.
185
- */
186
- function serializeThrownValue(value: unknown, depth = 0, seen = new WeakSet<object>()): unknown {
187
- if (value instanceof Error) {
188
- if (seen.has(value)) return "[circular]";
189
- seen.add(value);
190
- const transferred: Record<string, unknown> = {};
191
- for (const key of Object.getOwnPropertyNames(value)) {
192
- transferred[key] = transferNestedValue(
193
- (value as unknown as Record<string, unknown>)[key],
194
- depth + 1,
195
- seen,
196
- );
197
- }
198
- return {
199
- errorKind: "Error",
200
- constructorName: value.constructor?.name,
201
- ...transferred,
202
- ...(value.cause === undefined
203
- ? {}
204
- : {
205
- causeChain:
206
- depth >= 10
207
- ? "[cause-chain-depth-limit]"
208
- : serializeThrownValue(value.cause, depth + 1, seen),
209
- }),
210
- };
211
- }
212
- return value;
213
- }
214
-
215
180
  /** ENOENT identity shared with settlement.ts's hardened audit-artifact path. */
216
181
  function isMissingPathError(error: unknown): boolean {
217
182
  return (
@@ -221,34 +186,6 @@ function isMissingPathError(error: unknown): boolean {
221
186
  );
222
187
  }
223
188
 
224
- /**
225
- * Recursive Error-property transfer (#426 review: nested Errors must not be
226
- * passed raw to JSON.stringify — their non-enumerable message/stack would
227
- * serialize as {}). Depth-limited; cycle-safe via the seen set so the recursive
228
- * construction itself cannot diverge before stringify runs.
229
- */
230
- function transferNestedValue(value: unknown, depth: number, seen: WeakSet<object>): unknown {
231
- if (value instanceof Error) return serializeThrownValue(value, depth, seen);
232
- if (depth >= 10) return "[nested-depth-limit]";
233
- if (Array.isArray(value)) {
234
- return value.map((item) => transferNestedValue(item, depth + 1, seen));
235
- }
236
- if (value !== null && typeof value === "object") {
237
- if (seen.has(value)) return "[circular]";
238
- seen.add(value);
239
- const transferred: Record<string, unknown> = {};
240
- for (const key of Object.getOwnPropertyNames(value)) {
241
- transferred[key] = transferNestedValue(
242
- (value as unknown as Record<string, unknown>)[key],
243
- depth + 1,
244
- seen,
245
- );
246
- }
247
- return transferred;
248
- }
249
- return value;
250
- }
251
-
252
189
  /** Cycle- and bigint-safe JSON replacer so serialization itself cannot drop data. */
253
190
  function jsonSafeReplacer(): (key: string, value: unknown) => unknown {
254
191
  const seen = new WeakSet<object>();
@@ -387,6 +387,9 @@ async function runCountersignBody(
387
387
  projectRoot: resolve(parsed.project ?? env.cwd),
388
388
  role: "countersign",
389
389
  parentRunPath: gateParentRunPath,
390
+ ...(env.boundTicketNumber === undefined
391
+ ? {}
392
+ : { ticketNumber: env.boundTicketNumber }),
390
393
  freshSummons: env.freshSummons,
391
394
  summons: {
392
395
  sourceRunPath: gateParentRunPath,
@@ -616,6 +619,7 @@ export async function runPublicInstructionSeat(
616
619
  projectRoot,
617
620
  role,
618
621
  parentRunPath: sourceDirectory,
622
+ ...(auditorTicket === undefined ? {} : { ticketNumber: auditorTicket }),
619
623
  freshSummons: env.freshSummons,
620
624
  summons,
621
625
  resume: (runId, materials) => runPublicInstructionSeatResume(
@@ -644,6 +648,7 @@ export async function runPublicInstructionSeat(
644
648
  projectRoot,
645
649
  role,
646
650
  parentRunPath,
651
+ ...(env.boundTicketNumber === undefined ? {} : { ticketNumber: env.boundTicketNumber }),
647
652
  freshSummons: env.freshSummons,
648
653
  summons,
649
654
  resume: (runId, materials) => runPublicInstructionSeatResume(
@@ -672,6 +677,7 @@ export async function runPublicInstructionSeat(
672
677
  throw error;
673
678
  }
674
679
  const resumeInstruction = env.reviewReask ?? env.gateReviewInstruction;
680
+ const knownTicket = (await readBoardTicketNumber(source.runDirectory)) ?? env.boundTicketNumber;
675
681
  const summons: SameTicketSummonsMaterials = {
676
682
  sourceRunPath: source.runDirectory,
677
683
  sourceRun: source,
@@ -682,6 +688,7 @@ export async function runPublicInstructionSeat(
682
688
  projectRoot,
683
689
  role,
684
690
  parentRunPath: source.runDirectory,
691
+ ...(knownTicket === undefined ? {} : { ticketNumber: knownTicket }),
685
692
  freshSummons: env.freshSummons,
686
693
  summons,
687
694
  resume: (runId, materials) => runPublicInstructionSeatResume(
@@ -1122,6 +1122,7 @@ export async function findLatestRunIdForSeatTicket(input: {
1122
1122
  readonly bookKey: string;
1123
1123
  readonly role: RoleRunRecord["role"];
1124
1124
  readonly parentRunPath: string;
1125
+ readonly ticketNumber?: number;
1125
1126
  }): Promise<string | undefined> {
1126
1127
  if (input.parentRunPath.trim() === "") {
1127
1128
  return undefined;
@@ -1130,7 +1131,13 @@ export async function findLatestRunIdForSeatTicket(input: {
1130
1131
  const bookDir = activationBookDirectory(ledgerHome, input.bookKey);
1131
1132
  let runDirectories: string[];
1132
1133
  try {
1133
- runDirectories = await listBookRunDirectories(bookDir);
1134
+ // A typed ticket narrows the existing walk surface to that ticket's runs;
1135
+ // same-parent matching below still selects the actual prior leg.
1136
+ runDirectories = await listBookRunDirectories(
1137
+ input.ticketNumber === undefined
1138
+ ? bookDir
1139
+ : join(bookDir, String(input.ticketNumber)),
1140
+ );
1134
1141
  } catch (error) {
1135
1142
  if (errorCodeOf(error) === "ENOENT") return undefined;
1136
1143
  throw error;
@@ -30,6 +30,7 @@ export async function tryResumeSameTicketSeatRun<T>(input: {
30
30
  readonly projectRoot: string;
31
31
  readonly role: RoleRunRecord["role"];
32
32
  readonly parentRunPath: string;
33
+ readonly ticketNumber?: number;
33
34
  readonly freshSummons: true | undefined;
34
35
  readonly summons?: SameTicketSummonsMaterials;
35
36
  readonly resume: (
@@ -44,6 +45,9 @@ export async function tryResumeSameTicketSeatRun<T>(input: {
44
45
  bookKey: resolveBookKeyFromGit(input.projectRoot),
45
46
  role: input.role,
46
47
  parentRunPath: input.parentRunPath,
48
+ ...(input.ticketNumber === undefined
49
+ ? {}
50
+ : { ticketNumber: input.ticketNumber }),
47
51
  });
48
52
  if (previousRunId === undefined) return undefined;
49
53
  return await input.resume(previousRunId, input.summons);
@@ -24,6 +24,7 @@ import { isAuditEscalationResult } from "../audit-escalation.ts";
24
24
  import { AUDITOR_SOUL_ROLES } from "../auditor-soul.ts";
25
25
  import type { RoleTurnKnownFailure } from "../host-contracts.ts";
26
26
  import { knownFailureFromProviderStop } from "../pi/known-failure.ts";
27
+ import { serializeThrownValue } from "../serialize-thrown-value.ts";
27
28
  import {
28
29
  isV1ResumableProvider,
29
30
  readLatestTypedProviderHttpObservation,
@@ -520,7 +521,12 @@ export function projectThrownFailureLeaf(error: unknown): ControlledFailure {
520
521
  cause: error.knownCause,
521
522
  diagnostic: error.message || error.name || "exception",
522
523
  identity,
523
- ...(error.details === undefined ? {} : { details: error.details }),
524
+ details: {
525
+ ...(typeof error.details === "object" && error.details !== null
526
+ ? error.details as Record<string, unknown>
527
+ : error.details === undefined ? {} : { priorDetails: error.details }),
528
+ error: serializeThrownValue(error),
529
+ },
524
530
  };
525
531
  }
526
532
  if (error instanceof Error) {
@@ -529,10 +535,12 @@ export function projectThrownFailureLeaf(error: unknown): ControlledFailure {
529
535
  return {
530
536
  diagnostic: error.message || error.name || "exception",
531
537
  identity,
538
+ details: { error: serializeThrownValue(error) },
532
539
  };
533
540
  }
534
541
  return {
535
- diagnostic: String(error),
542
+ diagnostic: error !== null && typeof error === "object" ? "non-Error throw" : String(error),
543
+ details: { error: serializeThrownValue(error) },
536
544
  };
537
545
  }
538
546
 
@@ -38,6 +38,7 @@ import {
38
38
  buildNavigatorInfrastructureFailureFact,
39
39
  extractInfrastructureFailureEvidence,
40
40
  } from "./navigator-invocation-identity.ts";
41
+ import { serializeThrownValue } from "./serialize-thrown-value.ts";
41
42
 
42
43
  export { projectActivationFlags };
43
44
 
@@ -381,6 +382,7 @@ export async function prepareRoleEnvelope(options: {
381
382
  ...extractInfrastructureFailureEvidence(error),
382
383
  cause: "infrastructure",
383
384
  code: errorCode,
385
+ error: serializeThrownValue(error),
384
386
  };
385
387
  rememberInfrastructureFailure(details, content);
386
388
  return { content, details };
@@ -0,0 +1,6 @@
1
+ import { inspect } from "node:util";
2
+
3
+ /** Record the whole thrown value without invoking its getters or custom formatter. */
4
+ export function serializeThrownValue(value: unknown): string {
5
+ return inspect(value, { depth: 10, showHidden: true, customInspect: false });
6
+ }