@akagilnc/pi-workflow-roles 0.1.3932 → 0.1.3975

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 (162) hide show
  1. package/CLAUDE.md +1 -1
  2. package/dist/acp-host/production-host.js +2389 -6018
  3. package/dist/analyst-gate-cycles-read.js +15 -19
  4. package/dist/audit-escalation.js +16 -46
  5. package/dist/auditor-dossier-tool.js +7 -62
  6. package/dist/collector-identity.js +0 -157
  7. package/dist/collector-ledger.js +2 -42
  8. package/dist/compliance-transport.js +40 -14
  9. package/dist/diarist-contracts.js +2 -40
  10. package/dist/doctor-contracts.js +39 -108
  11. package/dist/doctor-evidence.js +1 -5
  12. package/dist/engine-detour-tool.js +1 -1
  13. package/dist/gatekeeper-role.js +49 -38
  14. package/dist/headless-host/production-host.js +4814 -8450
  15. package/dist/host-contracts.js +0 -5
  16. package/dist/merger-contracts.js +4 -6
  17. package/dist/navigator-attendance.js +30 -52
  18. package/dist/navigator-invocation-identity.js +0 -1
  19. package/dist/navigator-public-session.js +2 -1
  20. package/dist/notary-contracts.js +4 -10
  21. package/dist/package-contracts/auditor-output.js +5 -23
  22. package/dist/package-contracts/fixer-output.js +25 -49
  23. package/dist/package-contracts/gatekeeper-output.js +3 -13
  24. package/dist/package-contracts/navigator-output.js +4 -7
  25. package/dist/package-contracts/reviewer-output.js +1 -95
  26. package/dist/package-contracts/terminating-tools.js +33 -144
  27. package/dist/package-contracts/worker-output.js +1 -3
  28. package/dist/public-cli/auto-resume.js +30 -68
  29. package/dist/public-cli/case-dossier-delivery.js +5 -17
  30. package/dist/public-cli/diarist-run.js +9 -4
  31. package/dist/public-cli/inspector-run.js +2 -8
  32. package/dist/public-cli/instruction-seat-run.js +3 -7
  33. package/dist/public-cli/invocation.js +5 -2
  34. package/dist/public-cli/main.js +6068 -6964
  35. package/dist/public-cli/notary-run.js +1 -8
  36. package/dist/public-cli/post-admission.js +314 -113
  37. package/dist/public-cli/run-lifecycle.js +14 -38
  38. package/dist/public-cli/settlement.js +209 -390
  39. package/dist/public-cli/terminal.js +51 -45
  40. package/dist/public-role-summons.js +1 -12
  41. package/dist/reviewer-dispatch.js +12 -258
  42. package/dist/submission-correctable-error.js +0 -12
  43. package/dist/submission-errors.js +6 -1
  44. package/dist/submission-ledger.js +125 -168
  45. package/dist/ticket-provenance-contracts.js +2 -49
  46. package/dist/ticket-provenance.js +82 -31
  47. package/extensions/role-runtime.ts +1 -6
  48. package/package.json +1 -1
  49. package/resources/836-deleted-machine-instruction-inventory.md +18 -0
  50. package/src/acp-host/role-turn-host.ts +8 -3
  51. package/src/analyst-gate-cycles-read.ts +17 -29
  52. package/src/audit-escalation.ts +20 -50
  53. package/src/auditor-dossier-tool.ts +5 -103
  54. package/src/canonical-skill-binding.ts +3 -2
  55. package/src/collector-identity.ts +0 -179
  56. package/src/collector-ledger.ts +3 -46
  57. package/src/collector-role.ts +32 -61
  58. package/src/collector-tool-schemas.ts +20 -14
  59. package/src/compliance-transport.ts +55 -17
  60. package/src/countersign-role.ts +17 -8
  61. package/src/diarist-contracts.ts +3 -36
  62. package/src/diarist-role.ts +13 -7
  63. package/src/diarist.ts +4 -16
  64. package/src/doctor-contracts.ts +73 -94
  65. package/src/doctor-evidence.ts +1 -1
  66. package/src/doctor-role.ts +3 -3
  67. package/src/engine-detour-tool.ts +4 -1
  68. package/src/external-host-turn-loop.ts +9 -3
  69. package/src/gatekeeper-pass-envelope.ts +7 -12
  70. package/src/gatekeeper-role.ts +56 -50
  71. package/src/gleaner-left-role.ts +4 -2
  72. package/src/headless-host/role-turn-host.ts +4 -5
  73. package/src/host-contracts.ts +3 -8
  74. package/src/judge-role.ts +19 -13
  75. package/src/merger-contracts.ts +10 -6
  76. package/src/merger-role.ts +1 -5
  77. package/src/navigator-attendance.ts +37 -74
  78. package/src/navigator-invocation-identity.ts +0 -6
  79. package/src/navigator-public-session.ts +2 -1
  80. package/src/notary-contracts.ts +7 -10
  81. package/src/package-contracts/auditor-output.ts +4 -21
  82. package/src/package-contracts/fixer-output.ts +34 -52
  83. package/src/package-contracts/gatekeeper-output.ts +5 -22
  84. package/src/package-contracts/navigator-output.ts +7 -7
  85. package/src/package-contracts/reviewer-output.ts +2 -150
  86. package/src/package-contracts/terminating-tools.ts +32 -147
  87. package/src/package-contracts/worker-output.ts +0 -1
  88. package/src/pi/adapter.ts +3 -8
  89. package/src/public-cli/auto-resume.ts +41 -94
  90. package/src/public-cli/case-dossier-delivery.ts +5 -15
  91. package/src/public-cli/countersign-run.ts +14 -6
  92. package/src/public-cli/diarist-run.ts +11 -9
  93. package/src/public-cli/inspector-run.ts +2 -18
  94. package/src/public-cli/instruction-seat-run.ts +3 -17
  95. package/src/public-cli/invocation.ts +5 -2
  96. package/src/public-cli/merger-run.ts +1 -1
  97. package/src/public-cli/notary-run.ts +1 -18
  98. package/src/public-cli/post-admission.ts +385 -115
  99. package/src/public-cli/run-lifecycle.ts +13 -44
  100. package/src/public-cli/settlement.ts +314 -562
  101. package/src/public-cli/terminal.ts +66 -72
  102. package/src/public-role-summons.ts +5 -30
  103. package/src/reviewer-dispatch.ts +29 -331
  104. package/src/reviewer-role.ts +16 -83
  105. package/src/role-envelope.ts +16 -24
  106. package/src/role-runtime-dependencies.ts +1 -6
  107. package/src/role-runtime.ts +65 -201
  108. package/src/submission-correctable-error.ts +0 -14
  109. package/src/submission-errors.ts +6 -1
  110. package/src/submission-ledger.ts +187 -187
  111. package/src/ticket-provenance-contracts.ts +4 -60
  112. package/src/ticket-provenance.ts +98 -32
  113. package/src/worker-role.ts +35 -36
  114. package/dist/activation-ledger-session.js +0 -105
  115. package/dist/activation-ledger.js +0 -139
  116. package/dist/activation-trace.js +0 -33
  117. package/dist/atomic-write.js +0 -23
  118. package/dist/auditor-role.js +0 -12
  119. package/dist/canonical-skill-binding.js +0 -61
  120. package/dist/collector-handbook.js +0 -142
  121. package/dist/collector-receipt.js +0 -107
  122. package/dist/collector-role.js +0 -566
  123. package/dist/collector-tool-schemas.js +0 -107
  124. package/dist/countersign-role.js +0 -28
  125. package/dist/diarist-role.js +0 -44
  126. package/dist/diarist.js +0 -66
  127. package/dist/doctor-role.js +0 -75
  128. package/dist/fixer-bash-seatbelt.js +0 -13
  129. package/dist/gatekeeper-pass-envelope.js +0 -77
  130. package/dist/gleaner-left-role.js +0 -26
  131. package/dist/inspector-role.js +0 -29
  132. package/dist/judge-role.js +0 -104
  133. package/dist/merger-role.js +0 -55
  134. package/dist/navigator-role.js +0 -12
  135. package/dist/notary-role.js +0 -134
  136. package/dist/oauth-keepalive.js +0 -158
  137. package/dist/pi/adapter.js +0 -223
  138. package/dist/reviewer-agent.js +0 -122
  139. package/dist/reviewer-child-executor.js +0 -194
  140. package/dist/reviewer-construction.js +0 -103
  141. package/dist/reviewer-execution-ledger.js +0 -166
  142. package/dist/reviewer-failure-diagnostic.js +0 -17
  143. package/dist/reviewer-role.js +0 -159
  144. package/dist/reviewer-scope-prompt.js +0 -21
  145. package/dist/reviewer-settlement.js +0 -66
  146. package/dist/reviewer-workspace.js +0 -132
  147. package/dist/role-runtime.js +0 -1604
  148. package/dist/stderr-jsonl.js +0 -26
  149. package/dist/tool-execution-observation.js +0 -141
  150. package/dist/worker-role.js +0 -345
  151. package/dist/worker-submission-gates.js +0 -305
  152. package/src/collector-receipt.ts +0 -140
  153. package/src/diagnostic-tail.ts +0 -18
  154. package/src/reviewer-agent.ts +0 -135
  155. package/src/reviewer-child-executor.ts +0 -252
  156. package/src/reviewer-construction.ts +0 -195
  157. package/src/reviewer-execution-ledger.ts +0 -212
  158. package/src/reviewer-failure-diagnostic.ts +0 -18
  159. package/src/reviewer-scope-prompt.ts +0 -24
  160. package/src/reviewer-settlement.ts +0 -74
  161. package/src/reviewer-workspace.ts +0 -105
  162. package/src/shape-unreadable-failure.ts +0 -49
