@akagilnc/pi-workflow-roles 0.1.3644 → 0.1.3652

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 (92) hide show
  1. package/dist/acp-host/production-host.js +3089 -2187
  2. package/dist/activation-ledger-session.js +105 -0
  3. package/dist/activation-ledger.js +139 -0
  4. package/dist/activation-trace.js +33 -0
  5. package/dist/agent-start-materials.js +11 -0
  6. package/dist/audit-escalation.js +5 -5
  7. package/dist/auditor-role.js +12 -0
  8. package/dist/canonical-skill-binding.js +64 -0
  9. package/dist/collector-identity.js +151 -0
  10. package/dist/collector-receipt.js +95 -0
  11. package/dist/collector-role.js +441 -0
  12. package/dist/compliance-transport.js +11 -57
  13. package/dist/countersign-role.js +28 -0
  14. package/dist/diarist-contracts.js +0 -12
  15. package/dist/diarist-role.js +29 -0
  16. package/dist/doctor-contracts.js +0 -2
  17. package/dist/doctor-role.js +74 -0
  18. package/dist/fixer-bash-seatbelt.js +13 -0
  19. package/dist/gatekeeper-pass-envelope.js +72 -0
  20. package/dist/gleaner-left-contracts.js +0 -7
  21. package/dist/gleaner-left-role.js +26 -0
  22. package/dist/inspector-contracts.js +0 -4
  23. package/dist/inspector-role.js +29 -0
  24. package/dist/judge-role.js +106 -0
  25. package/dist/merger-role.js +66 -0
  26. package/dist/navigator-public-session.js +1 -5
  27. package/dist/navigator-role.js +12 -0
  28. package/dist/notary-contracts.js +0 -18
  29. package/dist/notary-role.js +137 -0
  30. package/dist/oauth-keepalive.js +158 -0
  31. package/dist/package-contracts/auditor-output.js +0 -13
  32. package/dist/package-contracts/gatekeeper-output.js +0 -10
  33. package/dist/package-contracts/judge-output.js +0 -2
  34. package/dist/package-contracts/navigator-output.js +0 -4
  35. package/dist/package-contracts/terminating-tools.js +2 -16
  36. package/dist/packaged-role-registry.js +1 -18
  37. package/dist/pi/adapter.js +211 -0
  38. package/dist/pi/role-turn-host.js +0 -2
  39. package/dist/public-cli/instruction-seat-run.js +2 -6
  40. package/dist/public-cli/invocation.js +0 -7
  41. package/dist/public-cli/main.js +138 -735
  42. package/dist/public-cli/option-definitions.js +0 -14
  43. package/dist/public-cli/registry.js +1 -2
  44. package/dist/public-cli/run-lifecycle.js +1 -3
  45. package/dist/public-cli/settlement.js +66 -537
  46. package/dist/public-role-summons.js +0 -14
  47. package/dist/reviewer-child-executor.js +163 -70
  48. package/dist/reviewer-construction.js +2 -2
  49. package/dist/reviewer-role.js +159 -0
  50. package/dist/reviewer-settlement.js +66 -0
  51. package/dist/role-runtime.js +1394 -0
  52. package/dist/stderr-jsonl.js +26 -0
  53. package/dist/tool-execution-observation.js +141 -0
  54. package/dist/worker-role.js +343 -0
  55. package/dist/worker-submission-gates.js +305 -0
  56. package/extensions/role-runtime.ts +1 -2
  57. package/package.json +1 -1
  58. package/src/acp-host/production-host.ts +0 -1
  59. package/src/audit-escalation.ts +9 -9
  60. package/src/compliance-transport.ts +28 -94
  61. package/src/diarist-contracts.ts +0 -12
  62. package/src/doctor-contracts.ts +0 -1
  63. package/src/doctor-role.ts +2 -2
  64. package/src/gleaner-left-contracts.ts +0 -9
  65. package/src/host-contracts.ts +0 -2
  66. package/src/inspector-contracts.ts +0 -8
  67. package/src/judge-role.ts +4 -5
  68. package/src/navigator-public-session.ts +4 -5
  69. package/src/notary-contracts.ts +0 -18
  70. package/src/package-contracts/auditor-output.ts +0 -11
  71. package/src/package-contracts/gatekeeper-output.ts +0 -11
  72. package/src/package-contracts/judge-output.ts +0 -1
  73. package/src/package-contracts/navigator-output.ts +0 -3
  74. package/src/package-contracts/terminating-tools.ts +1 -19
  75. package/src/packaged-role-registry.ts +1 -19
  76. package/src/pi/role-turn-host.ts +0 -2
  77. package/src/public-cli/cli.ts +1 -5
  78. package/src/public-cli/instruction-seat-run.ts +5 -14
  79. package/src/public-cli/invocation.ts +3 -21
  80. package/src/public-cli/option-definitions.ts +0 -16
  81. package/src/public-cli/registry.ts +1 -2
  82. package/src/public-cli/run-lifecycle.ts +0 -6
  83. package/src/public-cli/settlement.ts +58 -572
  84. package/src/public-cli/terminal.ts +0 -1
  85. package/src/public-role-summons.ts +0 -15
  86. package/src/reviewer-child-executor.ts +199 -98
  87. package/src/reviewer-construction.ts +3 -3
  88. package/src/role-runtime.ts +1 -33
  89. package/dist/package-contracts/evidence-child-output.js +0 -34
  90. package/souls/evidence-child.md +0 -1
  91. package/src/evidence-child-role.ts +0 -22
  92. package/src/package-contracts/evidence-child-output.ts +0 -51
