@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
@@ -206,1960 +206,6 @@ var init_collector_output = __esm({
206
206
  }
207
207
  });
208
208
 
209
- // src/collector-evidence.ts
210
- import { createHash } from "node:crypto";
211
- function createSystemCollectorClock() {
212
- const start = process.hrtime.bigint();
213
- return {
214
- wallNow: () => /* @__PURE__ */ new Date(),
215
- monoNow: () => Number(process.hrtime.bigint() - start) / 1e6,
216
- sleep: (ms, signal) => new Promise((resolve22, reject) => {
217
- if (signal?.aborted) {
218
- reject(signal.reason ?? new Error("aborted"));
219
- return;
220
- }
221
- const timer = setTimeout(resolve22, ms);
222
- const onAbort = () => {
223
- clearTimeout(timer);
224
- reject(signal?.reason ?? new Error("aborted"));
225
- };
226
- signal?.addEventListener("abort", onAbort, { once: true });
227
- })
228
- };
229
- }
230
- function sha256Text(text) {
231
- return createHash("sha256").update(text, "utf8").digest("hex");
232
- }
233
- function computeWindowRelation(authoritativeTime, activationTime, deadlineTime) {
234
- if (authoritativeTime === void 0 || authoritativeTime === null || authoritativeTime.length === 0) {
235
- return "uncertain";
236
- }
237
- const ms = Date.parse(authoritativeTime);
238
- if (!Number.isFinite(ms)) return "uncertain";
239
- const activationMs = activationTime.getTime();
240
- const deadlineMs = deadlineTime.getTime();
241
- if (ms < activationMs) return "before";
242
- if (ms <= deadlineMs) return "within";
243
- return "after";
244
- }
245
- function stableId(kind, githubId) {
246
- return `${kind}:${githubId}`;
247
- }
248
- function versionDigest(parts) {
249
- return sha256Text(JSON.stringify(parts));
250
- }
251
- function evidenceIdFor(kind, versionId) {
252
- return sha256Text(`${kind}:${versionId}`).slice(0, 16);
253
- }
254
- function normalizeAuthenticatedUserEvidence(user, observedAt) {
255
- const login = user.login.toLowerCase();
256
- const rawId = user.raw?.id;
257
- const stableNumericOrStringId = typeof rawId === "number" || typeof rawId === "string" ? rawId : void 0;
258
- const retainedRaw = { login };
259
- if (stableNumericOrStringId !== void 0) {
260
- retainedRaw.id = stableNumericOrStringId;
261
- }
262
- const contentDigest = versionDigest({
263
- login,
264
- ...stableNumericOrStringId !== void 0 ? { id: stableNumericOrStringId } : {}
265
- });
266
- const versionId = `user:${login}:${contentDigest.slice(0, 12)}`;
267
- return {
268
- evidenceId: evidenceIdFor("authenticated_user", versionId),
269
- kind: "authenticated_user",
270
- stableGitHubId: stableId("user", login),
271
- versionId,
272
- contentDigest,
273
- authorLogin: login,
274
- firstObservedAt: observedAt,
275
- raw: retainedRaw
276
- };
277
- }
278
- function normalizePullRequestEvidence(pr, observedAt) {
279
- const contentDigest = versionDigest({
280
- number: pr.number,
281
- state: pr.state,
282
- headOid: pr.headOid,
283
- createdAt: pr.createdAt ?? null,
284
- updatedAt: pr.updatedAt ?? null,
285
- htmlUrl: pr.url
286
- });
287
- const versionId = `pr:${pr.number}:${contentDigest.slice(0, 12)}`;
288
- return {
289
- evidenceId: evidenceIdFor("pull_request", versionId),
290
- kind: "pull_request",
291
- stableGitHubId: stableId("pr", pr.number),
292
- versionId,
293
- contentDigest,
294
- state: pr.state,
295
- commitOid: pr.headOid,
296
- htmlUrl: pr.url,
297
- // Version clock stays updatedAt. Create success for the wait window is snapshot.prCreatedAt only (#678).
298
- authoritativeTime: pr.updatedAt ?? null,
299
- firstObservedAt: observedAt,
300
- raw: pr.raw
301
- };
302
- }
303
- function normalizeReviewEvidence(review, observedAt) {
304
- const authorLogin = review.userLogin === null || review.userLogin === void 0 ? void 0 : review.userLogin.toLowerCase();
305
- const contentDigest = versionDigest({
306
- id: review.id,
307
- state: review.state,
308
- body: review.body,
309
- commitId: review.commitId,
310
- submittedAt: review.submittedAt,
311
- htmlUrl: review.htmlUrl,
312
- userLogin: authorLogin ?? null,
313
- machineIdentity: review.machineIdentity ?? null
314
- });
315
- const versionId = `review:${review.id}:${contentDigest.slice(0, 12)}`;
316
- return {
317
- evidenceId: evidenceIdFor("review", versionId),
318
- kind: "review",
319
- stableGitHubId: stableId("review", review.id),
320
- githubId: review.id,
321
- machineIdentity: review.machineIdentity ?? null,
322
- versionId,
323
- contentDigest,
324
- ...authorLogin === void 0 ? {} : { authorLogin },
325
- state: review.state,
326
- body: review.body,
327
- commitOid: review.commitId,
328
- htmlUrl: review.htmlUrl,
329
- // Submission metadata only; ledger history assigns authoritativeTime.
330
- submittedAt: review.submittedAt,
331
- authoritativeTime: review.submittedAt,
332
- firstObservedAt: observedAt,
333
- raw: review.raw
334
- };
335
- }
336
- function normalizePullRequestReactionEvidence(reaction, observedAt) {
337
- const authorLogin = reaction.userLogin?.toLowerCase();
338
- const contentDigest = versionDigest({
339
- id: reaction.id,
340
- content: reaction.content,
341
- createdAt: reaction.createdAt,
342
- machineIdentity: reaction.machineIdentity ?? null
343
- });
344
- const versionId = `reaction:${reaction.id}:${contentDigest.slice(0, 12)}`;
345
- return {
346
- evidenceId: evidenceIdFor("reaction", versionId),
347
- kind: "reaction",
348
- stableGitHubId: stableId("reaction", reaction.id),
349
- githubId: reaction.id,
350
- machineIdentity: reaction.machineIdentity ?? null,
351
- versionId,
352
- contentDigest,
353
- ...authorLogin === void 0 ? {} : { authorLogin },
354
- body: reaction.content,
355
- authoritativeTime: reaction.createdAt,
356
- firstObservedAt: observedAt,
357
- raw: reaction.raw
358
- };
359
- }
360
- function normalizeIssueCommentEvidence(comment, observedAt) {
361
- const authorLogin = comment.userLogin === null || comment.userLogin === void 0 ? void 0 : comment.userLogin.toLowerCase();
362
- const contentDigest = versionDigest({
363
- id: comment.id,
364
- body: comment.body,
365
- updatedAt: comment.updatedAt,
366
- userLogin: authorLogin ?? null,
367
- machineIdentity: comment.machineIdentity ?? null,
368
- htmlUrl: comment.htmlUrl
369
- });
370
- const versionId = `issue_comment:${comment.id}:${contentDigest.slice(0, 12)}`;
371
- return {
372
- evidenceId: evidenceIdFor("issue_comment", versionId),
373
- kind: "issue_comment",
374
- stableGitHubId: stableId("issue_comment", comment.id),
375
- githubId: comment.id,
376
- machineIdentity: comment.machineIdentity ?? null,
377
- versionId,
378
- contentDigest,
379
- ...authorLogin === void 0 ? {} : { authorLogin },
380
- body: comment.body,
381
- htmlUrl: comment.htmlUrl,
382
- authoritativeTime: comment.updatedAt ?? null,
383
- firstObservedAt: observedAt,
384
- raw: comment.raw
385
- };
386
- }
387
- function normalizeReviewCommentEvidence(comment, observedAt) {
388
- const authorLogin = comment.userLogin === null || comment.userLogin === void 0 ? void 0 : comment.userLogin.toLowerCase();
389
- const contentDigest = versionDigest({
390
- id: comment.id,
391
- body: comment.body,
392
- path: comment.path,
393
- line: comment.line,
394
- originalLine: comment.originalLine,
395
- side: comment.side,
396
- position: comment.position,
397
- updatedAt: comment.updatedAt,
398
- commitId: comment.commitId,
399
- pullRequestReviewId: comment.pullRequestReviewId,
400
- userLogin: authorLogin ?? null,
401
- machineIdentity: comment.machineIdentity ?? null,
402
- htmlUrl: comment.htmlUrl
403
- });
404
- const versionId = `review_comment:${comment.id}:${contentDigest.slice(0, 12)}`;
405
- return {
406
- evidenceId: evidenceIdFor("review_comment", versionId),
407
- kind: "review_comment",
408
- stableGitHubId: stableId("review_comment", comment.id),
409
- githubId: comment.id,
410
- machineIdentity: comment.machineIdentity ?? null,
411
- versionId,
412
- contentDigest,
413
- ...authorLogin === void 0 ? {} : { authorLogin },
414
- body: comment.body,
415
- commitOid: comment.commitId,
416
- htmlUrl: comment.htmlUrl,
417
- path: comment.path,
418
- line: comment.line,
419
- originalLine: comment.originalLine,
420
- side: comment.side,
421
- position: comment.position,
422
- pullRequestReviewId: comment.pullRequestReviewId,
423
- authoritativeTime: comment.updatedAt ?? null,
424
- firstObservedAt: observedAt,
425
- raw: comment.raw
426
- };
427
- }
428
- function applyEvidenceVersionHistory(pending, priorEvidence, cutoff) {
429
- const versionsByStable = /* @__PURE__ */ new Map();
430
- const add = (stableIdValue, versionId) => {
431
- let set = versionsByStable.get(stableIdValue);
432
- if (set === void 0) {
433
- set = /* @__PURE__ */ new Set();
434
- versionsByStable.set(stableIdValue, set);
435
- }
436
- set.add(versionId);
437
- };
438
- for (const record4 of priorEvidence) {
439
- if (record4.stableGitHubId !== void 0) {
440
- add(record4.stableGitHubId, record4.versionId);
441
- }
442
- }
443
- const priorByVersionId = /* @__PURE__ */ new Map();
444
- for (const record4 of priorEvidence) {
445
- priorByVersionId.set(record4.versionId, record4);
446
- }
447
- for (const record4 of pending) {
448
- if (record4.stableGitHubId === void 0) continue;
449
- const priorVersions = versionsByStable.get(record4.stableGitHubId) ?? /* @__PURE__ */ new Set();
450
- const isNewVersion = !priorVersions.has(record4.versionId);
451
- const hadEarlierDistinctVersion = [...priorVersions].some(
452
- (versionId) => versionId !== record4.versionId
453
- );
454
- if (record4.kind === "review") {
455
- if (!isNewVersion) {
456
- const prior = priorByVersionId.get(record4.versionId);
457
- if (prior !== void 0) {
458
- record4.authoritativeTime = prior.authoritativeTime ?? null;
459
- }
460
- } else if (hadEarlierDistinctVersion) {
461
- record4.authoritativeTime = null;
462
- } else {
463
- const { deadlineMono, firstObservedMono } = cutoff;
464
- if (!Number.isFinite(deadlineMono) || !Number.isFinite(firstObservedMono) || firstObservedMono > deadlineMono) {
465
- record4.authoritativeTime = null;
466
- } else {
467
- record4.authoritativeTime = record4.submittedAt ?? null;
468
- }
469
- }
470
- } else if (record4.kind === "issue_comment" || record4.kind === "review_comment") {
471
- if (record4.authoritativeTime === void 0 || record4.authoritativeTime === "") {
472
- record4.authoritativeTime = null;
473
- }
474
- }
475
- if (isNewVersion) {
476
- add(record4.stableGitHubId, record4.versionId);
477
- }
478
- }
479
- }
480
- function measureNormalizedBytes(records) {
481
- return Buffer.byteLength(JSON.stringify(records), "utf8");
482
- }
483
- function assignWindowRelations(records, activationTime, deadlineTime) {
484
- if (activationTime === void 0 || deadlineTime === void 0) return;
485
- for (const record4 of records) {
486
- if (record4.kind === "review" || record4.kind === "issue_comment" || record4.kind === "review_comment" || record4.kind === "pull_request") {
487
- record4.windowRelation = computeWindowRelation(
488
- record4.authoritativeTime,
489
- activationTime,
490
- deadlineTime
491
- );
492
- }
493
- }
494
- }
495
- var COLLECTOR_DEFAULT_WAIT_WINDOW_MS;
496
- var init_collector_evidence = __esm({
497
- "src/collector-evidence.ts"() {
498
- "use strict";
499
- COLLECTOR_DEFAULT_WAIT_WINDOW_MS = 10 * 60 * 1e3;
500
- }
501
- });
502
-
503
- // src/collector-config.ts
504
- import { createHash as createHash2 } from "node:crypto";
505
- import { readFile } from "node:fs/promises";
506
- function fail(message, cause) {
507
- throw new Error(message, cause === void 0 ? void 0 : { cause });
508
- }
509
- function conservativeAscii(input) {
510
- for (let i = 0; i < input.length; i += 1) {
511
- const code = input.charCodeAt(i);
512
- if (code <= 31 || code === 127 || code > 127) return false;
513
- }
514
- return true;
515
- }
516
- function parseCollectorRepository(raw) {
517
- if (typeof raw !== "string" || raw.trim() !== raw || raw.length === 0) fail("Collector repository must be a string owner/repo");
518
- if (!conservativeAscii(raw) || raw.includes("://") || /[?#@%\\ ]/.test(raw)) fail("Collector repository rejects URL syntax and non-identity bytes");
519
- const parts = raw.split("/");
520
- if (parts.length !== 2) fail("Collector repository must contain exactly one '/' separating owner and repo");
521
- const [ownerDisplay, repoDisplay] = parts;
522
- if (!COLLECTOR_OWNER_PATTERN.test(ownerDisplay) || !COLLECTOR_REPO_PATTERN.test(repoDisplay)) fail("Collector repository does not match the conservative owner/repo grammar");
523
- const owner = ownerDisplay.toLowerCase();
524
- const repo = repoDisplay.toLowerCase();
525
- return { display: raw, canonical: `${owner}/${repo}`, owner, repo };
526
- }
527
- function parseCollectorPrNumber(raw) {
528
- if (typeof raw === "string" && !/^[1-9][0-9]*$/.test(raw)) fail("Collector pull request number must be a positive safe integer string");
529
- if (typeof raw !== "string" && typeof raw !== "number") fail("Collector pull request number is required");
530
- const value = Number(raw);
531
- if (!Number.isSafeInteger(value) || value < 1) fail("Collector pull request number must be a positive safe integer");
532
- return value;
533
- }
534
- function record(value) {
535
- return typeof value === "object" && value !== null && !Array.isArray(value);
536
- }
537
- function canonicalManifest(requests) {
538
- return `${JSON.stringify({ requests: requests.map((request) => ({ id: request.id, body: request.requestBody })) })}
539
- `;
540
- }
541
- function emptyCollectorManifest() {
542
- const canonicalJson2 = canonicalManifest([]);
543
- return { requests: [], canonicalJson: canonicalJson2, digest: createHash2("sha256").update(canonicalJson2).digest("hex") };
544
- }
545
- async function loadCollectorManifest(path) {
546
- let bytes;
547
- try {
548
- bytes = await readFile(path);
549
- } catch (error) {
550
- fail(`Collector request manifest is unreadable at ${path}`, error);
551
- }
552
- let parsed;
553
- try {
554
- parsed = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
555
- } catch (error) {
556
- fail("Collector request manifest must be UTF-8 JSON", error);
557
- }
558
- if (!record(parsed)) fail("Collector request manifest must be an object");
559
- const rawRequests = parsed.requests ?? [];
560
- if (!Array.isArray(rawRequests)) fail("Collector request manifest requests must be an array");
561
- const requests = [];
562
- const ids = /* @__PURE__ */ new Set();
563
- for (const [index, item] of rawRequests.entries()) {
564
- 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`);
565
- if (ids.has(item.id)) fail(`Collector request manifest has duplicate request id "${item.id}"`);
566
- ids.add(item.id);
567
- requests.push({ id: item.id, requestBody: item.body });
568
- }
569
- const canonicalJson2 = canonicalManifest(requests);
570
- return { requests, canonicalJson: canonicalJson2, digest: createHash2("sha256").update(canonicalJson2).digest("hex"), sourcePath: path };
571
- }
572
- var COLLECTOR_OWNER_PATTERN, COLLECTOR_REPO_PATTERN;
573
- var init_collector_config = __esm({
574
- "src/collector-config.ts"() {
575
- "use strict";
576
- COLLECTOR_OWNER_PATTERN = /^[A-Za-z0-9](?:[A-Za-z0-9-]{0,37}[A-Za-z0-9])?$/;
577
- COLLECTOR_REPO_PATTERN = /^[A-Za-z0-9](?:[A-Za-z0-9._-]{0,98}[A-Za-z0-9])?$/;
578
- }
579
- });
580
-
581
- // src/collector-github.ts
582
- import { spawn as spawn2 } from "node:child_process";
583
- import { createHash as createHash3 } from "node:crypto";
584
- function isRecord(value) {
585
- return typeof value === "object" && value !== null && !Array.isArray(value);
586
- }
587
- function requireString(value, label) {
588
- if (typeof value !== "string") {
589
- throw new Error(`GitHub payload missing string ${label}`);
590
- }
591
- return value;
592
- }
593
- function requireNumber(value, label) {
594
- if (typeof value !== "number" || !Number.isFinite(value)) {
595
- throw new Error(`GitHub payload missing number ${label}`);
596
- }
597
- return value;
598
- }
599
- function optionalString(value) {
600
- return typeof value === "string" ? value : null;
601
- }
602
- function parseLinkNext(linkHeader) {
603
- if (linkHeader === void 0 || linkHeader.length === 0) return void 0;
604
- for (const part of linkHeader.split(",")) {
605
- const match = part.trim().match(/^<([^>]+)>\s*;\s*rel="next"$/i);
606
- if (match?.[1]) return match[1];
607
- }
608
- return void 0;
609
- }
610
- function parseJson(text, label) {
611
- try {
612
- return JSON.parse(text);
613
- } catch (error) {
614
- throw new Error(`GitHub ${label} returned malformed JSON`, { cause: error });
615
- }
616
- }
617
- function parsePullRequestNumberList(raw, label) {
618
- if (!Array.isArray(raw)) {
619
- throw new Error(`GitHub ${label} payload is not a list`);
620
- }
621
- const numbers = [];
622
- for (const item of raw) {
623
- if (!isRecord(item)) {
624
- throw new Error(`GitHub ${label} payload contains a non-object pull request entry`);
625
- }
626
- try {
627
- numbers.push(parseCollectorPrNumber(item["number"]));
628
- } catch (error) {
629
- throw new Error(`GitHub ${label} payload contains an invalid pull request number`, {
630
- cause: error
631
- });
632
- }
633
- }
634
- return numbers;
635
- }
636
- async function listPullRequestNumbersByHead(runner, input) {
637
- const head = `${input.headOwner}:${input.headRef}`;
638
- const path = `/repos/${input.owner}/${input.repo}/pulls?head=${encodeURIComponent(head)}&state=all&per_page=100`;
639
- const response = await runner(
640
- ["api", "--hostname", "github.com", "--include", "-X", "GET", path],
641
- input.signal === void 0 ? {} : { signal: input.signal }
642
- );
643
- if (response.status < 200 || response.status >= 300) {
644
- throw new Error(`GitHub ${path} failed with HTTP ${response.status}`, {
645
- cause: {
646
- endpoint: path,
647
- status: response.status,
648
- headers: response.headers,
649
- body: response.bodyText
650
- }
651
- });
652
- }
653
- return parsePullRequestNumberList(parseJson(response.bodyText, path), path);
654
- }
655
- async function listPullRequestNumbersByCommit(runner, input) {
656
- const path = `/repos/${input.owner}/${input.repo}/commits/${encodeURIComponent(input.commitSha)}/pulls`;
657
- const response = await runner(
658
- ["api", "--hostname", "github.com", "--include", "-X", "GET", path],
659
- input.signal === void 0 ? {} : { signal: input.signal }
660
- );
661
- if (response.status < 200 || response.status >= 300) {
662
- throw new Error(`GitHub ${path} failed with HTTP ${response.status}`, {
663
- cause: {
664
- endpoint: path,
665
- status: response.status,
666
- headers: response.headers,
667
- body: response.bodyText
668
- }
669
- });
670
- }
671
- return parsePullRequestNumberList(parseJson(response.bodyText, path), path);
672
- }
673
- async function listPullRequestNumbersByTicket(runner, input) {
674
- const issuePath = `/repos/${input.owner}/${input.repo}/issues/${input.ticketNumber}`;
675
- const issueResponse = await runner(
676
- ["api", "--hostname", "github.com", "--include", "-X", "GET", issuePath],
677
- input.signal === void 0 ? {} : { signal: input.signal }
678
- );
679
- if (issueResponse.status === 404) return [];
680
- if (issueResponse.status < 200 || issueResponse.status >= 300) {
681
- throw new Error(`GitHub ${issuePath} failed with HTTP ${issueResponse.status}`, {
682
- cause: {
683
- endpoint: issuePath,
684
- status: issueResponse.status,
685
- headers: issueResponse.headers,
686
- body: issueResponse.bodyText
687
- }
688
- });
689
- }
690
- const issueRaw = parseJson(issueResponse.bodyText, issuePath);
691
- if (!isRecord(issueRaw)) {
692
- throw new Error(`GitHub ${issuePath} payload is not an object`);
693
- }
694
- if (Object.hasOwn(issueRaw, "pull_request")) {
695
- return [parseCollectorPrNumber(issueRaw["number"] ?? input.ticketNumber)];
696
- }
697
- const query = `query($owner: String!, $repo: String!, $number: Int!) {
698
- repository(owner: $owner, name: $repo) {
699
- issue(number: $number) {
700
- closedByPullRequestsReferences(first: 50) { nodes { number } }
701
- timelineItems(first: 100, itemTypes: [CROSS_REFERENCED_EVENT, CONNECTED_EVENT]) {
702
- nodes {
703
- __typename
704
- ... on CrossReferencedEvent {
705
- source { ... on PullRequest { number } }
706
- }
707
- ... on ConnectedEvent {
708
- subject { ... on PullRequest { number } }
709
- }
710
- }
711
- }
712
- }
713
- }
714
- }`;
715
- const args = [
716
- "api",
717
- "graphql",
718
- "--hostname",
719
- "github.com",
720
- "--include",
721
- "-f",
722
- `query=${query}`,
723
- "-f",
724
- `owner=${input.owner}`,
725
- "-f",
726
- `repo=${input.repo}`,
727
- "-F",
728
- `number=${input.ticketNumber}`
729
- ];
730
- const gqlResponse = await runner(
731
- args,
732
- input.signal === void 0 ? {} : { signal: input.signal }
733
- );
734
- if (gqlResponse.status < 200 || gqlResponse.status >= 300) {
735
- throw new Error(`GitHub GraphQL issue\u2192PR failed with HTTP ${gqlResponse.status}`, {
736
- cause: {
737
- endpoint: "graphql",
738
- status: gqlResponse.status,
739
- headers: gqlResponse.headers,
740
- body: gqlResponse.bodyText
741
- }
742
- });
743
- }
744
- let payload;
745
- try {
746
- payload = JSON.parse(gqlResponse.bodyText);
747
- } catch (error) {
748
- throw new Error("GitHub GraphQL issue\u2192PR returned malformed JSON", { cause: error });
749
- }
750
- if (!isRecord(payload)) {
751
- throw new Error("GitHub GraphQL issue\u2192PR payload is not an object");
752
- }
753
- if (payload.errors !== void 0) {
754
- throw new Error(`GitHub GraphQL issue\u2192PR errors: ${JSON.stringify(payload.errors).slice(0, 600)}`, {
755
- cause: { body: gqlResponse.bodyText, errors: payload.errors }
756
- });
757
- }
758
- const data = payload.data;
759
- if (!isRecord(data)) return [];
760
- const repository = data["repository"];
761
- if (!isRecord(repository)) return [];
762
- const issue = repository["issue"];
763
- if (!isRecord(issue)) return [];
764
- const numbers = [];
765
- const closedBy = issue["closedByPullRequestsReferences"];
766
- if (isRecord(closedBy) && Array.isArray(closedBy["nodes"])) {
767
- for (const node of closedBy["nodes"]) {
768
- if (isRecord(node) && typeof node["number"] === "number") {
769
- numbers.push(parseCollectorPrNumber(node["number"]));
770
- }
771
- }
772
- }
773
- const timeline = issue["timelineItems"];
774
- if (isRecord(timeline) && Array.isArray(timeline["nodes"])) {
775
- for (const node of timeline["nodes"]) {
776
- if (!isRecord(node)) continue;
777
- const source = node["source"];
778
- if (isRecord(source) && typeof source["number"] === "number") {
779
- numbers.push(parseCollectorPrNumber(source["number"]));
780
- }
781
- const subject = node["subject"];
782
- if (isRecord(subject) && typeof subject["number"] === "number") {
783
- numbers.push(parseCollectorPrNumber(subject["number"]));
784
- }
785
- }
786
- }
787
- return [...new Set(numbers)];
788
- }
789
- function commentFailureCause(error) {
790
- return {
791
- name: error instanceof Error ? error.name : typeof error,
792
- message: error instanceof Error ? error.message : String(error),
793
- evidenceId: `github-comment-failure-${++commentFailureEvidence}`
794
- };
795
- }
796
- function requireUserLogin(raw) {
797
- if (!isRecord(raw) || typeof raw["login"] !== "string") {
798
- throw new Error("GitHub payload missing user.login");
799
- }
800
- return raw["login"];
801
- }
802
- function optionalUserLogin(raw) {
803
- if (raw === null) return null;
804
- if (!isRecord(raw) || typeof raw["login"] !== "string") {
805
- throw new Error("GitHub payload missing user.login");
806
- }
807
- return raw["login"];
808
- }
809
- function machineIdentity(raw) {
810
- const user = raw["user"];
811
- if (!isRecord(user) || typeof user["type"] !== "string" || typeof user["id"] !== "number") {
812
- return null;
813
- }
814
- const app = raw["performed_via_github_app"];
815
- const appId = isRecord(app) && typeof app["id"] === "number" ? app["id"] : void 0;
816
- return {
817
- userType: user["type"],
818
- userId: user["id"],
819
- ...appId === void 0 ? {} : { appId }
820
- };
821
- }
822
- function normalizePullRequest(raw) {
823
- if (!isRecord(raw)) throw new Error("GitHub pull request payload must be an object");
824
- const head = raw["head"];
825
- if (!isRecord(head) || typeof head["sha"] !== "string" || head["sha"].length === 0) {
826
- throw new Error("GitHub pull request payload missing head.sha");
827
- }
828
- const number = requireNumber(raw["number"], "number");
829
- const mergedFlag = raw["merged"] === true || typeof raw["merged_at"] === "string" && raw["merged_at"].length > 0;
830
- const rawState = requireString(raw["state"], "state").toUpperCase();
831
- const state = mergedFlag ? "MERGED" : rawState;
832
- const htmlUrl = typeof raw["html_url"] === "string" ? raw["html_url"] : `https://github.com/unknown/unknown/pull/${number}`;
833
- return {
834
- number,
835
- state,
836
- headOid: head["sha"],
837
- ...typeof raw["created_at"] === "string" ? { createdAt: raw["created_at"] } : {},
838
- ...typeof raw["updated_at"] === "string" ? { updatedAt: raw["updated_at"] } : {},
839
- url: htmlUrl,
840
- raw
841
- };
842
- }
843
- function normalizePullRequestReaction(raw) {
844
- if (!isRecord(raw)) throw new Error("GitHub reaction payload must be an object");
845
- return {
846
- id: requireNumber(raw["id"], "reaction.id"),
847
- userLogin: optionalUserLogin(raw["user"]),
848
- machineIdentity: machineIdentity(raw),
849
- content: requireString(raw["content"], "reaction.content"),
850
- createdAt: requireString(raw["created_at"], "reaction.created_at"),
851
- raw
852
- };
853
- }
854
- function normalizeReview(raw) {
855
- if (!isRecord(raw)) throw new Error("GitHub review payload must be an object");
856
- return {
857
- id: requireNumber(raw["id"], "review.id"),
858
- ...typeof raw["node_id"] === "string" ? { nodeId: raw["node_id"] } : {},
859
- userLogin: optionalUserLogin(raw["user"]),
860
- machineIdentity: machineIdentity(raw),
861
- state: requireString(raw["state"], "review.state").toUpperCase(),
862
- body: typeof raw["body"] === "string" ? raw["body"] : "",
863
- commitId: optionalString(raw["commit_id"]),
864
- submittedAt: optionalString(raw["submitted_at"]),
865
- htmlUrl: typeof raw["html_url"] === "string" ? raw["html_url"] : "",
866
- raw
867
- };
868
- }
869
- function normalizeIssueComment(raw) {
870
- if (!isRecord(raw)) throw new Error("GitHub issue comment payload must be an object");
871
- return {
872
- id: requireNumber(raw["id"], "comment.id"),
873
- userLogin: optionalUserLogin(raw["user"]),
874
- machineIdentity: machineIdentity(raw),
875
- body: typeof raw["body"] === "string" ? raw["body"] : "",
876
- createdAt: requireString(raw["created_at"], "comment.created_at"),
877
- updatedAt: requireString(raw["updated_at"], "comment.updated_at"),
878
- htmlUrl: typeof raw["html_url"] === "string" ? raw["html_url"] : "",
879
- raw
880
- };
881
- }
882
- function normalizeReviewComment(raw) {
883
- if (!isRecord(raw)) throw new Error("GitHub review comment payload must be an object");
884
- return {
885
- id: requireNumber(raw["id"], "review_comment.id"),
886
- pullRequestReviewId: typeof raw["pull_request_review_id"] === "number" ? raw["pull_request_review_id"] : null,
887
- userLogin: optionalUserLogin(raw["user"]),
888
- machineIdentity: machineIdentity(raw),
889
- body: typeof raw["body"] === "string" ? raw["body"] : "",
890
- path: requireString(raw["path"], "review_comment.path"),
891
- line: typeof raw["line"] === "number" ? raw["line"] : null,
892
- originalLine: typeof raw["original_line"] === "number" ? raw["original_line"] : null,
893
- side: optionalString(raw["side"]),
894
- position: typeof raw["position"] === "number" ? raw["position"] : null,
895
- originalPosition: typeof raw["original_position"] === "number" ? raw["original_position"] : null,
896
- commitId: optionalString(raw["commit_id"]),
897
- originalCommitId: optionalString(raw["original_commit_id"]),
898
- createdAt: requireString(raw["created_at"], "review_comment.created_at"),
899
- updatedAt: requireString(raw["updated_at"], "review_comment.updated_at"),
900
- htmlUrl: typeof raw["html_url"] === "string" ? raw["html_url"] : "",
901
- raw
902
- };
903
- }
904
- function createGhApiRunner(options = {}) {
905
- const spawnImpl = options.spawnImpl ?? spawn2;
906
- return async (args, runOptions = {}) => {
907
- return await new Promise((resolve22, reject) => {
908
- const signal = runOptions.signal;
909
- if (signal?.aborted) {
910
- reject(signal.reason ?? new Error("aborted"));
911
- return;
912
- }
913
- const child = spawnImpl("gh", args, {
914
- env: options.env ?? process.env,
915
- stdio: ["pipe", "pipe", "pipe"]
916
- });
917
- let stdout = "";
918
- let stderr = "";
919
- let settled = false;
920
- const settle = (fn) => {
921
- if (settled) return;
922
- settled = true;
923
- if (signal !== void 0) {
924
- signal.removeEventListener("abort", onAbort);
925
- }
926
- fn();
927
- };
928
- const onAbort = () => {
929
- try {
930
- child.kill("SIGTERM");
931
- } catch (error) {
932
- settle(() => reject(error));
933
- return;
934
- }
935
- settle(() => {
936
- reject(signal?.reason ?? new Error("aborted"));
937
- });
938
- };
939
- if (signal !== void 0) {
940
- signal.addEventListener("abort", onAbort, { once: true });
941
- }
942
- child.stdout.setEncoding("utf8").on("data", (chunk) => {
943
- stdout += chunk;
944
- });
945
- child.stderr.setEncoding("utf8").on("data", (chunk) => {
946
- stderr += chunk;
947
- });
948
- child.on("error", (error) => {
949
- settle(() => reject(error));
950
- });
951
- child.stdin.on("error", (error) => {
952
- settle(() => {
953
- if (signal?.aborted) {
954
- reject(signal.reason ?? new Error("aborted"));
955
- return;
956
- }
957
- const err = error instanceof Error ? error : new Error(String(error));
958
- reject(Object.assign(err, { ambiguousGhFailure: true }));
959
- });
960
- });
961
- if (runOptions.stdin !== void 0) {
962
- child.stdin.write(runOptions.stdin);
963
- }
964
- child.stdin.end();
965
- child.on("close", (code, signal2) => {
966
- settle(() => {
967
- const match = stdout.match(/^HTTP\/[\d.]+\s+(\d+)[^\n]*\r?\n([\s\S]*?)\r?\n\r?\n([\s\S]*)$/);
968
- if (match) {
969
- const status = Number(match[1]);
970
- const headerText = match[2] ?? "";
971
- const bodyText = match[3] ?? "";
972
- const headers = {};
973
- for (const line2 of headerText.split(/\r?\n/)) {
974
- const idx = line2.indexOf(":");
975
- if (idx === -1) continue;
976
- const name = line2.slice(0, idx).trim().toLowerCase();
977
- const value = line2.slice(idx + 1).trim();
978
- headers[name] = value;
979
- }
980
- resolve22({ status, headers, bodyText });
981
- return;
982
- }
983
- if (code === 0) {
984
- resolve22({ status: 200, headers: {}, bodyText: stdout });
985
- return;
986
- }
987
- const failure2 = new Error(
988
- `gh api failed without a parseable HTTP response (code=${String(code)}): ${stderr || stdout}`,
989
- { cause: { code, signal: signal2, stderr, stdout } }
990
- );
991
- reject(Object.assign(failure2, { ambiguousGhFailure: true, stderr, stdout, code, signal: signal2 }));
992
- });
993
- });
994
- });
995
- };
996
- }
997
- function createGhCollectorGitHubTransport(runner = createGhApiRunner()) {
998
- const hostnameArgs = ["api", "--hostname", "github.com", "--include"];
999
- async function apiGet(path, signal) {
1000
- return await runner(
1001
- [...hostnameArgs, "-X", "GET", path],
1002
- signal === void 0 ? {} : { signal }
1003
- );
1004
- }
1005
- async function paginate(path, mapItem, options = {}) {
1006
- const { signal, retainPage } = options;
1007
- const items = [];
1008
- const pages = [];
1009
- let nextPath = path;
1010
- let page = 1;
1011
- const seen = /* @__PURE__ */ new Set();
1012
- while (nextPath !== void 0) {
1013
- if (signal?.aborted) {
1014
- throw signal.reason ?? new Error("aborted");
1015
- }
1016
- if (seen.has(nextPath)) {
1017
- throw new Error(`GitHub pagination repeated page: ${nextPath}`);
1018
- }
1019
- seen.add(nextPath);
1020
- const response = await apiGet(nextPath, signal);
1021
- const diagnostics = {
1022
- path: nextPath,
1023
- page,
1024
- status: response.status,
1025
- itemCount: 0,
1026
- ...response.headers["link"] === void 0 ? {} : { linkHeader: response.headers["link"] }
1027
- };
1028
- if (response.status === 429) {
1029
- throw Object.assign(
1030
- new Error(`GitHub API rate limited on ${nextPath} (HTTP 429)`),
1031
- { githubStatus: 429, page: diagnostics }
1032
- );
1033
- }
1034
- if (response.status < 200 || response.status >= 300) {
1035
- throw Object.assign(
1036
- new Error(`GitHub API ${nextPath} failed with HTTP ${response.status}`),
1037
- { githubStatus: response.status, page: diagnostics }
1038
- );
1039
- }
1040
- const parsed = parseJson(response.bodyText, nextPath);
1041
- if (!Array.isArray(parsed)) {
1042
- throw new Error(`GitHub API ${nextPath} did not return a JSON array`);
1043
- }
1044
- diagnostics.itemCount = parsed.length;
1045
- pages.push(diagnostics);
1046
- const pageItems = parsed.map((entry) => mapItem(entry));
1047
- retainPage?.(pageItems);
1048
- for (const item of pageItems) items.push(item);
1049
- const nextUrl = parseLinkNext(response.headers["link"]);
1050
- if (nextUrl === void 0) {
1051
- nextPath = void 0;
1052
- } else {
1053
- if (nextUrl.startsWith("/")) {
1054
- nextPath = nextUrl;
1055
- } else {
1056
- const url = new URL(nextUrl);
1057
- if (url.hostname !== "api.github.com" && url.hostname !== "github.com") {
1058
- throw new Error(`unexpected pagination host ${url.hostname}`);
1059
- }
1060
- nextPath = `${url.pathname}${url.search}`;
1061
- if (nextPath.startsWith("/api/v3/")) {
1062
- nextPath = nextPath.slice("/api/v3".length);
1063
- }
1064
- }
1065
- }
1066
- page += 1;
1067
- }
1068
- return { items, pages };
1069
- }
1070
- return {
1071
- async getAuthenticatedUser(options = {}) {
1072
- const response = await apiGet("/user", options.signal);
1073
- if (response.status < 200 || response.status >= 300) {
1074
- throw new Error(`GitHub /user failed with HTTP ${response.status}`, { cause: { endpoint: "/user", status: response.status, headers: response.headers, body: response.bodyText } });
1075
- }
1076
- const raw = parseJson(response.bodyText, "/user");
1077
- return { login: requireUserLogin(raw).toLowerCase(), raw };
1078
- },
1079
- async getPullRequest(input) {
1080
- const path = `/repos/${input.owner}/${input.repo}/pulls/${input.prNumber}`;
1081
- const response = await apiGet(path, input.signal);
1082
- if (response.status < 200 || response.status >= 300) {
1083
- throw new Error(`GitHub ${path} failed with HTTP ${response.status}`, { cause: { endpoint: path, status: response.status, headers: response.headers, body: response.bodyText } });
1084
- }
1085
- return normalizePullRequest(parseJson(response.bodyText, path));
1086
- },
1087
- async listPullRequestReviews(input) {
1088
- const path = `/repos/${input.owner}/${input.repo}/pulls/${input.prNumber}/reviews?per_page=100`;
1089
- return await paginate(path, normalizeReview, {
1090
- ...input.signal === void 0 ? {} : { signal: input.signal },
1091
- ...input.retainPage === void 0 ? {} : { retainPage: input.retainPage }
1092
- });
1093
- },
1094
- async listPullRequestReactions(input) {
1095
- const path = `/repos/${input.owner}/${input.repo}/issues/${input.prNumber}/reactions?per_page=100`;
1096
- return await paginate(path, normalizePullRequestReaction, {
1097
- ...input.signal === void 0 ? {} : { signal: input.signal },
1098
- ...input.retainPage === void 0 ? {} : { retainPage: input.retainPage }
1099
- });
1100
- },
1101
- async listIssueComments(input) {
1102
- const path = `/repos/${input.owner}/${input.repo}/issues/${input.prNumber}/comments?per_page=100`;
1103
- return await paginate(path, normalizeIssueComment, {
1104
- ...input.signal === void 0 ? {} : { signal: input.signal },
1105
- ...input.retainPage === void 0 ? {} : { retainPage: input.retainPage }
1106
- });
1107
- },
1108
- async listReviewComments(input) {
1109
- const path = `/repos/${input.owner}/${input.repo}/pulls/${input.prNumber}/comments?per_page=100`;
1110
- return await paginate(path, normalizeReviewComment, {
1111
- ...input.signal === void 0 ? {} : { signal: input.signal },
1112
- ...input.retainPage === void 0 ? {} : { retainPage: input.retainPage }
1113
- });
1114
- },
1115
- async createIssueComment(input) {
1116
- const path = `/repos/${input.owner}/${input.repo}/issues/${input.prNumber}/comments`;
1117
- try {
1118
- const response = await runner(
1119
- [...hostnameArgs, "-X", "POST", path, "--input", "-"],
1120
- input.signal === void 0 ? { stdin: JSON.stringify({ body: input.body }) } : { stdin: JSON.stringify({ body: input.body }), signal: input.signal }
1121
- );
1122
- if (response.status >= 200 && response.status < 300) {
1123
- try {
1124
- return {
1125
- kind: "success",
1126
- comment: normalizeIssueComment(parseJson(response.bodyText, path))
1127
- };
1128
- } catch (error) {
1129
- const cause = commentFailureCause(error);
1130
- return { kind: "ambiguous_loss", diagnostics: cause.message, cause };
1131
- }
1132
- }
1133
- return {
1134
- kind: "rejected",
1135
- status: response.status,
1136
- diagnostics: `HTTP ${response.status}: ${response.bodyText.slice(0, 500)}`
1137
- };
1138
- } catch (error) {
1139
- if (input.signal?.aborted) {
1140
- throw error;
1141
- }
1142
- if (isRecord(error) && error["ambiguousGhFailure"] === true) {
1143
- const cause = commentFailureCause(error);
1144
- return { kind: "ambiguous_loss", diagnostics: cause.message, cause };
1145
- }
1146
- if (isRecord(error) && error["name"] === "AbortError") {
1147
- throw error;
1148
- }
1149
- throw error;
1150
- }
1151
- }
1152
- };
1153
- }
1154
- function buildCollectorRequestMarker(input) {
1155
- const prefix = input.manifestDigest.slice(0, 12);
1156
- const requestMarkerId = createHash3("sha256").update(input.requestId).digest("hex");
1157
- return `<!-- ak-collector:v1 manifest=${prefix} request=${requestMarkerId} head=${input.headOid} -->`;
1158
- }
1159
- function buildCollectorRequestBody(input) {
1160
- const marker = buildCollectorRequestMarker(input);
1161
- const body = input.configuredBody.endsWith("\n") ? `${input.configuredBody}${marker}
1162
- ` : `${input.configuredBody}
1163
- ${marker}
1164
- `;
1165
- return { body, marker };
1166
- }
1167
- var commentFailureEvidence;
1168
- var init_collector_github = __esm({
1169
- "src/collector-github.ts"() {
1170
- "use strict";
1171
- init_collector_config();
1172
- commentFailureEvidence = 0;
1173
- }
1174
- });
1175
-
1176
- // src/readable-gate-item.ts
1177
- var readable_gate_item_exports = {};
1178
- __export(readable_gate_item_exports, {
1179
- joinReadableGateItems: () => joinReadableGateItems,
1180
- readableGateItem: () => readableGateItem
1181
- });
1182
- function readableGateItem(value) {
1183
- return typeof value === "string" ? value : JSON.stringify(value);
1184
- }
1185
- function joinReadableGateItems(items, separator = "; ") {
1186
- return items.map(readableGateItem).join(separator);
1187
- }
1188
- var init_readable_gate_item = __esm({
1189
- "src/readable-gate-item.ts"() {
1190
- "use strict";
1191
- }
1192
- });
1193
-
1194
- // src/submission-errors.ts
1195
- function serializeReceipt(receipt) {
1196
- return readableGateItem(receipt);
1197
- }
1198
- function gatekeeperNonPassMessage(result) {
1199
- if (result.status === "continue") {
1200
- return serializeReceipt(result.receipt);
1201
- }
1202
- if (result.status === "transport_failure") {
1203
- const head = `\u95E8\u4E0B\u7701 ${result.status}\uFF08${result.stage}\uFF09\uFF1A${result.reason}`;
1204
- return result.submission === void 0 ? head : `${head}
1205
- ${serializeReceipt(result.submission)}`;
1206
- }
1207
- return `\u95E8\u4E0B\u7701 ${result.status}\uFF08${result.stage}\uFF09\uFF1A${result.reason}`;
1208
- }
1209
- function unreadableDiscriminatorNotice(field, received) {
1210
- if (received === void 0) return `\u8BFB\u4E0D\u51FA ${field}`;
1211
- return `\u8BFB\u4E0D\u51FA ${field}\uFF1A${readableGateItem(received)}`;
1212
- }
1213
- function receivedDiscriminator(receipt, field) {
1214
- if (receipt === null || typeof receipt !== "object" || Array.isArray(receipt)) return void 0;
1215
- if (!Object.hasOwn(receipt, field)) return void 0;
1216
- return receipt[field];
1217
- }
1218
- var GatekeeperDecisionError, WorkerCommitReminderError, WorkerPrefixReminderError, WorkerUnfinishedReasonReminderError, ParentQueueReaskError;
1219
- var init_submission_errors = __esm({
1220
- "src/submission-errors.ts"() {
1221
- "use strict";
1222
- init_readable_gate_item();
1223
- GatekeeperDecisionError = class extends Error {
1224
- result;
1225
- constructor(result, message) {
1226
- super(message ?? gatekeeperNonPassMessage(result));
1227
- this.name = "GatekeeperDecisionError";
1228
- this.result = result;
1229
- }
1230
- };
1231
- WorkerCommitReminderError = class extends Error {
1232
- code = "worker_commit_reminder";
1233
- constructor() {
1234
- super("\u672A\u89C2\u5BDF\u5230 commit");
1235
- this.name = "WorkerCommitReminderError";
1236
- }
1237
- };
1238
- WorkerPrefixReminderError = class extends Error {
1239
- code = "worker_prefix_reminder";
1240
- constructor() {
1241
- super("\u89C2\u5BDF\u5230\u7F3A\u524D\u7F00 commit");
1242
- this.name = "WorkerPrefixReminderError";
1243
- }
1244
- };
1245
- WorkerUnfinishedReasonReminderError = class extends Error {
1246
- code = "worker_unfinished_reason_reminder";
1247
- constructor() {
1248
- super("\u672C\u6B21 unfinished \u56DE\u6267\u672A\u542B reason\uFF1B\u672C\u63A5\u7F1D\u7F3A\u7531\u81F3\u591A\u6253\u56DE\u4E24\u6B21\u3002");
1249
- this.name = "WorkerUnfinishedReasonReminderError";
1250
- }
1251
- };
1252
- ParentQueueReaskError = class extends Error {
1253
- code = "parent_queue_reask";
1254
- constructor(message) {
1255
- super(message);
1256
- this.name = "ParentQueueReaskError";
1257
- }
1258
- };
1259
- }
1260
- });
1261
-
1262
- // src/submission-correctable-error.ts
1263
- function isCorrectableSubmissionError(error) {
1264
- return error instanceof CorrectableSubmissionError;
1265
- }
1266
- function isCorrectableExecuteError(error) {
1267
- return isCorrectableSubmissionError(error) || error instanceof GatekeeperDecisionError || error instanceof ParentQueueReaskError || error instanceof WorkerCommitReminderError || error instanceof WorkerPrefixReminderError || error instanceof WorkerUnfinishedReasonReminderError;
1268
- }
1269
- function projectCorrectableExecuteRejection(error) {
1270
- const diagnostic = error instanceof Error ? error.message : String(error);
1271
- if (error instanceof GatekeeperDecisionError) {
1272
- return { diagnostic, details: { ...error.result } };
1273
- }
1274
- if (error instanceof WorkerCommitReminderError || error instanceof WorkerPrefixReminderError || error instanceof WorkerUnfinishedReasonReminderError) {
1275
- return { diagnostic, details: { code: error.code } };
1276
- }
1277
- if (typeof error.code === "string") {
1278
- return { diagnostic, details: { code: error.code } };
1279
- }
1280
- return {
1281
- diagnostic,
1282
- details: {
1283
- code: error instanceof Error && error.name ? error.name : "correctable-submission-error"
1284
- }
1285
- };
1286
- }
1287
- var correctableSubmissionErrorBrand, CorrectableSubmissionError;
1288
- var init_submission_correctable_error = __esm({
1289
- "src/submission-correctable-error.ts"() {
1290
- "use strict";
1291
- init_submission_errors();
1292
- correctableSubmissionErrorBrand = /* @__PURE__ */ Symbol("ak-roles.correctable-submission-error");
1293
- CorrectableSubmissionError = class extends Error {
1294
- [correctableSubmissionErrorBrand] = true;
1295
- };
1296
- }
1297
- });
1298
-
1299
- // src/collector-identity.ts
1300
- var CollectorUnknownEvidenceError, CollectorNonOpenRequestError, CollectorWaitWindowClosedError;
1301
- var init_collector_identity = __esm({
1302
- "src/collector-identity.ts"() {
1303
- "use strict";
1304
- init_submission_correctable_error();
1305
- CollectorUnknownEvidenceError = class extends CorrectableSubmissionError {
1306
- constructor(evidenceId) {
1307
- 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`);
1308
- this.name = "CollectorUnknownEvidenceError";
1309
- }
1310
- };
1311
- CollectorNonOpenRequestError = class extends CorrectableSubmissionError {
1312
- constructor(prState) {
1313
- 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`);
1314
- this.name = "CollectorNonOpenRequestError";
1315
- }
1316
- };
1317
- CollectorWaitWindowClosedError = class extends CorrectableSubmissionError {
1318
- constructor(action) {
1319
- super(
1320
- 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"
1321
- );
1322
- this.name = "CollectorWaitWindowClosedError";
1323
- }
1324
- };
1325
- }
1326
- });
1327
-
1328
- // src/collector-ledger.ts
1329
- function projectObserveContextView(modelView) {
1330
- return modelView;
1331
- }
1332
- function isOperationalTool(name) {
1333
- return COLLECTOR_OPERATIONAL_TOOLS.includes(name);
1334
- }
1335
- function resolveWaitWindowMs(raw) {
1336
- if (raw === void 0) return COLLECTOR_DEFAULT_WAIT_WINDOW_MS;
1337
- if (!Number.isSafeInteger(raw) || raw < 1) {
1338
- throw new Error("\u901A\u8FDB\u53F8 waitWindowMs \u987B\u4E3A\u6B63\u5B89\u5168\u6574\u6570\u6BEB\u79D2");
1339
- }
1340
- return raw;
1341
- }
1342
- function createCollectorLedger(input, options) {
1343
- const config = {
1344
- repository: input.repository,
1345
- prNumber: input.prNumber,
1346
- manifest: input.manifest,
1347
- waitWindowMs: resolveWaitWindowMs(input.waitWindowMs)
1348
- };
1349
- const clock = options?.clock;
1350
- const journal = options?.journal;
1351
- let fatal = false;
1352
- let fatalReason;
1353
- let outputCandidate = false;
1354
- let pendingOutputCallId;
1355
- let sessionReady = false;
1356
- let activationTime;
1357
- let deadlineTime;
1358
- let activationMono;
1359
- let deadlineMono;
1360
- let requesterLogin;
1361
- let latestCompleteSnapshotId;
1362
- let finalObservationRequired = false;
1363
- let finalObservationCompleted = false;
1364
- let activeOperationalCallId;
1365
- let mutationGeneration = 0;
1366
- let observedGeneration = 0;
1367
- const evidenceById = /* @__PURE__ */ new Map();
1368
- const evidenceByVersion = /* @__PURE__ */ new Map();
1369
- const snapshots = [];
1370
- const attempts = [];
1371
- const attemptKeys = /* @__PURE__ */ new Set();
1372
- const waits = [];
1373
- const transportFailures = [];
1374
- const latchFatal = (reason, cause) => {
1375
- fatal = true;
1376
- fatalReason = reason;
1377
- const error = new Error(reason, cause === void 0 ? void 0 : { cause });
1378
- Object.assign(error, { collectorFatal: true });
1379
- return error;
1380
- };
1381
- const assertNotFatal = () => {
1382
- if (fatal) throw new Error(fatalReason ?? "\u901A\u8FDB\u53F8\u81F4\u547D\u72B6\u6001");
1383
- };
1384
- const storeEvidence = (record4) => {
1385
- const existingId = evidenceByVersion.get(record4.versionId);
1386
- if (existingId !== void 0) {
1387
- return evidenceById.get(existingId) ?? record4;
1388
- }
1389
- evidenceByVersion.set(record4.versionId, record4.evidenceId);
1390
- evidenceById.set(record4.evidenceId, record4);
1391
- return record4;
1392
- };
1393
- const monoNowOrThrow = (clock2) => clock2.monoNow();
1394
- const pastCutoff = (clock2) => {
1395
- if (deadlineMono === void 0) return false;
1396
- return monoNowOrThrow(clock2) >= deadlineMono;
1397
- };
1398
- const remainingMs = (clock2) => {
1399
- if (deadlineMono === void 0) return config.waitWindowMs;
1400
- return Math.max(0, deadlineMono - monoNowOrThrow(clock2));
1401
- };
1402
- const prIdentity = (pr) => `${pr.state}|${pr.headOid}|${pr.updatedAt ?? ""}`;
1403
- const requireBoundPr = () => {
1404
- if (config.prNumber === void 0) {
1405
- throw new Error("\u901A\u8FDB\u53F8 PR \u76EE\u6807\u672A\u7ED1\u5B9A");
1406
- }
1407
- return config.prNumber;
1408
- };
1409
- const fetchObserveSurfaces = async (transport, observedAt, signal) => {
1410
- const owner = config.repository.owner;
1411
- const repo = config.repository.repo;
1412
- const prNumber = requireBoundPr();
1413
- const signalOpt = signal === void 0 ? {} : { signal };
1414
- const user = await transport.getAuthenticatedUser(signalOpt);
1415
- const prInitial = await transport.getPullRequest({
1416
- owner,
1417
- repo,
1418
- prNumber,
1419
- ...signalOpt
1420
- });
1421
- const reviews = await transport.listPullRequestReviews({
1422
- owner,
1423
- repo,
1424
- prNumber,
1425
- ...signalOpt
1426
- });
1427
- const reactions = transport.listPullRequestReactions === void 0 ? { items: [], pages: [] } : await transport.listPullRequestReactions({ owner, repo, prNumber, ...signalOpt });
1428
- const issueComments = await transport.listIssueComments({
1429
- owner,
1430
- repo,
1431
- prNumber,
1432
- ...signalOpt
1433
- });
1434
- const reviewComments = await transport.listReviewComments({
1435
- owner,
1436
- repo,
1437
- prNumber,
1438
- ...signalOpt
1439
- });
1440
- const prTerminal = await transport.getPullRequest({
1441
- owner,
1442
- repo,
1443
- prNumber,
1444
- ...signalOpt
1445
- });
1446
- return { user, prInitial, reviews, reactions, issueComments, reviewComments, prTerminal };
1447
- };
1448
- const appendJournal = (customType, data) => {
1449
- journal?.append(customType, data);
1450
- };
1451
- const bindDeadlineMonoFromWall = () => {
1452
- if (clock === void 0 || activationTime === void 0 || deadlineTime === void 0) return;
1453
- const wallNow = clock.wallNow().getTime();
1454
- const monoNow = clock.monoNow();
1455
- activationMono = monoNow - (wallNow - activationTime.getTime());
1456
- deadlineMono = monoNow + (deadlineTime.getTime() - wallNow);
1457
- };
1458
- const rebindSnapshotCompletedMono = (snapshot) => {
1459
- const copy = { ...snapshot, evidenceIds: [...snapshot.evidenceIds] };
1460
- if (deadlineTime !== void 0 && deadlineMono !== void 0 && copy.completedAt !== void 0) {
1461
- const completedWall = new Date(copy.completedAt).getTime();
1462
- copy.completedMono = deadlineMono + (completedWall - deadlineTime.getTime());
1463
- }
1464
- return copy;
1465
- };
1466
- const commitActivationWindow = (nextActivation, nextDeadline) => {
1467
- if (activationTime !== void 0) return;
1468
- sessionReady = true;
1469
- activationTime = nextActivation;
1470
- deadlineTime = nextDeadline;
1471
- bindDeadlineMonoFromWall();
1472
- };
1473
- const recoverAmbiguousRequestLosses = (snapshotId, observedRecords) => {
1474
- for (const failure2 of transportFailures) {
1475
- if (failure2.recovered || failure2.kind !== "ambiguous_request_loss") continue;
1476
- if (failure2.marker === void 0 || failure2.requestId === void 0) continue;
1477
- const found = observedRecords.find(
1478
- (record4) => record4.kind === "issue_comment" && record4.authorLogin === requesterLogin && typeof record4.body === "string" && record4.body.includes(failure2.marker)
1479
- );
1480
- if (found === void 0) continue;
1481
- failure2.recovered = true;
1482
- const attempt = attempts.find(
1483
- (item) => item.status === "ambiguous_loss" && item.requestId === failure2.requestId && item.marker === failure2.marker
1484
- );
1485
- if (attempt !== void 0) {
1486
- attempt.status = "recovered";
1487
- attempt.commentEvidenceId = found.evidenceId;
1488
- attempt.recoverySnapshotId = snapshotId;
1489
- }
1490
- }
1491
- };
1492
- const finalizeObservedSnapshot = (snapshot) => {
1493
- if (requesterLogin === void 0) {
1494
- for (const id of snapshot.evidenceIds) {
1495
- const record4 = evidenceById.get(id);
1496
- if (record4?.kind === "authenticated_user" && record4.authorLogin !== void 0) {
1497
- requesterLogin = record4.authorLogin.toLowerCase();
1498
- break;
1499
- }
1500
- }
1501
- }
1502
- const stored = rebindSnapshotCompletedMono(snapshot);
1503
- snapshots.push(stored);
1504
- latestCompleteSnapshotId = stored.snapshotId;
1505
- const observedRecords = stored.evidenceIds.flatMap((id) => {
1506
- const record4 = evidenceById.get(id);
1507
- return record4 === void 0 ? [] : [record4];
1508
- });
1509
- recoverAmbiguousRequestLosses(stored.snapshotId, observedRecords);
1510
- observedGeneration = mutationGeneration;
1511
- if (finalObservationRequired && stored.completedMono !== void 0 && deadlineMono !== void 0 && stored.completedMono >= deadlineMono) {
1512
- finalObservationCompleted = true;
1513
- } else if (clock !== void 0 && deadlineMono !== void 0 && clock.monoNow() >= deadlineMono && stored.completedMono !== void 0 && stored.completedMono >= deadlineMono) {
1514
- finalObservationRequired = true;
1515
- finalObservationCompleted = true;
1516
- }
1517
- return stored;
1518
- };
1519
- const commitObservedSnapshot = (snapshot, evidenceRecords) => {
1520
- for (const record4 of evidenceRecords) {
1521
- storeEvidence(record4);
1522
- }
1523
- return finalizeObservedSnapshot(snapshot);
1524
- };
1525
- const commitRequestAttempt = (attempt, attemptKey, commentEvidence) => {
1526
- if (commentEvidence !== void 0) {
1527
- storeEvidence(commentEvidence);
1528
- }
1529
- const existing = attempts.find((item) => item.attemptId === attempt.attemptId);
1530
- if (existing === void 0) {
1531
- attempts.push({ ...attempt });
1532
- attemptKeys.add(attemptKey);
1533
- } else {
1534
- Object.assign(existing, attempt);
1535
- }
1536
- if (attempt.status === "ambiguous_loss" && !transportFailures.some((failure2) => failure2.requestId === attempt.requestId && failure2.observedHead === attempt.observedHead)) {
1537
- transportFailures.push({
1538
- failureId: sha256Text(`loss:${attempt.attemptId}`).slice(0, 16),
1539
- kind: "ambiguous_request_loss",
1540
- message: attempt.responseDiagnostics ?? "ambiguous request loss",
1541
- requestId: attempt.requestId,
1542
- observedHead: attempt.observedHead,
1543
- marker: attempt.marker,
1544
- recovered: false
1545
- });
1546
- }
1547
- if (attempt.status === "succeeded" || attempt.status === "ambiguous_loss") {
1548
- mutationGeneration += 1;
1549
- finalObservationCompleted = false;
1550
- }
1551
- };
1552
- const commitWaitRecord = (wait) => {
1553
- waits.push({ ...wait });
1554
- if (wait.cutoffReached) finalObservationRequired = true;
1555
- mutationGeneration += 1;
1556
- finalObservationCompleted = false;
1557
- };
1558
- const replayDossierEntries = (entries) => {
1559
- const orderedEntries = Array.from(entries);
1560
- const finalRequestStatus = /* @__PURE__ */ new Map();
1561
- for (const raw of orderedEntries) {
1562
- if (typeof raw !== "object" || raw === null) continue;
1563
- const entry = raw;
1564
- if (entry.type !== "custom" || entry.customType !== COLLECTOR_REQUEST_ENTRY_TYPE || typeof entry.data !== "object" || entry.data === null) continue;
1565
- const attempt = entry.data.attempt;
1566
- if (attempt?.attemptId !== void 0) finalRequestStatus.set(attempt.attemptId, attempt.status);
1567
- }
1568
- for (const raw of orderedEntries) {
1569
- if (typeof raw !== "object" || raw === null) continue;
1570
- const entry = raw;
1571
- if (entry.type !== "custom" || typeof entry.data !== "object" || entry.data === null) continue;
1572
- const data = entry.data;
1573
- if (entry.customType === COLLECTOR_ACTIVATION_ENTRY_TYPE) {
1574
- if (typeof data.activationTime === "string" && typeof data.deadlineTime === "string") {
1575
- commitActivationWindow(new Date(data.activationTime), new Date(data.deadlineTime));
1576
- } else if (data.sessionReady === true) {
1577
- sessionReady = true;
1578
- }
1579
- continue;
1580
- }
1581
- if (entry.customType === COLLECTOR_SNAPSHOT_ENTRY_TYPE) {
1582
- const snapshot = data.snapshot;
1583
- if (snapshot?.snapshotId === void 0 || !Array.isArray(data.evidence)) continue;
1584
- commitObservedSnapshot(snapshot, data.evidence);
1585
- continue;
1586
- }
1587
- if (entry.customType === COLLECTOR_REQUEST_ENTRY_TYPE) {
1588
- const attempt = data.attempt;
1589
- if (attempt?.attemptId === void 0) continue;
1590
- const attemptKey = typeof data.attemptKey === "string" ? data.attemptKey : [config.repository.canonical, String(config.prNumber), attempt.observedHead, attempt.requestId].join("|");
1591
- const commentEvidence = data.commentEvidence;
1592
- const replayAttempt = attempt.status === "started" && finalRequestStatus.get(attempt.attemptId) === "started" ? {
1593
- ...attempt,
1594
- status: "ambiguous_loss",
1595
- responseDiagnostics: "request interrupted after dispatch before completion was recorded"
1596
- } : attempt;
1597
- commitRequestAttempt(replayAttempt, attemptKey, commentEvidence);
1598
- continue;
1599
- }
1600
- if (entry.customType === COLLECTOR_WAIT_ENTRY_TYPE) {
1601
- const wait = data.waitRecord;
1602
- if (wait?.waitId === void 0) continue;
1603
- commitWaitRecord(wait);
1604
- }
1605
- }
1606
- };
1607
- if (options?.dossierEntries !== void 0) {
1608
- replayDossierEntries(options.dossierEntries);
1609
- }
1610
- if (clock !== void 0 && deadlineMono !== void 0 && clock.monoNow() >= deadlineMono) {
1611
- finalObservationRequired = true;
1612
- const lastSnap = snapshots.find((item) => item.snapshotId === latestCompleteSnapshotId);
1613
- if (lastSnap?.completedMono !== void 0 && lastSnap.completedMono >= deadlineMono) {
1614
- finalObservationCompleted = true;
1615
- }
1616
- }
1617
- const ledger = {
1618
- get config() {
1619
- return config;
1620
- },
1621
- get fatal() {
1622
- return fatal;
1623
- },
1624
- get fatalReason() {
1625
- return fatalReason;
1626
- },
1627
- get outputCandidate() {
1628
- return outputCandidate || pendingOutputCallId !== void 0;
1629
- },
1630
- get activationRecorded() {
1631
- return sessionReady;
1632
- },
1633
- get activationTime() {
1634
- return activationTime;
1635
- },
1636
- get deadlineTime() {
1637
- return deadlineTime;
1638
- },
1639
- get activationMono() {
1640
- return activationMono;
1641
- },
1642
- get deadlineMono() {
1643
- return deadlineMono;
1644
- },
1645
- get requesterLogin() {
1646
- return requesterLogin;
1647
- },
1648
- get latestCompleteSnapshotId() {
1649
- return latestCompleteSnapshotId;
1650
- },
1651
- get finalObservationRequired() {
1652
- return finalObservationRequired;
1653
- },
1654
- get finalObservationCompleted() {
1655
- return finalObservationCompleted;
1656
- },
1657
- get unresolvedTransportFailure() {
1658
- return transportFailures.some((failure2) => !failure2.recovered);
1659
- },
1660
- get mutationGeneration() {
1661
- return mutationGeneration;
1662
- },
1663
- get observedGeneration() {
1664
- return observedGeneration;
1665
- },
1666
- latchFatal,
1667
- assertNotFatal,
1668
- recordActivation(_clock) {
1669
- assertNotFatal();
1670
- if (sessionReady) return;
1671
- sessionReady = true;
1672
- appendJournal(COLLECTOR_ACTIVATION_ENTRY_TYPE, {
1673
- sessionReady: true
1674
- });
1675
- },
1676
- openWaitWindow(clock2, options2) {
1677
- assertNotFatal();
1678
- if (!sessionReady) {
1679
- throw latchFatal("\u901A\u8FDB\u53F8\u5F00\u542F\u7B49\u5F85\u7A97\u9700\u8981\u5148\u6FC0\u6D3B\u4F1A\u8BDD");
1680
- }
1681
- if (activationTime !== void 0) return;
1682
- const startedAt = options2?.startedAt ?? clock2.wallNow();
1683
- if (!(startedAt instanceof Date) || Number.isNaN(startedAt.getTime())) {
1684
- throw new Error("\u901A\u8FDB\u53F8\u7B49\u5F85\u7A97 startedAt \u987B\u4E3A\u6709\u6548\u65F6\u95F4");
1685
- }
1686
- const nextDeadline = new Date(startedAt.getTime() + config.waitWindowMs);
1687
- activationTime = startedAt;
1688
- deadlineTime = nextDeadline;
1689
- const wallNow = clock2.wallNow().getTime();
1690
- const monoNow = clock2.monoNow();
1691
- activationMono = monoNow - (wallNow - startedAt.getTime());
1692
- deadlineMono = monoNow + (nextDeadline.getTime() - wallNow);
1693
- appendJournal(COLLECTOR_ACTIVATION_ENTRY_TYPE, {
1694
- activationTime: activationTime.toISOString(),
1695
- deadlineTime: deadlineTime.toISOString(),
1696
- waitWindowMs: config.waitWindowMs
1697
- });
1698
- },
1699
- recordOutputCandidate() {
1700
- assertNotFatal();
1701
- outputCandidate = true;
1702
- },
1703
- bindTarget(prNumber) {
1704
- assertNotFatal();
1705
- config.prNumber = prNumber;
1706
- appendJournal("ak-collector-target-bound", {
1707
- prNumber,
1708
- repository: config.repository.canonical
1709
- });
1710
- },
1711
- beginOperational(toolName, toolCallId) {
1712
- assertNotFatal();
1713
- if (toolName === COLLECTOR_OUTPUT_TOOL) {
1714
- pendingOutputCallId = toolCallId;
1715
- return;
1716
- }
1717
- if (activeOperationalCallId === toolCallId) {
1718
- return;
1719
- }
1720
- if (activeOperationalCallId !== void 0) {
1721
- throw latchFatal("\u901A\u8FDB\u53F8\u64CD\u4F5C\u8C03\u7528\u5DF2\u5728\u8FDB\u884C");
1722
- }
1723
- if (!isOperationalTool(toolName)) {
1724
- throw latchFatal(`\u672A\u77E5\u901A\u8FDB\u53F8\u5DE5\u5177 ${toolName}`);
1725
- }
1726
- activeOperationalCallId = toolCallId;
1727
- },
1728
- completeOperational(toolCallId) {
1729
- if (pendingOutputCallId === toolCallId) {
1730
- pendingOutputCallId = void 0;
1731
- }
1732
- if (activeOperationalCallId === toolCallId) {
1733
- activeOperationalCallId = void 0;
1734
- }
1735
- },
1736
- noteCutoffObserved() {
1737
- finalObservationRequired = true;
1738
- },
1739
- assertOutputObservationLaw(clock2) {
1740
- assertNotFatal();
1741
- if (activationTime === void 0 || deadlineTime === void 0 || deadlineMono === void 0) {
1742
- throw new Error("\u901A\u8FDB\u53F8\u56DE\u6267\u9700\u8981\u6FC0\u6D3B\u65F6\u95F4\u7EBF");
1743
- }
1744
- if (latestCompleteSnapshotId === void 0) {
1745
- throw new Error("\u901A\u8FDB\u53F8\u56DE\u6267\u9700\u8981\u5B8C\u6574\u7EC8\u5C40\u5FEB\u7167");
1746
- }
1747
- if (observedGeneration !== mutationGeneration) {
1748
- throw new Error(
1749
- "\u901A\u8FDB\u53F8\u56DE\u6267\u8981\u6C42\u5728\u6700\u8FD1 request/wait \u53D8\u66F4\u540E\u5B8C\u6210\u4E00\u6B21 observe"
1750
- );
1751
- }
1752
- const snapshot = snapshots.find((item) => item.snapshotId === latestCompleteSnapshotId);
1753
- if (snapshot === void 0 || !snapshot.complete) {
1754
- throw new Error("\u901A\u8FDB\u53F8\u7EC8\u5C40\u5FEB\u7167\u7F3A\u5931\u6216\u4E0D\u5B8C\u6574");
1755
- }
1756
- const mono = monoNowOrThrow(clock2);
1757
- const atOrAfterCutoff = mono >= deadlineMono;
1758
- if (atOrAfterCutoff) {
1759
- finalObservationRequired = true;
1760
- if (snapshot.completedMono === void 0 || snapshot.completedMono < deadlineMono) {
1761
- throw new Error(
1762
- "\u901A\u8FDB\u53F8\u622A\u6B62\u65F6/\u540E\u56DE\u6267\u8981\u6C42\u4E0D\u65E9\u4E8E\u622A\u6B62\u5B8C\u6210\u7684\u5B8C\u6574\u89C2\u5BDF"
1763
- );
1764
- }
1765
- finalObservationCompleted = true;
1766
- }
1767
- },
1768
- async observe(transport, clock2, signal) {
1769
- assertNotFatal();
1770
- if (!sessionReady) {
1771
- throw latchFatal("\u901A\u8FDB\u53F8\u89C2\u5BDF\u9700\u8981\u6FC0\u6D3B");
1772
- }
1773
- if (signal?.aborted) {
1774
- const abortMessage = signal.reason instanceof Error ? signal.reason.message : String(signal.reason ?? "\u5DF2\u4E2D\u6B62");
1775
- throw latchFatal(`\u901A\u8FDB\u53F8\u89C2\u5BDF\u5931\u8D25\uFF1A${abortMessage}`, signal.reason);
1776
- }
1777
- const observedAt = clock2.wallNow().toISOString();
1778
- const cutoff = pastCutoff(clock2);
1779
- if (cutoff) {
1780
- finalObservationRequired = true;
1781
- }
1782
- let surfaces;
1783
- try {
1784
- surfaces = await fetchObserveSurfaces(transport, observedAt, signal);
1785
- if (prIdentity(surfaces.prInitial) !== prIdentity(surfaces.prTerminal)) {
1786
- surfaces = await fetchObserveSurfaces(transport, observedAt, signal);
1787
- if (prIdentity(surfaces.prInitial) !== prIdentity(surfaces.prTerminal)) {
1788
- throw new Error(
1789
- `PR \u8EAB\u4EFD\u5728 observe \u62EC\u5F27\u91CD\u8BD5\u540E\u4ECD\u6F02\u79FB\uFF08${prIdentity(surfaces.prInitial)} \u2192 ${prIdentity(surfaces.prTerminal)}\uFF09`
1790
- );
1791
- }
1792
- }
1793
- } catch (error) {
1794
- const message = error instanceof Error ? error.message : "\u672A\u77E5\u5931\u8D25";
1795
- throw latchFatal(`\u901A\u8FDB\u53F8\u89C2\u5BDF\u5931\u8D25\uFF1A${message}`, error);
1796
- }
1797
- const firstObservedAt = clock2.wallNow().toISOString();
1798
- const firstObservedMono = monoNowOrThrow(clock2);
1799
- const pr = surfaces.prTerminal;
1800
- const { user, reviews, reactions, issueComments, reviewComments } = surfaces;
1801
- requesterLogin = user.login.toLowerCase();
1802
- const pageDiagnostics = [
1803
- ...reviews.pages,
1804
- ...reactions.pages,
1805
- ...issueComments.pages,
1806
- ...reviewComments.pages
1807
- ];
1808
- const pendingRecords = [];
1809
- pendingRecords.push(normalizeAuthenticatedUserEvidence(user, firstObservedAt));
1810
- pendingRecords.push(normalizePullRequestEvidence(pr, firstObservedAt));
1811
- for (const review of reviews.items) {
1812
- pendingRecords.push(normalizeReviewEvidence(review, firstObservedAt));
1813
- }
1814
- for (const reaction of reactions.items) {
1815
- pendingRecords.push(normalizePullRequestReactionEvidence(reaction, firstObservedAt));
1816
- }
1817
- for (const comment of issueComments.items) {
1818
- pendingRecords.push(normalizeIssueCommentEvidence(comment, firstObservedAt));
1819
- }
1820
- for (const comment of reviewComments.items) {
1821
- pendingRecords.push(normalizeReviewCommentEvidence(comment, firstObservedAt));
1822
- }
1823
- applyEvidenceVersionHistory(
1824
- pendingRecords,
1825
- [...evidenceById.values()],
1826
- { deadlineMono, firstObservedMono }
1827
- );
1828
- assignWindowRelations(pendingRecords, activationTime, deadlineTime);
1829
- const normalizedByteLength = measureNormalizedBytes(pendingRecords);
1830
- const storedIds = [];
1831
- for (const record4 of pendingRecords) {
1832
- const stored = storeEvidence(record4);
1833
- storedIds.push(stored.evidenceId);
1834
- }
1835
- const storedRecords = storedIds.map((id) => {
1836
- const stored = evidenceById.get(id);
1837
- if (stored === void 0) {
1838
- throw latchFatal(`\u901A\u8FDB\u53F8\u89C2\u5BDF\u4E22\u5931\u5DF2\u5B58\u8BC1\u636E ${id}`);
1839
- }
1840
- return stored;
1841
- });
1842
- const completedAt = clock2.wallNow().toISOString();
1843
- const completedMono = clock2.monoNow();
1844
- const snapshotId = sha256Text(
1845
- `${completedAt}:${pr.headOid}:${storedIds.join(",")}`
1846
- ).slice(0, 16);
1847
- const snapshot = {
1848
- snapshotId,
1849
- observedAt,
1850
- completedAt,
1851
- completedMono,
1852
- host: "github.com",
1853
- repository: config.repository.canonical,
1854
- prNumber: requireBoundPr(),
1855
- prState: pr.state,
1856
- headOid: pr.headOid,
1857
- ...pr.createdAt === void 0 ? {} : { prCreatedAt: pr.createdAt },
1858
- complete: true,
1859
- evidenceIds: storedIds,
1860
- pageDiagnostics,
1861
- normalizedByteLength
1862
- };
1863
- if (cutoff) {
1864
- finalObservationRequired = true;
1865
- }
1866
- const committed = finalizeObservedSnapshot(snapshot);
1867
- appendJournal(COLLECTOR_SNAPSHOT_ENTRY_TYPE, {
1868
- snapshot: committed,
1869
- evidence: committed.evidenceIds.flatMap((id) => {
1870
- const record4 = evidenceById.get(id);
1871
- return record4 === void 0 ? [] : [record4];
1872
- })
1873
- });
1874
- const modelView = buildObserveModelView({
1875
- snapshot: committed,
1876
- records: committed.evidenceIds.flatMap((id) => {
1877
- const record4 = evidenceById.get(id);
1878
- return record4 === void 0 ? [] : [record4];
1879
- }),
1880
- requesterLogin,
1881
- attempts
1882
- });
1883
- return {
1884
- snapshot: committed,
1885
- modelView,
1886
- contextView: projectObserveContextView(modelView)
1887
- };
1888
- },
1889
- async request(input2, transport, clock2, signal) {
1890
- assertNotFatal();
1891
- if (!sessionReady) {
1892
- throw latchFatal("\u901A\u8FDB\u53F8\u8BF7\u6C42\u9700\u8981\u6FC0\u6D3B");
1893
- }
1894
- if (ledger.unresolvedTransportFailure) {
1895
- throw latchFatal("\u901A\u8FDB\u53F8\u8BF7\u6C42\u65F6\u5B58\u5728\u672A\u6062\u590D\u7684\u4F20\u8F93\u5931\u8D25");
1896
- }
1897
- if (typeof input2.requestId !== "string") {
1898
- throw new Error("\u901A\u8FDB\u53F8 requestId \u987B\u4E3A\u5B57\u7B26\u4E32");
1899
- }
1900
- const requestId = input2.requestId.trim();
1901
- if (requestId.length === 0) {
1902
- throw new Error("\u901A\u8FDB\u53F8 requestId \u987B\u4E3A\u975E\u7A7A\uFF08\u9996\u5C3E\u7A7A\u767D\u4E0D\u6784\u6210\u8EAB\u4EFD\uFF09");
1903
- }
1904
- const configured = config.manifest.requests.find((item) => item.id === requestId);
1905
- const roleBody = typeof input2.body === "string" ? input2.body : void 0;
1906
- if (configured === void 0) {
1907
- if (roleBody === void 0 || roleBody.trim().length === 0) {
1908
- throw new Error(
1909
- `\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`
1910
- );
1911
- }
1912
- }
1913
- const snapshot = snapshots.find((item) => item.snapshotId === input2.snapshotId);
1914
- if (snapshot === void 0) {
1915
- throw new Error(`\u672A\u77E5\u901A\u8FDB\u53F8 snapshotId "${input2.snapshotId}"`);
1916
- }
1917
- if (snapshot.snapshotId !== latestCompleteSnapshotId) {
1918
- throw new Error("\u901A\u8FDB\u53F8\u8BF7\u6C42\u8981\u6C42\u6700\u65B0\u5B8C\u6574\u5FEB\u7167");
1919
- }
1920
- if (snapshot.prState !== "OPEN") {
1921
- throw new CollectorNonOpenRequestError(snapshot.prState);
1922
- }
1923
- if (pastCutoff(clock2)) {
1924
- finalObservationRequired = true;
1925
- throw new CollectorWaitWindowClosedError("request");
1926
- }
1927
- const configuredBody = configured?.requestBody ?? roleBody;
1928
- const { body, marker } = buildCollectorRequestBody({
1929
- configuredBody,
1930
- manifestDigest: config.manifest.digest,
1931
- requestId,
1932
- headOid: snapshot.headOid
1933
- });
1934
- const existingMarker = snapshot.evidenceIds.some((id) => {
1935
- const record4 = evidenceById.get(id);
1936
- return record4?.kind === "issue_comment" && record4.authorLogin === requesterLogin && typeof record4.body === "string" && record4.body.includes(marker);
1937
- });
1938
- if (existingMarker) {
1939
- throw new Error(
1940
- `\u901A\u8FDB\u53F8\u5728\u6B64 HEAD \u5DF2\u6709\u540C marker \u7684\u5DF2\u8BA4\u8BC1\u8BF7\u6C42 "${requestId}"`
1941
- );
1942
- }
1943
- const boundPr = requireBoundPr();
1944
- const attemptKey = [
1945
- config.repository.canonical,
1946
- String(boundPr),
1947
- snapshot.headOid,
1948
- requestId
1949
- ].join("|");
1950
- if (attemptKeys.has(attemptKey)) {
1951
- throw new Error(
1952
- `\u901A\u8FDB\u53F8\u8FDB\u7A0B\u5185\u8BF7\u6C42 "${requestId}" \u5728 HEAD ${snapshot.headOid} \u7684 attempt \u5DF2\u7528`
1953
- );
1954
- }
1955
- const startedAt = clock2.wallNow().toISOString();
1956
- const attemptId = sha256Text(`${attemptKey}:${startedAt}`).slice(0, 16);
1957
- const attempt = {
1958
- attemptId,
1959
- requestId,
1960
- observedHead: snapshot.headOid,
1961
- snapshotId: snapshot.snapshotId,
1962
- marker,
1963
- body,
1964
- startedAt,
1965
- status: "started"
1966
- };
1967
- commitRequestAttempt(attempt, attemptKey, void 0);
1968
- appendJournal(COLLECTOR_REQUEST_ENTRY_TYPE, {
1969
- attempt: { ...attempt },
1970
- attemptKey
1971
- });
1972
- const result = await transport.createIssueComment({
1973
- owner: config.repository.owner,
1974
- repo: config.repository.repo,
1975
- prNumber: boundPr,
1976
- body,
1977
- ...signal === void 0 ? {} : { signal }
1978
- });
1979
- const journalRequest = (commentEvidence) => {
1980
- const attemptKey2 = [
1981
- config.repository.canonical,
1982
- String(config.prNumber),
1983
- attempt.observedHead,
1984
- attempt.requestId
1985
- ].join("|");
1986
- appendJournal(COLLECTOR_REQUEST_ENTRY_TYPE, {
1987
- attempt: { ...attempt },
1988
- attemptKey: attemptKey2,
1989
- commentEvidence
1990
- });
1991
- };
1992
- if (result.kind === "success") {
1993
- const record4 = normalizeIssueCommentEvidence(result.comment, startedAt);
1994
- attempt.status = "succeeded";
1995
- attempt.commentEvidenceId = record4.evidenceId;
1996
- commitRequestAttempt(attempt, attemptKey, record4);
1997
- journalRequest(record4);
1998
- return {
1999
- status: "succeeded",
2000
- attemptId,
2001
- requestId,
2002
- observedHead: snapshot.headOid,
2003
- marker,
2004
- commentEvidenceId: record4.evidenceId
2005
- };
2006
- }
2007
- if (result.kind === "ambiguous_loss") {
2008
- attempt.status = "ambiguous_loss";
2009
- attempt.responseDiagnostics = result.diagnostics;
2010
- commitRequestAttempt(attempt, attemptKey, void 0);
2011
- journalRequest(void 0);
2012
- return {
2013
- status: "ambiguous_loss",
2014
- attemptId,
2015
- requestId,
2016
- observedHead: snapshot.headOid,
2017
- marker,
2018
- diagnostics: result.diagnostics
2019
- };
2020
- }
2021
- attempt.status = "rejected";
2022
- attempt.responseDiagnostics = result.diagnostics;
2023
- commitRequestAttempt(attempt, attemptKey, void 0);
2024
- journalRequest(void 0);
2025
- throw latchFatal(`\u901A\u8FDB\u53F8\u8BF7\u6C42\u88AB\u62D2\uFF1A${result.diagnostics}`);
2026
- },
2027
- async wait(input2, clock2, signal) {
2028
- assertNotFatal();
2029
- if (!sessionReady) {
2030
- throw latchFatal("\u901A\u8FDB\u53F8\u7B49\u5F85\u9700\u8981\u6FC0\u6D3B");
2031
- }
2032
- if (activationTime === void 0 || deadlineTime === void 0) {
2033
- throw new CollectorWaitWindowClosedError("wait-before-open");
2034
- }
2035
- if (pastCutoff(clock2)) {
2036
- finalObservationRequired = true;
2037
- throw new CollectorWaitWindowClosedError("wait");
2038
- }
2039
- const remaining = remainingMs(clock2);
2040
- const effectiveMs = Math.min(input2.durationMs, remaining);
2041
- const startedAt = clock2.wallNow().toISOString();
2042
- const waitId = sha256Text(`wait:${startedAt}:${effectiveMs}`).slice(0, 16);
2043
- await clock2.sleep(effectiveMs, signal);
2044
- const endedAt = clock2.wallNow().toISOString();
2045
- const cutoffReached = pastCutoff(clock2);
2046
- const record4 = {
2047
- waitId,
2048
- requestedMs: input2.durationMs,
2049
- effectiveMs,
2050
- startedAt,
2051
- endedAt,
2052
- cutoffReached
2053
- };
2054
- commitWaitRecord(record4);
2055
- appendJournal(COLLECTOR_WAIT_ENTRY_TYPE, {
2056
- waitRecord: record4
2057
- });
2058
- return {
2059
- waitId,
2060
- requestedMs: input2.durationMs,
2061
- effectiveMs,
2062
- cutoffReached,
2063
- remainingMsAfter: remainingMs(clock2)
2064
- };
2065
- },
2066
- getSnapshot(snapshotId) {
2067
- return snapshots.find((item) => item.snapshotId === snapshotId);
2068
- },
2069
- getEvidence(evidenceId) {
2070
- return evidenceById.get(evidenceId);
2071
- },
2072
- allEvidence() {
2073
- return [...evidenceById.values()];
2074
- },
2075
- allSnapshots() {
2076
- return [...snapshots];
2077
- },
2078
- requestAttempts() {
2079
- return [...attempts];
2080
- },
2081
- waits() {
2082
- return [...waits];
2083
- },
2084
- transportFailures() {
2085
- return [...transportFailures];
2086
- },
2087
- requestById(requestId) {
2088
- return config.manifest.requests.find((request) => request.id === requestId);
2089
- }
2090
- };
2091
- return ledger;
2092
- }
2093
- function projectEvidenceEntryView(record4) {
2094
- return {
2095
- evidenceId: record4.evidenceId,
2096
- kind: record4.kind,
2097
- authorLogin: record4.authorLogin,
2098
- state: record4.state,
2099
- body: record4.body,
2100
- commitOid: record4.commitOid,
2101
- htmlUrl: record4.htmlUrl,
2102
- path: record4.path,
2103
- // Single display fallback: current line, else originalLine.
2104
- line: record4.line ?? record4.originalLine,
2105
- side: record4.side,
2106
- authoritativeTime: record4.authoritativeTime,
2107
- windowRelation: record4.windowRelation,
2108
- pullRequestReviewId: record4.pullRequestReviewId
2109
- };
2110
- }
2111
- function buildObserveModelView(input) {
2112
- const relevant = input.records;
2113
- return {
2114
- snapshotId: input.snapshot.snapshotId,
2115
- observedAt: input.snapshot.observedAt,
2116
- completedAt: input.snapshot.completedAt,
2117
- prState: input.snapshot.prState,
2118
- headOid: input.snapshot.headOid,
2119
- ...input.snapshot.prCreatedAt === void 0 ? {} : { prCreatedAt: input.snapshot.prCreatedAt },
2120
- complete: input.snapshot.complete,
2121
- evidence: relevant.map((record4) => projectEvidenceEntryView(record4)),
2122
- requestAttempts: input.attempts.map((attempt) => ({
2123
- attemptId: attempt.attemptId,
2124
- requestId: attempt.requestId,
2125
- observedHead: attempt.observedHead,
2126
- status: attempt.status,
2127
- marker: attempt.marker,
2128
- recoverySnapshotId: attempt.recoverySnapshotId
2129
- }))
2130
- };
2131
- }
2132
- 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;
2133
- var init_collector_ledger = __esm({
2134
- "src/collector-ledger.ts"() {
2135
- "use strict";
2136
- init_collector_evidence();
2137
- init_collector_github();
2138
- init_collector_identity();
2139
- init_collector_output();
2140
- COLLECTOR_OBSERVE_TOOL = "ak_collector_observe";
2141
- COLLECTOR_READ_TOOL = "ak_collector_read";
2142
- COLLECTOR_REQUEST_TOOL = "ak_collector_request";
2143
- COLLECTOR_WAIT_TOOL = "ak_collector_wait";
2144
- COLLECTOR_OPEN_WAIT_WINDOW_TOOL = "ak_collector_open_wait_window";
2145
- COLLECTOR_BIND_TARGET_TOOL = "ak_collector_bind_target";
2146
- COLLECTOR_HANDBOOK_WRITE_TOOL = "ak_collector_handbook_write";
2147
- COLLECTOR_OPERATIONAL_TOOLS = [
2148
- COLLECTOR_BIND_TARGET_TOOL,
2149
- COLLECTOR_OBSERVE_TOOL,
2150
- COLLECTOR_READ_TOOL,
2151
- COLLECTOR_REQUEST_TOOL,
2152
- COLLECTOR_OPEN_WAIT_WINDOW_TOOL,
2153
- COLLECTOR_WAIT_TOOL,
2154
- COLLECTOR_HANDBOOK_WRITE_TOOL
2155
- ];
2156
- COLLECTOR_ACTIVATION_ENTRY_TYPE = "ak-collector-activation";
2157
- COLLECTOR_SNAPSHOT_ENTRY_TYPE = "ak-collector-snapshot";
2158
- COLLECTOR_REQUEST_ENTRY_TYPE = "ak-collector-request";
2159
- COLLECTOR_WAIT_ENTRY_TYPE = "ak-collector-wait";
2160
- }
2161
- });
2162
-
2163
209
  // src/open-tool-schema.ts
2164
210
  import { Type } from "typebox";
2165
211
  function described(name, schema) {
@@ -2497,27 +543,27 @@ function causeMessage(cause) {
2497
543
  return String(cause);
2498
544
  }
2499
545
  }
2500
- function fail2(cause) {
546
+ function fail(cause) {
2501
547
  throw new FixerPacketValidationError(cause);
2502
548
  }
2503
549
  function parseFailure(value) {
2504
- if (!Array.isArray(value)) fail2(new Error("Fixer prerequisites must be a JSON array"));
550
+ if (!Array.isArray(value)) fail(new Error("Fixer prerequisites must be a JSON array"));
2505
551
  for (const entry of value) {
2506
552
  if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
2507
- fail2(new Error("Fixer prerequisite entry must be an object with id and requirement fields"));
553
+ fail(new Error("Fixer prerequisite entry must be an object with id and requirement fields"));
2508
554
  }
2509
555
  const keys = Object.keys(entry);
2510
556
  if (keys.length !== 2 || !keys.includes("id") || !keys.includes("requirement")) {
2511
- fail2(new Error("Fixer prerequisite entry fields must be exactly id and requirement"));
557
+ fail(new Error("Fixer prerequisite entry fields must be exactly id and requirement"));
2512
558
  }
2513
559
  if (typeof entry.id !== "string" || !new RegExp(FIXER_PREREQUISITE_ID_PATTERN).test(entry.id)) {
2514
- fail2(new Error(`Fixer prerequisite id violates pattern ${FIXER_PREREQUISITE_ID_PATTERN}`));
560
+ fail(new Error(`Fixer prerequisite id violates pattern ${FIXER_PREREQUISITE_ID_PATTERN}`));
2515
561
  }
2516
562
  if (typeof entry.requirement !== "string" || !/\S/.test(entry.requirement)) {
2517
- fail2(new Error("Fixer prerequisite requirement must be nonblank"));
563
+ fail(new Error("Fixer prerequisite requirement must be nonblank"));
2518
564
  }
2519
565
  }
2520
- fail2(new Error("Fixer prerequisites violate the attachment schema"));
566
+ fail(new Error("Fixer prerequisites violate the attachment schema"));
2521
567
  }
2522
568
  function validateFixerPrerequisites(value) {
2523
569
  if (!Value.Check(fixerPrerequisitesSchema, value)) parseFailure(value);
@@ -2525,7 +571,7 @@ function validateFixerPrerequisites(value) {
2525
571
  const ids = /* @__PURE__ */ new Set();
2526
572
  const prerequisites = entries.map((entry) => {
2527
573
  if (ids.has(entry.id)) {
2528
- fail2(new Error(`Fixer prerequisites contain duplicate id: ${entry.id}`));
574
+ fail(new Error(`Fixer prerequisites contain duplicate id: ${entry.id}`));
2529
575
  }
2530
576
  ids.add(entry.id);
2531
577
  return Object.freeze({ id: entry.id, requirement: entry.requirement });
@@ -2537,7 +583,7 @@ function parseFixerPrerequisites(source) {
2537
583
  try {
2538
584
  decoded = JSON.parse(source);
2539
585
  } catch (error) {
2540
- fail2(error);
586
+ fail(error);
2541
587
  }
2542
588
  return validateFixerPrerequisites(decoded);
2543
589
  }
@@ -2716,7 +762,7 @@ var init_exact_utf8 = __esm({
2716
762
 
2717
763
  // src/merger-contracts.ts
2718
764
  import { Type as Type9 } from "typebox";
2719
- function fail3(message = "Merger input violates its exact contract") {
765
+ function fail2(message = "Merger input violates its exact contract") {
2720
766
  throw new MergerInputContractError(message);
2721
767
  }
2722
768
  function deepFreeze(value) {
@@ -2727,18 +773,18 @@ function deepFreeze(value) {
2727
773
  return value;
2728
774
  }
2729
775
  function readMaterial(value, label) {
2730
- if (!record2(value) || typeof value.bytesBase64 !== "string") fail3(`Merger ${label} material is malformed`);
776
+ if (!record(value) || typeof value.bytesBase64 !== "string") fail2(`Merger ${label} material is malformed`);
2731
777
  exactUtf8(Buffer.from(value.bytesBase64, "base64"), `Merger ${label} material`);
2732
778
  return { bytesBase64: value.bytesBase64, sha256: typeof value.sha256 === "string" ? value.sha256 : "" };
2733
779
  }
2734
780
  function validateMergerInput(value) {
2735
- if (!record2(value) || blank(value.attemptId)) fail3("Merger input requires a non-empty attemptId for accounting");
2736
- if (!record2(value.materials)) fail3("Merger materials are missing");
781
+ if (!record(value) || blank(value.attemptId)) fail2("Merger input requires a non-empty attemptId for accounting");
782
+ if (!record(value.materials)) fail2("Merger materials are missing");
2737
783
  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") };
2738
- 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) : [];
784
+ 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) : [];
2739
785
  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 }));
2740
786
  }
2741
- var materialSchema, checkSchema, mergerInputSchema, MERGER_STATUS_DESCRIPTION, mergerOutputVariants, mergerOutputSchema, MERGER_OUTPUT_TOOL_NAME, record2, blank, MergerInputContractError, asString, asStringArray;
787
+ var materialSchema, checkSchema, mergerInputSchema, MERGER_STATUS_DESCRIPTION, mergerOutputVariants, mergerOutputSchema, MERGER_OUTPUT_TOOL_NAME, record, blank, MergerInputContractError, asString, asStringArray;
2742
788
  var init_merger_contracts = __esm({
2743
789
  "src/merger-contracts.ts"() {
2744
790
  "use strict";
@@ -2763,7 +809,7 @@ var init_merger_contracts = __esm({
2763
809
  ]);
2764
810
  mergerOutputSchema = withTerminatingOutputDeclarations(openToolObjectFromUnion(mergerOutputVariants));
2765
811
  MERGER_OUTPUT_TOOL_NAME = "ak_merger_output";
2766
- record2 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
812
+ record = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
2767
813
  blank = (v) => typeof v !== "string" || v.trim().length === 0;
2768
814
  MergerInputContractError = class extends Error {
2769
815
  constructor(message = "Merger input violates its exact contract") {
@@ -2856,7 +902,7 @@ var init_auditor_output = __esm({
2856
902
  });
2857
903
 
2858
904
  // src/ticket-provenance-contracts.ts
2859
- function isRecord2(value) {
905
+ function isRecord(value) {
2860
906
  return typeof value === "object" && value !== null && !Array.isArray(value);
2861
907
  }
2862
908
  function positiveInteger(value) {
@@ -2868,7 +914,7 @@ function positiveInteger(value) {
2868
914
  return void 0;
2869
915
  }
2870
916
  function projectBound(value) {
2871
- if (!isRecord2(value)) return void 0;
917
+ if (!isRecord(value)) return void 0;
2872
918
  const id = typeof value.id === "string" && value.id !== "" ? value.id : void 0;
2873
919
  const line2 = positiveInteger(value.line);
2874
920
  if (id === void 0 && line2 === void 0) return void 0;
@@ -2879,13 +925,13 @@ function projectTicketProvenanceSessions(value) {
2879
925
  if (value.length === 0) return [];
2880
926
  const sessions = [];
2881
927
  for (const raw of value) {
2882
- if (!isRecord2(raw)) return void 0;
928
+ if (!isRecord(raw)) return void 0;
2883
929
  const path = raw.path;
2884
930
  if (typeof path !== "string" || path.trim() === "") return void 0;
2885
931
  if (!Array.isArray(raw.ranges) || raw.ranges.length === 0) return void 0;
2886
932
  const ranges = [];
2887
933
  for (const rawRange of raw.ranges) {
2888
- if (!isRecord2(rawRange)) return void 0;
934
+ if (!isRecord(rawRange)) return void 0;
2889
935
  const from = projectBound(rawRange.from);
2890
936
  const to = projectBound(rawRange.to);
2891
937
  if (from === void 0 || to === void 0) return void 0;
@@ -2914,7 +960,7 @@ __export(run_ticket_number_exports, {
2914
960
  readRunTicketNumber: () => readRunTicketNumber,
2915
961
  requireSafePositiveTicketNumber: () => requireSafePositiveTicketNumber
2916
962
  });
2917
- import { readFile as readFile2 } from "node:fs/promises";
963
+ import { readFile } from "node:fs/promises";
2918
964
  import { join as join2 } from "node:path";
2919
965
  function isEnoent(error) {
2920
966
  return error instanceof Error && "code" in error && error.code === "ENOENT";
@@ -2944,7 +990,7 @@ function ticketFromRecord(record4) {
2944
990
  }
2945
991
  async function readJsonObject(path) {
2946
992
  try {
2947
- const raw = JSON.parse(await readFile2(path, "utf8"));
993
+ const raw = JSON.parse(await readFile(path, "utf8"));
2948
994
  if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
2949
995
  return void 0;
2950
996
  }
@@ -3290,7 +1336,6 @@ var init_packaged_role_registry = __esm({
3290
1336
  "src/packaged-role-registry.ts"() {
3291
1337
  "use strict";
3292
1338
  init_collector_output();
3293
- init_collector_ledger();
3294
1339
  init_gatekeeper_output();
3295
1340
  init_navigator_output();
3296
1341
  init_judge_output();
@@ -3486,23 +1531,18 @@ var init_packaged_role_registry = __esm({
3486
1531
  ]
3487
1532
  },
3488
1533
  // ak-collector-repo is GitHub owner/repo identity, not a local material path (#438).
1534
+ // #1088: seat + request-manifest kept; code no longer collects — LLM uses host CLI.
3489
1535
  {
3490
1536
  role: "collector",
3491
1537
  inCallAutoResume: false,
3492
1538
  presentSettled: "always",
3493
1539
  summonResume: false,
3494
1540
  admission: "collect-target",
3495
- /** Public no_receipt projects a durable bind-target rejection. */
3496
- projectTargetBindRejection: true,
3497
1541
  sameParent: "none",
3498
1542
  phases: [null],
3499
1543
  bareCommand: false,
3500
1544
  outputTool: COLLECTOR_OUTPUT_TOOL,
3501
- settlement: "residual",
3502
- /** #633: a prior wait-tool residual must not mask this attempt. */
3503
- residualScan: "current-attempt",
3504
- residualTool: COLLECTOR_WAIT_TOOL,
3505
- runnerFailure: "collector-known-first",
1545
+ settlement: "sealed",
3506
1546
  artifactFace: {
3507
1547
  evidenceRole: true,
3508
1548
  leaves: [
@@ -3517,11 +1557,14 @@ var init_packaged_role_registry = __esm({
3517
1557
  activationFlags: [
3518
1558
  { field: "repo", from: "repository.display", flag: "ak-collector-repo" },
3519
1559
  { field: "pr", from: "prNumber", text: true, flag: "ak-collector-pr" },
3520
- { field: "requestManifestPath", flag: "ak-collector-request-manifest" },
3521
- { field: "waitMs", from: "waitWindowMs", text: true, flag: "ak-collector-wait-ms" }
1560
+ { field: "requestManifestPath", flag: "ak-collector-request-manifest" }
3522
1561
  ],
3523
1562
  activationStage: "load-and-install",
3524
- sessionMaterials: ["CLAUDE.md", "souls/collector.md"]
1563
+ sessionMaterials: [
1564
+ "CLAUDE.md",
1565
+ "souls/collector.md",
1566
+ "resources/collector-bot-handbook.md"
1567
+ ]
3525
1568
  },
3526
1569
  {
3527
1570
  role: "doctor",
@@ -4340,15 +2383,15 @@ var init_sitian_appender = __esm({
4340
2383
 
4341
2384
  // src/sitian-reader.ts
4342
2385
  import { existsSync } from "node:fs";
4343
- import { readFile as readFile3 } from "node:fs/promises";
4344
- function isRecord3(value) {
2386
+ import { readFile as readFile2 } from "node:fs/promises";
2387
+ function isRecord2(value) {
4345
2388
  return typeof value === "object" && value !== null && !Array.isArray(value);
4346
2389
  }
4347
2390
  async function readSitianRecords(recordFile) {
4348
2391
  if (!existsSync(recordFile)) {
4349
2392
  return { records: [], diagnostics: [] };
4350
2393
  }
4351
- const text = await readFile3(recordFile, "utf8");
2394
+ const text = await readFile2(recordFile, "utf8");
4352
2395
  const lines = text.split("\n");
4353
2396
  const records = [];
4354
2397
  const diagnostics = [];
@@ -4357,7 +2400,7 @@ async function readSitianRecords(recordFile) {
4357
2400
  if (!line2.trim()) continue;
4358
2401
  try {
4359
2402
  const parsed = JSON.parse(line2);
4360
- if (isRecord3(parsed)) {
2403
+ if (isRecord2(parsed)) {
4361
2404
  records.push(parsed);
4362
2405
  } else {
4363
2406
  const typeDesc = parsed === null ? "null" : Array.isArray(parsed) ? "array" : typeof parsed;
@@ -4490,7 +2533,7 @@ __export(run_terminal_artifacts_exports, {
4490
2533
  readRunTerminalArtifact: () => readRunTerminalArtifact,
4491
2534
  runIdFromRunDirectory: () => runIdFromRunDirectory
4492
2535
  });
4493
- import { readdir as readdir2, readFile as readFile4 } from "node:fs/promises";
2536
+ import { readdir as readdir2, readFile as readFile3 } from "node:fs/promises";
4494
2537
  import { basename as basename3, dirname as dirname4, join as join6 } from "node:path";
4495
2538
  function isMissingPathError2(error) {
4496
2539
  return error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR");
@@ -4498,14 +2541,14 @@ function isMissingPathError2(error) {
4498
2541
  function errorText2(error) {
4499
2542
  return error instanceof Error ? error.message : String(error);
4500
2543
  }
4501
- function isRecord4(value) {
2544
+ function isRecord3(value) {
4502
2545
  return typeof value === "object" && value !== null && !Array.isArray(value);
4503
2546
  }
4504
2547
  function readUsableTerminalArtifactBody(body) {
4505
2548
  if (body === null) {
4506
2549
  return { ok: false, reason: "terminal artifact JSON value is null" };
4507
2550
  }
4508
- if (!isRecord4(body)) {
2551
+ if (!isRecord3(body)) {
4509
2552
  return {
4510
2553
  ok: false,
4511
2554
  reason: `terminal artifact JSON value is not a typed object (${Array.isArray(body) ? "array" : typeof body})`
@@ -4522,7 +2565,7 @@ function readUsableTerminalArtifactBody(body) {
4522
2565
  async function readTerminalArtifactAtPath(path, file) {
4523
2566
  let raw;
4524
2567
  try {
4525
- raw = await readFile4(path, "utf8");
2568
+ raw = await readFile3(path, "utf8");
4526
2569
  } catch (error) {
4527
2570
  if (isMissingPathError2(error)) return void 0;
4528
2571
  return {
@@ -4677,7 +2720,7 @@ var init_cli_errors = __esm({
4677
2720
  });
4678
2721
 
4679
2722
  // src/typed-provider-http.ts
4680
- import { readFile as readFile5, unlink, writeFile as writeFile2 } from "node:fs/promises";
2723
+ import { readFile as readFile4, unlink, writeFile as writeFile2 } from "node:fs/promises";
4681
2724
  import { join as join7 } from "node:path";
4682
2725
  function typedProviderHttpPath(runDirectory) {
4683
2726
  return join7(runDirectory, TYPED_HTTP_FILE);
@@ -4711,31 +2754,109 @@ async function recordTypedProviderHttpStatus(runDirectory, observation) {
4711
2754
  async function readLatestTypedProviderHttpObservation(runDirectory) {
4712
2755
  let text;
4713
2756
  try {
4714
- text = await readFile5(typedProviderHttpPath(runDirectory), "utf8");
2757
+ text = await readFile4(typedProviderHttpPath(runDirectory), "utf8");
2758
+ } catch (error) {
2759
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
2760
+ return void 0;
2761
+ }
2762
+ throw error;
2763
+ }
2764
+ const raw = JSON.parse(text);
2765
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
2766
+ throw new Error("typed provider HTTP observation must be a JSON object");
2767
+ }
2768
+ const record4 = raw;
2769
+ if (typeof record4.httpStatus !== "number") {
2770
+ throw new Error("typed provider HTTP observation missing numeric httpStatus");
2771
+ }
2772
+ if (typeof record4.provider !== "string" || record4.provider.trim() === "") {
2773
+ throw new Error("typed provider HTTP observation missing non-empty provider");
2774
+ }
2775
+ return { httpStatus: record4.httpStatus, provider: record4.provider };
2776
+ }
2777
+ var TYPED_HTTP_FILE;
2778
+ var init_typed_provider_http = __esm({
2779
+ "src/typed-provider-http.ts"() {
2780
+ "use strict";
2781
+ TYPED_HTTP_FILE = "typed-provider-http.json";
2782
+ }
2783
+ });
2784
+
2785
+ // src/collector-config.ts
2786
+ import { createHash } from "node:crypto";
2787
+ import { readFile as readFile5 } from "node:fs/promises";
2788
+ function fail3(message, cause) {
2789
+ throw new Error(message, cause === void 0 ? void 0 : { cause });
2790
+ }
2791
+ function conservativeAscii(input) {
2792
+ for (let i = 0; i < input.length; i += 1) {
2793
+ const code = input.charCodeAt(i);
2794
+ if (code <= 31 || code === 127 || code > 127) return false;
2795
+ }
2796
+ return true;
2797
+ }
2798
+ function parseCollectorRepository(raw) {
2799
+ if (typeof raw !== "string" || raw.trim() !== raw || raw.length === 0) fail3("Collector repository must be a string owner/repo");
2800
+ if (!conservativeAscii(raw) || raw.includes("://") || /[?#@%\\ ]/.test(raw)) fail3("Collector repository rejects URL syntax and non-identity bytes");
2801
+ const parts = raw.split("/");
2802
+ if (parts.length !== 2) fail3("Collector repository must contain exactly one '/' separating owner and repo");
2803
+ const [ownerDisplay, repoDisplay] = parts;
2804
+ if (!COLLECTOR_OWNER_PATTERN.test(ownerDisplay) || !COLLECTOR_REPO_PATTERN.test(repoDisplay)) fail3("Collector repository does not match the conservative owner/repo grammar");
2805
+ const owner = ownerDisplay.toLowerCase();
2806
+ const repo = repoDisplay.toLowerCase();
2807
+ return { display: raw, canonical: `${owner}/${repo}`, owner, repo };
2808
+ }
2809
+ function parseCollectorPrNumber(raw) {
2810
+ if (typeof raw === "string" && !/^[1-9][0-9]*$/.test(raw)) fail3("Collector pull request number must be a positive safe integer string");
2811
+ if (typeof raw !== "string" && typeof raw !== "number") fail3("Collector pull request number is required");
2812
+ const value = Number(raw);
2813
+ if (!Number.isSafeInteger(value) || value < 1) fail3("Collector pull request number must be a positive safe integer");
2814
+ return value;
2815
+ }
2816
+ function record2(value) {
2817
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2818
+ }
2819
+ function canonicalManifest(requests) {
2820
+ return `${JSON.stringify({ requests: requests.map((request) => ({ id: request.id, body: request.requestBody })) })}
2821
+ `;
2822
+ }
2823
+ function emptyCollectorManifest() {
2824
+ const canonicalJson2 = canonicalManifest([]);
2825
+ return { requests: [], canonicalJson: canonicalJson2, digest: createHash("sha256").update(canonicalJson2).digest("hex") };
2826
+ }
2827
+ async function loadCollectorManifest(path) {
2828
+ let bytes;
2829
+ try {
2830
+ bytes = await readFile5(path);
4715
2831
  } catch (error) {
4716
- if (error instanceof Error && "code" in error && error.code === "ENOENT") {
4717
- return void 0;
4718
- }
4719
- throw error;
4720
- }
4721
- const raw = JSON.parse(text);
4722
- if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
4723
- throw new Error("typed provider HTTP observation must be a JSON object");
2832
+ fail3(`Collector request manifest is unreadable at ${path}`, error);
4724
2833
  }
4725
- const record4 = raw;
4726
- if (typeof record4.httpStatus !== "number") {
4727
- throw new Error("typed provider HTTP observation missing numeric httpStatus");
2834
+ let parsed;
2835
+ try {
2836
+ parsed = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
2837
+ } catch (error) {
2838
+ fail3("Collector request manifest must be UTF-8 JSON", error);
4728
2839
  }
4729
- if (typeof record4.provider !== "string" || record4.provider.trim() === "") {
4730
- throw new Error("typed provider HTTP observation missing non-empty provider");
2840
+ if (!record2(parsed)) fail3("Collector request manifest must be an object");
2841
+ const rawRequests = parsed.requests ?? [];
2842
+ if (!Array.isArray(rawRequests)) fail3("Collector request manifest requests must be an array");
2843
+ const requests = [];
2844
+ const ids = /* @__PURE__ */ new Set();
2845
+ for (const [index, item] of rawRequests.entries()) {
2846
+ if (!record2(item) || typeof item.id !== "string" || item.id.length === 0 || typeof item.body !== "string" || item.body.trim() === "") fail3(`Collector request manifest requests[${index}] is invalid`);
2847
+ if (ids.has(item.id)) fail3(`Collector request manifest has duplicate request id "${item.id}"`);
2848
+ ids.add(item.id);
2849
+ requests.push({ id: item.id, requestBody: item.body });
4731
2850
  }
4732
- return { httpStatus: record4.httpStatus, provider: record4.provider };
2851
+ const canonicalJson2 = canonicalManifest(requests);
2852
+ return { requests, canonicalJson: canonicalJson2, digest: createHash("sha256").update(canonicalJson2).digest("hex"), sourcePath: path };
4733
2853
  }
4734
- var TYPED_HTTP_FILE;
4735
- var init_typed_provider_http = __esm({
4736
- "src/typed-provider-http.ts"() {
2854
+ var COLLECTOR_OWNER_PATTERN, COLLECTOR_REPO_PATTERN;
2855
+ var init_collector_config = __esm({
2856
+ "src/collector-config.ts"() {
4737
2857
  "use strict";
4738
- TYPED_HTTP_FILE = "typed-provider-http.json";
2858
+ COLLECTOR_OWNER_PATTERN = /^[A-Za-z0-9](?:[A-Za-z0-9-]{0,37}[A-Za-z0-9])?$/;
2859
+ COLLECTOR_REPO_PATTERN = /^[A-Za-z0-9](?:[A-Za-z0-9._-]{0,98}[A-Za-z0-9])?$/;
4739
2860
  }
4740
2861
  });
4741
2862
 
@@ -4790,6 +2911,92 @@ var init_auditor_dossier_tool = __esm({
4790
2911
  }
4791
2912
  });
4792
2913
 
2914
+ // src/readable-gate-item.ts
2915
+ var readable_gate_item_exports = {};
2916
+ __export(readable_gate_item_exports, {
2917
+ joinReadableGateItems: () => joinReadableGateItems,
2918
+ readableGateItem: () => readableGateItem
2919
+ });
2920
+ function readableGateItem(value) {
2921
+ return typeof value === "string" ? value : JSON.stringify(value);
2922
+ }
2923
+ function joinReadableGateItems(items, separator = "; ") {
2924
+ return items.map(readableGateItem).join(separator);
2925
+ }
2926
+ var init_readable_gate_item = __esm({
2927
+ "src/readable-gate-item.ts"() {
2928
+ "use strict";
2929
+ }
2930
+ });
2931
+
2932
+ // src/submission-errors.ts
2933
+ function serializeReceipt(receipt) {
2934
+ return readableGateItem(receipt);
2935
+ }
2936
+ function gatekeeperNonPassMessage(result) {
2937
+ if (result.status === "continue") {
2938
+ return serializeReceipt(result.receipt);
2939
+ }
2940
+ if (result.status === "transport_failure") {
2941
+ const head = `\u95E8\u4E0B\u7701 ${result.status}\uFF08${result.stage}\uFF09\uFF1A${result.reason}`;
2942
+ return result.submission === void 0 ? head : `${head}
2943
+ ${serializeReceipt(result.submission)}`;
2944
+ }
2945
+ return `\u95E8\u4E0B\u7701 ${result.status}\uFF08${result.stage}\uFF09\uFF1A${result.reason}`;
2946
+ }
2947
+ function unreadableDiscriminatorNotice(field, received) {
2948
+ if (received === void 0) return `\u8BFB\u4E0D\u51FA ${field}`;
2949
+ return `\u8BFB\u4E0D\u51FA ${field}\uFF1A${readableGateItem(received)}`;
2950
+ }
2951
+ function receivedDiscriminator(receipt, field) {
2952
+ if (receipt === null || typeof receipt !== "object" || Array.isArray(receipt)) return void 0;
2953
+ if (!Object.hasOwn(receipt, field)) return void 0;
2954
+ return receipt[field];
2955
+ }
2956
+ var GatekeeperDecisionError, WorkerCommitReminderError, WorkerPrefixReminderError, WorkerUnfinishedReasonReminderError, ParentQueueReaskError;
2957
+ var init_submission_errors = __esm({
2958
+ "src/submission-errors.ts"() {
2959
+ "use strict";
2960
+ init_readable_gate_item();
2961
+ GatekeeperDecisionError = class extends Error {
2962
+ result;
2963
+ constructor(result, message) {
2964
+ super(message ?? gatekeeperNonPassMessage(result));
2965
+ this.name = "GatekeeperDecisionError";
2966
+ this.result = result;
2967
+ }
2968
+ };
2969
+ WorkerCommitReminderError = class extends Error {
2970
+ code = "worker_commit_reminder";
2971
+ constructor() {
2972
+ super("\u672A\u89C2\u5BDF\u5230 commit");
2973
+ this.name = "WorkerCommitReminderError";
2974
+ }
2975
+ };
2976
+ WorkerPrefixReminderError = class extends Error {
2977
+ code = "worker_prefix_reminder";
2978
+ constructor() {
2979
+ super("\u89C2\u5BDF\u5230\u7F3A\u524D\u7F00 commit");
2980
+ this.name = "WorkerPrefixReminderError";
2981
+ }
2982
+ };
2983
+ WorkerUnfinishedReasonReminderError = class extends Error {
2984
+ code = "worker_unfinished_reason_reminder";
2985
+ constructor() {
2986
+ super("\u672C\u6B21 unfinished \u56DE\u6267\u672A\u542B reason\uFF1B\u672C\u63A5\u7F1D\u7F3A\u7531\u81F3\u591A\u6253\u56DE\u4E24\u6B21\u3002");
2987
+ this.name = "WorkerUnfinishedReasonReminderError";
2988
+ }
2989
+ };
2990
+ ParentQueueReaskError = class extends Error {
2991
+ code = "parent_queue_reask";
2992
+ constructor(message) {
2993
+ super(message);
2994
+ this.name = "ParentQueueReaskError";
2995
+ }
2996
+ };
2997
+ }
2998
+ });
2999
+
4793
3000
  // src/gatekeeper-role.ts
4794
3001
  function gateSeatLabel(stage) {
4795
3002
  return packagedGateStageLabel(stage) ?? stage;
@@ -5103,10 +3310,10 @@ __export(session_assistant_usage_exports, {
5103
3310
  });
5104
3311
  import { join as join9 } from "node:path";
5105
3312
  async function readAssistantUsageFromSessionFile(sessionFile) {
5106
- const { readFile: readFile26 } = await import("node:fs/promises");
3313
+ const { readFile: readFile25 } = await import("node:fs/promises");
5107
3314
  let text;
5108
3315
  try {
5109
- text = await readFile26(sessionFile, "utf8");
3316
+ text = await readFile25(sessionFile, "utf8");
5110
3317
  } catch (error) {
5111
3318
  if (error?.code === "ENOENT") return void 0;
5112
3319
  throw error;
@@ -5399,7 +3606,7 @@ __export(role_turn_host_exports, {
5399
3606
  createPiRoleTurnHost: () => createPiRoleTurnHost,
5400
3607
  resolveInternalRoleEntrypoint: () => resolveInternalRoleEntrypoint
5401
3608
  });
5402
- import { execFile, spawn as spawn3 } from "node:child_process";
3609
+ import { execFile, spawn as spawn2 } from "node:child_process";
5403
3610
  import { constants } from "node:fs";
5404
3611
  import { access, appendFile, readFile as readFile6, realpath } from "node:fs/promises";
5405
3612
  import { delimiter, dirname as dirname6, isAbsolute as isAbsolute3, join as join12, resolve as resolve4 } from "node:path";
@@ -5509,7 +3716,7 @@ function createDefaultPiSpawnRunner(options) {
5509
3716
  const command = spawnOptions.env.PI_BINARY ?? "pi";
5510
3717
  const piIdentity = await selectedPiIdentity(command, spawnOptions.cwd, spawnOptions.env);
5511
3718
  return await new Promise((resolveResult, reject) => {
5512
- const child = spawn3(piIdentity.executable, [...args], {
3719
+ const child = spawn2(piIdentity.executable, [...args], {
5513
3720
  cwd: spawnOptions.cwd,
5514
3721
  env: spawnOptions.env,
5515
3722
  stdio: ["pipe", "ignore", "pipe"]
@@ -5805,9 +4012,9 @@ var init_host_descriptions = __esm({
5805
4012
  });
5806
4013
 
5807
4014
  // src/sha256.ts
5808
- import { createHash as createHash4 } from "node:crypto";
4015
+ import { createHash as createHash2 } from "node:crypto";
5809
4016
  function sha256Hex(bytes) {
5810
- return createHash4("sha256").update(bytes).digest("hex");
4017
+ return createHash2("sha256").update(bytes).digest("hex");
5811
4018
  }
5812
4019
  var init_sha256 = __esm({
5813
4020
  "src/sha256.ts"() {
@@ -5815,6 +4022,43 @@ var init_sha256 = __esm({
5815
4022
  }
5816
4023
  });
5817
4024
 
4025
+ // src/submission-correctable-error.ts
4026
+ function isCorrectableSubmissionError(error) {
4027
+ return error instanceof CorrectableSubmissionError;
4028
+ }
4029
+ function isCorrectableExecuteError(error) {
4030
+ return isCorrectableSubmissionError(error) || error instanceof GatekeeperDecisionError || error instanceof ParentQueueReaskError || error instanceof WorkerCommitReminderError || error instanceof WorkerPrefixReminderError || error instanceof WorkerUnfinishedReasonReminderError;
4031
+ }
4032
+ function projectCorrectableExecuteRejection(error) {
4033
+ const diagnostic = error instanceof Error ? error.message : String(error);
4034
+ if (error instanceof GatekeeperDecisionError) {
4035
+ return { diagnostic, details: { ...error.result } };
4036
+ }
4037
+ if (error instanceof WorkerCommitReminderError || error instanceof WorkerPrefixReminderError || error instanceof WorkerUnfinishedReasonReminderError) {
4038
+ return { diagnostic, details: { code: error.code } };
4039
+ }
4040
+ if (typeof error.code === "string") {
4041
+ return { diagnostic, details: { code: error.code } };
4042
+ }
4043
+ return {
4044
+ diagnostic,
4045
+ details: {
4046
+ code: error instanceof Error && error.name ? error.name : "correctable-submission-error"
4047
+ }
4048
+ };
4049
+ }
4050
+ var correctableSubmissionErrorBrand, CorrectableSubmissionError;
4051
+ var init_submission_correctable_error = __esm({
4052
+ "src/submission-correctable-error.ts"() {
4053
+ "use strict";
4054
+ init_submission_errors();
4055
+ correctableSubmissionErrorBrand = /* @__PURE__ */ Symbol("ak-roles.correctable-submission-error");
4056
+ CorrectableSubmissionError = class extends Error {
4057
+ [correctableSubmissionErrorBrand] = true;
4058
+ };
4059
+ }
4060
+ });
4061
+
5818
4062
  // src/package-contracts/terminating-tools.ts
5819
4063
  function isTerminatingToolName(name) {
5820
4064
  return TERMINATING_TOOL_NAMES.includes(name);
@@ -6020,11 +4264,6 @@ var init_doctor_evidence = __esm({
6020
4264
  });
6021
4265
 
6022
4266
  // src/public-cli/github-remote.ts
6023
- function ownerFromGitHubRemoteUrl(remoteUrl) {
6024
- const ownerRepo = ownerRepoFromGitHubRemoteUrl(remoteUrl);
6025
- if (ownerRepo === void 0) return void 0;
6026
- return ownerRepo.split("/")[0].toLowerCase();
6027
- }
6028
4267
  function ownerRepoFromGitHubRemoteUrl(remoteUrl) {
6029
4268
  const trimmed = remoteUrl.trim();
6030
4269
  const scp = /^git@github\.com:([^/\s]+)\/([^/\s]+?)(?:\.git)?$/i.exec(trimmed);
@@ -6058,143 +4297,6 @@ var init_github_remote = __esm({
6058
4297
  }
6059
4298
  });
6060
4299
 
6061
- // src/collector-target.ts
6062
- import { execFileSync as execFileSync2 } from "node:child_process";
6063
- function ambiguousTarget(detail, cause) {
6064
- throw new CliUsageError(
6065
- `collector target is ambiguous: ${detail}; pass an explicit --pr`,
6066
- cause === void 0 ? void 0 : { cause }
6067
- );
6068
- }
6069
- function gitFailure(detail, cause) {
6070
- throw new Error(`collector git failed: ${detail}`, {
6071
- cause: cause instanceof Error ? cause : new Error(String(cause))
6072
- });
6073
- }
6074
- function gitText(projectRoot, args) {
6075
- return execFileSync2("git", [...args], {
6076
- cwd: projectRoot,
6077
- encoding: "utf8",
6078
- stdio: ["ignore", "pipe", "pipe"]
6079
- }).trim();
6080
- }
6081
- function isGitConfigMissing(error) {
6082
- if (typeof error !== "object" || error === null) return false;
6083
- const status = error.status;
6084
- return status === 1;
6085
- }
6086
- function readCurrentBranch(projectRoot) {
6087
- try {
6088
- return gitText(projectRoot, ["rev-parse", "--abbrev-ref", "HEAD"]);
6089
- } catch (error) {
6090
- gitFailure("cannot read current git branch", error);
6091
- }
6092
- }
6093
- function readHeadSha(projectRoot) {
6094
- try {
6095
- return gitText(projectRoot, ["rev-parse", "HEAD"]);
6096
- } catch (error) {
6097
- gitFailure("cannot read current HEAD", error);
6098
- }
6099
- }
6100
- function headRefFromMerge(merge) {
6101
- const trimmed = merge.trim();
6102
- if (trimmed.length === 0) return void 0;
6103
- if (trimmed.startsWith("refs/heads/")) {
6104
- const ref = trimmed.slice("refs/heads/".length);
6105
- return ref.length > 0 ? ref : void 0;
6106
- }
6107
- if (trimmed.startsWith("refs/")) return void 0;
6108
- return trimmed;
6109
- }
6110
- function readUpstreamHeadBinding(projectRoot, branch) {
6111
- let remote;
6112
- try {
6113
- remote = gitText(projectRoot, ["config", "--get", `branch.${branch}.remote`]);
6114
- } catch (error) {
6115
- if (isGitConfigMissing(error)) remote = void 0;
6116
- else gitFailure(`cannot read branch.${branch}.remote`, error);
6117
- }
6118
- if (remote === void 0 || remote.length === 0) return void 0;
6119
- let merge;
6120
- try {
6121
- merge = gitText(projectRoot, ["config", "--get", `branch.${branch}.merge`]);
6122
- } catch (error) {
6123
- if (isGitConfigMissing(error)) merge = void 0;
6124
- else gitFailure(`cannot read branch.${branch}.merge`, error);
6125
- }
6126
- if (merge === void 0 || merge.length === 0) return void 0;
6127
- const headRef = headRefFromMerge(merge);
6128
- if (headRef === void 0) return void 0;
6129
- let remoteUrl;
6130
- try {
6131
- remoteUrl = gitText(projectRoot, ["remote", "get-url", remote]);
6132
- } catch (error) {
6133
- gitFailure(`cannot read remote URL for ${remote}`, error);
6134
- }
6135
- const headOwner = ownerFromGitHubRemoteUrl(remoteUrl);
6136
- if (headOwner === void 0) return void 0;
6137
- return { headOwner, headRef };
6138
- }
6139
- async function resolveCollectorTarget(input) {
6140
- if (input.explicitPrNumber !== void 0) {
6141
- return { kind: "bound", prNumber: input.explicitPrNumber };
6142
- }
6143
- const branch = readCurrentBranch(input.projectRoot);
6144
- const detached = branch.length === 0 || branch === "HEAD";
6145
- const runner = createGhApiRunner();
6146
- const { owner, repo } = input.repository;
6147
- const numbers = [];
6148
- if (!detached) {
6149
- const headSha = readHeadSha(input.projectRoot);
6150
- const upstream = readUpstreamHeadBinding(input.projectRoot, branch);
6151
- if (upstream !== void 0) {
6152
- numbers.push(
6153
- ...await listPullRequestNumbersByHead(runner, {
6154
- owner,
6155
- repo,
6156
- headOwner: upstream.headOwner,
6157
- headRef: upstream.headRef
6158
- })
6159
- );
6160
- }
6161
- numbers.push(
6162
- ...await listPullRequestNumbersByCommit(runner, {
6163
- owner,
6164
- repo,
6165
- commitSha: headSha
6166
- })
6167
- );
6168
- } else {
6169
- const headSha = readHeadSha(input.projectRoot);
6170
- numbers.push(
6171
- ...await listPullRequestNumbersByCommit(runner, {
6172
- owner,
6173
- repo,
6174
- commitSha: headSha
6175
- })
6176
- );
6177
- }
6178
- const unique = [...new Set(numbers)];
6179
- if (unique.length === 1) {
6180
- return { kind: "bound", prNumber: unique[0] };
6181
- }
6182
- if (unique.length > 1) {
6183
- ambiguousTarget(
6184
- `multiple PRs associated with context: ${unique.join(", ")}`
6185
- );
6186
- }
6187
- return { kind: "unbound" };
6188
- }
6189
- var init_collector_target = __esm({
6190
- "src/collector-target.ts"() {
6191
- "use strict";
6192
- init_collector_github();
6193
- init_cli_errors();
6194
- init_github_remote();
6195
- }
6196
- });
6197
-
6198
4300
  // src/git-object-id.ts
6199
4301
  function isFullGitObjectId(value) {
6200
4302
  return typeof value === "string" && FULL_GIT_OBJECT_ID_RE.test(value);
@@ -6307,7 +4409,7 @@ var init_merger_git_state = __esm({
6307
4409
 
6308
4410
  // src/ledger-session-read.ts
6309
4411
  import { readFile as readFile9 } from "node:fs/promises";
6310
- function isRecord5(value) {
4412
+ function isRecord4(value) {
6311
4413
  return typeof value === "object" && value !== null && !Array.isArray(value);
6312
4414
  }
6313
4415
  async function readLedgerSessionJsonlLines(path) {
@@ -6332,7 +4434,7 @@ async function readLedgerSessionJsonlLines(path) {
6332
4434
  });
6333
4435
  continue;
6334
4436
  }
6335
- if (!isRecord5(row)) {
4437
+ if (!isRecord4(row)) {
6336
4438
  const kind = row === null ? "null" : Array.isArray(row) ? "array" : typeof row;
6337
4439
  out.push({
6338
4440
  line: lineNumber,
@@ -6385,7 +4487,7 @@ function extractSessionModelSequence(rows) {
6385
4487
  if (row.type === "model_change" && typeof row.modelId === "string") {
6386
4488
  push(row.modelId);
6387
4489
  }
6388
- const message = isRecord5(row.message) ? row.message : void 0;
4490
+ const message = isRecord4(row.message) ? row.message : void 0;
6389
4491
  if (message?.role === "assistant" && typeof message.model === "string") {
6390
4492
  push(message.model);
6391
4493
  }
@@ -6401,11 +4503,11 @@ function extractSessionToolIntervals(rows) {
6401
4503
  const openById = /* @__PURE__ */ new Map();
6402
4504
  for (const row of rows) {
6403
4505
  const rowTimestamp = typeof row.timestamp === "string" ? row.timestamp : void 0;
6404
- const message = isRecord5(row.message) ? row.message : void 0;
4506
+ const message = isRecord4(row.message) ? row.message : void 0;
6405
4507
  if (message?.role === "assistant" && Array.isArray(message.content)) {
6406
4508
  const callTimestamp = typeof message.timestamp === "string" && message.timestamp ? message.timestamp : rowTimestamp;
6407
4509
  for (const part of message.content) {
6408
- if (!isRecord5(part) || part.type !== "toolCall") continue;
4510
+ if (!isRecord4(part) || part.type !== "toolCall") continue;
6409
4511
  if (typeof part.id !== "string" || part.id.length === 0) {
6410
4512
  throw new Error("toolCall frame missing string id");
6411
4513
  }
@@ -6418,7 +4520,7 @@ function extractSessionToolIntervals(rows) {
6418
4520
  if (openById.has(part.id)) {
6419
4521
  throw new Error(`duplicate toolCall id ${part.id}`);
6420
4522
  }
6421
- const args = isRecord5(part.arguments) ? part.arguments : void 0;
4523
+ const args = isRecord4(part.arguments) ? part.arguments : void 0;
6422
4524
  const command = part.name === "bash" && args !== void 0 && typeof args.command === "string" ? bashCommandFirstLine(args.command) : void 0;
6423
4525
  const interval = {
6424
4526
  toolCallId: part.id,
@@ -6502,7 +4604,7 @@ var init_ledger_session_read = __esm({
6502
4604
  });
6503
4605
 
6504
4606
  // src/session-dialogue.ts
6505
- function isRecord6(value) {
4607
+ function isRecord5(value) {
6506
4608
  return typeof value === "object" && value !== null && !Array.isArray(value);
6507
4609
  }
6508
4610
  function nativeEventId(row) {
@@ -6512,7 +4614,7 @@ function nativeEventId(row) {
6512
4614
  }
6513
4615
  for (const nestKey of ["message", "payload"]) {
6514
4616
  const nested = row[nestKey];
6515
- if (!isRecord6(nested)) continue;
4617
+ if (!isRecord5(nested)) continue;
6516
4618
  for (const key of ["uuid", "id"]) {
6517
4619
  const value = nested[key];
6518
4620
  if (typeof value === "string" && value !== "") return value;
@@ -6525,19 +4627,19 @@ function textParts(content) {
6525
4627
  if (!Array.isArray(content)) return [];
6526
4628
  const out = [];
6527
4629
  for (const part of content) {
6528
- if (!isRecord6(part) || !SPEAKER_TEXT_PART_TYPES.has(String(part.type))) continue;
4630
+ if (!isRecord5(part) || !SPEAKER_TEXT_PART_TYPES.has(String(part.type))) continue;
6529
4631
  const text = part.text;
6530
4632
  if (typeof text === "string" && text !== "") out.push(text);
6531
4633
  }
6532
4634
  return out;
6533
4635
  }
6534
4636
  function responseItemMessage(row) {
6535
- if (row.type !== "response_item" || !isRecord6(row.payload)) return void 0;
4637
+ if (row.type !== "response_item" || !isRecord5(row.payload)) return void 0;
6536
4638
  if (row.payload.type !== "message") return void 0;
6537
4639
  return row.payload;
6538
4640
  }
6539
4641
  function messageBody(row) {
6540
- if (isRecord6(row.message)) return row.message;
4642
+ if (isRecord5(row.message)) return row.message;
6541
4643
  return responseItemMessage(row);
6542
4644
  }
6543
4645
  function speakerOf(message) {
@@ -6547,7 +4649,7 @@ function speakerOf(message) {
6547
4649
  }
6548
4650
  function codexContentItemKinds(message) {
6549
4651
  const pass = message.internal_chat_message_metadata_passthrough;
6550
- if (!isRecord6(pass) || !Array.isArray(pass.content_item_kinds)) return void 0;
4652
+ if (!isRecord5(pass) || !Array.isArray(pass.content_item_kinds)) return void 0;
6551
4653
  const kinds = [];
6552
4654
  for (const kind of pass.content_item_kinds) {
6553
4655
  if (typeof kind === "string" && kind !== "") kinds.push(kind);
@@ -6576,7 +4678,7 @@ function isFixedNonOwnerEnqueueShape(content) {
6576
4678
  return hasFixedOpenTagPrefix(content, TASK_NOTIFICATION_OPEN_TAG);
6577
4679
  }
6578
4680
  function materializationOriginKind(row) {
6579
- if (!isRecord6(row.origin)) return void 0;
4681
+ if (!isRecord5(row.origin)) return void 0;
6580
4682
  const kind = row.origin.kind;
6581
4683
  return typeof kind === "string" && kind !== "" ? kind : void 0;
6582
4684
  }
@@ -7658,13 +5760,12 @@ var init_option_definitions = __esm({
7658
5760
  canonical: "--pr",
7659
5761
  aliases: [],
7660
5762
  valueMetavar: "number",
7661
- // #676 D1: optional when context uniquely determines the PR; ambiguous → require explicit.
7662
5763
  required: false,
7663
5764
  repeatable: false,
7664
5765
  form: "option",
7665
5766
  description: {
7666
- 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.",
7667
- 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"
5767
+ en: "Positive GitHub pull request number. Optional when the Collector role locates the PR via host CLI from task materials.",
5768
+ 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"
7668
5769
  }
7669
5770
  },
7670
5771
  {
@@ -7691,22 +5792,8 @@ var init_option_definitions = __esm({
7691
5792
  repeatable: false,
7692
5793
  form: "option",
7693
5794
  description: {
7694
- en: "Optional request manifest JSON path ({requests:[{id,body}]}). Role may also decide request bodies from handbook/field activity without this file.",
7695
- 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"
7696
- }
7697
- },
7698
- {
7699
- id: "wait-ms",
7700
- owner: "collector",
7701
- canonical: "--wait-ms",
7702
- aliases: [],
7703
- valueMetavar: "ms",
7704
- required: false,
7705
- repeatable: false,
7706
- form: "option",
7707
- description: {
7708
- en: "Wait-window duration in milliseconds after the work step opens (default 600000 = 10 minutes). Does not require a code change to adjust.",
7709
- 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"
5795
+ 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.",
5796
+ 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"
7710
5797
  }
7711
5798
  }
7712
5799
  ];
@@ -8162,7 +6249,7 @@ var init_option_definitions = __esm({
8162
6249
  });
8163
6250
 
8164
6251
  // src/public-cli/invocation.ts
8165
- import { execFileSync as execFileSync3 } from "node:child_process";
6252
+ import { execFileSync as execFileSync2 } from "node:child_process";
8166
6253
  import { existsSync as existsSync3 } from "node:fs";
8167
6254
  import {
8168
6255
  lstat as lstat3,
@@ -8562,17 +6649,6 @@ function assignPublicSeatOption(owner, taken, fields) {
8562
6649
  case "request-manifest":
8563
6650
  fields.requestManifestPath = requireOptionPath(taken.def.canonical, value);
8564
6651
  return;
8565
- case "wait-ms": {
8566
- if (value === void 0 || !/^[1-9]\d*$/.test(value.trim())) {
8567
- throw new CliUsageError("--wait-ms requires a positive safe-integer millisecond value");
8568
- }
8569
- const parsed = Number(value.trim());
8570
- if (!Number.isSafeInteger(parsed) || parsed < 1) {
8571
- throw new CliUsageError("--wait-ms requires a positive safe-integer millisecond value");
8572
- }
8573
- fields.waitWindowMs = parsed;
8574
- return;
8575
- }
8576
6652
  case "issue": {
8577
6653
  if (value === void 0 || value.trim() === "") {
8578
6654
  throw new CliUsageError("doctor --issue requires a positive integer");
@@ -8669,7 +6745,6 @@ function parsePublicSeatArgv(owner, args) {
8669
6745
  ...fields.prNumber === void 0 ? {} : { prNumber: fields.prNumber },
8670
6746
  ...fields.repo === void 0 ? {} : { repo: fields.repo },
8671
6747
  ...fields.requestManifestPath === void 0 ? {} : { requestManifestPath: fields.requestManifestPath },
8672
- ...fields.waitWindowMs === void 0 ? {} : { waitWindowMs: fields.waitWindowMs },
8673
6748
  ...fields.issueNumber === void 0 ? {} : { issueNumber: fields.issueNumber },
8674
6749
  ...fields.runs === void 0 ? {} : { runs: fields.runs },
8675
6750
  ...fields.sourceRun === void 0 ? {} : { sourceRun: fields.sourceRun },
@@ -9029,23 +7104,16 @@ async function admitPublicRole(role, parsed, env, override) {
9029
7104
  attachmentPaths,
9030
7105
  ...project,
9031
7106
  placedFields: async (placed) => {
9032
- const target = await resolveCollectorTarget({
9033
- projectRoot,
9034
- repository,
9035
- ...explicitPrNumber === void 0 ? {} : { explicitPrNumber }
9036
- });
9037
- const prNumber = target.kind === "bound" ? target.prNumber : void 0;
9038
7107
  let requestManifestPath;
9039
7108
  if (manifestCanonicalJson !== void 0) {
9040
7109
  requestManifestPath = join15(placed.runDirectory, "request-manifest.json");
9041
7110
  await writeFile3(requestManifestPath, manifestCanonicalJson, "utf8");
9042
7111
  }
9043
7112
  return {
9044
- ...prNumber === void 0 ? {} : { prNumber },
7113
+ ...explicitPrNumber === void 0 ? {} : { prNumber: explicitPrNumber },
9045
7114
  repository: repository.canonical,
9046
7115
  repositoryDisplay: repository.display,
9047
7116
  ...requestManifestPath === void 0 ? {} : { requestManifestPath },
9048
- ...parsed.waitWindowMs === void 0 ? {} : { waitWindowMs: parsed.waitWindowMs },
9049
7117
  manifestDigest
9050
7118
  };
9051
7119
  }
@@ -9499,7 +7567,7 @@ function parseRepoOption(raw) {
9499
7567
  function resolveGitHubRemoteRepository(projectRoot) {
9500
7568
  let remoteUrl;
9501
7569
  try {
9502
- remoteUrl = execFileSync3("git", ["remote", "get-url", "origin"], {
7570
+ remoteUrl = execFileSync2("git", ["remote", "get-url", "origin"], {
9503
7571
  cwd: projectRoot,
9504
7572
  encoding: "utf8",
9505
7573
  stdio: ["ignore", "pipe", "pipe"]
@@ -9643,11 +7711,11 @@ function parseAnalystCohortIssueToken(raw, flag) {
9643
7711
  `${flag} requires a comma-separated list of N or book:N`
9644
7712
  );
9645
7713
  }
9646
- const sep7 = trimmed.lastIndexOf(":");
9647
- if (sep7 > 0) {
9648
- const rhs = trimmed.slice(sep7 + 1);
7714
+ const sep6 = trimmed.lastIndexOf(":");
7715
+ if (sep6 > 0) {
7716
+ const rhs = trimmed.slice(sep6 + 1);
9649
7717
  if (ANALYST_TICKET_NUMBER_PATTERN.test(rhs)) {
9650
- const bookKey = trimmed.slice(0, sep7);
7718
+ const bookKey = trimmed.slice(0, sep6);
9651
7719
  if (bookKey.trim() === "") {
9652
7720
  throw new CliUsageError(
9653
7721
  `${flag} book:N requires a non-empty book key, got ${raw}`
@@ -9851,7 +7919,6 @@ var init_invocation = __esm({
9851
7919
  init_doctor_evidence();
9852
7920
  init_diarist_contracts();
9853
7921
  init_collector_config();
9854
- init_collector_target();
9855
7922
  init_github_remote();
9856
7923
  init_fixer_packet();
9857
7924
  init_merger_git_state();
@@ -10757,7 +8824,7 @@ var init_host_providers = __esm({
10757
8824
  // src/analyst-gate-cycles-read.ts
10758
8825
  import { readdir as readdir4 } from "node:fs/promises";
10759
8826
  import { join as join20 } from "node:path";
10760
- function isRecord7(value) {
8827
+ function isRecord6(value) {
10761
8828
  return typeof value === "object" && value !== null && !Array.isArray(value);
10762
8829
  }
10763
8830
  function isParentAttemptBindingRow(row) {
@@ -10787,7 +8854,7 @@ function isGateTerminatingToolName(toolName) {
10787
8854
  function acceptedGateReceiptIds(rows) {
10788
8855
  const accepted = /* @__PURE__ */ new Set();
10789
8856
  for (const row of rows) {
10790
- const message = isRecord7(row.message) ? row.message : void 0;
8857
+ const message = isRecord6(row.message) ? row.message : void 0;
10791
8858
  if (message?.role !== "toolResult") continue;
10792
8859
  if (typeof message.toolCallId !== "string" || message.toolCallId.length === 0) continue;
10793
8860
  if (message.isError === false) accepted.add(message.toolCallId);
@@ -10822,7 +8889,7 @@ function nearestAttemptBindingBefore(rows, beforeIndex) {
10822
8889
  for (let i = beforeIndex - 1; i >= 0; i -= 1) {
10823
8890
  const row = rows[i];
10824
8891
  if (!isParentAttemptBindingRow(row)) continue;
10825
- if (!isRecord7(row.data) || !isRecord7(row.data.parent)) continue;
8892
+ if (!isRecord6(row.data) || !isRecord6(row.data.parent)) continue;
10826
8893
  const id = row.data.parent.attemptEntryId;
10827
8894
  const sessionFile = row.data.parent.sessionFile;
10828
8895
  return {
@@ -10837,10 +8904,10 @@ function extractAllAcceptedGateToolCalls(rows) {
10837
8904
  const out = [];
10838
8905
  for (let rowIndex = 0; rowIndex < rows.length; rowIndex += 1) {
10839
8906
  const row = rows[rowIndex];
10840
- const message = isRecord7(row.message) ? row.message : void 0;
8907
+ const message = isRecord6(row.message) ? row.message : void 0;
10841
8908
  if (message?.role !== "assistant" || !Array.isArray(message.content)) continue;
10842
8909
  for (const part of message.content) {
10843
- if (!isRecord7(part) || part.type !== "toolCall") continue;
8910
+ if (!isRecord6(part) || part.type !== "toolCall") continue;
10844
8911
  if (typeof part.id !== "string" || part.id.length === 0) continue;
10845
8912
  if (typeof part.name !== "string" || part.name.length === 0) continue;
10846
8913
  if (!isGateTerminatingToolName(part.name)) continue;
@@ -10848,7 +8915,7 @@ function extractAllAcceptedGateToolCalls(rows) {
10848
8915
  const binding = nearestAttemptBindingBefore(rows, rowIndex);
10849
8916
  out.push({
10850
8917
  toolName: part.name,
10851
- args: isRecord7(part.arguments) ? part.arguments : void 0,
8918
+ args: isRecord6(part.arguments) ? part.arguments : void 0,
10852
8919
  accepted: true,
10853
8920
  rowIndex,
10854
8921
  ...binding
@@ -10971,17 +9038,17 @@ function pairGateRounds(volumes) {
10971
9038
  return rounds.sort((a, b) => a.officerStartedAt.localeCompare(b.officerStartedAt)).map((round, index) => ({ ...round, roundIndex: index + 1 }));
10972
9039
  }
10973
9040
  async function resolveOfficerSessionFromPointerFile(pointerPath) {
10974
- const { readFile: readFile26 } = await import("node:fs/promises");
9041
+ const { readFile: readFile25 } = await import("node:fs/promises");
10975
9042
  let raw;
10976
9043
  try {
10977
- raw = JSON.parse(await readFile26(pointerPath, "utf8"));
9044
+ raw = JSON.parse(await readFile25(pointerPath, "utf8"));
10978
9045
  } catch (error) {
10979
9046
  throw new Error(
10980
9047
  `direct officer run pointer unreadable in ${pointerPath}: ${error instanceof Error ? error.message : String(error)}`,
10981
9048
  { cause: error }
10982
9049
  );
10983
9050
  }
10984
- if (!isRecord7(raw) || raw.kind !== "direct-officer-run-pointer" || raw.version !== 1) {
9051
+ if (!isRecord6(raw) || raw.kind !== "direct-officer-run-pointer" || raw.version !== 1) {
10985
9052
  throw new Error(`direct officer run pointer has unknown shape in ${pointerPath}`);
10986
9053
  }
10987
9054
  const sessionFile = raw.sessionFile;
@@ -11340,11 +9407,11 @@ function reportEngineDetourCall(input) {
11340
9407
  recordPointer: pointer
11341
9408
  };
11342
9409
  }
11343
- function isRecord8(value) {
9410
+ function isRecord7(value) {
11344
9411
  return typeof value === "object" && value !== null && !Array.isArray(value);
11345
9412
  }
11346
9413
  function callFactFromSitianPayload(payload, pointer) {
11347
- if (!isRecord8(payload)) return void 0;
9414
+ if (!isRecord7(payload)) return void 0;
11348
9415
  if (payload.tool !== ENGINE_DETOUR_TOOL_NAME) return void 0;
11349
9416
  if (typeof payload.toolCallId !== "string" || payload.toolCallId.length === 0) {
11350
9417
  return void 0;
@@ -11361,11 +9428,11 @@ function callFactFromSitianPayload(payload, pointer) {
11361
9428
  };
11362
9429
  }
11363
9430
  function invocationScopeIdOfRecord(record4) {
11364
- if (isRecord8(record4.subject)) {
9431
+ if (isRecord7(record4.subject)) {
11365
9432
  const fromSubject = record4.subject.invocationScopeId;
11366
9433
  if (typeof fromSubject === "string" && fromSubject.length > 0) return fromSubject;
11367
9434
  }
11368
- if (isRecord8(record4.payload)) {
9435
+ if (isRecord7(record4.payload)) {
11369
9436
  const fromPayload = record4.payload.invocationScopeId;
11370
9437
  if (typeof fromPayload === "string" && fromPayload.length > 0) return fromPayload;
11371
9438
  }
@@ -11426,7 +9493,7 @@ function readInvocationRecord(runDirectory) {
11426
9493
  const raw = JSON.parse(
11427
9494
  readFileSync2(join23(runDirectory, "invocation.json"), "utf8")
11428
9495
  );
11429
- return isRecord8(raw) ? raw : void 0;
9496
+ return isRecord7(raw) ? raw : void 0;
11430
9497
  } catch (error) {
11431
9498
  if (error?.code === "ENOENT") return void 0;
11432
9499
  throw error;
@@ -11439,7 +9506,7 @@ async function readInvocationEngineMounted(runDirectory) {
11439
9506
  }
11440
9507
  function withEngineDetourToolUsageFact(outcome, usage) {
11441
9508
  if (usage === void 0) return outcome;
11442
- const prior = isRecord8(outcome.decisiveFacts) ? outcome.decisiveFacts : {};
9509
+ const prior = isRecord7(outcome.decisiveFacts) ? outcome.decisiveFacts : {};
11443
9510
  return {
11444
9511
  ...outcome,
11445
9512
  decisiveFacts: {
@@ -11509,13 +9576,13 @@ function resolveAuditDossier(source) {
11509
9576
  }
11510
9577
  return { status: "ok", runDirectory };
11511
9578
  }
11512
- function isRecord9(value) {
9579
+ function isRecord8(value) {
11513
9580
  return typeof value === "object" && value !== null && !Array.isArray(value);
11514
9581
  }
11515
9582
  function readDoctorAuditSubjects(context) {
11516
9583
  const entries = context.sessionManager.getEntries?.() ?? [];
11517
9584
  for (const entry of entries) {
11518
- if (isRecord9(entry) && entry.type === "custom" && entry.customType === DOCTOR_CANDIDATE_ENTRY_TYPE) {
9585
+ if (isRecord8(entry) && entry.type === "custom" && entry.customType === DOCTOR_CANDIDATE_ENTRY_TYPE) {
11519
9586
  return { status: "ok" };
11520
9587
  }
11521
9588
  }
@@ -11759,11 +9826,11 @@ var init_navigator_invocation_identity = __esm({
11759
9826
  });
11760
9827
 
11761
9828
  // src/receipt-delivery-policy.ts
11762
- function isRecord10(value) {
9829
+ function isRecord9(value) {
11763
9830
  return typeof value === "object" && value !== null && !Array.isArray(value);
11764
9831
  }
11765
9832
  function parseNoReceiptLifecycleFacts(input) {
11766
- 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")) {
9833
+ 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")) {
11767
9834
  throw new TypeError("malformed no-receipt lifecycle facts");
11768
9835
  }
11769
9836
  return {
@@ -11869,7 +9936,6 @@ __export(settlement_exports, {
11869
9936
  controlledFailureInputFromResolution: () => controlledFailureInputFromResolution,
11870
9937
  exitCodeForTerminalOutcome: () => exitCodeForTerminalOutcome,
11871
9938
  explicitInternalKnownFailureClassificationInput: () => explicitInternalKnownFailureClassificationInput,
11872
- extractCollectorInfrastructureFailure: () => extractCollectorInfrastructureFailure,
11873
9939
  extractEngineDetourInfrastructureFailure: () => extractEngineDetourInfrastructureFailure,
11874
9940
  extractGateFactFromSessionDirectory: () => extractGateFactFromSessionDirectory,
11875
9941
  extractNavigatorFact: () => extractNavigatorFact,
@@ -11890,7 +9956,6 @@ __export(settlement_exports, {
11890
9956
  publishedFailureErrorPath: () => publishedFailureErrorPath,
11891
9957
  raceNavigatorGrace: () => raceNavigatorGrace,
11892
9958
  readBoundSessionEntries: () => readBoundSessionEntries,
11893
- readCollectorInfrastructureFailure: () => readCollectorInfrastructureFailure,
11894
9959
  readEngineDetourInfrastructureFailure: () => readEngineDetourInfrastructureFailure,
11895
9960
  readSessionProviderStop: () => readSessionProviderStop,
11896
9961
  recordedSubmissionPayloads: () => recordedSubmissionPayloads,
@@ -12388,7 +10453,7 @@ async function readSitianRetainedAuditorProviderStop(sessionFile) {
12388
10453
  const { records } = await readSitianRecords(recordFile);
12389
10454
  for (let i = records.length - 1; i >= 0; i -= 1) {
12390
10455
  const payload = records[i]?.payload;
12391
- if (!isRecord11(payload) || !isRecord11(payload.response)) continue;
10456
+ if (!isRecord10(payload) || !isRecord10(payload.response)) continue;
12392
10457
  if (typeof payload.type === "string") continue;
12393
10458
  const stop = sessionProviderStopFromAssistant(payload.response);
12394
10459
  if (stop !== void 0) return stop;
@@ -12438,7 +10503,7 @@ async function loadBoundAuditorVolumes(sessionFile) {
12438
10503
  throw sessionReadFailure(error, "failed to read discovered auditor session");
12439
10504
  }
12440
10505
  const header = entries.find((entry) => entry.type === "session");
12441
- if (!isRecord11(header)) continue;
10506
+ if (!isRecord10(header)) continue;
12442
10507
  const bindingIndexes = [];
12443
10508
  for (let i = 0; i < entries.length; i += 1) {
12444
10509
  const entry = entries[i];
@@ -12452,7 +10517,7 @@ async function loadBoundAuditorVolumes(sessionFile) {
12452
10517
  end: idx + 1 < bindingIndexes.length ? bindingIndexes[idx + 1] : entries.length
12453
10518
  })) : [{ entry: void 0, start: 0, end: entries.length }];
12454
10519
  for (const { entry: bindingEntry, start, end } of bindingPasses) {
12455
- const bindingParent = bindingEntry !== void 0 && isRecord11(bindingEntry.data) && isRecord11(bindingEntry.data.parent) ? bindingEntry.data.parent : void 0;
10520
+ const bindingParent = bindingEntry !== void 0 && isRecord10(bindingEntry.data) && isRecord10(bindingEntry.data.parent) ? bindingEntry.data.parent : void 0;
12456
10521
  const attemptEntryId = typeof bindingParent?.attemptEntryId === "string" ? bindingParent.attemptEntryId : void 0;
12457
10522
  const boundSessionFile = typeof bindingParent?.sessionFile === "string" ? bindingParent.sessionFile : typeof header.parentSession === "string" ? header.parentSession : void 0;
12458
10523
  if (boundSessionFile !== sessionFile) continue;
@@ -12476,12 +10541,12 @@ function complianceFailureFromAuditorVolumes(volumes) {
12476
10541
  if (stop === void 0) continue;
12477
10542
  for (let i = entries.length - 1; i >= 0; i -= 1) {
12478
10543
  const entry = entries[i];
12479
- if (entry?.type !== "custom" || entry.customType !== AUDITOR_COMPLIANCE_FAILURE_ENTRY_TYPE || !isRecord11(entry.data)) continue;
12480
- const parent = isRecord11(entry.data.parent) ? entry.data.parent : void 0;
12481
- const failure2 = isRecord11(entry.data.failure) ? entry.data.failure : void 0;
10544
+ if (entry?.type !== "custom" || entry.customType !== AUDITOR_COMPLIANCE_FAILURE_ENTRY_TYPE || !isRecord10(entry.data)) continue;
10545
+ const parent = isRecord10(entry.data.parent) ? entry.data.parent : void 0;
10546
+ const failure2 = isRecord10(entry.data.failure) ? entry.data.failure : void 0;
12482
10547
  if (parent?.sessionId !== parentId || parent.sessionFile !== sessionFile || parent.attemptEntryId !== attemptEntryId) continue;
12483
10548
  if (failure2 === void 0) continue;
12484
- const identity = isRecord11(failure2.identity) ? failure2.identity : void 0;
10549
+ const identity = isRecord10(failure2.identity) ? failure2.identity : void 0;
12485
10550
  const typedCause = failure2.cause === "provider" || failure2.cause === "activation" || failure2.cause === "session" || failure2.cause === "output" || failure2.cause === "timeout" ? failure2.cause : void 0;
12486
10551
  return {
12487
10552
  ...typedCause === void 0 ? {} : { cause: typedCause },
@@ -12490,7 +10555,7 @@ function complianceFailureFromAuditorVolumes(volumes) {
12490
10555
  ...typeof identity.code === "string" || typeof identity.code === "number" ? { code: identity.code } : {}
12491
10556
  } },
12492
10557
  ...typeof failure2.diagnostic === "string" ? { diagnostic: failure2.diagnostic } : {},
12493
- ...isRecord11(failure2.details) ? { details: failure2.details } : {}
10558
+ ...isRecord10(failure2.details) ? { details: failure2.details } : {}
12494
10559
  };
12495
10560
  }
12496
10561
  }
@@ -12537,9 +10602,9 @@ function typedFailedTerminatingToolKnownFailure(entries) {
12537
10602
  if (classification.kind !== "infrastructure") continue;
12538
10603
  if (typeof message.toolCallId !== "string" || typeof message.toolName !== "string") continue;
12539
10604
  if (boundRoleToolCallForResult(attemptEntries, i, message, message.toolName) === void 0) continue;
12540
- const textPart = Array.isArray(message.content) ? message.content.find((part) => isRecord11(part) && part.type === "text" && typeof part.text === "string") : void 0;
12541
- const diagnostic = isRecord11(textPart) ? textPart.text : void 0;
12542
- const details = isRecord11(message.details) ? message.details : classification.fact;
10605
+ const textPart = Array.isArray(message.content) ? message.content.find((part) => isRecord10(part) && part.type === "text" && typeof part.text === "string") : void 0;
10606
+ const diagnostic = isRecord10(textPart) ? textPart.text : void 0;
10607
+ const details = isRecord10(message.details) ? message.details : classification.fact;
12543
10608
  return {
12544
10609
  cause: "activation",
12545
10610
  identity: { name: message.toolName, code: message.toolCallId },
@@ -12676,7 +10741,7 @@ function controlledFailureInputFromResolution(resolution) {
12676
10741
  } : {}
12677
10742
  };
12678
10743
  }
12679
- function isRecord11(value) {
10744
+ function isRecord10(value) {
12680
10745
  return typeof value === "object" && value !== null && !Array.isArray(value);
12681
10746
  }
12682
10747
  function toolResultText(message) {
@@ -12686,25 +10751,9 @@ function toolResultText(message) {
12686
10751
  return content.map((part) => {
12687
10752
  if (typeof part === "object" && part !== null && !Array.isArray(part) && typeof part.text === "string") {
12688
10753
  return part.text;
12689
- }
12690
- return "";
12691
- }).join("").trim();
12692
- }
12693
- function extractCollectorTargetBindRejection(entries) {
12694
- for (let i = entries.length - 1; i >= 0; i -= 1) {
12695
- const entry = entries[i];
12696
- if (entry?.type !== "message") continue;
12697
- const message = entry.message;
12698
- if (message?.role !== "toolResult") continue;
12699
- if (message.toolName !== COLLECTOR_BIND_TARGET_TOOL) continue;
12700
- if (message.isError !== true) return void 0;
12701
- const diagnostic = toolResultText(message);
12702
- if (diagnostic.length === 0) return void 0;
12703
- const details = message.details;
12704
- const code = isRecord11(details) && typeof details.code === "string" && details.code.trim() !== "" ? details.code : void 0;
12705
- return code === void 0 ? { diagnostic } : { diagnostic, code };
12706
- }
12707
- return void 0;
10754
+ }
10755
+ return "";
10756
+ }).join("").trim();
12708
10757
  }
12709
10758
  function boundErroredToolCandidate(entries, resultIndex, message, toolName) {
12710
10759
  if (message.toolName !== toolName || message.isError !== true) return void 0;
@@ -12746,21 +10795,6 @@ async function readInfrastructureToolFailure(sessionFile, spec, options = {}) {
12746
10795
  return void 0;
12747
10796
  }
12748
10797
  }
12749
- function extractCollectorInfrastructureFailure(entries) {
12750
- return extractInfrastructureToolFailure(
12751
- entries,
12752
- COLLECTOR_INFRASTRUCTURE_FAILURE_SPEC
12753
- );
12754
- }
12755
- async function readCollectorInfrastructureFailure(sessionFile) {
12756
- return readInfrastructureToolFailure(
12757
- sessionFile,
12758
- COLLECTOR_INFRASTRUCTURE_FAILURE_SPEC,
12759
- // Multi-attempt resume: only a current-attempt infrastructure failure
12760
- // may preempt the current failure cause (#633).
12761
- { currentAttemptOnly: true }
12762
- );
12763
- }
12764
10798
  function extractEngineDetourInfrastructureFailure(entries) {
12765
10799
  return extractInfrastructureToolFailure(
12766
10800
  entries,
@@ -12802,7 +10836,7 @@ function boundRoleToolCallForResult(entries, resultIndex, message, outputToolNam
12802
10836
  const candidateMessage = entries[index]?.message;
12803
10837
  if (candidateMessage?.role === "assistant" && Array.isArray(candidateMessage.content)) {
12804
10838
  for (const part of candidateMessage.content) {
12805
- if (!isRecord11(part) || part.type !== "toolCall" || part.id !== callId) {
10839
+ if (!isRecord10(part) || part.type !== "toolCall" || part.id !== callId) {
12806
10840
  continue;
12807
10841
  }
12808
10842
  if (part.name !== outputToolName) return void 0;
@@ -12873,7 +10907,7 @@ function parseNavigatorAttendanceDetails(details) {
12873
10907
  if (typeof details.prose === "string" && details.prose.trim() !== "") {
12874
10908
  prose = details.prose;
12875
10909
  } else {
12876
- const next = isRecord11(details.next) && typeof details.next.role === "string" ? details.next.role : void 0;
10910
+ const next = isRecord10(details.next) && typeof details.next.role === "string" ? details.next.role : void 0;
12877
10911
  const reason = typeof details.reason === "string" && details.reason.trim() !== "" ? details.reason : void 0;
12878
10912
  const command = typeof details.command === "string" && details.command.trim() !== "" ? details.command : void 0;
12879
10913
  if (reason !== void 0 && next !== void 0) {
@@ -12982,7 +11016,7 @@ function detourGateContext(admitted, scope) {
12982
11016
  }
12983
11017
  async function withOptionalGateProjection(base, sessionDirectory, gateContext = {}) {
12984
11018
  const secondaryEvidence = base.roleOutcome.kind === "failure" ? base.roleOutcome.decisiveFacts.secondaryEvidence : void 0;
12985
- const skipGate = isRecord11(secondaryEvidence) && secondaryEvidence.kind === "role_infrastructure_failure" && packagedSkipsGateOnInfrastructureStage(secondaryEvidence.stage);
11019
+ const skipGate = isRecord10(secondaryEvidence) && secondaryEvidence.kind === "role_infrastructure_failure" && packagedSkipsGateOnInfrastructureStage(secondaryEvidence.stage);
12986
11020
  let next = base;
12987
11021
  if (!skipGate) {
12988
11022
  const gate = await extractGateFactFromSessionDirectory(sessionDirectory, gateContext);
@@ -12995,7 +11029,7 @@ function routePlaybookFailureMessage(entries) {
12995
11029
  const entry = entries[i];
12996
11030
  if (entry?.type !== "custom" || entry.customType !== NAVIGATOR_ROUTE_PLAYBOOK_FAILURE_ENTRY) continue;
12997
11031
  const data = entry.data;
12998
- if (!isRecord11(data) || typeof data.message !== "string" || data.message.trim() === "") return void 0;
11032
+ if (!isRecord10(data) || typeof data.message !== "string" || data.message.trim() === "") return void 0;
12999
11033
  return data.message;
13000
11034
  }
13001
11035
  return void 0;
@@ -13042,7 +11076,7 @@ function extractNavigatorAttendanceFact(entries) {
13042
11076
  const entry = entries[i];
13043
11077
  if (entry?.type === "custom_message" && entry.customType === "ak-navigator-attendance") {
13044
11078
  const details = entry.message?.details ?? entry.details;
13045
- if (!isRecord11(details)) {
11079
+ if (!isRecord10(details)) {
13046
11080
  return {
13047
11081
  disposition: "unavailable",
13048
11082
  source: "unknown",
@@ -13193,7 +11227,7 @@ async function settleSealedAcceptedOrToolResidual(admitted, authority, scope, ro
13193
11227
  const residual = boundErroredToolCandidate(entries, index, message, residualToolName);
13194
11228
  if (residual === void 0) continue;
13195
11229
  const candidate = residual.candidate;
13196
- const details = isRecord11(candidate) ? candidate : { candidate };
11230
+ const details = isRecord10(candidate) ? candidate : { candidate };
13197
11231
  const failed = await settleFailureTerminalResult(
13198
11232
  admitted,
13199
11233
  {
@@ -13268,7 +11302,7 @@ function extractDoctorCandidateFacts(entries) {
13268
11302
  continue;
13269
11303
  }
13270
11304
  const data = entry.data;
13271
- if (!isRecord11(data)) return {};
11305
+ if (!isRecord10(data)) return {};
13272
11306
  return {
13273
11307
  ...data.cost === void 0 ? {} : { cost: data.cost },
13274
11308
  ...data.auditNoReceipt === void 0 ? {} : { auditNoReceipt: data.auditNoReceipt }
@@ -13353,7 +11387,7 @@ async function settleLawfulSeatAcceptedTerminalResult(admitted, authority, spec,
13353
11387
  let residual;
13354
11388
  for (let index = entries.length - 1; index >= scanStart; index -= 1) {
13355
11389
  const entry = entries[index];
13356
- if (entry?.type === "custom" && entry.customType === "ak-role-submission-closure" && isRecord11(entry.data) && entry.data.toolName === spec.toolName && classifyPackagedRoleTerminalResult(entry.data).kind === "accepted") {
11390
+ if (entry?.type === "custom" && entry.customType === "ak-role-submission-closure" && isRecord10(entry.data) && entry.data.toolName === spec.toolName && classifyPackagedRoleTerminalResult(entry.data).kind === "accepted") {
13357
11391
  thisAttemptHasSeatSuccess = true;
13358
11392
  }
13359
11393
  const message = entries[index]?.message;
@@ -13393,7 +11427,7 @@ async function settleLawfulSeatAcceptedTerminalResult(admitted, authority, spec,
13393
11427
  );
13394
11428
  }
13395
11429
  if (residual !== void 0) {
13396
- const details = isRecord11(residual.candidate) ? residual.candidate : { candidate: residual.candidate };
11430
+ const details = isRecord10(residual.candidate) ? residual.candidate : { candidate: residual.candidate };
13397
11431
  const failed = await settleFailureTerminalResult(
13398
11432
  admitted,
13399
11433
  {
@@ -13443,7 +11477,7 @@ function countersignTerminalFromEntries(entries) {
13443
11477
  return void 0;
13444
11478
  }
13445
11479
  function withCountersignTerminalFact(roleOutcome, officer) {
13446
- const prior = roleOutcome.decisiveFacts !== void 0 && isRecord11(roleOutcome.decisiveFacts) ? roleOutcome.decisiveFacts : {};
11480
+ const prior = roleOutcome.decisiveFacts !== void 0 && isRecord10(roleOutcome.decisiveFacts) ? roleOutcome.decisiveFacts : {};
13447
11481
  return {
13448
11482
  ...roleOutcome,
13449
11483
  decisiveFacts: {
@@ -13456,7 +11490,7 @@ function acceptedSecretariatDefinesOfficerProjection(roleOutcome) {
13456
11490
  const payloads = roleOutcome.payloads ?? [];
13457
11491
  for (let index = payloads.length - 1; index >= 0; index -= 1) {
13458
11492
  const payload = payloads[index];
13459
- if (!isRecord11(payload)) continue;
11493
+ if (!isRecord10(payload)) continue;
13460
11494
  const status = payload.secretariatStatus;
13461
11495
  if (typeof status !== "string") continue;
13462
11496
  return status === "converged";
@@ -13684,17 +11718,6 @@ async function settleFailureTerminalResult(admitted, failure2, authority, option
13684
11718
  }
13685
11719
  if (facts !== void 0 && facts.runPointer === admitted.runDirectory && facts.attemptPointer === `current:${admitted.runDirectory}`) {
13686
11720
  let decisiveFacts2 = facts;
13687
- if (packagedProjectsTargetBindRejection(admitted.role)) {
13688
- const bindRejection = extractCollectorTargetBindRejection(entries.slice(attemptStart));
13689
- if (bindRejection !== void 0) {
13690
- decisiveFacts2 = {
13691
- ...facts,
13692
- targetBindRejected: true,
13693
- targetBindDiagnostic: bindRejection.diagnostic,
13694
- ...bindRejection.code === void 0 ? {} : { targetBindCode: bindRejection.code }
13695
- };
13696
- }
13697
- }
13698
11721
  await clearOppositeTerminalArtifactFace(admitted.runDirectory);
13699
11722
  return withOptionalGateProjection(
13700
11723
  {
@@ -13829,7 +11852,7 @@ function raceNavigatorGrace(work, graceMs = NAVIGATOR_POST_ROLE_GRACE_MS, sleep2
13829
11852
  });
13830
11853
  });
13831
11854
  }
13832
- 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;
11855
+ var privateFailureErrorPaths, NAVIGATOR_POST_ROLE_GRACE_MS, ENGINE_DETOUR_INFRASTRUCTURE_FAILURE_SPEC, RUNNER_FAILURE_POLICY, ATTEMPT_HISTORY_ENTRY_TYPE, EMPTY_ARTIFACT_FACE;
13833
11856
  var init_settlement = __esm({
13834
11857
  "src/public-cli/settlement.ts"() {
13835
11858
  "use strict";
@@ -13842,11 +11865,9 @@ var init_settlement = __esm({
13842
11865
  init_serialize_thrown_value();
13843
11866
  init_run_lifecycle();
13844
11867
  init_compliance_transport();
13845
- init_collector_ledger();
13846
11868
  init_engine_detour();
13847
11869
  init_engine_detour_usage();
13848
11870
  init_judge_output();
13849
- init_collector_output();
13850
11871
  init_worker_output();
13851
11872
  init_doctor_contracts();
13852
11873
  init_dossier_resolution();
@@ -13862,20 +11883,6 @@ var init_settlement = __esm({
13862
11883
  init_terminal();
13863
11884
  privateFailureErrorPaths = /* @__PURE__ */ new WeakMap();
13864
11885
  NAVIGATOR_POST_ROLE_GRACE_MS = 1e4;
13865
- COLLECTOR_INFRASTRUCTURE_TOOLS = /* @__PURE__ */ new Set([
13866
- COLLECTOR_OBSERVE_TOOL,
13867
- COLLECTOR_READ_TOOL,
13868
- COLLECTOR_REQUEST_TOOL,
13869
- COLLECTOR_WAIT_TOOL
13870
- ]);
13871
- COLLECTOR_INFRASTRUCTURE_FAILURE_SPEC = {
13872
- matchTool: (toolName) => COLLECTOR_INFRASTRUCTURE_TOOLS.has(toolName),
13873
- cause: "activation",
13874
- identityName: "CollectorInfrastructureError",
13875
- // read alone has a correctable rejection mode (unknown/non-openable pointers);
13876
- // only its typed infrastructure-failure fact counts as a real host failure.
13877
- requireInfrastructureFact: (toolName) => toolName === COLLECTOR_READ_TOOL
13878
- };
13879
11886
  ENGINE_DETOUR_INFRASTRUCTURE_FAILURE_SPEC = {
13880
11887
  matchTool: (toolName) => toolName === ENGINE_DETOUR_TOOL_NAME,
13881
11888
  cause: "output",
@@ -13889,10 +11896,6 @@ var init_settlement = __esm({
13889
11896
  "engine-detour-record-first": {
13890
11897
  read: readEngineDetourInfrastructureFailure,
13891
11898
  rank: "record-first"
13892
- },
13893
- "collector-known-first": {
13894
- read: readCollectorInfrastructureFailure,
13895
- rank: "known-first"
13896
11899
  }
13897
11900
  };
13898
11901
  ATTEMPT_HISTORY_ENTRY_TYPE = "ak_run_attempt_history";
@@ -16190,11 +14193,11 @@ var init_turn_request = __esm({
16190
14193
  });
16191
14194
 
16192
14195
  // src/public-cli/countersign-run.ts
16193
- function isRecord12(value) {
14196
+ function isRecord11(value) {
16194
14197
  return typeof value === "object" && value !== null && !Array.isArray(value);
16195
14198
  }
16196
14199
  function isEscalatePayload(payload) {
16197
- if (!isRecord12(payload)) return false;
14200
+ if (!isRecord11(payload)) return false;
16198
14201
  return payload.status === "escalate";
16199
14202
  }
16200
14203
  function courtDiaristPayloadRows(roleOutcome, submissions) {
@@ -17804,7 +15807,7 @@ function isMissingPathError6(error) {
17804
15807
  function errorText3(error) {
17805
15808
  return error instanceof Error ? error.message : String(error);
17806
15809
  }
17807
- function isRecord13(value) {
15810
+ function isRecord12(value) {
17808
15811
  return typeof value === "object" && value !== null && !Array.isArray(value);
17809
15812
  }
17810
15813
  async function readExistingRunLifecycleState(runDirectory) {
@@ -17861,7 +15864,7 @@ async function readInvocationScopeFields(runDirectory) {
17861
15864
  throw error;
17862
15865
  }
17863
15866
  const parsed = JSON.parse(raw);
17864
- if (!isRecord13(parsed)) return void 0;
15867
+ if (!isRecord12(parsed)) return void 0;
17865
15868
  if (typeof parsed.projectRoot !== "string" || parsed.projectRoot.trim() === "") {
17866
15869
  return void 0;
17867
15870
  }
@@ -17890,7 +15893,7 @@ async function resolveSessionFile(runDirectory) {
17890
15893
  try {
17891
15894
  const raw = await readFile18(join33(runDirectory, "invocation.json"), "utf8");
17892
15895
  const parsed = JSON.parse(raw);
17893
- if (isRecord13(parsed) && typeof parsed.sessionFile === "string" && parsed.sessionFile.trim() !== "") {
15896
+ if (isRecord12(parsed) && typeof parsed.sessionFile === "string" && parsed.sessionFile.trim() !== "") {
17894
15897
  return parsed.sessionFile;
17895
15898
  }
17896
15899
  } catch (error) {
@@ -18228,7 +16231,7 @@ var init_analyst_ledger = __esm({
18228
16231
  });
18229
16232
 
18230
16233
  // src/analyst-metric-families/acceptance-success-rework.ts
18231
- function isRecord14(value) {
16234
+ function isRecord13(value) {
18232
16235
  return typeof value === "object" && value !== null && !Array.isArray(value);
18233
16236
  }
18234
16237
  function wallMsFromSpan(span) {
@@ -18237,21 +16240,21 @@ function wallMsFromSpan(span) {
18237
16240
  function findCollectorGroups(body) {
18238
16241
  if (Array.isArray(body.groups)) return body.groups;
18239
16242
  const receipt = body.receipt;
18240
- if (isRecord14(receipt) && Array.isArray(receipt.groups)) return receipt.groups;
16243
+ if (isRecord13(receipt) && Array.isArray(receipt.groups)) return receipt.groups;
18241
16244
  const outcome = body.outcome;
18242
- if (isRecord14(outcome)) {
16245
+ if (isRecord13(outcome)) {
18243
16246
  const facts = outcome.decisiveFacts;
18244
- if (isRecord14(facts) && Array.isArray(facts.groups)) return facts.groups;
16247
+ if (isRecord13(facts) && Array.isArray(facts.groups)) return facts.groups;
18245
16248
  }
18246
16249
  return void 0;
18247
16250
  }
18248
16251
  function extractStatus(body) {
18249
16252
  const outcome = body.outcome;
18250
- if (isRecord14(outcome) && typeof outcome.status === "string" && outcome.status.trim() !== "") {
16253
+ if (isRecord13(outcome) && typeof outcome.status === "string" && outcome.status.trim() !== "") {
18251
16254
  return outcome.status;
18252
16255
  }
18253
16256
  const receipt = body.receipt;
18254
- if (isRecord14(receipt) && typeof receipt.status === "string" && receipt.status.trim() !== "") {
16257
+ if (isRecord13(receipt) && typeof receipt.status === "string" && receipt.status.trim() !== "") {
18255
16258
  return receipt.status;
18256
16259
  }
18257
16260
  if (typeof body.status === "string" && body.status.trim() !== "") {
@@ -18877,15 +16880,15 @@ var init_leg_wall_clock = __esm({
18877
16880
  });
18878
16881
 
18879
16882
  // src/analyst-metric-families/round-timeline.ts
18880
- function isRecord15(value) {
16883
+ function isRecord14(value) {
18881
16884
  return typeof value === "object" && value !== null && !Array.isArray(value);
18882
16885
  }
18883
16886
  function wallMsFromSpan2(startedAt, endedAt) {
18884
16887
  return Date.parse(endedAt) - Date.parse(startedAt);
18885
16888
  }
18886
16889
  function readClassCount(body) {
18887
- if (!isRecord15(body.outcome)) return void 0;
18888
- if (!isRecord15(body.outcome.decisiveFacts)) return void 0;
16890
+ if (!isRecord14(body.outcome)) return void 0;
16891
+ if (!isRecord14(body.outcome.decisiveFacts)) return void 0;
18889
16892
  const classCount = body.outcome.decisiveFacts.classCount;
18890
16893
  if (typeof classCount !== "number" || !Number.isFinite(classCount)) {
18891
16894
  return void 0;
@@ -19029,7 +17032,7 @@ var init_analyst_metric_family = __esm({
19029
17032
  });
19030
17033
 
19031
17034
  // src/analyst-page.ts
19032
- import { createHash as createHash5 } from "node:crypto";
17035
+ import { createHash as createHash3 } from "node:crypto";
19033
17036
  import { dirname as dirname21, join as join34 } from "node:path";
19034
17037
  function analystIssuePageKey(address) {
19035
17038
  const parts = ["book", address.bookKey];
@@ -19038,7 +17041,7 @@ function analystIssuePageKey(address) {
19038
17041
  } else if (address.scopeRootIdentity !== void 0) {
19039
17042
  parts.push("root", physicalPathIdentity(address.scopeRootIdentity));
19040
17043
  }
19041
- return createHash5("sha256").update(parts.join("\0")).digest("hex").slice(0, 32);
17044
+ return createHash3("sha256").update(parts.join("\0")).digest("hex").slice(0, 32);
19042
17045
  }
19043
17046
  function analystIssuePagePath(ledgerHome, address) {
19044
17047
  return join34(ledgerHome, "analyst", "issues", `${analystIssuePageKey(address)}.json`);
@@ -22875,8 +20878,8 @@ var init_submission_ledger = __esm({
22875
20878
  });
22876
20879
 
22877
20880
  // src/archivist-record-topology.ts
22878
- import { createHash as createHash6 } from "node:crypto";
22879
- import { join as join42 } from "node:path";
20881
+ import { createHash as createHash4 } from "node:crypto";
20882
+ import { join as join41 } from "node:path";
22880
20883
  function resolveNavigatorWorkSubjectPlacement(input) {
22881
20884
  let ledgerHome;
22882
20885
  if (input.parentSessionFile !== void 0 && input.parentSessionFile.length > 0) {
@@ -22886,10 +20889,10 @@ 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
- sessionDir: join42(
20895
+ sessionDir: join41(
22893
20896
  activationBookDirectory(ledgerHome, resolveBookKeyFromGit(input.cwd)),
22894
20897
  NAVIGATOR_RECORD_KIND,
22895
20898
  digest
@@ -22961,10 +20964,10 @@ import {
22961
20964
  statSync as statSync7,
22962
20965
  writeFileSync as writeFileSync3
22963
20966
  } from "node:fs";
22964
- import { dirname as dirname23, resolve as resolve17, join as join43 } from "node:path";
20967
+ import { dirname as dirname23, resolve as resolve17, join as join42 } from "node:path";
22965
20968
  import { StringDecoder } from "node:string_decoder";
22966
20969
  function readCurrentSession(sessionDir) {
22967
- const ledger = join43(sessionDir, CURRENT_SESSION_LEDGER);
20970
+ const ledger = join42(sessionDir, CURRENT_SESSION_LEDGER);
22968
20971
  try {
22969
20972
  const value = JSON.parse(readFileSync4(ledger, "utf8"));
22970
20973
  if (typeof value !== "object" || value === null || typeof value.sessionFile !== "string" || value.sessionFile.length === 0) {
@@ -22979,7 +20982,7 @@ function readCurrentSession(sessionDir) {
22979
20982
  }
22980
20983
  }
22981
20984
  function writeCurrentSession(sessionDir, sessionFile) {
22982
- const ledger = join43(sessionDir, CURRENT_SESSION_LEDGER);
20985
+ const ledger = join42(sessionDir, CURRENT_SESSION_LEDGER);
22983
20986
  try {
22984
20987
  writeFileSync3(ledger, `${JSON.stringify({ sessionFile })}
22985
20988
  `, { flag: "wx" });
@@ -22995,7 +20998,7 @@ function isCurrentSessionClaimRace(error) {
22995
20998
  return errnoCode(error.cause) === "EEXIST";
22996
20999
  }
22997
21000
  function currentSessionLedgerPath(sessionDir) {
22998
- return join43(sessionDir, CURRENT_SESSION_LEDGER);
21001
+ return join42(sessionDir, CURRENT_SESSION_LEDGER);
22999
21002
  }
23000
21003
  function readBoundedSessionHeader(filePath) {
23001
21004
  const fd = openSync2(filePath, "r");
@@ -23082,7 +21085,7 @@ function mostRecentNavigatorSessionFile(sessionDir, cwd) {
23082
21085
  const matched = [];
23083
21086
  for (const name of names) {
23084
21087
  if (!name.endsWith(".jsonl")) continue;
23085
- const filePath = join43(absoluteSessionDir, name);
21088
+ const filePath = join42(absoluteSessionDir, name);
23086
21089
  let st;
23087
21090
  try {
23088
21091
  st = statSync7(filePath);
@@ -23194,7 +21197,7 @@ function createRecordSessionOpen(options, host = piRecordSessionHost) {
23194
21197
  if (!physicallyContainedIn(ledgerHome, parentResolved)) {
23195
21198
  throw new Error("Durable record ownership requires a parent session inside the ledger home");
23196
21199
  }
23197
- sessionDir = join43(dirname23(parentResolved), options.kind);
21200
+ sessionDir = join42(dirname23(parentResolved), options.kind);
23198
21201
  parentSession = parentFile;
23199
21202
  mayResumeSameNest = options.kind === WORKER_SUBMISSION_GATE_KIND;
23200
21203
  }
@@ -23265,17 +21268,16 @@ init_packaged_role_registry();
23265
21268
  import { randomUUID as randomUUID9 } from "node:crypto";
23266
21269
  import { appendFile as appendFile3, mkdir as mkdir5, writeFile as writeFile10 } from "node:fs/promises";
23267
21270
  import { createServer } from "node:net";
23268
- import { dirname as dirname25, join as join46 } from "node:path";
21271
+ import { dirname as dirname25, join as join45 } from "node:path";
23269
21272
  import { fileURLToPath as fileURLToPath2 } from "node:url";
23270
21273
 
23271
21274
  // src/role-runtime.ts
23272
21275
  init_host_contracts();
23273
21276
  init_sitian_facade();
23274
21277
  init_submission_ledger();
23275
- init_collector_ledger();
23276
21278
  import { randomUUID as randomUUID8 } from "node:crypto";
23277
21279
  import { readFileSync as readFileSync6, writeSync as writeSync2 } from "node:fs";
23278
- import { join as join45 } from "node:path";
21280
+ import { join as join44 } from "node:path";
23279
21281
  import { Value as Value4 } from "typebox/value";
23280
21282
 
23281
21283
  // src/activation-trace.ts
@@ -23592,96 +21594,19 @@ init_receipt_delivery_policy();
23592
21594
 
23593
21595
  // src/collector-role.ts
23594
21596
  init_collector_config();
23595
- init_collector_evidence();
23596
- init_collector_github();
23597
-
23598
- // src/collector-handbook.ts
23599
- init_atomic_write();
23600
- init_activation_ledger_topology();
23601
- import { readFile as readFile22 } from "node:fs/promises";
23602
- import { join as join40, sep as sep6 } from "node:path";
21597
+ init_collector_output();
23603
21598
 
23604
21599
  // src/collector-tool-schemas.ts
23605
21600
  init_open_tool_schema();
23606
21601
  init_terminating_infrastructure();
23607
21602
  import { Type as Type14 } from "typebox";
23608
- var collectorObserveArgsSchema = Type14.Object({}, { additionalProperties: true });
23609
- var collectorRequestArgsSchema = Type14.Object({
23610
- requestId: Type14.String({
23611
- minLength: 1,
23612
- 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"
23613
- }),
23614
- snapshotId: Type14.String({ minLength: 1, description: "\u6700\u65B0\u7559\u5B58\u89C2\u5BDF\u5FEB\u7167" }),
23615
- // #836 r16 class 3: body.minLength deleted — manifest-configured requestId
23616
- // ignores body, and the unknown-requestId non-empty condition is a real
23617
- // branch in src/collector-ledger.ts:922-951, not a provider shape gate.
23618
- body: Type14.Optional(Type14.String({
23619
- description: "\u89D2\u8272\u5224\u5B9A\u7684\u8BF7\u6C42\u6B63\u6587\uFF1Brequest-manifest \u672A\u6536\u5F55\u8BE5 requestId \u65F6\u5FC5\u586B"
23620
- }))
23621
- }, { additionalProperties: true });
23622
- var COLLECTOR_HANDBOOK_MAX_BYTES = 64 * 1024;
23623
- var collectorHandbookWriteArgsSchema = Type14.Object({
23624
- scope: Type14.Union([
23625
- Type14.Literal("general"),
23626
- Type14.Literal("repo")
23627
- ], { description: "general\uFF1D\u901A\u7528\u624B\u518C\uFF1Brepo\uFF1D\u5F53\u524D\u4ED3\u5E93\u5DEE\u5F02" }),
23628
- body: Type14.String({
23629
- 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`
23630
- })
23631
- }, { additionalProperties: true });
23632
- var collectorReadArgsSchema = Type14.Object({
23633
- evidenceId: Type14.String({ minLength: 1, description: "observe \u8FD4\u56DE\u7684\u6750\u6599\u8BC1\u636E id\uFF08evidenceId\uFF09" })
23634
- }, { additionalProperties: true });
23635
- var collectorWaitArgsSchema = Type14.Object({
23636
- durationMs: Type14.Integer({
23637
- minimum: 1,
23638
- 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"
23639
- })
23640
- }, { additionalProperties: true });
23641
- var collectorOpenWaitWindowArgsSchema = Type14.Object({
23642
- startedAt: Type14.Optional(Type14.String({
23643
- 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"
23644
- }))
23645
- }, { additionalProperties: true });
23646
- var collectorBindTargetArgsSchema = Type14.Object({
23647
- prNumber: Type14.Optional(Type14.Unknown({
23648
- description: "\u672C\u4ED3 PR \u53F7\uFF08\u6B63\u6574\u6570\uFF09\u3002"
23649
- })),
23650
- issueNumber: Type14.Optional(Type14.Unknown({
23651
- description: "\u672C\u4ED3 issue \u53F7\uFF08\u6B63\u6574\u6570\uFF09\u3002"
23652
- }))
23653
- }, { additionalProperties: true });
23654
- var collectorFindingItemDeclaration = (() => {
23655
- const item = Type14.Object(
23656
- {
23657
- evidenceId: Type14.Unknown({
23658
- description: "observe \u8FD4\u56DE\u7684\u6750\u6599\u6307\u9488\uFF08\u5FC5\u586B\u8BED\u4E49\uFF09"
23659
- }),
23660
- category: Type14.Unknown({
23661
- description: "\u7B80\u77ED\u5F52\u7C7B\u6807\u7B7E\uFF0C\u4E0D\u662F\u6458\u8981"
23662
- }),
23663
- summary: Type14.Unknown({
23664
- description: "\u54EA\u4E2A bot\u3001\u4EC0\u4E48\u95EE\u9898\u7684\u6458\u8981\uFF1B\u4E0D\u8A8A\u6284\u6B63\u6587"
23665
- })
23666
- },
23667
- {
23668
- additionalProperties: true,
23669
- description: "\u5355\u6761 finding \u6307\u9488\uFF1AevidenceId\uFF0C\u4EE5\u53CA\u53EF\u9009 category\u3001summary\u3002"
23670
- }
23671
- );
23672
- item.required = [];
23673
- return item;
23674
- })();
23675
21603
  var collectorOutputBaseSchema = openToolObject(
23676
21604
  Type14.Object({
23677
- // No root type:array — host must not shape-reject non-array findings (#676 C).
23678
- // Nested item declarations ride `items` for registration preservation (ADR 0057).
23679
- findings: Type14.Unsafe({
23680
- description: "\u672C\u6B21\u6536\u96C6\u5230\u7684\u9010\u6761 findings \u6307\u9488\u3002",
23681
- items: collectorFindingItemDeclaration
21605
+ groups: Type14.Unsafe({
21606
+ 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"
23682
21607
  }),
23683
21608
  unfinishedReasons: Type14.Unknown({
23684
- description: "\u672A\u5B8C\u6210\u539F\u56E0\u3002"
21609
+ description: "\u672A\u5B8C\u6210\u539F\u56E0\uFF1B\u53D6\u8BC1\u53D7\u9650\u65F6\u5982\u5B9E\u62A5\u544A\u3002"
23685
21610
  })
23686
21611
  })
23687
21612
  );
@@ -23689,146 +21614,9 @@ var collectorOutputArgsSchema = withTerminatingOutputDeclarations(
23689
21614
  collectorOutputBaseSchema
23690
21615
  );
23691
21616
 
23692
- // src/collector-handbook.ts
23693
- function resolveCollectorHandbookRoot(sessionPath) {
23694
- if (typeof sessionPath !== "string" || sessionPath.trim().length === 0) {
23695
- throw new Error("\u901A\u8FDB\u53F8\u624B\u518C\u8981\u6C42\u975E\u7A7A session \u8DEF\u5F84\uFF0C\u4E14\u4F4D\u4E8E books/<bookKey>/");
23696
- }
23697
- const segments = sessionPath.split(sep6);
23698
- let bookKey;
23699
- for (let i = 0; i + 3 < segments.length; i += 1) {
23700
- if (segments[i] === ".ak-roles" && segments[i + 1] === "books") {
23701
- const candidate = segments[i + 2];
23702
- if (candidate.length > 0) {
23703
- bookKey = candidate;
23704
- break;
23705
- }
23706
- }
23707
- }
23708
- if (bookKey === void 0) {
23709
- throw new Error(
23710
- `\u901A\u8FDB\u53F8\u624B\u518C\u8981\u6C42 session \u4F4D\u4E8E books/<bookKey>/\uFF1B\u6536\u5230 ${sessionPath}`
23711
- );
23712
- }
23713
- if (bookKey === "." || bookKey === "..") {
23714
- throw new Error(`\u901A\u8FDB\u53F8\u624B\u518C\u62D2\u7EDD\u4E0D\u5B89\u5168 bookKey ${JSON.stringify(bookKey)}`);
23715
- }
23716
- const ledgerHome = resolveActivationLedgerHomeForPath(sessionPath);
23717
- const root = join40(activationBookDirectory(ledgerHome, bookKey), "collector-handbook");
23718
- return { ledgerHome, bookKey, root };
23719
- }
23720
- function collectorHandbookRepoFileName(repositoryCanonical) {
23721
- if (!/^[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*$/.test(repositoryCanonical)) {
23722
- throw new Error(
23723
- `\u901A\u8FDB\u53F8\u624B\u518C\u4ED3\u5E93\u6587\u4EF6\u8981\u6C42\u89C4\u8303 owner/repo\uFF0C\u6536\u5230 ${JSON.stringify(repositoryCanonical)}`
23724
- );
23725
- }
23726
- return `${repositoryCanonical.replaceAll("/", "__")}.md`;
23727
- }
23728
- function createCollectorHandbookStore(input) {
23729
- const generalPath = join40(input.handbookRoot, "general.md");
23730
- const repoDir = join40(input.handbookRoot, "repos");
23731
- const repoPath = join40(repoDir, collectorHandbookRepoFileName(input.repositoryCanonical));
23732
- const assertHandbookBudget = (body, label) => {
23733
- const byteLength = Buffer.byteLength(body, "utf8");
23734
- if (byteLength > COLLECTOR_HANDBOOK_MAX_BYTES) {
23735
- throw new Error(
23736
- `\u901A\u8FDB\u53F8\u624B\u518C${label} UTF-8 \u81F3\u591A ${COLLECTOR_HANDBOOK_MAX_BYTES} \u5B57\u8282\uFF0C\u6536\u5230 ${byteLength}`
23737
- );
23738
- }
23739
- return byteLength;
23740
- };
23741
- const readOptional = async (path, parentDir2) => {
23742
- ensureRealDirectoryTree(input.ledgerHome, parentDir2);
23743
- assertLedgerFileInsideHome(path, input.ledgerHome);
23744
- try {
23745
- const body = await readFile22(path, "utf8");
23746
- assertHandbookBudget(body, "\u6B63\u6587");
23747
- return body;
23748
- } catch (error) {
23749
- if (isNotFound(error)) return void 0;
23750
- throw error;
23751
- }
23752
- };
23753
- return {
23754
- root: input.handbookRoot,
23755
- repositoryCanonical: input.repositoryCanonical,
23756
- async read() {
23757
- const bookGeneral = await readOptional(generalPath, input.handbookRoot);
23758
- const bookRepo = await readOptional(repoPath, repoDir);
23759
- if (bookGeneral !== void 0) {
23760
- return {
23761
- general: bookGeneral,
23762
- repo: bookRepo ?? "",
23763
- generalSource: "book",
23764
- repoSource: bookRepo === void 0 ? "empty" : "book",
23765
- generalPath,
23766
- repoPath
23767
- };
23768
- }
23769
- const seed = input.seedGeneral;
23770
- if (typeof seed === "string" && seed.length > 0) {
23771
- assertHandbookBudget(seed, "\u6B63\u6587");
23772
- return {
23773
- general: seed,
23774
- repo: bookRepo ?? "",
23775
- generalSource: "seed",
23776
- repoSource: bookRepo === void 0 ? "empty" : "book",
23777
- generalPath,
23778
- repoPath
23779
- };
23780
- }
23781
- return {
23782
- general: "",
23783
- repo: bookRepo ?? "",
23784
- generalSource: "empty",
23785
- repoSource: bookRepo === void 0 ? "empty" : "book",
23786
- generalPath,
23787
- repoPath
23788
- };
23789
- },
23790
- async write(scope, body) {
23791
- const byteLength = assertHandbookBudget(body, "\u6B63\u6587");
23792
- ensureRealDirectoryTree(input.ledgerHome, input.handbookRoot);
23793
- const path = scope === "general" ? generalPath : repoPath;
23794
- if (scope === "repo") {
23795
- ensureRealDirectoryTree(input.ledgerHome, repoDir);
23796
- }
23797
- assertLedgerFileInsideHome(path, input.ledgerHome);
23798
- await writeFileAtomically(path, body);
23799
- return {
23800
- scope,
23801
- path,
23802
- byteLength
23803
- };
23804
- }
23805
- };
23806
- }
23807
- function isNotFound(error) {
23808
- return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
23809
- }
23810
-
23811
21617
  // src/collector-role.ts
23812
- init_collector_ledger();
23813
- init_submission_correctable_error();
23814
- init_collector_identity();
23815
- init_collector_identity();
23816
- var CollectorTargetBindError = class extends CorrectableSubmissionError {
23817
- constructor(message) {
23818
- super(message);
23819
- this.name = "CollectorTargetBindError";
23820
- }
23821
- };
23822
- var COLLECTOR_REQUIRED_TOOLS = [
23823
- COLLECTOR_BIND_TARGET_TOOL,
23824
- COLLECTOR_OBSERVE_TOOL,
23825
- COLLECTOR_READ_TOOL,
23826
- COLLECTOR_REQUEST_TOOL,
23827
- COLLECTOR_OPEN_WAIT_WINDOW_TOOL,
23828
- COLLECTOR_WAIT_TOOL,
23829
- COLLECTOR_HANDBOOK_WRITE_TOOL,
23830
- COLLECTOR_OUTPUT_TOOL
23831
- ];
21618
+ var COLLECTOR_REQUIRED_TOOLS = [COLLECTOR_OUTPUT_TOOL];
21619
+ var COLLECTOR_CONSTRUCTION_TOOLS = Object.freeze(["write", "edit"]);
23832
21620
  var COLLECTOR_TRANSPORT_FLAGS = Object.freeze([
23833
21621
  Object.freeze({
23834
21622
  name: "ak-collector-repo",
@@ -23840,87 +21628,49 @@ var COLLECTOR_TRANSPORT_FLAGS = Object.freeze([
23840
21628
  Object.freeze({
23841
21629
  name: "ak-collector-pr",
23842
21630
  definition: Object.freeze({
23843
- description: "Optional positive safe-integer pull request number for Collector. Omit when the role will bind from task materials.",
21631
+ description: "Optional positive safe-integer pull request number for Collector. Omit when the role will locate the PR via host CLI.",
23844
21632
  type: "string"
23845
21633
  })
23846
21634
  }),
23847
21635
  Object.freeze({
23848
21636
  name: "ak-collector-request-manifest",
23849
21637
  definition: Object.freeze({
23850
- description: "Path to the Collector v1 request manifest JSON file.",
23851
- type: "string"
23852
- })
23853
- }),
23854
- Object.freeze({
23855
- name: "ak-collector-wait-ms",
23856
- definition: Object.freeze({
23857
- 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).`,
21638
+ description: "Path to the Collector v1 request manifest JSON file (caller guidance; not a machine collection directive).",
23858
21639
  type: "string"
23859
21640
  })
23860
21641
  })
23861
21642
  ]);
23862
- var observeSchema = collectorObserveArgsSchema;
23863
- var readSchema = collectorReadArgsSchema;
23864
- var requestSchema = collectorRequestArgsSchema;
23865
- var openWaitWindowSchema = collectorOpenWaitWindowArgsSchema;
23866
- var waitSchema = collectorWaitArgsSchema;
23867
- var bindSchema = collectorBindTargetArgsSchema;
23868
- var handbookWriteSchema = collectorHandbookWriteArgsSchema;
23869
21643
  var outputSchema = collectorOutputArgsSchema;
23870
- function parseWaitWindowMsFlag(raw) {
23871
- if (raw === void 0 || raw === null || raw === "") return COLLECTOR_DEFAULT_WAIT_WINDOW_MS;
23872
- if (typeof raw === "number" && Number.isSafeInteger(raw) && raw >= 1) return raw;
23873
- if (typeof raw === "string" && /^[1-9]\d*$/.test(raw.trim())) {
23874
- const value = Number(raw.trim());
23875
- if (Number.isSafeInteger(value) && value >= 1) return value;
23876
- }
23877
- throw new Error("Collector --ak-collector-wait-ms must be a positive safe-integer millisecond string");
23878
- }
23879
21644
  function buildMethodContext(activation) {
23880
- const pr = activation.ledger.config.prNumber;
23881
- const handbook = activation.handbookView;
23882
21645
  const lines = [
23883
21646
  "<collector_method>",
23884
21647
  `host: github.com`,
23885
21648
  `repository: ${activation.repository.canonical}`,
23886
- `prNumber: ${pr === void 0 ? "\u672A\u7ED1\u5B9A" : String(pr)}`,
23887
- `waitWindowMs: ${String(activation.ledger.config.waitWindowMs)}`,
21649
+ `prNumber: ${activation.prNumber === void 0 ? "\u672A\u7ED1\u5B9A" : String(activation.prNumber)}`,
23888
21650
  `requests: ${JSON.stringify(activation.manifest.requests.map((request) => ({ id: request.id })))}`,
23889
- `handbookGeneralSource: ${handbook.generalSource}`,
23890
- `handbookRepoSource: ${handbook.repoSource}`,
21651
+ `manifestDigest: ${activation.manifest.digest}`,
23891
21652
  "</collector_method>"
23892
21653
  ];
23893
- if (handbook.general.length > 0 || handbook.repo.length > 0) {
21654
+ if (activation.manifest.requests.length > 0) {
23894
21655
  const payload = JSON.stringify({
23895
- general: handbook.general,
23896
- repo: handbook.repo,
23897
- generalSource: handbook.generalSource,
23898
- repoSource: handbook.repoSource,
23899
- repository: activation.repository.canonical
21656
+ requests: activation.manifest.requests.map((request) => ({
21657
+ id: request.id,
21658
+ body: request.requestBody
21659
+ }))
23900
21660
  }).replaceAll("<", "\\u003c");
23901
- lines.push("", "<collector_handbook>", payload, "</collector_handbook>");
21661
+ lines.push("", "<collector_request_manifest>", payload, "</collector_request_manifest>");
23902
21662
  }
23903
21663
  return lines.join("\n");
23904
21664
  }
23905
- function parsePositiveTicket(raw, label) {
23906
- if (raw === void 0 || raw === null) return void 0;
23907
- if (typeof raw === "number" && Number.isSafeInteger(raw) && raw >= 1) return raw;
23908
- if (typeof raw === "string" && /^[1-9]\d*$/.test(raw.trim())) {
23909
- const value = Number(raw.trim());
23910
- if (Number.isSafeInteger(value)) return value;
23911
- }
23912
- throw new CollectorTargetBindError(`\u901A\u8FDB\u53F8\u7ED1\u5B9A ${label} \u987B\u4E3A\u6B63\u5B89\u5168\u6574\u6570`);
23913
- }
23914
- function createCollectorRoleRuntime(pi, dependencies, hostActions) {
21665
+ function createCollectorRoleRuntime(pi, dependencies) {
23915
21666
  let toolsRegistered = false;
23916
21667
  return {
23917
- async activate(ctx) {
21668
+ async activate(_ctx) {
23918
21669
  const soul = (await dependencies.loadSoul()).trim();
23919
21670
  if (soul.length === 0) throw new Error("Collector soul is empty");
23920
21671
  const repoFlag = pi.getFlag("ak-collector-repo");
23921
21672
  const prFlag = pi.getFlag("ak-collector-pr");
23922
21673
  const requestManifestFlag = pi.getFlag("ak-collector-request-manifest");
23923
- const waitMsFlag = pi.getFlag("ak-collector-wait-ms");
23924
21674
  if (typeof repoFlag !== "string" || repoFlag.trim().length === 0) {
23925
21675
  throw new Error("Collector requires --ak-collector-repo");
23926
21676
  }
@@ -23932,36 +21682,11 @@ function createCollectorRoleRuntime(pi, dependencies, hostActions) {
23932
21682
  prNumber = parseCollectorPrNumber(prFlag);
23933
21683
  }
23934
21684
  const manifest = typeof requestManifestFlag === "string" && requestManifestFlag.trim().length > 0 ? await loadCollectorManifest(requestManifestFlag) : emptyCollectorManifest();
23935
- const waitWindowMs = parseWaitWindowMsFlag(waitMsFlag);
23936
- const clock = dependencies.createClock?.() ?? createSystemCollectorClock();
23937
- const transport = dependencies.createTransport();
23938
- const ledger = dependencies.createLedger(
23939
- { repository, prNumber, manifest, waitWindowMs },
23940
- clock,
23941
- ctx
23942
- );
23943
- const sessionPath = ctx.sessionManager?.getSessionFile?.() ?? ctx.sessionManager?.getSessionDir?.();
23944
- if (typeof sessionPath !== "string" || sessionPath.length === 0) {
23945
- throw new Error("\u901A\u8FDB\u53F8\u624B\u518C\u8981\u6C42 session \u8DEF\u5F84\u4F4D\u4E8E books/<bookKey>/");
23946
- }
23947
- const placement = resolveCollectorHandbookRoot(sessionPath);
23948
- const seedGeneral = dependencies.loadHandbookSeed === void 0 ? void 0 : (await dependencies.loadHandbookSeed()).trim();
23949
- const handbook = createCollectorHandbookStore({
23950
- ledgerHome: placement.ledgerHome,
23951
- handbookRoot: placement.root,
23952
- repositoryCanonical: repository.canonical,
23953
- ...seedGeneral === void 0 || seedGeneral.length === 0 ? {} : { seedGeneral }
23954
- });
23955
- const handbookView = await handbook.read();
23956
21685
  return {
23957
21686
  soul,
23958
21687
  repository,
23959
- manifest,
23960
- ledger,
23961
- transport,
23962
- clock,
23963
- handbook,
23964
- handbookView
21688
+ prNumber,
21689
+ manifest
23965
21690
  };
23966
21691
  },
23967
21692
  assembleMaterials(activation, baseSystemPrompt) {
@@ -23975,335 +21700,32 @@ function createCollectorRoleRuntime(pi, dependencies, hostActions) {
23975
21700
  buildMethodContext(activation)
23976
21701
  ].join("\n");
23977
21702
  },
23978
- onToolCall(activation, event) {
23979
- if (activation.ledger.fatal) {
21703
+ onToolCall(_activation, event) {
21704
+ if (COLLECTOR_CONSTRUCTION_TOOLS.includes(event.toolName)) {
23980
21705
  return {
23981
21706
  block: true,
23982
- reason: activation.ledger.fatalReason ?? "\u901A\u8FDB\u53F8\u81F4\u547D\u72B6\u6001"
21707
+ reason: `\u901A\u8FDB\u53F8\u4E3A\u6536\u8BC1\u5E2D\uFF0C\u7981\u7528\u65BD\u5DE5\u5DE5\u5177 ${event.toolName}`
23983
21708
  };
23984
21709
  }
23985
- if (event.toolName === COLLECTOR_OUTPUT_TOOL) {
23986
- activation.ledger.beginOperational(COLLECTOR_OUTPUT_TOOL, event.toolCallId);
23987
- }
23988
21710
  return void 0;
23989
21711
  },
23990
- onToolResult(activation, event) {
23991
- activation.ledger.completeOperational(event.toolCallId);
23992
- },
23993
21712
  registerBusinessTools(getActivation) {
23994
21713
  if (toolsRegistered) return;
23995
21714
  toolsRegistered = true;
23996
- pi.registerTool({
23997
- name: COLLECTOR_BIND_TARGET_TOOL,
23998
- label: "\u901A\u8FDB\u53F8\u8BA4\u7968\u7ED1\u5B9A",
23999
- description: "\u7ED1\u5B9A\u672C\u4ED3\u552F\u4E00 PR \u76EE\u6807\u3002",
24000
- promptSnippet: "\u7ED1\u5B9A\u89D2\u8272\u5224\u5B9A\u7684 issue/PR \u76EE\u6807",
24001
- parameters: bindSchema,
24002
- async execute(toolCallId, params, _signal, _onUpdate, ctx) {
24003
- const activation = getActivation();
24004
- if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
24005
- try {
24006
- activation.ledger.beginOperational(COLLECTOR_BIND_TARGET_TOOL, toolCallId);
24007
- const prNumber = parsePositiveTicket(params.prNumber, "prNumber");
24008
- const issueNumber = parsePositiveTicket(params.issueNumber, "issueNumber");
24009
- if (prNumber === void 0 && issueNumber === void 0) {
24010
- throw new CollectorTargetBindError(
24011
- "\u901A\u8FDB\u53F8\u7ED1\u5B9A\u987B\u7531\u89D2\u8272\u5224\u5B9A prNumber \u4E0E/\u6216 issueNumber"
24012
- );
24013
- }
24014
- let bound = prNumber;
24015
- let associated = [];
24016
- if (issueNumber !== void 0) {
24017
- associated = await listPullRequestNumbersByTicket(createGhApiRunner(), {
24018
- owner: activation.repository.owner,
24019
- repo: activation.repository.repo,
24020
- ticketNumber: issueNumber
24021
- });
24022
- if (bound === void 0 && associated.length === 1) {
24023
- bound = associated[0];
24024
- }
24025
- }
24026
- if (bound === void 0) {
24027
- return {
24028
- content: [{
24029
- type: "text",
24030
- text: JSON.stringify({
24031
- bound: false,
24032
- repository: activation.repository.canonical,
24033
- prNumber: prNumber ?? null,
24034
- issueNumber: issueNumber ?? null,
24035
- associated
24036
- })
24037
- }],
24038
- details: {
24039
- bound: false,
24040
- repository: activation.repository.canonical,
24041
- prNumber: prNumber ?? null,
24042
- issueNumber: issueNumber ?? null,
24043
- associated
24044
- }
24045
- };
24046
- }
24047
- activation.ledger.bindTarget(bound);
24048
- activation.ledger.completeOperational(toolCallId);
24049
- return {
24050
- content: [{
24051
- type: "text",
24052
- text: `\u76EE\u6807\u5DF2\u7ED1\u5B9A\uFF1A${activation.repository.canonical}#${bound}`
24053
- }],
24054
- details: {
24055
- bound: true,
24056
- repository: activation.repository.canonical,
24057
- prNumber: bound,
24058
- issueNumber: issueNumber ?? null,
24059
- associated
24060
- }
24061
- };
24062
- } catch (error) {
24063
- if (isCorrectableExecuteError(error)) throw error;
24064
- hostActions.failInfrastructure(error, ctx, toolCallId);
24065
- } finally {
24066
- try {
24067
- activation.ledger.completeOperational(toolCallId);
24068
- } catch {
24069
- }
24070
- }
24071
- }
24072
- });
24073
- pi.registerTool({
24074
- name: COLLECTOR_OBSERVE_TOOL,
24075
- label: "\u901A\u8FDB\u53F8\u89C2\u5BDF",
24076
- description: "\u6293\u53D6\u914D\u7F6E\u76EE\u6807\u7684 GitHub PR \u8BC1\u636E\u3002",
24077
- promptSnippet: "\u6293\u53D6\u914D\u7F6E\u76EE\u6807 PR \u8BC1\u636E",
24078
- parameters: observeSchema,
24079
- async execute(toolCallId, _params, signal, _onUpdate, ctx) {
24080
- const activation = getActivation();
24081
- if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
24082
- try {
24083
- activation.ledger.beginOperational(COLLECTOR_OBSERVE_TOOL, toolCallId);
24084
- const { snapshot, contextView } = await activation.ledger.observe(
24085
- activation.transport,
24086
- activation.clock,
24087
- signal
24088
- );
24089
- activation.ledger.completeOperational(toolCallId);
24090
- return {
24091
- content: [{
24092
- type: "text",
24093
- text: JSON.stringify(contextView)
24094
- }],
24095
- details: contextView
24096
- };
24097
- } catch (error) {
24098
- if (isCorrectableExecuteError(error)) throw error;
24099
- hostActions.failInfrastructure(error, ctx, toolCallId);
24100
- }
24101
- }
24102
- });
24103
- pi.registerTool({
24104
- name: COLLECTOR_READ_TOOL,
24105
- label: "\u901A\u8FDB\u53F8\u5F00\u5377",
24106
- description: "\u6309 evidenceId \u5F00\u5377\u8BFB\u53D6\u4E00\u6761\u5DF2\u89C2\u6D4B\u6750\u6599\u7684\u5168\u91CF\u6B63\u6587\u4E0E\u6307\u9488\u3002",
24107
- promptSnippet: "\u6309\u6307\u9488\u5F00\u5377\u8BFB\u6750\u6599",
24108
- parameters: readSchema,
24109
- async execute(toolCallId, params, _signal, _onUpdate, ctx) {
24110
- const activation = getActivation();
24111
- if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
24112
- try {
24113
- activation.ledger.beginOperational(COLLECTOR_READ_TOOL, toolCallId);
24114
- const record4 = activation.ledger.getEvidence(params.evidenceId);
24115
- if (record4 === void 0 || record4.kind !== "review" && record4.kind !== "issue_comment" && record4.kind !== "review_comment" && record4.kind !== "reaction" || typeof record4.body !== "string") {
24116
- throw new CollectorUnknownEvidenceError(params.evidenceId);
24117
- }
24118
- const material = projectEvidenceEntryView(record4);
24119
- activation.ledger.completeOperational(toolCallId);
24120
- return {
24121
- content: [{
24122
- type: "text",
24123
- text: JSON.stringify(material)
24124
- }],
24125
- details: material
24126
- };
24127
- } catch (error) {
24128
- if (isCorrectableExecuteError(error)) throw error;
24129
- hostActions.failInfrastructure(error, ctx, toolCallId);
24130
- }
24131
- }
24132
- });
24133
- pi.registerTool({
24134
- name: COLLECTOR_REQUEST_TOOL,
24135
- label: "\u901A\u8FDB\u53F8\u8BF7\u6C42",
24136
- description: "\u53D1\u4E00\u6B21\u8BF7\u6C42\u3002",
24137
- promptSnippet: "\u53D1\u4E00\u6B21\u8BC4\u5BA1\u8BF7\u6C42",
24138
- parameters: requestSchema,
24139
- async execute(toolCallId, params, signal, _onUpdate, ctx) {
24140
- const activation = getActivation();
24141
- if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
24142
- try {
24143
- activation.ledger.beginOperational(COLLECTOR_REQUEST_TOOL, toolCallId);
24144
- const details = await activation.ledger.request(
24145
- {
24146
- requestId: params.requestId,
24147
- snapshotId: params.snapshotId,
24148
- ...typeof params.body === "string" ? { body: params.body } : {}
24149
- },
24150
- activation.transport,
24151
- activation.clock,
24152
- signal
24153
- );
24154
- activation.ledger.completeOperational(toolCallId);
24155
- return {
24156
- content: [{
24157
- type: "text",
24158
- text: `\u8BF7\u6C42\u5C1D\u8BD5\u5DF2\u8BB0\u5F55\uFF1Arequest ${params.requestId}`
24159
- }],
24160
- details
24161
- };
24162
- } catch (error) {
24163
- if (isCorrectableExecuteError(error)) throw error;
24164
- hostActions.failInfrastructure(error, ctx, toolCallId);
24165
- }
24166
- }
24167
- });
24168
- pi.registerTool({
24169
- name: COLLECTOR_HANDBOOK_WRITE_TOOL,
24170
- label: "\u901A\u8FDB\u53F8\u624B\u518C\u5199\u5165",
24171
- description: "\u5199\u5165\u901A\u7528\u624B\u518C\u6216\u5F53\u524D\u4ED3\u5E93\u5DEE\u5F02\u5168\u6587\uFF08\u6574\u4EFD\u66FF\u6362\uFF09\u3002",
24172
- promptSnippet: "\u66F4\u65B0 bot \u624B\u518C",
24173
- parameters: handbookWriteSchema,
24174
- async execute(toolCallId, params, _signal, _onUpdate, ctx) {
24175
- const activation = getActivation();
24176
- if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
24177
- try {
24178
- activation.ledger.beginOperational(COLLECTOR_HANDBOOK_WRITE_TOOL, toolCallId);
24179
- const details = await activation.handbook.write(params.scope, params.body);
24180
- activation.handbookView = await activation.handbook.read();
24181
- activation.ledger.completeOperational(toolCallId);
24182
- return {
24183
- content: [{
24184
- type: "text",
24185
- text: `\u624B\u518C\u5DF2\u5199\u5165\uFF1A${details.scope}`
24186
- }],
24187
- details: {
24188
- scope: details.scope,
24189
- path: details.path,
24190
- byteLength: details.byteLength,
24191
- generalSource: activation.handbookView.generalSource,
24192
- repoSource: activation.handbookView.repoSource
24193
- }
24194
- };
24195
- } catch (error) {
24196
- if (isCorrectableExecuteError(error)) throw error;
24197
- hostActions.failInfrastructure(error, ctx, toolCallId);
24198
- } finally {
24199
- try {
24200
- activation.ledger.completeOperational(toolCallId);
24201
- } catch {
24202
- }
24203
- }
24204
- }
24205
- });
24206
- pi.registerTool({
24207
- name: COLLECTOR_OPEN_WAIT_WINDOW_TOOL,
24208
- label: "\u901A\u8FDB\u53F8\u5F00\u542F\u7B49\u5F85\u7A97",
24209
- 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",
24210
- promptSnippet: "\u6309\u5DE5\u4F5C\u6B65\u9AA4\u5F00\u542F\u7B49\u5F85\u7A97",
24211
- parameters: openWaitWindowSchema,
24212
- async execute(toolCallId, params, _signal, _onUpdate, ctx) {
24213
- const activation = getActivation();
24214
- if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
24215
- try {
24216
- activation.ledger.beginOperational(COLLECTOR_OPEN_WAIT_WINDOW_TOOL, toolCallId);
24217
- let startedAt;
24218
- if (typeof params.startedAt === "string" && params.startedAt.trim().length > 0) {
24219
- const parsed = new Date(params.startedAt);
24220
- if (Number.isNaN(parsed.getTime())) {
24221
- throw new Error("\u901A\u8FDB\u53F8\u7B49\u5F85\u7A97 startedAt \u987B\u4E3A\u6709\u6548 ISO \u65F6\u95F4");
24222
- }
24223
- startedAt = parsed;
24224
- }
24225
- activation.ledger.openWaitWindow(
24226
- activation.clock,
24227
- startedAt === void 0 ? void 0 : { startedAt }
24228
- );
24229
- activation.ledger.completeOperational(toolCallId);
24230
- return {
24231
- content: [{
24232
- type: "text",
24233
- text: "\u7B49\u5F85\u7A97\u5DF2\u5F00\u542F"
24234
- }],
24235
- details: {
24236
- activationTime: activation.ledger.activationTime?.toISOString(),
24237
- deadlineTime: activation.ledger.deadlineTime?.toISOString(),
24238
- waitWindowMs: activation.ledger.config.waitWindowMs
24239
- }
24240
- };
24241
- } catch (error) {
24242
- if (isCorrectableExecuteError(error)) throw error;
24243
- hostActions.failInfrastructure(error, ctx, toolCallId);
24244
- } finally {
24245
- try {
24246
- activation.ledger.completeOperational(toolCallId);
24247
- } catch {
24248
- }
24249
- }
24250
- }
24251
- });
24252
- pi.registerTool({
24253
- name: COLLECTOR_WAIT_TOOL,
24254
- label: "\u901A\u8FDB\u53F8\u7B49\u5F85",
24255
- description: "\u7B49\u5F85\u3002\u5B9E\u9645\u7761\u7720\u4E0D\u8D85\u8FC7\u5269\u4F59\u7B49\u5F85\u7A97\u3002",
24256
- promptSnippet: "\u7B49\u5F85\u7A97\u5185\u7B49\u5F85",
24257
- parameters: waitSchema,
24258
- async execute(toolCallId, params, signal, _onUpdate, ctx) {
24259
- const activation = getActivation();
24260
- if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
24261
- try {
24262
- activation.ledger.beginOperational(COLLECTOR_WAIT_TOOL, toolCallId);
24263
- const details = await activation.ledger.wait(
24264
- params,
24265
- activation.clock,
24266
- signal
24267
- );
24268
- activation.ledger.completeOperational(toolCallId);
24269
- return {
24270
- content: [{
24271
- type: "text",
24272
- text: `\u5DF2\u7B49\u5F85 ${String(details.effectiveMs)}ms`
24273
- }],
24274
- details
24275
- };
24276
- } catch (error) {
24277
- if (isCorrectableExecuteError(error)) throw error;
24278
- hostActions.failInfrastructure(error, ctx, toolCallId);
24279
- }
24280
- }
24281
- });
24282
21715
  pi.registerTool({
24283
21716
  name: COLLECTOR_OUTPUT_TOOL,
24284
21717
  label: "\u901A\u8FDB\u53F8\u8F93\u51FA",
24285
21718
  description: "\u63D0\u4EA4\u901A\u8FDB\u53F8\u56DE\u6267\u3002",
24286
21719
  promptSnippet: "\u63D0\u4EA4\u901A\u8FDB\u53F8\u56DE\u6267",
24287
21720
  parameters: outputSchema,
24288
- async execute(toolCallId, params, _signal, _onUpdate, ctx) {
21721
+ async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
24289
21722
  const activation = getActivation();
24290
21723
  if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
24291
- try {
24292
- activation.ledger.beginOperational(COLLECTOR_OUTPUT_TOOL, toolCallId);
24293
- activation.ledger.recordOutputCandidate();
24294
- return {
24295
- content: [],
24296
- details: params,
24297
- terminate: true
24298
- };
24299
- } catch (error) {
24300
- if (error instanceof Error && error.collectorFatal === true) {
24301
- hostActions.failInfrastructure(error, ctx, toolCallId);
24302
- }
24303
- throw error;
24304
- } finally {
24305
- activation.ledger.completeOperational(toolCallId);
24306
- }
21724
+ return {
21725
+ content: [],
21726
+ details: params,
21727
+ terminate: true
21728
+ };
24307
21729
  }
24308
21730
  });
24309
21731
  }
@@ -24740,7 +22162,7 @@ var AUDITOR_TOOL_SPEC = {
24740
22162
  };
24741
22163
 
24742
22164
  // src/navigator-attendance.ts
24743
- import { createHash as createHash7 } from "node:crypto";
22165
+ import { createHash as createHash5 } from "node:crypto";
24744
22166
  init_navigator_invocation_identity();
24745
22167
  init_packaged_role_registry();
24746
22168
  init_activation_ledger_topology();
@@ -24945,11 +22367,11 @@ init_packaged_role_registry();
24945
22367
  // src/navigator-work-base.ts
24946
22368
  init_atomic_write();
24947
22369
  import { existsSync as existsSync10, realpathSync as realpathSync3 } from "node:fs";
24948
- import { readFile as readFile23 } from "node:fs/promises";
24949
- import { basename as basename10, dirname as dirname22, join as join41, resolve as resolve16 } from "node:path";
22370
+ import { readFile as readFile22 } from "node:fs/promises";
22371
+ import { basename as basename10, dirname as dirname22, join as join40, resolve as resolve16 } from "node:path";
24950
22372
  var NAVIGATOR_WORK_CONTEXT_BASENAME = "work-context.json";
24951
22373
  function navigatorWorkContextFile(sessionDir) {
24952
- return join41(sessionDir, NAVIGATOR_WORK_CONTEXT_BASENAME);
22374
+ return join40(sessionDir, NAVIGATOR_WORK_CONTEXT_BASENAME);
24953
22375
  }
24954
22376
  function isNavigatorWorkContextFile(path) {
24955
22377
  const resolved = resolve16(path);
@@ -24974,7 +22396,7 @@ async function persistNavigatorWorkBase(sessionDir, body) {
24974
22396
  const next = `${JSON.stringify({ subject: body.subject, authority: body.authority })}
24975
22397
  `;
24976
22398
  try {
24977
- const current = await readFile23(path, "utf8");
22399
+ const current = await readFile22(path, "utf8");
24978
22400
  if (current === next) return path;
24979
22401
  } catch (error) {
24980
22402
  if (!(error instanceof Error && "code" in error && error.code === "ENOENT")) {
@@ -24989,7 +22411,7 @@ async function readNavigatorWorkBase(path) {
24989
22411
  if (canonical === void 0) return void 0;
24990
22412
  let text;
24991
22413
  try {
24992
- text = await readFile23(canonical, "utf8");
22414
+ text = await readFile22(canonical, "utf8");
24993
22415
  } catch (error) {
24994
22416
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
24995
22417
  return void 0;
@@ -25301,7 +22723,7 @@ function navigatorSubjectKey(subjectRoot, subject, provenance = "role_input") {
25301
22723
  if (provenance === "placeholder") return subjectRoot;
25302
22724
  const normalized = subject.trim().replace(/\s+/g, " ");
25303
22725
  if (normalized === "") return subjectRoot;
25304
- return `${subjectRoot}#${createHash7("sha256").update(normalized).digest("hex").slice(0, 32)}`;
22726
+ return `${subjectRoot}#${createHash5("sha256").update(normalized).digest("hex").slice(0, 32)}`;
25305
22727
  }
25306
22728
  function navigatorSubjectKeyForInput(subjectRoot, reference, cwd = process.cwd()) {
25307
22729
  if (issueRoot(subjectRoot) !== void 0 || !subjectRoot.includes("/.ak/work/")) return subjectRoot;
@@ -25789,7 +23211,7 @@ init_submission_errors();
25789
23211
  init_worker_submission_contracts();
25790
23212
  init_submission_errors();
25791
23213
  init_worker_submission_contracts();
25792
- import { execFileSync as execFileSync4 } from "node:child_process";
23214
+ import { execFileSync as execFileSync3 } from "node:child_process";
25793
23215
  import { existsSync as existsSync14, lstatSync as lstatSync3, readdirSync as readdirSync4, readFileSync as readFileSync5, rmdirSync, rmSync as rmSync2 } from "node:fs";
25794
23216
  import { resolve as resolve19 } from "node:path";
25795
23217
  var WORKER_SUBMISSION_GATE_RECORD_KIND = WORKER_SUBMISSION_GATE_KIND;
@@ -25802,7 +23224,7 @@ var HOOK_FILE = "reference-transaction";
25802
23224
  var PLATFORM_PREFIX = /^[A-Za-z][A-Za-z0-9_-]*:/;
25803
23225
  var UNFINISHED_REASON_BOUNCE_LIMIT = 2;
25804
23226
  function git2(cwd, args) {
25805
- return execFileSync4("git", args, {
23227
+ return execFileSync3("git", args, {
25806
23228
  cwd,
25807
23229
  encoding: "utf8",
25808
23230
  stdio: ["ignore", "pipe", "pipe"],
@@ -25810,7 +23232,7 @@ function git2(cwd, args) {
25810
23232
  }).trim();
25811
23233
  }
25812
23234
  function gitFile(file, args) {
25813
- return execFileSync4("git", ["config", "--file", file, ...args], {
23235
+ return execFileSync3("git", ["config", "--file", file, ...args], {
25814
23236
  encoding: "utf8",
25815
23237
  stdio: ["ignore", "pipe", "pipe"],
25816
23238
  env: { ...process.env, GIT_DIR: void 0, GIT_WORK_TREE: void 0, GIT_COMMON_DIR: void 0 }
@@ -25886,7 +23308,7 @@ function uninstallPackageWorkerHooks(cwd) {
25886
23308
  rmOwnedDir(resolve19(gitDir, HOOKS_DIR));
25887
23309
  }
25888
23310
  }
25889
- function isRecord16(value) {
23311
+ function isRecord15(value) {
25890
23312
  return typeof value === "object" && value !== null && !Array.isArray(value);
25891
23313
  }
25892
23314
  function unfinishedReasonPresent(details) {
@@ -25902,7 +23324,7 @@ function readGateState(session) {
25902
23324
  if (entry.type !== "custom") continue;
25903
23325
  if (entry.customType === WORKER_COMMIT_BASELINE_ENTRY_TYPE) {
25904
23326
  const data = entry.data;
25905
- if (isRecord16(data) && (data.head === null || typeof data.head === "string")) {
23327
+ if (isRecord15(data) && (data.head === null || typeof data.head === "string")) {
25906
23328
  baseline = data.head;
25907
23329
  }
25908
23330
  } else if (entry.customType === WORKER_COMMIT_REMINDER_BOUNCE_ENTRY_TYPE) {
@@ -25928,11 +23350,11 @@ function reliableWindow(cwd, baseline, head) {
25928
23350
  const raw = git2(cwd, ["log", "--format=%P%x1e%s", range]);
25929
23351
  if (raw.length === 0) return [];
25930
23352
  return raw.split("\n").flatMap((line2) => {
25931
- const sep7 = line2.indexOf("");
25932
- if (sep7 < 0) return [];
23353
+ const sep6 = line2.indexOf("");
23354
+ if (sep6 < 0) return [];
25933
23355
  return [{
25934
- subject: line2.slice(sep7 + 1),
25935
- merge: line2.slice(0, sep7).trim().includes(" ")
23356
+ subject: line2.slice(sep6 + 1),
23357
+ merge: line2.slice(0, sep6).trim().includes(" ")
25936
23358
  }];
25937
23359
  });
25938
23360
  }
@@ -26095,11 +23517,11 @@ var FIXER_PHASES = ["plan", "apply"];
26095
23517
  function isWorkerPhase(value) {
26096
23518
  return typeof value === "string" && FIXER_PHASES.includes(value);
26097
23519
  }
26098
- function isRecord17(value) {
23520
+ function isRecord16(value) {
26099
23521
  return typeof value === "object" && value !== null && !Array.isArray(value);
26100
23522
  }
26101
23523
  function workerStatusOf(output) {
26102
- return isRecord17(output) && typeof output.status === "string" ? output.status : void 0;
23524
+ return isRecord16(output) && typeof output.status === "string" ? output.status : void 0;
26103
23525
  }
26104
23526
  function deepFreeze2(value) {
26105
23527
  if (typeof value !== "object" || value === null || Object.isFrozen(value)) return value;
@@ -26785,7 +24207,7 @@ function readDiaristTicketAssertion(submitted) {
26785
24207
  function readRoleRunCoordinates(ctx, label) {
26786
24208
  const runDirectory = runDirectoryFromHostContext(ctx);
26787
24209
  if (runDirectory === void 0) throw new Error(`${label} requires AK_ROLE_RUN_DIR`);
26788
- const admittedPath = join45(runDirectory, "admitted-request.json");
24210
+ const admittedPath = join44(runDirectory, "admitted-request.json");
26789
24211
  const admitted = JSON.parse(readFileSync6(admittedPath, "utf8"));
26790
24212
  if (typeof admitted.projectRoot !== "string" || admitted.projectRoot.trim() === "") {
26791
24213
  throw new Error(`${label} admitted-request missing projectRoot (${admittedPath})`);
@@ -27097,10 +24519,6 @@ function createRoleRuntimeExtension(dependencies) {
27097
24519
  };
27098
24520
  }
27099
24521
  if (activeCollector !== void 0 && selectedRole === role) {
27100
- if (!collectorFirstDispatchDone) {
27101
- collectorFirstDispatchDone = true;
27102
- activeCollector.ledger.recordActivation(activeCollector.clock);
27103
- }
27104
24522
  return {
27105
24523
  systemPrompt: collectorBusiness.assembleMaterials(activeCollector, event.systemPrompt)
27106
24524
  };
@@ -27141,9 +24559,6 @@ function createRoleRuntimeExtension(dependencies) {
27141
24559
  roleHost.on("tool_result", async (event) => {
27142
24560
  const role = selectedRole;
27143
24561
  if (role === void 0) return;
27144
- if (activeCollector !== void 0 && selectedRole === roleHost.getFlag(ROLE_FLAG.name)) {
27145
- collectorBusiness.onToolResult(activeCollector, event);
27146
- }
27147
24562
  const pendingInfra = pendingInfrastructureFailures.get(event.toolCallId);
27148
24563
  const isRoleInfrastructureFailure = pendingInfra !== void 0;
27149
24564
  if (pendingInfra !== void 0) pendingInfrastructureFailures.delete(event.toolCallId);
@@ -27278,11 +24693,6 @@ function createRoleRuntimeExtension(dependencies) {
27278
24693
  priorFetch = void 0;
27279
24694
  fetchWrapped = false;
27280
24695
  }
27281
- if (activeCollector !== void 0 && activeCollector.ledger.fatal) {
27282
- if (process.exitCode === void 0 || process.exitCode === 0) {
27283
- process.exitCode = 1;
27284
- }
27285
- }
27286
24696
  const presentation = pendingNavigatorPresentation;
27287
24697
  pendingNavigatorPresentation = void 0;
27288
24698
  if (presentation !== void 0) {
@@ -27414,41 +24824,16 @@ function createRoleRuntimeExtension(dependencies) {
27414
24824
  }
27415
24825
  });
27416
24826
  let activeCollector;
27417
- let collectorFirstDispatchDone = false;
27418
24827
  const collectorBusiness = createCollectorRoleRuntime(
27419
24828
  roleHost,
27420
24829
  {
27421
- loadSoul: () => requireRoleSoul("collector"),
27422
- createTransport() {
27423
- if (dependencies.createCollectorTransport === void 0) {
27424
- throw new Error("Collector GitHub transport is not configured");
27425
- }
27426
- return dependencies.createCollectorTransport();
27427
- },
27428
- createLedger(config, collectorClock, context) {
27429
- const append = context.sessionManager?.appendCustomEntry;
27430
- return createCollectorLedger(config, {
27431
- clock: collectorClock,
27432
- ...append === void 0 ? {} : {
27433
- journal: {
27434
- append(customType, data) {
27435
- context.sessionManager?.appendCustomEntry?.(customType, data);
27436
- }
27437
- }
27438
- },
27439
- dossierEntries: context.sessionManager?.getEntries?.() ?? []
27440
- });
27441
- },
27442
- ...dependencies.createCollectorClock === void 0 ? {} : { createClock: dependencies.createCollectorClock },
27443
- ...dependencies.loadCollectorHandbookSeed === void 0 ? {} : { loadHandbookSeed: dependencies.loadCollectorHandbookSeed }
27444
- },
27445
- hostActions
24830
+ loadSoul: () => requireRoleSoul("collector")
24831
+ }
27446
24832
  );
27447
24833
  let collectorToolCallRegistered = false;
27448
24834
  const collector = {
27449
24835
  async activate(context, event) {
27450
24836
  activeCollector = void 0;
27451
- collectorFirstDispatchDone = false;
27452
24837
  if (context.mode !== "print" && context.mode !== "json") {
27453
24838
  throw new Error(
27454
24839
  `Collector supports only print or json mode (got ${context.mode})`
@@ -27482,16 +24867,19 @@ function createRoleRuntimeExtension(dependencies) {
27482
24867
  throw new Error(`Collector required tool name collision: ${required}`);
27483
24868
  }
27484
24869
  }
27485
- roleHost.setActiveTools([...COLLECTOR_REQUIRED_TOOLS]);
24870
+ const priorActive = roleHost.getActiveTools();
24871
+ const hostSurface = (priorActive.length > 0 ? priorActive : allTools.map((tool) => tool.name)).filter((name) => !COLLECTOR_CONSTRUCTION_TOOLS.includes(name));
24872
+ const nextActive = [.../* @__PURE__ */ new Set([...hostSurface, ...COLLECTOR_REQUIRED_TOOLS])];
24873
+ roleHost.setActiveTools(nextActive);
27486
24874
  const active = new Set(roleHost.getActiveTools());
27487
24875
  for (const required of COLLECTOR_REQUIRED_TOOLS) {
27488
24876
  if (!active.has(required)) {
27489
24877
  throw new Error(`Collector failed to activate required tool ${required}`);
27490
24878
  }
27491
24879
  }
27492
- for (const name of active) {
27493
- if (!COLLECTOR_REQUIRED_TOOLS.includes(name)) {
27494
- throw new Error(`Collector active tool surface includes unexpected ${name}`);
24880
+ for (const name of COLLECTOR_CONSTRUCTION_TOOLS) {
24881
+ if (active.has(name)) {
24882
+ throw new Error(`Collector must not activate construction tool ${name}`);
27495
24883
  }
27496
24884
  }
27497
24885
  if (!collectorToolCallRegistered) {
@@ -27499,20 +24887,10 @@ function createRoleRuntimeExtension(dependencies) {
27499
24887
  roleHost.on("tool_call", (toolEvent) => {
27500
24888
  const liveRole = roleHost.getFlag(ROLE_FLAG.name);
27501
24889
  if (activeCollector === void 0 || selectedRole === void 0 || selectedRole !== liveRole) return;
27502
- if (!COLLECTOR_REQUIRED_TOOLS.includes(toolEvent.toolName)) {
27503
- return {
27504
- block: true,
27505
- reason: `\u901A\u8FDB\u53F8\u7981\u7528\u5DE5\u5177 ${toolEvent.toolName}`
27506
- };
27507
- }
27508
24890
  return collectorBusiness.onToolCall(activeCollector, toolEvent);
27509
24891
  });
27510
24892
  }
27511
- const activation = await collectorBusiness.activate(context);
27512
- if (activation.ledger.activationRecorded) {
27513
- collectorFirstDispatchDone = true;
27514
- }
27515
- activeCollector = activation;
24893
+ activeCollector = await collectorBusiness.activate(context);
27516
24894
  }
27517
24895
  };
27518
24896
  const clock = dependencies.activationClock ?? (() => (/* @__PURE__ */ new Date()).toISOString());
@@ -27562,7 +24940,6 @@ function createRoleRuntimeExtension(dependencies) {
27562
24940
  roleReferenceMaterials = "";
27563
24941
  activeReviewerParent = void 0;
27564
24942
  activeCollector = void 0;
27565
- collectorFirstDispatchDone = false;
27566
24943
  receiptDelivery = createReceiptDeliveryPolicy();
27567
24944
  noReceiptRecorded = false;
27568
24945
  pendingNavigatorPresentation = void 0;
@@ -27745,7 +25122,7 @@ async function prepareRoleEnvelope(options) {
27745
25122
  const hostAbort = new AbortController();
27746
25123
  const runId = request.runDirectory.split("/").filter(Boolean).at(-1) ?? randomUUID9();
27747
25124
  await mkdir5(request.runDirectory, { recursive: true });
27748
- let sessionFile = options.sessionFile ?? join46(request.runDirectory, "session", "session.jsonl");
25125
+ let sessionFile = options.sessionFile ?? join45(request.runDirectory, "session", "session.jsonl");
27749
25126
  await mkdir5(dirname25(sessionFile), { recursive: true });
27750
25127
  if (request.continuation.kind !== "resume") {
27751
25128
  try {
@@ -28262,15 +25639,13 @@ async function prepareRoleEnvelope(options) {
28262
25639
  }
28263
25640
 
28264
25641
  // src/role-runtime-dependencies.ts
28265
- init_collector_github();
25642
+ import { readFile as readFile24 } from "node:fs/promises";
28266
25643
  init_doctor_evidence();
28267
- import { readFile as readFile25 } from "node:fs/promises";
28268
- import { join as join47 } from "node:path";
28269
25644
 
28270
25645
  // src/navigator-work-context.ts
28271
25646
  init_doctor_evidence();
28272
25647
  init_host_contracts();
28273
- import { readFile as readFile24 } from "node:fs/promises";
25648
+ import { readFile as readFile23 } from "node:fs/promises";
28274
25649
  import { resolve as resolve20 } from "node:path";
28275
25650
  init_notary_source_run();
28276
25651
  init_packaged_role_registry();
@@ -28284,7 +25659,7 @@ function navigatorInputReference(getFlag, role) {
28284
25659
  async function loadNavigatorWorkContext(options) {
28285
25660
  const reference = navigatorInputReference(options.getFlag, options.role);
28286
25661
  const subjectMode = packagedNavigatorSubject(options.role);
28287
- const input = reference === void 0 || subjectMode === "case" || subjectMode === "source-run" ? void 0 : await readFile24(reference, "utf8");
25662
+ const input = reference === void 0 || subjectMode === "case" || subjectMode === "source-run" ? void 0 : await readFile23(reference, "utf8");
28288
25663
  const subjectRoot = subjectPath(reference ?? options.context.sessionManager.getSessionDir(), options.context.cwd);
28289
25664
  let subjectKey = reference === void 0 ? subjectRoot : navigatorSubjectKeyForInput(subjectRoot, reference, options.context.cwd);
28290
25665
  let subject = input ?? `work subject: ${subjectKey}`;
@@ -28341,7 +25716,7 @@ async function loadNavigatorWorkContext(options) {
28341
25716
  let authorityMaterial;
28342
25717
  for (const path of authorityFiles) {
28343
25718
  try {
28344
- const content = await readFile24(path, "utf8");
25719
+ const content = await readFile23(path, "utf8");
28345
25720
  if (content.trim() !== "") {
28346
25721
  authorityMaterial = content;
28347
25722
  break;
@@ -28378,19 +25753,16 @@ function loadRegisteredRoleSoul(role) {
28378
25753
  return usesSubjectSoul(role) ? loadAuditorSoulFromSubjectInput() : loadMainRoleSessionMaterials(role);
28379
25754
  }
28380
25755
  function createRoleRuntimeDependencies(packageRoot) {
28381
- const collectorHandbookSeedPath = join47(packageRoot, "resources/collector-bot-handbook.md");
28382
25756
  const navigatorSessionFactory = createNativeNavigatorSessionFactory();
28383
25757
  return {
28384
25758
  packageRoot,
28385
25759
  loadRoleReferenceMaterials: loadPackagedRoleReferenceMaterials,
28386
25760
  loadRoleSoul: loadRegisteredRoleSoul,
28387
- loadFixPacket: (path) => readFile25(path, "utf8"),
28388
- loadCoderTask: (path) => readFile25(path, "utf8"),
28389
- loadCollectorHandbookSeed: () => readFile25(collectorHandbookSeedPath, "utf8"),
28390
- createCollectorTransport: () => createGhCollectorGitHubTransport(),
25761
+ loadFixPacket: (path) => readFile24(path, "utf8"),
25762
+ loadCoderTask: (path) => readFile24(path, "utf8"),
28391
25763
  loadDoctorCase,
28392
25764
  loadNotarySourceRun: loadNotarySourceRunLocator,
28393
- loadMergerInput: async (path) => JSON.parse(await readFile25(path, "utf8")),
25765
+ loadMergerInput: async (path) => JSON.parse(await readFile24(path, "utf8")),
28394
25766
  loadNavigatorWorkContext: (options) => loadNavigatorWorkContext({
28395
25767
  context: options.context,
28396
25768
  role: options.role,
@@ -28415,9 +25787,9 @@ function createRoleRuntimeDependencies(packageRoot) {
28415
25787
  init_session_identity();
28416
25788
 
28417
25789
  // src/acp-host/description.ts
28418
- import { join as join48 } from "node:path";
25790
+ import { join as join46 } from "node:path";
28419
25791
  function resolveAcpBinary(description, operatorHome) {
28420
- return join48(operatorHome, ...description.binaryFromHome);
25792
+ return join46(operatorHome, ...description.binaryFromHome);
28421
25793
  }
28422
25794
  function acpStdioArgs(description, model, seat) {
28423
25795
  const { prefix, suffix, modelFlag, thinkingFlag } = description.argv;
@@ -28436,8 +25808,8 @@ function acpModelId(modelPassing, model) {
28436
25808
  }
28437
25809
 
28438
25810
  // src/acp-host/role-turn-host.ts
28439
- import { join as join49 } from "node:path";
28440
- import { spawn as spawn4 } from "node:child_process";
25811
+ import { join as join47 } from "node:path";
25812
+ import { spawn as spawn3 } from "node:child_process";
28441
25813
  import { createInterface } from "node:readline";
28442
25814
 
28443
25815
  // src/external-host-turn-loop.ts
@@ -28620,7 +25992,7 @@ function acpError(code, message, cause) {
28620
25992
  return Object.assign(new Error(message, cause === void 0 ? void 0 : { cause }), { code });
28621
25993
  }
28622
25994
  function connectAcpStdio(options) {
28623
- const child = spawn4(options.binary, [...options.args], { cwd: options.cwd, env: options.env, stdio: ["pipe", "pipe", "pipe"] });
25995
+ const child = spawn3(options.binary, [...options.args], { cwd: options.cwd, env: options.env, stdio: ["pipe", "pipe", "pipe"] });
28624
25996
  const pending = /* @__PURE__ */ new Map();
28625
25997
  const notificationHandlers = [];
28626
25998
  if (options.onNotification !== void 0) notificationHandlers.push(options.onNotification);
@@ -28883,7 +26255,7 @@ function createAcpRoleTurnHost(config) {
28883
26255
  host: config.hostName,
28884
26256
  sessionId,
28885
26257
  cwd: request.cwd,
28886
- sessionDirectory: join49(request.runDirectory, "session"),
26258
+ sessionDirectory: join47(request.runDirectory, "session"),
28887
26259
  sessionParent,
28888
26260
  continuation: request.continuation,
28889
26261
  ...request.model !== void 0 ? { model: request.model } : {},
@@ -28903,12 +26275,12 @@ function createAcpRoleTurnHost(config) {
28903
26275
  // src/acp-host/seat-profile-soul.ts
28904
26276
  import { constants as constants3 } from "node:fs";
28905
26277
  import { access as access3, copyFile, lstat as lstat8, mkdir as mkdir6, readlink, symlink as symlink2, unlink as unlink6 } from "node:fs/promises";
28906
- import { dirname as dirname26, join as join50, relative as relative3, resolve as resolve21 } from "node:path";
26278
+ import { dirname as dirname26, join as join48, relative as relative3, resolve as resolve21 } from "node:path";
28907
26279
  function seatProfileName(spec, role) {
28908
26280
  return `${spec.namePrefix}${role}`;
28909
26281
  }
28910
26282
  function packageRoleSoulPath(packageRoot, role) {
28911
- return join50(packageRoot, "souls", `${role}.md`);
26283
+ return join48(packageRoot, "souls", `${role}.md`);
28912
26284
  }
28913
26285
  async function pathExists2(path) {
28914
26286
  try {
@@ -28925,16 +26297,16 @@ async function ensureSeatProfileSoul(options) {
28925
26297
  if (!await pathExists2(soulTarget)) {
28926
26298
  throw new Error(`packaged role soul missing: ${soulTarget}`);
28927
26299
  }
28928
- const profilesRoot = join50(operatorHome, ...spec.profilesRootFromHome);
28929
- const profileDir = join50(profilesRoot, profileName);
26300
+ const profilesRoot = join48(operatorHome, ...spec.profilesRootFromHome);
26301
+ const profileDir = join48(profilesRoot, profileName);
28930
26302
  const hostRoot = dirname26(profilesRoot);
28931
- const soulPath = join50(profileDir, spec.soulFileName);
26303
+ const soulPath = join48(profileDir, spec.soulFileName);
28932
26304
  if (!await pathExists2(profileDir)) {
28933
26305
  await mkdir6(profileDir, { recursive: true });
28934
26306
  for (const name of ["auth.json", ".env", "config.yaml"]) {
28935
- const source = join50(hostRoot, name);
26307
+ const source = join48(hostRoot, name);
28936
26308
  if (!await pathExists2(source)) continue;
28937
- await copyFile(source, join50(profileDir, name));
26309
+ await copyFile(source, join48(profileDir, name));
28938
26310
  }
28939
26311
  } else {
28940
26312
  await mkdir6(profileDir, { recursive: true });