@@ -6,64 +6,45 @@ const DOCTOR_EVIDENCE_TOOL_NAME = "ak_doctor_evidence";
6
6
  const DOCTOR_OUTPUT_TOOL_NAME = "ak_doctor_output";
7
7
  const DOCTOR_ACCEPTED_TEXT = "\u592A\u533B\u7F72\u56DE\u6267\u5DF2\u63A5\u53D7";
8
8
  const DOCTOR_ACCEPTED_AUDIT_NO_RECEIPT_TEXT = "\u592A\u533B\u7F72\u56DE\u6267\u5DF2\u63A5\u53D7\uFF1B\u5BA1\u8BA1\u65E0\u56DE\u6267";
9
- const DOCTOR_OUTPUT_TOOL_DESCRIPTION = "\u63D0\u4EA4\u552F\u4E00\u7EC8\u5C40\u5355\u6848\u8BC1\u8BCD\uFF1Bcompleted \u5141\u8BB8\u7A7A findings\uFF1Bruntime \u8865\u8BB0\u6D3E\u751F\u6210\u672C\u5165\u56DE\u6267\u3002";
9
+ const DOCTOR_OUTPUT_TOOL_DESCRIPTION = "\u63D0\u4EA4\u552F\u4E00\u7EC8\u5C40\u5355\u6848\u8BC1\u8BCD\uFF1Bcompleted \u5141\u8BB8\u7A7A findings\u3002";
10
10
  const DOCTOR_TARGET_KINDS = ["law", "gate", "template", "station", "seat"];