@@ -0,0 +1,441 @@
1
+ import { COLLECTOR_FIXED_KICKOFF, emptyCollectorManifest, loadCollectorManifest, parseCollectorPrNumber, parseCollectorRepository, } from "./collector-config.js";
2
+ import { createSystemCollectorClock, } from "./collector-evidence.js";
3
+ import { COLLECTOR_OBSERVE_TOOL, COLLECTOR_OUTPUT_TOOL, COLLECTOR_READ_TOOL, COLLECTOR_REQUEST_TOOL, COLLECTOR_WAIT_TOOL, projectEvidenceEntryView, } from "./collector-ledger.js";
4
+ import { buildCollectorReceipt, } from "./collector-receipt.js";
5
+ import { collectorObserveArgsSchema, collectorOutputArgsSchema, collectorReadArgsSchema, collectorRequestArgsSchema, collectorWaitArgsSchema, } from "./collector-tool-schemas.js";
6
+ import { COLLECTOR_ACCEPTED_TEXT } from "./package-contracts/collector-output.js";
7
+ import { CorrectableSubmissionError, isCorrectableExecuteError } from "./submission-correctable-error.js";
8
+ import { CollectorUnknownEvidenceError } from "./collector-identity.js";
9
+ export { CollectorUnknownEvidenceError } from "./collector-identity.js";
10
+ /**
11
+ * #641 chain②: normal completion must never declare `infrastructureFailure`.
12
+ * When the runtime can machine-verify a lawful receipt assembly, a declaration
13
+ * is model misuse — bounce it as correctable guidance instead of host failure.
14
+ */
15
+ export class CollectorNormalCompletionDeclarationError extends CorrectableSubmissionError {
16
+ constructor() {
17
+ super("runtime 已按机器状态核验本局为正常完工(回执可合法组装):正常完工的交件不得填 infrastructureFailure,请省略该字段后重新提交。");
18
+ this.name = "CollectorNormalCompletionDeclarationError";
19
+ }
20
+ }
21
+ export { COLLECTOR_FIXED_KICKOFF, } from "./collector-config.js";
22
+ export { COLLECTOR_OBSERVE_TOOL, COLLECTOR_OUTPUT_TOOL, COLLECTOR_READ_TOOL, COLLECTOR_REQUEST_TOOL, COLLECTOR_WAIT_TOOL, };
23
+ export const COLLECTOR_REQUIRED_TOOLS = [
24
+ COLLECTOR_OBSERVE_TOOL,
25
+ COLLECTOR_READ_TOOL,
26
+ COLLECTOR_REQUEST_TOOL,
27
+ COLLECTOR_WAIT_TOOL,
28
+ COLLECTOR_OUTPUT_TOOL,
29
+ ];
30
+ const observeSchema = collectorObserveArgsSchema;
31
+ const readSchema = collectorReadArgsSchema;
32
+ const requestSchema = collectorRequestArgsSchema;
33
+ const waitSchema = collectorWaitArgsSchema;
34
+ const outputSchema = collectorOutputArgsSchema;
35
+ /** Sole-final at the output execution seam (same shape as other terminating roles). */
36
+ function buildMethodContext(activation) {
37
+ return [
38
+ "<collector_method>",
39
+ `host: github.com`,
40
+ `repository: ${activation.repository.canonical}`,
41
+ `prNumber: ${activation.prNumber}`,
42
+ `requests: ${JSON.stringify(activation.manifest.requests.map((request) => ({ id: request.id })))}`,
43
+ "</collector_method>",
44
+ ].join("\n");
45
+ }
46
+ export function createCollectorRoleRuntime(pi, dependencies, hostActions) {
47
+ let activation;
48
+ let inputCount = 0;
49
+ let lifecycleRegistered = false;
50
+ let toolsRegistered = false;
51
+ let firstDispatchDone = false;
52
+ pi.registerFlag("ak-collector-repo", {
53
+ description: "GitHub owner/repo target for Collector (github.com only; conservative ASCII grammar). Collector forbids every Skill, including command-only Skills.",
54
+ type: "string",
55
+ });
56
+ pi.registerFlag("ak-collector-pr", {
57
+ description: "Positive safe-integer pull request number for Collector. Supported profile: --no-skills, --no-extensions with only the explicit Collector package extension, no prompt templates/context files, one print/JSON prompt",
58
+ type: "string",
59
+ });
60
+ pi.registerFlag("ak-collector-request-manifest", {
61
+ description: "Path to the Collector v1 request manifest JSON file. In Pi latest, late hostile sibling-extension Skill injection is unsupported and fail-closed when detected; drift prevention only, not a security boundary or provider-zero guarantee",
62
+ type: "string",
63
+ });
64
+ const ensureLifecycle = () => {
65
+ if (lifecycleRegistered)
66
+ return;
67
+ lifecycleRegistered = true;
68
+ pi.on("input", (event, ctx) => {
69
+ if (activation === undefined) {
70
+ // role not active
71
+ return { action: "continue" };
72
+ }
73
+ if (inputCount >= 1) {
74
+ activation.ledger.latchFatal("通进司已拒绝后续输入");
75
+ if (process.exitCode === undefined || process.exitCode === 0) {
76
+ process.exitCode = 1;
77
+ }
78
+ console.error("Collector rejected later input");
79
+ return { action: "handled" };
80
+ }
81
+ inputCount += 1;
82
+ return {
83
+ action: "transform",
84
+ text: COLLECTOR_FIXED_KICKOFF,
85
+ images: [],
86
+ };
87
+ });
88
+ pi.on("before_agent_start", (event, ctx) => {
89
+ if (activation === undefined)
90
+ return;
91
+ // Detectable ambient instruction resources on the supported prompt surface.
92
+ const options = event.systemPromptOptions;
93
+ if (options.skills && options.skills.length > 0) {
94
+ hostActions.failInfrastructure(activation.ledger.latchFatal("通进司检测到系统提示中的环境 skills"), ctx);
95
+ }
96
+ if (options.contextFiles && options.contextFiles.length > 0) {
97
+ hostActions.failInfrastructure(activation.ledger.latchFatal("通进司检测到系统提示中的环境 context files"), ctx);
98
+ }
99
+ if (typeof options.appendSystemPrompt === "string" &&
100
+ options.appendSystemPrompt.trim().length > 0) {
101
+ hostActions.failInfrastructure(activation.ledger.latchFatal("通进司检测到 appendSystemPrompt 漂移"), ctx);
102
+ }
103
+ if (event.prompt !== COLLECTOR_FIXED_KICKOFF) {
104
+ hostActions.failInfrastructure(activation.ledger.latchFatal("通进司首条提示不是固定开场令"), ctx);
105
+ }
106
+ if (!firstDispatchDone) {
107
+ firstDispatchDone = true;
108
+ activation.ledger.recordActivation(activation.clock);
109
+ }
110
+ return {
111
+ systemPrompt: [
112
+ event.systemPrompt,
113
+ "",
114
+ "<collector_soul>",
115
+ activation.soul,
116
+ "</collector_soul>",
117
+ "",
118
+ buildMethodContext(activation),
119
+ ].join("\n"),
120
+ };
121
+ });
122
+ pi.on("tool_call", (event) => {
123
+ if (activation === undefined)
124
+ return;
125
+ if (activation.ledger.fatal) {
126
+ return {
127
+ block: true,
128
+ reason: activation.ledger.fatalReason ?? "通进司致命状态",
129
+ };
130
+ }
131
+ if (!COLLECTOR_REQUIRED_TOOLS.includes(event.toolName)) {
132
+ return {
133
+ block: true,
134
+ reason: `通进司禁用工具 ${event.toolName}`,
135
+ };
136
+ }
137
+ if (event.toolName === COLLECTOR_OUTPUT_TOOL) {
138
+ activation.ledger.beginOperational(COLLECTOR_OUTPUT_TOOL, event.toolCallId);
139
+ }
140
+ if (activation.ledger.outputCandidate &&
141
+ event.toolName !== COLLECTOR_OUTPUT_TOOL) {
142
+ return {
143
+ block: true,
144
+ reason: "通进司已产出输出候选,本局不再受理操作",
145
+ };
146
+ }
147
+ return undefined;
148
+ });
149
+ pi.on("tool_result", (event) => {
150
+ if (activation === undefined)
151
+ return;
152
+ activation.ledger.completeOperational(event.toolCallId);
153
+ });
154
+ pi.on("session_shutdown", () => {
155
+ if (activation === undefined)
156
+ return;
157
+ if (activation.ledger.fatal) {
158
+ if (process.exitCode === undefined || process.exitCode === 0) {
159
+ process.exitCode = 1;
160
+ }
161
+ }
162
+ });
163
+ };
164
+ const registerTools = () => {
165
+ if (toolsRegistered)
166
+ return;
167
+ toolsRegistered = true;
168
+ pi.registerTool({
169
+ name: COLLECTOR_OBSERVE_TOOL,
170
+ label: "通进司观察",
171
+ description: "抓取配置目标的完整 GitHub PR 证据,存不可变快照入卷。正文在上下文中只给头部摘录加指针;需要头部之外的正文时,用 ak_collector_read 按 evidenceId 开卷;findings 的拆分与归类由你在交件时完成。",
172
+ promptSnippet: "抓取配置目标 PR 证据",
173
+ parameters: observeSchema,
174
+ async execute(toolCallId, _params, signal, _onUpdate, ctx) {
175
+ if (activation === undefined) {
176
+ throw new Error("通进司未激活");
177
+ }
178
+ try {
179
+ activation.ledger.beginOperational(COLLECTOR_OBSERVE_TOOL, toolCallId);
180
+ const { snapshot, contextView } = await activation.ledger.observe(activation.transport, activation.clock, signal);
181
+ activation.ledger.completeOperational(toolCallId);
182
+ if (snapshot.prState !== "OPEN") {
183
+ // Non-OPEN observed as latest complete snapshot is target-state failure at output,
184
+ // but observe itself may return the fact. If this is a final observation, still return.
185
+ }
186
+ return {
187
+ content: [{
188
+ type: "text",
189
+ // #641 chain①: model context carries bounded body heads + pointers only.
190
+ text: JSON.stringify(contextView),
191
+ }],
192
+ // #641 the bounded projection is the only provider-visible face on every host
193
+ // (Grok/ACP relays tool details as MCP structuredContent); full bodies stay
194
+ // in the ledger volume and enter context only by explicit ak_collector_read.
195
+ details: contextView,
196
+ };
197
+ }
198
+ catch (error) {
199
+ hostActions.failInfrastructure(error, ctx, toolCallId);
200
+ }
201
+ },
202
+ });
203
+ pi.registerTool({
204
+ name: COLLECTOR_READ_TOOL,
205
+ label: "通进司开卷",
206
+ description: "按 evidenceId 开卷读取一条已观测材料的全量正文与指针;只在观察头部摘录不足以判读时调用。",
207
+ promptSnippet: "按指针开卷读材料",
208
+ parameters: readSchema,
209
+ async execute(toolCallId, params, _signal, _onUpdate, ctx) {
210
+ if (activation === undefined) {
211
+ throw new Error("通进司未激活");
212
+ }
213
+ try {
214
+ activation.ledger.beginOperational(COLLECTOR_READ_TOOL, toolCallId);
215
+ const record = activation.ledger.getEvidence(params.evidenceId);
216
+ if (record === undefined ||
217
+ (record.kind !== "review" && record.kind !== "issue_comment" && record.kind !== "review_comment" && record.kind !== "reaction") ||
218
+ typeof record.body !== "string") {
219
+ throw new CollectorUnknownEvidenceError(params.evidenceId);
220
+ }
221
+ const material = projectEvidenceEntryView(record);
222
+ activation.ledger.completeOperational(toolCallId);
223
+ return {
224
+ content: [{
225
+ type: "text",
226
+ // #641 chain①: full bodies enter provider context only by explicit pointer.
227
+ text: JSON.stringify(material),
228
+ }],
229
+ details: material,
230
+ };
231
+ }
232
+ catch (error) {
233
+ if (isCorrectableExecuteError(error))
234
+ throw error;
235
+ // typed toolCallId books the shared infrastructure fact so settlement can
236
+ // tell a read tool's real host failure from a correctable pointer bounce.
237
+ hostActions.failInfrastructure(error, ctx, toolCallId);
238
+ }
239
+ },
240
+ });
241
+ pi.registerTool({
242
+ name: COLLECTOR_REQUEST_TOOL,
243
+ label: "通进司请求",
244
+ description: "按配置请求体与关联标记,在所引最新快照 HEAD 发一次请求。",
245
+ promptSnippet: "按配置发一次请求",
246
+ parameters: requestSchema,
247
+ async execute(toolCallId, params, signal, _onUpdate, ctx) {
248
+ if (activation === undefined) {
249
+ throw new Error("通进司未激活");
250
+ }
251
+ try {
252
+ activation.ledger.beginOperational(COLLECTOR_REQUEST_TOOL, toolCallId);
253
+ const details = await activation.ledger.request(params, activation.transport, activation.clock, signal);
254
+ activation.ledger.completeOperational(toolCallId);
255
+ return {
256
+ content: [{
257
+ type: "text",
258
+ text: `请求尝试已记录:request ${params.requestId}`,
259
+ }],
260
+ details,
261
+ };
262
+ }
263
+ catch (error) {
264
+ hostActions.failInfrastructure(error, ctx, toolCallId);
265
+ }
266
+ },
267
+ });
268
+ pi.registerTool({
269
+ name: COLLECTOR_WAIT_TOOL,
270
+ label: "通进司等待",
271
+ description: "再观察前等待;单次上限五分钟且不超剩余资格。",
272
+ promptSnippet: "资格截止前等待",
273
+ parameters: waitSchema,
274
+ async execute(toolCallId, params, signal, _onUpdate, ctx) {
275
+ if (activation === undefined) {
276
+ throw new Error("通进司未激活");
277
+ }
278
+ try {
279
+ activation.ledger.beginOperational(COLLECTOR_WAIT_TOOL, toolCallId);
280
+ const details = await activation.ledger.wait(params, activation.clock, signal);
281
+ activation.ledger.completeOperational(toolCallId);
282
+ return {
283
+ content: [{
284
+ type: "text",
285
+ text: `已等待 ${String(details.effectiveMs)}ms`,
286
+ }],
287
+ details,
288
+ };
289
+ }
290
+ catch (error) {
291
+ hostActions.failInfrastructure(error, ctx, toolCallId);
292
+ }
293
+ },
294
+ });
295
+ pi.registerTool({
296
+ name: COLLECTOR_OUTPUT_TOOL,
297
+ label: "通进司输出",
298
+ description: "观察完成后提交;回执由 runtime 组装。正常完工提交空对象 {}(如需报 finding,填 findings 指针数组);仅在基础设施真实失败时才可填 infrastructureFailure,无失败时必须省略该字段。",
299
+ promptSnippet: "提交通进司回执",
300
+ // #641 chain②: the seat owns the normal-completion decision. The probe
301
+ // runs the exact receipt assembly (validation only, no accept side
302
+ // effects); success ⇒ machine-verified normal completion ⇒ bounce.
303
+ bounceInfrastructureDeclaration(params) {
304
+ if (activation === undefined)
305
+ return undefined;
306
+ try {
307
+ buildCollectorReceipt(activation.ledger, params, activation.clock);
308
+ }
309
+ catch {
310
+ return undefined;
311
+ }
312
+ return new CollectorNormalCompletionDeclarationError();
313
+ },
314
+ parameters: outputSchema,
315
+ async execute(toolCallId, params, _signal, _onUpdate, ctx) {
316
+ if (activation === undefined) {
317
+ throw new Error("通进司未激活");
318
+ }
319
+ try {
320
+ activation.ledger.beginOperational(COLLECTOR_OUTPUT_TOOL, toolCallId);
321
+ const receipt = buildCollectorReceipt(activation.ledger, params, activation.clock);
322
+ activation.ledger.recordOutputCandidate();
323
+ const acceptedDetails = receipt;
324
+ return {
325
+ content: [{
326
+ type: "text",
327
+ text: COLLECTOR_ACCEPTED_TEXT,
328
+ }],
329
+ details: acceptedDetails,
330
+ terminate: true,
331
+ };
332
+ }
333
+ catch (error) {
334
+ // Output validation errors are model-visible rejections when non-fatal.
335
+ if (error instanceof Error &&
336
+ error.collectorFatal === true) {
337
+ hostActions.failInfrastructure(error, ctx, toolCallId);
338
+ }
339
+ throw error;
340
+ }
341
+ finally {
342
+ activation.ledger.completeOperational(toolCallId);
343
+ }
344
+ },
345
+ });
346
+ };
347
+ return {
348
+ async activate(ctx, event) {
349
+ activation = undefined;
350
+ ensureLifecycle();
351
+ if (ctx.mode !== "print" && ctx.mode !== "json") {
352
+ throw new Error(`Collector supports only print or json mode (got ${ctx.mode})`);
353
+ }
354
+ if (event.reason === "fork" ||
355
+ event.reason === "reload") {
356
+ throw new Error(`Collector does not support session_start reason ${event.reason}`);
357
+ }
358
+ const soul = (await dependencies.loadSoul()).trim();
359
+ if (soul.length === 0)
360
+ throw new Error("Collector soul is empty");
361
+ const repoFlag = pi.getFlag("ak-collector-repo");
362
+ const prFlag = pi.getFlag("ak-collector-pr");
363
+ const requestManifestFlag = pi.getFlag("ak-collector-request-manifest");
364
+ if (typeof repoFlag !== "string" || repoFlag.trim().length === 0) {
365
+ throw new Error("Collector requires --ak-collector-repo");
366
+ }
367
+ if (typeof prFlag !== "string" && typeof prFlag !== "number") {
368
+ throw new Error("Collector requires --ak-collector-pr");
369
+ }
370
+ const repository = parseCollectorRepository(repoFlag);
371
+ const prNumber = parseCollectorPrNumber(prFlag);
372
+ const manifest = typeof requestManifestFlag === "string" && requestManifestFlag.trim().length > 0
373
+ ? await loadCollectorManifest(requestManifestFlag)
374
+ : emptyCollectorManifest();
375
+ // Detectable ambient command surface (skills/templates) when exposed.
376
+ const commands = pi.getCommands?.() ?? [];
377
+ const ambientCommands = commands.filter((command) => {
378
+ const name = command.name.toLowerCase();
379
+ return (name.includes("skill") ||
380
+ name.includes("prompt") ||
381
+ name.startsWith("template"));
382
+ });
383
+ if (ambientCommands.length > 0) {
384
+ throw new Error(`Collector detected ambient instruction commands: ${ambientCommands.map((c) => c.name).join(", ")}`);
385
+ }
386
+ // Fail closed if a required name is already occupied before Collector registers.
387
+ const preExisting = pi.getAllTools();
388
+ for (const required of COLLECTOR_REQUIRED_TOOLS) {
389
+ const prior = preExisting.filter((tool) => tool.name === required);
390
+ if (prior.length > 0) {
391
+ throw new Error(`Collector required tool name collision: ${required}`);
392
+ }
393
+ }
394
+ registerTools();
395
+ const allTools = pi.getAllTools();
396
+ for (const required of COLLECTOR_REQUIRED_TOOLS) {
397
+ const matches = allTools.filter((tool) => tool.name === required);
398
+ if (matches.length === 0) {
399
+ throw new Error(`Collector required tool missing: ${required}`);
400
+ }
401
+ if (matches.length > 1) {
402
+ throw new Error(`Collector required tool name collision: ${required}`);
403
+ }
404
+ const tool = matches[0];
405
+ if (dependencies.packageExtensionPath !== undefined &&
406
+ tool.sourceInfo?.path !== undefined &&
407
+ tool.sourceInfo.path !== dependencies.packageExtensionPath &&
408
+ !tool.sourceInfo.path.includes("role-runtime")) {
409
+ throw new Error(`Collector required tool ${required} is overridden by ${tool.sourceInfo.path}`);
410
+ }
411
+ }
412
+ pi.setActiveTools([...COLLECTOR_REQUIRED_TOOLS]);
413
+ const active = new Set(pi.getActiveTools());
414
+ for (const required of COLLECTOR_REQUIRED_TOOLS) {
415
+ if (!active.has(required)) {
416
+ throw new Error(`Collector failed to activate required tool ${required}`);
417
+ }
418
+ }
419
+ for (const name of active) {
420
+ if (!COLLECTOR_REQUIRED_TOOLS.includes(name)) {
421
+ throw new Error(`Collector active tool surface includes unexpected ${name}`);
422
+ }
423
+ }
424
+ const clock = dependencies.createClock?.() ?? createSystemCollectorClock();
425
+ const transport = dependencies.createTransport();
426
+ const ledger = dependencies.createLedger({ repository, prNumber, manifest }, clock, ctx);
427
+ if (ledger.activationRecorded) {
428
+ firstDispatchDone = true;
429
+ }
430
+ activation = {
431
+ soul,
432
+ repository,
433
+ prNumber,
434
+ manifest,
435
+ ledger,
436
+ transport,
437
+ clock,
438
+ };
439
+ },
440
+ };
441
+ }
@@ -1,19 +1,5 @@
1
1
  import { Type } from "typebox";
