@akagilnc/pi-workflow-roles 0.1.5241 → 0.1.5245

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 (39) hide show
  1. package/README.md +2 -3
  2. package/README.zh-CN.md +2 -3
  3. package/dist/acp-host/production-host.js +442 -3070
  4. package/dist/collector-config.js +0 -1
  5. package/dist/headless-host/production-host.js +443 -3071
  6. package/dist/migrate-book-topology.js +40 -107
  7. package/dist/package-contracts/collector-output.js +1 -90
  8. package/dist/package-contracts/terminating-tools.js +2 -2
  9. package/dist/packaged-role-registry.js +8 -11
  10. package/dist/public-cli/invocation.js +2 -22
  11. package/dist/public-cli/main.js +252 -698
  12. package/dist/public-cli/option-definitions.js +4 -19
  13. package/dist/public-cli/settlement.js +2 -79
  14. package/package.json +1 -1
  15. package/resources/collector-bot-handbook.md +4 -2
  16. package/src/collector-config.ts +0 -1
  17. package/src/collector-role.ts +40 -535
  18. package/src/collector-tool-schemas.ts +7 -117
  19. package/src/gh-api-runner.ts +102 -0
  20. package/src/package-contracts/collector-output.ts +15 -174
  21. package/src/package-contracts/terminating-tools.ts +0 -2
  22. package/src/packaged-role-registry.ts +7 -10
  23. package/src/public-cli/invocation.ts +3 -27
  24. package/src/public-cli/option-definitions.ts +4 -19
  25. package/src/public-cli/settlement.ts +3 -102
  26. package/src/role-runtime-dependencies.ts +0 -4
  27. package/src/role-runtime.ts +16 -98
  28. package/src/ticket-snapshot.ts +1 -1
  29. package/dist/collector-evidence.js +0 -319
  30. package/dist/collector-github.js +0 -725
  31. package/dist/collector-identity.js +0 -92
  32. package/dist/collector-ledger.js +0 -888
  33. package/dist/collector-target.js +0 -169
  34. package/src/collector-evidence.ts +0 -466
  35. package/src/collector-github.ts +0 -1032
  36. package/src/collector-handbook.ts +0 -194
  37. package/src/collector-identity.ts +0 -151
  38. package/src/collector-ledger.ts +0 -1186
  39. package/src/collector-target.ts +0 -207
@@ -13,683 +13,10 @@ var __export = (target, all) => {
13
13
  __defProp(target, name, { get: all[name], enumerable: true });
14
14
  };
15
15
 
16
- // src/collector-config.ts
17
- import { createHash } from "node:crypto";
18
- import { readFile } from "node:fs/promises";
19
- function fail(message, cause) {
20
- throw new Error(message, cause === void 0 ? void 0 : { cause });
21
- }
22
- function conservativeAscii(input) {
23
- for (let i = 0; i < input.length; i += 1) {
24
- const code = input.charCodeAt(i);
25
- if (code <= 31 || code === 127 || code > 127) return false;
26
- }
27
- return true;
28
- }
29
- function parseCollectorRepository(raw) {
30
- if (typeof raw !== "string" || raw.trim() !== raw || raw.length === 0) fail("Collector repository must be a string owner/repo");
31
- if (!conservativeAscii(raw) || raw.includes("://") || /[?#@%\\ ]/.test(raw)) fail("Collector repository rejects URL syntax and non-identity bytes");
32
- const parts = raw.split("/");
33
- if (parts.length !== 2) fail("Collector repository must contain exactly one '/' separating owner and repo");
34
- const [ownerDisplay, repoDisplay] = parts;
35
- if (!COLLECTOR_OWNER_PATTERN.test(ownerDisplay) || !COLLECTOR_REPO_PATTERN.test(repoDisplay)) fail("Collector repository does not match the conservative owner/repo grammar");
36
- const owner = ownerDisplay.toLowerCase();
37
- const repo = repoDisplay.toLowerCase();
38
- return { display: raw, canonical: `${owner}/${repo}`, owner, repo };
39
- }
40
- function parseCollectorPrNumber(raw) {
41
- if (typeof raw === "string" && !/^[1-9][0-9]*$/.test(raw)) fail("Collector pull request number must be a positive safe integer string");
42
- if (typeof raw !== "string" && typeof raw !== "number") fail("Collector pull request number is required");
43
- const value = Number(raw);
44
- if (!Number.isSafeInteger(value) || value < 1) fail("Collector pull request number must be a positive safe integer");
45
- return value;
46
- }
47
- function record(value) {
48
- return typeof value === "object" && value !== null && !Array.isArray(value);
49
- }
50
- function canonicalManifest(requests) {
51
- return `${JSON.stringify({ requests: requests.map((request) => ({ id: request.id, body: request.requestBody })) })}
52
- `;
53
- }
54
- function emptyCollectorManifest() {
55
- const canonicalJson2 = canonicalManifest([]);
56
- return { requests: [], canonicalJson: canonicalJson2, digest: createHash("sha256").update(canonicalJson2).digest("hex") };
57
- }
58
- async function loadCollectorManifest(path) {
59
- let bytes;
60
- try {
61
- bytes = await readFile(path);
62
- } catch (error) {
63
- fail(`Collector request manifest is unreadable at ${path}`, error);
64
- }
65
- let parsed;
66
- try {
67
- parsed = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
68
- } catch (error) {
69
- fail("Collector request manifest must be UTF-8 JSON", error);
70
- }
71
- if (!record(parsed)) fail("Collector request manifest must be an object");
72
- const rawRequests = parsed.requests ?? [];
73
- if (!Array.isArray(rawRequests)) fail("Collector request manifest requests must be an array");
74
- const requests = [];
75
- const ids = /* @__PURE__ */ new Set();
76
- for (const [index, item] of rawRequests.entries()) {
77
- if (!record(item) || typeof item.id !== "string" || item.id.length === 0 || typeof item.body !== "string" || item.body.trim() === "") fail(`Collector request manifest requests[${index}] is invalid`);
78
- if (ids.has(item.id)) fail(`Collector request manifest has duplicate request id "${item.id}"`);
79
- ids.add(item.id);
80
- requests.push({ id: item.id, requestBody: item.body });
81
- }
82
- const canonicalJson2 = canonicalManifest(requests);
83
- return { requests, canonicalJson: canonicalJson2, digest: createHash("sha256").update(canonicalJson2).digest("hex"), sourcePath: path };
84
- }
85
- var COLLECTOR_OWNER_PATTERN, COLLECTOR_REPO_PATTERN;
86
- var init_collector_config = __esm({
87
- "src/collector-config.ts"() {
88
- "use strict";
89
- COLLECTOR_OWNER_PATTERN = /^[A-Za-z0-9](?:[A-Za-z0-9-]{0,37}[A-Za-z0-9])?$/;
90
- COLLECTOR_REPO_PATTERN = /^[A-Za-z0-9](?:[A-Za-z0-9._-]{0,98}[A-Za-z0-9])?$/;
91
- }
92
- });
93
-
94
- // src/collector-github.ts
95
- import { spawn } from "node:child_process";
96
- import { createHash as createHash2 } from "node:crypto";
97
- function isRecord(value) {
98
- return typeof value === "object" && value !== null && !Array.isArray(value);
99
- }
100
- function requireString(value, label) {
101
- if (typeof value !== "string") {
102
- throw new Error(`GitHub payload missing string ${label}`);
103
- }
104
- return value;
105
- }
106
- function requireNumber(value, label) {
107
- if (typeof value !== "number" || !Number.isFinite(value)) {
108
- throw new Error(`GitHub payload missing number ${label}`);
109
- }
110
- return value;
111
- }
112
- function optionalString(value) {
113
- return typeof value === "string" ? value : null;
114
- }
115
- function parseLinkNext(linkHeader) {
116
- if (linkHeader === void 0 || linkHeader.length === 0) return void 0;
117
- for (const part of linkHeader.split(",")) {
118
- const match = part.trim().match(/^<([^>]+)>\s*;\s*rel="next"$/i);
119
- if (match?.[1]) return match[1];
120
- }
121
- return void 0;
122
- }
123
- function parseJson(text, label) {
124
- try {
125
- return JSON.parse(text);
126
- } catch (error) {
127
- throw new Error(`GitHub ${label} returned malformed JSON`, { cause: error });
128
- }
129
- }
130
- function parsePullRequestNumberList(raw, label) {
131
- if (!Array.isArray(raw)) {
132
- throw new Error(`GitHub ${label} payload is not a list`);
133
- }
134
- const numbers = [];
135
- for (const item of raw) {
136
- if (!isRecord(item)) {
137
- throw new Error(`GitHub ${label} payload contains a non-object pull request entry`);
138
- }
139
- try {
140
- numbers.push(parseCollectorPrNumber(item["number"]));
141
- } catch (error) {
142
- throw new Error(`GitHub ${label} payload contains an invalid pull request number`, {
143
- cause: error
144
- });
145
- }
146
- }
147
- return numbers;
148
- }
149
- async function listPullRequestNumbersByHead(runner, input) {
150
- const head = `${input.headOwner}:${input.headRef}`;
151
- const path = `/repos/${input.owner}/${input.repo}/pulls?head=${encodeURIComponent(head)}&state=all&per_page=100`;
152
- const response = await runner(
153
- ["api", "--hostname", "github.com", "--include", "-X", "GET", path],
154
- input.signal === void 0 ? {} : { signal: input.signal }
155
- );
156
- if (response.status < 200 || response.status >= 300) {
157
- throw new Error(`GitHub ${path} failed with HTTP ${response.status}`, {
158
- cause: {
159
- endpoint: path,
160
- status: response.status,
161
- headers: response.headers,
162
- body: response.bodyText
163
- }
164
- });
165
- }
166
- return parsePullRequestNumberList(parseJson(response.bodyText, path), path);
167
- }
168
- async function listPullRequestNumbersByCommit(runner, input) {
169
- const path = `/repos/${input.owner}/${input.repo}/commits/${encodeURIComponent(input.commitSha)}/pulls`;
170
- const response = await runner(
171
- ["api", "--hostname", "github.com", "--include", "-X", "GET", path],
172
- input.signal === void 0 ? {} : { signal: input.signal }
173
- );
174
- if (response.status < 200 || response.status >= 300) {
175
- throw new Error(`GitHub ${path} failed with HTTP ${response.status}`, {
176
- cause: {
177
- endpoint: path,
178
- status: response.status,
179
- headers: response.headers,
180
- body: response.bodyText
181
- }
182
- });
183
- }
184
- return parsePullRequestNumberList(parseJson(response.bodyText, path), path);
185
- }
186
- async function listPullRequestNumbersByTicket(runner, input) {
187
- const issuePath = `/repos/${input.owner}/${input.repo}/issues/${input.ticketNumber}`;
188
- const issueResponse = await runner(
189
- ["api", "--hostname", "github.com", "--include", "-X", "GET", issuePath],
190
- input.signal === void 0 ? {} : { signal: input.signal }
191
- );
192
- if (issueResponse.status === 404) return [];
193
- if (issueResponse.status < 200 || issueResponse.status >= 300) {
194
- throw new Error(`GitHub ${issuePath} failed with HTTP ${issueResponse.status}`, {
195
- cause: {
196
- endpoint: issuePath,
197
- status: issueResponse.status,
198
- headers: issueResponse.headers,
199
- body: issueResponse.bodyText
200
- }
201
- });
202
- }
203
- const issueRaw = parseJson(issueResponse.bodyText, issuePath);
204
- if (!isRecord(issueRaw)) {
205
- throw new Error(`GitHub ${issuePath} payload is not an object`);
206
- }
207
- if (Object.hasOwn(issueRaw, "pull_request")) {
208
- return [parseCollectorPrNumber(issueRaw["number"] ?? input.ticketNumber)];
209
- }
210
- const query = `query($owner: String!, $repo: String!, $number: Int!) {
211
- repository(owner: $owner, name: $repo) {
212
- issue(number: $number) {
213
- closedByPullRequestsReferences(first: 50) { nodes { number } }
214
- timelineItems(first: 100, itemTypes: [CROSS_REFERENCED_EVENT, CONNECTED_EVENT]) {
215
- nodes {
216
- __typename
217
- ... on CrossReferencedEvent {
218
- source { ... on PullRequest { number } }
219
- }
220
- ... on ConnectedEvent {
221
- subject { ... on PullRequest { number } }
222
- }
223
- }
224
- }
225
- }
226
- }
227
- }`;
228
- const args = [
229
- "api",
230
- "graphql",
231
- "--hostname",
232
- "github.com",
233
- "--include",
234
- "-f",
235
- `query=${query}`,
236
- "-f",
237
- `owner=${input.owner}`,
238
- "-f",
239
- `repo=${input.repo}`,
240
- "-F",
241
- `number=${input.ticketNumber}`
242
- ];
243
- const gqlResponse = await runner(
244
- args,
245
- input.signal === void 0 ? {} : { signal: input.signal }
246
- );
247
- if (gqlResponse.status < 200 || gqlResponse.status >= 300) {
248
- throw new Error(`GitHub GraphQL issue\u2192PR failed with HTTP ${gqlResponse.status}`, {
249
- cause: {
250
- endpoint: "graphql",
251
- status: gqlResponse.status,
252
- headers: gqlResponse.headers,
253
- body: gqlResponse.bodyText
254
- }
255
- });
256
- }
257
- let payload;
258
- try {
259
- payload = JSON.parse(gqlResponse.bodyText);
260
- } catch (error) {
261
- throw new Error("GitHub GraphQL issue\u2192PR returned malformed JSON", { cause: error });
262
- }
263
- if (!isRecord(payload)) {
264
- throw new Error("GitHub GraphQL issue\u2192PR payload is not an object");
265
- }
266
- if (payload.errors !== void 0) {
267
- throw new Error(`GitHub GraphQL issue\u2192PR errors: ${JSON.stringify(payload.errors).slice(0, 600)}`, {
268
- cause: { body: gqlResponse.bodyText, errors: payload.errors }
269
- });
270
- }
271
- const data = payload.data;
272
- if (!isRecord(data)) return [];
273
- const repository = data["repository"];
274
- if (!isRecord(repository)) return [];
275
- const issue = repository["issue"];
276
- if (!isRecord(issue)) return [];
277
- const numbers = [];
278
- const closedBy = issue["closedByPullRequestsReferences"];
279
- if (isRecord(closedBy) && Array.isArray(closedBy["nodes"])) {
280
- for (const node of closedBy["nodes"]) {
281
- if (isRecord(node) && typeof node["number"] === "number") {
282
- numbers.push(parseCollectorPrNumber(node["number"]));
283
- }
284
- }
285
- }
286
- const timeline = issue["timelineItems"];
287
- if (isRecord(timeline) && Array.isArray(timeline["nodes"])) {
288
- for (const node of timeline["nodes"]) {
289
- if (!isRecord(node)) continue;
290
- const source = node["source"];
291
- if (isRecord(source) && typeof source["number"] === "number") {
292
- numbers.push(parseCollectorPrNumber(source["number"]));
293
- }
294
- const subject = node["subject"];
295
- if (isRecord(subject) && typeof subject["number"] === "number") {
296
- numbers.push(parseCollectorPrNumber(subject["number"]));
297
- }
298
- }
299
- }
300
- return [...new Set(numbers)];
301
- }
302
- function commentFailureCause(error) {
303
- return {
304
- name: error instanceof Error ? error.name : typeof error,
305
- message: error instanceof Error ? error.message : String(error),
306
- evidenceId: `github-comment-failure-${++commentFailureEvidence}`
307
- };
308
- }
309
- function requireUserLogin(raw) {
310
- if (!isRecord(raw) || typeof raw["login"] !== "string") {
311
- throw new Error("GitHub payload missing user.login");
312
- }
313
- return raw["login"];
314
- }
315
- function optionalUserLogin(raw) {
316
- if (raw === null) return null;
317
- if (!isRecord(raw) || typeof raw["login"] !== "string") {
318
- throw new Error("GitHub payload missing user.login");
319
- }
320
- return raw["login"];
321
- }
322
- function machineIdentity(raw) {
323
- const user = raw["user"];
324
- if (!isRecord(user) || typeof user["type"] !== "string" || typeof user["id"] !== "number") {
325
- return null;
326
- }
327
- const app = raw["performed_via_github_app"];
328
- const appId = isRecord(app) && typeof app["id"] === "number" ? app["id"] : void 0;
329
- return {
330
- userType: user["type"],
331
- userId: user["id"],
332
- ...appId === void 0 ? {} : { appId }
333
- };
334
- }
335
- function normalizePullRequest(raw) {
336
- if (!isRecord(raw)) throw new Error("GitHub pull request payload must be an object");
337
- const head = raw["head"];
338
- if (!isRecord(head) || typeof head["sha"] !== "string" || head["sha"].length === 0) {
339
- throw new Error("GitHub pull request payload missing head.sha");
340
- }
341
- const number = requireNumber(raw["number"], "number");
342
- const mergedFlag = raw["merged"] === true || typeof raw["merged_at"] === "string" && raw["merged_at"].length > 0;
343
- const rawState = requireString(raw["state"], "state").toUpperCase();
344
- const state = mergedFlag ? "MERGED" : rawState;
345
- const htmlUrl = typeof raw["html_url"] === "string" ? raw["html_url"] : `https://github.com/unknown/unknown/pull/${number}`;
346
- return {
347
- number,
348
- state,
349
- headOid: head["sha"],
350
- ...typeof raw["created_at"] === "string" ? { createdAt: raw["created_at"] } : {},
351
- ...typeof raw["updated_at"] === "string" ? { updatedAt: raw["updated_at"] } : {},
352
- url: htmlUrl,
353
- raw
354
- };
355
- }
356
- function normalizePullRequestReaction(raw) {
357
- if (!isRecord(raw)) throw new Error("GitHub reaction payload must be an object");
358
- return {
359
- id: requireNumber(raw["id"], "reaction.id"),
360
- userLogin: optionalUserLogin(raw["user"]),
361
- machineIdentity: machineIdentity(raw),
362
- content: requireString(raw["content"], "reaction.content"),
363
- createdAt: requireString(raw["created_at"], "reaction.created_at"),
364
- raw
365
- };
366
- }
367
- function normalizeReview(raw) {
368
- if (!isRecord(raw)) throw new Error("GitHub review payload must be an object");
369
- return {
370
- id: requireNumber(raw["id"], "review.id"),
371
- ...typeof raw["node_id"] === "string" ? { nodeId: raw["node_id"] } : {},
372
- userLogin: optionalUserLogin(raw["user"]),
373
- machineIdentity: machineIdentity(raw),
374
- state: requireString(raw["state"], "review.state").toUpperCase(),
375
- body: typeof raw["body"] === "string" ? raw["body"] : "",
376
- commitId: optionalString(raw["commit_id"]),
377
- submittedAt: optionalString(raw["submitted_at"]),
378
- htmlUrl: typeof raw["html_url"] === "string" ? raw["html_url"] : "",
379
- raw
380
- };
381
- }
382
- function normalizeIssueComment(raw) {
383
- if (!isRecord(raw)) throw new Error("GitHub issue comment payload must be an object");
384
- return {
385
- id: requireNumber(raw["id"], "comment.id"),
386
- userLogin: optionalUserLogin(raw["user"]),
387
- machineIdentity: machineIdentity(raw),
388
- body: typeof raw["body"] === "string" ? raw["body"] : "",
389
- createdAt: requireString(raw["created_at"], "comment.created_at"),
390
- updatedAt: requireString(raw["updated_at"], "comment.updated_at"),
391
- htmlUrl: typeof raw["html_url"] === "string" ? raw["html_url"] : "",
392
- raw
393
- };
394
- }
395
- function normalizeReviewComment(raw) {
396
- if (!isRecord(raw)) throw new Error("GitHub review comment payload must be an object");
397
- return {
398
- id: requireNumber(raw["id"], "review_comment.id"),
399
- pullRequestReviewId: typeof raw["pull_request_review_id"] === "number" ? raw["pull_request_review_id"] : null,
400
- userLogin: optionalUserLogin(raw["user"]),
401
- machineIdentity: machineIdentity(raw),
402
- body: typeof raw["body"] === "string" ? raw["body"] : "",
403
- path: requireString(raw["path"], "review_comment.path"),
404
- line: typeof raw["line"] === "number" ? raw["line"] : null,
405
- originalLine: typeof raw["original_line"] === "number" ? raw["original_line"] : null,
406
- side: optionalString(raw["side"]),
407
- position: typeof raw["position"] === "number" ? raw["position"] : null,
408
- originalPosition: typeof raw["original_position"] === "number" ? raw["original_position"] : null,
409
- commitId: optionalString(raw["commit_id"]),
410
- originalCommitId: optionalString(raw["original_commit_id"]),
411
- createdAt: requireString(raw["created_at"], "review_comment.created_at"),
412
- updatedAt: requireString(raw["updated_at"], "review_comment.updated_at"),
413
- htmlUrl: typeof raw["html_url"] === "string" ? raw["html_url"] : "",
414
- raw
415
- };
416
- }
417
- function createGhApiRunner(options = {}) {
418
- const spawnImpl = options.spawnImpl ?? spawn;
419
- return async (args, runOptions = {}) => {
420
- return await new Promise((resolve22, reject) => {
421
- const signal = runOptions.signal;
422
- if (signal?.aborted) {
423
- reject(signal.reason ?? new Error("aborted"));
424
- return;
425
- }
426
- const child = spawnImpl("gh", args, {
427
- env: options.env ?? process.env,
428
- stdio: ["pipe", "pipe", "pipe"]
429
- });
430
- let stdout = "";
431
- let stderr = "";
432
- let settled = false;
433
- const settle = (fn) => {
434
- if (settled) return;
435
- settled = true;
436
- if (signal !== void 0) {
437
- signal.removeEventListener("abort", onAbort);
438
- }
439
- fn();
440
- };
441
- const onAbort = () => {
442
- try {
443
- child.kill("SIGTERM");
444
- } catch (error) {
445
- settle(() => reject(error));
446
- return;
447
- }
448
- settle(() => {
449
- reject(signal?.reason ?? new Error("aborted"));
450
- });
451
- };
452
- if (signal !== void 0) {
453
- signal.addEventListener("abort", onAbort, { once: true });
454
- }
455
- child.stdout.setEncoding("utf8").on("data", (chunk) => {
456
- stdout += chunk;
457
- });
458
- child.stderr.setEncoding("utf8").on("data", (chunk) => {
459
- stderr += chunk;
460
- });
461
- child.on("error", (error) => {
462
- settle(() => reject(error));
463
- });
464
- child.stdin.on("error", (error) => {
465
- settle(() => {
466
- if (signal?.aborted) {
467
- reject(signal.reason ?? new Error("aborted"));
468
- return;
469
- }
470
- const err = error instanceof Error ? error : new Error(String(error));
471
- reject(Object.assign(err, { ambiguousGhFailure: true }));
472
- });
473
- });
474
- if (runOptions.stdin !== void 0) {
475
- child.stdin.write(runOptions.stdin);
476
- }
477
- child.stdin.end();
478
- child.on("close", (code, signal2) => {
479
- settle(() => {
480
- const match = stdout.match(/^HTTP\/[\d.]+\s+(\d+)[^\n]*\r?\n([\s\S]*?)\r?\n\r?\n([\s\S]*)$/);
481
- if (match) {
482
- const status = Number(match[1]);
483
- const headerText = match[2] ?? "";
484
- const bodyText = match[3] ?? "";
485
- const headers = {};
486
- for (const line2 of headerText.split(/\r?\n/)) {
487
- const idx = line2.indexOf(":");
488
- if (idx === -1) continue;
489
- const name = line2.slice(0, idx).trim().toLowerCase();
490
- const value = line2.slice(idx + 1).trim();
491
- headers[name] = value;
492
- }
493
- resolve22({ status, headers, bodyText });
494
- return;
495
- }
496
- if (code === 0) {
497
- resolve22({ status: 200, headers: {}, bodyText: stdout });
498
- return;
499
- }
500
- const failure2 = new Error(
501
- `gh api failed without a parseable HTTP response (code=${String(code)}): ${stderr || stdout}`,
502
- { cause: { code, signal: signal2, stderr, stdout } }
503
- );
504
- reject(Object.assign(failure2, { ambiguousGhFailure: true, stderr, stdout, code, signal: signal2 }));
505
- });
506
- });
507
- });
508
- };
509
- }
510
- function createGhCollectorGitHubTransport(runner = createGhApiRunner()) {
511
- const hostnameArgs = ["api", "--hostname", "github.com", "--include"];
512
- async function apiGet(path, signal) {
513
- return await runner(
514
- [...hostnameArgs, "-X", "GET", path],
515
- signal === void 0 ? {} : { signal }
516
- );
517
- }
518
- async function paginate(path, mapItem, options = {}) {
519
- const { signal, retainPage } = options;
520
- const items = [];
521
- const pages = [];
522
- let nextPath = path;
523
- let page = 1;
524
- const seen = /* @__PURE__ */ new Set();
525
- while (nextPath !== void 0) {
526
- if (signal?.aborted) {
527
- throw signal.reason ?? new Error("aborted");
528
- }
529
- if (seen.has(nextPath)) {
530
- throw new Error(`GitHub pagination repeated page: ${nextPath}`);
531
- }
532
- seen.add(nextPath);
533
- const response = await apiGet(nextPath, signal);
534
- const diagnostics = {
535
- path: nextPath,
536
- page,
537
- status: response.status,
538
- itemCount: 0,
539
- ...response.headers["link"] === void 0 ? {} : { linkHeader: response.headers["link"] }
540
- };
541
- if (response.status === 429) {
542
- throw Object.assign(
543
- new Error(`GitHub API rate limited on ${nextPath} (HTTP 429)`),
544
- { githubStatus: 429, page: diagnostics }
545
- );
546
- }
547
- if (response.status < 200 || response.status >= 300) {
548
- throw Object.assign(
549
- new Error(`GitHub API ${nextPath} failed with HTTP ${response.status}`),
550
- { githubStatus: response.status, page: diagnostics }
551
- );
552
- }
553
- const parsed = parseJson(response.bodyText, nextPath);
554
- if (!Array.isArray(parsed)) {
555
- throw new Error(`GitHub API ${nextPath} did not return a JSON array`);
556
- }
557
- diagnostics.itemCount = parsed.length;
558
- pages.push(diagnostics);
559
- const pageItems = parsed.map((entry) => mapItem(entry));
560
- retainPage?.(pageItems);
561
- for (const item of pageItems) items.push(item);
562
- const nextUrl = parseLinkNext(response.headers["link"]);
563
- if (nextUrl === void 0) {
564
- nextPath = void 0;
565
- } else {
566
- if (nextUrl.startsWith("/")) {
567
- nextPath = nextUrl;
568
- } else {
569
- const url = new URL(nextUrl);
570
- if (url.hostname !== "api.github.com" && url.hostname !== "github.com") {
571
- throw new Error(`unexpected pagination host ${url.hostname}`);
572
- }
573
- nextPath = `${url.pathname}${url.search}`;
574
- if (nextPath.startsWith("/api/v3/")) {
575
- nextPath = nextPath.slice("/api/v3".length);
576
- }
577
- }
578
- }
579
- page += 1;
580
- }
581
- return { items, pages };
582
- }
583
- return {
584
- async getAuthenticatedUser(options = {}) {
585
- const response = await apiGet("/user", options.signal);
586
- if (response.status < 200 || response.status >= 300) {
587
- throw new Error(`GitHub /user failed with HTTP ${response.status}`, { cause: { endpoint: "/user", status: response.status, headers: response.headers, body: response.bodyText } });
588
- }
589
- const raw = parseJson(response.bodyText, "/user");
590
- return { login: requireUserLogin(raw).toLowerCase(), raw };
591
- },
592
- async getPullRequest(input) {
593
- const path = `/repos/${input.owner}/${input.repo}/pulls/${input.prNumber}`;
594
- const response = await apiGet(path, input.signal);
595
- if (response.status < 200 || response.status >= 300) {
596
- throw new Error(`GitHub ${path} failed with HTTP ${response.status}`, { cause: { endpoint: path, status: response.status, headers: response.headers, body: response.bodyText } });
597
- }
598
- return normalizePullRequest(parseJson(response.bodyText, path));
599
- },
600
- async listPullRequestReviews(input) {
601
- const path = `/repos/${input.owner}/${input.repo}/pulls/${input.prNumber}/reviews?per_page=100`;
602
- return await paginate(path, normalizeReview, {
603
- ...input.signal === void 0 ? {} : { signal: input.signal },
604
- ...input.retainPage === void 0 ? {} : { retainPage: input.retainPage }
605
- });
606
- },
607
- async listPullRequestReactions(input) {
608
- const path = `/repos/${input.owner}/${input.repo}/issues/${input.prNumber}/reactions?per_page=100`;
609
- return await paginate(path, normalizePullRequestReaction, {
610
- ...input.signal === void 0 ? {} : { signal: input.signal },
611
- ...input.retainPage === void 0 ? {} : { retainPage: input.retainPage }
612
- });
613
- },
614
- async listIssueComments(input) {
615
- const path = `/repos/${input.owner}/${input.repo}/issues/${input.prNumber}/comments?per_page=100`;
616
- return await paginate(path, normalizeIssueComment, {
617
- ...input.signal === void 0 ? {} : { signal: input.signal },
618
- ...input.retainPage === void 0 ? {} : { retainPage: input.retainPage }
619
- });
620
- },
621
- async listReviewComments(input) {
622
- const path = `/repos/${input.owner}/${input.repo}/pulls/${input.prNumber}/comments?per_page=100`;
623
- return await paginate(path, normalizeReviewComment, {
624
- ...input.signal === void 0 ? {} : { signal: input.signal },
625
- ...input.retainPage === void 0 ? {} : { retainPage: input.retainPage }
626
- });
627
- },
628
- async createIssueComment(input) {
629
- const path = `/repos/${input.owner}/${input.repo}/issues/${input.prNumber}/comments`;
630
- try {
631
- const response = await runner(
632
- [...hostnameArgs, "-X", "POST", path, "--input", "-"],
633
- input.signal === void 0 ? { stdin: JSON.stringify({ body: input.body }) } : { stdin: JSON.stringify({ body: input.body }), signal: input.signal }
634
- );
635
- if (response.status >= 200 && response.status < 300) {
636
- try {
637
- return {
638
- kind: "success",
639
- comment: normalizeIssueComment(parseJson(response.bodyText, path))
640
- };
641
- } catch (error) {
642
- const cause = commentFailureCause(error);
643
- return { kind: "ambiguous_loss", diagnostics: cause.message, cause };
644
- }
645
- }
646
- return {
647
- kind: "rejected",
648
- status: response.status,
649
- diagnostics: `HTTP ${response.status}: ${response.bodyText.slice(0, 500)}`
650
- };
651
- } catch (error) {
652
- if (input.signal?.aborted) {
653
- throw error;
654
- }
655
- if (isRecord(error) && error["ambiguousGhFailure"] === true) {
656
- const cause = commentFailureCause(error);
657
- return { kind: "ambiguous_loss", diagnostics: cause.message, cause };
658
- }
659
- if (isRecord(error) && error["name"] === "AbortError") {
660
- throw error;
661
- }
662
- throw error;
663
- }
664
- }
665
- };
666
- }
667
- function buildCollectorRequestMarker(input) {
668
- const prefix = input.manifestDigest.slice(0, 12);
669
- const requestMarkerId = createHash2("sha256").update(input.requestId).digest("hex");
670
- return `<!-- ak-collector:v1 manifest=${prefix} request=${requestMarkerId} head=${input.headOid} -->`;
671
- }
672
- function buildCollectorRequestBody(input) {
673
- const marker = buildCollectorRequestMarker(input);
674
- const body = input.configuredBody.endsWith("\n") ? `${input.configuredBody}${marker}
675
- ` : `${input.configuredBody}
676
- ${marker}
677
- `;
678
- return { body, marker };
679
- }
680
- var commentFailureEvidence;
681
- var init_collector_github = __esm({
682
- "src/collector-github.ts"() {
683
- "use strict";
684
- init_collector_config();
685
- commentFailureEvidence = 0;
686
- }
687
- });
688
-
689
16
  // src/sha256.ts
690
- import { createHash as createHash3 } from "node:crypto";
17
+ import { createHash } from "node:crypto";
691
18
  function sha256Hex(bytes) {
692
- return createHash3("sha256").update(bytes).digest("hex");
19
+ return createHash("sha256").update(bytes).digest("hex");
693
20
  }
694
21
  var init_sha256 = __esm({
695
22
  "src/sha256.ts"() {
@@ -815,1313 +142,32 @@ var init_review_submission = __esm({
815
142
  reason: Type2.Optional(Type2.Unknown({ description: "\u4E0A\u5448\u7406\u7531" })),
816
143
  violations: Type2.Optional(Type2.Unknown({ description: "\u8FDD\u89C4\u6761\u76EE" })),
817
144
  conflicts: Type2.Optional(Type2.Unknown({ description: "\u5F85\u51B3\u51B2\u7A81" })),
818
- fix: Type2.Optional(Type2.Unknown({ description: "continue \u65F6\u7684\u8865\u6551\u8BF4\u660E\uFF1B\u53EF\u5199 summary \u6458\u8981\uFF0C\u5176\u4F59\u5185\u5BB9\u539F\u6837\u7559\u5B58" })),
819
- classes: Type2.Optional(Type2.Unknown({ description: "\u5DF2\u88C1\u51B3 finding \u7C7B\uFF1B\u53EF\u8BF4\u660E name\u3001owner\u3001boundary\u3001disposition\uFF0C\u539F\u6837\u7559\u5B58" })),
820
- note: Type2.Optional(Type2.Unknown({ description: "\u88C1\u51B3\u9644\u6CE8" })),
821
- evidence: Type2.Optional(Type2.Unknown({ description: "\u7559\u5B58\u8BC1\u636E" })),
822
- decisionGate: Type2.Optional(Type2.Unknown({ description: "\u9700\u4EBA\u6743\u5A01\u5904\u7F6E\u7684\u95EE\u9898\u4E0E\u9009\u9879\uFF1B\u53EF\u8BF4\u660E question\u3001options\uFF0C\u539F\u6837\u7559\u5B58" }))
823
- }, { additionalProperties: true })
824
- );
825
- }
826
- });
827
-
828
- // src/package-contracts/judge-output.ts
829
- var JUDGE_OUTPUT_TOOL_NAME;
830
- var init_judge_output = __esm({
831
- "src/package-contracts/judge-output.ts"() {
832
- "use strict";
833
- init_review_submission();
834
- JUDGE_OUTPUT_TOOL_NAME = REVIEW_SUBMISSION_OUTPUT_TOOL_NAME;
835
- }
836
- });
837
-
838
- // src/package-contracts/reviewer-output.ts
839
- var REVIEWER_OUTPUT_TOOL_NAME;
840
- var init_reviewer_output = __esm({
841
- "src/package-contracts/reviewer-output.ts"() {
842
- "use strict";
843
- REVIEWER_OUTPUT_TOOL_NAME = "ak_reviewer_output";
844
- }
845
- });
846
-
847
- // src/collector-evidence.ts
848
- import { createHash as createHash4 } from "node:crypto";
849
- function createSystemCollectorClock() {
850
- const start = process.hrtime.bigint();
851
- return {
852
- wallNow: () => /* @__PURE__ */ new Date(),
853
- monoNow: () => Number(process.hrtime.bigint() - start) / 1e6,
854
- sleep: (ms, signal) => new Promise((resolve22, reject) => {
855
- if (signal?.aborted) {
856
- reject(signal.reason ?? new Error("aborted"));
857
- return;
858
- }
859
- const timer = setTimeout(resolve22, ms);
860
- const onAbort = () => {
861
- clearTimeout(timer);
862
- reject(signal?.reason ?? new Error("aborted"));
863
- };
864
- signal?.addEventListener("abort", onAbort, { once: true });
865
- })
866
- };
867
- }
868
- function sha256Text(text) {
869
- return createHash4("sha256").update(text, "utf8").digest("hex");
870
- }
871
- function computeWindowRelation(authoritativeTime, activationTime, deadlineTime) {
872
- if (authoritativeTime === void 0 || authoritativeTime === null || authoritativeTime.length === 0) {
873
- return "uncertain";
874
- }
875
- const ms = Date.parse(authoritativeTime);
876
- if (!Number.isFinite(ms)) return "uncertain";
877
- const activationMs = activationTime.getTime();
878
- const deadlineMs = deadlineTime.getTime();
879
- if (ms < activationMs) return "before";
880
- if (ms <= deadlineMs) return "within";
881
- return "after";
882
- }
883
- function stableId(kind, githubId) {
884
- return `${kind}:${githubId}`;
885
- }
886
- function versionDigest(parts) {
887
- return sha256Text(JSON.stringify(parts));
888
- }
889
- function evidenceIdFor(kind, versionId) {
890
- return sha256Text(`${kind}:${versionId}`).slice(0, 16);
891
- }
892
- function normalizeAuthenticatedUserEvidence(user, observedAt) {
893
- const login = user.login.toLowerCase();
894
- const rawId = user.raw?.id;
895
- const stableNumericOrStringId = typeof rawId === "number" || typeof rawId === "string" ? rawId : void 0;
896
- const retainedRaw = { login };
897
- if (stableNumericOrStringId !== void 0) {
898
- retainedRaw.id = stableNumericOrStringId;
899
- }
900
- const contentDigest = versionDigest({
901
- login,
902
- ...stableNumericOrStringId !== void 0 ? { id: stableNumericOrStringId } : {}
903
- });
904
- const versionId = `user:${login}:${contentDigest.slice(0, 12)}`;
905
- return {
906
- evidenceId: evidenceIdFor("authenticated_user", versionId),
907
- kind: "authenticated_user",
908
- stableGitHubId: stableId("user", login),
909
- versionId,
910
- contentDigest,
911
- authorLogin: login,
912
- firstObservedAt: observedAt,
913
- raw: retainedRaw
914
- };
915
- }
916
- function normalizePullRequestEvidence(pr, observedAt) {
917
- const contentDigest = versionDigest({
918
- number: pr.number,
919
- state: pr.state,
920
- headOid: pr.headOid,
921
- createdAt: pr.createdAt ?? null,
922
- updatedAt: pr.updatedAt ?? null,
923
- htmlUrl: pr.url
924
- });
925
- const versionId = `pr:${pr.number}:${contentDigest.slice(0, 12)}`;
926
- return {
927
- evidenceId: evidenceIdFor("pull_request", versionId),
928
- kind: "pull_request",
929
- stableGitHubId: stableId("pr", pr.number),
930
- versionId,
931
- contentDigest,
932
- state: pr.state,
933
- commitOid: pr.headOid,
934
- htmlUrl: pr.url,
935
- // Version clock stays updatedAt. Create success for the wait window is snapshot.prCreatedAt only (#678).
936
- authoritativeTime: pr.updatedAt ?? null,
937
- firstObservedAt: observedAt,
938
- raw: pr.raw
939
- };
940
- }
941
- function normalizeReviewEvidence(review, observedAt) {
942
- const authorLogin = review.userLogin === null || review.userLogin === void 0 ? void 0 : review.userLogin.toLowerCase();
943
- const contentDigest = versionDigest({
944
- id: review.id,
945
- state: review.state,
946
- body: review.body,
947
- commitId: review.commitId,
948
- submittedAt: review.submittedAt,
949
- htmlUrl: review.htmlUrl,
950
- userLogin: authorLogin ?? null,
951
- machineIdentity: review.machineIdentity ?? null
952
- });
953
- const versionId = `review:${review.id}:${contentDigest.slice(0, 12)}`;
954
- return {
955
- evidenceId: evidenceIdFor("review", versionId),
956
- kind: "review",
957
- stableGitHubId: stableId("review", review.id),
958
- githubId: review.id,
959
- machineIdentity: review.machineIdentity ?? null,
960
- versionId,
961
- contentDigest,
962
- ...authorLogin === void 0 ? {} : { authorLogin },
963
- state: review.state,
964
- body: review.body,
965
- commitOid: review.commitId,
966
- htmlUrl: review.htmlUrl,
967
- // Submission metadata only; ledger history assigns authoritativeTime.
968
- submittedAt: review.submittedAt,
969
- authoritativeTime: review.submittedAt,
970
- firstObservedAt: observedAt,
971
- raw: review.raw
972
- };
973
- }
974
- function normalizePullRequestReactionEvidence(reaction, observedAt) {
975
- const authorLogin = reaction.userLogin?.toLowerCase();
976
- const contentDigest = versionDigest({
977
- id: reaction.id,
978
- content: reaction.content,
979
- createdAt: reaction.createdAt,
980
- machineIdentity: reaction.machineIdentity ?? null
981
- });
982
- const versionId = `reaction:${reaction.id}:${contentDigest.slice(0, 12)}`;
983
- return {
984
- evidenceId: evidenceIdFor("reaction", versionId),
985
- kind: "reaction",
986
- stableGitHubId: stableId("reaction", reaction.id),
987
- githubId: reaction.id,
988
- machineIdentity: reaction.machineIdentity ?? null,
989
- versionId,
990
- contentDigest,
991
- ...authorLogin === void 0 ? {} : { authorLogin },
992
- body: reaction.content,
993
- authoritativeTime: reaction.createdAt,
994
- firstObservedAt: observedAt,
995
- raw: reaction.raw
996
- };
997
- }
998
- function normalizeIssueCommentEvidence(comment, observedAt) {
999
- const authorLogin = comment.userLogin === null || comment.userLogin === void 0 ? void 0 : comment.userLogin.toLowerCase();
1000
- const contentDigest = versionDigest({
1001
- id: comment.id,
1002
- body: comment.body,
1003
- updatedAt: comment.updatedAt,
1004
- userLogin: authorLogin ?? null,
1005
- machineIdentity: comment.machineIdentity ?? null,
1006
- htmlUrl: comment.htmlUrl
1007
- });
1008
- const versionId = `issue_comment:${comment.id}:${contentDigest.slice(0, 12)}`;
1009
- return {
1010
- evidenceId: evidenceIdFor("issue_comment", versionId),
1011
- kind: "issue_comment",
1012
- stableGitHubId: stableId("issue_comment", comment.id),
1013
- githubId: comment.id,
1014
- machineIdentity: comment.machineIdentity ?? null,
1015
- versionId,
1016
- contentDigest,
1017
- ...authorLogin === void 0 ? {} : { authorLogin },
1018
- body: comment.body,
1019
- htmlUrl: comment.htmlUrl,
1020
- authoritativeTime: comment.updatedAt ?? null,
1021
- firstObservedAt: observedAt,
1022
- raw: comment.raw
1023
- };
1024
- }
1025
- function normalizeReviewCommentEvidence(comment, observedAt) {
1026
- const authorLogin = comment.userLogin === null || comment.userLogin === void 0 ? void 0 : comment.userLogin.toLowerCase();
1027
- const contentDigest = versionDigest({
1028
- id: comment.id,
1029
- body: comment.body,
1030
- path: comment.path,
1031
- line: comment.line,
1032
- originalLine: comment.originalLine,
1033
- side: comment.side,
1034
- position: comment.position,
1035
- updatedAt: comment.updatedAt,
1036
- commitId: comment.commitId,
1037
- pullRequestReviewId: comment.pullRequestReviewId,
1038
- userLogin: authorLogin ?? null,
1039
- machineIdentity: comment.machineIdentity ?? null,
1040
- htmlUrl: comment.htmlUrl
1041
- });
1042
- const versionId = `review_comment:${comment.id}:${contentDigest.slice(0, 12)}`;
1043
- return {
1044
- evidenceId: evidenceIdFor("review_comment", versionId),
1045
- kind: "review_comment",
1046
- stableGitHubId: stableId("review_comment", comment.id),
1047
- githubId: comment.id,
1048
- machineIdentity: comment.machineIdentity ?? null,
1049
- versionId,
1050
- contentDigest,
1051
- ...authorLogin === void 0 ? {} : { authorLogin },
1052
- body: comment.body,
1053
- commitOid: comment.commitId,
1054
- htmlUrl: comment.htmlUrl,
1055
- path: comment.path,
1056
- line: comment.line,
1057
- originalLine: comment.originalLine,
1058
- side: comment.side,
1059
- position: comment.position,
1060
- pullRequestReviewId: comment.pullRequestReviewId,
1061
- authoritativeTime: comment.updatedAt ?? null,
1062
- firstObservedAt: observedAt,
1063
- raw: comment.raw
1064
- };
1065
- }
1066
- function applyEvidenceVersionHistory(pending, priorEvidence, cutoff) {
1067
- const versionsByStable = /* @__PURE__ */ new Map();
1068
- const add = (stableIdValue, versionId) => {
1069
- let set = versionsByStable.get(stableIdValue);
1070
- if (set === void 0) {
1071
- set = /* @__PURE__ */ new Set();
1072
- versionsByStable.set(stableIdValue, set);
1073
- }
1074
- set.add(versionId);
1075
- };
1076
- for (const record4 of priorEvidence) {
1077
- if (record4.stableGitHubId !== void 0) {
1078
- add(record4.stableGitHubId, record4.versionId);
1079
- }
1080
- }
1081
- const priorByVersionId = /* @__PURE__ */ new Map();
1082
- for (const record4 of priorEvidence) {
1083
- priorByVersionId.set(record4.versionId, record4);
1084
- }
1085
- for (const record4 of pending) {
1086
- if (record4.stableGitHubId === void 0) continue;
1087
- const priorVersions = versionsByStable.get(record4.stableGitHubId) ?? /* @__PURE__ */ new Set();
1088
- const isNewVersion = !priorVersions.has(record4.versionId);
1089
- const hadEarlierDistinctVersion = [...priorVersions].some(
1090
- (versionId) => versionId !== record4.versionId
1091
- );
1092
- if (record4.kind === "review") {
1093
- if (!isNewVersion) {
1094
- const prior = priorByVersionId.get(record4.versionId);
1095
- if (prior !== void 0) {
1096
- record4.authoritativeTime = prior.authoritativeTime ?? null;
1097
- }
1098
- } else if (hadEarlierDistinctVersion) {
1099
- record4.authoritativeTime = null;
1100
- } else {
1101
- const { deadlineMono, firstObservedMono } = cutoff;
1102
- if (!Number.isFinite(deadlineMono) || !Number.isFinite(firstObservedMono) || firstObservedMono > deadlineMono) {
1103
- record4.authoritativeTime = null;
1104
- } else {
1105
- record4.authoritativeTime = record4.submittedAt ?? null;
1106
- }
1107
- }
1108
- } else if (record4.kind === "issue_comment" || record4.kind === "review_comment") {
1109
- if (record4.authoritativeTime === void 0 || record4.authoritativeTime === "") {
1110
- record4.authoritativeTime = null;
1111
- }
1112
- }
1113
- if (isNewVersion) {
1114
- add(record4.stableGitHubId, record4.versionId);
1115
- }
1116
- }
1117
- }
1118
- function measureNormalizedBytes(records) {
1119
- return Buffer.byteLength(JSON.stringify(records), "utf8");
1120
- }
1121
- function assignWindowRelations(records, activationTime, deadlineTime) {
1122
- if (activationTime === void 0 || deadlineTime === void 0) return;
1123
- for (const record4 of records) {
1124
- if (record4.kind === "review" || record4.kind === "issue_comment" || record4.kind === "review_comment" || record4.kind === "pull_request") {
1125
- record4.windowRelation = computeWindowRelation(
1126
- record4.authoritativeTime,
1127
- activationTime,
1128
- deadlineTime
1129
- );
1130
- }
1131
- }
1132
- }
1133
- var COLLECTOR_DEFAULT_WAIT_WINDOW_MS;
1134
- var init_collector_evidence = __esm({
1135
- "src/collector-evidence.ts"() {
1136
- "use strict";
1137
- COLLECTOR_DEFAULT_WAIT_WINDOW_MS = 10 * 60 * 1e3;
1138
- }
1139
- });
1140
-
1141
- // src/readable-gate-item.ts
1142
- var readable_gate_item_exports = {};
1143
- __export(readable_gate_item_exports, {
1144
- joinReadableGateItems: () => joinReadableGateItems,
1145
- readableGateItem: () => readableGateItem
1146
- });
1147
- function readableGateItem(value) {
1148
- return typeof value === "string" ? value : JSON.stringify(value);
1149
- }
1150
- function joinReadableGateItems(items, separator = "; ") {
1151
- return items.map(readableGateItem).join(separator);
1152
- }
1153
- var init_readable_gate_item = __esm({
1154
- "src/readable-gate-item.ts"() {
1155
- "use strict";
1156
- }
1157
- });
1158
-
1159
- // src/submission-errors.ts
1160
- function serializeReceipt(receipt) {
1161
- return readableGateItem(receipt);
1162
- }
1163
- function gatekeeperNonPassMessage(result) {
1164
- if (result.status === "continue") {
1165
- return serializeReceipt(result.receipt);
1166
- }
1167
- if (result.status === "transport_failure") {
1168
- const head = `\u95E8\u4E0B\u7701 ${result.status}\uFF08${result.stage}\uFF09\uFF1A${result.reason}`;
1169
- return result.submission === void 0 ? head : `${head}
1170
- ${serializeReceipt(result.submission)}`;
1171
- }
1172
- return `\u95E8\u4E0B\u7701 ${result.status}\uFF08${result.stage}\uFF09\uFF1A${result.reason}`;
1173
- }
1174
- function unreadableDiscriminatorNotice(field, received) {
1175
- if (received === void 0) return `\u8BFB\u4E0D\u51FA ${field}`;
1176
- return `\u8BFB\u4E0D\u51FA ${field}\uFF1A${readableGateItem(received)}`;
1177
- }
1178
- function receivedDiscriminator(receipt, field) {
1179
- if (receipt === null || typeof receipt !== "object" || Array.isArray(receipt)) return void 0;
1180
- if (!Object.hasOwn(receipt, field)) return void 0;
1181
- return receipt[field];
1182
- }
1183
- var GatekeeperDecisionError, WorkerCommitReminderError, WorkerPrefixReminderError, WorkerUnfinishedReasonReminderError, ParentQueueReaskError;
1184
- var init_submission_errors = __esm({
1185
- "src/submission-errors.ts"() {
1186
- "use strict";
1187
- init_readable_gate_item();
1188
- GatekeeperDecisionError = class extends Error {
1189
- result;
1190
- constructor(result, message) {
1191
- super(message ?? gatekeeperNonPassMessage(result));
1192
- this.name = "GatekeeperDecisionError";
1193
- this.result = result;
1194
- }
1195
- };
1196
- WorkerCommitReminderError = class extends Error {
1197
- code = "worker_commit_reminder";
1198
- constructor() {
1199
- super("\u672A\u89C2\u5BDF\u5230 commit");
1200
- this.name = "WorkerCommitReminderError";
1201
- }
1202
- };
1203
- WorkerPrefixReminderError = class extends Error {
1204
- code = "worker_prefix_reminder";
1205
- constructor() {
1206
- super("\u89C2\u5BDF\u5230\u7F3A\u524D\u7F00 commit");
1207
- this.name = "WorkerPrefixReminderError";
1208
- }
1209
- };
1210
- WorkerUnfinishedReasonReminderError = class extends Error {
1211
- code = "worker_unfinished_reason_reminder";
1212
- constructor() {
1213
- super("\u672C\u6B21 unfinished \u56DE\u6267\u672A\u542B reason\uFF1B\u672C\u63A5\u7F1D\u7F3A\u7531\u81F3\u591A\u6253\u56DE\u4E24\u6B21\u3002");
1214
- this.name = "WorkerUnfinishedReasonReminderError";
1215
- }
1216
- };
1217
- ParentQueueReaskError = class extends Error {
1218
- code = "parent_queue_reask";
1219
- constructor(message) {
1220
- super(message);
1221
- this.name = "ParentQueueReaskError";
1222
- }
1223
- };
1224
- }
1225
- });
1226
-
1227
- // src/submission-correctable-error.ts
1228
- function isCorrectableSubmissionError(error) {
1229
- return error instanceof CorrectableSubmissionError;
1230
- }
1231
- function isCorrectableExecuteError(error) {
1232
- return isCorrectableSubmissionError(error) || error instanceof GatekeeperDecisionError || error instanceof ParentQueueReaskError || error instanceof WorkerCommitReminderError || error instanceof WorkerPrefixReminderError || error instanceof WorkerUnfinishedReasonReminderError;
1233
- }
1234
- function projectCorrectableExecuteRejection(error) {
1235
- const diagnostic = error instanceof Error ? error.message : String(error);
1236
- if (error instanceof GatekeeperDecisionError) {
1237
- return { diagnostic, details: { ...error.result } };
1238
- }
1239
- if (error instanceof WorkerCommitReminderError || error instanceof WorkerPrefixReminderError || error instanceof WorkerUnfinishedReasonReminderError) {
1240
- return { diagnostic, details: { code: error.code } };
1241
- }
1242
- if (typeof error.code === "string") {
1243
- return { diagnostic, details: { code: error.code } };
1244
- }
1245
- return {
1246
- diagnostic,
1247
- details: {
1248
- code: error instanceof Error && error.name ? error.name : "correctable-submission-error"
1249
- }
1250
- };
1251
- }
1252
- var correctableSubmissionErrorBrand, CorrectableSubmissionError;
1253
- var init_submission_correctable_error = __esm({
1254
- "src/submission-correctable-error.ts"() {
1255
- "use strict";
1256
- init_submission_errors();
1257
- correctableSubmissionErrorBrand = /* @__PURE__ */ Symbol("ak-roles.correctable-submission-error");
1258
- CorrectableSubmissionError = class extends Error {
1259
- [correctableSubmissionErrorBrand] = true;
1260
- };
145
+ fix: Type2.Optional(Type2.Unknown({ description: "continue \u65F6\u7684\u8865\u6551\u8BF4\u660E\uFF1B\u53EF\u5199 summary \u6458\u8981\uFF0C\u5176\u4F59\u5185\u5BB9\u539F\u6837\u7559\u5B58" })),
146
+ classes: Type2.Optional(Type2.Unknown({ description: "\u5DF2\u88C1\u51B3 finding \u7C7B\uFF1B\u53EF\u8BF4\u660E name\u3001owner\u3001boundary\u3001disposition\uFF0C\u539F\u6837\u7559\u5B58" })),
147
+ note: Type2.Optional(Type2.Unknown({ description: "\u88C1\u51B3\u9644\u6CE8" })),
148
+ evidence: Type2.Optional(Type2.Unknown({ description: "\u7559\u5B58\u8BC1\u636E" })),
149
+ decisionGate: Type2.Optional(Type2.Unknown({ description: "\u9700\u4EBA\u6743\u5A01\u5904\u7F6E\u7684\u95EE\u9898\u4E0E\u9009\u9879\uFF1B\u53EF\u8BF4\u660E question\u3001options\uFF0C\u539F\u6837\u7559\u5B58" }))
150
+ }, { additionalProperties: true })
151
+ );
1261
152
  }