11
- const nonblank = Type.String({ minLength: 1, pattern: "\\S" });
12
- const count = Type.Object({ count: Type.Integer({ minimum: 0 }), sources: Type.Array(nonblank) }, { additionalProperties: false });
13
- const evidenceIds = Type.Array(nonblank, { minItems: 1 });
14
- const guardrail = Type.Object({ answer: Type.Boolean(), evidenceIds, explanation: nonblank }, { additionalProperties: false });
11
+ const nonblank = Type.Optional(Type.String());
12
+ const evidenceIds = Type.Optional(Type.Array(Type.String()));
13
+ const guardrail = Type.Object({ answer: Type.Optional(Type.Boolean()), evidenceIds, explanation: nonblank }, { additionalProperties: true });
15
14
  const lastRealBite = Type.Union([
16
- Type.Object({ kind: Type.Literal("actual"), targetKey: nonblank, evidenceId: nonblank }, { additionalProperties: false }),
17
- Type.Object({ kind: Type.Literal("noRealBite"), targetKey: nonblank, eligibleEvidenceIds: evidenceIds }, { additionalProperties: false })
15
+ Type.Object({ kind: Type.Optional(Type.Literal("actual")), targetKey: nonblank, evidenceId: nonblank }, { additionalProperties: true }),
16
+ Type.Object({ kind: Type.Optional(Type.Literal("noRealBite")), targetKey: nonblank, eligibleEvidenceIds: evidenceIds }, { additionalProperties: true })
18
17
  ]);
19
18
  const assetKinds = DOCTOR_TARGET_KINDS;
20
19
  const findingBody = {
21
20
  evidenceIds,
22
- disposition: Type.Union([Type.Literal("keep"), Type.Literal("thin"), Type.Literal("delete")]),
23
- guardrails: Type.Object({ reproducibleFailure: guardrail, owningSeamOrInvariant: guardrail, deletionOrSimplificationSuffices: guardrail }, { additionalProperties: true }),
24
- prescription: Type.Object({ kind: Type.Union([Type.Literal("retain"), Type.Literal("delete"), Type.Literal("simplify"), Type.Literal("patch"), Type.Literal("addMechanism")]), recommendation: nonblank, necessityExplanation: Type.Optional(nonblank) }, { additionalProperties: false }),
25
- lastRealBite
21
+ disposition: Type.Optional(Type.Union([Type.Literal("keep"), Type.Literal("thin"), Type.Literal("delete")])),
22
+ guardrails: Type.Optional(Type.Object({ reproducibleFailure: guardrail, owningSeamOrInvariant: guardrail, deletionOrSimplificationSuffices: guardrail }, { additionalProperties: true })),
23
+ prescription: Type.Optional(Type.Object({ kind: Type.Optional(Type.Union([Type.Literal("retain"), Type.Literal("delete"), Type.Literal("simplify"), Type.Literal("patch"), Type.Literal("addMechanism")])), recommendation: nonblank, necessityExplanation: nonblank }, { additionalProperties: true })),
24
+ lastRealBite: Type.Optional(lastRealBite)
26
25
  };
27
26
  const finding = Type.Union([
28
- Type.Object({ targetKey: nonblank, observation: nonblank, evidenceIds }, { additionalProperties: false }),
29
- Type.Object({ targetKey: nonblank, targetKind: Type.Union(assetKinds.map((kind) => Type.Literal(kind))), assetEvidence: Type.Object({ targetKey: nonblank, targetKind: Type.Union(assetKinds.map((kind) => Type.Literal(kind))), evidenceId: nonblank }, { additionalProperties: false }), ...findingBody }, { additionalProperties: false })
27
+ Type.Object({ targetKey: nonblank, observation: nonblank, evidenceIds }, { additionalProperties: true }),
28
+ Type.Object({ targetKey: nonblank, targetKind: Type.Optional(Type.Union(assetKinds.map((kind) => Type.Literal(kind)))), assetEvidence: Type.Optional(Type.Object({ targetKey: nonblank, targetKind: Type.Optional(Type.Union(assetKinds.map((kind) => Type.Literal(kind)))), evidenceId: nonblank }, { additionalProperties: true })), ...findingBody }, { additionalProperties: true })
30
29
  ]);