2
2
  import { auditorRunDirectory } from "./auditor-dossier-tool.js";
3
- import { retainedShapeUnreadable } from "./shape-unreadable-failure.js";
4
- class ComplianceCandidateUnreadableError extends Error {
5
- observation;
6
- candidate;
7
- usage;
8
- constructor(observation, candidate, usage) {
9
- const detail = observation.kind === "non-object-arguments" ? `${observation.kind}:${observation.type}` : observation.kind === "object-status-unreadable" ? `${observation.kind}:${observation.status}` : observation.kind === "missing-subject" ? `${observation.kind}:${observation.subject}` : observation.kind;
10
- super(`Compliance candidate unreadable: ${detail}`);
11
- this.name = "ComplianceCandidateUnreadableError";
12
- this.observation = observation;
13
- this.candidate = candidate;
14
- if (usage !== void 0) this.usage = usage;
15
- }
16
- }
17
3
  const AUDITOR_DOSSIER_PROMPT = "\u672C run \u5377\u5B97\u5DF2\u5C31\u7EEA\u3002";
18
4
  const nonblank = Type.String({ minLength: 1, pattern: "\\S" });
19
5
  const decisionGateSchema = Type.Object({ question: nonblank, options: Type.Array(nonblank, { minItems: 1 }) }, { additionalProperties: false });