1262
153
  });
1263
154
 
1264
- // src/collector-identity.ts
1265
- var CollectorUnknownEvidenceError, CollectorNonOpenRequestError, CollectorWaitWindowClosedError;
1266
- var init_collector_identity = __esm({
1267
- "src/collector-identity.ts"() {
155
+ // src/package-contracts/judge-output.ts
156
+ var JUDGE_OUTPUT_TOOL_NAME;
157
+ var init_judge_output = __esm({
158
+ "src/package-contracts/judge-output.ts"() {
1268
159
  "use strict";
1269
- init_submission_correctable_error();
1270
- CollectorUnknownEvidenceError = class extends CorrectableSubmissionError {
1271
- constructor(evidenceId) {
1272
- super(`\u672A\u5728\u672C\u5C40\u5DF2\u89C2\u6D4B\u6750\u6599\u4E2D\u627E\u5230 evidenceId ${evidenceId}\uFF1B\u8BF7\u7528 observe \u8FD4\u56DE\u7684\u6307\u9488\u91CD\u8BD5\u3002`);
1273
- this.name = "CollectorUnknownEvidenceError";
1274
- }
1275
- };
1276
- CollectorNonOpenRequestError = class extends CorrectableSubmissionError {
1277
- constructor(prState) {
1278
- super(`\u901A\u8FDB\u53F8\u8BF7\u6C42\u8981\u6C42 OPEN \u72B6\u6001\u7684 PR \u5FEB\u7167\uFF1B\u5F53\u524D\u4E3A ${prState}\uFF0C\u4E0D\u518D\u89E6\u53D1\u65B0\u8BC4\u5BA1\uFF0C\u8BF7\u76F4\u63A5\u4EA4\u56DE\u5DF2\u6709\u6750\u6599`);
1279
- this.name = "CollectorNonOpenRequestError";
1280
- }
1281
- };
1282
- CollectorWaitWindowClosedError = class extends CorrectableSubmissionError {
1283
- constructor(action) {
1284
- super(
1285
- action === "request" ? "\u901A\u8FDB\u53F8\u8BF7\u6C42\u4E0D\u5728\u8D44\u683C\u622A\u6B62\u524D" : action === "wait-before-open" ? "\u901A\u8FDB\u53F8\u7B49\u5F85\u9700\u8981\u5148\u5728\u5DE5\u4F5C\u6B65\u9AA4\u5F00\u542F\u7B49\u5F85\u7A97\uFF08\u65B0\u5EFA PR \u7528\u521B\u5EFA\u6210\u529F\u65F6\u523B\uFF1B\u5DF2\u6709 PR \u5728\u89E6\u53D1\u9636\u6BB5\u7ED3\u675F\u540E\u5F00\u542F\uFF09" : "\u901A\u8FDB\u53F8\u7B49\u5F85\u4E0D\u5728\u8D44\u683C\u622A\u6B62\u524D"
1286
- );
1287
- this.name = "CollectorWaitWindowClosedError";
1288
- }
1289
- };
160
+ init_review_submission();
161
+ JUDGE_OUTPUT_TOOL_NAME = REVIEW_SUBMISSION_OUTPUT_TOOL_NAME;
1290
162
  }
1291
163
  });
1292
164
 
1293
- // src/collector-ledger.ts
1294
- function projectObserveContextView(modelView) {
1295
- return modelView;
1296
- }
1297
- function isOperationalTool(name) {
1298
- return COLLECTOR_OPERATIONAL_TOOLS.includes(name);
1299
- }
1300
- function resolveWaitWindowMs(raw) {
1301
- if (raw === void 0) return COLLECTOR_DEFAULT_WAIT_WINDOW_MS;
1302
- if (!Number.isSafeInteger(raw) || raw < 1) {
1303
- throw new Error("\u901A\u8FDB\u53F8 waitWindowMs \u987B\u4E3A\u6B63\u5B89\u5168\u6574\u6570\u6BEB\u79D2");
1304
- }
1305
- return raw;
1306
- }
1307
- function createCollectorLedger(input, options) {
1308
- const config = {
1309
- repository: input.repository,
1310
- prNumber: input.prNumber,
1311
- manifest: input.manifest,
1312
- waitWindowMs: resolveWaitWindowMs(input.waitWindowMs)
1313
- };
1314
- const clock = options?.clock;
1315
- const journal = options?.journal;
1316
- let fatal = false;
1317
- let fatalReason;
1318
- let outputCandidate = false;
1319
- let pendingOutputCallId;
1320
- let sessionReady = false;
1321
- let activationTime;
1322
- let deadlineTime;
1323
- let activationMono;
1324
- let deadlineMono;
1325
- let requesterLogin;
1326
- let latestCompleteSnapshotId;
1327
- let finalObservationRequired = false;
1328
- let finalObservationCompleted = false;
1329
- let activeOperationalCallId;
1330
- let mutationGeneration = 0;
1331
- let observedGeneration = 0;
1332
- const evidenceById = /* @__PURE__ */ new Map();
1333
- const evidenceByVersion = /* @__PURE__ */ new Map();
1334
- const snapshots = [];
1335
- const attempts = [];
1336
- const attemptKeys = /* @__PURE__ */ new Set();
1337
- const waits = [];
1338
- const transportFailures = [];
1339
- const latchFatal = (reason, cause) => {
1340
- fatal = true;
1341
- fatalReason = reason;
1342
- const error = new Error(reason, cause === void 0 ? void 0 : { cause });
1343
- Object.assign(error, { collectorFatal: true });
1344
- return error;
1345
- };
1346
- const assertNotFatal = () => {
1347
- if (fatal) throw new Error(fatalReason ?? "\u901A\u8FDB\u53F8\u81F4\u547D\u72B6\u6001");
1348
- };
1349
- const storeEvidence = (record4) => {
1350
- const existingId = evidenceByVersion.get(record4.versionId);
1351
- if (existingId !== void 0) {
1352
- return evidenceById.get(existingId) ?? record4;
1353
- }
1354
- evidenceByVersion.set(record4.versionId, record4.evidenceId);
1355
- evidenceById.set(record4.evidenceId, record4);
1356
- return record4;
1357
- };
1358
- const monoNowOrThrow = (clock2) => clock2.monoNow();
1359
- const pastCutoff = (clock2) => {
1360
- if (deadlineMono === void 0) return false;
1361
- return monoNowOrThrow(clock2) >= deadlineMono;
1362
- };
1363
- const remainingMs = (clock2) => {
1364
- if (deadlineMono === void 0) return config.waitWindowMs;
1365
- return Math.max(0, deadlineMono - monoNowOrThrow(clock2));
1366
- };
1367
- const prIdentity = (pr) => `${pr.state}|${pr.headOid}|${pr.updatedAt ?? ""}`;
1368
- const requireBoundPr = () => {
1369
- if (config.prNumber === void 0) {
1370
- throw new Error("\u901A\u8FDB\u53F8 PR \u76EE\u6807\u672A\u7ED1\u5B9A");
1371
- }
1372
- return config.prNumber;
1373
- };
1374
- const fetchObserveSurfaces = async (transport, observedAt, signal) => {
1375
- const owner = config.repository.owner;
1376
- const repo = config.repository.repo;
1377
- const prNumber = requireBoundPr();
1378
- const signalOpt = signal === void 0 ? {} : { signal };
1379
- const user = await transport.getAuthenticatedUser(signalOpt);
1380
- const prInitial = await transport.getPullRequest({
1381
- owner,
1382
- repo,
1383
- prNumber,
1384
- ...signalOpt
1385
- });
1386
- const reviews = await transport.listPullRequestReviews({
1387
- owner,
1388
- repo,
1389
- prNumber,
1390
- ...signalOpt
1391
- });
1392
- const reactions = transport.listPullRequestReactions === void 0 ? { items: [], pages: [] } : await transport.listPullRequestReactions({ owner, repo, prNumber, ...signalOpt });
1393
- const issueComments = await transport.listIssueComments({
1394
- owner,
1395
- repo,
1396
- prNumber,
1397
- ...signalOpt
1398
- });
1399
- const reviewComments = await transport.listReviewComments({
1400
- owner,
1401
- repo,
1402
- prNumber,
1403
- ...signalOpt
1404
- });
1405
- const prTerminal = await transport.getPullRequest({
1406
- owner,
1407
- repo,
1408
- prNumber,
1409
- ...signalOpt
1410
- });
1411
- return { user, prInitial, reviews, reactions, issueComments, reviewComments, prTerminal };
1412
- };
1413
- const appendJournal = (customType, data) => {
1414
- journal?.append(customType, data);
1415
- };
1416
- const bindDeadlineMonoFromWall = () => {
1417
- if (clock === void 0 || activationTime === void 0 || deadlineTime === void 0) return;
1418
- const wallNow = clock.wallNow().getTime();
1419
- const monoNow = clock.monoNow();
1420
- activationMono = monoNow - (wallNow - activationTime.getTime());
1421
- deadlineMono = monoNow + (deadlineTime.getTime() - wallNow);
1422
- };
1423
- const rebindSnapshotCompletedMono = (snapshot) => {
1424
- const copy = { ...snapshot, evidenceIds: [...snapshot.evidenceIds] };
1425
- if (deadlineTime !== void 0 && deadlineMono !== void 0 && copy.completedAt !== void 0) {
1426
- const completedWall = new Date(copy.completedAt).getTime();
1427
- copy.completedMono = deadlineMono + (completedWall - deadlineTime.getTime());
1428
- }
1429
- return copy;
1430
- };
1431
- const commitActivationWindow = (nextActivation, nextDeadline) => {
1432
- if (activationTime !== void 0) return;
1433
- sessionReady = true;
1434
- activationTime = nextActivation;
1435
- deadlineTime = nextDeadline;
1436
- bindDeadlineMonoFromWall();
1437
- };
1438
- const recoverAmbiguousRequestLosses = (snapshotId, observedRecords) => {
1439
- for (const failure2 of transportFailures) {
1440
- if (failure2.recovered || failure2.kind !== "ambiguous_request_loss") continue;
1441
- if (failure2.marker === void 0 || failure2.requestId === void 0) continue;
1442
- const found = observedRecords.find(
1443
- (record4) => record4.kind === "issue_comment" && record4.authorLogin === requesterLogin && typeof record4.body === "string" && record4.body.includes(failure2.marker)
1444
- );
1445
- if (found === void 0) continue;
1446
- failure2.recovered = true;
1447
- const attempt = attempts.find(
1448
- (item) => item.status === "ambiguous_loss" && item.requestId === failure2.requestId && item.marker === failure2.marker
1449
- );
1450
- if (attempt !== void 0) {
1451
- attempt.status = "recovered";
1452
- attempt.commentEvidenceId = found.evidenceId;
1453
- attempt.recoverySnapshotId = snapshotId;
1454
- }
1455
- }
1456
- };
1457
- const finalizeObservedSnapshot = (snapshot) => {
1458
- if (requesterLogin === void 0) {
1459
- for (const id of snapshot.evidenceIds) {
1460
- const record4 = evidenceById.get(id);
1461
- if (record4?.kind === "authenticated_user" && record4.authorLogin !== void 0) {
1462
- requesterLogin = record4.authorLogin.toLowerCase();
1463
- break;
1464
- }
1465
- }
1466
- }
1467
- const stored = rebindSnapshotCompletedMono(snapshot);
1468
- snapshots.push(stored);
1469
- latestCompleteSnapshotId = stored.snapshotId;
1470
- const observedRecords = stored.evidenceIds.flatMap((id) => {
1471
- const record4 = evidenceById.get(id);
1472
- return record4 === void 0 ? [] : [record4];
1473
- });
1474
- recoverAmbiguousRequestLosses(stored.snapshotId, observedRecords);
1475
- observedGeneration = mutationGeneration;
1476
- if (finalObservationRequired && stored.completedMono !== void 0 && deadlineMono !== void 0 && stored.completedMono >= deadlineMono) {
1477
- finalObservationCompleted = true;
1478
- } else if (clock !== void 0 && deadlineMono !== void 0 && clock.monoNow() >= deadlineMono && stored.completedMono !== void 0 && stored.completedMono >= deadlineMono) {
1479
- finalObservationRequired = true;
1480
- finalObservationCompleted = true;
1481
- }
1482
- return stored;
1483
- };
1484
- const commitObservedSnapshot = (snapshot, evidenceRecords) => {
1485
- for (const record4 of evidenceRecords) {
1486
- storeEvidence(record4);
1487
- }
1488
- return finalizeObservedSnapshot(snapshot);
1489
- };
1490
- const commitRequestAttempt = (attempt, attemptKey, commentEvidence) => {
1491
- if (commentEvidence !== void 0) {
1492
- storeEvidence(commentEvidence);
1493
- }
1494
- const existing = attempts.find((item) => item.attemptId === attempt.attemptId);
1495
- if (existing === void 0) {
1496
- attempts.push({ ...attempt });
1497
- attemptKeys.add(attemptKey);
1498
- } else {
1499
- Object.assign(existing, attempt);
1500
- }
1501
- if (attempt.status === "ambiguous_loss" && !transportFailures.some((failure2) => failure2.requestId === attempt.requestId && failure2.observedHead === attempt.observedHead)) {
1502
- transportFailures.push({
1503
- failureId: sha256Text(`loss:${attempt.attemptId}`).slice(0, 16),
1504
- kind: "ambiguous_request_loss",
1505
- message: attempt.responseDiagnostics ?? "ambiguous request loss",
1506
- requestId: attempt.requestId,
1507
- observedHead: attempt.observedHead,
1508
- marker: attempt.marker,
1509
- recovered: false
1510
- });
1511
- }
1512
- if (attempt.status === "succeeded" || attempt.status === "ambiguous_loss") {
1513
- mutationGeneration += 1;
1514
- finalObservationCompleted = false;
1515
- }
1516
- };
1517
- const commitWaitRecord = (wait) => {
1518
- waits.push({ ...wait });
1519
- if (wait.cutoffReached) finalObservationRequired = true;
1520
- mutationGeneration += 1;
1521
- finalObservationCompleted = false;
1522
- };
1523
- const replayDossierEntries = (entries) => {
1524
- const orderedEntries = Array.from(entries);
1525
- const finalRequestStatus = /* @__PURE__ */ new Map();
1526
- for (const raw of orderedEntries) {
1527
- if (typeof raw !== "object" || raw === null) continue;
1528
- const entry = raw;
1529
- if (entry.type !== "custom" || entry.customType !== COLLECTOR_REQUEST_ENTRY_TYPE || typeof entry.data !== "object" || entry.data === null) continue;
1530
- const attempt = entry.data.attempt;
1531
- if (attempt?.attemptId !== void 0) finalRequestStatus.set(attempt.attemptId, attempt.status);
1532
- }
1533
- for (const raw of orderedEntries) {
1534
- if (typeof raw !== "object" || raw === null) continue;
1535
- const entry = raw;
1536
- if (entry.type !== "custom" || typeof entry.data !== "object" || entry.data === null) continue;
1537
- const data = entry.data;
1538
- if (entry.customType === COLLECTOR_ACTIVATION_ENTRY_TYPE) {
1539
- if (typeof data.activationTime === "string" && typeof data.deadlineTime === "string") {
1540
- commitActivationWindow(new Date(data.activationTime), new Date(data.deadlineTime));
1541
- } else if (data.sessionReady === true) {
1542
- sessionReady = true;
1543
- }
1544
- continue;
1545
- }
1546
- if (entry.customType === COLLECTOR_SNAPSHOT_ENTRY_TYPE) {
1547
- const snapshot = data.snapshot;
1548
- if (snapshot?.snapshotId === void 0 || !Array.isArray(data.evidence)) continue;
1549
- commitObservedSnapshot(snapshot, data.evidence);
1550
- continue;
1551
- }
1552
- if (entry.customType === COLLECTOR_REQUEST_ENTRY_TYPE) {
1553
- const attempt = data.attempt;
1554
- if (attempt?.attemptId === void 0) continue;
1555
- const attemptKey = typeof data.attemptKey === "string" ? data.attemptKey : [config.repository.canonical, String(config.prNumber), attempt.observedHead, attempt.requestId].join("|");
1556
- const commentEvidence = data.commentEvidence;
1557
- const replayAttempt = attempt.status === "started" && finalRequestStatus.get(attempt.attemptId) === "started" ? {
1558
- ...attempt,
1559
- status: "ambiguous_loss",
1560
- responseDiagnostics: "request interrupted after dispatch before completion was recorded"
1561
- } : attempt;
1562
- commitRequestAttempt(replayAttempt, attemptKey, commentEvidence);
1563
- continue;
1564
- }
1565
- if (entry.customType === COLLECTOR_WAIT_ENTRY_TYPE) {
1566
- const wait = data.waitRecord;
1567
- if (wait?.waitId === void 0) continue;
1568
- commitWaitRecord(wait);
1569
- }
1570
- }
1571
- };
1572
- if (options?.dossierEntries !== void 0) {
1573
- replayDossierEntries(options.dossierEntries);
1574
- }
1575
- if (clock !== void 0 && deadlineMono !== void 0 && clock.monoNow() >= deadlineMono) {
1576
- finalObservationRequired = true;
1577
- const lastSnap = snapshots.find((item) => item.snapshotId === latestCompleteSnapshotId);
1578
- if (lastSnap?.completedMono !== void 0 && lastSnap.completedMono >= deadlineMono) {
1579
- finalObservationCompleted = true;
1580
- }
1581
- }
1582
- const ledger = {
1583
- get config() {
1584
- return config;
1585
- },
1586
- get fatal() {
1587
- return fatal;
1588
- },
1589
- get fatalReason() {
1590
- return fatalReason;
1591
- },
1592
- get outputCandidate() {
1593
- return outputCandidate || pendingOutputCallId !== void 0;
1594
- },
1595
- get activationRecorded() {
1596
- return sessionReady;
1597
- },
1598
- get activationTime() {
1599
- return activationTime;
1600
- },
1601
- get deadlineTime() {
1602
- return deadlineTime;
1603
- },
1604
- get activationMono() {
1605
- return activationMono;
1606
- },
1607
- get deadlineMono() {
1608
- return deadlineMono;
1609
- },
1610
- get requesterLogin() {
1611
- return requesterLogin;
1612
- },
1613
- get latestCompleteSnapshotId() {
1614
- return latestCompleteSnapshotId;
1615
- },
1616
- get finalObservationRequired() {
1617
- return finalObservationRequired;
1618
- },
1619
- get finalObservationCompleted() {
1620
- return finalObservationCompleted;
1621
- },
1622
- get unresolvedTransportFailure() {
1623
- return transportFailures.some((failure2) => !failure2.recovered);
1624
- },
1625
- get mutationGeneration() {
1626
- return mutationGeneration;
1627
- },
1628
- get observedGeneration() {
1629
- return observedGeneration;
1630
- },
1631
- latchFatal,
1632
- assertNotFatal,
1633
- recordActivation(_clock) {
1634
- assertNotFatal();
1635
- if (sessionReady) return;
1636
- sessionReady = true;
1637
- appendJournal(COLLECTOR_ACTIVATION_ENTRY_TYPE, {
1638
- sessionReady: true
1639
- });
1640
- },
1641
- openWaitWindow(clock2, options2) {
1642
- assertNotFatal();
1643
- if (!sessionReady) {
1644
- throw latchFatal("\u901A\u8FDB\u53F8\u5F00\u542F\u7B49\u5F85\u7A97\u9700\u8981\u5148\u6FC0\u6D3B\u4F1A\u8BDD");
1645
- }
1646
- if (activationTime !== void 0) return;
1647
- const startedAt = options2?.startedAt ?? clock2.wallNow();
1648
- if (!(startedAt instanceof Date) || Number.isNaN(startedAt.getTime())) {
1649
- throw new Error("\u901A\u8FDB\u53F8\u7B49\u5F85\u7A97 startedAt \u987B\u4E3A\u6709\u6548\u65F6\u95F4");
1650
- }
1651
- const nextDeadline = new Date(startedAt.getTime() + config.waitWindowMs);
1652
- activationTime = startedAt;
1653
- deadlineTime = nextDeadline;
1654
- const wallNow = clock2.wallNow().getTime();
1655
- const monoNow = clock2.monoNow();
1656
- activationMono = monoNow - (wallNow - startedAt.getTime());
1657
- deadlineMono = monoNow + (nextDeadline.getTime() - wallNow);
1658
- appendJournal(COLLECTOR_ACTIVATION_ENTRY_TYPE, {
1659
- activationTime: activationTime.toISOString(),
1660
- deadlineTime: deadlineTime.toISOString(),
1661
- waitWindowMs: config.waitWindowMs
1662
- });
1663
- },
1664
- recordOutputCandidate() {
1665
- assertNotFatal();
1666
- outputCandidate = true;
1667
- },
1668
- bindTarget(prNumber) {
1669
- assertNotFatal();
1670
- config.prNumber = prNumber;
1671
- appendJournal("ak-collector-target-bound", {
1672
- prNumber,
1673
- repository: config.repository.canonical
1674
- });
1675
- },
1676
- beginOperational(toolName, toolCallId) {
1677
- assertNotFatal();
1678
- if (toolName === COLLECTOR_OUTPUT_TOOL) {
1679
- pendingOutputCallId = toolCallId;
1680
- return;
1681
- }
1682
- if (activeOperationalCallId === toolCallId) {
1683
- return;
1684
- }
1685
- if (activeOperationalCallId !== void 0) {
1686
- throw latchFatal("\u901A\u8FDB\u53F8\u64CD\u4F5C\u8C03\u7528\u5DF2\u5728\u8FDB\u884C");
1687
- }
1688
- if (!isOperationalTool(toolName)) {
1689
- throw latchFatal(`\u672A\u77E5\u901A\u8FDB\u53F8\u5DE5\u5177 ${toolName}`);
1690
- }
1691
- activeOperationalCallId = toolCallId;
1692
- },
1693
- completeOperational(toolCallId) {
1694
- if (pendingOutputCallId === toolCallId) {
1695
- pendingOutputCallId = void 0;
1696
- }
1697
- if (activeOperationalCallId === toolCallId) {
1698
- activeOperationalCallId = void 0;
1699
- }
1700
- },
1701
- noteCutoffObserved() {
1702
- finalObservationRequired = true;
1703
- },
1704
- assertOutputObservationLaw(clock2) {
1705
- assertNotFatal();
1706
- if (activationTime === void 0 || deadlineTime === void 0 || deadlineMono === void 0) {
1707
- throw new Error("\u901A\u8FDB\u53F8\u56DE\u6267\u9700\u8981\u6FC0\u6D3B\u65F6\u95F4\u7EBF");
1708
- }
1709
- if (latestCompleteSnapshotId === void 0) {
1710
- throw new Error("\u901A\u8FDB\u53F8\u56DE\u6267\u9700\u8981\u5B8C\u6574\u7EC8\u5C40\u5FEB\u7167");
1711
- }
1712
- if (observedGeneration !== mutationGeneration) {
1713
- throw new Error(
1714
- "\u901A\u8FDB\u53F8\u56DE\u6267\u8981\u6C42\u5728\u6700\u8FD1 request/wait \u53D8\u66F4\u540E\u5B8C\u6210\u4E00\u6B21 observe"
1715
- );
1716
- }
1717
- const snapshot = snapshots.find((item) => item.snapshotId === latestCompleteSnapshotId);
1718
- if (snapshot === void 0 || !snapshot.complete) {
1719
- throw new Error("\u901A\u8FDB\u53F8\u7EC8\u5C40\u5FEB\u7167\u7F3A\u5931\u6216\u4E0D\u5B8C\u6574");
1720
- }
1721
- const mono = monoNowOrThrow(clock2);
1722
- const atOrAfterCutoff = mono >= deadlineMono;
1723
- if (atOrAfterCutoff) {
1724
- finalObservationRequired = true;
1725
- if (snapshot.completedMono === void 0 || snapshot.completedMono < deadlineMono) {
1726
- throw new Error(
1727
- "\u901A\u8FDB\u53F8\u622A\u6B62\u65F6/\u540E\u56DE\u6267\u8981\u6C42\u4E0D\u65E9\u4E8E\u622A\u6B62\u5B8C\u6210\u7684\u5B8C\u6574\u89C2\u5BDF"
1728
- );
1729
- }
1730
- finalObservationCompleted = true;
1731
- }
1732
- },
1733
- async observe(transport, clock2, signal) {
1734
- assertNotFatal();
1735
- if (!sessionReady) {
1736
- throw latchFatal("\u901A\u8FDB\u53F8\u89C2\u5BDF\u9700\u8981\u6FC0\u6D3B");
1737
- }
1738
- if (signal?.aborted) {
1739
- const abortMessage = signal.reason instanceof Error ? signal.reason.message : String(signal.reason ?? "\u5DF2\u4E2D\u6B62");
1740
- throw latchFatal(`\u901A\u8FDB\u53F8\u89C2\u5BDF\u5931\u8D25\uFF1A${abortMessage}`, signal.reason);
1741
- }
1742
- const observedAt = clock2.wallNow().toISOString();
1743
- const cutoff = pastCutoff(clock2);
1744
- if (cutoff) {
1745
- finalObservationRequired = true;
1746
- }
1747
- let surfaces;
1748
- try {
1749
- surfaces = await fetchObserveSurfaces(transport, observedAt, signal);
1750
- if (prIdentity(surfaces.prInitial) !== prIdentity(surfaces.prTerminal)) {
1751
- surfaces = await fetchObserveSurfaces(transport, observedAt, signal);
1752
- if (prIdentity(surfaces.prInitial) !== prIdentity(surfaces.prTerminal)) {
1753
- throw new Error(
1754
- `PR \u8EAB\u4EFD\u5728 observe \u62EC\u5F27\u91CD\u8BD5\u540E\u4ECD\u6F02\u79FB\uFF08${prIdentity(surfaces.prInitial)} \u2192 ${prIdentity(surfaces.prTerminal)}\uFF09`
1755
- );
1756
- }
1757
- }
1758
- } catch (error) {
1759
- const message = error instanceof Error ? error.message : "\u672A\u77E5\u5931\u8D25";
1760
- throw latchFatal(`\u901A\u8FDB\u53F8\u89C2\u5BDF\u5931\u8D25\uFF1A${message}`, error);
1761
- }
1762
- const firstObservedAt = clock2.wallNow().toISOString();
1763
- const firstObservedMono = monoNowOrThrow(clock2);
1764
- const pr = surfaces.prTerminal;
1765
- const { user, reviews, reactions, issueComments, reviewComments } = surfaces;
1766
- requesterLogin = user.login.toLowerCase();
1767
- const pageDiagnostics = [
1768
- ...reviews.pages,
1769
- ...reactions.pages,
1770
- ...issueComments.pages,
1771
- ...reviewComments.pages
1772
- ];
1773
- const pendingRecords = [];
1774
- pendingRecords.push(normalizeAuthenticatedUserEvidence(user, firstObservedAt));
1775
- pendingRecords.push(normalizePullRequestEvidence(pr, firstObservedAt));
1776
- for (const review of reviews.items) {
1777
- pendingRecords.push(normalizeReviewEvidence(review, firstObservedAt));
1778
- }
1779
- for (const reaction of reactions.items) {
1780
- pendingRecords.push(normalizePullRequestReactionEvidence(reaction, firstObservedAt));
1781
- }
1782
- for (const comment of issueComments.items) {
1783
- pendingRecords.push(normalizeIssueCommentEvidence(comment, firstObservedAt));
1784
- }
1785
- for (const comment of reviewComments.items) {
1786
- pendingRecords.push(normalizeReviewCommentEvidence(comment, firstObservedAt));
1787
- }
1788
- applyEvidenceVersionHistory(
1789
- pendingRecords,
1790
- [...evidenceById.values()],
1791
- { deadlineMono, firstObservedMono }
1792
- );
1793
- assignWindowRelations(pendingRecords, activationTime, deadlineTime);
1794
- const normalizedByteLength = measureNormalizedBytes(pendingRecords);
1795
- const storedIds = [];
1796
- for (const record4 of pendingRecords) {
1797
- const stored = storeEvidence(record4);
1798
- storedIds.push(stored.evidenceId);
1799
- }
1800
- const storedRecords = storedIds.map((id) => {
1801
- const stored = evidenceById.get(id);
1802
- if (stored === void 0) {
1803
- throw latchFatal(`\u901A\u8FDB\u53F8\u89C2\u5BDF\u4E22\u5931\u5DF2\u5B58\u8BC1\u636E ${id}`);
1804
- }
1805
- return stored;
1806
- });
1807
- const completedAt = clock2.wallNow().toISOString();
1808
- const completedMono = clock2.monoNow();
1809
- const snapshotId = sha256Text(
1810
- `${completedAt}:${pr.headOid}:${storedIds.join(",")}`
1811
- ).slice(0, 16);
1812
- const snapshot = {
1813
- snapshotId,
1814
- observedAt,
1815
- completedAt,
1816
- completedMono,
1817
- host: "github.com",
1818
- repository: config.repository.canonical,
1819
- prNumber: requireBoundPr(),
1820
- prState: pr.state,
1821
- headOid: pr.headOid,
1822
- ...pr.createdAt === void 0 ? {} : { prCreatedAt: pr.createdAt },
1823
- complete: true,
1824
- evidenceIds: storedIds,
1825
- pageDiagnostics,
1826
- normalizedByteLength
1827
- };
1828
- if (cutoff) {
1829
- finalObservationRequired = true;
1830
- }
1831
- const committed = finalizeObservedSnapshot(snapshot);
1832
- appendJournal(COLLECTOR_SNAPSHOT_ENTRY_TYPE, {
1833
- snapshot: committed,
1834
- evidence: committed.evidenceIds.flatMap((id) => {
1835
- const record4 = evidenceById.get(id);
1836
- return record4 === void 0 ? [] : [record4];
1837
- })
1838
- });
1839
- const modelView = buildObserveModelView({
1840
- snapshot: committed,
1841
- records: committed.evidenceIds.flatMap((id) => {
1842
- const record4 = evidenceById.get(id);
1843
- return record4 === void 0 ? [] : [record4];
1844
- }),
1845
- requesterLogin,
1846
- attempts
1847
- });
1848
- return {
1849
- snapshot: committed,
1850
- modelView,
1851
- contextView: projectObserveContextView(modelView)
1852
- };
1853
- },
1854
- async request(input2, transport, clock2, signal) {
1855
- assertNotFatal();
1856
- if (!sessionReady) {
1857
- throw latchFatal("\u901A\u8FDB\u53F8\u8BF7\u6C42\u9700\u8981\u6FC0\u6D3B");
1858
- }
1859
- if (ledger.unresolvedTransportFailure) {
1860
- throw latchFatal("\u901A\u8FDB\u53F8\u8BF7\u6C42\u65F6\u5B58\u5728\u672A\u6062\u590D\u7684\u4F20\u8F93\u5931\u8D25");
1861
- }
1862
- if (typeof input2.requestId !== "string") {
1863
- throw new Error("\u901A\u8FDB\u53F8 requestId \u987B\u4E3A\u5B57\u7B26\u4E32");
1864
- }
1865
- const requestId = input2.requestId.trim();
1866
- if (requestId.length === 0) {
1867
- throw new Error("\u901A\u8FDB\u53F8 requestId \u987B\u4E3A\u975E\u7A7A\uFF08\u9996\u5C3E\u7A7A\u767D\u4E0D\u6784\u6210\u8EAB\u4EFD\uFF09");
1868
- }
1869
- const configured = config.manifest.requests.find((item) => item.id === requestId);
1870
- const roleBody = typeof input2.body === "string" ? input2.body : void 0;
1871
- if (configured === void 0) {
1872
- if (roleBody === void 0 || roleBody.trim().length === 0) {
1873
- throw new Error(
1874
- `\u672A\u77E5\u901A\u8FDB\u53F8 requestId "${requestId}" \u4E14\u672A\u63D0\u4F9B body\uFF1B\u8BF7\u63D0\u4EA4\u89D2\u8272\u5224\u5B9A\u7684\u8BF7\u6C42\u6B63\u6587\u6216\u4F7F\u7528 request-manifest`
1875
- );
1876
- }
1877
- }
1878
- const snapshot = snapshots.find((item) => item.snapshotId === input2.snapshotId);
1879
- if (snapshot === void 0) {
1880
- throw new Error(`\u672A\u77E5\u901A\u8FDB\u53F8 snapshotId "${input2.snapshotId}"`);
1881
- }
1882
- if (snapshot.snapshotId !== latestCompleteSnapshotId) {
1883
- throw new Error("\u901A\u8FDB\u53F8\u8BF7\u6C42\u8981\u6C42\u6700\u65B0\u5B8C\u6574\u5FEB\u7167");
1884
- }
1885
- if (snapshot.prState !== "OPEN") {
1886
- throw new CollectorNonOpenRequestError(snapshot.prState);
1887
- }
1888
- if (pastCutoff(clock2)) {
1889
- finalObservationRequired = true;
1890
- throw new CollectorWaitWindowClosedError("request");
1891
- }
1892
- const configuredBody = configured?.requestBody ?? roleBody;
1893
- const { body, marker } = buildCollectorRequestBody({
1894
- configuredBody,
1895
- manifestDigest: config.manifest.digest,
1896
- requestId,
1897
- headOid: snapshot.headOid
1898
- });
1899
- const existingMarker = snapshot.evidenceIds.some((id) => {
1900
- const record4 = evidenceById.get(id);
1901
- return record4?.kind === "issue_comment" && record4.authorLogin === requesterLogin && typeof record4.body === "string" && record4.body.includes(marker);
1902
- });
1903
- if (existingMarker) {
1904
- throw new Error(
1905
- `\u901A\u8FDB\u53F8\u5728\u6B64 HEAD \u5DF2\u6709\u540C marker \u7684\u5DF2\u8BA4\u8BC1\u8BF7\u6C42 "${requestId}"`
1906
- );
1907
- }
1908
- const boundPr = requireBoundPr();
1909
- const attemptKey = [
1910
- config.repository.canonical,
1911
- String(boundPr),
1912
- snapshot.headOid,
1913
- requestId
1914
- ].join("|");
1915
- if (attemptKeys.has(attemptKey)) {
1916
- throw new Error(
1917
- `\u901A\u8FDB\u53F8\u8FDB\u7A0B\u5185\u8BF7\u6C42 "${requestId}" \u5728 HEAD ${snapshot.headOid} \u7684 attempt \u5DF2\u7528`
1918
- );
1919
- }
1920
- const startedAt = clock2.wallNow().toISOString();
1921
- const attemptId = sha256Text(`${attemptKey}:${startedAt}`).slice(0, 16);
1922
- const attempt = {
1923
- attemptId,
1924
- requestId,
1925
- observedHead: snapshot.headOid,
1926
- snapshotId: snapshot.snapshotId,
1927
- marker,
1928
- body,
1929
- startedAt,
1930
- status: "started"
1931
- };
1932
- commitRequestAttempt(attempt, attemptKey, void 0);
1933
- appendJournal(COLLECTOR_REQUEST_ENTRY_TYPE, {
1934
- attempt: { ...attempt },
1935
- attemptKey
1936
- });
1937
- const result = await transport.createIssueComment({
1938
- owner: config.repository.owner,
1939
- repo: config.repository.repo,
1940
- prNumber: boundPr,
1941
- body,
1942
- ...signal === void 0 ? {} : { signal }
1943
- });
1944
- const journalRequest = (commentEvidence) => {
1945
- const attemptKey2 = [
1946
- config.repository.canonical,
1947
- String(config.prNumber),
1948
- attempt.observedHead,
1949
- attempt.requestId
1950
- ].join("|");
1951
- appendJournal(COLLECTOR_REQUEST_ENTRY_TYPE, {
1952
- attempt: { ...attempt },
1953
- attemptKey: attemptKey2,
1954
- commentEvidence
1955
- });
1956
- };
1957
- if (result.kind === "success") {
1958
- const record4 = normalizeIssueCommentEvidence(result.comment, startedAt);
1959
- attempt.status = "succeeded";
1960
- attempt.commentEvidenceId = record4.evidenceId;
1961
- commitRequestAttempt(attempt, attemptKey, record4);
1962
- journalRequest(record4);
1963
- return {
1964
- status: "succeeded",
1965
- attemptId,
1966
- requestId,
1967
- observedHead: snapshot.headOid,
1968
- marker,
1969
- commentEvidenceId: record4.evidenceId
1970
- };
1971
- }
1972
- if (result.kind === "ambiguous_loss") {
1973
- attempt.status = "ambiguous_loss";
1974
- attempt.responseDiagnostics = result.diagnostics;
1975
- commitRequestAttempt(attempt, attemptKey, void 0);
1976
- journalRequest(void 0);
1977
- return {
1978
- status: "ambiguous_loss",
1979
- attemptId,
1980
- requestId,
1981
- observedHead: snapshot.headOid,
1982
- marker,
1983
- diagnostics: result.diagnostics
1984
- };
1985
- }
1986
- attempt.status = "rejected";
1987
- attempt.responseDiagnostics = result.diagnostics;
1988
- commitRequestAttempt(attempt, attemptKey, void 0);
1989
- journalRequest(void 0);
1990
- throw latchFatal(`\u901A\u8FDB\u53F8\u8BF7\u6C42\u88AB\u62D2\uFF1A${result.diagnostics}`);
1991
- },
1992
- async wait(input2, clock2, signal) {
1993
- assertNotFatal();
1994
- if (!sessionReady) {
1995
- throw latchFatal("\u901A\u8FDB\u53F8\u7B49\u5F85\u9700\u8981\u6FC0\u6D3B");
1996
- }
1997
- if (activationTime === void 0 || deadlineTime === void 0) {
1998
- throw new CollectorWaitWindowClosedError("wait-before-open");
1999
- }
2000
- if (pastCutoff(clock2)) {
2001
- finalObservationRequired = true;
2002
- throw new CollectorWaitWindowClosedError("wait");
2003
- }
2004
- const remaining = remainingMs(clock2);
2005
- const effectiveMs = Math.min(input2.durationMs, remaining);
2006
- const startedAt = clock2.wallNow().toISOString();
2007
- const waitId = sha256Text(`wait:${startedAt}:${effectiveMs}`).slice(0, 16);
2008
- await clock2.sleep(effectiveMs, signal);
2009
- const endedAt = clock2.wallNow().toISOString();
2010
- const cutoffReached = pastCutoff(clock2);
2011
- const record4 = {
2012
- waitId,
2013
- requestedMs: input2.durationMs,
2014
- effectiveMs,
2015
- startedAt,
2016
- endedAt,
2017
- cutoffReached
2018
- };
2019
- commitWaitRecord(record4);
2020
- appendJournal(COLLECTOR_WAIT_ENTRY_TYPE, {
2021
- waitRecord: record4
2022
- });
2023
- return {
2024
- waitId,
2025
- requestedMs: input2.durationMs,
2026
- effectiveMs,
2027
- cutoffReached,
2028
- remainingMsAfter: remainingMs(clock2)
2029
- };
2030
- },
2031
- getSnapshot(snapshotId) {
2032
- return snapshots.find((item) => item.snapshotId === snapshotId);
2033
- },
2034
- getEvidence(evidenceId) {
2035
- return evidenceById.get(evidenceId);
2036
- },
2037
- allEvidence() {
2038
- return [...evidenceById.values()];
2039
- },
2040
- allSnapshots() {
2041
- return [...snapshots];
2042
- },
2043
- requestAttempts() {
2044
- return [...attempts];
2045
- },
2046
- waits() {
2047
- return [...waits];
2048
- },
2049
- transportFailures() {
2050
- return [...transportFailures];
2051
- },
2052
- requestById(requestId) {
2053
- return config.manifest.requests.find((request) => request.id === requestId);
2054
- }
2055
- };
2056
- return ledger;
2057
- }
2058
- function projectEvidenceEntryView(record4) {
2059
- return {
2060
- evidenceId: record4.evidenceId,
2061
- kind: record4.kind,
2062
- authorLogin: record4.authorLogin,
2063
- state: record4.state,
2064
- body: record4.body,
2065
- commitOid: record4.commitOid,
2066
- htmlUrl: record4.htmlUrl,
2067
- path: record4.path,
2068
- // Single display fallback: current line, else originalLine.
2069
- line: record4.line ?? record4.originalLine,
2070
- side: record4.side,
2071
- authoritativeTime: record4.authoritativeTime,
2072
- windowRelation: record4.windowRelation,
2073
- pullRequestReviewId: record4.pullRequestReviewId
2074
- };
2075
- }
2076
- function buildObserveModelView(input) {
2077
- const relevant = input.records;
2078
- return {
2079
- snapshotId: input.snapshot.snapshotId,
2080
- observedAt: input.snapshot.observedAt,
2081
- completedAt: input.snapshot.completedAt,
2082
- prState: input.snapshot.prState,
2083
- headOid: input.snapshot.headOid,
2084
- ...input.snapshot.prCreatedAt === void 0 ? {} : { prCreatedAt: input.snapshot.prCreatedAt },
2085
- complete: input.snapshot.complete,
2086
- evidence: relevant.map((record4) => projectEvidenceEntryView(record4)),
2087
- requestAttempts: input.attempts.map((attempt) => ({
2088
- attemptId: attempt.attemptId,
2089
- requestId: attempt.requestId,
2090
- observedHead: attempt.observedHead,
2091
- status: attempt.status,
2092
- marker: attempt.marker,
2093
- recoverySnapshotId: attempt.recoverySnapshotId
2094
- }))
2095
- };
2096
- }
2097
- var COLLECTOR_OBSERVE_TOOL, COLLECTOR_READ_TOOL, COLLECTOR_REQUEST_TOOL, COLLECTOR_WAIT_TOOL, COLLECTOR_OPEN_WAIT_WINDOW_TOOL, COLLECTOR_BIND_TARGET_TOOL, COLLECTOR_HANDBOOK_WRITE_TOOL, COLLECTOR_OPERATIONAL_TOOLS, COLLECTOR_ACTIVATION_ENTRY_TYPE, COLLECTOR_SNAPSHOT_ENTRY_TYPE, COLLECTOR_REQUEST_ENTRY_TYPE, COLLECTOR_WAIT_ENTRY_TYPE;
2098
- var init_collector_ledger = __esm({
2099
- "src/collector-ledger.ts"() {
165
+ // src/package-contracts/reviewer-output.ts
166
+ var REVIEWER_OUTPUT_TOOL_NAME;
167
+ var init_reviewer_output = __esm({
168
+ "src/package-contracts/reviewer-output.ts"() {
2100
169
  "use strict";
2101
- init_collector_evidence();
2102
- init_collector_github();
2103
- init_collector_identity();
2104
- init_collector_output();
2105
- COLLECTOR_OBSERVE_TOOL = "ak_collector_observe";
2106
- COLLECTOR_READ_TOOL = "ak_collector_read";
2107
- COLLECTOR_REQUEST_TOOL = "ak_collector_request";
2108
- COLLECTOR_WAIT_TOOL = "ak_collector_wait";
2109
- COLLECTOR_OPEN_WAIT_WINDOW_TOOL = "ak_collector_open_wait_window";
2110
- COLLECTOR_BIND_TARGET_TOOL = "ak_collector_bind_target";
2111
- COLLECTOR_HANDBOOK_WRITE_TOOL = "ak_collector_handbook_write";
2112
- COLLECTOR_OPERATIONAL_TOOLS = [
2113
- COLLECTOR_BIND_TARGET_TOOL,
2114
- COLLECTOR_OBSERVE_TOOL,
2115
- COLLECTOR_READ_TOOL,
2116
- COLLECTOR_REQUEST_TOOL,
2117
- COLLECTOR_OPEN_WAIT_WINDOW_TOOL,
2118
- COLLECTOR_WAIT_TOOL,
2119
- COLLECTOR_HANDBOOK_WRITE_TOOL
2120
- ];
2121
- COLLECTOR_ACTIVATION_ENTRY_TYPE = "ak-collector-activation";
2122
- COLLECTOR_SNAPSHOT_ENTRY_TYPE = "ak-collector-snapshot";
2123
- COLLECTOR_REQUEST_ENTRY_TYPE = "ak-collector-request";
2124
- COLLECTOR_WAIT_ENTRY_TYPE = "ak-collector-wait";
170
+ REVIEWER_OUTPUT_TOOL_NAME = "ak_reviewer_output";
2125
171
  }
2126
172
  });
2127
173
 
@@ -2324,27 +370,27 @@ function causeMessage(cause) {
2324
370
  return String(cause);
2325
371
  }
2326
372
  }
2327
- function fail2(cause) {
373
+ function fail(cause) {
2328
374
  throw new FixerPacketValidationError(cause);
2329
375
  }
2330
376
  function parseFailure(value) {
2331
- if (!Array.isArray(value)) fail2(new Error("Fixer prerequisites must be a JSON array"));
377
+ if (!Array.isArray(value)) fail(new Error("Fixer prerequisites must be a JSON array"));
2332
378
  for (const entry of value) {
2333
379
  if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
2334
- fail2(new Error("Fixer prerequisite entry must be an object with id and requirement fields"));
380
+ fail(new Error("Fixer prerequisite entry must be an object with id and requirement fields"));
2335
381
  }
2336
382
  const keys = Object.keys(entry);
2337
383
  if (keys.length !== 2 || !keys.includes("id") || !keys.includes("requirement")) {
2338
- fail2(new Error("Fixer prerequisite entry fields must be exactly id and requirement"));
384
+ fail(new Error("Fixer prerequisite entry fields must be exactly id and requirement"));
2339
385
  }
2340
386
  if (typeof entry.id !== "string" || !new RegExp(FIXER_PREREQUISITE_ID_PATTERN).test(entry.id)) {
2341
- fail2(new Error(`Fixer prerequisite id violates pattern ${FIXER_PREREQUISITE_ID_PATTERN}`));
387
+ fail(new Error(`Fixer prerequisite id violates pattern ${FIXER_PREREQUISITE_ID_PATTERN}`));
2342
388
  }
2343
389
  if (typeof entry.requirement !== "string" || !/\S/.test(entry.requirement)) {
2344
- fail2(new Error("Fixer prerequisite requirement must be nonblank"));
390
+ fail(new Error("Fixer prerequisite requirement must be nonblank"));
2345
391
  }
2346
392
  }
2347
- fail2(new Error("Fixer prerequisites violate the attachment schema"));
393
+ fail(new Error("Fixer prerequisites violate the attachment schema"));
2348
394
  }
2349
395
  function validateFixerPrerequisites(value) {
2350
396
  if (!Value.Check(fixerPrerequisitesSchema, value)) parseFailure(value);
@@ -2352,7 +398,7 @@ function validateFixerPrerequisites(value) {
2352
398
  const ids = /* @__PURE__ */ new Set();
2353
399
  const prerequisites = entries.map((entry) => {
2354
400
  if (ids.has(entry.id)) {
2355
- fail2(new Error(`Fixer prerequisites contain duplicate id: ${entry.id}`));
401
+ fail(new Error(`Fixer prerequisites contain duplicate id: ${entry.id}`));
2356
402
  }
2357
403
  ids.add(entry.id);
2358
404
  return Object.freeze({ id: entry.id, requirement: entry.requirement });
@@ -2364,7 +410,7 @@ function parseFixerPrerequisites(source) {
2364
410
  try {
2365
411
  decoded = JSON.parse(source);
2366
412
  } catch (error) {
2367
- fail2(error);
413
+ fail(error);
2368
414
  }
2369
415
  return validateFixerPrerequisites(decoded);
2370
416
  }
@@ -2543,7 +589,7 @@ var init_exact_utf8 = __esm({
2543
589
 
2544
590
  // src/merger-contracts.ts
2545
591
  import { Type as Type9 } from "typebox";
2546
- function fail3(message = "Merger input violates its exact contract") {
592
+ function fail2(message = "Merger input violates its exact contract") {
2547
593
  throw new MergerInputContractError(message);
2548
594
  }
2549
595
  function deepFreeze(value) {
@@ -2554,18 +600,18 @@ function deepFreeze(value) {
2554
600
  return value;
2555
601
  }
2556
602
  function readMaterial(value, label) {
2557
- if (!record2(value) || typeof value.bytesBase64 !== "string") fail3(`Merger ${label} material is malformed`);
603
+ if (!record(value) || typeof value.bytesBase64 !== "string") fail2(`Merger ${label} material is malformed`);
2558
604
  exactUtf8(Buffer.from(value.bytesBase64, "base64"), `Merger ${label} material`);
2559
605
  return { bytesBase64: value.bytesBase64, sha256: typeof value.sha256 === "string" ? value.sha256 : "" };
2560
606
  }
2561
607
  function validateMergerInput(value) {
2562
- if (!record2(value) || blank(value.attemptId)) fail3("Merger input requires a non-empty attemptId for accounting");
2563
- if (!record2(value.materials)) fail3("Merger materials are missing");
608
+ if (!record(value) || blank(value.attemptId)) fail2("Merger input requires a non-empty attemptId for accounting");
609
+ if (!record(value.materials)) fail2("Merger materials are missing");
2564
610
  const materials = { task: readMaterial(value.materials.task, "task"), authority: readMaterial(value.materials.authority, "authority"), targetIntent: readMaterial(value.materials.targetIntent, "targetIntent"), sourceIntent: readMaterial(value.materials.sourceIntent, "sourceIntent") };
2565
- const authorizedChecks = Array.isArray(value.authorizedChecks) ? value.authorizedChecks.filter((check) => record2(check)).map((c) => ({ name: asString(c.name), argv: asStringArray(c.argv).filter((a) => a.trim().length > 0) })).filter((c) => c.name.trim().length > 0 && c.argv.length > 0) : [];
611
+ const authorizedChecks = Array.isArray(value.authorizedChecks) ? value.authorizedChecks.filter((check) => record(check)).map((c) => ({ name: asString(c.name), argv: asStringArray(c.argv).filter((a) => a.trim().length > 0) })).filter((c) => c.name.trim().length > 0 && c.argv.length > 0) : [];
2566
612
  return deepFreeze(structuredClone({ attemptId: value.attemptId.trim(), targetObjectId: asString(value.targetObjectId), sourceObjectId: asString(value.sourceObjectId), materials, expectedConflictPaths: asStringArray(value.expectedConflictPaths), resolutionScope: asStringArray(value.resolutionScope), authorizedChecks }));
2567
613
  }
2568
- var materialSchema, checkSchema, mergerInputSchema, MERGER_STATUS_DESCRIPTION, mergerOutputVariants, mergerOutputSchema, MERGER_OUTPUT_TOOL_NAME, record2, blank, MergerInputContractError, asString, asStringArray;
614
+ var materialSchema, checkSchema, mergerInputSchema, MERGER_STATUS_DESCRIPTION, mergerOutputVariants, mergerOutputSchema, MERGER_OUTPUT_TOOL_NAME, record, blank, MergerInputContractError, asString, asStringArray;
2569
615
  var init_merger_contracts = __esm({
2570
616
  "src/merger-contracts.ts"() {
2571
617
  "use strict";
@@ -2590,7 +636,7 @@ var init_merger_contracts = __esm({
2590
636
  ]);
2591
637
  mergerOutputSchema = withTerminatingOutputDeclarations(openToolObjectFromUnion(mergerOutputVariants));
2592
638
  MERGER_OUTPUT_TOOL_NAME = "ak_merger_output";
2593
- record2 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
639
+ record = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
2594
640
  blank = (v) => typeof v !== "string" || v.trim().length === 0;
2595
641
  MergerInputContractError = class extends Error {
2596
642
  constructor(message = "Merger input violates its exact contract") {
@@ -2683,7 +729,7 @@ var init_auditor_output = __esm({
2683
729
  });
2684
730
 
2685
731
  // src/ticket-provenance-contracts.ts
2686
- function isRecord2(value) {
732
+ function isRecord(value) {
2687
733
  return typeof value === "object" && value !== null && !Array.isArray(value);
2688
734
  }
2689
735
  function positiveInteger(value) {
@@ -2695,7 +741,7 @@ function positiveInteger(value) {
2695
741
  return void 0;
2696
742
  }
2697
743
  function projectBound(value) {
2698
- if (!isRecord2(value)) return void 0;
744
+ if (!isRecord(value)) return void 0;
2699
745
  const id = typeof value.id === "string" && value.id !== "" ? value.id : void 0;
2700
746
  const line2 = positiveInteger(value.line);
2701
747
  if (id === void 0 && line2 === void 0) return void 0;
@@ -2706,13 +752,13 @@ function projectTicketProvenanceSessions(value) {
2706
752
  if (value.length === 0) return [];
2707
753
  const sessions = [];
2708
754
  for (const raw of value) {
2709
- if (!isRecord2(raw)) return void 0;
755
+ if (!isRecord(raw)) return void 0;
2710
756
  const path = raw.path;
2711
757
  if (typeof path !== "string" || path.trim() === "") return void 0;
2712
758
  if (!Array.isArray(raw.ranges) || raw.ranges.length === 0) return void 0;
2713
759
  const ranges = [];
2714
760
  for (const rawRange of raw.ranges) {
2715
- if (!isRecord2(rawRange)) return void 0;
761
+ if (!isRecord(rawRange)) return void 0;
2716
762
  const from = projectBound(rawRange.from);
2717
763
  const to = projectBound(rawRange.to);
2718
764
  if (from === void 0 || to === void 0) return void 0;
@@ -2741,7 +787,7 @@ __export(run_ticket_number_exports, {
2741
787
  readRunTicketNumber: () => readRunTicketNumber,
2742
788
  requireSafePositiveTicketNumber: () => requireSafePositiveTicketNumber
2743
789
  });
2744
- import { readFile as readFile2 } from "node:fs/promises";
790
+ import { readFile } from "node:fs/promises";
2745
791
  import { join } from "node:path";
2746
792
  function isEnoent(error) {
2747
793
  return error instanceof Error && "code" in error && error.code === "ENOENT";
@@ -2771,7 +817,7 @@ function ticketFromRecord(record4) {
2771
817
  }
2772
818
  async function readJsonObject(path) {
2773
819
  try {
2774
- const raw = JSON.parse(await readFile2(path, "utf8"));
820
+ const raw = JSON.parse(await readFile(path, "utf8"));
2775
821
  if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
2776
822
  return void 0;
2777
823
  }
@@ -3117,7 +1163,6 @@ var init_packaged_role_registry = __esm({
3117
1163
  "src/packaged-role-registry.ts"() {
3118
1164
  "use strict";
3119
1165
  init_collector_output();
3120
- init_collector_ledger();
3121
1166
  init_gatekeeper_output();
3122
1167
  init_navigator_output();
3123
1168
  init_judge_output();
@@ -3313,23 +1358,18 @@ var init_packaged_role_registry = __esm({
3313
1358
  ]
3314
1359
  },
3315
1360
  // ak-collector-repo is GitHub owner/repo identity, not a local material path (#438).
1361
+ // #1088: seat + request-manifest kept; code no longer collects — LLM uses host CLI.
3316
1362
  {
3317
1363
  role: "collector",
3318
1364
  inCallAutoResume: false,
3319
1365
  presentSettled: "always",
3320
1366
  summonResume: false,
3321
1367
  admission: "collect-target",
3322
- /** Public no_receipt projects a durable bind-target rejection. */
3323
- projectTargetBindRejection: true,
3324
1368
  sameParent: "none",
3325
1369
  phases: [null],
3326
1370
  bareCommand: false,
3327
1371
  outputTool: COLLECTOR_OUTPUT_TOOL,
3328
- settlement: "residual",
3329
- /** #633: a prior wait-tool residual must not mask this attempt. */
3330
- residualScan: "current-attempt",
3331
- residualTool: COLLECTOR_WAIT_TOOL,
3332
- runnerFailure: "collector-known-first",
1372
+ settlement: "sealed",
3333
1373
  artifactFace: {
3334
1374
  evidenceRole: true,
3335
1375
  leaves: [
@@ -3344,11 +1384,14 @@ var init_packaged_role_registry = __esm({
3344
1384
  activationFlags: [
3345
1385
  { field: "repo", from: "repository.display", flag: "ak-collector-repo" },
3346
1386
  { field: "pr", from: "prNumber", text: true, flag: "ak-collector-pr" },
3347
- { field: "requestManifestPath", flag: "ak-collector-request-manifest" },
3348
- { field: "waitMs", from: "waitWindowMs", text: true, flag: "ak-collector-wait-ms" }
1387
+ { field: "requestManifestPath", flag: "ak-collector-request-manifest" }
3349
1388
  ],
3350
1389
  activationStage: "load-and-install",
3351
- sessionMaterials: ["CLAUDE.md", "souls/collector.md"]
1390
+ sessionMaterials: [
1391
+ "CLAUDE.md",
1392
+ "souls/collector.md",
1393
+ "resources/collector-bot-handbook.md"
1394
+ ]
3352
1395
  },
3353
1396
  {
3354
1397
  role: "doctor",
@@ -3637,8 +1680,131 @@ var init_packaged_role_registry = __esm({
3637
1680
  "resources/diarist-collect.md"
3638
1681
  ]
3639
1682
  }
3640
- ];
3641
- PACKAGED_ROLE_REGISTRY = PUBLIC_ROLE_RECORDS.map(({ sessionMaterials: _omit, ...metadata }) => metadata);
1683
+ ];
1684
+ PACKAGED_ROLE_REGISTRY = PUBLIC_ROLE_RECORDS.map(({ sessionMaterials: _omit, ...metadata }) => metadata);
1685
+ }
1686
+ });
1687
+
1688
+ // src/readable-gate-item.ts
1689
+ var readable_gate_item_exports = {};
1690
+ __export(readable_gate_item_exports, {
1691
+ joinReadableGateItems: () => joinReadableGateItems,
1692
+ readableGateItem: () => readableGateItem
1693
+ });
1694
+ function readableGateItem(value) {
1695
+ return typeof value === "string" ? value : JSON.stringify(value);
1696
+ }
1697
+ function joinReadableGateItems(items, separator = "; ") {
1698
+ return items.map(readableGateItem).join(separator);
1699
+ }
1700
+ var init_readable_gate_item = __esm({
1701
+ "src/readable-gate-item.ts"() {
1702
+ "use strict";
1703
+ }
1704
+ });
1705
+
1706
+ // src/submission-errors.ts
1707
+ function serializeReceipt(receipt) {
1708
+ return readableGateItem(receipt);
1709
+ }
1710
+ function gatekeeperNonPassMessage(result) {
1711
+ if (result.status === "continue") {
1712
+ return serializeReceipt(result.receipt);
1713
+ }
1714
+ if (result.status === "transport_failure") {
1715
+ const head = `\u95E8\u4E0B\u7701 ${result.status}\uFF08${result.stage}\uFF09\uFF1A${result.reason}`;
1716
+ return result.submission === void 0 ? head : `${head}
1717
+ ${serializeReceipt(result.submission)}`;
1718
+ }
1719
+ return `\u95E8\u4E0B\u7701 ${result.status}\uFF08${result.stage}\uFF09\uFF1A${result.reason}`;
1720
+ }
1721
+ function unreadableDiscriminatorNotice(field, received) {
1722
+ if (received === void 0) return `\u8BFB\u4E0D\u51FA ${field}`;
1723
+ return `\u8BFB\u4E0D\u51FA ${field}\uFF1A${readableGateItem(received)}`;
1724
+ }
1725
+ function receivedDiscriminator(receipt, field) {
1726
+ if (receipt === null || typeof receipt !== "object" || Array.isArray(receipt)) return void 0;
1727
+ if (!Object.hasOwn(receipt, field)) return void 0;
1728
+ return receipt[field];
1729
+ }
1730
+ var GatekeeperDecisionError, WorkerCommitReminderError, WorkerPrefixReminderError, WorkerUnfinishedReasonReminderError, ParentQueueReaskError;
1731
+ var init_submission_errors = __esm({
1732
+ "src/submission-errors.ts"() {
1733
+ "use strict";
1734
+ init_readable_gate_item();
1735
+ GatekeeperDecisionError = class extends Error {
1736
+ result;
1737
+ constructor(result, message) {
1738
+ super(message ?? gatekeeperNonPassMessage(result));
1739
+ this.name = "GatekeeperDecisionError";
1740
+ this.result = result;
1741
+ }
1742
+ };
1743
+ WorkerCommitReminderError = class extends Error {
1744
+ code = "worker_commit_reminder";
1745
+ constructor() {
1746
+ super("\u672A\u89C2\u5BDF\u5230 commit");
1747
+ this.name = "WorkerCommitReminderError";
1748
+ }
1749
+ };
1750
+ WorkerPrefixReminderError = class extends Error {
1751
+ code = "worker_prefix_reminder";
1752
+ constructor() {
1753
+ super("\u89C2\u5BDF\u5230\u7F3A\u524D\u7F00 commit");
1754
+ this.name = "WorkerPrefixReminderError";
1755
+ }
1756
+ };
1757
+ WorkerUnfinishedReasonReminderError = class extends Error {
1758
+ code = "worker_unfinished_reason_reminder";
1759
+ constructor() {
1760
+ super("\u672C\u6B21 unfinished \u56DE\u6267\u672A\u542B reason\uFF1B\u672C\u63A5\u7F1D\u7F3A\u7531\u81F3\u591A\u6253\u56DE\u4E24\u6B21\u3002");
1761
+ this.name = "WorkerUnfinishedReasonReminderError";
1762
+ }
1763
+ };
1764
+ ParentQueueReaskError = class extends Error {
1765
+ code = "parent_queue_reask";
1766
+ constructor(message) {
1767
+ super(message);
1768
+ this.name = "ParentQueueReaskError";
1769
+ }
1770
+ };
1771
+ }
1772
+ });
1773
+
1774
+ // src/submission-correctable-error.ts
1775
+ function isCorrectableSubmissionError(error) {
1776
+ return error instanceof CorrectableSubmissionError;
1777
+ }
1778
+ function isCorrectableExecuteError(error) {
1779
+ return isCorrectableSubmissionError(error) || error instanceof GatekeeperDecisionError || error instanceof ParentQueueReaskError || error instanceof WorkerCommitReminderError || error instanceof WorkerPrefixReminderError || error instanceof WorkerUnfinishedReasonReminderError;
1780
+ }
1781
+ function projectCorrectableExecuteRejection(error) {
1782
+ const diagnostic = error instanceof Error ? error.message : String(error);
1783
+ if (error instanceof GatekeeperDecisionError) {
1784
+ return { diagnostic, details: { ...error.result } };
1785
+ }
1786
+ if (error instanceof WorkerCommitReminderError || error instanceof WorkerPrefixReminderError || error instanceof WorkerUnfinishedReasonReminderError) {
1787
+ return { diagnostic, details: { code: error.code } };
1788
+ }
1789
+ if (typeof error.code === "string") {
1790
+ return { diagnostic, details: { code: error.code } };
1791
+ }
1792
+ return {
1793
+ diagnostic,
1794
+ details: {
1795
+ code: error instanceof Error && error.name ? error.name : "correctable-submission-error"
1796
+ }
1797
+ };
1798
+ }
1799
+ var correctableSubmissionErrorBrand, CorrectableSubmissionError;
1800
+ var init_submission_correctable_error = __esm({
1801
+ "src/submission-correctable-error.ts"() {
1802
+ "use strict";
1803
+ init_submission_errors();
1804
+ correctableSubmissionErrorBrand = /* @__PURE__ */ Symbol("ak-roles.correctable-submission-error");
1805
+ CorrectableSubmissionError = class extends Error {
1806
+ [correctableSubmissionErrorBrand] = true;
1807
+ };
3642
1808
  }
3643
1809
  });
3644
1810
 
@@ -3702,9 +1868,9 @@ var init_terminating_tools = __esm({
3702
1868
  });
3703
1869
 
3704
1870
  // src/doctor-evidence.ts
3705
- import { readdir, readFile as readFile3, realpath, stat } from "node:fs/promises";
1871
+ import { readdir, readFile as readFile2, realpath, stat } from "node:fs/promises";
3706
1872
  import { dirname, relative, resolve, sep } from "node:path";
3707
- function record3(value) {
1873
+ function record2(value) {
3708
1874
  return typeof value === "object" && value !== null && !Array.isArray(value);
3709
1875
  }
3710
1876
  async function discoverCaseFiles(root) {
@@ -3753,7 +1919,7 @@ function deriveSession(content, id) {
3753
1919
  for (const line2 of content.split("\n")) if (line2.trim()) {
3754
1920
  try {
3755
1921
  const row = JSON.parse(line2);
3756
- if (!record3(row)) {
1922
+ if (!record2(row)) {
3757
1923
  degradationReasons.push(`non-object session row in ${id}`);
3758
1924
  break;
3759
1925
  }
@@ -3772,17 +1938,17 @@ function deriveSession(content, id) {
3772
1938
  let accepted, observedCommit, turns = 0, calls = 0, tokens = 0;
3773
1939
  const statuses = [], commits = [];
3774
1940
  for (const row of rows) {
3775
- if (row.type === "custom" && row.customType === "ak-role-submission-closure" && record3(row.data) && row.data.isError === false && typeof row.data.toolName === "string" && isTerminatingToolName(row.data.toolName)) accepted = row;
3776
- const message = record3(row.message) ? row.message : void 0;
1941
+ if (row.type === "custom" && row.customType === "ak-role-submission-closure" && record2(row.data) && row.data.isError === false && typeof row.data.toolName === "string" && isTerminatingToolName(row.data.toolName)) accepted = row;
1942
+ const message = record2(row.message) ? row.message : void 0;
3777
1943
  if (message?.role === "assistant") {
3778
- for (const part of Array.isArray(message.content) ? message.content : []) if (record3(part) && part.type === "toolCall") calls++;
1944
+ for (const part of Array.isArray(message.content) ? message.content : []) if (record2(part) && part.type === "toolCall") calls++;
3779
1945
  if (typeof message.responseId === "string") {
3780
1946
  turns++;
3781
- const usage = record3(message.usage) ? message.usage : void 0;
1947
+ const usage = record2(message.usage) ? message.usage : void 0;
3782
1948
  if (usage && typeof usage.output === "number") tokens += usage.output;
3783
1949
  }
3784
1950
  }
3785
- if (message?.role === "toolResult" && message.isError !== true && typeof message.toolName === "string" && isTerminatingToolName(message.toolName) && record3(message.details)) {
1951
+ if (message?.role === "toolResult" && message.isError !== true && typeof message.toolName === "string" && isTerminatingToolName(message.toolName) && record2(message.details)) {
3786
1952
  let details;
3787
1953
  try {
3788
1954
  details = validateAcceptedDetails(message.toolName, message.details);
@@ -3818,7 +1984,7 @@ async function loadDoctorCase(runsPath) {
3818
1984
  const turns = { count: 0, sources: [] }, calls = { count: 0, sources: [] }, tokens = { count: 0, sources: [] };
3819
1985
  for (const path of await discoverCaseFiles(root)) {
3820
1986
  const id = relative(root, path).split(sep).join("/");
3821
- const bytes = await readFile3(path);
1987
+ const bytes = await readFile2(path);
3822
1988
  const content = bytes.toString("utf8");
3823
1989
  const kind = id.endsWith(".jsonl") ? "session" : "stderr";
3824
1990
  evidence.push({ id, kind, byteLength: bytes.byteLength, contentLength: content.length, sha256: sha256Hex(bytes), content });
@@ -4578,15 +2744,15 @@ var init_sitian_appender = __esm({
4578
2744
 
4579
2745
  // src/sitian-reader.ts
4580
2746
  import { existsSync } from "node:fs";
4581
- import { readFile as readFile4 } from "node:fs/promises";
4582
- function isRecord3(value) {
2747
+ import { readFile as readFile3 } from "node:fs/promises";
2748
+ function isRecord2(value) {
4583
2749
  return typeof value === "object" && value !== null && !Array.isArray(value);
4584
2750
  }
4585
2751
  async function readSitianRecords(recordFile) {
4586
2752
  if (!existsSync(recordFile)) {
4587
2753
  return { records: [], diagnostics: [] };
4588
2754
  }
4589
- const text = await readFile4(recordFile, "utf8");
2755
+ const text = await readFile3(recordFile, "utf8");
4590
2756
  const lines = text.split("\n");
4591
2757
  const records = [];
4592
2758
  const diagnostics = [];
@@ -4595,7 +2761,7 @@ async function readSitianRecords(recordFile) {
4595
2761
  if (!line2.trim()) continue;
4596
2762
  try {
4597
2763
  const parsed = JSON.parse(line2);
4598
- if (isRecord3(parsed)) {
2764
+ if (isRecord2(parsed)) {
4599
2765
  records.push(parsed);
4600
2766
  } else {
4601
2767
  const typeDesc = parsed === null ? "null" : Array.isArray(parsed) ? "array" : typeof parsed;
@@ -4943,7 +3109,7 @@ __export(config_exports, {
4943
3109
  setPersistentSeatHost: () => setPersistentSeatHost,
4944
3110
  validatePublicCliConfigAxes: () => validatePublicCliConfigAxes
4945
3111
  });
4946
- import { mkdir, readFile as readFile5, writeFile } from "node:fs/promises";
3112
+ import { mkdir, readFile as readFile4, writeFile } from "node:fs/promises";
4947
3113
  import { dirname as dirname5, join as join5 } from "node:path";
4948
3114
  function isGateOfficerSeat(value) {
4949
3115
  return packagedProvinceConfig(value);
@@ -4957,7 +3123,7 @@ function publicCliConfigPath(home) {
4957
3123
  async function loadPublicCliConfig(home) {
4958
3124
  const path = publicCliConfigPath(home);
4959
3125
  try {
4960
- const raw = await readFile5(path, "utf8");
3126
+ const raw = await readFile4(path, "utf8");
4961
3127
  return parsePublicCliConfig(JSON.parse(raw));
4962
3128
  } catch (error) {
4963
3129
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -5415,7 +3581,7 @@ function credentialProvidersFromAuthData(data) {
5415
3581
  }
5416
3582
  async function loadCredentialProviders(agentDir) {
5417
3583
  try {
5418
- const raw = await readFile5(join5(agentDir, "auth.json"), "utf8");
3584
+ const raw = await readFile4(join5(agentDir, "auth.json"), "utf8");
5419
3585
  return credentialProvidersFromAuthData(JSON.parse(raw));
5420
3586
  } catch (error) {
5421
3587
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -5666,7 +3832,7 @@ var init_durable_principal = __esm({
5666
3832
  });
5667
3833
 
5668
3834
  // src/typed-provider-http.ts
5669
- import { readFile as readFile7, unlink, writeFile as writeFile3 } from "node:fs/promises";
3835
+ import { readFile as readFile6, unlink, writeFile as writeFile3 } from "node:fs/promises";
5670
3836
  import { join as join10 } from "node:path";
5671
3837
  function typedProviderHttpPath(runDirectory) {
5672
3838
  return join10(runDirectory, TYPED_HTTP_FILE);
@@ -5700,7 +3866,7 @@ async function recordTypedProviderHttpStatus(runDirectory, observation) {
5700
3866
  async function readLatestTypedProviderHttpObservation(runDirectory) {
5701
3867
  let text;
5702
3868
  try {
5703
- text = await readFile7(typedProviderHttpPath(runDirectory), "utf8");
3869
+ text = await readFile6(typedProviderHttpPath(runDirectory), "utf8");
5704
3870
  } catch (error) {
5705
3871
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
5706
3872
  return void 0;
@@ -5728,6 +3894,84 @@ var init_typed_provider_http = __esm({
5728
3894
  }
5729
3895
  });
5730
3896
 
3897
+ // src/collector-config.ts
3898
+ import { createHash as createHash2 } from "node:crypto";
3899
+ import { readFile as readFile7 } from "node:fs/promises";
3900
+ function fail3(message, cause) {
3901
+ throw new Error(message, cause === void 0 ? void 0 : { cause });
3902
+ }
3903
+ function conservativeAscii(input) {
3904
+ for (let i = 0; i < input.length; i += 1) {
3905
+ const code = input.charCodeAt(i);
3906
+ if (code <= 31 || code === 127 || code > 127) return false;
3907
+ }
3908
+ return true;
3909
+ }
3910
+ function parseCollectorRepository(raw) {
3911
+ if (typeof raw !== "string" || raw.trim() !== raw || raw.length === 0) fail3("Collector repository must be a string owner/repo");
3912
+ if (!conservativeAscii(raw) || raw.includes("://") || /[?#@%\\ ]/.test(raw)) fail3("Collector repository rejects URL syntax and non-identity bytes");
3913
+ const parts = raw.split("/");
3914
+ if (parts.length !== 2) fail3("Collector repository must contain exactly one '/' separating owner and repo");
3915
+ const [ownerDisplay, repoDisplay] = parts;
3916
+ if (!COLLECTOR_OWNER_PATTERN.test(ownerDisplay) || !COLLECTOR_REPO_PATTERN.test(repoDisplay)) fail3("Collector repository does not match the conservative owner/repo grammar");
3917
+ const owner = ownerDisplay.toLowerCase();
3918
+ const repo = repoDisplay.toLowerCase();
3919
+ return { display: raw, canonical: `${owner}/${repo}`, owner, repo };
3920
+ }
3921
+ function parseCollectorPrNumber(raw) {
3922
+ if (typeof raw === "string" && !/^[1-9][0-9]*$/.test(raw)) fail3("Collector pull request number must be a positive safe integer string");
3923
+ if (typeof raw !== "string" && typeof raw !== "number") fail3("Collector pull request number is required");
3924
+ const value = Number(raw);
3925
+ if (!Number.isSafeInteger(value) || value < 1) fail3("Collector pull request number must be a positive safe integer");
3926
+ return value;
3927
+ }
3928
+ function record3(value) {
3929
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3930
+ }
3931
+ function canonicalManifest(requests) {
3932
+ return `${JSON.stringify({ requests: requests.map((request) => ({ id: request.id, body: request.requestBody })) })}
3933
+ `;
3934
+ }
3935
+ function emptyCollectorManifest() {
3936
+ const canonicalJson2 = canonicalManifest([]);
3937
+ return { requests: [], canonicalJson: canonicalJson2, digest: createHash2("sha256").update(canonicalJson2).digest("hex") };
3938
+ }
3939
+ async function loadCollectorManifest(path) {
3940
+ let bytes;
3941
+ try {
3942
+ bytes = await readFile7(path);
3943
+ } catch (error) {
3944
+ fail3(`Collector request manifest is unreadable at ${path}`, error);
3945
+ }
3946
+ let parsed;
3947
+ try {
3948
+ parsed = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
3949
+ } catch (error) {
3950
+ fail3("Collector request manifest must be UTF-8 JSON", error);
3951
+ }
3952
+ if (!record3(parsed)) fail3("Collector request manifest must be an object");
3953
+ const rawRequests = parsed.requests ?? [];
3954
+ if (!Array.isArray(rawRequests)) fail3("Collector request manifest requests must be an array");
3955
+ const requests = [];
3956
+ const ids = /* @__PURE__ */ new Set();
3957
+ for (const [index, item] of rawRequests.entries()) {
3958
+ if (!record3(item) || typeof item.id !== "string" || item.id.length === 0 || typeof item.body !== "string" || item.body.trim() === "") fail3(`Collector request manifest requests[${index}] is invalid`);
3959
+ if (ids.has(item.id)) fail3(`Collector request manifest has duplicate request id "${item.id}"`);
3960
+ ids.add(item.id);
3961
+ requests.push({ id: item.id, requestBody: item.body });
3962
+ }
3963
+ const canonicalJson2 = canonicalManifest(requests);
3964
+ return { requests, canonicalJson: canonicalJson2, digest: createHash2("sha256").update(canonicalJson2).digest("hex"), sourcePath: path };
3965
+ }
3966
+ var COLLECTOR_OWNER_PATTERN, COLLECTOR_REPO_PATTERN;
3967
+ var init_collector_config = __esm({
3968
+ "src/collector-config.ts"() {
3969
+ "use strict";
3970
+ COLLECTOR_OWNER_PATTERN = /^[A-Za-z0-9](?:[A-Za-z0-9-]{0,37}[A-Za-z0-9])?$/;
3971
+ COLLECTOR_REPO_PATTERN = /^[A-Za-z0-9](?:[A-Za-z0-9._-]{0,98}[A-Za-z0-9])?$/;
3972
+ }
3973
+ });
3974
+
5731
3975
  // src/auditor-dossier-tool.ts
5732
3976
  var auditor_dossier_tool_exports = {};
5733
3977
  __export(auditor_dossier_tool_exports, {
@@ -5797,14 +4041,14 @@ function isMissingPathError3(error) {
5797
4041
  function errorText2(error) {
5798
4042
  return error instanceof Error ? error.message : String(error);
5799
4043
  }
5800
- function isRecord4(value) {
4044
+ function isRecord3(value) {
5801
4045
  return typeof value === "object" && value !== null && !Array.isArray(value);
5802
4046
  }
5803
4047
  function readUsableTerminalArtifactBody(body) {
5804
4048
  if (body === null) {
5805
4049
  return { ok: false, reason: "terminal artifact JSON value is null" };
5806
4050
  }
5807
- if (!isRecord4(body)) {
4051
+ if (!isRecord3(body)) {
5808
4052
  return {
5809
4053
  ok: false,
5810
4054
  reason: `terminal artifact JSON value is not a typed object (${Array.isArray(body) ? "array" : typeof body})`
@@ -6266,10 +4510,10 @@ __export(session_assistant_usage_exports, {
6266
4510
  });
6267
4511
  import { join as join13 } from "node:path";
6268
4512
  async function readAssistantUsageFromSessionFile(sessionFile) {
6269
- const { readFile: readFile26 } = await import("node:fs/promises");
4513
+ const { readFile: readFile25 } = await import("node:fs/promises");
6270
4514
  let text;
6271
4515
  try {
6272
- text = await readFile26(sessionFile, "utf8");
4516
+ text = await readFile25(sessionFile, "utf8");
6273
4517
  } catch (error) {
6274
4518
  if (error?.code === "ENOENT") return void 0;
6275
4519
  throw error;
@@ -6359,7 +4603,7 @@ var init_session_assistant_usage = __esm({
6359
4603
  });
6360
4604
 
6361
4605
  // src/engine-detour.ts
6362
- import { spawn as spawn2 } from "node:child_process";
4606
+ import { spawn } from "node:child_process";
6363
4607
  import { mkdtemp, rm as rm2, writeFile as writeFile4 } from "node:fs/promises";
6364
4608
  import { tmpdir } from "node:os";
6365
4609
  import { join as join14 } from "node:path";
@@ -6410,7 +4654,7 @@ async function spawnEngineDetourOnce(input) {
6410
4654
  return await new Promise((resolve22, reject) => {
6411
4655
  let settled = false;
6412
4656
  const signal = input.signal;
6413
- const child = spawn2(command, args, {
4657
+ const child = spawn(command, args, {
6414
4658
  cwd: input.cwd,
6415
4659
  env: input.env ?? process.env,
6416
4660
  stdio: ["ignore", "pipe", "pipe"]
@@ -6595,7 +4839,7 @@ __export(role_turn_host_exports, {
6595
4839
  createPiRoleTurnHost: () => createPiRoleTurnHost,
6596
4840
  resolveInternalRoleEntrypoint: () => resolveInternalRoleEntrypoint
6597
4841
  });
6598
- import { execFile, spawn as spawn3 } from "node:child_process";
4842
+ import { execFile, spawn as spawn2 } from "node:child_process";
6599
4843
  import { constants } from "node:fs";
6600
4844
  import { access, appendFile, readFile as readFile9, realpath as realpath2 } from "node:fs/promises";
6601
4845
  import { delimiter, dirname as dirname10, isAbsolute as isAbsolute3, join as join15, resolve as resolve7 } from "node:path";
@@ -6705,7 +4949,7 @@ function createDefaultPiSpawnRunner(options) {
6705
4949
  const command = spawnOptions.env.PI_BINARY ?? "pi";
6706
4950
  const piIdentity = await selectedPiIdentity(command, spawnOptions.cwd, spawnOptions.env);
6707
4951
  return await new Promise((resolveResult, reject) => {
6708
- const child = spawn3(piIdentity.executable, [...args], {
4952
+ const child = spawn2(piIdentity.executable, [...args], {
6709
4953
  cwd: spawnOptions.cwd,
6710
4954
  env: spawnOptions.env,
6711
4955
  stdio: ["pipe", "ignore", "pipe"]
@@ -6900,11 +5144,6 @@ var init_role_turn_host = __esm({
6900
5144
  });
6901
5145
 
6902
5146
  // src/public-cli/github-remote.ts
6903
- function ownerFromGitHubRemoteUrl(remoteUrl) {
6904
- const ownerRepo = ownerRepoFromGitHubRemoteUrl(remoteUrl);
6905
- if (ownerRepo === void 0) return void 0;
6906
- return ownerRepo.split("/")[0].toLowerCase();
6907
- }
6908
5147
  function ownerRepoFromGitHubRemoteUrl(remoteUrl) {
6909
5148
  const trimmed = remoteUrl.trim();
6910
5149
  const scp = /^git@github\.com:([^/\s]+)\/([^/\s]+?)(?:\.git)?$/i.exec(trimmed);
@@ -6938,143 +5177,6 @@ var init_github_remote = __esm({
6938
5177
  }
6939
5178
  });
6940
5179
 
6941
- // src/collector-target.ts
6942
- import { execFileSync as execFileSync2 } from "node:child_process";
6943
- function ambiguousTarget(detail, cause) {
6944
- throw new CliUsageError(
6945
- `collector target is ambiguous: ${detail}; pass an explicit --pr`,
6946
- cause === void 0 ? void 0 : { cause }
6947
- );
6948
- }
6949
- function gitFailure(detail, cause) {
6950
- throw new Error(`collector git failed: ${detail}`, {
6951
- cause: cause instanceof Error ? cause : new Error(String(cause))
6952
- });
6953
- }
6954
- function gitText(projectRoot, args) {
6955
- return execFileSync2("git", [...args], {
6956
- cwd: projectRoot,
6957
- encoding: "utf8",
6958
- stdio: ["ignore", "pipe", "pipe"]
6959
- }).trim();
6960
- }
6961
- function isGitConfigMissing(error) {
6962
- if (typeof error !== "object" || error === null) return false;
6963
- const status = error.status;
6964
- return status === 1;
6965
- }
6966
- function readCurrentBranch(projectRoot) {
6967
- try {
6968
- return gitText(projectRoot, ["rev-parse", "--abbrev-ref", "HEAD"]);
6969
- } catch (error) {
6970
- gitFailure("cannot read current git branch", error);
6971
- }
6972
- }
6973
- function readHeadSha(projectRoot) {
6974
- try {
6975
- return gitText(projectRoot, ["rev-parse", "HEAD"]);
6976
- } catch (error) {
6977
- gitFailure("cannot read current HEAD", error);
6978
- }
6979
- }
6980
- function headRefFromMerge(merge) {
6981
- const trimmed = merge.trim();
6982
- if (trimmed.length === 0) return void 0;
6983
- if (trimmed.startsWith("refs/heads/")) {
6984
- const ref = trimmed.slice("refs/heads/".length);
6985
- return ref.length > 0 ? ref : void 0;
6986
- }
6987
- if (trimmed.startsWith("refs/")) return void 0;
6988
- return trimmed;
6989
- }
6990
- function readUpstreamHeadBinding(projectRoot, branch) {
6991
- let remote;
6992
- try {
6993
- remote = gitText(projectRoot, ["config", "--get", `branch.${branch}.remote`]);
6994
- } catch (error) {
6995
- if (isGitConfigMissing(error)) remote = void 0;
6996
- else gitFailure(`cannot read branch.${branch}.remote`, error);
6997
- }
6998
- if (remote === void 0 || remote.length === 0) return void 0;
6999
- let merge;
7000
- try {
7001
- merge = gitText(projectRoot, ["config", "--get", `branch.${branch}.merge`]);
7002
- } catch (error) {
7003
- if (isGitConfigMissing(error)) merge = void 0;
7004
- else gitFailure(`cannot read branch.${branch}.merge`, error);
7005
- }
7006
- if (merge === void 0 || merge.length === 0) return void 0;
7007
- const headRef = headRefFromMerge(merge);
7008
- if (headRef === void 0) return void 0;
7009
- let remoteUrl;
7010
- try {
7011
- remoteUrl = gitText(projectRoot, ["remote", "get-url", remote]);
7012
- } catch (error) {
7013
- gitFailure(`cannot read remote URL for ${remote}`, error);
7014
- }
7015
- const headOwner = ownerFromGitHubRemoteUrl(remoteUrl);
7016
- if (headOwner === void 0) return void 0;
7017
- return { headOwner, headRef };
7018
- }
7019
- async function resolveCollectorTarget(input) {
7020
- if (input.explicitPrNumber !== void 0) {
7021
- return { kind: "bound", prNumber: input.explicitPrNumber };
7022
- }
7023
- const branch = readCurrentBranch(input.projectRoot);
7024
- const detached = branch.length === 0 || branch === "HEAD";
7025
- const runner = createGhApiRunner();
7026
- const { owner, repo } = input.repository;
7027
- const numbers = [];
7028
- if (!detached) {
7029
- const headSha = readHeadSha(input.projectRoot);
7030
- const upstream = readUpstreamHeadBinding(input.projectRoot, branch);
7031
- if (upstream !== void 0) {
7032
- numbers.push(
7033
- ...await listPullRequestNumbersByHead(runner, {
7034
- owner,
7035
- repo,
7036
- headOwner: upstream.headOwner,
7037
- headRef: upstream.headRef
7038
- })
7039
- );
7040
- }
7041
- numbers.push(
7042
- ...await listPullRequestNumbersByCommit(runner, {
7043
- owner,
7044
- repo,
7045
- commitSha: headSha
7046
- })
7047
- );
7048
- } else {
7049
- const headSha = readHeadSha(input.projectRoot);
7050
- numbers.push(
7051
- ...await listPullRequestNumbersByCommit(runner, {
7052
- owner,
7053
- repo,
7054
- commitSha: headSha
7055
- })
7056
- );
7057
- }
7058
- const unique = [...new Set(numbers)];
7059
- if (unique.length === 1) {
7060
- return { kind: "bound", prNumber: unique[0] };
7061
- }
7062
- if (unique.length > 1) {
7063
- ambiguousTarget(
7064
- `multiple PRs associated with context: ${unique.join(", ")}`
7065
- );
7066
- }
7067
- return { kind: "unbound" };
7068
- }
7069
- var init_collector_target = __esm({
7070
- "src/collector-target.ts"() {
7071
- "use strict";
7072
- init_collector_github();
7073
- init_cli_errors();
7074
- init_github_remote();
7075
- }
7076
- });
7077
-
7078
5180
  // src/git-object-id.ts
7079
5181
  function isFullGitObjectId(value) {
7080
5182
  return typeof value === "string" && FULL_GIT_OBJECT_ID_RE.test(value);
@@ -7187,7 +5289,7 @@ var init_merger_git_state = __esm({
7187
5289
 
7188
5290
  // src/ledger-session-read.ts
7189
5291
  import { readFile as readFile11 } from "node:fs/promises";
7190
- function isRecord5(value) {
5292
+ function isRecord4(value) {
7191
5293
  return typeof value === "object" && value !== null && !Array.isArray(value);
7192
5294
  }
7193
5295
  async function readLedgerSessionJsonlLines(path) {
@@ -7212,7 +5314,7 @@ async function readLedgerSessionJsonlLines(path) {
7212
5314
  });
7213
5315
  continue;
7214
5316
  }
7215
- if (!isRecord5(row)) {
5317
+ if (!isRecord4(row)) {
7216
5318
  const kind = row === null ? "null" : Array.isArray(row) ? "array" : typeof row;
7217
5319
  out.push({
7218
5320
  line: lineNumber,
@@ -7265,7 +5367,7 @@ function extractSessionModelSequence(rows) {
7265
5367
  if (row.type === "model_change" && typeof row.modelId === "string") {
7266
5368
  push(row.modelId);
7267
5369
  }
7268
- const message = isRecord5(row.message) ? row.message : void 0;
5370
+ const message = isRecord4(row.message) ? row.message : void 0;
7269
5371
  if (message?.role === "assistant" && typeof message.model === "string") {
7270
5372
  push(message.model);
7271
5373
  }
@@ -7281,11 +5383,11 @@ function extractSessionToolIntervals(rows) {
7281
5383
  const openById = /* @__PURE__ */ new Map();
7282
5384
  for (const row of rows) {
7283
5385
  const rowTimestamp = typeof row.timestamp === "string" ? row.timestamp : void 0;
7284
- const message = isRecord5(row.message) ? row.message : void 0;
5386
+ const message = isRecord4(row.message) ? row.message : void 0;
7285
5387
  if (message?.role === "assistant" && Array.isArray(message.content)) {
7286
5388
  const callTimestamp = typeof message.timestamp === "string" && message.timestamp ? message.timestamp : rowTimestamp;
7287
5389
  for (const part of message.content) {
7288
- if (!isRecord5(part) || part.type !== "toolCall") continue;
5390
+ if (!isRecord4(part) || part.type !== "toolCall") continue;
7289
5391
  if (typeof part.id !== "string" || part.id.length === 0) {
7290
5392
  throw new Error("toolCall frame missing string id");
7291
5393
  }
@@ -7298,7 +5400,7 @@ function extractSessionToolIntervals(rows) {
7298
5400
  if (openById.has(part.id)) {
7299
5401
  throw new Error(`duplicate toolCall id ${part.id}`);
7300
5402
  }
7301
- const args = isRecord5(part.arguments) ? part.arguments : void 0;
5403
+ const args = isRecord4(part.arguments) ? part.arguments : void 0;
7302
5404
  const command = part.name === "bash" && args !== void 0 && typeof args.command === "string" ? bashCommandFirstLine(args.command) : void 0;
7303
5405
  const interval = {
7304
5406
  toolCallId: part.id,
@@ -7382,7 +5484,7 @@ var init_ledger_session_read = __esm({
7382
5484
  });
7383
5485
 
7384
5486
  // src/session-dialogue.ts
7385
- function isRecord6(value) {
5487
+ function isRecord5(value) {
7386
5488
  return typeof value === "object" && value !== null && !Array.isArray(value);
7387
5489
  }
7388
5490
  function nativeEventId(row) {
@@ -7392,7 +5494,7 @@ function nativeEventId(row) {
7392
5494
  }
7393
5495
  for (const nestKey of ["message", "payload"]) {
7394
5496
  const nested = row[nestKey];
7395
- if (!isRecord6(nested)) continue;
5497
+ if (!isRecord5(nested)) continue;
7396
5498
  for (const key of ["uuid", "id"]) {
7397
5499
  const value = nested[key];
7398
5500
  if (typeof value === "string" && value !== "") return value;
@@ -7405,19 +5507,19 @@ function textParts(content) {
7405
5507
  if (!Array.isArray(content)) return [];
7406
5508
  const out = [];
7407
5509
  for (const part of content) {
7408
- if (!isRecord6(part) || !SPEAKER_TEXT_PART_TYPES.has(String(part.type))) continue;
5510
+ if (!isRecord5(part) || !SPEAKER_TEXT_PART_TYPES.has(String(part.type))) continue;
7409
5511
  const text = part.text;
7410
5512
  if (typeof text === "string" && text !== "") out.push(text);
7411
5513
  }
7412
5514
  return out;
7413
5515
  }
7414
5516
  function responseItemMessage(row) {
7415
- if (row.type !== "response_item" || !isRecord6(row.payload)) return void 0;
5517
+ if (row.type !== "response_item" || !isRecord5(row.payload)) return void 0;
7416
5518
  if (row.payload.type !== "message") return void 0;
7417
5519
  return row.payload;
7418
5520
  }
7419
5521
  function messageBody(row) {
7420
- if (isRecord6(row.message)) return row.message;
5522
+ if (isRecord5(row.message)) return row.message;
7421
5523
  return responseItemMessage(row);
7422
5524
  }
7423
5525
  function speakerOf(message) {
@@ -7427,7 +5529,7 @@ function speakerOf(message) {
7427
5529
  }
7428
5530
  function codexContentItemKinds(message) {
7429
5531
  const pass = message.internal_chat_message_metadata_passthrough;
7430
- if (!isRecord6(pass) || !Array.isArray(pass.content_item_kinds)) return void 0;
5532
+ if (!isRecord5(pass) || !Array.isArray(pass.content_item_kinds)) return void 0;
7431
5533
  const kinds = [];
7432
5534
  for (const kind of pass.content_item_kinds) {
7433
5535
  if (typeof kind === "string" && kind !== "") kinds.push(kind);
@@ -7456,7 +5558,7 @@ function isFixedNonOwnerEnqueueShape(content) {
7456
5558
  return hasFixedOpenTagPrefix(content, TASK_NOTIFICATION_OPEN_TAG);
7457
5559
  }
7458
5560
  function materializationOriginKind(row) {
7459
- if (!isRecord6(row.origin)) return void 0;
5561
+ if (!isRecord5(row.origin)) return void 0;
7460
5562
  const kind = row.origin.kind;
7461
5563
  return typeof kind === "string" && kind !== "" ? kind : void 0;
7462
5564
  }
@@ -8439,13 +6541,12 @@ var init_option_definitions = __esm({
8439
6541
  canonical: "--pr",
8440
6542
  aliases: [],
8441
6543
  valueMetavar: "number",
8442
- // #676 D1: optional when context uniquely determines the PR; ambiguous → require explicit.
8443
6544
  required: false,
8444
6545
  repeatable: false,
8445
6546
  form: "option",
8446
6547
  description: {
8447
- en: "Positive GitHub pull request number. Optional when unique branch/HEAD association binds the PR, or when the Collector role can decide the target from task materials via bind-target; multi-candidate git context or a role that cannot decide requires an explicit value.",
8448
- zh: "\u6B63\u6574\u6570 GitHub PR \u53F7\u3002\u5206\u652F/HEAD \u552F\u4E00\u5173\u8054\u53EF\u7ED1\u5B9A\u65F6\u53EF\u7701\u7565\uFF1B\u4EA6\u53EF\u7531\u901A\u8FDB\u53F8\u4ECE\u4EFB\u52A1\u6750\u6599\u7ECF bind-target \u5224\u5B9A\u3002git \u591A\u5019\u9009\u6216\u89D2\u8272\u65E0\u6CD5\u5224\u5B9A\u65F6\u5FC5\u987B\u663E\u5F0F\u63D0\u4F9B\u3002"
6548
+ en: "Positive GitHub pull request number. Optional when the Collector role locates the PR via host CLI from task materials.",
6549
+ zh: "\u6B63\u6574\u6570 GitHub PR \u53F7\u3002\u53EF\u9009\uFF1B\u7701\u7565\u65F6\u7531\u901A\u8FDB\u53F8\u7ECF\u5BBF\u4E3B CLI \u4ECE\u4EFB\u52A1\u6750\u6599\u81EA\u884C\u5B9A\u4F4D\u3002"
8449
6550
  }
8450
6551
  },
8451
6552
  {
@@ -8472,22 +6573,8 @@ var init_option_definitions = __esm({
8472
6573
  repeatable: false,
8473
6574
  form: "option",
8474
6575
  description: {
8475
- en: "Optional request manifest JSON path ({requests:[{id,body}]}). Role may also decide request bodies from handbook/field activity without this file.",
8476
- zh: "\u53EF\u9009 request manifest JSON \u8DEF\u5F84\uFF08{requests:[{id,body}]}\uFF09\u3002\u89D2\u8272\u4EA6\u53EF\u4F9D\u624B\u518C/\u73B0\u573A\u81EA\u884C\u5224\u5B9A\u8BF7\u6C42\u6B63\u6587\uFF0C\u4E0D\u5FC5\u4F9D\u8D56\u672C\u6587\u4EF6\u3002"
8477
- }
8478
- },
8479
- {
8480
- id: "wait-ms",
8481
- owner: "collector",
8482
- canonical: "--wait-ms",
8483
- aliases: [],
8484
- valueMetavar: "ms",
8485
- required: false,
8486
- repeatable: false,
8487
- form: "option",
8488
- description: {
8489
- en: "Wait-window duration in milliseconds after the work step opens (default 600000 = 10 minutes). Does not require a code change to adjust.",
8490
- zh: "\u5DE5\u4F5C\u6B65\u9AA4\u5F00\u542F\u540E\u7684\u7B49\u5F85\u7A97\u65F6\u957F\uFF08\u6BEB\u79D2\uFF1B\u9ED8\u8BA4 600000\uFF1D\u5341\u5206\u949F\uFF09\u3002\u6539\u914D\u7F6E\u5373\u53EF\uFF0C\u65E0\u9700\u6539\u4EE3\u7801\u3002"
6576
+ en: "Optional request manifest JSON path ({requests:[{id,body}]}). Parsed for semantics and passed to the Collector as materials \u2014 not a machine collection directive.",
6577
+ zh: "\u53EF\u9009 request manifest JSON \u8DEF\u5F84\uFF08{requests:[{id,body}]}\uFF09\u3002\u6309\u8BED\u4E49\u89E3\u6790\u540E\u4F5C\u4E3A\u6750\u6599\u9012\u7ED9\u901A\u8FDB\u53F8\uFF0C\u4E0D\u662F\u673A\u5668\u4EE3\u6536 finding \u7684\u6307\u4EE4\u3002"
8491
6578
  }
8492
6579
  }
8493
6580
  ];
@@ -8943,7 +7030,7 @@ var init_option_definitions = __esm({
8943
7030
  });
8944
7031
 
8945
7032
  // src/public-cli/invocation.ts
8946
- import { execFileSync as execFileSync3 } from "node:child_process";
7033
+ import { execFileSync as execFileSync2 } from "node:child_process";
8947
7034
  import { existsSync as existsSync4 } from "node:fs";
8948
7035
  import {
8949
7036
  lstat as lstat3,
@@ -9343,17 +7430,6 @@ function assignPublicSeatOption(owner, taken, fields) {
9343
7430
  case "request-manifest":
9344
7431
  fields.requestManifestPath = requireOptionPath(taken.def.canonical, value);
9345
7432
  return;
9346
- case "wait-ms": {
9347
- if (value === void 0 || !/^[1-9]\d*$/.test(value.trim())) {
9348
- throw new CliUsageError("--wait-ms requires a positive safe-integer millisecond value");
9349
- }
9350
- const parsed = Number(value.trim());
9351
- if (!Number.isSafeInteger(parsed) || parsed < 1) {
9352
- throw new CliUsageError("--wait-ms requires a positive safe-integer millisecond value");
9353
- }
9354
- fields.waitWindowMs = parsed;
9355
- return;
9356
- }
9357
7433
  case "issue": {
9358
7434
  if (value === void 0 || value.trim() === "") {
9359
7435
  throw new CliUsageError("doctor --issue requires a positive integer");
@@ -9450,7 +7526,6 @@ function parsePublicSeatArgv(owner, args) {
9450
7526
  ...fields.prNumber === void 0 ? {} : { prNumber: fields.prNumber },
9451
7527
  ...fields.repo === void 0 ? {} : { repo: fields.repo },
9452
7528
  ...fields.requestManifestPath === void 0 ? {} : { requestManifestPath: fields.requestManifestPath },
9453
- ...fields.waitWindowMs === void 0 ? {} : { waitWindowMs: fields.waitWindowMs },
9454
7529
  ...fields.issueNumber === void 0 ? {} : { issueNumber: fields.issueNumber },
9455
7530
  ...fields.runs === void 0 ? {} : { runs: fields.runs },
9456
7531
  ...fields.sourceRun === void 0 ? {} : { sourceRun: fields.sourceRun },
@@ -9810,23 +7885,16 @@ async function admitPublicRole(role, parsed, env, override) {
9810
7885
  attachmentPaths,
9811
7886
  ...project,
9812
7887
  placedFields: async (placed) => {
9813
- const target = await resolveCollectorTarget({
9814
- projectRoot,
9815
- repository,
9816
- ...explicitPrNumber === void 0 ? {} : { explicitPrNumber }
9817
- });
9818
- const prNumber = target.kind === "bound" ? target.prNumber : void 0;
9819
7888
  let requestManifestPath;
9820
7889
  if (manifestCanonicalJson !== void 0) {
9821
7890
  requestManifestPath = join18(placed.runDirectory, "request-manifest.json");
9822
7891
  await writeFile5(requestManifestPath, manifestCanonicalJson, "utf8");
9823
7892
  }
9824
7893
  return {
9825
- ...prNumber === void 0 ? {} : { prNumber },
7894
+ ...explicitPrNumber === void 0 ? {} : { prNumber: explicitPrNumber },
9826
7895
  repository: repository.canonical,
9827
7896
  repositoryDisplay: repository.display,
9828
7897
  ...requestManifestPath === void 0 ? {} : { requestManifestPath },
9829
- ...parsed.waitWindowMs === void 0 ? {} : { waitWindowMs: parsed.waitWindowMs },
9830
7898
  manifestDigest
9831
7899
  };
9832
7900
  }
@@ -10280,7 +8348,7 @@ function parseRepoOption(raw) {
10280
8348
  function resolveGitHubRemoteRepository(projectRoot) {
10281
8349
  let remoteUrl;
10282
8350
  try {
10283
- remoteUrl = execFileSync3("git", ["remote", "get-url", "origin"], {
8351
+ remoteUrl = execFileSync2("git", ["remote", "get-url", "origin"], {
10284
8352
  cwd: projectRoot,
10285
8353
  encoding: "utf8",
10286
8354
  stdio: ["ignore", "pipe", "pipe"]
@@ -10424,11 +8492,11 @@ function parseAnalystCohortIssueToken(raw, flag) {
10424
8492
  `${flag} requires a comma-separated list of N or book:N`
10425
8493
  );
10426
8494
  }
10427
- const sep7 = trimmed.lastIndexOf(":");
10428
- if (sep7 > 0) {
10429
- const rhs = trimmed.slice(sep7 + 1);
8495
+ const sep6 = trimmed.lastIndexOf(":");
8496
+ if (sep6 > 0) {
8497
+ const rhs = trimmed.slice(sep6 + 1);
10430
8498
  if (ANALYST_TICKET_NUMBER_PATTERN.test(rhs)) {
10431
- const bookKey = trimmed.slice(0, sep7);
8499
+ const bookKey = trimmed.slice(0, sep6);
10432
8500
  if (bookKey.trim() === "") {
10433
8501
  throw new CliUsageError(
10434
8502
  `${flag} book:N requires a non-empty book key, got ${raw}`
@@ -10632,7 +8700,6 @@ var init_invocation = __esm({
10632
8700
  init_doctor_evidence();
10633
8701
  init_diarist_contracts();
10634
8702
  init_collector_config();
10635
- init_collector_target();
10636
8703
  init_github_remote();
10637
8704
  init_fixer_packet();
10638
8705
  init_merger_git_state();
@@ -10989,7 +9056,7 @@ var init_host_providers = __esm({
10989
9056
  // src/analyst-gate-cycles-read.ts
10990
9057
  import { readdir as readdir4 } from "node:fs/promises";
10991
9058
  import { join as join22 } from "node:path";
10992
- function isRecord7(value) {
9059
+ function isRecord6(value) {
10993
9060
  return typeof value === "object" && value !== null && !Array.isArray(value);
10994
9061
  }
10995
9062
  function isParentAttemptBindingRow(row) {
@@ -11019,7 +9086,7 @@ function isGateTerminatingToolName(toolName) {
11019
9086
  function acceptedGateReceiptIds(rows) {
11020
9087
  const accepted = /* @__PURE__ */ new Set();
11021
9088
  for (const row of rows) {
11022
- const message = isRecord7(row.message) ? row.message : void 0;
9089
+ const message = isRecord6(row.message) ? row.message : void 0;
11023
9090
  if (message?.role !== "toolResult") continue;
11024
9091
  if (typeof message.toolCallId !== "string" || message.toolCallId.length === 0) continue;
11025
9092
  if (message.isError === false) accepted.add(message.toolCallId);
@@ -11054,7 +9121,7 @@ function nearestAttemptBindingBefore(rows, beforeIndex) {
11054
9121
  for (let i = beforeIndex - 1; i >= 0; i -= 1) {
11055
9122
  const row = rows[i];
11056
9123
  if (!isParentAttemptBindingRow(row)) continue;
11057
- if (!isRecord7(row.data) || !isRecord7(row.data.parent)) continue;
9124
+ if (!isRecord6(row.data) || !isRecord6(row.data.parent)) continue;
11058
9125
  const id = row.data.parent.attemptEntryId;
11059
9126
  const sessionFile = row.data.parent.sessionFile;
11060
9127
  return {
@@ -11069,10 +9136,10 @@ function extractAllAcceptedGateToolCalls(rows) {
11069
9136
  const out = [];
11070
9137
  for (let rowIndex = 0; rowIndex < rows.length; rowIndex += 1) {
11071
9138
  const row = rows[rowIndex];
11072
- const message = isRecord7(row.message) ? row.message : void 0;
9139
+ const message = isRecord6(row.message) ? row.message : void 0;
11073
9140
  if (message?.role !== "assistant" || !Array.isArray(message.content)) continue;
11074
9141
  for (const part of message.content) {
11075
- if (!isRecord7(part) || part.type !== "toolCall") continue;
9142
+ if (!isRecord6(part) || part.type !== "toolCall") continue;
11076
9143
  if (typeof part.id !== "string" || part.id.length === 0) continue;
11077
9144
  if (typeof part.name !== "string" || part.name.length === 0) continue;
11078
9145
  if (!isGateTerminatingToolName(part.name)) continue;
@@ -11080,7 +9147,7 @@ function extractAllAcceptedGateToolCalls(rows) {
11080
9147
  const binding = nearestAttemptBindingBefore(rows, rowIndex);
11081
9148
  out.push({
11082
9149
  toolName: part.name,
11083
- args: isRecord7(part.arguments) ? part.arguments : void 0,
9150
+ args: isRecord6(part.arguments) ? part.arguments : void 0,
11084
9151
  accepted: true,
11085
9152
  rowIndex,
11086
9153
  ...binding
@@ -11203,17 +9270,17 @@ function pairGateRounds(volumes) {
11203
9270
  return rounds.sort((a, b) => a.officerStartedAt.localeCompare(b.officerStartedAt)).map((round, index) => ({ ...round, roundIndex: index + 1 }));
11204
9271
  }
11205
9272
  async function resolveOfficerSessionFromPointerFile(pointerPath) {
11206
- const { readFile: readFile26 } = await import("node:fs/promises");
9273
+ const { readFile: readFile25 } = await import("node:fs/promises");
11207
9274
  let raw;
11208
9275
  try {
11209
- raw = JSON.parse(await readFile26(pointerPath, "utf8"));
9276
+ raw = JSON.parse(await readFile25(pointerPath, "utf8"));
11210
9277
  } catch (error) {
11211
9278
  throw new Error(
11212
9279
  `direct officer run pointer unreadable in ${pointerPath}: ${error instanceof Error ? error.message : String(error)}`,
11213
9280
  { cause: error }
11214
9281
  );
11215
9282
  }
11216
- if (!isRecord7(raw) || raw.kind !== "direct-officer-run-pointer" || raw.version !== 1) {
9283
+ if (!isRecord6(raw) || raw.kind !== "direct-officer-run-pointer" || raw.version !== 1) {
11217
9284
  throw new Error(`direct officer run pointer has unknown shape in ${pointerPath}`);
11218
9285
  }
11219
9286
  const sessionFile = raw.sessionFile;
@@ -11971,11 +10038,11 @@ function reportEngineDetourCall(input) {
11971
10038
  recordPointer: pointer
11972
10039
  };
11973
10040
  }
11974
- function isRecord8(value) {
10041
+ function isRecord7(value) {
11975
10042
  return typeof value === "object" && value !== null && !Array.isArray(value);
11976
10043
  }
11977
10044
  function callFactFromSitianPayload(payload, pointer) {
11978
- if (!isRecord8(payload)) return void 0;
10045
+ if (!isRecord7(payload)) return void 0;
11979
10046
  if (payload.tool !== ENGINE_DETOUR_TOOL_NAME) return void 0;
11980
10047
  if (typeof payload.toolCallId !== "string" || payload.toolCallId.length === 0) {
11981
10048
  return void 0;
@@ -11992,11 +10059,11 @@ function callFactFromSitianPayload(payload, pointer) {
11992
10059
  };
11993
10060
  }
11994
10061
  function invocationScopeIdOfRecord(record4) {
11995
- if (isRecord8(record4.subject)) {
10062
+ if (isRecord7(record4.subject)) {
11996
10063
  const fromSubject = record4.subject.invocationScopeId;
11997
10064
  if (typeof fromSubject === "string" && fromSubject.length > 0) return fromSubject;
11998
10065
  }
11999
- if (isRecord8(record4.payload)) {
10066
+ if (isRecord7(record4.payload)) {
12000
10067
  const fromPayload = record4.payload.invocationScopeId;
12001
10068
  if (typeof fromPayload === "string" && fromPayload.length > 0) return fromPayload;
12002
10069
  }
@@ -12057,7 +10124,7 @@ function readInvocationRecord(runDirectory) {
12057
10124
  const raw = JSON.parse(
12058
10125
  readFileSync2(join26(runDirectory, "invocation.json"), "utf8")
12059
10126
  );
12060
- return isRecord8(raw) ? raw : void 0;
10127
+ return isRecord7(raw) ? raw : void 0;
12061
10128
  } catch (error) {
12062
10129
  if (error?.code === "ENOENT") return void 0;
12063
10130
  throw error;
@@ -12070,7 +10137,7 @@ async function readInvocationEngineMounted(runDirectory) {
12070
10137
  }
12071
10138
  function withEngineDetourToolUsageFact(outcome, usage) {
12072
10139
  if (usage === void 0) return outcome;
12073
- const prior = isRecord8(outcome.decisiveFacts) ? outcome.decisiveFacts : {};
10140
+ const prior = isRecord7(outcome.decisiveFacts) ? outcome.decisiveFacts : {};
12074
10141
  return {
12075
10142
  ...outcome,
12076
10143
  decisiveFacts: {
@@ -12140,13 +10207,13 @@ function resolveAuditDossier(source) {
12140
10207
  }
12141
10208
  return { status: "ok", runDirectory };
12142
10209
  }
12143
- function isRecord9(value) {
10210
+ function isRecord8(value) {
12144
10211
  return typeof value === "object" && value !== null && !Array.isArray(value);
12145
10212
  }
12146
10213
  function readDoctorAuditSubjects(context) {
12147
10214
  const entries = context.sessionManager.getEntries?.() ?? [];
12148
10215
  for (const entry of entries) {
12149
- if (isRecord9(entry) && entry.type === "custom" && entry.customType === DOCTOR_CANDIDATE_ENTRY_TYPE) {
10216
+ if (isRecord8(entry) && entry.type === "custom" && entry.customType === DOCTOR_CANDIDATE_ENTRY_TYPE) {
12150
10217
  return { status: "ok" };
12151
10218
  }
12152
10219
  }
@@ -12179,11 +10246,11 @@ var init_dossier_resolution = __esm({
12179
10246
  });
12180
10247
 
12181
10248
  // src/receipt-delivery-policy.ts
12182
- function isRecord10(value) {
10249
+ function isRecord9(value) {
12183
10250
  return typeof value === "object" && value !== null && !Array.isArray(value);
12184
10251
  }
12185
10252
  function parseNoReceiptLifecycleFacts(input) {
12186
- if (!isRecord10(input) || typeof input.terminalToolCalled !== "boolean" || input.deliveryTurns !== RECEIPT_DELIVERY_TURN_LIMIT || input.sessionCompletion !== "settled-without-accepted-receipt" || input.acceptedReceipt !== false || typeof input.runPointer !== "string" || input.runPointer.trim() === "" || typeof input.attemptPointer !== "string" || input.attemptPointer.trim() === "" || !Array.isArray(input.rejectedReceipts) || !input.rejectedReceipts.every((item) => isRecord10(item) && typeof item.reason === "string")) {
10253
+ if (!isRecord9(input) || typeof input.terminalToolCalled !== "boolean" || input.deliveryTurns !== RECEIPT_DELIVERY_TURN_LIMIT || input.sessionCompletion !== "settled-without-accepted-receipt" || input.acceptedReceipt !== false || typeof input.runPointer !== "string" || input.runPointer.trim() === "" || typeof input.attemptPointer !== "string" || input.attemptPointer.trim() === "" || !Array.isArray(input.rejectedReceipts) || !input.rejectedReceipts.every((item) => isRecord9(item) && typeof item.reason === "string")) {
12187
10254
  throw new TypeError("malformed no-receipt lifecycle facts");
12188
10255
  }
12189
10256
  return {
@@ -12289,7 +10356,6 @@ __export(settlement_exports, {
12289
10356
  controlledFailureInputFromResolution: () => controlledFailureInputFromResolution,
12290
10357
  exitCodeForTerminalOutcome: () => exitCodeForTerminalOutcome,
12291
10358
  explicitInternalKnownFailureClassificationInput: () => explicitInternalKnownFailureClassificationInput,
12292
- extractCollectorInfrastructureFailure: () => extractCollectorInfrastructureFailure,
12293
10359
  extractEngineDetourInfrastructureFailure: () => extractEngineDetourInfrastructureFailure,
12294
10360
  extractGateFactFromSessionDirectory: () => extractGateFactFromSessionDirectory,
12295
10361
  extractNavigatorFact: () => extractNavigatorFact,
@@ -12310,7 +10376,6 @@ __export(settlement_exports, {
12310
10376
  publishedFailureErrorPath: () => publishedFailureErrorPath,
12311
10377
  raceNavigatorGrace: () => raceNavigatorGrace,
12312
10378
  readBoundSessionEntries: () => readBoundSessionEntries,
12313
- readCollectorInfrastructureFailure: () => readCollectorInfrastructureFailure,
12314
10379
  readEngineDetourInfrastructureFailure: () => readEngineDetourInfrastructureFailure,
12315
10380
  readSessionProviderStop: () => readSessionProviderStop,
12316
10381
  recordedSubmissionPayloads: () => recordedSubmissionPayloads,
@@ -12808,7 +10873,7 @@ async function readSitianRetainedAuditorProviderStop(sessionFile) {
12808
10873
  const { records } = await readSitianRecords(recordFile);
12809
10874
  for (let i = records.length - 1; i >= 0; i -= 1) {
12810
10875
  const payload = records[i]?.payload;
12811
- if (!isRecord11(payload) || !isRecord11(payload.response)) continue;
10876
+ if (!isRecord10(payload) || !isRecord10(payload.response)) continue;
12812
10877
  if (typeof payload.type === "string") continue;
12813
10878
  const stop = sessionProviderStopFromAssistant(payload.response);
12814
10879
  if (stop !== void 0) return stop;
@@ -12858,7 +10923,7 @@ async function loadBoundAuditorVolumes(sessionFile) {
12858
10923
  throw sessionReadFailure(error, "failed to read discovered auditor session");
12859
10924
  }
12860
10925
  const header = entries.find((entry) => entry.type === "session");
12861
- if (!isRecord11(header)) continue;
10926
+ if (!isRecord10(header)) continue;
12862
10927
  const bindingIndexes = [];
12863
10928
  for (let i = 0; i < entries.length; i += 1) {
12864
10929
  const entry = entries[i];
@@ -12872,7 +10937,7 @@ async function loadBoundAuditorVolumes(sessionFile) {
12872
10937
  end: idx + 1 < bindingIndexes.length ? bindingIndexes[idx + 1] : entries.length
12873
10938
  })) : [{ entry: void 0, start: 0, end: entries.length }];
12874
10939
  for (const { entry: bindingEntry, start, end } of bindingPasses) {
12875
- const bindingParent = bindingEntry !== void 0 && isRecord11(bindingEntry.data) && isRecord11(bindingEntry.data.parent) ? bindingEntry.data.parent : void 0;
10940
+ const bindingParent = bindingEntry !== void 0 && isRecord10(bindingEntry.data) && isRecord10(bindingEntry.data.parent) ? bindingEntry.data.parent : void 0;
12876
10941
  const attemptEntryId = typeof bindingParent?.attemptEntryId === "string" ? bindingParent.attemptEntryId : void 0;
12877
10942
  const boundSessionFile = typeof bindingParent?.sessionFile === "string" ? bindingParent.sessionFile : typeof header.parentSession === "string" ? header.parentSession : void 0;
12878
10943
  if (boundSessionFile !== sessionFile) continue;
@@ -12896,12 +10961,12 @@ function complianceFailureFromAuditorVolumes(volumes) {
12896
10961
  if (stop === void 0) continue;
12897
10962
  for (let i = entries.length - 1; i >= 0; i -= 1) {
12898
10963
  const entry = entries[i];
12899
- if (entry?.type !== "custom" || entry.customType !== AUDITOR_COMPLIANCE_FAILURE_ENTRY_TYPE || !isRecord11(entry.data)) continue;
12900
- const parent = isRecord11(entry.data.parent) ? entry.data.parent : void 0;
12901
- const failure2 = isRecord11(entry.data.failure) ? entry.data.failure : void 0;
10964
+ if (entry?.type !== "custom" || entry.customType !== AUDITOR_COMPLIANCE_FAILURE_ENTRY_TYPE || !isRecord10(entry.data)) continue;
10965
+ const parent = isRecord10(entry.data.parent) ? entry.data.parent : void 0;
10966
+ const failure2 = isRecord10(entry.data.failure) ? entry.data.failure : void 0;
12902
10967
  if (parent?.sessionId !== parentId || parent.sessionFile !== sessionFile || parent.attemptEntryId !== attemptEntryId) continue;
12903
10968
  if (failure2 === void 0) continue;
12904
- const identity = isRecord11(failure2.identity) ? failure2.identity : void 0;
10969
+ const identity = isRecord10(failure2.identity) ? failure2.identity : void 0;
12905
10970
  const typedCause = failure2.cause === "provider" || failure2.cause === "activation" || failure2.cause === "session" || failure2.cause === "output" || failure2.cause === "timeout" ? failure2.cause : void 0;
12906
10971
  return {
12907
10972
  ...typedCause === void 0 ? {} : { cause: typedCause },
@@ -12910,7 +10975,7 @@ function complianceFailureFromAuditorVolumes(volumes) {
12910
10975
  ...typeof identity.code === "string" || typeof identity.code === "number" ? { code: identity.code } : {}
12911
10976
  } },
12912
10977
  ...typeof failure2.diagnostic === "string" ? { diagnostic: failure2.diagnostic } : {},
12913
- ...isRecord11(failure2.details) ? { details: failure2.details } : {}
10978
+ ...isRecord10(failure2.details) ? { details: failure2.details } : {}
12914
10979
  };
12915
10980
  }
12916
10981
  }
@@ -12957,9 +11022,9 @@ function typedFailedTerminatingToolKnownFailure(entries) {
12957
11022
  if (classification.kind !== "infrastructure") continue;
12958
11023
  if (typeof message.toolCallId !== "string" || typeof message.toolName !== "string") continue;
12959
11024
  if (boundRoleToolCallForResult(attemptEntries, i, message, message.toolName) === void 0) continue;
12960
- const textPart = Array.isArray(message.content) ? message.content.find((part) => isRecord11(part) && part.type === "text" && typeof part.text === "string") : void 0;
12961
- const diagnostic = isRecord11(textPart) ? textPart.text : void 0;
12962
- const details = isRecord11(message.details) ? message.details : classification.fact;
11025
+ const textPart = Array.isArray(message.content) ? message.content.find((part) => isRecord10(part) && part.type === "text" && typeof part.text === "string") : void 0;
11026
+ const diagnostic = isRecord10(textPart) ? textPart.text : void 0;
11027
+ const details = isRecord10(message.details) ? message.details : classification.fact;
12963
11028
  return {
12964
11029
  cause: "activation",
12965
11030
  identity: { name: message.toolName, code: message.toolCallId },
@@ -13096,35 +11161,19 @@ function controlledFailureInputFromResolution(resolution) {
13096
11161
  } : {}
13097
11162
  };
13098
11163
  }
13099
- function isRecord11(value) {
11164
+ function isRecord10(value) {
13100
11165
  return typeof value === "object" && value !== null && !Array.isArray(value);
13101
11166
  }
13102
11167
  function toolResultText(message) {
13103
11168
  const content = message.content;
13104
11169
  if (typeof content === "string") return content.trim();
13105
11170
  if (!Array.isArray(content)) return "";
13106
- return content.map((part) => {
13107
- if (typeof part === "object" && part !== null && !Array.isArray(part) && typeof part.text === "string") {
13108
- return part.text;
13109
- }
13110
- return "";
13111
- }).join("").trim();
13112
- }
13113
- function extractCollectorTargetBindRejection(entries) {
13114
- for (let i = entries.length - 1; i >= 0; i -= 1) {
13115
- const entry = entries[i];
13116
- if (entry?.type !== "message") continue;
13117
- const message = entry.message;
13118
- if (message?.role !== "toolResult") continue;
13119
- if (message.toolName !== COLLECTOR_BIND_TARGET_TOOL) continue;
13120
- if (message.isError !== true) return void 0;
13121
- const diagnostic = toolResultText(message);
13122
- if (diagnostic.length === 0) return void 0;
13123
- const details = message.details;
13124
- const code = isRecord11(details) && typeof details.code === "string" && details.code.trim() !== "" ? details.code : void 0;
13125
- return code === void 0 ? { diagnostic } : { diagnostic, code };
13126
- }
13127
- return void 0;
11171
+ return content.map((part) => {
11172
+ if (typeof part === "object" && part !== null && !Array.isArray(part) && typeof part.text === "string") {
11173
+ return part.text;
11174
+ }
11175
+ return "";
11176
+ }).join("").trim();
13128
11177
  }
13129
11178
  function boundErroredToolCandidate(entries, resultIndex, message, toolName) {
13130
11179
  if (message.toolName !== toolName || message.isError !== true) return void 0;
@@ -13166,21 +11215,6 @@ async function readInfrastructureToolFailure(sessionFile, spec, options = {}) {
13166
11215
  return void 0;
13167
11216
  }
13168
11217
  }
13169
- function extractCollectorInfrastructureFailure(entries) {
13170
- return extractInfrastructureToolFailure(
13171
- entries,
13172
- COLLECTOR_INFRASTRUCTURE_FAILURE_SPEC
13173
- );
13174
- }
13175
- async function readCollectorInfrastructureFailure(sessionFile) {
13176
- return readInfrastructureToolFailure(
13177
- sessionFile,
13178
- COLLECTOR_INFRASTRUCTURE_FAILURE_SPEC,
13179
- // Multi-attempt resume: only a current-attempt infrastructure failure
13180
- // may preempt the current failure cause (#633).
13181
- { currentAttemptOnly: true }
13182
- );
13183
- }
13184
11218
  function extractEngineDetourInfrastructureFailure(entries) {
13185
11219
  return extractInfrastructureToolFailure(
13186
11220
  entries,
@@ -13222,7 +11256,7 @@ function boundRoleToolCallForResult(entries, resultIndex, message, outputToolNam
13222
11256
  const candidateMessage = entries[index]?.message;
13223
11257
  if (candidateMessage?.role === "assistant" && Array.isArray(candidateMessage.content)) {
13224
11258
  for (const part of candidateMessage.content) {
13225
- if (!isRecord11(part) || part.type !== "toolCall" || part.id !== callId) {
11259
+ if (!isRecord10(part) || part.type !== "toolCall" || part.id !== callId) {
13226
11260
  continue;
13227
11261
  }
13228
11262
  if (part.name !== outputToolName) return void 0;
@@ -13293,7 +11327,7 @@ function parseNavigatorAttendanceDetails(details) {
13293
11327
  if (typeof details.prose === "string" && details.prose.trim() !== "") {
13294
11328
  prose = details.prose;
13295
11329
  } else {
13296
- const next = isRecord11(details.next) && typeof details.next.role === "string" ? details.next.role : void 0;
11330
+ const next = isRecord10(details.next) && typeof details.next.role === "string" ? details.next.role : void 0;
13297
11331
  const reason = typeof details.reason === "string" && details.reason.trim() !== "" ? details.reason : void 0;
13298
11332
  const command = typeof details.command === "string" && details.command.trim() !== "" ? details.command : void 0;
13299
11333
  if (reason !== void 0 && next !== void 0) {
@@ -13402,7 +11436,7 @@ function detourGateContext(admitted, scope) {
13402
11436
  }
13403
11437
  async function withOptionalGateProjection(base, sessionDirectory, gateContext = {}) {
13404
11438
  const secondaryEvidence = base.roleOutcome.kind === "failure" ? base.roleOutcome.decisiveFacts.secondaryEvidence : void 0;
13405
- const skipGate = isRecord11(secondaryEvidence) && secondaryEvidence.kind === "role_infrastructure_failure" && packagedSkipsGateOnInfrastructureStage(secondaryEvidence.stage);
11439
+ const skipGate = isRecord10(secondaryEvidence) && secondaryEvidence.kind === "role_infrastructure_failure" && packagedSkipsGateOnInfrastructureStage(secondaryEvidence.stage);
13406
11440
  let next = base;
13407
11441
  if (!skipGate) {
13408
11442
  const gate = await extractGateFactFromSessionDirectory(sessionDirectory, gateContext);
@@ -13415,7 +11449,7 @@ function routePlaybookFailureMessage(entries) {
13415
11449
  const entry = entries[i];
13416
11450
  if (entry?.type !== "custom" || entry.customType !== NAVIGATOR_ROUTE_PLAYBOOK_FAILURE_ENTRY) continue;
13417
11451
  const data = entry.data;
13418
- if (!isRecord11(data) || typeof data.message !== "string" || data.message.trim() === "") return void 0;
11452
+ if (!isRecord10(data) || typeof data.message !== "string" || data.message.trim() === "") return void 0;
13419
11453
  return data.message;
13420
11454
  }
13421
11455
  return void 0;
@@ -13462,7 +11496,7 @@ function extractNavigatorAttendanceFact(entries) {
13462
11496
  const entry = entries[i];
13463
11497
  if (entry?.type === "custom_message" && entry.customType === "ak-navigator-attendance") {
13464
11498
  const details = entry.message?.details ?? entry.details;
13465
- if (!isRecord11(details)) {
11499
+ if (!isRecord10(details)) {
13466
11500
  return {
13467
11501
  disposition: "unavailable",
13468
11502
  source: "unknown",
@@ -13613,7 +11647,7 @@ async function settleSealedAcceptedOrToolResidual(admitted, authority, scope, ro
13613
11647
  const residual = boundErroredToolCandidate(entries, index, message, residualToolName);
13614
11648
  if (residual === void 0) continue;
13615
11649
  const candidate = residual.candidate;
13616
- const details = isRecord11(candidate) ? candidate : { candidate };
11650
+ const details = isRecord10(candidate) ? candidate : { candidate };
13617
11651
  const failed = await settleFailureTerminalResult(
13618
11652
  admitted,
13619
11653
  {
@@ -13688,7 +11722,7 @@ function extractDoctorCandidateFacts(entries) {
13688
11722
  continue;
13689
11723
  }
13690
11724
  const data = entry.data;
13691
- if (!isRecord11(data)) return {};
11725
+ if (!isRecord10(data)) return {};
13692
11726
  return {
13693
11727
  ...data.cost === void 0 ? {} : { cost: data.cost },
13694
11728
  ...data.auditNoReceipt === void 0 ? {} : { auditNoReceipt: data.auditNoReceipt }
@@ -13773,7 +11807,7 @@ async function settleLawfulSeatAcceptedTerminalResult(admitted, authority, spec,
13773
11807
  let residual;
13774
11808
  for (let index = entries.length - 1; index >= scanStart; index -= 1) {
13775
11809
  const entry = entries[index];
13776
- if (entry?.type === "custom" && entry.customType === "ak-role-submission-closure" && isRecord11(entry.data) && entry.data.toolName === spec.toolName && classifyPackagedRoleTerminalResult(entry.data).kind === "accepted") {
11810
+ if (entry?.type === "custom" && entry.customType === "ak-role-submission-closure" && isRecord10(entry.data) && entry.data.toolName === spec.toolName && classifyPackagedRoleTerminalResult(entry.data).kind === "accepted") {
13777
11811
  thisAttemptHasSeatSuccess = true;
13778
11812
  }
13779
11813
  const message = entries[index]?.message;
@@ -13813,7 +11847,7 @@ async function settleLawfulSeatAcceptedTerminalResult(admitted, authority, spec,
13813
11847
  );
13814
11848
  }
13815
11849
  if (residual !== void 0) {
13816
- const details = isRecord11(residual.candidate) ? residual.candidate : { candidate: residual.candidate };
11850
+ const details = isRecord10(residual.candidate) ? residual.candidate : { candidate: residual.candidate };
13817
11851
  const failed = await settleFailureTerminalResult(
13818
11852
  admitted,
13819
11853
  {
@@ -13863,7 +11897,7 @@ function countersignTerminalFromEntries(entries) {
13863
11897
  return void 0;
13864
11898
  }
13865
11899
  function withCountersignTerminalFact(roleOutcome, officer) {
13866
- const prior = roleOutcome.decisiveFacts !== void 0 && isRecord11(roleOutcome.decisiveFacts) ? roleOutcome.decisiveFacts : {};
11900
+ const prior = roleOutcome.decisiveFacts !== void 0 && isRecord10(roleOutcome.decisiveFacts) ? roleOutcome.decisiveFacts : {};
13867
11901
  return {
13868
11902
  ...roleOutcome,
13869
11903
  decisiveFacts: {
@@ -13876,7 +11910,7 @@ function acceptedSecretariatDefinesOfficerProjection(roleOutcome) {
13876
11910
  const payloads = roleOutcome.payloads ?? [];
13877
11911
  for (let index = payloads.length - 1; index >= 0; index -= 1) {
13878
11912
  const payload = payloads[index];
13879
- if (!isRecord11(payload)) continue;
11913
+ if (!isRecord10(payload)) continue;
13880
11914
  const status = payload.secretariatStatus;
13881
11915
  if (typeof status !== "string") continue;
13882
11916
  return status === "converged";
@@ -14104,17 +12138,6 @@ async function settleFailureTerminalResult(admitted, failure2, authority, option
14104
12138
  }
14105
12139
  if (facts !== void 0 && facts.runPointer === admitted.runDirectory && facts.attemptPointer === `current:${admitted.runDirectory}`) {
14106
12140
  let decisiveFacts2 = facts;
14107
- if (packagedProjectsTargetBindRejection(admitted.role)) {
14108
- const bindRejection = extractCollectorTargetBindRejection(entries.slice(attemptStart));
14109
- if (bindRejection !== void 0) {
14110
- decisiveFacts2 = {
14111
- ...facts,
14112
- targetBindRejected: true,
14113
- targetBindDiagnostic: bindRejection.diagnostic,
14114
- ...bindRejection.code === void 0 ? {} : { targetBindCode: bindRejection.code }
14115
- };
14116
- }
14117
- }
14118
12141
  await clearOppositeTerminalArtifactFace(admitted.runDirectory);
14119
12142
  return withOptionalGateProjection(
14120
12143
  {
@@ -14249,7 +12272,7 @@ function raceNavigatorGrace(work, graceMs = NAVIGATOR_POST_ROLE_GRACE_MS, sleep2
14249
12272
  });
14250
12273
  });
14251
12274
  }
14252
- var privateFailureErrorPaths, NAVIGATOR_POST_ROLE_GRACE_MS, COLLECTOR_INFRASTRUCTURE_TOOLS, COLLECTOR_INFRASTRUCTURE_FAILURE_SPEC, ENGINE_DETOUR_INFRASTRUCTURE_FAILURE_SPEC, RUNNER_FAILURE_POLICY, ATTEMPT_HISTORY_ENTRY_TYPE, EMPTY_ARTIFACT_FACE;
12275
+ var privateFailureErrorPaths, NAVIGATOR_POST_ROLE_GRACE_MS, ENGINE_DETOUR_INFRASTRUCTURE_FAILURE_SPEC, RUNNER_FAILURE_POLICY, ATTEMPT_HISTORY_ENTRY_TYPE, EMPTY_ARTIFACT_FACE;
14253
12276
  var init_settlement = __esm({
14254
12277
  "src/public-cli/settlement.ts"() {
14255
12278
  "use strict";
@@ -14262,11 +12285,9 @@ var init_settlement = __esm({
14262
12285
  init_serialize_thrown_value();
14263
12286
  init_run_lifecycle();
14264
12287
  init_compliance_transport();
14265
- init_collector_ledger();
14266
12288
  init_engine_detour();
14267
12289
  init_engine_detour_usage();
14268
12290
  init_judge_output();
14269
- init_collector_output();
14270
12291
  init_worker_output();
14271
12292
  init_doctor_contracts();
14272
12293
  init_dossier_resolution();
@@ -14282,20 +12303,6 @@ var init_settlement = __esm({
14282
12303
  init_terminal();
14283
12304
  privateFailureErrorPaths = /* @__PURE__ */ new WeakMap();
14284
12305
  NAVIGATOR_POST_ROLE_GRACE_MS = 1e4;
14285
- COLLECTOR_INFRASTRUCTURE_TOOLS = /* @__PURE__ */ new Set([
14286
- COLLECTOR_OBSERVE_TOOL,
14287
- COLLECTOR_READ_TOOL,
14288
- COLLECTOR_REQUEST_TOOL,
14289
- COLLECTOR_WAIT_TOOL
14290
- ]);
14291
- COLLECTOR_INFRASTRUCTURE_FAILURE_SPEC = {
14292
- matchTool: (toolName) => COLLECTOR_INFRASTRUCTURE_TOOLS.has(toolName),
14293
- cause: "activation",
14294
- identityName: "CollectorInfrastructureError",
14295
- // read alone has a correctable rejection mode (unknown/non-openable pointers);
14296
- // only its typed infrastructure-failure fact counts as a real host failure.
14297
- requireInfrastructureFact: (toolName) => toolName === COLLECTOR_READ_TOOL
14298
- };
14299
12306
  ENGINE_DETOUR_INFRASTRUCTURE_FAILURE_SPEC = {
14300
12307
  matchTool: (toolName) => toolName === ENGINE_DETOUR_TOOL_NAME,
14301
12308
  cause: "output",
@@ -14309,10 +12316,6 @@ var init_settlement = __esm({
14309
12316
  "engine-detour-record-first": {
14310
12317
  read: readEngineDetourInfrastructureFailure,
14311
12318
  rank: "record-first"
14312
- },
14313
- "collector-known-first": {
14314
- read: readCollectorInfrastructureFailure,
14315
- rank: "known-first"
14316
12319
  }
14317
12320
  };
14318
12321
  ATTEMPT_HISTORY_ENTRY_TYPE = "ak_run_attempt_history";
@@ -16610,11 +14613,11 @@ var init_turn_request = __esm({
16610
14613
  });
16611
14614
 
16612
14615
  // src/public-cli/countersign-run.ts
16613
- function isRecord12(value) {
14616
+ function isRecord11(value) {
16614
14617
  return typeof value === "object" && value !== null && !Array.isArray(value);
16615
14618
  }
16616
14619
  function isEscalatePayload(payload) {
16617
- if (!isRecord12(payload)) return false;
14620
+ if (!isRecord11(payload)) return false;
16618
14621
  return payload.status === "escalate";
16619
14622
  }
16620
14623
  function courtDiaristPayloadRows(roleOutcome, submissions) {
@@ -18203,7 +16206,7 @@ function isMissingPathError6(error) {
18203
16206
  function errorText3(error) {
18204
16207
  return error instanceof Error ? error.message : String(error);
18205
16208
  }
18206
- function isRecord13(value) {
16209
+ function isRecord12(value) {
18207
16210
  return typeof value === "object" && value !== null && !Array.isArray(value);
18208
16211
  }
18209
16212
  async function readExistingRunLifecycleState(runDirectory) {
@@ -18260,7 +16263,7 @@ async function readInvocationScopeFields(runDirectory) {
18260
16263
  throw error;
18261
16264
  }
18262
16265
  const parsed = JSON.parse(raw);
18263
- if (!isRecord13(parsed)) return void 0;
16266
+ if (!isRecord12(parsed)) return void 0;
18264
16267
  if (typeof parsed.projectRoot !== "string" || parsed.projectRoot.trim() === "") {
18265
16268
  return void 0;
18266
16269
  }
@@ -18289,7 +16292,7 @@ async function resolveSessionFile(runDirectory) {
18289
16292
  try {
18290
16293
  const raw = await readFile19(join35(runDirectory, "invocation.json"), "utf8");
18291
16294
  const parsed = JSON.parse(raw);
18292
- if (isRecord13(parsed) && typeof parsed.sessionFile === "string" && parsed.sessionFile.trim() !== "") {
16295
+ if (isRecord12(parsed) && typeof parsed.sessionFile === "string" && parsed.sessionFile.trim() !== "") {
18293
16296
  return parsed.sessionFile;
18294
16297
  }
18295
16298
  } catch (error) {
@@ -18627,7 +16630,7 @@ var init_analyst_ledger = __esm({
18627
16630
  });
18628
16631
 
18629
16632
  // src/analyst-metric-families/acceptance-success-rework.ts
18630
- function isRecord14(value) {
16633
+ function isRecord13(value) {
18631
16634
  return typeof value === "object" && value !== null && !Array.isArray(value);
18632
16635
  }
18633
16636
  function wallMsFromSpan(span) {
@@ -18636,21 +16639,21 @@ function wallMsFromSpan(span) {
18636
16639
  function findCollectorGroups(body) {
18637
16640
  if (Array.isArray(body.groups)) return body.groups;
18638
16641
  const receipt = body.receipt;
18639
- if (isRecord14(receipt) && Array.isArray(receipt.groups)) return receipt.groups;
16642
+ if (isRecord13(receipt) && Array.isArray(receipt.groups)) return receipt.groups;
18640
16643
  const outcome = body.outcome;
18641
- if (isRecord14(outcome)) {
16644
+ if (isRecord13(outcome)) {
18642
16645
  const facts = outcome.decisiveFacts;
18643
- if (isRecord14(facts) && Array.isArray(facts.groups)) return facts.groups;
16646
+ if (isRecord13(facts) && Array.isArray(facts.groups)) return facts.groups;
18644
16647
  }
18645
16648
  return void 0;
18646
16649
  }
18647
16650
  function extractStatus(body) {
18648
16651
  const outcome = body.outcome;
18649
- if (isRecord14(outcome) && typeof outcome.status === "string" && outcome.status.trim() !== "") {
16652
+ if (isRecord13(outcome) && typeof outcome.status === "string" && outcome.status.trim() !== "") {
18650
16653
  return outcome.status;
18651
16654
  }
18652
16655
  const receipt = body.receipt;
18653
- if (isRecord14(receipt) && typeof receipt.status === "string" && receipt.status.trim() !== "") {
16656
+ if (isRecord13(receipt) && typeof receipt.status === "string" && receipt.status.trim() !== "") {
18654
16657
  return receipt.status;
18655
16658
  }
18656
16659
  if (typeof body.status === "string" && body.status.trim() !== "") {
@@ -19276,15 +17279,15 @@ var init_leg_wall_clock = __esm({
19276
17279
  });
19277
17280
 
19278
17281
  // src/analyst-metric-families/round-timeline.ts
19279
- function isRecord15(value) {
17282
+ function isRecord14(value) {
19280
17283
  return typeof value === "object" && value !== null && !Array.isArray(value);
19281
17284
  }
19282
17285
  function wallMsFromSpan2(startedAt, endedAt) {
19283
17286
  return Date.parse(endedAt) - Date.parse(startedAt);
19284
17287
  }
19285
17288
  function readClassCount(body) {
19286
- if (!isRecord15(body.outcome)) return void 0;
19287
- if (!isRecord15(body.outcome.decisiveFacts)) return void 0;
17289
+ if (!isRecord14(body.outcome)) return void 0;
17290
+ if (!isRecord14(body.outcome.decisiveFacts)) return void 0;
19288
17291
  const classCount = body.outcome.decisiveFacts.classCount;
19289
17292
  if (typeof classCount !== "number" || !Number.isFinite(classCount)) {
19290
17293
  return void 0;
@@ -19428,7 +17431,7 @@ var init_analyst_metric_family = __esm({
19428
17431
  });
19429
17432
 
19430
17433
  // src/analyst-page.ts
19431
- import { createHash as createHash5 } from "node:crypto";
17434
+ import { createHash as createHash3 } from "node:crypto";
19432
17435
  import { dirname as dirname22, join as join36 } from "node:path";
19433
17436
  function analystIssuePageKey(address) {
19434
17437
  const parts = ["book", address.bookKey];
@@ -19437,7 +17440,7 @@ function analystIssuePageKey(address) {
19437
17440
  } else if (address.scopeRootIdentity !== void 0) {
19438
17441
  parts.push("root", physicalPathIdentity(address.scopeRootIdentity));
19439
17442
  }
19440
- return createHash5("sha256").update(parts.join("\0")).digest("hex").slice(0, 32);
17443
+ return createHash3("sha256").update(parts.join("\0")).digest("hex").slice(0, 32);
19441
17444
  }
19442
17445
  function analystIssuePagePath(ledgerHome, address) {
19443
17446
  return join36(ledgerHome, "analyst", "issues", `${analystIssuePageKey(address)}.json`);
@@ -22875,7 +20878,7 @@ var init_run_lifecycle = __esm({
22875
20878
  });
22876
20879
 
22877
20880
  // src/archivist-record-topology.ts
22878
- import { createHash as createHash6 } from "node:crypto";
20881
+ import { createHash as createHash4 } from "node:crypto";
22879
20882
  import { join as join41 } from "node:path";
22880
20883
  function resolveNavigatorWorkSubjectPlacement(input) {
22881
20884
  let ledgerHome;
@@ -22886,7 +20889,7 @@ function resolveNavigatorWorkSubjectPlacement(input) {
22886
20889
  }
22887
20890
  }
22888
20891
  ledgerHome ??= resolveActivationLedgerHome(input.home);
22889
- const digest = createHash6("sha256").update(input.subject).digest("hex").slice(0, 32);
20892
+ const digest = createHash4("sha256").update(input.subject).digest("hex").slice(0, 32);
22890
20893
  return {
22891
20894
  ledgerHome,
22892
20895
  sessionDir: join41(
@@ -23260,13 +21263,11 @@ var init_archivist_record_entry = __esm({
23260
21263
  import { randomUUID as randomUUID11 } from "node:crypto";
23261
21264
 
23262
21265
  // src/role-runtime-dependencies.ts
23263
- init_collector_github();
21266
+ import { readFile as readFile24 } from "node:fs/promises";
23264
21267
  init_doctor_evidence();
23265
- import { readFile as readFile25 } from "node:fs/promises";
23266
- import { join as join46 } from "node:path";
23267
21268
 
23268
21269
  // src/navigator-attendance.ts
23269
- import { createHash as createHash7 } from "node:crypto";
21270
+ import { createHash as createHash5 } from "node:crypto";
23270
21271
  init_navigator_invocation_identity();
23271
21272
  init_packaged_role_registry();
23272
21273
  init_activation_ledger_topology();
@@ -23471,7 +21472,7 @@ init_packaged_role_registry();
23471
21472
  // src/navigator-work-base.ts
23472
21473
  init_atomic_write();
23473
21474
  import { existsSync as existsSync3, realpathSync as realpathSync2 } from "node:fs";
23474
- import { readFile as readFile6 } from "node:fs/promises";
21475
+ import { readFile as readFile5 } from "node:fs/promises";
23475
21476
  import { basename as basename3, dirname as dirname7, join as join7, resolve as resolve5 } from "node:path";
23476
21477
  var NAVIGATOR_WORK_CONTEXT_BASENAME = "work-context.json";
23477
21478
  function navigatorWorkContextFile(sessionDir) {
@@ -23500,7 +21501,7 @@ async function persistNavigatorWorkBase(sessionDir, body) {
23500
21501
  const next = `${JSON.stringify({ subject: body.subject, authority: body.authority })}
23501
21502
  `;
23502
21503
  try {
23503
- const current = await readFile6(path, "utf8");
21504
+ const current = await readFile5(path, "utf8");
23504
21505
  if (current === next) return path;
23505
21506
  } catch (error) {
23506
21507
  if (!(error instanceof Error && "code" in error && error.code === "ENOENT")) {
@@ -23515,7 +21516,7 @@ async function readNavigatorWorkBase(path) {
23515
21516
  if (canonical === void 0) return void 0;
23516
21517
  let text;
23517
21518
  try {
23518
- text = await readFile6(canonical, "utf8");
21519
+ text = await readFile5(canonical, "utf8");
23519
21520
  } catch (error) {
23520
21521
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
23521
21522
  return void 0;
@@ -23827,7 +21828,7 @@ function navigatorSubjectKey(subjectRoot, subject, provenance = "role_input") {
23827
21828
  if (provenance === "placeholder") return subjectRoot;
23828
21829
  const normalized = subject.trim().replace(/\s+/g, " ");
23829
21830
  if (normalized === "") return subjectRoot;
23830
- return `${subjectRoot}#${createHash7("sha256").update(normalized).digest("hex").slice(0, 32)}`;
21831
+ return `${subjectRoot}#${createHash5("sha256").update(normalized).digest("hex").slice(0, 32)}`;
23831
21832
  }
23832
21833
  function navigatorSubjectKeyForInput(subjectRoot, reference, cwd = process.cwd()) {
23833
21834
  if (issueRoot(subjectRoot) !== void 0 || !subjectRoot.includes("/.ak/work/")) return subjectRoot;
@@ -24327,10 +22328,9 @@ init_notary_source_run();
24327
22328
  init_host_contracts();
24328
22329
  init_sitian_facade();
24329
22330
  init_submission_ledger();
24330
- init_collector_ledger();
24331
22331
  import { randomUUID as randomUUID8 } from "node:crypto";
24332
22332
  import { readFileSync as readFileSync6, writeSync as writeSync2 } from "node:fs";
24333
- import { join as join45 } from "node:path";
22333
+ import { join as join44 } from "node:path";
24334
22334
  import { Value as Value4 } from "typebox/value";
24335
22335
 
24336
22336
  // src/activation-trace.ts
@@ -24647,96 +22647,19 @@ init_receipt_delivery_policy();
24647
22647
 
24648
22648
  // src/collector-role.ts
24649
22649
  init_collector_config();
24650
- init_collector_evidence();
24651
- init_collector_github();
24652
-
24653
- // src/collector-handbook.ts
24654
- init_atomic_write();
24655
- init_activation_ledger_topology();
24656
- import { readFile as readFile24 } from "node:fs/promises";
24657
- import { join as join44, sep as sep6 } from "node:path";
22650
+ init_collector_output();
24658
22651
 
24659
22652
  // src/collector-tool-schemas.ts
24660
22653
  init_open_tool_schema();
24661
22654
  init_terminating_infrastructure();
24662
22655
  import { Type as Type16 } from "typebox";
24663
- var collectorObserveArgsSchema = Type16.Object({}, { additionalProperties: true });
24664
- var collectorRequestArgsSchema = Type16.Object({
24665
- requestId: Type16.String({
24666
- minLength: 1,
24667
- description: "\u8BF7\u6C42\u8EAB\u4EFD\uFF08\u914D\u7F6E id \u6216\u89D2\u8272\u5224\u5B9A\u7684\u7A33\u5B9A id\uFF1B\u9996\u5C3E\u65E0\u7A7A\u767D\uFF09"
24668
- }),
24669
- snapshotId: Type16.String({ minLength: 1, description: "\u6700\u65B0\u7559\u5B58\u89C2\u5BDF\u5FEB\u7167" }),
24670
- // #836 r16 class 3: body.minLength deleted — manifest-configured requestId
24671
- // ignores body, and the unknown-requestId non-empty condition is a real
24672
- // branch in src/collector-ledger.ts:922-951, not a provider shape gate.
24673
- body: Type16.Optional(Type16.String({
24674
- description: "\u89D2\u8272\u5224\u5B9A\u7684\u8BF7\u6C42\u6B63\u6587\uFF1Brequest-manifest \u672A\u6536\u5F55\u8BE5 requestId \u65F6\u5FC5\u586B"
24675
- }))
24676
- }, { additionalProperties: true });
24677
- var COLLECTOR_HANDBOOK_MAX_BYTES = 64 * 1024;
24678
- var collectorHandbookWriteArgsSchema = Type16.Object({
24679
- scope: Type16.Union([
24680
- Type16.Literal("general"),
24681
- Type16.Literal("repo")
24682
- ], { description: "general\uFF1D\u901A\u7528\u624B\u518C\uFF1Brepo\uFF1D\u5F53\u524D\u4ED3\u5E93\u5DEE\u5F02" }),
24683
- body: Type16.String({
24684
- description: `\u624B\u518C\u5168\u6587\uFF08opaque \u5DE5\u4F5C\u8BB0\u5FC6\uFF1B\u6574\u4EFD\u66FF\u6362\uFF1BUTF-8 \u81F3\u591A ${COLLECTOR_HANDBOOK_MAX_BYTES} \u5B57\u8282\uFF09`
24685
- })
24686
- }, { additionalProperties: true });
24687
- var collectorReadArgsSchema = Type16.Object({
24688
- evidenceId: Type16.String({ minLength: 1, description: "observe \u8FD4\u56DE\u7684\u6750\u6599\u8BC1\u636E id\uFF08evidenceId\uFF09" })
24689
- }, { additionalProperties: true });
24690
- var collectorWaitArgsSchema = Type16.Object({
24691
- durationMs: Type16.Integer({
24692
- minimum: 1,
24693
- description: "\u7B49\u5F85\u6BEB\u79D2\uFF1B\u5B9E\u9645\u7761\u7720\u4E0D\u8D85\u8FC7\u5269\u4F59\u7B49\u5F85\u7A97\uFF08#678\uFF1B\u65E0\u5305\u5185\u5355\u6B21\u4EFB\u610F\u4E0A\u9650\uFF09"
24694
- })
24695
- }, { additionalProperties: true });
24696
- var collectorOpenWaitWindowArgsSchema = Type16.Object({
24697
- startedAt: Type16.Optional(Type16.String({
24698
- description: "\u7B49\u5F85\u7A97\u8D77\u70B9 ISO \u65F6\u95F4\uFF1B\u65B0\u5EFA PR \u7528\u521B\u5EFA\u6210\u529F\u65F6\u523B\uFF1B\u7701\u7565\uFF1D\u73B0\u5728\uFF08\u89E6\u53D1\u9636\u6BB5\u7ED3\u675F\uFF09"
24699
- }))
24700
- }, { additionalProperties: true });
24701
- var collectorBindTargetArgsSchema = Type16.Object({
24702
- prNumber: Type16.Optional(Type16.Unknown({
24703
- description: "\u672C\u4ED3 PR \u53F7\uFF08\u6B63\u6574\u6570\uFF09\u3002"
24704
- })),
24705
- issueNumber: Type16.Optional(Type16.Unknown({
24706
- description: "\u672C\u4ED3 issue \u53F7\uFF08\u6B63\u6574\u6570\uFF09\u3002"
24707
- }))
24708
- }, { additionalProperties: true });
24709
- var collectorFindingItemDeclaration = (() => {
24710
- const item = Type16.Object(
24711
- {
24712
- evidenceId: Type16.Unknown({
24713
- description: "observe \u8FD4\u56DE\u7684\u6750\u6599\u6307\u9488\uFF08\u5FC5\u586B\u8BED\u4E49\uFF09"
24714
- }),
24715
- category: Type16.Unknown({
24716
- description: "\u7B80\u77ED\u5F52\u7C7B\u6807\u7B7E\uFF0C\u4E0D\u662F\u6458\u8981"
24717
- }),
24718
- summary: Type16.Unknown({
24719
- description: "\u54EA\u4E2A bot\u3001\u4EC0\u4E48\u95EE\u9898\u7684\u6458\u8981\uFF1B\u4E0D\u8A8A\u6284\u6B63\u6587"
24720
- })
24721
- },
24722
- {
24723
- additionalProperties: true,
24724
- description: "\u5355\u6761 finding \u6307\u9488\uFF1AevidenceId\uFF0C\u4EE5\u53CA\u53EF\u9009 category\u3001summary\u3002"
24725
- }
24726
- );
24727
- item.required = [];
24728
- return item;
24729
- })();
24730
22656
  var collectorOutputBaseSchema = openToolObject(
24731
22657
  Type16.Object({
24732
- // No root type:array — host must not shape-reject non-array findings (#676 C).
24733
- // Nested item declarations ride `items` for registration preservation (ADR 0057).
24734
- findings: Type16.Unsafe({
24735
- description: "\u672C\u6B21\u6536\u96C6\u5230\u7684\u9010\u6761 findings \u6307\u9488\u3002",
24736
- items: collectorFindingItemDeclaration
22658
+ groups: Type16.Unsafe({
22659
+ description: "\u6309\u673A\u5668\u8EAB\u4EFD\u5F52\u7EC4\u7684\u51FA\u5E2D\u3001\u6750\u6599\u4E0E\u9010\u6761 findings\uFF08LLM \u81EA\u884C\u4ECE\u5BBF\u4E3B CLI \u53D6\u8BC1\u6574\u7406\uFF1B\u4EE3\u7801\u4E0D\u4EE3\u6536\u4E0D\u5F52\u5E76\uFF09\u3002"
24737
22660
  }),
24738
22661
  unfinishedReasons: Type16.Unknown({
24739
- description: "\u672A\u5B8C\u6210\u539F\u56E0\u3002"
22662
+ description: "\u672A\u5B8C\u6210\u539F\u56E0\uFF1B\u53D6\u8BC1\u53D7\u9650\u65F6\u5982\u5B9E\u62A5\u544A\u3002"
24740
22663
  })
24741
22664
  })
24742
22665
  );
@@ -24744,146 +22667,9 @@ var collectorOutputArgsSchema = withTerminatingOutputDeclarations(
24744
22667
  collectorOutputBaseSchema
24745
22668
  );
24746
22669
 
24747
- // src/collector-handbook.ts
24748
- function resolveCollectorHandbookRoot(sessionPath) {
24749
- if (typeof sessionPath !== "string" || sessionPath.trim().length === 0) {
24750
- throw new Error("\u901A\u8FDB\u53F8\u624B\u518C\u8981\u6C42\u975E\u7A7A session \u8DEF\u5F84\uFF0C\u4E14\u4F4D\u4E8E books/<bookKey>/");
24751
- }
24752
- const segments = sessionPath.split(sep6);
24753
- let bookKey;
24754
- for (let i = 0; i + 3 < segments.length; i += 1) {
24755
- if (segments[i] === ".ak-roles" && segments[i + 1] === "books") {
24756
- const candidate = segments[i + 2];
24757
- if (candidate.length > 0) {
24758
- bookKey = candidate;
24759
- break;
24760
- }
24761
- }
24762
- }
24763
- if (bookKey === void 0) {
24764
- throw new Error(
24765
- `\u901A\u8FDB\u53F8\u624B\u518C\u8981\u6C42 session \u4F4D\u4E8E books/<bookKey>/\uFF1B\u6536\u5230 ${sessionPath}`
24766
- );
24767
- }
24768
- if (bookKey === "." || bookKey === "..") {
24769
- throw new Error(`\u901A\u8FDB\u53F8\u624B\u518C\u62D2\u7EDD\u4E0D\u5B89\u5168 bookKey ${JSON.stringify(bookKey)}`);
24770
- }
24771
- const ledgerHome = resolveActivationLedgerHomeForPath(sessionPath);
24772
- const root = join44(activationBookDirectory(ledgerHome, bookKey), "collector-handbook");
24773
- return { ledgerHome, bookKey, root };
24774
- }
24775
- function collectorHandbookRepoFileName(repositoryCanonical) {
24776
- if (!/^[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*$/.test(repositoryCanonical)) {
24777
- throw new Error(
24778
- `\u901A\u8FDB\u53F8\u624B\u518C\u4ED3\u5E93\u6587\u4EF6\u8981\u6C42\u89C4\u8303 owner/repo\uFF0C\u6536\u5230 ${JSON.stringify(repositoryCanonical)}`
24779
- );
24780
- }
24781
- return `${repositoryCanonical.replaceAll("/", "__")}.md`;
24782
- }
24783
- function createCollectorHandbookStore(input) {
24784
- const generalPath = join44(input.handbookRoot, "general.md");
24785
- const repoDir = join44(input.handbookRoot, "repos");
24786
- const repoPath = join44(repoDir, collectorHandbookRepoFileName(input.repositoryCanonical));
24787
- const assertHandbookBudget = (body, label) => {
24788
- const byteLength = Buffer.byteLength(body, "utf8");
24789
- if (byteLength > COLLECTOR_HANDBOOK_MAX_BYTES) {
24790
- throw new Error(
24791
- `\u901A\u8FDB\u53F8\u624B\u518C${label} UTF-8 \u81F3\u591A ${COLLECTOR_HANDBOOK_MAX_BYTES} \u5B57\u8282\uFF0C\u6536\u5230 ${byteLength}`
24792
- );
24793
- }
24794
- return byteLength;
24795
- };
24796
- const readOptional = async (path, parentDir2) => {
24797
- ensureRealDirectoryTree(input.ledgerHome, parentDir2);
24798
- assertLedgerFileInsideHome(path, input.ledgerHome);
24799
- try {
24800
- const body = await readFile24(path, "utf8");
24801
- assertHandbookBudget(body, "\u6B63\u6587");
24802
- return body;
24803
- } catch (error) {
24804
- if (isNotFound(error)) return void 0;
24805
- throw error;
24806
- }
24807
- };
24808
- return {
24809
- root: input.handbookRoot,
24810
- repositoryCanonical: input.repositoryCanonical,
24811
- async read() {
24812
- const bookGeneral = await readOptional(generalPath, input.handbookRoot);
24813
- const bookRepo = await readOptional(repoPath, repoDir);
24814
- if (bookGeneral !== void 0) {
24815
- return {
24816
- general: bookGeneral,
24817
- repo: bookRepo ?? "",
24818
- generalSource: "book",
24819
- repoSource: bookRepo === void 0 ? "empty" : "book",
24820
- generalPath,
24821
- repoPath
24822
- };
24823
- }
24824
- const seed = input.seedGeneral;
24825
- if (typeof seed === "string" && seed.length > 0) {
24826
- assertHandbookBudget(seed, "\u6B63\u6587");
24827
- return {
24828
- general: seed,
24829
- repo: bookRepo ?? "",
24830
- generalSource: "seed",
24831
- repoSource: bookRepo === void 0 ? "empty" : "book",
24832
- generalPath,
24833
- repoPath
24834
- };
24835
- }
24836
- return {
24837
- general: "",
24838
- repo: bookRepo ?? "",
24839
- generalSource: "empty",
24840
- repoSource: bookRepo === void 0 ? "empty" : "book",
24841
- generalPath,
24842
- repoPath
24843
- };
24844
- },
24845
- async write(scope, body) {
24846
- const byteLength = assertHandbookBudget(body, "\u6B63\u6587");
24847
- ensureRealDirectoryTree(input.ledgerHome, input.handbookRoot);
24848
- const path = scope === "general" ? generalPath : repoPath;
24849
- if (scope === "repo") {
24850
- ensureRealDirectoryTree(input.ledgerHome, repoDir);
24851
- }
24852
- assertLedgerFileInsideHome(path, input.ledgerHome);
24853
- await writeFileAtomically(path, body);
24854
- return {
24855
- scope,
24856
- path,
24857
- byteLength
24858
- };
24859
- }
24860
- };
24861
- }
24862
- function isNotFound(error) {
24863
- return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
24864
- }
24865
-
24866
22670
  // src/collector-role.ts
24867
- init_collector_ledger();
24868
- init_submission_correctable_error();
24869
- init_collector_identity();
24870
- init_collector_identity();
24871
- var CollectorTargetBindError = class extends CorrectableSubmissionError {
24872
- constructor(message) {
24873
- super(message);
24874
- this.name = "CollectorTargetBindError";
24875
- }
24876
- };
24877
- var COLLECTOR_REQUIRED_TOOLS = [
24878
- COLLECTOR_BIND_TARGET_TOOL,
24879
- COLLECTOR_OBSERVE_TOOL,
24880
- COLLECTOR_READ_TOOL,
24881
- COLLECTOR_REQUEST_TOOL,
24882
- COLLECTOR_OPEN_WAIT_WINDOW_TOOL,
24883
- COLLECTOR_WAIT_TOOL,
24884
- COLLECTOR_HANDBOOK_WRITE_TOOL,
24885
- COLLECTOR_OUTPUT_TOOL
24886
- ];
22671
+ var COLLECTOR_REQUIRED_TOOLS = [COLLECTOR_OUTPUT_TOOL];
22672
+ var COLLECTOR_CONSTRUCTION_TOOLS = Object.freeze(["write", "edit"]);
24887
22673
  var COLLECTOR_TRANSPORT_FLAGS = Object.freeze([
24888
22674
  Object.freeze({
24889
22675
  name: "ak-collector-repo",
@@ -24895,87 +22681,49 @@ var COLLECTOR_TRANSPORT_FLAGS = Object.freeze([
24895
22681
  Object.freeze({
24896
22682
  name: "ak-collector-pr",
24897
22683
  definition: Object.freeze({
24898
- description: "Optional positive safe-integer pull request number for Collector. Omit when the role will bind from task materials.",
22684
+ description: "Optional positive safe-integer pull request number for Collector. Omit when the role will locate the PR via host CLI.",
24899
22685
  type: "string"
24900
22686
  })
24901
22687
  }),
24902
22688
  Object.freeze({
24903
22689
  name: "ak-collector-request-manifest",
24904
22690
  definition: Object.freeze({
24905
- description: "Path to the Collector v1 request manifest JSON file.",
24906
- type: "string"
24907
- })
24908
- }),
24909
- Object.freeze({
24910
- name: "ak-collector-wait-ms",
24911
- definition: Object.freeze({
24912
- description: `Collector wait-window duration in milliseconds (default ${COLLECTOR_DEFAULT_WAIT_WINDOW_MS}). Caller-configurable; opens at a work step, not session start (#678 D4).`,
22691
+ description: "Path to the Collector v1 request manifest JSON file (caller guidance; not a machine collection directive).",
24913
22692
  type: "string"
24914
22693
  })
24915
22694
  })
24916
22695
  ]);
24917
- var observeSchema = collectorObserveArgsSchema;
24918
- var readSchema = collectorReadArgsSchema;
24919
- var requestSchema = collectorRequestArgsSchema;
24920
- var openWaitWindowSchema = collectorOpenWaitWindowArgsSchema;
24921
- var waitSchema = collectorWaitArgsSchema;
24922
- var bindSchema = collectorBindTargetArgsSchema;
24923
- var handbookWriteSchema = collectorHandbookWriteArgsSchema;
24924
22696
  var outputSchema = collectorOutputArgsSchema;
24925
- function parseWaitWindowMsFlag(raw) {
24926
- if (raw === void 0 || raw === null || raw === "") return COLLECTOR_DEFAULT_WAIT_WINDOW_MS;
24927
- if (typeof raw === "number" && Number.isSafeInteger(raw) && raw >= 1) return raw;
24928
- if (typeof raw === "string" && /^[1-9]\d*$/.test(raw.trim())) {
24929
- const value = Number(raw.trim());
24930
- if (Number.isSafeInteger(value) && value >= 1) return value;
24931
- }
24932
- throw new Error("Collector --ak-collector-wait-ms must be a positive safe-integer millisecond string");
24933
- }
24934
22697
  function buildMethodContext(activation) {
24935
- const pr = activation.ledger.config.prNumber;
24936
- const handbook = activation.handbookView;
24937
22698
  const lines = [
24938
22699
  "<collector_method>",
24939
22700
  `host: github.com`,
24940
22701
  `repository: ${activation.repository.canonical}`,
24941
- `prNumber: ${pr === void 0 ? "\u672A\u7ED1\u5B9A" : String(pr)}`,
24942
- `waitWindowMs: ${String(activation.ledger.config.waitWindowMs)}`,
22702
+ `prNumber: ${activation.prNumber === void 0 ? "\u672A\u7ED1\u5B9A" : String(activation.prNumber)}`,
24943
22703
  `requests: ${JSON.stringify(activation.manifest.requests.map((request) => ({ id: request.id })))}`,
24944
- `handbookGeneralSource: ${handbook.generalSource}`,
24945
- `handbookRepoSource: ${handbook.repoSource}`,
22704
+ `manifestDigest: ${activation.manifest.digest}`,
24946
22705
  "</collector_method>"
24947
22706
  ];
24948
- if (handbook.general.length > 0 || handbook.repo.length > 0) {
22707
+ if (activation.manifest.requests.length > 0) {
24949
22708
  const payload = JSON.stringify({
24950
- general: handbook.general,
24951
- repo: handbook.repo,
24952
- generalSource: handbook.generalSource,
24953
- repoSource: handbook.repoSource,
24954
- repository: activation.repository.canonical
22709
+ requests: activation.manifest.requests.map((request) => ({
22710
+ id: request.id,
22711
+ body: request.requestBody
22712
+ }))
24955
22713
  }).replaceAll("<", "\\u003c");
24956
- lines.push("", "<collector_handbook>", payload, "</collector_handbook>");
22714
+ lines.push("", "<collector_request_manifest>", payload, "</collector_request_manifest>");
24957
22715
  }
24958
22716
  return lines.join("\n");
24959
22717
  }
24960
- function parsePositiveTicket(raw, label) {
24961
- if (raw === void 0 || raw === null) return void 0;
24962
- if (typeof raw === "number" && Number.isSafeInteger(raw) && raw >= 1) return raw;
24963
- if (typeof raw === "string" && /^[1-9]\d*$/.test(raw.trim())) {
24964
- const value = Number(raw.trim());
24965
- if (Number.isSafeInteger(value)) return value;
24966
- }
24967
- throw new CollectorTargetBindError(`\u901A\u8FDB\u53F8\u7ED1\u5B9A ${label} \u987B\u4E3A\u6B63\u5B89\u5168\u6574\u6570`);
24968
- }
24969
- function createCollectorRoleRuntime(pi, dependencies, hostActions) {
22718
+ function createCollectorRoleRuntime(pi, dependencies) {
24970
22719
  let toolsRegistered = false;
24971
22720
  return {
24972
- async activate(ctx) {
22721
+ async activate(_ctx) {
24973
22722
  const soul = (await dependencies.loadSoul()).trim();
24974
22723
  if (soul.length === 0) throw new Error("Collector soul is empty");
24975
22724
  const repoFlag = pi.getFlag("ak-collector-repo");
24976
22725
  const prFlag = pi.getFlag("ak-collector-pr");
24977
22726
  const requestManifestFlag = pi.getFlag("ak-collector-request-manifest");
24978
- const waitMsFlag = pi.getFlag("ak-collector-wait-ms");
24979
22727
  if (typeof repoFlag !== "string" || repoFlag.trim().length === 0) {
24980
22728
  throw new Error("Collector requires --ak-collector-repo");
24981
22729
  }
@@ -24987,36 +22735,11 @@ function createCollectorRoleRuntime(pi, dependencies, hostActions) {
24987
22735
  prNumber = parseCollectorPrNumber(prFlag);
24988
22736
  }
24989
22737
  const manifest = typeof requestManifestFlag === "string" && requestManifestFlag.trim().length > 0 ? await loadCollectorManifest(requestManifestFlag) : emptyCollectorManifest();
24990
- const waitWindowMs = parseWaitWindowMsFlag(waitMsFlag);
24991
- const clock = dependencies.createClock?.() ?? createSystemCollectorClock();
24992
- const transport = dependencies.createTransport();
24993
- const ledger = dependencies.createLedger(
24994
- { repository, prNumber, manifest, waitWindowMs },
24995
- clock,
24996
- ctx
24997
- );
24998
- const sessionPath = ctx.sessionManager?.getSessionFile?.() ?? ctx.sessionManager?.getSessionDir?.();
24999
- if (typeof sessionPath !== "string" || sessionPath.length === 0) {
25000
- throw new Error("\u901A\u8FDB\u53F8\u624B\u518C\u8981\u6C42 session \u8DEF\u5F84\u4F4D\u4E8E books/<bookKey>/");
25001
- }
25002
- const placement = resolveCollectorHandbookRoot(sessionPath);
25003
- const seedGeneral = dependencies.loadHandbookSeed === void 0 ? void 0 : (await dependencies.loadHandbookSeed()).trim();
25004
- const handbook = createCollectorHandbookStore({
25005
- ledgerHome: placement.ledgerHome,
25006
- handbookRoot: placement.root,
25007
- repositoryCanonical: repository.canonical,
25008
- ...seedGeneral === void 0 || seedGeneral.length === 0 ? {} : { seedGeneral }
25009
- });
25010
- const handbookView = await handbook.read();
25011
22738
  return {
25012
22739
  soul,
25013
22740
  repository,
25014
- manifest,
25015
- ledger,
25016
- transport,
25017
- clock,
25018
- handbook,
25019
- handbookView
22741
+ prNumber,
22742
+ manifest
25020
22743
  };
25021
22744
  },
25022
22745
  assembleMaterials(activation, baseSystemPrompt) {
@@ -25030,335 +22753,32 @@ function createCollectorRoleRuntime(pi, dependencies, hostActions) {
25030
22753
  buildMethodContext(activation)
25031
22754
  ].join("\n");
25032
22755
  },
25033
- onToolCall(activation, event) {
25034
- if (activation.ledger.fatal) {
22756
+ onToolCall(_activation, event) {
22757
+ if (COLLECTOR_CONSTRUCTION_TOOLS.includes(event.toolName)) {
25035
22758
  return {
25036
22759
  block: true,
25037
- reason: activation.ledger.fatalReason ?? "\u901A\u8FDB\u53F8\u81F4\u547D\u72B6\u6001"
22760
+ reason: `\u901A\u8FDB\u53F8\u4E3A\u6536\u8BC1\u5E2D\uFF0C\u7981\u7528\u65BD\u5DE5\u5DE5\u5177 ${event.toolName}`
25038
22761
  };
25039
22762
  }
25040
- if (event.toolName === COLLECTOR_OUTPUT_TOOL) {
25041
- activation.ledger.beginOperational(COLLECTOR_OUTPUT_TOOL, event.toolCallId);
25042
- }
25043
22763
  return void 0;
25044
22764
  },
25045
- onToolResult(activation, event) {
25046
- activation.ledger.completeOperational(event.toolCallId);
25047
- },
25048
22765
  registerBusinessTools(getActivation) {
25049
22766
  if (toolsRegistered) return;
25050
22767
  toolsRegistered = true;
25051
- pi.registerTool({
25052
- name: COLLECTOR_BIND_TARGET_TOOL,
25053
- label: "\u901A\u8FDB\u53F8\u8BA4\u7968\u7ED1\u5B9A",
25054
- description: "\u7ED1\u5B9A\u672C\u4ED3\u552F\u4E00 PR \u76EE\u6807\u3002",
25055
- promptSnippet: "\u7ED1\u5B9A\u89D2\u8272\u5224\u5B9A\u7684 issue/PR \u76EE\u6807",
25056
- parameters: bindSchema,
25057
- async execute(toolCallId, params, _signal, _onUpdate, ctx) {
25058
- const activation = getActivation();
25059
- if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
25060
- try {
25061
- activation.ledger.beginOperational(COLLECTOR_BIND_TARGET_TOOL, toolCallId);
25062
- const prNumber = parsePositiveTicket(params.prNumber, "prNumber");
25063
- const issueNumber = parsePositiveTicket(params.issueNumber, "issueNumber");
25064
- if (prNumber === void 0 && issueNumber === void 0) {
25065
- throw new CollectorTargetBindError(
25066
- "\u901A\u8FDB\u53F8\u7ED1\u5B9A\u987B\u7531\u89D2\u8272\u5224\u5B9A prNumber \u4E0E/\u6216 issueNumber"
25067
- );
25068
- }
25069
- let bound = prNumber;
25070
- let associated = [];
25071
- if (issueNumber !== void 0) {
25072
- associated = await listPullRequestNumbersByTicket(createGhApiRunner(), {
25073
- owner: activation.repository.owner,
25074
- repo: activation.repository.repo,
25075
- ticketNumber: issueNumber
25076
- });
25077
- if (bound === void 0 && associated.length === 1) {
25078
- bound = associated[0];
25079
- }
25080
- }
25081
- if (bound === void 0) {
25082
- return {
25083
- content: [{
25084
- type: "text",
25085
- text: JSON.stringify({
25086
- bound: false,
25087
- repository: activation.repository.canonical,
25088
- prNumber: prNumber ?? null,
25089
- issueNumber: issueNumber ?? null,
25090
- associated
25091
- })
25092
- }],
25093
- details: {
25094
- bound: false,
25095
- repository: activation.repository.canonical,
25096
- prNumber: prNumber ?? null,
25097
- issueNumber: issueNumber ?? null,
25098
- associated
25099
- }
25100
- };
25101
- }
25102
- activation.ledger.bindTarget(bound);
25103
- activation.ledger.completeOperational(toolCallId);
25104
- return {
25105
- content: [{
25106
- type: "text",
25107
- text: `\u76EE\u6807\u5DF2\u7ED1\u5B9A\uFF1A${activation.repository.canonical}#${bound}`
25108
- }],
25109
- details: {
25110
- bound: true,
25111
- repository: activation.repository.canonical,
25112
- prNumber: bound,
25113
- issueNumber: issueNumber ?? null,
25114
- associated
25115
- }
25116
- };
25117
- } catch (error) {
25118
- if (isCorrectableExecuteError(error)) throw error;
25119
- hostActions.failInfrastructure(error, ctx, toolCallId);
25120
- } finally {
25121
- try {
25122
- activation.ledger.completeOperational(toolCallId);
25123
- } catch {
25124
- }
25125
- }
25126
- }
25127
- });
25128
- pi.registerTool({
25129
- name: COLLECTOR_OBSERVE_TOOL,
25130
- label: "\u901A\u8FDB\u53F8\u89C2\u5BDF",
25131
- description: "\u6293\u53D6\u914D\u7F6E\u76EE\u6807\u7684 GitHub PR \u8BC1\u636E\u3002",
25132
- promptSnippet: "\u6293\u53D6\u914D\u7F6E\u76EE\u6807 PR \u8BC1\u636E",
25133
- parameters: observeSchema,
25134
- async execute(toolCallId, _params, signal, _onUpdate, ctx) {
25135
- const activation = getActivation();
25136
- if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
25137
- try {
25138
- activation.ledger.beginOperational(COLLECTOR_OBSERVE_TOOL, toolCallId);
25139
- const { snapshot, contextView } = await activation.ledger.observe(
25140
- activation.transport,
25141
- activation.clock,
25142
- signal
25143
- );
25144
- activation.ledger.completeOperational(toolCallId);
25145
- return {
25146
- content: [{
25147
- type: "text",
25148
- text: JSON.stringify(contextView)
25149
- }],
25150
- details: contextView
25151
- };
25152
- } catch (error) {
25153
- if (isCorrectableExecuteError(error)) throw error;
25154
- hostActions.failInfrastructure(error, ctx, toolCallId);
25155
- }
25156
- }
25157
- });
25158
- pi.registerTool({
25159
- name: COLLECTOR_READ_TOOL,
25160
- label: "\u901A\u8FDB\u53F8\u5F00\u5377",
25161
- description: "\u6309 evidenceId \u5F00\u5377\u8BFB\u53D6\u4E00\u6761\u5DF2\u89C2\u6D4B\u6750\u6599\u7684\u5168\u91CF\u6B63\u6587\u4E0E\u6307\u9488\u3002",
25162
- promptSnippet: "\u6309\u6307\u9488\u5F00\u5377\u8BFB\u6750\u6599",
25163
- parameters: readSchema,
25164
- async execute(toolCallId, params, _signal, _onUpdate, ctx) {
25165
- const activation = getActivation();
25166
- if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
25167
- try {
25168
- activation.ledger.beginOperational(COLLECTOR_READ_TOOL, toolCallId);
25169
- const record4 = activation.ledger.getEvidence(params.evidenceId);
25170
- if (record4 === void 0 || record4.kind !== "review" && record4.kind !== "issue_comment" && record4.kind !== "review_comment" && record4.kind !== "reaction" || typeof record4.body !== "string") {
25171
- throw new CollectorUnknownEvidenceError(params.evidenceId);
25172
- }
25173
- const material = projectEvidenceEntryView(record4);
25174
- activation.ledger.completeOperational(toolCallId);
25175
- return {
25176
- content: [{
25177
- type: "text",
25178
- text: JSON.stringify(material)
25179
- }],
25180
- details: material
25181
- };
25182
- } catch (error) {
25183
- if (isCorrectableExecuteError(error)) throw error;
25184
- hostActions.failInfrastructure(error, ctx, toolCallId);
25185
- }
25186
- }
25187
- });
25188
- pi.registerTool({
25189
- name: COLLECTOR_REQUEST_TOOL,
25190
- label: "\u901A\u8FDB\u53F8\u8BF7\u6C42",
25191
- description: "\u53D1\u4E00\u6B21\u8BF7\u6C42\u3002",
25192
- promptSnippet: "\u53D1\u4E00\u6B21\u8BC4\u5BA1\u8BF7\u6C42",
25193
- parameters: requestSchema,
25194
- async execute(toolCallId, params, signal, _onUpdate, ctx) {
25195
- const activation = getActivation();
25196
- if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
25197
- try {
25198
- activation.ledger.beginOperational(COLLECTOR_REQUEST_TOOL, toolCallId);
25199
- const details = await activation.ledger.request(
25200
- {
25201
- requestId: params.requestId,
25202
- snapshotId: params.snapshotId,
25203
- ...typeof params.body === "string" ? { body: params.body } : {}
25204
- },
25205
- activation.transport,
25206
- activation.clock,
25207
- signal
25208
- );
25209
- activation.ledger.completeOperational(toolCallId);
25210
- return {
25211
- content: [{
25212
- type: "text",
25213
- text: `\u8BF7\u6C42\u5C1D\u8BD5\u5DF2\u8BB0\u5F55\uFF1Arequest ${params.requestId}`
25214
- }],
25215
- details
25216
- };
25217
- } catch (error) {
25218
- if (isCorrectableExecuteError(error)) throw error;
25219
- hostActions.failInfrastructure(error, ctx, toolCallId);
25220
- }
25221
- }
25222
- });
25223
- pi.registerTool({
25224
- name: COLLECTOR_HANDBOOK_WRITE_TOOL,
25225
- label: "\u901A\u8FDB\u53F8\u624B\u518C\u5199\u5165",
25226
- description: "\u5199\u5165\u901A\u7528\u624B\u518C\u6216\u5F53\u524D\u4ED3\u5E93\u5DEE\u5F02\u5168\u6587\uFF08\u6574\u4EFD\u66FF\u6362\uFF09\u3002",
25227
- promptSnippet: "\u66F4\u65B0 bot \u624B\u518C",
25228
- parameters: handbookWriteSchema,
25229
- async execute(toolCallId, params, _signal, _onUpdate, ctx) {
25230
- const activation = getActivation();
25231
- if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
25232
- try {
25233
- activation.ledger.beginOperational(COLLECTOR_HANDBOOK_WRITE_TOOL, toolCallId);
25234
- const details = await activation.handbook.write(params.scope, params.body);
25235
- activation.handbookView = await activation.handbook.read();
25236
- activation.ledger.completeOperational(toolCallId);
25237
- return {
25238
- content: [{
25239
- type: "text",
25240
- text: `\u624B\u518C\u5DF2\u5199\u5165\uFF1A${details.scope}`
25241
- }],
25242
- details: {
25243
- scope: details.scope,
25244
- path: details.path,
25245
- byteLength: details.byteLength,
25246
- generalSource: activation.handbookView.generalSource,
25247
- repoSource: activation.handbookView.repoSource
25248
- }
25249
- };
25250
- } catch (error) {
25251
- if (isCorrectableExecuteError(error)) throw error;
25252
- hostActions.failInfrastructure(error, ctx, toolCallId);
25253
- } finally {
25254
- try {
25255
- activation.ledger.completeOperational(toolCallId);
25256
- } catch {
25257
- }
25258
- }
25259
- }
25260
- });
25261
- pi.registerTool({
25262
- name: COLLECTOR_OPEN_WAIT_WINDOW_TOOL,
25263
- label: "\u901A\u8FDB\u53F8\u5F00\u542F\u7B49\u5F85\u7A97",
25264
- description: "\u5728\u5DE5\u4F5C\u6B65\u9AA4\u4E0A\u5F00\u542F\u7B49\u5F85\u7A97\uFF1A\u65B0\u5EFA\u5E76\u81EA\u52A8\u89E6\u53D1\u7684 PR \u4F20\u521B\u5EFA\u6210\u529F\u65F6\u523B\uFF1B\u5DF2\u6709 PR \u5728\u89E6\u53D1\u9636\u6BB5\u7ED3\u675F\u540E\u7701\u7565 startedAt\uFF08=\u73B0\u5728\uFF09\u3002\u7A97\u957F\u7531\u4F7F\u7528\u65B9\u914D\u7F6E\uFF0C\u9ED8\u8BA4\u5341\u5206\u949F\uFF1B\u5F00\u542F\u540E\u4E0D\u56E0 PR \u66F4\u65B0\u91CD\u7F6E\u3002",
25265
- promptSnippet: "\u6309\u5DE5\u4F5C\u6B65\u9AA4\u5F00\u542F\u7B49\u5F85\u7A97",
25266
- parameters: openWaitWindowSchema,
25267
- async execute(toolCallId, params, _signal, _onUpdate, ctx) {
25268
- const activation = getActivation();
25269
- if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
25270
- try {
25271
- activation.ledger.beginOperational(COLLECTOR_OPEN_WAIT_WINDOW_TOOL, toolCallId);
25272
- let startedAt;
25273
- if (typeof params.startedAt === "string" && params.startedAt.trim().length > 0) {
25274
- const parsed = new Date(params.startedAt);
25275
- if (Number.isNaN(parsed.getTime())) {
25276
- throw new Error("\u901A\u8FDB\u53F8\u7B49\u5F85\u7A97 startedAt \u987B\u4E3A\u6709\u6548 ISO \u65F6\u95F4");
25277
- }
25278
- startedAt = parsed;
25279
- }
25280
- activation.ledger.openWaitWindow(
25281
- activation.clock,
25282
- startedAt === void 0 ? void 0 : { startedAt }
25283
- );
25284
- activation.ledger.completeOperational(toolCallId);
25285
- return {
25286
- content: [{
25287
- type: "text",
25288
- text: "\u7B49\u5F85\u7A97\u5DF2\u5F00\u542F"
25289
- }],
25290
- details: {
25291
- activationTime: activation.ledger.activationTime?.toISOString(),
25292
- deadlineTime: activation.ledger.deadlineTime?.toISOString(),
25293
- waitWindowMs: activation.ledger.config.waitWindowMs
25294
- }
25295
- };
25296
- } catch (error) {
25297
- if (isCorrectableExecuteError(error)) throw error;
25298
- hostActions.failInfrastructure(error, ctx, toolCallId);
25299
- } finally {
25300
- try {
25301
- activation.ledger.completeOperational(toolCallId);
25302
- } catch {
25303
- }
25304
- }
25305
- }
25306
- });
25307
- pi.registerTool({
25308
- name: COLLECTOR_WAIT_TOOL,
25309
- label: "\u901A\u8FDB\u53F8\u7B49\u5F85",
25310
- description: "\u7B49\u5F85\u3002\u5B9E\u9645\u7761\u7720\u4E0D\u8D85\u8FC7\u5269\u4F59\u7B49\u5F85\u7A97\u3002",
25311
- promptSnippet: "\u7B49\u5F85\u7A97\u5185\u7B49\u5F85",
25312
- parameters: waitSchema,
25313
- async execute(toolCallId, params, signal, _onUpdate, ctx) {
25314
- const activation = getActivation();
25315
- if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
25316
- try {
25317
- activation.ledger.beginOperational(COLLECTOR_WAIT_TOOL, toolCallId);
25318
- const details = await activation.ledger.wait(
25319
- params,
25320
- activation.clock,
25321
- signal
25322
- );
25323
- activation.ledger.completeOperational(toolCallId);
25324
- return {
25325
- content: [{
25326
- type: "text",
25327
- text: `\u5DF2\u7B49\u5F85 ${String(details.effectiveMs)}ms`
25328
- }],
25329
- details
25330
- };
25331
- } catch (error) {
25332
- if (isCorrectableExecuteError(error)) throw error;
25333
- hostActions.failInfrastructure(error, ctx, toolCallId);
25334
- }
25335
- }
25336
- });
25337
22768
  pi.registerTool({
25338
22769
  name: COLLECTOR_OUTPUT_TOOL,
25339
22770
  label: "\u901A\u8FDB\u53F8\u8F93\u51FA",
25340
22771
  description: "\u63D0\u4EA4\u901A\u8FDB\u53F8\u56DE\u6267\u3002",
25341
22772
  promptSnippet: "\u63D0\u4EA4\u901A\u8FDB\u53F8\u56DE\u6267",
25342
22773
  parameters: outputSchema,
25343
- async execute(toolCallId, params, _signal, _onUpdate, ctx) {
22774
+ async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
25344
22775
  const activation = getActivation();
25345
22776
  if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
25346
- try {
25347
- activation.ledger.beginOperational(COLLECTOR_OUTPUT_TOOL, toolCallId);
25348
- activation.ledger.recordOutputCandidate();
25349
- return {
25350
- content: [],
25351
- details: params,
25352
- terminate: true
25353
- };
25354
- } catch (error) {
25355
- if (error instanceof Error && error.collectorFatal === true) {
25356
- hostActions.failInfrastructure(error, ctx, toolCallId);
25357
- }
25358
- throw error;
25359
- } finally {
25360
- activation.ledger.completeOperational(toolCallId);
25361
- }
22777
+ return {
22778
+ content: [],
22779
+ details: params,
22780
+ terminate: true
22781
+ };
25362
22782
  }
25363
22783
  });
25364
22784
  }
@@ -25884,7 +23304,7 @@ init_submission_errors();
25884
23304
  init_worker_submission_contracts();
25885
23305
  init_submission_errors();
25886
23306
  init_worker_submission_contracts();
25887
- import { execFileSync as execFileSync4 } from "node:child_process";
23307
+ import { execFileSync as execFileSync3 } from "node:child_process";
25888
23308
  import { existsSync as existsSync14, lstatSync as lstatSync3, readdirSync as readdirSync4, readFileSync as readFileSync5, rmdirSync, rmSync as rmSync2 } from "node:fs";
25889
23309
  import { resolve as resolve20 } from "node:path";
25890
23310
  var WORKER_SUBMISSION_GATE_RECORD_KIND = WORKER_SUBMISSION_GATE_KIND;
@@ -25897,7 +23317,7 @@ var HOOK_FILE = "reference-transaction";
25897
23317
  var PLATFORM_PREFIX = /^[A-Za-z][A-Za-z0-9_-]*:/;
25898
23318
  var UNFINISHED_REASON_BOUNCE_LIMIT = 2;
25899
23319
  function git2(cwd, args) {
25900
- return execFileSync4("git", args, {
23320
+ return execFileSync3("git", args, {
25901
23321
  cwd,
25902
23322
  encoding: "utf8",
25903
23323
  stdio: ["ignore", "pipe", "pipe"],
@@ -25905,7 +23325,7 @@ function git2(cwd, args) {
25905
23325
  }).trim();
25906
23326
  }
25907
23327
  function gitFile(file, args) {
25908
- return execFileSync4("git", ["config", "--file", file, ...args], {
23328
+ return execFileSync3("git", ["config", "--file", file, ...args], {
25909
23329
  encoding: "utf8",
25910
23330
  stdio: ["ignore", "pipe", "pipe"],
25911
23331
  env: { ...process.env, GIT_DIR: void 0, GIT_WORK_TREE: void 0, GIT_COMMON_DIR: void 0 }
@@ -25981,7 +23401,7 @@ function uninstallPackageWorkerHooks(cwd) {
25981
23401
  rmOwnedDir(resolve20(gitDir, HOOKS_DIR));
25982
23402
  }
25983
23403
  }
25984
- function isRecord16(value) {
23404
+ function isRecord15(value) {
25985
23405
  return typeof value === "object" && value !== null && !Array.isArray(value);
25986
23406
  }
25987
23407
  function unfinishedReasonPresent(details) {
@@ -25997,7 +23417,7 @@ function readGateState(session) {
25997
23417
  if (entry.type !== "custom") continue;
25998
23418
  if (entry.customType === WORKER_COMMIT_BASELINE_ENTRY_TYPE) {
25999
23419
  const data = entry.data;
26000
- if (isRecord16(data) && (data.head === null || typeof data.head === "string")) {
23420
+ if (isRecord15(data) && (data.head === null || typeof data.head === "string")) {
26001
23421
  baseline = data.head;
26002
23422
  }
26003
23423
  } else if (entry.customType === WORKER_COMMIT_REMINDER_BOUNCE_ENTRY_TYPE) {
@@ -26023,11 +23443,11 @@ function reliableWindow(cwd, baseline, head) {
26023
23443
  const raw = git2(cwd, ["log", "--format=%P%x1e%s", range]);
26024
23444
  if (raw.length === 0) return [];
26025
23445
  return raw.split("\n").flatMap((line2) => {
26026
- const sep7 = line2.indexOf("");
26027
- if (sep7 < 0) return [];
23446
+ const sep6 = line2.indexOf("");
23447
+ if (sep6 < 0) return [];
26028
23448
  return [{
26029
- subject: line2.slice(sep7 + 1),
26030
- merge: line2.slice(0, sep7).trim().includes(" ")
23449
+ subject: line2.slice(sep6 + 1),
23450
+ merge: line2.slice(0, sep6).trim().includes(" ")
26031
23451
  }];
26032
23452
  });
26033
23453
  }
@@ -26190,11 +23610,11 @@ var FIXER_PHASES = ["plan", "apply"];
26190
23610
  function isWorkerPhase(value) {
26191
23611
  return typeof value === "string" && FIXER_PHASES.includes(value);
26192
23612
  }
26193
- function isRecord17(value) {
23613
+ function isRecord16(value) {
26194
23614
  return typeof value === "object" && value !== null && !Array.isArray(value);
26195
23615
  }
26196
23616
  function workerStatusOf(output) {
26197
- return isRecord17(output) && typeof output.status === "string" ? output.status : void 0;
23617
+ return isRecord16(output) && typeof output.status === "string" ? output.status : void 0;
26198
23618
  }
26199
23619
  function deepFreeze2(value) {
26200
23620
  if (typeof value !== "object" || value === null || Object.isFrozen(value)) return value;
@@ -26880,7 +24300,7 @@ function readDiaristTicketAssertion(submitted) {
26880
24300
  function readRoleRunCoordinates(ctx, label) {
26881
24301
  const runDirectory = runDirectoryFromHostContext(ctx);
26882
24302
  if (runDirectory === void 0) throw new Error(`${label} requires AK_ROLE_RUN_DIR`);
26883
- const admittedPath = join45(runDirectory, "admitted-request.json");
24303
+ const admittedPath = join44(runDirectory, "admitted-request.json");
26884
24304
  const admitted = JSON.parse(readFileSync6(admittedPath, "utf8"));
26885
24305
  if (typeof admitted.projectRoot !== "string" || admitted.projectRoot.trim() === "") {
26886
24306
  throw new Error(`${label} admitted-request missing projectRoot (${admittedPath})`);
@@ -27192,10 +24612,6 @@ function createRoleRuntimeExtension(dependencies) {
27192
24612
  };
27193
24613
  }
27194
24614
  if (activeCollector !== void 0 && selectedRole === role) {
27195
- if (!collectorFirstDispatchDone) {
27196
- collectorFirstDispatchDone = true;
27197
- activeCollector.ledger.recordActivation(activeCollector.clock);
27198
- }
27199
24615
  return {
27200
24616
  systemPrompt: collectorBusiness.assembleMaterials(activeCollector, event.systemPrompt)
27201
24617
  };
@@ -27236,9 +24652,6 @@ function createRoleRuntimeExtension(dependencies) {
27236
24652
  roleHost.on("tool_result", async (event) => {
27237
24653
  const role = selectedRole;
27238
24654
  if (role === void 0) return;
27239
- if (activeCollector !== void 0 && selectedRole === roleHost.getFlag(ROLE_FLAG.name)) {
27240
- collectorBusiness.onToolResult(activeCollector, event);
27241
- }
27242
24655
  const pendingInfra = pendingInfrastructureFailures.get(event.toolCallId);
27243
24656
  const isRoleInfrastructureFailure = pendingInfra !== void 0;
27244
24657
  if (pendingInfra !== void 0) pendingInfrastructureFailures.delete(event.toolCallId);
@@ -27373,11 +24786,6 @@ function createRoleRuntimeExtension(dependencies) {
27373
24786
  priorFetch = void 0;
27374
24787
  fetchWrapped = false;
27375
24788
  }
27376
- if (activeCollector !== void 0 && activeCollector.ledger.fatal) {
27377
- if (process.exitCode === void 0 || process.exitCode === 0) {
27378
- process.exitCode = 1;
27379
- }
27380
- }
27381
24789
  const presentation = pendingNavigatorPresentation;
27382
24790
  pendingNavigatorPresentation = void 0;
27383
24791
  if (presentation !== void 0) {
@@ -27509,41 +24917,16 @@ function createRoleRuntimeExtension(dependencies) {
27509
24917
  }
27510
24918
  });
27511
24919
  let activeCollector;
27512
- let collectorFirstDispatchDone = false;
27513
24920
  const collectorBusiness = createCollectorRoleRuntime(
27514
24921
  roleHost,
27515
24922
  {
27516
- loadSoul: () => requireRoleSoul("collector"),
27517
- createTransport() {
27518
- if (dependencies.createCollectorTransport === void 0) {
27519
- throw new Error("Collector GitHub transport is not configured");
27520
- }
27521
- return dependencies.createCollectorTransport();
27522
- },
27523
- createLedger(config, collectorClock, context) {
27524
- const append = context.sessionManager?.appendCustomEntry;
27525
- return createCollectorLedger(config, {
27526
- clock: collectorClock,
27527
- ...append === void 0 ? {} : {
27528
- journal: {
27529
- append(customType, data) {
27530
- context.sessionManager?.appendCustomEntry?.(customType, data);
27531
- }
27532
- }
27533
- },
27534
- dossierEntries: context.sessionManager?.getEntries?.() ?? []
27535
- });
27536
- },
27537
- ...dependencies.createCollectorClock === void 0 ? {} : { createClock: dependencies.createCollectorClock },
27538
- ...dependencies.loadCollectorHandbookSeed === void 0 ? {} : { loadHandbookSeed: dependencies.loadCollectorHandbookSeed }
27539
- },
27540
- hostActions
24923
+ loadSoul: () => requireRoleSoul("collector")
24924
+ }
27541
24925
  );
27542
24926
  let collectorToolCallRegistered = false;
27543
24927
  const collector = {
27544
24928
  async activate(context, event) {
27545
24929
  activeCollector = void 0;
27546
- collectorFirstDispatchDone = false;
27547
24930
  if (context.mode !== "print" && context.mode !== "json") {
27548
24931
  throw new Error(
27549
24932
  `Collector supports only print or json mode (got ${context.mode})`
@@ -27577,16 +24960,19 @@ function createRoleRuntimeExtension(dependencies) {
27577
24960
  throw new Error(`Collector required tool name collision: ${required}`);
27578
24961
  }
27579
24962
  }
27580
- roleHost.setActiveTools([...COLLECTOR_REQUIRED_TOOLS]);
24963
+ const priorActive = roleHost.getActiveTools();
24964
+ const hostSurface = (priorActive.length > 0 ? priorActive : allTools.map((tool) => tool.name)).filter((name) => !COLLECTOR_CONSTRUCTION_TOOLS.includes(name));
24965
+ const nextActive = [.../* @__PURE__ */ new Set([...hostSurface, ...COLLECTOR_REQUIRED_TOOLS])];
24966
+ roleHost.setActiveTools(nextActive);
27581
24967
  const active = new Set(roleHost.getActiveTools());
27582
24968
  for (const required of COLLECTOR_REQUIRED_TOOLS) {
27583
24969
  if (!active.has(required)) {
27584
24970
  throw new Error(`Collector failed to activate required tool ${required}`);
27585
24971
  }
27586
24972
  }
27587
- for (const name of active) {
27588
- if (!COLLECTOR_REQUIRED_TOOLS.includes(name)) {
27589
- throw new Error(`Collector active tool surface includes unexpected ${name}`);
24973
+ for (const name of COLLECTOR_CONSTRUCTION_TOOLS) {
24974
+ if (active.has(name)) {
24975
+ throw new Error(`Collector must not activate construction tool ${name}`);
27590
24976
  }
27591
24977
  }
27592
24978
  if (!collectorToolCallRegistered) {
@@ -27594,20 +24980,10 @@ function createRoleRuntimeExtension(dependencies) {
27594
24980
  roleHost.on("tool_call", (toolEvent) => {
27595
24981
  const liveRole = roleHost.getFlag(ROLE_FLAG.name);
27596
24982
  if (activeCollector === void 0 || selectedRole === void 0 || selectedRole !== liveRole) return;
27597
- if (!COLLECTOR_REQUIRED_TOOLS.includes(toolEvent.toolName)) {
27598
- return {
27599
- block: true,
27600
- reason: `\u901A\u8FDB\u53F8\u7981\u7528\u5DE5\u5177 ${toolEvent.toolName}`
27601
- };
27602
- }
27603
24983
  return collectorBusiness.onToolCall(activeCollector, toolEvent);
27604
24984
  });
27605
24985
  }
27606
- const activation = await collectorBusiness.activate(context);
27607
- if (activation.ledger.activationRecorded) {
27608
- collectorFirstDispatchDone = true;
27609
- }
27610
- activeCollector = activation;
24986
+ activeCollector = await collectorBusiness.activate(context);
27611
24987
  }
27612
24988
  };
27613
24989
  const clock = dependencies.activationClock ?? (() => (/* @__PURE__ */ new Date()).toISOString());
@@ -27657,7 +25033,6 @@ function createRoleRuntimeExtension(dependencies) {
27657
25033
  roleReferenceMaterials = "";
27658
25034
  activeReviewerParent = void 0;
27659
25035
  activeCollector = void 0;
27660
- collectorFirstDispatchDone = false;
27661
25036
  receiptDelivery = createReceiptDeliveryPolicy();
27662
25037
  noReceiptRecorded = false;
27663
25038
  pendingNavigatorPresentation = void 0;
@@ -27810,19 +25185,16 @@ function loadRegisteredRoleSoul(role) {
27810
25185
  return usesSubjectSoul(role) ? loadAuditorSoulFromSubjectInput() : loadMainRoleSessionMaterials(role);
27811
25186
  }
27812
25187
  function createRoleRuntimeDependencies(packageRoot) {
27813
- const collectorHandbookSeedPath = join46(packageRoot, "resources/collector-bot-handbook.md");
27814
25188
  const navigatorSessionFactory = createNativeNavigatorSessionFactory();
27815
25189
  return {
27816
25190
  packageRoot,
27817
25191
  loadRoleReferenceMaterials: loadPackagedRoleReferenceMaterials,
27818
25192
  loadRoleSoul: loadRegisteredRoleSoul,
27819
- loadFixPacket: (path) => readFile25(path, "utf8"),
27820
- loadCoderTask: (path) => readFile25(path, "utf8"),
27821
- loadCollectorHandbookSeed: () => readFile25(collectorHandbookSeedPath, "utf8"),
27822
- createCollectorTransport: () => createGhCollectorGitHubTransport(),
25193
+ loadFixPacket: (path) => readFile24(path, "utf8"),
25194
+ loadCoderTask: (path) => readFile24(path, "utf8"),
27823
25195
  loadDoctorCase,
27824
25196
  loadNotarySourceRun: loadNotarySourceRunLocator,
27825
- loadMergerInput: async (path) => JSON.parse(await readFile25(path, "utf8")),
25197
+ loadMergerInput: async (path) => JSON.parse(await readFile24(path, "utf8")),
27826
25198
  loadNavigatorWorkContext: (options) => loadNavigatorWorkContext({
27827
25199
  context: options.context,
27828
25200
  role: options.role,
@@ -27849,7 +25221,7 @@ init_packaged_role_registry();
27849
25221
  import { randomUUID as randomUUID9 } from "node:crypto";
27850
25222
  import { appendFile as appendFile3, mkdir as mkdir5, writeFile as writeFile10 } from "node:fs/promises";
27851
25223
  import { createServer } from "node:net";
27852
- import { dirname as dirname25, join as join47 } from "node:path";
25224
+ import { dirname as dirname25, join as join45 } from "node:path";
27853
25225
  import { fileURLToPath as fileURLToPath2 } from "node:url";
27854
25226
  init_role_activation_flags();
27855
25227
  init_submission_correctable_error();
@@ -27895,7 +25267,7 @@ async function prepareRoleEnvelope(options) {
27895
25267
  const hostAbort = new AbortController();
27896
25268
  const runId = request.runDirectory.split("/").filter(Boolean).at(-1) ?? randomUUID9();
27897
25269
  await mkdir5(request.runDirectory, { recursive: true });
27898
- let sessionFile = options.sessionFile ?? join47(request.runDirectory, "session", "session.jsonl");
25270
+ let sessionFile = options.sessionFile ?? join45(request.runDirectory, "session", "session.jsonl");
27899
25271
  await mkdir5(dirname25(sessionFile), { recursive: true });
27900
25272
  if (request.continuation.kind !== "resume") {
27901
25273
  try {
@@ -28415,7 +25787,7 @@ async function prepareRoleEnvelope(options) {
28415
25787
  init_session_identity();
28416
25788
 
28417
25789
  // src/headless-host/description.ts
28418
- import { join as join48 } from "node:path";
25790
+ import { join as join46 } from "node:path";
28419
25791
  function isClaudePrintDescription(description) {
28420
25792
  return description.protocol === "claude-print";
28421
25793
  }
@@ -28423,7 +25795,7 @@ function isCodexExecDescription(description) {
28423
25795
  return description.protocol === "codex-exec";
28424
25796
  }
28425
25797
  function resolveHeadlessBinary(description, operatorHome) {
28426
- return join48(operatorHome, ...description.binaryFromHome);
25798
+ return join46(operatorHome, ...description.binaryFromHome);
28427
25799
  }
28428
25800
  function headlessTurnArgs(options) {
28429
25801
  const { description } = options;
@@ -28683,11 +26055,11 @@ function headlessMcpConfigDocument(mcpServers) {
28683
26055
  }
28684
26056
 
28685
26057
  // src/headless-host/role-turn-host.ts
28686
- import { spawn as spawn4, spawnSync as spawnSync3 } from "node:child_process";
26058
+ import { spawn as spawn3, spawnSync as spawnSync3 } from "node:child_process";
28687
26059
  import { randomUUID as randomUUID10 } from "node:crypto";
28688
26060
  import { existsSync as existsSync15 } from "node:fs";
28689
26061
  import { writeFile as writeFile11 } from "node:fs/promises";
28690
- import { dirname as dirname26, isAbsolute as isAbsolute12, join as join49, resolve as resolve21 } from "node:path";
26062
+ import { dirname as dirname26, isAbsolute as isAbsolute12, join as join47, resolve as resolve21 } from "node:path";
28691
26063
 
28692
26064
  // src/external-host-turn-loop.ts
28693
26065
  var EXTERNAL_ROLE_TURN_ROUND_LIMIT = 8;
@@ -28873,7 +26245,7 @@ function formatCodexFailurePayload(payload) {
28873
26245
  function cwdIsGitWorkTree(cwd) {
28874
26246
  let dir = cwd;
28875
26247
  for (; ; ) {
28876
- if (existsSync15(join49(dir, ".git"))) return true;
26248
+ if (existsSync15(join47(dir, ".git"))) return true;
28877
26249
  const parent = dirname26(dir);
28878
26250
  if (parent === dir) return false;
28879
26251
  dir = parent;
@@ -28910,7 +26282,7 @@ function spawnHeadlessTurn(options) {
28910
26282
  reject(hostAbortedError("headless host aborted"));
28911
26283
  return;
28912
26284
  }
28913
- const child = spawn4(options.binary, [...options.args], {
26285
+ const child = spawn3(options.binary, [...options.args], {
28914
26286
  cwd: options.cwd,
28915
26287
  env: options.env,
28916
26288
  stdio: ["pipe", "pipe", "pipe"]
@@ -29089,13 +26461,13 @@ function createHeadlessRoleTurnHost(config) {
29089
26461
  await config.sessionIdentity.bind(request.principal, sessionId);
29090
26462
  }
29091
26463
  const env = { ...process.env, ...config.env ?? {} };
29092
- const systemPromptPath = join49(request.runDirectory, "headless-system-prompt.txt");
26464
+ const systemPromptPath = join47(request.runDirectory, "headless-system-prompt.txt");
29093
26465
  await writeFile11(systemPromptPath, systemPrompt, "utf8");
29094
26466
  let mcpConfigPath;
29095
26467
  let outputSchemaPath;
29096
26468
  if (codex) {
29097
26469
  if (prepared.terminatingToolName !== NAVIGATOR_OUTPUT_TOOL_NAME) {
29098
- outputSchemaPath = join49(request.runDirectory, "headless-output-schema.json");
26470
+ outputSchemaPath = join47(request.runDirectory, "headless-output-schema.json");
29099
26471
  await writeFile11(
29100
26472
  outputSchemaPath,
29101
26473
  `${JSON.stringify(closeJsonSchemaForCodex(prepared.jsonSchema), null, 2)}
@@ -29104,7 +26476,7 @@ function createHeadlessRoleTurnHost(config) {
29104
26476
  );
29105
26477
  }
29106
26478
  } else {
29107
- mcpConfigPath = join49(request.runDirectory, "headless-mcp-config.json");
26479
+ mcpConfigPath = join47(request.runDirectory, "headless-mcp-config.json");
29108
26480
  await writeFile11(
29109
26481
  mcpConfigPath,
29110
26482
  `${JSON.stringify(headlessMcpConfigDocument(prepared.mcpServers), null, 2)}
@@ -29368,7 +26740,7 @@ function createHeadlessRoleTurnHost(config) {
29368
26740
  host: config.hostName,
29369
26741
  sessionId: exitedSessionId,
29370
26742
  cwd: request.cwd,
29371
- sessionDirectory: join49(request.runDirectory, "session"),
26743
+ sessionDirectory: join47(request.runDirectory, "session"),
29372
26744
  sessionParent,
29373
26745
  continuation: request.continuation,
29374
26746
  ...request.model !== void 0 ? { model: request.model } : {},