31
- const caseIdentity = Type.Object({ issueNumber: Type.Integer({ minimum: 1 }), runsPath: nonblank }, { additionalProperties: false });
32
- const cost = Type.Object({
33
- invocations: count,
34
- legs: count,
35
- modelApiTurns: count,
36
- outputTokens: count,
37
- toolCalls: count,
38
- retries: Type.Object({ count: Type.Integer({ minimum: 0 }), sources: Type.Array(nonblank), evidence: Type.Literal("literal run-dir naming") }, { additionalProperties: false }),
39
- statuses: Type.Array(Type.Object({ source: nonblank, status: nonblank }, { additionalProperties: false })),
40
- commits: Type.Array(Type.Object({ source: nonblank, commit: nonblank }, { additionalProperties: false })),
41
- sessions: Type.Array(Type.Union([
42
- Type.Object({ source: nonblank, startedAt: nonblank, endedAt: nonblank, wallMilliseconds: Type.Number({ minimum: 0 }), completion: Type.Literal("accepted") }, { additionalProperties: false }),
43
- Type.Object({ source: nonblank, startedAt: Type.Optional(nonblank), endedAt: Type.Optional(nonblank), wallMilliseconds: Type.Optional(Type.Number({ minimum: 0 })), completion: Type.Literal("incomplete"), degradationReason: Type.Optional(nonblank) }, { additionalProperties: false })
44
- ])),
45
- outputBytes: Type.Object({ count: Type.Integer({ minimum: 0 }), sources: Type.Array(nonblank), payload: Type.Literal("raw JSONL bytes"), providerWireBytes: Type.Literal("unavailable") }, { additionalProperties: false })
46
- }, { additionalProperties: false });
30
+ const caseIdentity = Type.Object({ issueNumber: Type.Optional(Type.Integer()), runsPath: nonblank }, { additionalProperties: true });
31
+ const DOCTOR_STATUS_DESCRIPTION = "completed | refused \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\uFF1Bcompleted \u5141\u8BB8\u7A7A findings\uFF1Brefused \u4EC5\u5F53\u8BC1\u636E\u4E0D\u8DB3\u4EE5\u652F\u6491\u5982\u5B9E\u6848\u8BC1\u8BCD";
47
32
  const doctorSubmissionVariants = Type.Union([
48
33
  Type.Object({
49
- status: Type.Literal("completed", { description: "completed \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\uFF1B\u5141\u8BB8\u7A7A findings\uFF1Bruntime \u8865\u8BB0\u6D3E\u751F\u6210\u672C\u5165\u56DE\u6267" }),
34
+ status: Type.Unknown({ description: DOCTOR_STATUS_DESCRIPTION }),
50
35
  case: Type.Unsafe({ ...caseIdentity, description: "\u7559\u5B58\u592A\u533B\u7F72\u6848\u8EAB\u4EFD" }),
51
36
  findings: Type.Array(finding, { description: "\u53EF\u7A7A\u6216\u4EC5\u542B\u975E\u5904\u65B9\u6848\u89C2\u5BDF\uFF1B\u7F3A\u53EF\u590D\u7528\u8D44\u4EA7\u6216 bounded-bite \u8BC1\u636E\u53EA\u6392\u9664\u5BF9\u5E94\u8D44\u4EA7\u5904\u65B9" })
52
37
  }, { additionalProperties: false, description: "\u5355\u6848\u8BC1\u8BCD\uFF0C\u4E0D\u8981\u6C42\u4EFB\u4F55\u5904\u65B9\u6216\u53EF\u590D\u7528 finding" }),
53
38
  Type.Object({
54
- status: Type.Literal("refused", { description: "refused \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\uFF1B\u4EC5\u5F53\u8BC1\u636E\u4E0D\u8DB3\u4EE5\u652F\u6491\u5982\u5B9E\u6848\u8BC1\u8BCD" }),
55
- reason: Type.String({ minLength: 1, description: "\u8BC1\u636E\u4E0D\u8DB3\u4EE5\u652F\u6491\u5982\u5B9E\u8BC1\u8BCD\u7684\u539F\u56E0" }),
56
- missingEvidence: Type.Array(Type.Object({ need: nonblank, targetKeys: Type.Array(nonblank, { minItems: 1 }) }, { additionalProperties: false }), { minItems: 1, description: "\u5982\u5B9E\u8BC1\u8BCD\u6240\u9700\u800C\u5C1A\u7F3A\u7684\u8BC1\u636E" })
39
+ status: Type.Unknown({ description: DOCTOR_STATUS_DESCRIPTION }),
40
+ reason: Type.String({ description: "\u8BC1\u636E\u4E0D\u8DB3\u4EE5\u652F\u6491\u5982\u5B9E\u8BC1\u8BCD\u7684\u539F\u56E0" }),
41
+ missingEvidence: Type.Array(Type.Object({ need: nonblank, targetKeys: evidenceIds }, { additionalProperties: true }), { description: "\u5982\u5B9E\u8BC1\u8BCD\u6240\u9700\u800C\u5C1A\u7F3A\u7684\u8BC1\u636E" })
57
42
  }, { additionalProperties: false, description: "\u8BC1\u636E\u4E0D\u8DB3\u4EE5\u652F\u6491\u5982\u5B9E\u6848\u8BC1\u8BCD" })
58
43
  ]);
59
44
  const doctorSubmissionSchema = withInfrastructureFailureDeclaration(
60
45
  openToolObjectFromUnion(doctorSubmissionVariants)
61
46
  );