@@ -51,45 +37,16 @@ function tryReadComplianceCandidate(arguments_, usage) {
51
37
  function readComplianceCandidate(arguments_, usage) {
52
38
  const projected = tryReadComplianceCandidate(arguments_, usage);
53
39
  if (projected !== void 0) return projected;
54
- if (typeof arguments_ !== "object" || arguments_ === null || Array.isArray(arguments_)) {
55
- throw new ComplianceCandidateUnreadableError(
56
- { kind: "non-object-arguments", type: arguments_ === null ? "null" : Array.isArray(arguments_) ? "array" : typeof arguments_ },
57
- arguments_,
58
- usage
59
- );
60
- }
61
- const status = arguments_.status;
62
- throw new ComplianceCandidateUnreadableError(
63
- { kind: "object-status-unreadable", status: status === void 0 ? "missing" : "unknown" },
64
- arguments_,
65
- usage
66
- );
40
+ return {
41
+ status: "received",
42
+ reply: arguments_,
43
+ ...usage === void 0 ? {} : { usage }
44
+ };
67
45
  }
68
46
  async function usageFromSummonedSession(summoned) {
69
47
  const { usageFromPublicSummon } = await import("./session-assistant-usage.js");
70
48
  return usageFromPublicSummon(summoned);
71
49
  }
72
- function observationFromUnreadableCandidate(candidate) {
73
- if (typeof candidate !== "object" || candidate === null || Array.isArray(candidate)) {
74
- return {
75
- kind: "non-object-arguments",
76
- type: candidate === null ? "null" : Array.isArray(candidate) ? "array" : typeof candidate
77
- };
78
- }
79
- const status = candidate.status;
80
- return {
81
- kind: "object-status-unreadable",
82
- status: status === void 0 ? "missing" : "unknown"
83
- };
84
- }
85
- function unreadableDecision(candidate, usage) {
86
- return {
87
- status: "unreadable",
88
- observation: observationFromUnreadableCandidate(candidate),
89
- candidate,
90
- ...usage === void 0 ? {} : { usage }
91
- };
92
- }
93
50
  async function projectAuditorTerminal(summoned) {
94
51
  const outcome = summoned.terminal?.roleOutcome;
95
52
  if (outcome === void 0) {
@@ -105,10 +62,6 @@ async function projectAuditorTerminal(summoned) {
105
62
  };
106
63
  }
107
64
  if (outcome.kind === "failure") {
108
- const shape = retainedShapeUnreadable(outcome.decisiveFacts);
109
- if (shape !== void 0) {
110
- return unreadableDecision(shape.candidate, usage);
111
- }
112
65
  throw new Error(outcome.diagnostic);
113
66
  }
114
67
  if (outcome.kind === "accepted") {
@@ -116,11 +69,13 @@ async function projectAuditorTerminal(summoned) {
116
69
  status: outcome.status,
117
70
  ...outcome.decisiveFacts
118
71
  };
119
- const projected = tryReadComplianceCandidate(candidate, usage);
120
- if (projected !== void 0) return projected;
121
- return unreadableDecision(candidate, usage);
72
+ return readComplianceCandidate(candidate, usage);
122
73
  }
123
- throw new Error("Auditor public summon returned unusable terminal kind");
74
+ return {
75
+ status: "received",
76
+ reply: outcome,
77
+ ...usage === void 0 ? {} : { usage }
78
+ };
124
79
  }
125
80
  async function runComplianceAudit(options) {
126
81
  const runDirectory = options.runDirectory ?? auditorRunDirectory(options.context);
@@ -154,7 +109,6 @@ export {
154
109
  AUDITOR_DOSSIER_PROMPT,
155
110
  AUDITOR_PARENT_ATTEMPT_BINDING_ENTRY_TYPE,
156
111
  COMPLIANCE_RESPONSE_ENTRY_TYPE,
157
- ComplianceCandidateUnreadableError,
158
112
  ComplianceResponseRetentionError,
159
113
  complianceDecisionSchema,
160
114
  readComplianceCandidate,
@@ -0,0 +1,28 @@
1
+ import { Type } from "typebox";
2
+ import { stringEnum } from "./host-contracts.js";
3
+ import { withInfrastructureFailureDeclaration } from "./package-contracts/terminating-infrastructure.js";
4
+ import { COUNTERSIGN_OUTPUT_TOOL_NAME, validateRecordedCountersignOutput, } from "./countersign-contracts.js";
5
+ export { COUNTERSIGN_ACCEPTED_TEXT, COUNTERSIGN_OUTPUT_TOOL_NAME } from "./countersign-contracts.js";
6
+ /** 给事中票庭审读五问的交卷形状(ADR 0074);形状指引,非 schema 闸。 */
7
+ export const countersignVerdictSchema = withInfrastructureFailureDeclaration(Type.Object({
8
+ countersignStatus: stringEnum(["converged", "continue", "escalate"], { description: "converged | continue | escalate" }),
9
+ fix: Type.Optional(Type.Object({ summary: Type.String({ minLength: 1, description: "退回摘要" }) }, { additionalProperties: false, description: "退回说明" })),
10
+ note: Type.Optional(Type.String({ minLength: 1, description: "附注" })),
11
+ evidence: Type.Optional(Type.Unknown({ description: "留存证据" })),
12
+ decisionGate: Type.Optional(Type.Object({
13
+ question: Type.String({ minLength: 1 }),
14
+ options: Type.Array(Type.String({ minLength: 1 }), { minItems: 1 }),
15
+ }, { additionalProperties: false, description: "需陛下处置的问题与选项" })),
16
+ }, { additionalProperties: true }));
17
+ countersignVerdictSchema.required = [];
18
+ /**
19
+ * 决定工具规格。生命周期装配(注册、activate、prompt 注入、singleton 检查、
20
+ * terminate)归注册信封 owner——src/role-runtime.ts(ADR 0018 / #572 R2 判词)。
21
+ */
22
+ export const COUNTERSIGN_TOOL_SPEC = {
23
+ name: COUNTERSIGN_OUTPUT_TOOL_NAME,
24
+ label: "给事中输出",
25
+ description: "给事中决议。",
26
+ promptSnippet: "给事中决议",
27
+ parameters: countersignVerdictSchema,
28
+ };
@@ -58,15 +58,3 @@ export function projectDiaristSelections(value) {
58
58
  }
59
59
  return out;
60
60
  }
61
- /** Machine-facing facts from an accepted receipt. Submitted rows retained as-is. */
62
- export function diaristDecisiveFacts(output) {
63
- const facts = { status: output.status };
64
- const selections = output.selections;
65
- if (Array.isArray(selections))
66
- facts.selections = selections;
67
- // Mechanical sitian facts recorded by the envelope at accept time.
68
- const sitian = output.sitian;
69
- if (sitian !== undefined)
70
- facts.sitian = sitian;
71
- return facts;
72
- }
@@ -0,0 +1,29 @@
1
+ import { Type } from "typebox";
2
+ import { openToolObject } from "./open-tool-schema.js";
3
+ import { withInfrastructureFailureDeclaration } from "./package-contracts/terminating-infrastructure.js";
4
+ import { DIARIST_OUTPUT_TOOL_NAME, validateRecordedDiaristOutput, } from "./diarist-contracts.js";
5
+ export { DIARIST_ACCEPTED_TEXT, DIARIST_OUTPUT_TOOL_NAME, } from "./diarist-contracts.js";
6
+ export { validateRecordedDiaristOutput };
7
+ /** 起居郎交卷形状;形状指引,非 schema 闸。 */
8
+ export const diaristOutputSchema = withInfrastructureFailureDeclaration(openToolObject(Type.Object({
9
+ status: Type.Unknown({
10
+ description: "completed — 形状指引,非 schema 闸",
11
+ }),
12
+ selections: Type.Array(Type.Object({
13
+ candidateIndex: Type.Number({ description: "候选目录中的整块序号" }),
14
+ quotes: Type.Array(Type.String(), {
15
+ description: "该块 transcript 内的连续原文;机械反验",
16
+ }),
17
+ note: Type.Optional(Type.String({ description: "该材料与本案的关系(人读)" })),
18
+ }, { additionalProperties: true, description: "一条入录选择" }), { description: "入录选择;空列表合法完局" }),
19
+ })));
20
+ /**
21
+ * 决定工具规格。生命周期装配归注册信封 owner——src/role-runtime.ts(ADR 0018)。
22
+ */
23
+ export const DIARIST_TOOL_SPEC = {
24
+ name: DIARIST_OUTPUT_TOOL_NAME,
25
+ label: "起居郎输出",
26
+ description: "起居郎入录选择。",
27
+ promptSnippet: "起居郎入录选择",
28
+ parameters: diaristOutputSchema,
29
+ };
@@ -6,7 +6,6 @@ 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_ACCEPTED_AUDIT_UNREADABLE_TEXT = "\u592A\u533B\u7F72\u56DE\u6267\u5DF2\u63A5\u53D7\uFF1B\u5BA1\u8BA1\u5F62\u72B6\u4E0D\u53EF\u8BFB";
10
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";
11
10
  const DOCTOR_TARGET_KINDS = ["law", "gate", "template", "station", "seat"];
12
11
  const nonblank = Type.String({ minLength: 1, pattern: "\\S" });
@@ -185,7 +184,6 @@ function validateDoctorOutput(value, patient, store) {
185
184
  }
186
185
  export {
187
186
  DOCTOR_ACCEPTED_AUDIT_NO_RECEIPT_TEXT,
188
- DOCTOR_ACCEPTED_AUDIT_UNREADABLE_TEXT,
189
187
  DOCTOR_ACCEPTED_TEXT,
190
188
  DOCTOR_EVIDENCE_TOOL_NAME,
191
189
  DOCTOR_OUTPUT_TOOL_DESCRIPTION,