@akagilnc/pi-workflow-roles 0.1.5406 → 0.1.5475

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 (93) hide show
  1. package/CLAUDE.md +1 -1
  2. package/README.md +42 -55
  3. package/README.zh-CN.md +59 -73
  4. package/THIRD_PARTY_NOTICES.md +4 -7
  5. package/dist/acp-host/production-host.js +8261 -9073
  6. package/dist/collector-tool-schemas.js +1 -1
  7. package/dist/compliance-transport.js +2 -5
  8. package/dist/engine-detour-usage.js +3 -30
  9. package/dist/gatekeeper-role.js +4 -18
  10. package/dist/headless-host/description.js +0 -209
  11. package/dist/headless-host/production-host.js +6973 -8035
  12. package/dist/host-contracts.js +8 -0
  13. package/dist/migrate-book-topology.js +30 -27
  14. package/dist/packaged-role-registry.js +1 -9
  15. package/dist/pi/role-turn-host.js +37 -19
  16. package/dist/public-cli/auto-resume.js +29 -66
  17. package/dist/public-cli/countersign-run.js +4 -18
  18. package/dist/public-cli/instruction-seat-run.js +59 -76
  19. package/dist/public-cli/main.js +9844 -10720
  20. package/dist/public-cli/option-definitions.js +1 -1
  21. package/dist/public-cli/post-admission.js +204 -285
  22. package/dist/public-cli/process-cancel.js +8 -0
  23. package/dist/public-cli/run-lifecycle.js +24 -94
  24. package/dist/public-cli/settlement.js +614 -1524
  25. package/dist/public-cli/terminal.js +23 -53
  26. package/dist/public-role-summons.js +3 -8
  27. package/dist/receipt-delivery-policy.js +11 -12
  28. package/dist/run-terminal-artifacts.js +19 -14
  29. package/dist/serialize-thrown-value.js +7 -1
  30. package/dist/submission-ledger.js +21 -89
  31. package/package.json +1 -1
  32. package/packets/fixer-repair.md +3 -1
  33. package/packets/judge-apply.md +7 -16
  34. package/packets/judge-authority.md +7 -17
  35. package/packets/judge-plan.md +7 -18
  36. package/packets/judge-review.md +8 -22
  37. package/packets/judge-submission.md +4 -7
  38. package/resources/collector-bot-handbook.md +2 -2
  39. package/resources/diarist-collect.md +2 -2
  40. package/resources/engine-dispatch.md +2 -2
  41. package/resources/navigator-route-playbook.md +1 -1
  42. package/resources/secretariat-ticket-identity.md +1 -1
  43. package/scripts/build-package.mjs +0 -2
  44. package/souls/coder-output-guide.md +3 -3
  45. package/souls/coder.md +2 -3
  46. package/souls/doctor-auditor.md +0 -3
  47. package/souls/fixer-auditor.md +0 -2
  48. package/souls/fixer-output-guide.md +3 -3
  49. package/souls/fixer.md +2 -2
  50. package/souls/gate-output-guide.md +1 -1
  51. package/souls/quality-law.md +2 -0
  52. package/src/acp-host/role-turn-host.ts +168 -75
  53. package/src/collector-tool-schemas.ts +1 -1
  54. package/src/compliance-transport.ts +3 -6
  55. package/src/engine-detour-usage.ts +3 -33
  56. package/src/external-host-turn-loop.ts +81 -36
  57. package/src/gatekeeper-role.ts +5 -20
  58. package/src/headless-host/description.ts +4 -214
  59. package/src/headless-host/production-host.ts +2 -1
  60. package/src/headless-host/role-turn-host.ts +153 -186
  61. package/src/host-contracts.ts +13 -10
  62. package/src/navigator-public-session.ts +1 -1
  63. package/src/navigator-session-contracts.ts +1 -1
  64. package/src/package-contracts/gatekeeper-output.ts +1 -1
  65. package/src/package-contracts/navigator-output.ts +1 -1
  66. package/src/package-contracts/terminating-infrastructure.ts +1 -1
  67. package/src/packaged-role-registry.ts +2 -10
  68. package/src/pi/adapter.ts +0 -3
  69. package/src/pi/role-turn-host.ts +42 -28
  70. package/src/prepared-role-turn.ts +2 -0
  71. package/src/public-cli/auto-resume.ts +27 -66
  72. package/src/public-cli/countersign-run.ts +4 -22
  73. package/src/public-cli/instruction-seat-run.ts +79 -80
  74. package/src/public-cli/option-definitions.ts +1 -1
  75. package/src/public-cli/post-admission.ts +264 -340
  76. package/src/public-cli/process-cancel.ts +9 -0
  77. package/src/public-cli/run-lifecycle.ts +25 -126
  78. package/src/public-cli/settlement.ts +792 -1912
  79. package/src/public-cli/terminal.ts +29 -69
  80. package/src/public-role-summons.ts +3 -8
  81. package/src/receipt-delivery-policy.ts +11 -12
  82. package/src/role-envelope.ts +16 -9
  83. package/src/role-runtime.ts +14 -81
  84. package/src/run-terminal-artifacts.ts +21 -17
  85. package/src/serialize-thrown-value.ts +7 -1
  86. package/src/submission-ledger.ts +30 -116
  87. package/dist/audit-escalation.js +0 -7
  88. package/dist/pi/known-failure.js +0 -51
  89. package/dist/typed-provider-http.js +0 -57
  90. package/dist/upstream-error-testimony.js +0 -19
  91. package/src/pi/known-failure.ts +0 -76
  92. package/src/typed-provider-http.ts +0 -89
  93. package/src/upstream-error-testimony.ts +0 -45