62
- const doctorOutputSchema = Type.Union([
63
- Type.Object({ status: Type.Literal("completed"), case: caseIdentity, findings: Type.Array(finding), cost }, { additionalProperties: false }),
64
- doctorSubmissionVariants.anyOf[1]
65
- ]);
66
- const doctorEvidenceReadSchema = Type.Object({ evidenceId: Type.String({ minLength: 1, description: "\u5F85\u8BFB\u7559\u5B58\u8BC1\u636E\u6807\u8BC6" }), offset: Type.Optional(Type.Integer({ minimum: 0, description: "\u8D77\u59CB\u5B57\u8282\u504F\u79FB\uFF08\u4ECE 0 \u8BA1\uFF09" })), limit: Type.Optional(Type.Integer({ minimum: 1, maximum: 4096, description: "\u8FD4\u56DE\u5B57\u8282\u4E0A\u9650" })) }, { additionalProperties: false });
47
+ const doctorEvidenceReadSchema = Type.Object({ evidenceId: Type.String({ minLength: 1, description: "\u5F85\u8BFB\u7559\u5B58\u8BC1\u636E\u6807\u8BC6" }), offset: Type.Optional(Type.Integer({ minimum: 0, description: "\u8D77\u59CB\u5B57\u8282\u504F\u79FB\uFF08\u4ECE 0 \u8BA1\uFF09" })), limit: Type.Optional(Type.Integer({ minimum: 1, description: "\u8FD4\u56DE\u5B57\u8282\u6570\uFF08\u65E0\u4E0A\u9650\uFF09" })) }, { additionalProperties: true });
67
48
  class DoctorSubmissionContractError extends Error {
68
49
  name = "DoctorSubmissionContractError";
69
50
  }
@@ -79,15 +60,10 @@ function read(value, key) {
79
60
  }
80
61
  }
81
62
  function validateDoctorSubmissionShape(value) {
82
- const status = read(value, "status");
83
- if (status !== "completed" && status !== "refused") throw new DoctorSubmissionContractError("\u592A\u533B\u7F72\u4EA4\u5377\u65E0\u5DF2\u8BC6\u522B\u7684\u6267\u884C\u72B6\u6001");
84
63
  return value;
85
64
  }
86
65
  function validateRecordedDoctorOutput(value) {
87
- const output = validateDoctorSubmissionShape(value);
88
- const status = read(output, "status");
89
- if (status === "completed" && read(output, "cost") === void 0) throw new DoctorSubmissionContractError("completed \u592A\u533B\u7F72\u56DE\u6267\u7F3A\u5C11 runtime \u6301\u6709\u7684 cost \u8BC1\u8BCD");
90
- return output;
66
+ return value;
91
67
  }
