@akagilnc/pi-workflow-roles 0.1.3783 → 0.1.3789

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.
@@ -883,10 +883,10 @@ __export(session_assistant_usage_exports, {
883
883
  });
884
884
  import { join as join2 } from "node:path";
885
885
  async function readAssistantUsageFromSessionFile(sessionFile) {
886
- const { readFile: readFile21 } = await import("node:fs/promises");
886
+ const { readFile: readFile22 } = await import("node:fs/promises");
887
887
  let text;
888
888
  try {
889
- text = await readFile21(sessionFile, "utf8");
889
+ text = await readFile22(sessionFile, "utf8");
890
890
  } catch (error) {
891
891
  if (error?.code === "ENOENT") return void 0;
892
892
  throw error;
@@ -6085,8 +6085,8 @@ var init_option_definitions = __esm({
6085
6085
  repeatable: false,
6086
6086
  form: "option",
6087
6087
  description: {
6088
- en: "Optional request manifest JSON path ({requests:[{id,body}]}).",
6089
- zh: "\u53EF\u9009 request manifest JSON \u8DEF\u5F84\uFF08{requests:[{id,body}]}\uFF09\u3002"
6088
+ en: "Optional request manifest JSON path ({requests:[{id,body}]}). Role may also decide request bodies from handbook/field activity without this file.",
6089
+ 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"
6090
6090
  }
6091
6091
  }
6092
6092
  ];
@@ -8518,11 +8518,11 @@ function parseAnalystCohortIssueToken(raw, flag) {
8518
8518
  `${flag} requires a comma-separated list of N or book:N`
8519
8519
  );
8520
8520
  }
8521
- const sep4 = trimmed.lastIndexOf(":");
8522
- if (sep4 > 0) {
8523
- const rhs = trimmed.slice(sep4 + 1);
8521
+ const sep5 = trimmed.lastIndexOf(":");
8522
+ if (sep5 > 0) {
8523
+ const rhs = trimmed.slice(sep5 + 1);
8524
8524
  if (ANALYST_TICKET_NUMBER_PATTERN.test(rhs)) {
8525
- const bookKey = trimmed.slice(0, sep4);
8525
+ const bookKey = trimmed.slice(0, sep5);
8526
8526
  if (bookKey.trim() === "") {
8527
8527
  throw new CliUsageError(
8528
8528
  `${flag} book:N requires a non-empty book key, got ${raw}`
@@ -11011,10 +11011,10 @@ function pairGateRounds(volumes) {
11011
11011
  return rounds.sort((a, b) => a.officerStartedAt.localeCompare(b.officerStartedAt)).map((round, index) => ({ ...round, roundIndex: index + 1 }));
11012
11012
  }
11013
11013
  async function resolveOfficerSessionFromPointerFile(pointerPath) {
11014
- const { readFile: readFile21 } = await import("node:fs/promises");
11014
+ const { readFile: readFile22 } = await import("node:fs/promises");
11015
11015
  let raw;
11016
11016
  try {
11017
- raw = JSON.parse(await readFile21(pointerPath, "utf8"));
11017
+ raw = JSON.parse(await readFile22(pointerPath, "utf8"));
11018
11018
  } catch (error) {
11019
11019
  throw new Error(
11020
11020
  `direct officer run pointer unreadable in ${pointerPath}: ${error instanceof Error ? error.message : String(error)}`,
@@ -12504,76 +12504,7 @@ var init_collector_identity = __esm({
12504
12504
  }
12505
12505
  });
12506
12506
 
12507
- // src/collector-tool-schemas.ts
12508
- import { Type as Type13 } from "typebox";
12509
- var collectorObserveArgsSchema, collectorRequestArgsSchema, collectorReadArgsSchema, collectorWaitArgsSchema, collectorBindTargetArgsSchema, collectorFindingItemDeclaration, collectorOutputBaseSchema, collectorOutputArgsSchema;
12510
- var init_collector_tool_schemas = __esm({
12511
- "src/collector-tool-schemas.ts"() {
12512
- "use strict";
12513
- init_collector_evidence();
12514
- init_open_tool_schema();
12515
- init_terminating_infrastructure();
12516
- collectorObserveArgsSchema = Type13.Object({}, { additionalProperties: false });
12517
- collectorRequestArgsSchema = Type13.Object({
12518
- requestId: Type13.String({ minLength: 1, description: "\u914D\u7F6E\u8BF7\u6C42\u8EAB\u4EFD" }),
12519
- snapshotId: Type13.String({ minLength: 1, description: "\u6700\u65B0\u7559\u5B58\u89C2\u5BDF\u5FEB\u7167" })
12520
- }, { additionalProperties: false });
12521
- collectorReadArgsSchema = Type13.Object({
12522
- evidenceId: Type13.String({ minLength: 1, description: "observe \u8FD4\u56DE\u7684\u6750\u6599\u8BC1\u636E id\uFF08evidenceId\uFF09" })
12523
- }, { additionalProperties: false });
12524
- collectorWaitArgsSchema = Type13.Object({
12525
- durationMs: Type13.Integer({ minimum: 1, maximum: COLLECTOR_ELIGIBILITY_MS, description: "\u7B49\u5F85\u6BEB\u79D2\uFF1B\u5355\u6B21\u4E0A\u9650\u4E94\u5206\u949F\u4E14\u4E0D\u8D85\u5269\u4F59\u8D44\u683C" })
12526
- }, { additionalProperties: false });
12527
- collectorBindTargetArgsSchema = Type13.Object({
12528
- prNumber: Type13.Optional(Type13.Unknown({
12529
- description: "\u89D2\u8272\u5224\u5B9A\u7684\u672C\u4ED3 PR \u53F7\uFF08\u6B63\u6574\u6570\uFF09\u3002\u4E0E issueNumber \u4E8C\u9009\u4E00\u6216\u540C\u6307\u552F\u4E00\u76EE\u6807\u3002\u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\u3002"
12530
- })),
12531
- issueNumber: Type13.Optional(Type13.Unknown({
12532
- description: "\u89D2\u8272\u5224\u5B9A\u7684\u672C\u4ED3 issue \u53F7\uFF08\u6B63\u6574\u6570\uFF09\uFF1Bruntime \u7ECF\u7EBF\u4E0A\u5173\u8054\u89E3\u6790\u552F\u4E00 PR\u3002\u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\u3002"
12533
- }))
12534
- }, { additionalProperties: true });
12535
- collectorFindingItemDeclaration = (() => {
12536
- const item = Type13.Object(
12537
- {
12538
- evidenceId: Type13.Unknown({
12539
- description: "observe \u8FD4\u56DE\u7684\u6750\u6599\u6307\u9488\uFF08\u5FC5\u586B\u8BED\u4E49\uFF09"
12540
- }),
12541
- category: Type13.Unknown({
12542
- description: "\u7B80\u77ED\u5F52\u7C7B\u6807\u7B7E\uFF0C\u4E0D\u662F\u6458\u8981"
12543
- }),
12544
- summary: Type13.Unknown({
12545
- description: "\u54EA\u4E2A bot\u3001\u4EC0\u4E48\u95EE\u9898\u7684\u6458\u8981\uFF1B\u4E0D\u8A8A\u6284\u6B63\u6587"
12546
- })
12547
- },
12548
- {
12549
- additionalProperties: true,
12550
- description: "\u5355\u6761 finding \u6307\u9488\uFF1AevidenceId + \u53EF\u9009 category/summary\u3002\u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\u3002"
12551
- }
12552
- );
12553
- item.required = [];
12554
- return item;
12555
- })();
12556
- collectorOutputBaseSchema = openToolObject(
12557
- Type13.Object({
12558
- // No root type:array — host must not shape-reject non-array findings (#676 C).
12559
- // Nested item declarations ride `items` for registration preservation (ADR 0057).
12560
- findings: Type13.Unsafe({
12561
- description: "\u672C\u6B21\u6536\u96C6\u5230\u7684\u9010\u6761 findings\uFF08\u6307\u9488\u6570\u7EC4\u4E3A\u89C4\u8303\u5F62\uFF09\u3002\u96F6 finding \u7684\u6A21\u677F\u901A\u77E5\u4E0D\u5F97\u8FDB\u5165\uFF1B\u6B63\u5E38\u5B8C\u5DE5\u65E0 finding \u65F6\u7701\u7565\u3002\u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\u3002",
12562
- items: collectorFindingItemDeclaration
12563
- }),
12564
- unfinishedReasons: Type13.Unknown({
12565
- description: "\u672A\u5B8C\u6210\u539F\u56E0\u5B57\u7B26\u4E32\u6570\u7EC4\uFF08\u989D\u5EA6/\u6545\u969C/\u7B49\u5F85\u5C4A\u6EE1\u7B49\u73B0\u573A\u4F9D\u636E\uFF09\uFF1B\u4E0D\u5F97\u628A\u672A\u5B8C\u6210\u8868\u8FF0\u4E3A\u65E0\u95EE\u9898\u3002\u65E0\u53EF\u62A5\u544A\u65F6\u7701\u7565\u3002\u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\u3002"
12566
- })
12567
- })
12568
- );
12569
- collectorOutputArgsSchema = withInfrastructureFailureDeclaration(
12570
- collectorOutputBaseSchema
12571
- );
12572
- }
12573
- });
12574
-
12575
12507
  // src/collector-ledger.ts
12576
- import Value2 from "typebox/value";
12577
12508
  function utf8SafePrefix(text, maxBytes) {
12578
12509
  if (Buffer.byteLength(text, "utf8") <= maxBytes) return text;
12579
12510
  const bytes = Buffer.from(text, "utf8");
@@ -12646,9 +12577,7 @@ function createCollectorLedger(config, options) {
12646
12577
  const prIdentity = (pr) => `${pr.state}|${pr.headOid}|${pr.updatedAt ?? ""}`;
12647
12578
  const requireBoundPr = () => {
12648
12579
  if (config.prNumber === void 0) {
12649
- throw new Error(
12650
- "Collector PR target is unbound; call ak_collector_bind_target with the role-decided issue/PR or pass --pr"
12651
- );
12580
+ throw new Error("\u901A\u8FDB\u53F8 PR \u76EE\u6807\u672A\u7ED1\u5B9A");
12652
12581
  }
12653
12582
  return config.prNumber;
12654
12583
  };
@@ -12930,11 +12859,11 @@ function createCollectorLedger(config, options) {
12930
12859
  throw new Error("\u901A\u8FDB\u53F8\u5DF2\u4EA7\u51FA\u8F93\u51FA\u5019\u9009\uFF0C\u672C\u5C40\u4E0D\u518D\u53D7\u7406\u76EE\u6807\u7ED1\u5B9A");
12931
12860
  }
12932
12861
  if (!Number.isSafeInteger(prNumber) || prNumber < 1) {
12933
- throw new Error("Collector bind target requires a positive safe-integer PR number");
12862
+ throw new Error("\u901A\u8FDB\u53F8\u7ED1\u5B9A\u76EE\u6807\u8981\u6C42\u6B63\u5B89\u5168\u6574\u6570 PR \u53F7");
12934
12863
  }
12935
12864
  if (config.prNumber !== void 0 && config.prNumber !== prNumber) {
12936
12865
  throw new Error(
12937
- `Collector target already bound to PR ${config.prNumber}; cannot rebind to ${prNumber}`
12866
+ `\u901A\u8FDB\u53F8\u76EE\u6807\u5DF2\u7ED1\u5B9A PR ${config.prNumber}\uFF0C\u4E0D\u53EF\u6539\u7ED1\u4E3A ${prNumber}`
12938
12867
  );
12939
12868
  }
12940
12869
  config.prNumber = prNumber;
@@ -13131,9 +13060,21 @@ function createCollectorLedger(config, options) {
13131
13060
  if (ledger.unresolvedTransportFailure) {
13132
13061
  throw latchFatal("\u901A\u8FDB\u53F8\u8BF7\u6C42\u65F6\u5B58\u5728\u672A\u6062\u590D\u7684\u4F20\u8F93\u5931\u8D25");
13133
13062
  }
13134
- const request = config.manifest.requests.find((item) => item.id === input.requestId);
13135
- if (request === void 0) {
13136
- throw new Error(`\u672A\u77E5\u901A\u8FDB\u53F8 requestId "${input.requestId}"`);
13063
+ if (typeof input.requestId !== "string") {
13064
+ throw new Error("\u901A\u8FDB\u53F8 requestId \u987B\u4E3A\u5B57\u7B26\u4E32");
13065
+ }
13066
+ const requestId = input.requestId.trim();
13067
+ if (requestId.length === 0) {
13068
+ throw new Error("\u901A\u8FDB\u53F8 requestId \u987B\u4E3A\u975E\u7A7A\uFF08\u9996\u5C3E\u7A7A\u767D\u4E0D\u6784\u6210\u8EAB\u4EFD\uFF09");
13069
+ }
13070
+ const configured = config.manifest.requests.find((item) => item.id === requestId);
13071
+ const roleBody = typeof input.body === "string" ? input.body : void 0;
13072
+ if (configured === void 0) {
13073
+ if (roleBody === void 0 || roleBody.trim().length === 0) {
13074
+ throw new Error(
13075
+ `\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`
13076
+ );
13077
+ }
13137
13078
  }
13138
13079
  const snapshot = snapshots.find((item) => item.snapshotId === input.snapshotId);
13139
13080
  if (snapshot === void 0) {
@@ -13149,10 +13090,11 @@ function createCollectorLedger(config, options) {
13149
13090
  finalObservationRequired = true;
13150
13091
  throw latchFatal("\u901A\u8FDB\u53F8\u8BF7\u6C42\u4E0D\u5728\u8D44\u683C\u622A\u6B62\u524D");
13151
13092
  }
13093
+ const configuredBody = configured?.requestBody ?? roleBody;
13152
13094
  const { body, marker } = buildCollectorRequestBody({
13153
- configuredBody: request.requestBody,
13095
+ configuredBody,
13154
13096
  manifestDigest: config.manifest.digest,
13155
- requestId: request.id,
13097
+ requestId,
13156
13098
  headOid: snapshot.headOid
13157
13099
  });
13158
13100
  const existingMarker = snapshot.evidenceIds.some((id) => {
@@ -13161,7 +13103,7 @@ function createCollectorLedger(config, options) {
13161
13103
  });
13162
13104
  if (existingMarker) {
13163
13105
  throw new Error(
13164
- `\u901A\u8FDB\u53F8\u5728\u6B64 HEAD \u5DF2\u6709\u540C marker \u7684\u5DF2\u8BA4\u8BC1\u8BF7\u6C42 "${input.requestId}"`
13106
+ `\u901A\u8FDB\u53F8\u5728\u6B64 HEAD \u5DF2\u6709\u540C marker \u7684\u5DF2\u8BA4\u8BC1\u8BF7\u6C42 "${requestId}"`
13165
13107
  );
13166
13108
  }
13167
13109
  const boundPr = requireBoundPr();
@@ -13169,18 +13111,18 @@ function createCollectorLedger(config, options) {
13169
13111
  config.repository.canonical,
13170
13112
  String(boundPr),
13171
13113
  snapshot.headOid,
13172
- request.id
13114
+ requestId
13173
13115
  ].join("|");
13174
13116
  if (attemptKeys.has(attemptKey)) {
13175
13117
  throw new Error(
13176
- `\u901A\u8FDB\u53F8\u8FDB\u7A0B\u5185\u8BF7\u6C42 "${request.id}" \u5728 HEAD ${snapshot.headOid} \u7684 attempt \u5DF2\u7528`
13118
+ `\u901A\u8FDB\u53F8\u8FDB\u7A0B\u5185\u8BF7\u6C42 "${requestId}" \u5728 HEAD ${snapshot.headOid} \u7684 attempt \u5DF2\u7528`
13177
13119
  );
13178
13120
  }
13179
13121
  const startedAt = clock2.wallNow().toISOString();
13180
13122
  const attemptId = sha256Text(`${attemptKey}:${startedAt}`).slice(0, 16);
13181
13123
  const attempt = {
13182
13124
  attemptId,
13183
- requestId: request.id,
13125
+ requestId,
13184
13126
  observedHead: snapshot.headOid,
13185
13127
  snapshotId: snapshot.snapshotId,
13186
13128
  marker,
@@ -13222,7 +13164,7 @@ function createCollectorLedger(config, options) {
13222
13164
  return {
13223
13165
  status: "succeeded",
13224
13166
  attemptId,
13225
- requestId: request.id,
13167
+ requestId,
13226
13168
  observedHead: snapshot.headOid,
13227
13169
  marker,
13228
13170
  commentEvidenceId: record4.evidenceId
@@ -13236,7 +13178,7 @@ function createCollectorLedger(config, options) {
13236
13178
  return {
13237
13179
  status: "ambiguous_loss",
13238
13180
  attemptId,
13239
- requestId: request.id,
13181
+ requestId,
13240
13182
  observedHead: snapshot.headOid,
13241
13183
  marker,
13242
13184
  diagnostics: result.diagnostics
@@ -13253,14 +13195,6 @@ function createCollectorLedger(config, options) {
13253
13195
  if (activationTime === void 0) {
13254
13196
  throw latchFatal("\u901A\u8FDB\u53F8\u7B49\u5F85\u9700\u8981\u6FC0\u6D3B");
13255
13197
  }
13256
- if (!Number.isSafeInteger(input.durationMs) || input.durationMs < 1) {
13257
- throw new Error("\u901A\u8FDB\u53F8\u7B49\u5F85 durationMs \u987B\u4E3A\u6B63\u5B89\u5168\u6574\u6570");
13258
- }
13259
- if (input.durationMs > COLLECTOR_ELIGIBILITY_MS) {
13260
- throw new Error(
13261
- `\u901A\u8FDB\u53F8\u7B49\u5F85 durationMs \u81F3\u591A\u4E3A ${COLLECTOR_ELIGIBILITY_MS}`
13262
- );
13263
- }
13264
13198
  if (pastCutoff(clock2)) {
13265
13199
  finalObservationRequired = true;
13266
13200
  throw latchFatal("\u901A\u8FDB\u53F8\u7B49\u5F85\u4E0D\u5728\u8D44\u683C\u622A\u6B62\u524D");
@@ -13362,26 +13296,27 @@ function buildObserveModelView(input) {
13362
13296
  }))
13363
13297
  };
13364
13298
  }
13365
- var COLLECTOR_OBSERVE_TOOL, COLLECTOR_READ_TOOL, COLLECTOR_REQUEST_TOOL, COLLECTOR_WAIT_TOOL, COLLECTOR_BIND_TARGET_TOOL, COLLECTOR_OPERATIONAL_TOOLS, COLLECTOR_OBSERVE_BODY_HEAD_BYTES, COLLECTOR_ACTIVATION_ENTRY_TYPE, COLLECTOR_SNAPSHOT_ENTRY_TYPE, COLLECTOR_REQUEST_ENTRY_TYPE, COLLECTOR_WAIT_ENTRY_TYPE;
13299
+ var COLLECTOR_OBSERVE_TOOL, COLLECTOR_READ_TOOL, COLLECTOR_REQUEST_TOOL, COLLECTOR_WAIT_TOOL, COLLECTOR_BIND_TARGET_TOOL, COLLECTOR_HANDBOOK_WRITE_TOOL, COLLECTOR_OPERATIONAL_TOOLS, COLLECTOR_OBSERVE_BODY_HEAD_BYTES, COLLECTOR_ACTIVATION_ENTRY_TYPE, COLLECTOR_SNAPSHOT_ENTRY_TYPE, COLLECTOR_REQUEST_ENTRY_TYPE, COLLECTOR_WAIT_ENTRY_TYPE;
13366
13300
  var init_collector_ledger = __esm({
13367
13301
  "src/collector-ledger.ts"() {
13368
13302
  "use strict";
13369
13303
  init_collector_evidence();
13370
13304
  init_collector_github();
13371
13305
  init_collector_identity();
13372
- init_collector_tool_schemas();
13373
13306
  init_collector_output();
13374
13307
  COLLECTOR_OBSERVE_TOOL = "ak_collector_observe";
13375
13308
  COLLECTOR_READ_TOOL = "ak_collector_read";
13376
13309
  COLLECTOR_REQUEST_TOOL = "ak_collector_request";
13377
13310
  COLLECTOR_WAIT_TOOL = "ak_collector_wait";
13378
13311
  COLLECTOR_BIND_TARGET_TOOL = "ak_collector_bind_target";
13312
+ COLLECTOR_HANDBOOK_WRITE_TOOL = "ak_collector_handbook_write";
13379
13313
  COLLECTOR_OPERATIONAL_TOOLS = [
13380
13314
  COLLECTOR_BIND_TARGET_TOOL,
13381
13315
  COLLECTOR_OBSERVE_TOOL,
13382
13316
  COLLECTOR_READ_TOOL,
13383
13317
  COLLECTOR_REQUEST_TOOL,
13384
- COLLECTOR_WAIT_TOOL
13318
+ COLLECTOR_WAIT_TOOL,
13319
+ COLLECTOR_HANDBOOK_WRITE_TOOL
13385
13320
  ];
13386
13321
  COLLECTOR_OBSERVE_BODY_HEAD_BYTES = 512;
13387
13322
  COLLECTOR_ACTIVATION_ENTRY_TYPE = "ak-collector-activation";
@@ -17921,11 +17856,11 @@ async function summonPublicRole(options) {
17921
17856
  };
17922
17857
  }
17923
17858
  async function parentInvocationHost(sourceRunDirectory) {
17924
- const { readFile: readFile21 } = await import("node:fs/promises");
17859
+ const { readFile: readFile22 } = await import("node:fs/promises");
17925
17860
  const path = join28(sourceRunDirectory, "invocation.json");
17926
17861
  let text;
17927
17862
  try {
17928
- text = await readFile21(path, "utf8");
17863
+ text = await readFile22(path, "utf8");
17929
17864
  } catch (error) {
17930
17865
  const code = error instanceof Error && "code" in error ? error.code : void 0;
17931
17866
  throw new Error(
@@ -18026,7 +17961,7 @@ __export(compliance_transport_exports, {
18026
17961
  runComplianceAudit: () => runComplianceAudit,
18027
17962
  tryReadComplianceCandidate: () => tryReadComplianceCandidate
18028
17963
  });
18029
- import { Type as Type14 } from "typebox";
17964
+ import { Type as Type13 } from "typebox";
18030
17965
  function readListField(value) {
18031
17966
  return Array.isArray(value) ? value : value === void 0 ? [] : [value];
18032
17967
  }
@@ -18124,9 +18059,9 @@ var init_compliance_transport = __esm({
18124
18059
  "use strict";
18125
18060
  init_auditor_dossier_tool();
18126
18061
  AUDITOR_DOSSIER_PROMPT = "\u672C run \u5377\u5B97\u5DF2\u5C31\u7EEA\u3002";
18127
- nonblank2 = Type14.String({ minLength: 1, pattern: "\\S" });
18128
- decisionGateSchema = Type14.Object({ question: nonblank2, options: Type14.Array(nonblank2, { minItems: 1 }) }, { additionalProperties: false });
18129
- complianceDecisionSchema = Type14.Object({ status: Type14.Unknown({ description: "pass | bounce | escalate \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8" }), violations: Type14.Array(nonblank2, { description: "\u89C2\u5BDF\u5230\u7684\u5408\u89C4\u8FDD\u89C4" }), conflicts: Type14.Array(nonblank2, { description: "\u672A\u51B3\u6743\u5A01\u6216\u6267\u884C\u51B2\u7A81" }), decisionGate: Type14.Union([decisionGateSchema, Type14.Null()], { description: "\u5347\u7EA7\u95EE\u9898\u4E0E\u53EF\u9009\u9009\u9879" }) }, { additionalProperties: true, required: [] });
18062
+ nonblank2 = Type13.String({ minLength: 1, pattern: "\\S" });
18063
+ decisionGateSchema = Type13.Object({ question: nonblank2, options: Type13.Array(nonblank2, { minItems: 1 }) }, { additionalProperties: false });
18064
+ complianceDecisionSchema = Type13.Object({ status: Type13.Unknown({ description: "pass | bounce | escalate \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8" }), violations: Type13.Array(nonblank2, { description: "\u89C2\u5BDF\u5230\u7684\u5408\u89C4\u8FDD\u89C4" }), conflicts: Type13.Array(nonblank2, { description: "\u672A\u51B3\u6743\u5A01\u6216\u6267\u884C\u51B2\u7A81" }), decisionGate: Type13.Union([decisionGateSchema, Type13.Null()], { description: "\u5347\u7EA7\u95EE\u9898\u4E0E\u53EF\u9009\u9009\u9879" }) }, { additionalProperties: true, required: [] });
18130
18065
  COMPLIANCE_RESPONSE_ENTRY_TYPE = "ak_compliance_response";
18131
18066
  AUDITOR_PARENT_ATTEMPT_BINDING_ENTRY_TYPE = "ak_auditor_parent_attempt_binding";
18132
18067
  AUDITOR_COMPLIANCE_FAILURE_ENTRY_TYPE = "ak_auditor_compliance_failure";
@@ -18220,8 +18155,8 @@ var init_doctor_auditor = __esm({
18220
18155
  });
18221
18156
 
18222
18157
  // src/navigator-session-contracts.ts
18223
- import { Type as Type15 } from "typebox";
18224
- import { Value as Value3 } from "typebox/value";
18158
+ import { Type as Type14 } from "typebox";
18159
+ import { Value as Value2 } from "typebox/value";
18225
18160
  function navigatorUnavailableKey(value) {
18226
18161
  return typeof value === "string" && NAVIGATOR_UNAVAILABLE_KEYS.has(value) ? value : void 0;
18227
18162
  }
@@ -18372,26 +18307,26 @@ var init_navigator_session_contracts = __esm({
18372
18307
  this.originalCause = originalCause;
18373
18308
  }
18374
18309
  };
18375
- navigatorProviderFailureSchema = Type15.Object({
18376
- source: Type15.Union([
18377
- Type15.Literal("context"),
18378
- Type15.Literal("session"),
18379
- Type15.Literal("model"),
18380
- Type15.Literal("thinking"),
18381
- Type15.Literal("auth"),
18382
- Type15.Literal("quota"),
18383
- Type15.Literal("transport"),
18384
- Type15.Literal("unknown")
18310
+ navigatorProviderFailureSchema = Type14.Object({
18311
+ source: Type14.Union([
18312
+ Type14.Literal("context"),
18313
+ Type14.Literal("session"),
18314
+ Type14.Literal("model"),
18315
+ Type14.Literal("thinking"),
18316
+ Type14.Literal("auth"),
18317
+ Type14.Literal("quota"),
18318
+ Type14.Literal("transport"),
18319
+ Type14.Literal("unknown")
18385
18320
  ]),
18386
- cause: Type15.Union([
18387
- Type15.Literal("context"),
18388
- Type15.Literal("session"),
18389
- Type15.Literal("model"),
18390
- Type15.Literal("thinking"),
18391
- Type15.Literal("auth"),
18392
- Type15.Literal("quota"),
18393
- Type15.Literal("transport"),
18394
- Type15.Literal("unknown")
18321
+ cause: Type14.Union([
18322
+ Type14.Literal("context"),
18323
+ Type14.Literal("session"),
18324
+ Type14.Literal("model"),
18325
+ Type14.Literal("thinking"),
18326
+ Type14.Literal("auth"),
18327
+ Type14.Literal("quota"),
18328
+ Type14.Literal("transport"),
18329
+ Type14.Literal("unknown")
18395
18330
  ])
18396
18331
  }, { additionalProperties: false });
18397
18332
  }
@@ -18743,7 +18678,7 @@ var init_navigator_public_session = __esm({
18743
18678
  import { createHash as createHash9 } from "node:crypto";
18744
18679
  import { resolve as resolve14 } from "node:path";
18745
18680
  import "@earendil-works/pi-coding-agent";
18746
- import { Type as Type16 } from "typebox";
18681
+ import { Type as Type15 } from "typebox";
18747
18682
  function resolveNavigatorAuthorityMaterial(roleInput, fileAuthority) {
18748
18683
  if (roleInput !== void 0 && roleInput.trim() !== "") return roleInput;
18749
18684
  if (fileAuthority !== void 0 && fileAuthority.trim() !== "") return fileAuthority;
@@ -19406,8 +19341,8 @@ var init_navigator_attendance = __esm({
19406
19341
  NAVIGATOR_EVENT_TYPE = "ak-navigator-attendance";
19407
19342
  NAVIGATOR_PREPARE_ACCEPTED_TEXT = "\u6E38\u5955\u4F7F\u51C6\u5907\u5DF2\u63A5\u53D7";
19408
19343
  NAVIGATOR_TARGETS = PACKAGED_ROLE_REGISTRY.map(({ role, phases }) => ({ role, phases }));
19409
- prepareSchema = Type16.Object({
19410
- candidates: Type16.Optional(Type16.Unknown({
19344
+ prepareSchema = Type15.Object({
19345
+ candidates: Type15.Optional(Type15.Unknown({
19411
19346
  description: "\u65B9\u5411\u5019\u9009\uFF1Bcandidates[].next.role \u5FC5\u586B\uFF0Cphase \u53EF\u9009\uFF0Croute/matches/reason/command \u53EF\u9009\u4E0A\u4E0B\u6587\uFF0C\u975E\u53D7\u7406\u95F8"
19412
19347
  }))
19413
19348
  }, { additionalProperties: true });
@@ -19420,7 +19355,7 @@ var init_navigator_attendance = __esm({
19420
19355
  });
19421
19356
 
19422
19357
  // src/engine-detour-tool.ts
19423
- import { Type as Type17 } from "typebox";
19358
+ import { Type as Type16 } from "typebox";
19424
19359
  function isCallerCancellation(error, signal) {
19425
19360
  if (signal?.aborted === true) return true;
19426
19361
  if (typeof error === "object" && error !== null && error.name === "AbortError") {
@@ -19495,9 +19430,9 @@ var init_engine_detour_tool = __esm({
19495
19430
  "src/engine-detour-tool.ts"() {
19496
19431
  "use strict";
19497
19432
  init_engine_detour();
19498
- engineDetourArgsSchema = Type17.Object(
19433
+ engineDetourArgsSchema = Type16.Object(
19499
19434
  {
19500
- argv: Type17.Array(Type17.String({ minLength: 1 }), {
19435
+ argv: Type16.Array(Type16.String({ minLength: 1 }), {
19501
19436
  minItems: 1,
19502
19437
  description: "\u9996\u9879\u4E3A PATH \u4E2D\u7684\u53EF\u6267\u884C\u6587\u4EF6\uFF0C\u5176\u4F59\u9879\u4E3A\u53C2\u6570\u3002"
19503
19438
  })
@@ -19824,7 +19759,7 @@ var init_oauth_keepalive = __esm({
19824
19759
  });
19825
19760
 
19826
19761
  // src/activation-trace.ts
19827
- import { Type as Type18 } from "typebox";
19762
+ import { Type as Type17 } from "typebox";
19828
19763
  function namedActivationCause(error) {
19829
19764
  const evidenceId = `activation-cause-${++activationCauseEvidence}`;
19830
19765
  retainedActivationCauses.set(evidenceId, error);
@@ -19845,17 +19780,17 @@ var causeSchema, activationTraceRecordSchema, activationCauseEvidence, retainedA
19845
19780
  var init_activation_trace = __esm({
19846
19781
  "src/activation-trace.ts"() {
19847
19782
  "use strict";
19848
- causeSchema = Type18.Object({
19849
- identity: Type18.String({ minLength: 1 }),
19850
- name: Type18.String({ minLength: 1 }),
19851
- message: Type18.String(),
19852
- evidenceId: Type18.Optional(Type18.String({ minLength: 1 }))
19783
+ causeSchema = Type17.Object({
19784
+ identity: Type17.String({ minLength: 1 }),
19785
+ name: Type17.String({ minLength: 1 }),
19786
+ message: Type17.String(),
19787
+ evidenceId: Type17.Optional(Type17.String({ minLength: 1 }))
19853
19788
  }, { additionalProperties: false });
19854
- activationTraceRecordSchema = Type18.Object({
19855
- role: Type18.String({ minLength: 1 }),
19856
- stageId: Type18.String({ pattern: "^[a-z][a-z0-9-]*$" }),
19857
- status: Type18.Literal("failed"),
19858
- timestamp: Type18.String({ format: "date-time" }),
19789
+ activationTraceRecordSchema = Type17.Object({
19790
+ role: Type17.String({ minLength: 1 }),
19791
+ stageId: Type17.String({ pattern: "^[a-z][a-z0-9-]*$" }),
19792
+ status: Type17.Literal("failed"),
19793
+ timestamp: Type17.String({ format: "date-time" }),
19859
19794
  cause: causeSchema
19860
19795
  }, { additionalProperties: false });
19861
19796
  activationCauseEvidence = 0;
@@ -20137,10 +20072,10 @@ var init_stderr_jsonl = __esm({
20137
20072
 
20138
20073
  // src/tool-execution-observation.ts
20139
20074
  import { writeSync as writeSync3 } from "node:fs";
20140
- import { Type as Type19 } from "typebox";
20141
- import { Value as Value4 } from "typebox/value";
20075
+ import { Type as Type18 } from "typebox";
20076
+ import { Value as Value3 } from "typebox/value";
20142
20077
  function validateToolExecutionObservationRecord(record4) {
20143
- if (!Value4.Check(toolExecutionObservationRecordSchema, record4)) {
20078
+ if (!Value3.Check(toolExecutionObservationRecordSchema, record4)) {
20144
20079
  throw new TypeError("Tool execution observation record does not match its contract");
20145
20080
  }
20146
20081
  return record4;
@@ -20231,29 +20166,266 @@ var init_tool_execution_observation = __esm({
20231
20166
  init_stderr_jsonl();
20232
20167
  TOOL_EXECUTION_UPDATE_THROTTLE_MS = 3e4;
20233
20168
  observationBase = {
20234
- role: Type19.String({ minLength: 1 }),
20235
- toolCallId: Type19.String({ minLength: 1 }),
20236
- toolName: Type19.String({ minLength: 1 }),
20237
- timestamp: Type19.String({ format: "date-time" })
20169
+ role: Type18.String({ minLength: 1 }),
20170
+ toolCallId: Type18.String({ minLength: 1 }),
20171
+ toolName: Type18.String({ minLength: 1 }),
20172
+ timestamp: Type18.String({ format: "date-time" })
20238
20173
  };
20239
- toolExecutionObservationRecordSchema = Type19.Union([
20240
- Type19.Object({
20174
+ toolExecutionObservationRecordSchema = Type18.Union([
20175
+ Type18.Object({
20241
20176
  ...observationBase,
20242
- event: Type19.Literal("tool_execution_start")
20177
+ event: Type18.Literal("tool_execution_start")
20243
20178
  }, { additionalProperties: true }),
20244
- Type19.Object({
20179
+ Type18.Object({
20245
20180
  ...observationBase,
20246
- event: Type19.Literal("tool_execution_update")
20181
+ event: Type18.Literal("tool_execution_update")
20247
20182
  }, { additionalProperties: true }),
20248
- Type19.Object({
20183
+ Type18.Object({
20249
20184
  ...observationBase,
20250
- event: Type19.Literal("tool_execution_end"),
20251
- isError: Type19.Boolean()
20185
+ event: Type18.Literal("tool_execution_end"),
20186
+ isError: Type18.Boolean()
20252
20187
  }, { additionalProperties: true })
20253
20188
  ]);
20254
20189
  }
20255
20190
  });
20256
20191
 
20192
+ // src/atomic-write.ts
20193
+ import { randomUUID as randomUUID6 } from "node:crypto";
20194
+ import { rename, rm as rm2, writeFile as writeFile8 } from "node:fs/promises";
20195
+ import { dirname as dirname17, join as join32 } from "node:path";
20196
+ async function writeFileAtomically(destination, contents) {
20197
+ const parent = dirname17(destination);
20198
+ const temporary = join32(parent, `.atomic-write-${randomUUID6()}.tmp`);
20199
+ try {
20200
+ await writeFile8(temporary, contents);
20201
+ await rename(temporary, destination);
20202
+ } catch (error) {
20203
+ await rm2(temporary, { force: true }).catch(() => void 0);
20204
+ throw error;
20205
+ }
20206
+ }
20207
+ var init_atomic_write = __esm({
20208
+ "src/atomic-write.ts"() {
20209
+ "use strict";
20210
+ }
20211
+ });
20212
+
20213
+ // src/collector-tool-schemas.ts
20214
+ import { Type as Type19 } from "typebox";
20215
+ var collectorObserveArgsSchema, COLLECTOR_REQUEST_ID_PATTERN, collectorRequestArgsSchema, COLLECTOR_HANDBOOK_MAX_BYTES, collectorHandbookWriteArgsSchema, collectorReadArgsSchema, collectorWaitArgsSchema, collectorBindTargetArgsSchema, collectorFindingItemDeclaration, collectorOutputBaseSchema, collectorOutputArgsSchema;
20216
+ var init_collector_tool_schemas = __esm({
20217
+ "src/collector-tool-schemas.ts"() {
20218
+ "use strict";
20219
+ init_collector_evidence();
20220
+ init_open_tool_schema();
20221
+ init_terminating_infrastructure();
20222
+ collectorObserveArgsSchema = Type19.Object({}, { additionalProperties: false });
20223
+ COLLECTOR_REQUEST_ID_PATTERN = /^\S(?:.*\S)?$/;
20224
+ collectorRequestArgsSchema = Type19.Object({
20225
+ requestId: Type19.String({
20226
+ minLength: 1,
20227
+ pattern: COLLECTOR_REQUEST_ID_PATTERN.source,
20228
+ 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"
20229
+ }),
20230
+ snapshotId: Type19.String({ minLength: 1, description: "\u6700\u65B0\u7559\u5B58\u89C2\u5BDF\u5FEB\u7167" }),
20231
+ body: Type19.Optional(Type19.String({
20232
+ minLength: 1,
20233
+ description: "\u89D2\u8272\u5224\u5B9A\u7684\u8BF7\u6C42\u6B63\u6587\uFF1Brequest-manifest \u672A\u6536\u5F55\u8BE5 requestId \u65F6\u5FC5\u586B"
20234
+ }))
20235
+ }, { additionalProperties: false });
20236
+ COLLECTOR_HANDBOOK_MAX_BYTES = 64 * 1024;
20237
+ collectorHandbookWriteArgsSchema = Type19.Object({
20238
+ scope: Type19.Union([
20239
+ Type19.Literal("general"),
20240
+ Type19.Literal("repo")
20241
+ ], { description: "general\uFF1D\u901A\u7528\u624B\u518C\uFF1Brepo\uFF1D\u5F53\u524D\u4ED3\u5E93\u5DEE\u5F02" }),
20242
+ body: Type19.String({
20243
+ 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`
20244
+ })
20245
+ }, { additionalProperties: false });
20246
+ collectorReadArgsSchema = Type19.Object({
20247
+ evidenceId: Type19.String({ minLength: 1, description: "observe \u8FD4\u56DE\u7684\u6750\u6599\u8BC1\u636E id\uFF08evidenceId\uFF09" })
20248
+ }, { additionalProperties: false });
20249
+ collectorWaitArgsSchema = Type19.Object({
20250
+ durationMs: Type19.Integer({ minimum: 1, maximum: COLLECTOR_ELIGIBILITY_MS, description: "\u7B49\u5F85\u6BEB\u79D2\uFF1B\u5355\u6B21\u4E0A\u9650\u4E94\u5206\u949F\u4E14\u4E0D\u8D85\u5269\u4F59\u8D44\u683C" })
20251
+ }, { additionalProperties: false });
20252
+ collectorBindTargetArgsSchema = Type19.Object({
20253
+ prNumber: Type19.Optional(Type19.Unknown({
20254
+ description: "\u89D2\u8272\u5224\u5B9A\u7684\u672C\u4ED3 PR \u53F7\uFF08\u6B63\u6574\u6570\uFF09\u3002\u4E0E issueNumber \u4E8C\u9009\u4E00\u6216\u540C\u6307\u552F\u4E00\u76EE\u6807\u3002\u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\u3002"
20255
+ })),
20256
+ issueNumber: Type19.Optional(Type19.Unknown({
20257
+ description: "\u89D2\u8272\u5224\u5B9A\u7684\u672C\u4ED3 issue \u53F7\uFF08\u6B63\u6574\u6570\uFF09\uFF1Bruntime \u7ECF\u7EBF\u4E0A\u5173\u8054\u89E3\u6790\u552F\u4E00 PR\u3002\u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\u3002"
20258
+ }))
20259
+ }, { additionalProperties: true });
20260
+ collectorFindingItemDeclaration = (() => {
20261
+ const item = Type19.Object(
20262
+ {
20263
+ evidenceId: Type19.Unknown({
20264
+ description: "observe \u8FD4\u56DE\u7684\u6750\u6599\u6307\u9488\uFF08\u5FC5\u586B\u8BED\u4E49\uFF09"
20265
+ }),
20266
+ category: Type19.Unknown({
20267
+ description: "\u7B80\u77ED\u5F52\u7C7B\u6807\u7B7E\uFF0C\u4E0D\u662F\u6458\u8981"
20268
+ }),
20269
+ summary: Type19.Unknown({
20270
+ description: "\u54EA\u4E2A bot\u3001\u4EC0\u4E48\u95EE\u9898\u7684\u6458\u8981\uFF1B\u4E0D\u8A8A\u6284\u6B63\u6587"
20271
+ })
20272
+ },
20273
+ {
20274
+ additionalProperties: true,
20275
+ description: "\u5355\u6761 finding \u6307\u9488\uFF1AevidenceId + \u53EF\u9009 category/summary\u3002\u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\u3002"
20276
+ }
20277
+ );
20278
+ item.required = [];
20279
+ return item;
20280
+ })();
20281
+ collectorOutputBaseSchema = openToolObject(
20282
+ Type19.Object({
20283
+ // No root type:array — host must not shape-reject non-array findings (#676 C).
20284
+ // Nested item declarations ride `items` for registration preservation (ADR 0057).
20285
+ findings: Type19.Unsafe({
20286
+ description: "\u672C\u6B21\u6536\u96C6\u5230\u7684\u9010\u6761 findings\uFF08\u6307\u9488\u6570\u7EC4\u4E3A\u89C4\u8303\u5F62\uFF09\u3002\u96F6 finding \u7684\u6A21\u677F\u901A\u77E5\u4E0D\u5F97\u8FDB\u5165\uFF1B\u6B63\u5E38\u5B8C\u5DE5\u65E0 finding \u65F6\u7701\u7565\u3002\u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\u3002",
20287
+ items: collectorFindingItemDeclaration
20288
+ }),
20289
+ unfinishedReasons: Type19.Unknown({
20290
+ description: "\u672A\u5B8C\u6210\u539F\u56E0\u5B57\u7B26\u4E32\u6570\u7EC4\uFF08\u989D\u5EA6/\u6545\u969C/\u7B49\u5F85\u5C4A\u6EE1\u7B49\u73B0\u573A\u4F9D\u636E\uFF09\uFF1B\u4E0D\u5F97\u628A\u672A\u5B8C\u6210\u8868\u8FF0\u4E3A\u65E0\u95EE\u9898\u3002\u65E0\u53EF\u62A5\u544A\u65F6\u7701\u7565\u3002\u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\u3002"
20291
+ })
20292
+ })
20293
+ );
20294
+ collectorOutputArgsSchema = withInfrastructureFailureDeclaration(
20295
+ collectorOutputBaseSchema
20296
+ );
20297
+ }
20298
+ });
20299
+
20300
+ // src/collector-handbook.ts
20301
+ import { readFile as readFile18 } from "node:fs/promises";
20302
+ import { join as join33, sep as sep4 } from "node:path";
20303
+ function resolveCollectorHandbookRoot(sessionPath) {
20304
+ if (typeof sessionPath !== "string" || sessionPath.trim().length === 0) {
20305
+ throw new Error("\u901A\u8FDB\u53F8\u624B\u518C\u8981\u6C42\u975E\u7A7A session \u8DEF\u5F84\uFF0C\u4E14\u4F4D\u4E8E books/<bookKey>/");
20306
+ }
20307
+ const segments = sessionPath.split(sep4);
20308
+ let bookKey;
20309
+ for (let i = 0; i + 3 < segments.length; i += 1) {
20310
+ if (segments[i] === ".ak-roles" && segments[i + 1] === "books") {
20311
+ const candidate = segments[i + 2];
20312
+ if (candidate.length > 0) {
20313
+ bookKey = candidate;
20314
+ break;
20315
+ }
20316
+ }
20317
+ }
20318
+ if (bookKey === void 0) {
20319
+ throw new Error(
20320
+ `\u901A\u8FDB\u53F8\u624B\u518C\u8981\u6C42 session \u4F4D\u4E8E books/<bookKey>/\uFF1B\u6536\u5230 ${sessionPath}`
20321
+ );
20322
+ }
20323
+ if (bookKey === "." || bookKey === "..") {
20324
+ throw new Error(`\u901A\u8FDB\u53F8\u624B\u518C\u62D2\u7EDD\u4E0D\u5B89\u5168 bookKey ${JSON.stringify(bookKey)}`);
20325
+ }
20326
+ const ledgerHome = resolveActivationLedgerHomeForPath(sessionPath);
20327
+ const root = join33(activationBookDirectory(ledgerHome, bookKey), "collector-handbook");
20328
+ return { ledgerHome, bookKey, root };
20329
+ }
20330
+ function collectorHandbookRepoFileName(repositoryCanonical) {
20331
+ if (!/^[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*$/.test(repositoryCanonical)) {
20332
+ throw new Error(
20333
+ `\u901A\u8FDB\u53F8\u624B\u518C\u4ED3\u5E93\u6587\u4EF6\u8981\u6C42\u89C4\u8303 owner/repo\uFF0C\u6536\u5230 ${JSON.stringify(repositoryCanonical)}`
20334
+ );
20335
+ }
20336
+ return `${repositoryCanonical.replaceAll("/", "__")}.md`;
20337
+ }
20338
+ function createCollectorHandbookStore(input) {
20339
+ const generalPath = join33(input.handbookRoot, "general.md");
20340
+ const repoDir = join33(input.handbookRoot, "repos");
20341
+ const repoPath = join33(repoDir, collectorHandbookRepoFileName(input.repositoryCanonical));
20342
+ const assertHandbookBudget = (body, label) => {
20343
+ const byteLength = Buffer.byteLength(body, "utf8");
20344
+ if (byteLength > COLLECTOR_HANDBOOK_MAX_BYTES) {
20345
+ throw new Error(
20346
+ `\u901A\u8FDB\u53F8\u624B\u518C${label} UTF-8 \u81F3\u591A ${COLLECTOR_HANDBOOK_MAX_BYTES} \u5B57\u8282\uFF0C\u6536\u5230 ${byteLength}`
20347
+ );
20348
+ }
20349
+ return byteLength;
20350
+ };
20351
+ const readOptional = async (path, parentDir2) => {
20352
+ ensureRealDirectoryTree(input.ledgerHome, parentDir2);
20353
+ assertLedgerFileInsideHome(path, input.ledgerHome);
20354
+ try {
20355
+ const body = await readFile18(path, "utf8");
20356
+ assertHandbookBudget(body, "\u6B63\u6587");
20357
+ return body;
20358
+ } catch (error) {
20359
+ if (isNotFound(error)) return void 0;
20360
+ throw error;
20361
+ }
20362
+ };
20363
+ return {
20364
+ root: input.handbookRoot,
20365
+ repositoryCanonical: input.repositoryCanonical,
20366
+ async read() {
20367
+ const bookGeneral = await readOptional(generalPath, input.handbookRoot);
20368
+ const bookRepo = await readOptional(repoPath, repoDir);
20369
+ if (bookGeneral !== void 0) {
20370
+ return {
20371
+ general: bookGeneral,
20372
+ repo: bookRepo ?? "",
20373
+ generalSource: "book",
20374
+ repoSource: bookRepo === void 0 ? "empty" : "book",
20375
+ generalPath,
20376
+ repoPath
20377
+ };
20378
+ }
20379
+ const seed = input.seedGeneral;
20380
+ if (typeof seed === "string" && seed.length > 0) {
20381
+ assertHandbookBudget(seed, "\u6B63\u6587");
20382
+ return {
20383
+ general: seed,
20384
+ repo: bookRepo ?? "",
20385
+ generalSource: "seed",
20386
+ repoSource: bookRepo === void 0 ? "empty" : "book",
20387
+ generalPath,
20388
+ repoPath
20389
+ };
20390
+ }
20391
+ return {
20392
+ general: "",
20393
+ repo: bookRepo ?? "",
20394
+ generalSource: "empty",
20395
+ repoSource: bookRepo === void 0 ? "empty" : "book",
20396
+ generalPath,
20397
+ repoPath
20398
+ };
20399
+ },
20400
+ async write(scope, body) {
20401
+ const byteLength = assertHandbookBudget(body, "\u6B63\u6587");
20402
+ ensureRealDirectoryTree(input.ledgerHome, input.handbookRoot);
20403
+ const path = scope === "general" ? generalPath : repoPath;
20404
+ if (scope === "repo") {
20405
+ ensureRealDirectoryTree(input.ledgerHome, repoDir);
20406
+ }
20407
+ assertLedgerFileInsideHome(path, input.ledgerHome);
20408
+ await writeFileAtomically(path, body);
20409
+ return {
20410
+ scope,
20411
+ path,
20412
+ byteLength
20413
+ };
20414
+ }
20415
+ };
20416
+ }
20417
+ function isNotFound(error) {
20418
+ return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
20419
+ }
20420
+ var init_collector_handbook = __esm({
20421
+ "src/collector-handbook.ts"() {
20422
+ "use strict";
20423
+ init_atomic_write();
20424
+ init_activation_ledger_topology();
20425
+ init_collector_tool_schemas();
20426
+ }
20427
+ });
20428
+
20257
20429
  // src/collector-receipt.ts
20258
20430
  function fail4(message) {
20259
20431
  throw new Error(message);
@@ -20353,20 +20525,34 @@ var init_collector_receipt = __esm({
20353
20525
  // src/collector-role.ts
20354
20526
  function buildMethodContext(activation) {
20355
20527
  const pr = activation.ledger.config.prNumber;
20356
- return [
20528
+ const handbook = activation.handbookView;
20529
+ const lines = [
20357
20530
  "<collector_method>",
20358
20531
  `host: github.com`,
20359
20532
  `repository: ${activation.repository.canonical}`,
20360
- `prNumber: ${pr === void 0 ? "unbound \u2014 call ak_collector_bind_target with the role-decided issue/PR before observe" : String(pr)}`,
20533
+ `prNumber: ${pr === void 0 ? "\u672A\u7ED1\u5B9A" : String(pr)}`,
20361
20534
  `requests: ${JSON.stringify(activation.manifest.requests.map((request) => ({ id: request.id })))}`,
20535
+ `handbookGeneralSource: ${handbook.generalSource}`,
20536
+ `handbookRepoSource: ${handbook.repoSource}`,
20362
20537
  "</collector_method>"
20363
- ].join("\n");
20538
+ ];
20539
+ if (handbook.general.length > 0 || handbook.repo.length > 0) {
20540
+ const payload = JSON.stringify({
20541
+ general: handbook.general,
20542
+ repo: handbook.repo,
20543
+ generalSource: handbook.generalSource,
20544
+ repoSource: handbook.repoSource,
20545
+ repository: activation.repository.canonical
20546
+ }).replaceAll("<", "\\u003c");
20547
+ lines.push("", "<collector_handbook>", payload, "</collector_handbook>");
20548
+ }
20549
+ return lines.join("\n");
20364
20550
  }
20365
20551
  function parsePositiveTicket(raw, label) {
20366
20552
  if (raw === void 0 || raw === null) return void 0;
20367
20553
  if (typeof raw === "number" && Number.isSafeInteger(raw) && raw >= 1) return raw;
20368
20554
  if (typeof raw === "string" && /^[1-9]\d*$/.test(raw.trim())) return Number(raw.trim());
20369
- throw new CollectorTargetBindError(`ak_collector_bind_target ${label} must be a positive safe integer`);
20555
+ throw new CollectorTargetBindError(`\u901A\u8FDB\u53F8\u7ED1\u5B9A ${label} \u987B\u4E3A\u6B63\u5B89\u5168\u6574\u6570`);
20370
20556
  }
20371
20557
  function createCollectorRoleRuntime(pi, dependencies, hostActions) {
20372
20558
  let toolsRegistered = false;
@@ -20395,13 +20581,28 @@ function createCollectorRoleRuntime(pi, dependencies, hostActions) {
20395
20581
  clock,
20396
20582
  ctx
20397
20583
  );
20584
+ const sessionPath = ctx.sessionManager?.getSessionFile?.() ?? ctx.sessionManager?.getSessionDir?.();
20585
+ if (typeof sessionPath !== "string" || sessionPath.length === 0) {
20586
+ throw new Error("\u901A\u8FDB\u53F8\u624B\u518C\u8981\u6C42 session \u8DEF\u5F84\u4F4D\u4E8E books/<bookKey>/");
20587
+ }
20588
+ const placement = resolveCollectorHandbookRoot(sessionPath);
20589
+ const seedGeneral = dependencies.loadHandbookSeed === void 0 ? void 0 : (await dependencies.loadHandbookSeed()).trim();
20590
+ const handbook = createCollectorHandbookStore({
20591
+ ledgerHome: placement.ledgerHome,
20592
+ handbookRoot: placement.root,
20593
+ repositoryCanonical: repository.canonical,
20594
+ ...seedGeneral === void 0 || seedGeneral.length === 0 ? {} : { seedGeneral }
20595
+ });
20596
+ const handbookView = await handbook.read();
20398
20597
  return {
20399
20598
  soul,
20400
20599
  repository,
20401
20600
  manifest,
20402
20601
  ledger,
20403
20602
  transport,
20404
- clock
20603
+ clock,
20604
+ handbook,
20605
+ handbookView
20405
20606
  };
20406
20607
  },
20407
20608
  assembleMaterials(activation, baseSystemPrompt) {
@@ -20454,7 +20655,7 @@ function createCollectorRoleRuntime(pi, dependencies, hostActions) {
20454
20655
  const issueNumber = parsePositiveTicket(params.issueNumber, "issueNumber");
20455
20656
  if (prNumber === void 0 && issueNumber === void 0) {
20456
20657
  throw new CollectorTargetBindError(
20457
- "ak_collector_bind_target requires role-decided prNumber and/or issueNumber"
20658
+ "\u901A\u8FDB\u53F8\u7ED1\u5B9A\u987B\u7531\u89D2\u8272\u5224\u5B9A prNumber \u4E0E/\u6216 issueNumber"
20458
20659
  );
20459
20660
  }
20460
20661
  let bound = prNumber;
@@ -20466,18 +20667,18 @@ function createCollectorRoleRuntime(pi, dependencies, hostActions) {
20466
20667
  });
20467
20668
  if (associated.length === 0) {
20468
20669
  throw new CollectorTargetBindError(
20469
- `no PR associated with issue #${issueNumber} in ${activation.repository.canonical}; pass an explicit --pr or a different issueNumber`
20670
+ `${activation.repository.canonical} \u7684 issue #${issueNumber} \u65E0\u5173\u8054 PR\uFF1B\u8BF7\u6539\u7528\u660E\u786E --pr \u6216\u5176\u4ED6 issueNumber`
20470
20671
  );
20471
20672
  }
20472
20673
  if (associated.length > 1) {
20473
20674
  throw new CollectorTargetBindError(
20474
- `multiple PRs associated with issue #${issueNumber}: ${associated.join(", ")}; pass an explicit prNumber or --pr`
20675
+ `issue #${issueNumber} \u5173\u8054\u591A\u4E2A PR\uFF1A${associated.join("\u3001")}\uFF1B\u8BF7\u6539\u7528\u660E\u786E prNumber \u6216 --pr`
20475
20676
  );
20476
20677
  }
20477
20678
  const fromIssue = associated[0];
20478
20679
  if (prNumber !== void 0 && prNumber !== fromIssue) {
20479
20680
  throw new CollectorTargetBindError(
20480
- `prNumber ${prNumber} conflicts with issue #${issueNumber} association PR ${fromIssue}`
20681
+ `prNumber ${prNumber} \u4E0E issue #${issueNumber} \u5173\u8054 PR ${fromIssue} \u51B2\u7A81`
20481
20682
  );
20482
20683
  }
20483
20684
  bound = fromIssue;
@@ -20569,8 +20770,8 @@ function createCollectorRoleRuntime(pi, dependencies, hostActions) {
20569
20770
  pi.registerTool({
20570
20771
  name: COLLECTOR_REQUEST_TOOL,
20571
20772
  label: "\u901A\u8FDB\u53F8\u8BF7\u6C42",
20572
- description: "\u6309\u914D\u7F6E\u8BF7\u6C42\u4F53\u4E0E\u5173\u8054\u6807\u8BB0\uFF0C\u5728\u6240\u5F15\u6700\u65B0\u5FEB\u7167 HEAD \u53D1\u4E00\u6B21\u8BF7\u6C42\u3002",
20573
- promptSnippet: "\u6309\u914D\u7F6E\u53D1\u4E00\u6B21\u8BF7\u6C42",
20773
+ description: "\u5728\u6240\u5F15\u6700\u65B0\u5FEB\u7167 HEAD \u53D1\u4E00\u6B21\u8BF7\u6C42\u3002requestId \u53EF\u53D6\u914D\u7F6E\u6E05\u5355\uFF0C\u6216\u89D2\u8272\u4F9D\u624B\u518C/\u73B0\u573A\u5224\u5B9A\u7684\u7A33\u5B9A id\uFF1B\u540E\u8005\u987B\u540C\u65F6\u63D0\u4F9B body\u3002",
20774
+ promptSnippet: "\u53D1\u4E00\u6B21\u8BC4\u5BA1\u8BF7\u6C42",
20574
20775
  parameters: requestSchema,
20575
20776
  async execute(toolCallId, params, signal, _onUpdate, ctx) {
20576
20777
  const activation = getActivation();
@@ -20578,7 +20779,11 @@ function createCollectorRoleRuntime(pi, dependencies, hostActions) {
20578
20779
  try {
20579
20780
  activation.ledger.beginOperational(COLLECTOR_REQUEST_TOOL, toolCallId);
20580
20781
  const details = await activation.ledger.request(
20581
- params,
20782
+ {
20783
+ requestId: params.requestId,
20784
+ snapshotId: params.snapshotId,
20785
+ ...typeof params.body === "string" ? { body: params.body } : {}
20786
+ },
20582
20787
  activation.transport,
20583
20788
  activation.clock,
20584
20789
  signal
@@ -20597,6 +20802,44 @@ function createCollectorRoleRuntime(pi, dependencies, hostActions) {
20597
20802
  }
20598
20803
  }
20599
20804
  });
20805
+ pi.registerTool({
20806
+ name: COLLECTOR_HANDBOOK_WRITE_TOOL,
20807
+ label: "\u901A\u8FDB\u53F8\u624B\u518C\u5199\u5165",
20808
+ description: "\u5199\u5165\u901A\u7528\u624B\u518C\u6216\u5F53\u524D\u4ED3\u5E93\u5DEE\u5F02\u5168\u6587\uFF08\u6574\u4EFD\u66FF\u6362\uFF09\u3002",
20809
+ promptSnippet: "\u66F4\u65B0 bot \u624B\u518C",
20810
+ parameters: handbookWriteSchema,
20811
+ async execute(toolCallId, params, _signal, _onUpdate, ctx) {
20812
+ const activation = getActivation();
20813
+ if (activation === void 0) throw new Error("\u901A\u8FDB\u53F8\u672A\u6FC0\u6D3B");
20814
+ try {
20815
+ activation.ledger.beginOperational(COLLECTOR_HANDBOOK_WRITE_TOOL, toolCallId);
20816
+ const details = await activation.handbook.write(params.scope, params.body);
20817
+ activation.handbookView = await activation.handbook.read();
20818
+ activation.ledger.completeOperational(toolCallId);
20819
+ return {
20820
+ content: [{
20821
+ type: "text",
20822
+ text: `\u624B\u518C\u5DF2\u5199\u5165\uFF1A${details.scope}`
20823
+ }],
20824
+ details: {
20825
+ scope: details.scope,
20826
+ path: details.path,
20827
+ byteLength: details.byteLength,
20828
+ generalSource: activation.handbookView.generalSource,
20829
+ repoSource: activation.handbookView.repoSource
20830
+ }
20831
+ };
20832
+ } catch (error) {
20833
+ if (isCorrectableExecuteError(error)) throw error;
20834
+ hostActions.failInfrastructure(error, ctx, toolCallId);
20835
+ } finally {
20836
+ try {
20837
+ activation.ledger.completeOperational(toolCallId);
20838
+ } catch {
20839
+ }
20840
+ }
20841
+ }
20842
+ });
20600
20843
  pi.registerTool({
20601
20844
  name: COLLECTOR_WAIT_TOOL,
20602
20845
  label: "\u901A\u8FDB\u53F8\u7B49\u5F85",
@@ -20674,13 +20917,14 @@ function createCollectorRoleRuntime(pi, dependencies, hostActions) {
20674
20917
  }
20675
20918
  };
20676
20919
  }
20677
- var CollectorNormalCompletionDeclarationError, CollectorTargetBindError, COLLECTOR_REQUIRED_TOOLS, COLLECTOR_TRANSPORT_FLAGS, observeSchema, readSchema, requestSchema, waitSchema, bindSchema, outputSchema;
20920
+ var CollectorNormalCompletionDeclarationError, CollectorTargetBindError, COLLECTOR_REQUIRED_TOOLS, COLLECTOR_TRANSPORT_FLAGS, observeSchema, readSchema, requestSchema, waitSchema, bindSchema, handbookWriteSchema, outputSchema;
20678
20921
  var init_collector_role = __esm({
20679
20922
  "src/collector-role.ts"() {
20680
20923
  "use strict";
20681
20924
  init_collector_config();
20682
20925
  init_collector_evidence();
20683
20926
  init_collector_github();
20927
+ init_collector_handbook();
20684
20928
  init_collector_ledger();
20685
20929
  init_collector_receipt();
20686
20930
  init_collector_tool_schemas();
@@ -20706,6 +20950,7 @@ var init_collector_role = __esm({
20706
20950
  COLLECTOR_READ_TOOL,
20707
20951
  COLLECTOR_REQUEST_TOOL,
20708
20952
  COLLECTOR_WAIT_TOOL,
20953
+ COLLECTOR_HANDBOOK_WRITE_TOOL,
20709
20954
  COLLECTOR_OUTPUT_TOOL
20710
20955
  ];
20711
20956
  COLLECTOR_TRANSPORT_FLAGS = Object.freeze([
@@ -20736,6 +20981,7 @@ var init_collector_role = __esm({
20736
20981
  requestSchema = collectorRequestArgsSchema;
20737
20982
  waitSchema = collectorWaitArgsSchema;
20738
20983
  bindSchema = collectorBindTargetArgsSchema;
20984
+ handbookWriteSchema = collectorHandbookWriteArgsSchema;
20739
20985
  outputSchema = collectorOutputArgsSchema;
20740
20986
  }
20741
20987
  });
@@ -21846,11 +22092,11 @@ function reliableWindow(cwd, baseline, head) {
21846
22092
  const raw = git2(cwd, ["log", "--format=%P%x1e%s", range]);
21847
22093
  if (raw.length === 0) return [];
21848
22094
  return raw.split("\n").flatMap((line2) => {
21849
- const sep4 = line2.indexOf("");
21850
- if (sep4 < 0) return [];
22095
+ const sep5 = line2.indexOf("");
22096
+ if (sep5 < 0) return [];
21851
22097
  return [{
21852
- subject: line2.slice(sep4 + 1),
21853
- merge: line2.slice(0, sep4).trim().includes(" ")
22098
+ subject: line2.slice(sep5 + 1),
22099
+ merge: line2.slice(0, sep5).trim().includes(" ")
21854
22100
  }];
21855
22101
  });
21856
22102
  }
@@ -22468,8 +22714,8 @@ var init_activation_reconciliation = __esm({
22468
22714
 
22469
22715
  // src/role-runtime.ts
22470
22716
  import { readFileSync as readFileSync5, writeSync as writeSync4 } from "node:fs";
22471
- import { join as join32 } from "node:path";
22472
- import { Value as Value5 } from "typebox/value";
22717
+ import { join as join34 } from "node:path";
22718
+ import { Value as Value4 } from "typebox/value";
22473
22719
  function decodeReviewerAdmittedInputs(getFlag) {
22474
22720
  let reviewScopeKeys;
22475
22721
  const rawScopeKeys = getFlag("ak-review-scope-keys");
@@ -22596,7 +22842,7 @@ function activationStage(role, runtime) {
22596
22842
  }
22597
22843
  }
22598
22844
  function validateActivationTraceRecord(record4) {
22599
- if (!Value5.Check(activationTraceRecordSchema, record4)) {
22845
+ if (!Value4.Check(activationTraceRecordSchema, record4)) {
22600
22846
  throw new TypeError("Activation trace record does not match its closed contract");
22601
22847
  }
22602
22848
  return record4;
@@ -22840,7 +23086,7 @@ function readDiaristRunCoordinates() {
22840
23086
  if (typeof runDirectory !== "string" || runDirectory.trim() === "") {
22841
23087
  throw new Error("diarist accept requires AK_ROLE_RUN_DIR");
22842
23088
  }
22843
- const admittedPath = join32(runDirectory, "admitted-request.json");
23089
+ const admittedPath = join34(runDirectory, "admitted-request.json");
22844
23090
  const admitted = JSON.parse(readFileSync5(admittedPath, "utf8"));
22845
23091
  if (typeof admitted.projectRoot !== "string" || admitted.projectRoot.trim() === "") {
22846
23092
  throw new Error(`diarist admitted-request missing projectRoot (${admittedPath})`);
@@ -23458,7 +23704,8 @@ function createRoleRuntimeExtension(dependencies) {
23458
23704
  dossierEntries: context.sessionManager?.getEntries?.() ?? []
23459
23705
  });
23460
23706
  },
23461
- ...dependencies.createCollectorClock === void 0 ? {} : { createClock: dependencies.createCollectorClock }
23707
+ ...dependencies.createCollectorClock === void 0 ? {} : { createClock: dependencies.createCollectorClock },
23708
+ ...dependencies.loadCollectorHandbookSeed === void 0 ? {} : { loadHandbookSeed: dependencies.loadCollectorHandbookSeed }
23462
23709
  },
23463
23710
  hostActions
23464
23711
  );
@@ -24199,9 +24446,9 @@ __export(in_process_session_exports, {
24199
24446
  DEFAULT_COMPLIANCE_IDLE_MAX_RETRIES: () => DEFAULT_COMPLIANCE_IDLE_MAX_RETRIES,
24200
24447
  openPiInProcessSession: () => openPiInProcessSession
24201
24448
  });
24202
- import { mkdtemp as mkdtemp2, rm as rm2 } from "node:fs/promises";
24449
+ import { mkdtemp as mkdtemp2, rm as rm3 } from "node:fs/promises";
24203
24450
  import { tmpdir as tmpdir2 } from "node:os";
24204
- import { join as join33 } from "node:path";
24451
+ import { join as join35 } from "node:path";
24205
24452
  import {
24206
24453
  createAgentSession,
24207
24454
  DefaultResourceLoader,
@@ -24324,7 +24571,7 @@ async function openPiInProcessSession(options) {
24324
24571
  let scratchDir;
24325
24572
  let resolvedAgentDir = options.agentDir;
24326
24573
  if (resolvedAgentDir === void 0) {
24327
- scratchDir = await mkdtemp2(join33(options.credentialScratchParent ?? tmpdir2(), "ak-institutional-"));
24574
+ scratchDir = await mkdtemp2(join35(options.credentialScratchParent ?? tmpdir2(), "ak-institutional-"));
24328
24575
  resolvedAgentDir = scratchDir;
24329
24576
  }
24330
24577
  try {
@@ -24806,7 +25053,7 @@ async function openPiInProcessSession(options) {
24806
25053
  }
24807
25054
  if (scratchDir !== void 0) {
24808
25055
  try {
24809
- await rm2(scratchDir, { recursive: true, force: true });
25056
+ await rm3(scratchDir, { recursive: true, force: true });
24810
25057
  } catch (error) {
24811
25058
  cleanupFailures.push(error);
24812
25059
  }
@@ -24831,7 +25078,7 @@ async function openPiInProcessSession(options) {
24831
25078
  } catch (openError) {
24832
25079
  if (scratchDir !== void 0) {
24833
25080
  try {
24834
- await rm2(scratchDir, { recursive: true, force: true });
25081
+ await rm3(scratchDir, { recursive: true, force: true });
24835
25082
  } catch (cleanupFailure) {
24836
25083
  throw new AggregateError(
24837
25084
  [openError, cleanupFailure],
@@ -25018,9 +25265,9 @@ var init_reviewer_child_executor = __esm({
25018
25265
 
25019
25266
  // src/reviewer-workspace.ts
25020
25267
  import { spawn as spawn4 } from "node:child_process";
25021
- import { mkdtemp as mkdtemp3, rm as rm3 } from "node:fs/promises";
25268
+ import { mkdtemp as mkdtemp3, rm as rm4 } from "node:fs/promises";
25022
25269
  import { tmpdir as tmpdir3 } from "node:os";
25023
- import { join as join34 } from "node:path";
25270
+ import { join as join36 } from "node:path";
25024
25271
  async function runCommand(command, args, options = {}) {
25025
25272
  return await new Promise((resolve20, reject) => {
25026
25273
  const child = spawn4(command, args, { ...options.cwd === void 0 ? {} : { cwd: options.cwd }, stdio: ["ignore", "pipe", "pipe"], signal: options.signal });
@@ -25069,8 +25316,8 @@ async function prepareSnapshot(accepted, signal, dependencies) {
25069
25316
  if (!sameReviewerPinnedTarget({ repositoryRoot: accepted.repositoryRoot, objectFormat, targetHead }, accepted)) throw new Error("Accepted Reviewer target identity no longer matches the repository");
25070
25317
  await git3(accepted.repositoryRoot, ["cat-file", "-e", `${targetHead}^{commit}`], signal);
25071
25318
  dependencies.fault?.("mirror.before-create");
25072
- mirrorRoot = await mkdtemp3(join34(tmpdir3(), "ak-reviewer-snapshot-"));
25073
- const mirrorPath = join34(mirrorRoot, "repository.git");
25319
+ mirrorRoot = await mkdtemp3(join36(tmpdir3(), "ak-reviewer-snapshot-"));
25320
+ const mirrorPath = join36(mirrorRoot, "repository.git");
25074
25321
  dependencies.fault?.("mirror.create");
25075
25322
  await runCommand("git", ["init", "--bare", `--object-format=${accepted.objectFormat}`, mirrorPath], signal === void 0 ? {} : { signal });
25076
25323
  await git3(mirrorPath, ["fetch", "--no-tags", accepted.repositoryRoot, targetHead], signal);
@@ -25087,7 +25334,7 @@ async function prepareClone(snapshot, signal, dependencies) {
25087
25334
  const target = { repositoryRoot: snapshot.repositoryRoot, objectFormat: snapshot.objectFormat, targetHead: snapshot.targetHead, refs: { ...snapshot.refs } };
25088
25335
  try {
25089
25336
  dependencies.fault?.("workspace.before-create");
25090
- workspace = await mkdtemp3(join34(tmpdir3(), "ak-reviewer-leg-"));
25337
+ workspace = await mkdtemp3(join36(tmpdir3(), "ak-reviewer-leg-"));
25091
25338
  dependencies.fault?.("workspace.init");
25092
25339
  await git3(workspace, ["init", `--object-format=${snapshot.objectFormat}`, "--initial-branch=ak-reviewer-unborn"], signal);
25093
25340
  dependencies.fault?.("workspace.fetch");
@@ -25121,12 +25368,12 @@ function createReviewerWorkspaceOwner(dependencies = {}) {
25121
25368
  return Object.freeze({ target: frozenTarget, workspaces: Object.freeze(workspaces) });
25122
25369
  },
25123
25370
  async dispose(workspace) {
25124
- await rm3(workspace.path, { recursive: true, force: false });
25371
+ await rm4(workspace.path, { recursive: true, force: false });
25125
25372
  return "deleted";
25126
25373
  },
25127
25374
  async shutdown() {
25128
25375
  if (ownedSnapshot === void 0) return;
25129
- cleanupPromise ??= rm3(ownedSnapshot.mirrorRoot, { recursive: true, force: false });
25376
+ cleanupPromise ??= rm4(ownedSnapshot.mirrorRoot, { recursive: true, force: false });
25130
25377
  await cleanupPromise;
25131
25378
  }
25132
25379
  };
@@ -25288,7 +25535,7 @@ var init_reviewer_agent = __esm({
25288
25535
  });
25289
25536
 
25290
25537
  // src/acp-host/production-host.ts
25291
- import { readFile as readFile20 } from "node:fs/promises";
25538
+ import { readFile as readFile21 } from "node:fs/promises";
25292
25539
  import { fileURLToPath as fileURLToPath3 } from "node:url";
25293
25540
 
25294
25541
  // src/canonical-skill-binding.ts
@@ -25502,9 +25749,9 @@ init_auditor_soul();
25502
25749
  init_session_opening_materials();
25503
25750
 
25504
25751
  // src/acp-host/description.ts
25505
- import { join as join35 } from "node:path";
25752
+ import { join as join37 } from "node:path";
25506
25753
  function resolveAcpBinary(description, operatorHome) {
25507
- return join35(operatorHome, ...description.binaryFromHome);
25754
+ return join37(operatorHome, ...description.binaryFromHome);
25508
25755
  }
25509
25756
  function acpStdioArgs(description, model, seat) {
25510
25757
  const { prefix, suffix, modelFlag, thinkingFlag } = description.argv;
@@ -25527,10 +25774,10 @@ init_gatekeeper_pass_envelope();
25527
25774
  init_packaged_role_registry();
25528
25775
  init_method_skill();
25529
25776
  init_role_runtime();
25530
- import { randomUUID as randomUUID6 } from "node:crypto";
25531
- import { mkdir as mkdir5, readFile as readFile18, writeFile as writeFile8 } from "node:fs/promises";
25777
+ import { randomUUID as randomUUID7 } from "node:crypto";
25778
+ import { mkdir as mkdir5, readFile as readFile19, writeFile as writeFile9 } from "node:fs/promises";
25532
25779
  import { createServer } from "node:net";
25533
- import { basename as basename7, dirname as dirname17, join as join36 } from "node:path";
25780
+ import { basename as basename7, dirname as dirname18, join as join38 } from "node:path";
25534
25781
  import { fileURLToPath as fileURLToPath2 } from "node:url";
25535
25782
 
25536
25783
  // src/acp-host/role-turn-host.ts
@@ -25829,7 +26076,7 @@ function buildAcpSkillExpansion(methodSkills, prompt) {
25829
26076
  return Object.freeze({
25830
26077
  name: parsed.name,
25831
26078
  location: method.path,
25832
- content: `References are relative to ${dirname17(method.path)}.
26079
+ content: `References are relative to ${dirname18(method.path)}.
25833
26080
 
25834
26081
  ${method.body}`,
25835
26082
  userMessage: parsed.userMessage
@@ -25881,7 +26128,7 @@ function createComposedAcpRoleTurnHost(config) {
25881
26128
  dependencies: config.roleRuntimeDependencies,
25882
26129
  // Same durable-principal path settlement uses for isAvailable (#617 DK-4 layout).
25883
26130
  sessionFile: config.sessionIdentity.resolveSessionFile(request.principal),
25884
- socketPath: config.socketPath?.(request) ?? `/tmp/ak-acp-mcp-${randomUUID6()}.sock`
26131
+ socketPath: config.socketPath?.(request) ?? `/tmp/ak-acp-mcp-${randomUUID7()}.sock`
25885
26132
  })
25886
26133
  });
25887
26134
  }
@@ -25913,19 +26160,19 @@ async function prepareAcpRoleEnvelope(options) {
25913
26160
  let rejection;
25914
26161
  let infrastructureRoundFailure;
25915
26162
  const hostAbort = new AbortController();
25916
- const runId = request.runDirectory.split("/").filter(Boolean).at(-1) ?? randomUUID6();
26163
+ const runId = request.runDirectory.split("/").filter(Boolean).at(-1) ?? randomUUID7();
25917
26164
  await mkdir5(request.runDirectory, { recursive: true });
25918
26165
  for (const method of request.methods) {
25919
26166
  if (method.kind !== "skill") continue;
25920
- const name = basename7(dirname17(method.path));
25921
- const raw = await readFile18(method.path, "utf8");
26167
+ const name = basename7(dirname18(method.path));
26168
+ const raw = await readFile19(method.path, "utf8");
25922
26169
  methodSkills.set(name, { path: method.path, body: stripSkillFrontmatter(raw).trim() });
25923
26170
  }
25924
- let sessionFile = options.sessionFile ?? join36(request.runDirectory, "session", "session.jsonl");
25925
- await mkdir5(dirname17(sessionFile), { recursive: true });
26171
+ let sessionFile = options.sessionFile ?? join38(request.runDirectory, "session", "session.jsonl");
26172
+ await mkdir5(dirname18(sessionFile), { recursive: true });
25926
26173
  if (request.continuation.kind !== "resume") {
25927
26174
  try {
25928
- await writeFile8(
26175
+ await writeFile9(
25929
26176
  sessionFile,
25930
26177
  `${JSON.stringify({
25931
26178
  type: "session",
@@ -25949,7 +26196,7 @@ async function prepareAcpRoleEnvelope(options) {
25949
26196
  getLeafEntry: () => sessionEntries.at(-1),
25950
26197
  getLeafId: () => runId,
25951
26198
  getEntries: () => sessionEntries,
25952
- getSessionDir: () => dirname17(sessionFile),
26199
+ getSessionDir: () => dirname18(sessionFile),
25953
26200
  getSessionFile: () => sessionFile,
25954
26201
  getHeader: () => ({ type: "session", id: runId }),
25955
26202
  setSessionFile(path) {
@@ -26050,7 +26297,7 @@ async function prepareAcpRoleEnvelope(options) {
26050
26297
  }
26051
26298
  };
26052
26299
  createRoleRuntimeExtension(options.dependencies)(envelope);
26053
- const token = randomUUID6();
26300
+ const token = randomUUID7();
26054
26301
  const server = createServer((socket) => serveSocket(socket));
26055
26302
  function rememberProjectedRejection(details, toolCallId) {
26056
26303
  if (typeof details !== "object" || details === null) return;
@@ -26127,7 +26374,7 @@ async function prepareAcpRoleEnvelope(options) {
26127
26374
  async function invokeAkTool(name, args) {
26128
26375
  const tool = tools.get(name);
26129
26376
  if (tool === void 0) throw new Error(`Unknown AK tool: ${name}`);
26130
- const toolCallId = randomUUID6();
26377
+ const toolCallId = randomUUID7();
26131
26378
  calls.push({ toolCallId, toolName: name });
26132
26379
  sessionEntries.push({
26133
26380
  type: "message",
@@ -26335,7 +26582,7 @@ async function prepareAcpRoleEnvelope(options) {
26335
26582
  message: { role: "user", content: prompt }
26336
26583
  });
26337
26584
  }
26338
- const methodPrompt = (await Promise.all(request.methods.map(({ path }) => readFile18(path, "utf8")))).join("\n\n");
26585
+ const methodPrompt = (await Promise.all(request.methods.map(({ path }) => readFile19(path, "utf8")))).join("\n\n");
26339
26586
  const promptResults = await emit("before_agent_start", {
26340
26587
  prompt,
26341
26588
  systemPrompt: methodPrompt,
@@ -26396,12 +26643,12 @@ async function prepareAcpRoleEnvelope(options) {
26396
26643
  // src/acp-host/seat-profile-soul.ts
26397
26644
  import { constants as constants3 } from "node:fs";
26398
26645
  import { access as access4, copyFile, lstat as lstat6, mkdir as mkdir6, readlink, symlink, unlink as unlink4 } from "node:fs/promises";
26399
- import { dirname as dirname18, join as join37, relative as relative3, resolve as resolve19 } from "node:path";
26646
+ import { dirname as dirname19, join as join39, relative as relative3, resolve as resolve19 } from "node:path";
26400
26647
  function seatProfileName(spec, role) {
26401
26648
  return `${spec.namePrefix}${role}`;
26402
26649
  }
26403
26650
  function packageRoleSoulPath(packageRoot, role) {
26404
- return join37(packageRoot, "souls", `${role}.md`);
26651
+ return join39(packageRoot, "souls", `${role}.md`);
26405
26652
  }
26406
26653
  async function pathExists(path) {
26407
26654
  try {
@@ -26418,16 +26665,16 @@ async function ensureSeatProfileSoul(options) {
26418
26665
  if (!await pathExists(soulTarget)) {
26419
26666
  throw new Error(`packaged role soul missing: ${soulTarget}`);
26420
26667
  }
26421
- const profilesRoot = join37(operatorHome, ...spec.profilesRootFromHome);
26422
- const profileDir = join37(profilesRoot, profileName);
26423
- const hostRoot = dirname18(profilesRoot);
26424
- const soulPath = join37(profileDir, spec.soulFileName);
26668
+ const profilesRoot = join39(operatorHome, ...spec.profilesRootFromHome);
26669
+ const profileDir = join39(profilesRoot, profileName);
26670
+ const hostRoot = dirname19(profilesRoot);
26671
+ const soulPath = join39(profileDir, spec.soulFileName);
26425
26672
  if (!await pathExists(profileDir)) {
26426
26673
  await mkdir6(profileDir, { recursive: true });
26427
26674
  for (const name of ["auth.json", ".env", "config.yaml"]) {
26428
- const source = join37(hostRoot, name);
26675
+ const source = join39(hostRoot, name);
26429
26676
  if (!await pathExists(source)) continue;
26430
- await copyFile(source, join37(profileDir, name));
26677
+ await copyFile(source, join39(profileDir, name));
26431
26678
  }
26432
26679
  } else {
26433
26680
  await mkdir6(profileDir, { recursive: true });
@@ -26453,17 +26700,17 @@ async function ensureSeatProfileSoul(options) {
26453
26700
  }
26454
26701
 
26455
26702
  // src/acp-host/session-identity.ts
26456
- import { mkdir as mkdir7, readFile as readFile19, rename, writeFile as writeFile9 } from "node:fs/promises";
26457
- import { dirname as dirname19, join as join38 } from "node:path";
26703
+ import { mkdir as mkdir7, readFile as readFile20, rename as rename2, writeFile as writeFile10 } from "node:fs/promises";
26704
+ import { dirname as dirname20, join as join40 } from "node:path";
26458
26705
  function createAcpSessionIdentityAuthority(authority, sessionBindingFile) {
26459
- const bindingPath = (principal) => join38(authority.decode(principal).sessionDirectory, sessionBindingFile);
26706
+ const bindingPath = (principal) => join40(authority.decode(principal).sessionDirectory, sessionBindingFile);
26460
26707
  return {
26461
26708
  resolveSessionFile(principal) {
26462
26709
  return authority.decode(principal).sessionFile;
26463
26710
  },
26464
26711
  async load(principal) {
26465
26712
  try {
26466
- const value = JSON.parse(await readFile19(bindingPath(principal), "utf8"));
26713
+ const value = JSON.parse(await readFile20(bindingPath(principal), "utf8"));
26467
26714
  if (typeof value !== "object" || value === null || typeof value.sessionId !== "string") {
26468
26715
  throw new Error("durable ACP session binding is invalid");
26469
26716
  }
@@ -26475,11 +26722,11 @@ function createAcpSessionIdentityAuthority(authority, sessionBindingFile) {
26475
26722
  },
26476
26723
  async bind(principal, sessionId) {
26477
26724
  const target = bindingPath(principal);
26478
- await mkdir7(dirname19(target), { recursive: true });
26725
+ await mkdir7(dirname20(target), { recursive: true });
26479
26726
  const temporary = `${target}.${process.pid}.tmp`;
26480
- await writeFile9(temporary, `${JSON.stringify({ sessionId })}
26727
+ await writeFile10(temporary, `${JSON.stringify({ sessionId })}
26481
26728
  `, { encoding: "utf8", mode: 384 });
26482
- await rename(temporary, target);
26729
+ await rename2(temporary, target);
26483
26730
  }
26484
26731
  };
26485
26732
  }
@@ -26488,6 +26735,9 @@ function createAcpSessionIdentityAuthority(authority, sessionBindingFile) {
26488
26735
  var navigatorRoutePlaybookPath = fileURLToPath3(
26489
26736
  new URL("../../resources/navigator-route-playbook.md", import.meta.url)
26490
26737
  );
26738
+ var collectorHandbookSeedPath = fileURLToPath3(
26739
+ new URL("../../resources/collector-bot-handbook.md", import.meta.url)
26740
+ );
26491
26741
  function createAcpRoleRuntimeDependencies(packageRoot) {
26492
26742
  const doctorAuditor = createPiDoctorAuditor();
26493
26743
  const reviewerAgent = createPerDispatchReviewerAgent({ packageRoot });
@@ -26495,13 +26745,14 @@ function createAcpRoleRuntimeDependencies(packageRoot) {
26495
26745
  return {
26496
26746
  loadJudgeSoul: () => loadMainRoleSessionMaterials("judge"),
26497
26747
  loadFixerSoul: () => loadMainRoleSessionMaterials("fixer"),
26498
- loadFixPacket: (path) => readFile20(path, "utf8"),
26748
+ loadFixPacket: (path) => readFile21(path, "utf8"),
26499
26749
  loadCoderSoul: () => loadMainRoleSessionMaterials("coder"),
26500
- loadCoderTask: (path) => readFile20(path, "utf8"),
26750
+ loadCoderTask: (path) => readFile21(path, "utf8"),
26501
26751
  loadReviewerSoul: () => loadMainRoleSessionMaterials("reviewer"),
26502
26752
  createReviewerPinnedGitReader: () => createReviewerPinnedGitReader(),
26503
26753
  createReviewerIssueFetcher: () => createGhIssueSoftFetcher(),
26504
26754
  loadCollectorSoul: () => loadMainRoleSessionMaterials("collector"),
26755
+ loadCollectorHandbookSeed: () => readFile21(collectorHandbookSeedPath, "utf8"),
26505
26756
  createCollectorTransport: () => createGhCollectorGitHubTransport(),
26506
26757
  loadDoctorSoul: () => loadMainRoleSessionMaterials("doctor"),
26507
26758
  loadDoctorCase,
@@ -26515,7 +26766,7 @@ function createAcpRoleRuntimeDependencies(packageRoot) {
26515
26766
  loadDiaristSoul: () => loadMainRoleSessionMaterials("diarist"),
26516
26767
  loadNotarySourceRun: loadNotarySourceRunLocator,
26517
26768
  loadMergerSoul: () => loadMainRoleSessionMaterials("merger"),
26518
- loadMergerInput: async (path) => JSON.parse(await readFile20(path, "utf8")),
26769
+ loadMergerInput: async (path) => JSON.parse(await readFile21(path, "utf8")),
26519
26770
  createMergerGitState: (repositoryRoot) => createProductionMergerGitState(repositoryRoot),
26520
26771
  async loadCanonicalSkillBinding(name) {
26521
26772
  if (name === "tdd") {
@@ -26544,7 +26795,7 @@ function createAcpRoleRuntimeDependencies(packageRoot) {
26544
26795
  authority: options.authority,
26545
26796
  invocationId: options.invocationId,
26546
26797
  loadSoul: () => loadMainRoleSessionMaterials("navigator"),
26547
- loadRoutePlaybook: () => readFile20(navigatorRoutePlaybookPath, "utf8"),
26798
+ loadRoutePlaybook: () => readFile21(navigatorRoutePlaybookPath, "utf8"),
26548
26799
  loadRoleHelp: async (role) => formatNavigatorRoleHelp(role),
26549
26800
  createSession: navigatorSessionFactory,
26550
26801
  ...options.contextError === void 0 ? {} : { contextError: options.contextError },