@@ -55,3 +55,11 @@ export function processCancelSignalName(signal) {
55
55
  export function processCancelDiagnostic(signalName) {
56
56
  return `ak-role terminated by ${signalName}`;
57
57
  }
58
+ /**
59
+ * Diagnostic line for a child the host lost to a signal. The child reported
60
+ * code=null, which is a non-normal exit and never a successful run
61
+ * (ADR 0052: 真失败退非零).
62
+ */
63
+ export function childSignalDeathDiagnostic(signal) {
64
+ return `role run was killed by ${signal}`;
65
+ }
@@ -11,18 +11,12 @@ import { activationBookDirectory, resolveActivationLedgerHome, } from "../activa
11
11
  import { listBookRunDirectories } from "../role-run-placement.js";
12
12
  import { isSafePositiveTicketNumber } from "../run-ticket-number.js";
13
13
  import { CliUsageError } from "./cli-errors.js";
14
- import { readLatestTypedProviderHttpObservation, } from "../typed-provider-http.js";
15
- export { clearTypedProviderHttpObservation, recordTypedProviderHttpStatus, readLatestTypedProviderHttpObservation, } from "../typed-provider-http.js";
16
14
  import { parseCollectorRepository } from "../collector-config.js";
17
15
  import { rewriteAdmittedRoleRunPage, rewriteRunDirectoryPathValue, } from "../role-run-relocation.js";
18
16
  import { appendEngineSessionMaterial, engineSessionMaterialFromOptions, pickEngineAxis, } from "../package-resources/engine-material.js";
19
17
  import { packagedResumeSourcePath, packagedRoleMetadata, } from "../packaged-role-registry.js";
20
18
  import { admittedReviewerBaseFault, recordEffectiveInvocationModel, requireAuthorityRef, isReviewerLens, } from "./invocation.js";
21
19
  import { isRecord, errorText, isEnoent } from "../unknown-value.js";
22
- /** Providers eligible for v1 typed-429 resume (Codex / xAI only).
23
- * @deprecated v1 429-only gate removed by #416 (owner 2026-08-22: "根本不要有限制"). Kept for compatibility; do not use for new branching.
24
- */
25
- export const V1_RESUMABLE_PROVIDERS = ["openai-codex", "xai"];
26
20
  /** Default for the #422 configurable single-call auto-resume ceiling
27
21
  * (public-cli.json top-level `autoResumeLimit`). No longer the runtime truth
28
22
  * source: runWithAutoResumeLoop receives the effective value once per call.
@@ -49,25 +43,6 @@ export function buildAutoResumeContinuationPrompt(options) {
49
43
  }
50
44
  const RUN_STATE_FILE = "run-state.json";
51
45
  const WRITER_LOCK_FILE = "writer.lock";
52
- /** @deprecated #416: 429-only classification removed; kept for compatibility. */
53
- export function isV1ResumableProvider(provider) {
54
- return V1_RESUMABLE_PROVIDERS.includes(provider);
55
- }
56
- /** @deprecated #416: 429-only observation no longer gates resume; kept for historical runs. */
57
- export async function readTypedHttp429Observation(runDirectory) {
58
- const observation = await readLatestTypedProviderHttpObservation(runDirectory);
59
- if (observation === undefined)
60
- return undefined;
61
- if (observation.httpStatus !== 429)
62
- return undefined;
63
- if (!isV1ResumableProvider(observation.provider))
64
- return undefined;
65
- return { httpStatus: 429, provider: observation.provider };
66
- }
67
- /** Complete public resume command. Run ID is revealed only through this command text. */
68
- export function renderResumeCommand(runId) {
69
- return `ak-role resume ${runId}`;
70
- }
71
46
  export async function writeRoleRunState(runDirectory, record) {
72
47
  const payload = { ...record, runDirectory };
73
48
  await writeFile(join(runDirectory, RUN_STATE_FILE), `${JSON.stringify(payload, null, 2)}\n`, "utf8");
@@ -140,7 +115,7 @@ async function readRoleRunStateRaw(runDirectory) {
140
115
  // failure (EISDIR, EACCES, ...) or a JSON.parse SyntaxError on a present
141
116
  // file is genuine infrastructure/data damage and must keep its own
142
117
  // identity — callers route it through the controlled-failure seam
143
- // (markRunRunning/markRunResumable/markRunTerminal/recordCurrentCourt)
118
+ // (markRunRunning/markRunTerminal/recordCurrentCourt)
144
119
  // instead of it being relabeled "run state missing" (#836).
145
120
  if (errorCodeOf(error) === "ENOENT")
146
121
  return undefined;
@@ -199,17 +174,6 @@ async function readRoleRunStateDisk(runDirectory) {
199
174
  ? { sessionFile: rewriteRunDirectoryPathValue(record.sessionFile, storedRunDirectory, runDirectory) }
200
175
  : {}),
201
176
  };
202
- let resumable;
203
- if (record.resumable !== undefined && record.resumable !== null) {
204
- if (isRecord(record.resumable)) {
205
- const r = record.resumable;
206
- if (r.httpStatus === 429 &&
207
- typeof r.provider === "string" &&
208
- isV1ResumableProvider(r.provider)) {
209
- resumable = { httpStatus: 429, provider: r.provider };
210
- }
211
- }
212
- }
213
177
  const phase = record.phase === "plan" || record.phase === "apply"
214
178
  ? record.phase
215
179
  : undefined;
@@ -224,7 +188,6 @@ async function readRoleRunStateDisk(runDirectory) {
224
188
  admittedRequestPath: rewriteRunDirectoryPathValue(record.admittedRequestPath, storedRunDirectory, runDirectory),
225
189
  principalWire,
226
190
  ...(phase === undefined ? {} : { phase }),
227
- ...(resumable === undefined ? {} : { resumable }),
228
191
  ...(currentCourt === undefined ? {} : { currentCourt }),
229
192
  };
230
193
  }
@@ -242,7 +205,6 @@ async function writeRoleRunStateDisk(runDirectory, disk) {
242
205
  : { sessionFile: disk.principalWire.sessionFile }),
243
206
  admittedRequestPath: disk.admittedRequestPath,
244
207
  ...(disk.phase === undefined ? {} : { phase: disk.phase }),
245
- ...(disk.resumable === undefined ? {} : { resumable: disk.resumable }),
246
208
  ...(disk.currentCourt === undefined ? {} : { currentCourt: disk.currentCourt }),
247
209
  };