92
68
  class DoctorEvidenceStore {
93
69
  constructor(patient) {
@@ -97,12 +73,16 @@ class DoctorEvidenceStore {
97
73
  patient;
98
74
  entries;
99
75
  coverage = /* @__PURE__ */ new Map();
100
- read(evidenceId, offset = 0, limit = 4096) {
76
+ // #836 A6.5: no 4096 hard cap — limit only bounds the requested window when provided.
77
+ read(evidenceId, offset = 0, limit) {
101
78
  const entry = this.entries.get(evidenceId);
102
79
  if (!entry) throw new Error(`\u8BC1\u636E ID \u672A\u51C6\u5165\uFF1A${evidenceId}`);
103
- if (!Number.isInteger(offset) || offset < 0 || !Number.isInteger(limit) || limit < 1 || limit > 4096) throw new Error("\u8BC1\u636E\u5206\u9875\u53C2\u6570\u65E0\u6548");
80
+ if (!Number.isInteger(offset) || offset < 0) throw new Error("\u8BC1\u636E\u5206\u9875\u53C2\u6570\u65E0\u6548");
104
81
  if (offset > entry.contentLength) throw new Error("\u8BC1\u636E offset \u8D85\u51FA\u5185\u5BB9");
105
- const end = Math.min(entry.contentLength, offset + limit);
82
+ const window = limit === void 0 ? entry.contentLength - offset : !Number.isInteger(limit) || limit < 1 ? (() => {
83
+ throw new Error("\u8BC1\u636E\u5206\u9875\u53C2\u6570\u65E0\u6548");
84
+ })() : limit;
85
+ const end = Math.min(entry.contentLength, offset + window);
106
86
  const ranges = [...this.coverage.get(evidenceId) ?? [], [offset, end]].sort((a, b) => a[0] - b[0]);
107
87
  const merged = [];
108
88
  for (const range of ranges) {
@@ -111,7 +91,16 @@ class DoctorEvidenceStore {
111
91
  else merged.push([...range]);
112
92
  }
113
93
  this.coverage.set(evidenceId, merged);
114
- return { evidenceId, kind: entry.kind, offset, content: entry.content.slice(offset, end), nextOffset: end < entry.contentLength ? end : null, contentLength: entry.contentLength, byteLength: entry.byteLength, sha256: entry.sha256 };
94
+ return {
95
+ evidenceId,
96
+ kind: entry.kind,
97
+ offset,
98
+ content: entry.content.slice(offset, end),
99
+ nextOffset: end < entry.contentLength ? end : null,
100
+ contentLength: entry.contentLength,
101
+ byteLength: entry.byteLength,
102
+ sha256: entry.sha256
103
+ };
115
104
  }
116
105
  hasRead(id) {
117
106
  const entry = this.entries.get(id);
@@ -122,65 +111,8 @@ class DoctorEvidenceStore {
122
111
  return [...this.coverage.keys()].sort().map((evidenceId) => ({ evidenceId, fullyRead: this.hasRead(evidenceId) }));
123
112
  }
124
113
  }
125
- function validateDoctorOutput(value, patient, store) {
126
- const output = validateDoctorSubmissionShape(value);
127
- const lawfulTargets = /* @__PURE__ */ new Set(["case", ...patient.cost.invocations.sources]);
128
- const assertTarget = (targetKey) => {
129
- if (typeof targetKey === "string" && !lawfulTargets.has(targetKey)) throw new DoctorSubmissionContractError(`targetKey \u4E0D\u662F\u5408\u6CD5\u6848\u76EE\u6807\uFF1A${targetKey}`);
130
- };
131
- const readCitations = (ids, label) => {
132
- if (!Array.isArray(ids)) return;
133
- for (const id of ids) if (typeof id === "string" && (!store.entries.has(id) || !store.hasRead(id))) throw new DoctorSubmissionContractError(`${label} \u987B\u5F15\u7528\u5DF2\u51C6\u5165/\u5DF2\u8BFB\u8BC1\u636E\uFF1A${id}`);
134
- };
135
- if (read(output, "status") === "refused") {
136
- const missingEvidence = read(output, "missingEvidence");
137
- if (Array.isArray(missingEvidence)) for (const missing of missingEvidence) {
138
- const targets = read(missing, "targetKeys");
139
- if (Array.isArray(targets)) for (const target of targets) assertTarget(target);
140
- }
141
- return output;
142
- }
143
- const identity = read(output, "case");
144
- const issueNumber = read(identity, "issueNumber");
145
- const runsPath = read(identity, "runsPath");
146
- if (issueNumber !== void 0 && issueNumber !== patient.identity.issueNumber || runsPath !== void 0 && runsPath !== patient.identity.runsPath) throw new DoctorSubmissionContractError("\u592A\u533B\u7F72\u4EA4\u5377 case \u987B\u7B49\u4E8E\u5DF2\u6FC0\u6D3B\u6848\u8EAB\u4EFD");
147
- const findings = read(output, "findings");
148
- if (!Array.isArray(findings)) return output;
149
- for (const finding2 of findings) {
150
- const targetKey = read(finding2, "targetKey");
151
- readCitations(read(finding2, "evidenceIds"), "finding");
152
- const assetEvidence = read(finding2, "assetEvidence");
153
- if (!isRecord(assetEvidence)) {
154
- assertTarget(targetKey);
155
- continue;
156
- }
157
- const assetTargetKey = read(assetEvidence, "targetKey");
158
- const assetTargetKind = read(assetEvidence, "targetKind");
159
- const assetEvidenceId = read(assetEvidence, "evidenceId");
160
- if (typeof assetTargetKey === "string" && assetTargetKey !== targetKey) throw new DoctorSubmissionContractError("\u7C7B\u578B\u5316\u8D44\u4EA7\u8BC1\u636E\u987B\u786E\u7ACB finding \u7684 targetKey");
161
- if (typeof assetTargetKind === "string" && assetTargetKind !== read(finding2, "targetKind")) throw new DoctorSubmissionContractError("\u7C7B\u578B\u5316\u8D44\u4EA7\u8BC1\u636E\u987B\u786E\u7ACB finding \u7684 targetKind");
162
- if (typeof assetEvidenceId === "string") readCitations([assetEvidenceId], "asset evidence");
163
- const guardrails = read(finding2, "guardrails");
164
- for (const key of ["reproducibleFailure", "owningSeamOrInvariant", "deletionOrSimplificationSuffices"]) readCitations(read(read(guardrails, key), "evidenceIds"), "guardrail");
165
- const bite = read(finding2, "lastRealBite");
166
- const biteKind = read(bite, "kind");
167
- if (biteKind !== "actual" && biteKind !== "noRealBite") continue;
168
- if (read(bite, "targetKey") !== targetKey) throw new DoctorSubmissionContractError("lastRealBite \u76EE\u6807\u4E0D\u5339\u914D");
169
- if (biteKind === "actual") {
170
- const evidenceId = read(bite, "evidenceId");
171
- const entry = typeof evidenceId === "string" ? store.entries.get(evidenceId) : void 0;
172
- if (!entry || entry.kind !== "session" || !store.hasRead(entry.id)) throw new DoctorSubmissionContractError("actual bite \u987B\u5F15\u7528\u5DF2\u51C6\u5165/\u5DF2\u8BFB\u7684\u7559\u5B58 session");
173
- } else {
174
- const eligible = patient.evidence.map((entry) => entry.id).sort();
175
- const ids = read(bite, "eligibleEvidenceIds");
176
- if (Array.isArray(ids)) {
177
- const claimed = ids.filter((id) => typeof id === "string").sort();
178
- if (canonicalJson(claimed) !== canonicalJson(eligible)) throw new DoctorSubmissionContractError("noRealBite \u987B\u8BC1\u660E\u5B8C\u6574\u7684\u5355\u6848\u5408\u683C\u8BC1\u636E\u5168\u96C6");
179
- readCitations(eligible, "noRealBite");
180
- }
181
- }
182
- }
183
- return output;
114
+ function validateDoctorOutput(value, _patient, _store) {
115
+ return validateDoctorSubmissionShape(value);
184
116
  }
185
117
  export {
186
118
  DOCTOR_ACCEPTED_AUDIT_NO_RECEIPT_TEXT,
@@ -192,7 +124,6 @@ export {
192
124
  DoctorEvidenceStore,
193
125
  DoctorSubmissionContractError,
194
126
  doctorEvidenceReadSchema,
195
- doctorOutputSchema,
196
127
  doctorSubmissionSchema,
197
128
  validateDoctorOutput,
198
129
  validateDoctorSubmissionShape,
@@ -86,14 +86,10 @@ function deriveSession(content, id) {
86
86
  if (facts.commit && facts.commit !== observedCommit) {
87
87
  commits.push({ source: id, commit: facts.commit });
88
88
  observedCommit = facts.commit;
89
- }
90
- statuses.length = 0;
89
+ } /* #836 B10.3: do not wipe earlier statuses or invent a code status sentence */
91
90
  if (facts.status !== undefined) {
92
91
  statuses.push({ source: id, status: facts.status });
93
92
  }
94
- else {
95
- statuses.push({ source: id, status: "terminating receipt has no receipt-level status" });
96
- }
97
93
  }
98
94
  }
99
95
  const acceptedAt = accepted && timestamp(accepted);
@@ -13,7 +13,7 @@ const engineDetourArgsSchema = Type.Object(
13
13
  description: "\u9996\u9879\u4E3A PATH \u4E2D\u7684\u53EF\u6267\u884C\u6587\u4EF6\uFF0C\u5176\u4F59\u9879\u4E3A\u53C2\u6570\u3002"
14
14
  })
15
15
  },
16
- { additionalProperties: false }
16
+ { additionalProperties: true }
17
17
  );
18
18
  function isCallerCancellation(error, signal) {
19
19
  if (signal?.aborted === true) return true;
@@ -1,4 +1,4 @@
1
- import { auditorRunDirectory, persistGateSubmissionCandidate, readLatestSubmissionArguments, } from "./auditor-dossier-tool.js";
1
+ import { auditorRunDirectory } from "./auditor-dossier-tool.js";
2
2
  import { GatekeeperDecisionError } from "./submission-errors.js";
3
3
  import { INSPECTOR_OUTPUT_TOOL_NAME } from "./inspector-contracts.js";
4
4
  import { GATEKEEPER_OUTPUT_TOOL_NAME, gatekeeperDecisionSchema, gatekeeperOutputSchema, } from "./package-contracts/gatekeeper-output.js";
@@ -51,19 +51,12 @@ function failureReason(error) {
51
51
  return error.errors.map(failureReason).join("; ");
52
52
  return error instanceof Error ? `${error.name}: ${error.message}` : String(error);
53
53
  }
54
- /** Serializable stand-in when the child tool call had no arguments object. */
55
- export const MISSING_ARGUMENTS_SUBMISSION = Object.freeze({ missing: "arguments" });
56
54
  function isRecord(value) {
57
55
  return typeof value === "object" && value !== null && !Array.isArray(value);
58
56
  }
59
- /** Keep original decision bytes for the next reader; undefined becomes a serializable missing-args fact. */
57
+ /** Original decision bytes — no sentinel replacement (#836). */
60
58
  function retainedReceipt(decision) {
61
- // undefined must not be stored: JSON drops it and the missing-args fact vanishes.
62
- // Through the real provider adapter an undefined root argument arrives as an
63
- // empty object after serialization; that must also project a missing-args fact.
64
- return decision === undefined || (isRecord(decision) && Object.keys(decision).length === 0)
65
- ? MISSING_ARGUMENTS_SUBMISSION
66
- : decision;
59
+ return decision;
67
60
  }
68
61
  function readRecord(value) {
69
62
  if (typeof value !== "object" || value === null || Array.isArray(value))
@@ -92,63 +85,85 @@ function projectOfficerDecision(officer, decision, fallbackStatus) {
92
85
  }
93
86
  /**
94
87
  * Project a public-role terminal onto the gate queue surface.
95
- * Lifecycle facts (no_receipt / transport) stay loud; conclusion reads only
96
- * the status field. No unusable/unreadable judgment (#753).
88
+ * Host failure stays failure; recorded officer payloads ride beside it (#836 A.3).
89
+ * Multiple recorded payloads are all kept — code does not pick last-wins.
97
90
  */
91
+ function officerPayloads(terminal) {
92
+ const outcome = terminal?.roleOutcome;
93
+ if (outcome !== undefined && (outcome.kind === "accepted" || outcome.kind === "audit_escalation")) {
94
+ return outcome.payloads ?? terminal?.submissions ?? [];
95
+ }
96
+ if (outcome?.kind === "failure")
97
+ return outcome.payloads ?? terminal?.submissions ?? [];
98
+ return terminal?.submissions ?? [];
99
+ }
100
+ function projectOfficerPayloads(officer, payloads, fallbackStatus) {
101
+ if (payloads.length === 0) {
102
+ return projectOfficerDecision(officer, undefined, fallbackStatus);
103
+ }
104
+ // Present every recorded payload; queue only the latest conclusion so a reask
105
+ // can converge (#836 呈现 ≠ 排队).
106
+ const queued = projectOfficerDecision(officer, payloads[payloads.length - 1], fallbackStatus);
107
+ if (payloads.length === 1)
108
+ return queued;
109
+ if (queued.status === "pass"
110
+ || queued.status === "bounce"
111
+ || queued.status === "escalate"
112
+ || queued.status === "needs_reask") {
113
+ return { ...queued, receipt: payloads };
114
+ }
115
+ return queued;
116
+ }
98
117
  function projectOfficerTerminal(officer, summoned) {
99
118
  const terminal = summoned.terminal;
100
119
  const outcome = terminal?.roleOutcome;
120
+ const recorded = officerPayloads(terminal);
101
121
  if (outcome === undefined) {
102
- const detail = summoned.stderr?.trim();
122
+ const detail = summoned.stderr ?? "";
103
123
  return {
104
124
  status: "transport_failure",
105
125
  stage: officer,
106
- reason: detail && detail.length > 0
126
+ reason: detail.length > 0
107
127
  ? `${gateSeatLabel(officer)} public summon exit ${summoned.exitCode}: ${detail}`
108
128
  : `${gateSeatLabel(officer)} public summon produced no terminal (exit ${summoned.exitCode})`,
109
- submission: summoned,
129
+ submission: recorded.length > 0 ? recorded : summoned,
110
130
  };
111
131
  }
112
132
  if (outcome.kind === "no_receipt") {
113
133
  return {
114
134
  status: "no_receipt",
115
135
  stage: officer,
116
- reason: `${gateSeatLabel(officer)}未产生已接受回执即散局`,
136
+ reason: typeof outcome.status === "string" && outcome.status.length > 0
137
+ ? outcome.status
138
+ : "no_receipt",
117
139
  facts: outcome,
118
140
  };
119
141
  }
120
142
  if (outcome.kind === "failure") {
121
- // Real provider/engine/disk failure — keep loud. Not a shape judgment.
122
143
  return {
123
144
  status: "transport_failure",
124
145
  stage: officer,
125
146
  reason: outcome.diagnostic,
126
- submission: outcome.decisiveFacts,
147
+ submission: recorded.length > 0 ? recorded : outcome.decisiveFacts,
127
148
  };
128
149
  }
129
150
  if (outcome.kind === "audit_escalation") {
130
- // Residual/compliance escalate face: queue as escalate, receipt as written.
131
- // Nested officer escalate itself seals accepted+status escalate (no rewrite).
132
151
  return {
133
152
  status: "escalate",
134
153
  officer,
135
- receipt: retainedReceipt(outcome.decisiveFacts),
154
+ receipt: recorded.length === 1 ? recorded[0] : recorded,
136
155
  };
137
156
  }
138
157
  if (outcome.kind === "accepted") {
139
- // Prefer the officer's own decisiveFacts as the receipt body. outcome.status is
140
- // only a fallback when facts have no status key (missing-args sentinel stays intact).
141
- const facts = outcome.decisiveFacts;
142
- if (isRecord(facts) && Object.keys(facts).length > 0) {
143
- return projectOfficerDecision(officer, facts, outcome.status);
144
- }
145
- return projectOfficerDecision(officer, { status: outcome.status });
158
+ // outcome.status is the fixture/compat leaf: production settlement leaves
159
+ // it undefined once payloads are recorded, so this only matters when a
160
+ // caller still supplies status without any recorded payload (#836 hang).
161
+ return projectOfficerPayloads(officer, recorded, outcome.status);
146
162
  }
147
- // Unknown terminal kind: still not a shape judgment — ask the speaker again.
148
163
  return {
149
164
  status: "needs_reask",
150
165
  officer,
151
- receipt: retainedReceipt(outcome),
166
+ receipt: recorded.length > 0 ? recorded : retainedReceipt(outcome),
152
167
  };
153
168
  }
154
169
  /**
@@ -173,15 +188,12 @@ export async function projectGatekeeperRun(options) {
173
188
  },
174
189
  };
175
190
  }
176
- // #632: Grok session.jsonl is header-only — freeze the in-memory tool-call leaf
177
- // as a run artifact so dossier exploration still resolves. LLM→LLM resume does
178
- // not ride this path: submission body goes verbatim on gateReviewInstruction (#786).
179
- persistGateSubmissionCandidate(runDirectory, options.context);
180
- const submission = readLatestSubmissionArguments(options.context);
191
+ // #836: officers receive the whole parent run directory pointer and find the
192
+ // submission themselves — code no longer picks latest toolCall leaf (A7.1–A7.3).
181
193
  let summoned;
182
194
  try {
183
195
  const summon = options.summonOfficer
184
- ?? (async (nextOfficer, sourceRunDirectory, officerSignal, reask, nextSubmission) => {
196
+ ?? (async (nextOfficer, sourceRunDirectory, officerSignal, reask) => {
185
197
  const { summonGateOfficer } = await import("./public-role-summons.js");
186
198
  return summonGateOfficer({
187
199
  officer: nextOfficer,
@@ -189,14 +201,13 @@ export async function projectGatekeeperRun(options) {
189
201
  cwd: options.context.cwd ?? process.cwd(),
190
202
  ...(officerSignal === undefined ? {} : { signal: officerSignal }),
191
203
  ...(reask === undefined ? {} : { reask }),
192
- ...(nextSubmission === undefined ? {} : { submission: nextSubmission }),
193
204
  ...(options.home === undefined ? {} : { home: options.home }),
194
205
  ...(options.packageRoot === undefined ? {} : { packageRoot: options.packageRoot }),
195
206
  ...(options.roleTurnHost === undefined ? {} : { roleTurnHost: options.roleTurnHost }),
196
207
  ...(options.createRunId === undefined ? {} : { createRunId: options.createRunId }),
197
208
  });
198
209
  });
199
- summoned = await summon(officer, runDirectory, options.signal, options.reask, submission);
210
+ summoned = await summon(officer, runDirectory, options.signal, options.reask);
200
211
  }
201
212
  catch (error) {
202
213
  return {