248
210
  await writeFile(join(runDirectory, RUN_STATE_FILE), `${JSON.stringify(payload, null, 2)}\n`, "utf8");
@@ -264,7 +226,6 @@ function materializeRoleRunFromDisk(disk, authority) {
264
226
  runDirectory: disk.runDirectory,
265
227
  admittedRequestPath: disk.admittedRequestPath,
266
228
  ...(disk.phase === undefined ? {} : { phase: disk.phase }),
267
- ...(disk.resumable === undefined ? {} : { resumable: disk.resumable }),
268
229
  },
269
230
  };
270
231
  }
@@ -328,20 +289,10 @@ export async function markRunRunning(runDirectory, effectiveModel, effectiveEngi
328
289
  if (current === undefined) {
329
290
  throw new Error("cannot mark running: run state missing");
330
291
  }
331
- // Omit resumable while a writer is active. Principal wire is passed through uninterpreted.
292
+ // Principal wire is passed through uninterpreted.
332
293
  // Preserve open currentCourt across running transitions (#637).
333
- await writeRoleRunStateDisk(runDirectory, {
334
- runId: current.runId,
335
- role: current.role,
336
- state: "running",
337
- bookKey: current.bookKey,
338
- projectRoot: current.projectRoot,
339
- runDirectory: current.runDirectory,
340
- admittedRequestPath: current.admittedRequestPath,
341
- principalWire: current.principalWire,
342
- ...(current.phase === undefined ? {} : { phase: current.phase }),
343
- ...(current.currentCourt === undefined ? {} : { currentCourt: current.currentCourt }),
344
- });
294
+ // A historical resumable payload on disk is not copied: the parser never kept it.
295
+ await writeRoleRunStateDisk(runDirectory, { ...current, state: "running" });
345
296
  await recordEffectiveInvocationModel(runDirectory, effectiveModel,
346
297
  // Authoritative seat projection: absent engine ⇒ null (delete).
347
298
  effectiveEngine === undefined ? null : effectiveEngine, effectiveHost,
@@ -352,36 +303,13 @@ export async function markRunRunning(runDirectory, effectiveModel, effectiveEngi
352
303
  ? null
353
304
  : effectiveEngineModel);
354
305
  }
355
- /** @deprecated #416: 429-only resumable marker; kept for historical runs. */
356
- export async function markRunResumable(runDirectory, observation) {
357
- const current = await readRoleRunStateDisk(runDirectory);
358
- if (current === undefined) {
359
- throw new Error("cannot mark resumable: run state missing");
360
- }
361
- await writeRoleRunStateDisk(runDirectory, {
362
- ...current,
363
- state: "resumable",
364
- resumable: observation,
365
- });
366
- }
367
306
  export async function markRunTerminal(runDirectory) {
368
307
  const current = await readRoleRunStateDisk(runDirectory);
369
308
  if (current === undefined) {
370
309
  throw new Error("cannot mark terminal: run state missing");
371
310
  }
372
311
  // Preserve the open court's settlement identity after a failed/incomplete turn (#637).
373
- await writeRoleRunStateDisk(runDirectory, {
374
- runId: current.runId,
375
- role: current.role,
376
- state: "terminal",
377
- bookKey: current.bookKey,
378
- projectRoot: current.projectRoot,
379
- runDirectory: current.runDirectory,
380
- admittedRequestPath: current.admittedRequestPath,
381
- principalWire: current.principalWire,
382
- ...(current.phase === undefined ? {} : { phase: current.phase }),
383
- ...(current.currentCourt === undefined ? {} : { currentCourt: current.currentCourt }),
384
- });
312
+ await writeRoleRunStateDisk(runDirectory, { ...current, state: "terminal" });
385
313
  }
386
314
  /** Read the open court turn on a retained run, if any (#637). */
387
315
  export async function readCurrentCourt(runDirectory) {
@@ -413,26 +341,30 @@ export async function clearCurrentCourt(runDirectory, expectedCourtAttemptId) {
413
341
  current.currentCourt.courtAttemptId !== expectedCourtAttemptId) {
414
342
  return;
415
343
  }
416
- await writeRoleRunStateDisk(runDirectory, {
417
- runId: current.runId,
418
- role: current.role,
419
- state: current.state,
420
- bookKey: current.bookKey,
421
- projectRoot: current.projectRoot,
422
- runDirectory: current.runDirectory,
423
- admittedRequestPath: current.admittedRequestPath,
424
- principalWire: current.principalWire,
425
- ...(current.phase === undefined ? {} : { phase: current.phase }),
426
- ...(current.resumable === undefined ? {} : { resumable: current.resumable }),
427
- });
344
+ const { currentCourt: _currentCourt, ...rest } = current;
345
+ await writeRoleRunStateDisk(runDirectory, rest);
428
346
  }
429
347
  export class RunWriterLeaseHeldError extends Error {
430
348
  code = "AK_RUN_WRITER_LEASE_HELD";
431
- constructor(message = "role run writer lease is already held") {
349
+ /**
350
+ * Why the lease could not be taken, as structured data: the OS errno of the
351
+ * underlying reclaim failure when there was one. Carried so a consumer
352
+ * asserts the real cause instead of recognising it in the message text
353
+ * (质量法: 机器只咬契约,不咬呈现).
354
+ */
355
+ causeCode;
356
+ constructor(message = "role run writer lease is already held", causeCode) {
432
357
  super(message);
433
358
  this.name = "RunWriterLeaseHeldError";
359
+ if (causeCode !== undefined)
360
+ this.causeCode = causeCode;
434
361
  }
435
362
  }
363
+ /** The OS errno of a thrown value, when it carries one. */
364
+ function errnoOf(error) {
365
+ const code = error?.code;
366
+ return typeof code === "string" || typeof code === "number" ? code : undefined;
367
+ }
436
368
  /**
437
369
  * True error identity for diagnostics — name/code/message as-is, never a
438
370
  * guessed label (failure-honesty constitution).
@@ -681,7 +613,7 @@ export async function acquireRunWriterLease(runDirectory, onCleanupFailure) {
681
613
  }
682
614
  }
683
615
  catch (reclaimError) {
684
- throw new RunWriterLeaseHeldError(`stale writer lease reclaim failed at ${lockPath} (autopsy: ${describeAutopsy(lastAutopsy)}): ${describeErrorIdentity(reclaimError)}`);
616
+ throw new RunWriterLeaseHeldError(`stale writer lease reclaim failed at ${lockPath} (autopsy: ${describeAutopsy(lastAutopsy)}): ${describeErrorIdentity(reclaimError)}`, errnoOf(reclaimError));
685
617
  }
686
618
  if (reclaimed) {
687
619
  reportDiagnostic(`stale writer lease reclaimed at ${lockPath} (holder pid ${lastAutopsy.pid} verified dead): the killed holder may have left an orphaned pi child still writing this run — check for a surviving pi process on this run before continuing`, "stale-reclaimed");
@@ -689,7 +621,7 @@ export async function acquireRunWriterLease(runDirectory, onCleanupFailure) {
689
621
  }
690
622
  throw new RunWriterLeaseHeldError(lastReclaimFailure !== undefined
691
623
  ? `role run writer lease stayed contested at ${lockPath} after ${WRITER_LEASE_RECLAIM_ROUNDS} reclaims (last autopsy: ${describeAutopsy(lastAutopsy)}; last reclaim failure: ${describeErrorIdentity(lastReclaimFailure)})`
692
- : `role run writer lease stayed contested at ${lockPath} after ${WRITER_LEASE_RECLAIM_ROUNDS} reclaims (last autopsy: ${describeAutopsy(lastAutopsy)})`);
624
+ : `role run writer lease stayed contested at ${lockPath} after ${WRITER_LEASE_RECLAIM_ROUNDS} reclaims (last autopsy: ${describeAutopsy(lastAutopsy)})`, lastReclaimFailure === undefined ? undefined : errnoOf(lastReclaimFailure));
693
625
  }
694
626
  /**
695
627
  * Locate a Role run directory by run ID under the ledger books home.
@@ -1096,7 +1028,6 @@ async function loadResumableRunRecord(home, runId, authority) {
1096
1028
  return {
1097
1029
  run,
1098
1030
  principal,
1099
- ...(run.resumable === undefined ? {} : { observation: run.resumable }),
1100
1031
  admittedFields: {
1101
1032
  instruction,
1102
1033
  instructionEmpty,
@@ -1152,7 +1083,6 @@ function seatLoadedResult(loaded, admitted) {
1152
1083
  return {
1153
1084
  admitted,
1154
1085
  run: loaded.run,
1155
- ...(loaded.observation === undefined ? {} : { observation: loaded.observation }),
1156
1086
  };
1157
1087
  }
1158
1088
  export async function peekRoleRunRole(home, runId) {