@akagilnc/pi-workflow-roles 0.1.3873 → 0.1.3886

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.
@@ -418,7 +418,7 @@ function normalizeReviewComment(raw) {
418
418
  function createGhApiRunner(options = {}) {
419
419
  const spawnImpl = options.spawnImpl ?? spawn;
420
420
  return async (args, runOptions = {}) => {
421
- return await new Promise((resolve19, reject) => {
421
+ return await new Promise((resolve20, reject) => {
422
422
  const signal = runOptions.signal;
423
423
  if (signal?.aborted) {
424
424
  reject(signal.reason ?? new Error("aborted"));
@@ -491,11 +491,11 @@ function createGhApiRunner(options = {}) {
491
491
  const value = line2.slice(idx + 1).trim();
492
492
  headers[name] = value;
493
493
  }
494
- resolve19({ status, headers, bodyText });
494
+ resolve20({ status, headers, bodyText });
495
495
  return;
496
496
  }
497
497
  if (code === 0) {
498
- resolve19({ status: 200, headers: {}, bodyText: stdout });
498
+ resolve20({ status: 200, headers: {}, bodyText: stdout });
499
499
  return;
500
500
  }
501
501
  const failure2 = new Error(
@@ -884,10 +884,10 @@ __export(session_assistant_usage_exports, {
884
884
  });
885
885
  import { join as join2 } from "node:path";
886
886
  async function readAssistantUsageFromSessionFile(sessionFile) {
887
- const { readFile: readFile22 } = await import("node:fs/promises");
887
+ const { readFile: readFile23 } = await import("node:fs/promises");
888
888
  let text;
889
889
  try {
890
- text = await readFile22(sessionFile, "utf8");
890
+ text = await readFile23(sessionFile, "utf8");
891
891
  } catch (error) {
892
892
  if (error?.code === "ENOENT") return void 0;
893
893
  throw error;
@@ -1488,7 +1488,7 @@ async function spawnEngineDetourOnce(input) {
1488
1488
  }
1489
1489
  const command = input.argv[0];
1490
1490
  const args = input.argv.slice(1);
1491
- return await new Promise((resolve19, reject) => {
1491
+ return await new Promise((resolve20, reject) => {
1492
1492
  let settled = false;
1493
1493
  const signal = input.signal;
1494
1494
  const child = spawn2(command, args, {
@@ -1518,7 +1518,7 @@ async function spawnEngineDetourOnce(input) {
1518
1518
  if (signal !== void 0) {
1519
1519
  signal.removeEventListener("abort", onAbort);
1520
1520
  }
1521
- resolve19(result);
1521
+ resolve20(result);
1522
1522
  };
1523
1523
  const onAbort = () => {
1524
1524
  fail5(signal !== void 0 ? abortReasonError(signal) : new Error("aborted"));
@@ -2487,18 +2487,6 @@ var init_doctor_contracts = __esm({
2487
2487
  }
2488
2488
  });
2489
2489
 
2490
- // src/git-object-id.ts
2491
- function isFullGitObjectId(value) {
2492
- return typeof value === "string" && FULL_GIT_OBJECT_ID_RE.test(value);
2493
- }
2494
- var FULL_GIT_OBJECT_ID_RE;
2495
- var init_git_object_id = __esm({
2496
- "src/git-object-id.ts"() {
2497
- "use strict";
2498
- FULL_GIT_OBJECT_ID_RE = /^(?:[0-9a-f]{40}|[0-9a-f]{64})$/;
2499
- }
2500
- });
2501
-
2502
2490
  // src/exact-utf8.ts
2503
2491
  function exactUtf8(bytes, label) {
2504
2492
  let text;
@@ -2517,35 +2505,11 @@ var init_exact_utf8 = __esm({
2517
2505
  }
2518
2506
  });
2519
2507
 
2520
- // src/sha256.ts
2521
- import { createHash as createHash3 } from "node:crypto";
2522
- function sha256Hex(bytes) {
2523
- return createHash3("sha256").update(bytes).digest("hex");
2524
- }
2525
- var init_sha256 = __esm({
2526
- "src/sha256.ts"() {
2527
- "use strict";
2528
- }
2529
- });
2530
-
2531
2508
  // src/merger-contracts.ts
2532
2509
  import { Type as Type10 } from "typebox";
2533
2510
  function fail3(message = "Merger input violates its exact contract") {
2534
2511
  throw new MergerInputContractError(message);
2535
2512
  }
2536
- function canonicalPath(path) {
2537
- return typeof path === "string" && path.length > 0 && !path.startsWith("/") && !path.includes("\0") && path.split("/").every((part) => part !== "" && part !== "." && part !== "..");
2538
- }
2539
- function validatePathSet(value, label) {
2540
- if (!Array.isArray(value) || value.length === 0 || !value.every(canonicalPath)) fail3(`Merger ${label} must be a non-empty canonical path set`);
2541
- return value;
2542
- }
2543
- function validateMaterial(value, label) {
2544
- if (!record2(value) || typeof value.bytesBase64 !== "string" || typeof value.sha256 !== "string") fail3(`Merger ${label} material is malformed`);
2545
- const bytes = Buffer.from(value.bytesBase64, "base64");
2546
- exactUtf8(bytes, `Merger ${label} material`);
2547
- if (sha256Hex(bytes) !== value.sha256) fail3(`Merger ${label} material digest mismatch`);
2548
- }
2549
2513
  function deepFreeze(value) {
2550
2514
  if (value && typeof value === "object") {
2551
2515
  for (const child of Object.values(value)) deepFreeze(child);
@@ -2553,55 +2517,47 @@ function deepFreeze(value) {
2553
2517
  }
2554
2518
  return value;
2555
2519
  }
2520
+ function readMaterial(value, label) {
2521
+ if (!record2(value) || typeof value.bytesBase64 !== "string") fail3(`Merger ${label} material is malformed`);
2522
+ exactUtf8(Buffer.from(value.bytesBase64, "base64"), `Merger ${label} material`);
2523
+ return { bytesBase64: value.bytesBase64, sha256: typeof value.sha256 === "string" ? value.sha256 : "" };
2524
+ }
2556
2525
  function validateMergerInput(value) {
2557
- if (!record2(value) || blank(value.attemptId) || !isFullGitObjectId(value.targetObjectId) || !isFullGitObjectId(value.sourceObjectId) || value.targetObjectId.length !== value.sourceObjectId.length) fail3("Merger input has invalid identity or object ID");
2558
- if (!record2(value.materials)) fail3();
2559
- for (const key of ["task", "authority", "targetIntent", "sourceIntent"]) validateMaterial(value.materials[key], key);
2560
- const conflicts = validatePathSet(value.expectedConflictPaths, "expected conflict paths");
2561
- const scope = validatePathSet(value.resolutionScope, "resolution scope");
2562
- if (!conflicts.every((path) => scope.includes(path))) fail3("Merger resolution scope must contain the complete conflict set");
2563
- if (!Array.isArray(value.authorizedChecks)) fail3("Merger authorized checks are malformed");
2564
- for (const check of value.authorizedChecks) {
2565
- if (!record2(check) || !Array.isArray(check.argv) || check.argv.length === 0 || check.argv.some(blank)) fail3("Merger authorized check is malformed");
2566
- }
2567
- return deepFreeze(structuredClone(value));
2568
- }
2569
- function validateMergerOutput(value, expectedAttemptId) {
2570
- if (!record2(value) || expectedAttemptId !== void 0 && value.attemptId !== expectedAttemptId) throw new Error("\u5408\u5E76\u56DE\u6267 attempt \u4E0D\u5339\u914D");
2526
+ if (!record2(value) || blank(value.attemptId)) fail3("Merger input requires a non-empty attemptId for accounting");
2527
+ if (!record2(value.materials)) fail3("Merger materials are missing");
2528
+ 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") };
2529
+ const authorizedChecks = Array.isArray(value.authorizedChecks) ? value.authorizedChecks.filter((check) => record2(check)).map((c) => ({ name: asString(c.name), argv: asStringArray2(c.argv).filter((a) => a.trim().length > 0) })).filter((c) => c.name.trim().length > 0 && c.argv.length > 0) : [];
2530
+ return deepFreeze(structuredClone({ attemptId: value.attemptId.trim(), targetObjectId: asString(value.targetObjectId), sourceObjectId: asString(value.sourceObjectId), materials, expectedConflictPaths: asStringArray2(value.expectedConflictPaths), resolutionScope: asStringArray2(value.resolutionScope), authorizedChecks }));
2531
+ }
2532
+ function validateMergerOutput(value) {
2533
+ if (!record2(value)) throw new Error("\u5408\u5E76\u56DE\u6267\u65E0\u5DF2\u8BC6\u522B\u7684\u6267\u884C\u5224\u522B");
2571
2534
  const status = typeof value.status === "string" ? value.status : void 0;
2572
- if (status === "completed" && isFullGitObjectId(value.mergeCommitId)) return structuredClone(value);
2573
- if (status === "escalate") return structuredClone(value);
2535
+ if (status === "completed" || status === "escalate") return structuredClone(value);
2574
2536
  throw new Error("\u5408\u5E76\u56DE\u6267\u65E0\u5DF2\u8BC6\u522B\u7684\u6267\u884C\u5224\u522B");
2575
2537
  }
2576
- var oidPattern, materialSchema, checkSchema, mergerInputSchema, mergerOutputVariants, mergerOutputSchema, MERGER_OUTPUT_TOOL_NAME, MERGER_ACCEPTED_TEXT, record2, blank, MergerInputContractError;
2538
+ var materialSchema, checkSchema, mergerInputSchema, mergerOutputVariants, mergerOutputSchema, MERGER_OUTPUT_TOOL_NAME, MERGER_ACCEPTED_TEXT, record2, blank, MergerInputContractError, asString, asStringArray2;
2577
2539
  var init_merger_contracts = __esm({
2578
2540
  "src/merger-contracts.ts"() {
2579
2541
  "use strict";
2580
- init_git_object_id();
2581
2542
  init_exact_utf8();
2582
- init_sha256();
2583
2543
  init_open_tool_schema();
2584
2544
  init_terminating_infrastructure();
2585
- oidPattern = "^(?:[0-9a-f]{40}|[0-9a-f]{64})$";
2586
2545
  materialSchema = Type10.Object({ bytesBase64: Type10.String(), sha256: Type10.String() }, { additionalProperties: false });
2587
2546
  checkSchema = Type10.Object({ name: Type10.String({ minLength: 1 }), argv: Type10.Array(Type10.String({ minLength: 1 }), { minItems: 1 }) }, { additionalProperties: false });
2588
2547
  mergerInputSchema = Type10.Object({
2589
- version: Type10.Literal(1),
2590
- attemptId: Type10.String({ minLength: 1 }),
2591
- targetObjectId: Type10.String({ pattern: oidPattern }),
2592
- sourceObjectId: Type10.String({ pattern: oidPattern }),
2548
+ attemptId: Type10.String({ minLength: 1, description: "\u5BF9\u8D26 attempt \u8EAB\u4EFD\uFF08transport\uFF09" }),
2549
+ targetObjectId: Type10.String({ description: "\u6750\u6599\uFF1Atarget parent OID\uFF1B\u53EF\u7A7A" }),
2550
+ sourceObjectId: Type10.String({ description: "\u6750\u6599\uFF1Asource parent OID\uFF1B\u53EF\u7A7A" }),
2593
2551
  materials: Type10.Object({ task: materialSchema, authority: materialSchema, targetIntent: materialSchema, sourceIntent: materialSchema }, { additionalProperties: false }),
2594
- expectedConflictPaths: Type10.Array(Type10.String({ minLength: 1 }), { minItems: 1 }),
2595
- resolutionScope: Type10.Array(Type10.String({ minLength: 1 }), { minItems: 1 }),
2552
+ expectedConflictPaths: Type10.Array(Type10.String(), { description: "\u6750\u6599\uFF1A\u5F53\u524D\u672A\u5408\u5E76\u8DEF\u5F84\uFF1B\u53EF\u7A7A" }),
2553
+ resolutionScope: Type10.Array(Type10.String(), { description: "\u6750\u6599\uFF1A\u89E3\u6790\u8303\u56F4\u63D0\u793A\uFF1B\u53EF\u7A7A" }),
2596
2554
  authorizedChecks: Type10.Array(checkSchema)
2597
2555
  }, { additionalProperties: false });
2598
2556
  mergerOutputVariants = Type10.Union([
2599
- Type10.Object({ status: Type10.Literal("completed", { description: "completed \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8" }), attemptId: Type10.String({ minLength: 1, description: "\u5DF2\u53D7\u7406\u5408\u5E76 attempt \u8EAB\u4EFD" }), report: Type10.String({ minLength: 1, description: "\u5982\u5B9E\u7ED3\u679C\u62A5\u544A" }), mergeCommitId: Type10.String({ pattern: oidPattern, description: "\u5DF2\u6838\u9A8C\u7684\u5B8C\u6210\u5408\u5E76 commit object ID" }) }, { additionalProperties: false }),
2600
- Type10.Object({ status: Type10.Literal("escalate", { description: "escalate \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8" }), attemptId: Type10.String({ minLength: 1, description: "\u5DF2\u53D7\u7406\u5408\u5E76 attempt \u8EAB\u4EFD" }), diagnosis: Type10.String({ minLength: 1, description: "\u5408\u5E76\u5B8C\u6210\u9700\u5347\u7EA7\u7684\u539F\u56E0" }), report: Type10.String({ minLength: 1, description: "\u5982\u5B9E\u7ED3\u679C\u62A5\u544A" }) }, { additionalProperties: false })
2557
+ Type10.Object({ status: Type10.Literal("completed", { description: "completed \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8" }), attemptId: Type10.String({ minLength: 1, description: "\u5DF2\u53D7\u7406\u5408\u5E76 attempt \u8EAB\u4EFD" }), report: Type10.String({ minLength: 1, description: "\u5982\u5B9E\u7ED3\u679C\u62A5\u544A" }), mergeCommitId: Type10.String({ description: "\u5B8C\u6210\u5408\u5E76 commit object ID" }) }, { additionalProperties: false }),
2558
+ Type10.Object({ status: Type10.Literal("escalate", { description: "escalate \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8" }), attemptId: Type10.String({ minLength: 1, description: "\u5DF2\u53D7\u7406\u5408\u5E76 attempt \u8EAB\u4EFD" }), diagnosis: Type10.String({ minLength: 1, description: "\u5408\u5E76\u65E0\u6CD5\u6216\u4E0D\u5E94\u7531\u672C\u5E2D\u5B8C\u6210\u7684\u539F\u56E0\uFF08\u542B\u65E0\u8FDB\u884C\u4E2D\u5408\u5E76\u3001\u65E0\u6D3B\u53EF\u5E72\u3001\u9700\u65B0\u7684\u4EA7\u54C1/\u6743\u529B\u51B3\u5B9A\uFF09" }), report: Type10.String({ minLength: 1, description: "\u5982\u5B9E\u7ED3\u679C\u62A5\u544A" }) }, { additionalProperties: false })
2601
2559
  ]);
2602
- mergerOutputSchema = withInfrastructureFailureDeclaration(
2603
- openToolObjectFromUnion(mergerOutputVariants)
2604
- );
2560
+ mergerOutputSchema = withInfrastructureFailureDeclaration(openToolObjectFromUnion(mergerOutputVariants));
2605
2561
  MERGER_OUTPUT_TOOL_NAME = "ak_merger_output";
2606
2562
  MERGER_ACCEPTED_TEXT = "\u5408\u5E76\u56DE\u6267\u5DF2\u63A5\u53D7";
2607
2563
  record2 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
@@ -2612,6 +2568,8 @@ var init_merger_contracts = __esm({
2612
2568
  this.name = "MergerInputContractError";
2613
2569
  }
2614
2570
  };
2571
+ asString = (v) => typeof v === "string" ? v : "";
2572
+ asStringArray2 = (v) => Array.isArray(v) ? v.filter((item) => typeof item === "string") : [];
2615
2573
  }
2616
2574
  });
2617
2575
 
@@ -3175,7 +3133,7 @@ var init_sitian_contracts = __esm({
3175
3133
  });
3176
3134
 
3177
3135
  // src/sitian-appender.ts
3178
- import { createHash as createHash4, randomUUID } from "node:crypto";
3136
+ import { createHash as createHash3, randomUUID } from "node:crypto";
3179
3137
  import {
3180
3138
  appendFileSync,
3181
3139
  existsSync,
@@ -3191,7 +3149,7 @@ function errorCodeOf(error) {
3191
3149
  return error.code;
3192
3150
  }
3193
3151
  function identityClaimPath(recordFile, identity) {
3194
- const digest = createHash4("sha256").update(identity, "utf8").digest("hex");
3152
+ const digest = createHash3("sha256").update(identity, "utf8").digest("hex");
3195
3153
  return `${recordFile}.id-${digest}`;
3196
3154
  }
3197
3155
  function createExclusiveFile(path, contents) {
@@ -3335,7 +3293,7 @@ function resolveSitianRecordPathInLedger(input, ledgerHome) {
3335
3293
  } else {
3336
3294
  subjectStr = JSON.stringify(input.subject);
3337
3295
  }
3338
- const digest = createHash4("sha256").update(subjectStr).digest("hex").slice(0, 32);
3296
+ const digest = createHash3("sha256").update(subjectStr).digest("hex").slice(0, 32);
3339
3297
  sessionDir = join6(bookDir, category, digest);
3340
3298
  } else {
3341
3299
  sessionDir = join6(bookDir, category);
@@ -3809,6 +3767,17 @@ var init_run_ticket_number = __esm({
3809
3767
  }
3810
3768
  });
3811
3769
 
3770
+ // src/sha256.ts
3771
+ import { createHash as createHash4 } from "node:crypto";
3772
+ function sha256Hex(bytes) {
3773
+ return createHash4("sha256").update(bytes).digest("hex");
3774
+ }
3775
+ var init_sha256 = __esm({
3776
+ "src/sha256.ts"() {
3777
+ "use strict";
3778
+ }
3779
+ });
3780
+
3812
3781
  // src/audit-escalation.ts
3813
3782
  function buildAuditEscalationResult(decision, deliveredOutput) {
3814
3783
  const auditOwned = {
@@ -4524,8 +4493,23 @@ var init_collector_target = __esm({
4524
4493
  }
4525
4494
  });
4526
4495
 
4496
+ // src/git-object-id.ts
4497
+ function isFullGitObjectId(value) {
4498
+ return typeof value === "string" && FULL_GIT_OBJECT_ID_RE.test(value);
4499
+ }
4500
+ var FULL_GIT_OBJECT_ID_RE;
4501
+ var init_git_object_id = __esm({
4502
+ "src/git-object-id.ts"() {
4503
+ "use strict";
4504
+ FULL_GIT_OBJECT_ID_RE = /^(?:[0-9a-f]{40}|[0-9a-f]{64})$/;
4505
+ }
4506
+ });
4507
+
4527
4508
  // src/merger-git-state.ts
4528
4509
  import { execFile as execFile2 } from "node:child_process";
4510
+ import { access as access2, readFile as readFile7 } from "node:fs/promises";
4511
+ import { constants as fsConstants } from "node:fs";
4512
+ import { isAbsolute as isAbsolute4, resolve as resolve8 } from "node:path";
4529
4513
  import { promisify as promisify2 } from "node:util";
4530
4514
  async function git(cwd, args) {
4531
4515
  const { stdout } = await execFileAsync2("git", args, { cwd, encoding: "buffer", maxBuffer: 16 * 1024 * 1024 });
@@ -4536,10 +4520,31 @@ function line(bytes, label) {
4536
4520
  if (!value) throw new Error(`${label} is empty`);
4537
4521
  return value;
4538
4522
  }
4539
- function nulPaths(bytes, label) {
4540
- const raw = exactUtf8(bytes, label);
4541
- if (raw.length > 0 && !raw.endsWith("\0")) throw new Error(`${label} is not NUL terminated`);
4542
- return raw.split("\0").filter(Boolean).sort((a, b) => Buffer.compare(Buffer.from(a), Buffer.from(b)));
4523
+ async function pathExists(path) {
4524
+ try {
4525
+ await access2(path, fsConstants.F_OK);
4526
+ return true;
4527
+ } catch (error) {
4528
+ if (error.code === "ENOENT") return false;
4529
+ throw error;
4530
+ }
4531
+ }
4532
+ async function requireInsideWorkTree(cwd) {
4533
+ const stdout = await git(cwd, ["rev-parse", "--is-inside-work-tree"]);
4534
+ if (exactUtf8(stdout, "Git worktree check").trim() !== "true") throw new Error("Assigned path is not inside a Git work tree");
4535
+ }
4536
+ async function tryResolveCommit(cwd, rev) {
4537
+ let stdout;
4538
+ try {
4539
+ const res = await execFileAsync2("git", ["rev-parse", "--verify", "--quiet", `${rev}^{commit}`], { cwd, encoding: "buffer", maxBuffer: 16 * 1024 * 1024 });
4540
+ stdout = new Uint8Array(res.stdout);
4541
+ } catch (error) {
4542
+ if (error.code === 1) return void 0;
4543
+ throw error;
4544
+ }
4545
+ const oid = line(stdout, `Git ${rev}`);
4546
+ if (!isFullGitObjectId(oid)) throw new Error(`Git ${rev} identity is unavailable or invalid`);
4547
+ return oid;
4543
4548
  }
4544
4549
  async function unmerged(cwd) {
4545
4550
  const raw = exactUtf8(await git(cwd, ["ls-files", "-u", "-z"]), "Git unmerged index");
@@ -4552,40 +4557,39 @@ async function unmerged(cwd) {
4552
4557
  }
4553
4558
  return [...paths].sort((a, b) => Buffer.compare(Buffer.from(a), Buffer.from(b)));
4554
4559
  }
4560
+ async function resolveHeadMaterial(cwd) {
4561
+ const commit = await tryResolveCommit(cwd, "HEAD");
4562
+ if (commit !== void 0) return commit;
4563
+ try {
4564
+ await execFileAsync2("git", ["rev-parse", "--verify", "--quiet", "HEAD"], { cwd, encoding: "buffer", maxBuffer: 16 * 1024 * 1024 });
4565
+ } catch (error) {
4566
+ if (error.code === 1) return "";
4567
+ throw error;
4568
+ }
4569
+ throw new Error("Git HEAD identity is unavailable or invalid");
4570
+ }
4555
4571
  function createProductionMergerGitState(repositoryRoot = process.cwd()) {
4556
4572
  return {
4557
4573
  async activeMerge() {
4558
- const targetObjectId = line(await git(repositoryRoot, ["rev-parse", "--verify", "HEAD"]), "Git HEAD");
4559
- let mergeHeadRaw;
4560
- try {
4561
- mergeHeadRaw = await git(repositoryRoot, ["rev-parse", "--verify", "MERGE_HEAD"]);
4562
- } catch {
4563
- throw new Error("Assigned repository does not have one ordinary in-progress merge");
4564
- }
4565
- const mergeHeads = exactUtf8(mergeHeadRaw, "Git MERGE_HEAD").trim().split(/\r?\n/).filter(Boolean);
4566
- if (mergeHeads.length !== 1 || !isFullGitObjectId(targetObjectId) || !isFullGitObjectId(mergeHeads[0]) || targetObjectId.length !== mergeHeads[0].length) throw new Error("Assigned repository does not have one ordinary in-progress merge");
4567
- let automaticMergeTreeRaw;
4568
- try {
4569
- automaticMergeTreeRaw = await git(repositoryRoot, ["rev-parse", "--verify", "AUTO_MERGE^{tree}"]);
4570
- } catch {
4571
- throw new Error("Git automatic merge tree identity is unavailable or invalid");
4574
+ await requireInsideWorkTree(repositoryRoot);
4575
+ const targetObjectId = await resolveHeadMaterial(repositoryRoot);
4576
+ const mergeHeadReported = line(await git(repositoryRoot, ["rev-parse", "--git-path", "MERGE_HEAD"]), "Git MERGE_HEAD path");
4577
+ const mergeHeadPath = isAbsolute4(mergeHeadReported) ? mergeHeadReported : resolve8(repositoryRoot, mergeHeadReported);
4578
+ let sourceObjectId = "";
4579
+ if (await pathExists(mergeHeadPath)) {
4580
+ const raw = exactUtf8(await readFile7(mergeHeadPath), "Git MERGE_HEAD");
4581
+ const mergeHeads = raw.trim().split(/\r?\n/).map((row) => row.trim()).filter(Boolean);
4582
+ if (mergeHeads.length === 0) throw new Error("Git MERGE_HEAD is empty");
4583
+ if (mergeHeads.length !== 1) throw new Error("Assigned repository does not have one ordinary in-progress merge");
4584
+ const source = mergeHeads[0];
4585
+ if (!isFullGitObjectId(source)) throw new Error("Git MERGE_HEAD identity is unavailable or invalid");
4586
+ const resolved = await tryResolveCommit(repositoryRoot, source);
4587
+ if (resolved === void 0 || targetObjectId !== "" && resolved.length !== targetObjectId.length) {
4588
+ throw new Error("Git MERGE_HEAD identity is unavailable or invalid");
4589
+ }
4590
+ sourceObjectId = resolved;
4572
4591
  }
4573
- const automaticMergeTreeId = line(automaticMergeTreeRaw, "Git automatic merge tree");
4574
- if (!isFullGitObjectId(automaticMergeTreeId) || automaticMergeTreeId.length !== targetObjectId.length) throw new Error("Git automatic merge tree identity is unavailable or invalid");
4575
- return { targetObjectId, sourceObjectId: mergeHeads[0], unmergedPaths: await unmerged(repositoryRoot), automaticMergeTreeId };
4576
- },
4577
- async completedMerge(mergeCommitId, automaticMergeTreeId) {
4578
- if (!isFullGitObjectId(mergeCommitId) || !isFullGitObjectId(automaticMergeTreeId) || mergeCommitId.length !== automaticMergeTreeId.length) throw new Error("Merger completion object ID is invalid");
4579
- const identity = exactUtf8(await git(repositoryRoot, ["show", "-s", "--format=%H%x00%P", mergeCommitId]), "Git merge commit").trimEnd().split("\0");
4580
- if (identity.length !== 2 || identity[0] !== mergeCommitId) throw new Error("Git merge completion identity drifted");
4581
- const parentObjectIds = identity[1].split(" ").filter(Boolean);
4582
- const currentHead = line(await git(repositoryRoot, ["rev-parse", "--verify", "HEAD"]), "Git HEAD");
4583
- const status = await git(repositoryRoot, ["status", "--porcelain=v1", "-z", "--untracked-files=all"]);
4584
- const frozenTree = line(await git(repositoryRoot, ["rev-parse", "--verify", `${automaticMergeTreeId}^{tree}`]), "Git frozen automatic merge tree");
4585
- if (frozenTree !== automaticMergeTreeId) throw new Error("Git frozen automatic merge tree identity drifted");
4586
- const mergeTree = line(await git(repositoryRoot, ["rev-parse", "--verify", `${mergeCommitId}^{tree}`]), "Git completed merge tree");
4587
- const resolutionChangedPaths = nulPaths(await git(repositoryRoot, ["diff-tree", "--no-commit-id", "--name-only", "-r", "-z", "--no-renames", automaticMergeTreeId, mergeTree]), "Git resolution path delta");
4588
- return { mergeCommitId: currentHead, parentObjectIds, unmergedPaths: await unmerged(repositoryRoot), worktreeClean: status.byteLength === 0 && currentHead === mergeCommitId, resolutionChangedPaths };
4592
+ return { targetObjectId, sourceObjectId, unmergedPaths: await unmerged(repositoryRoot) };
4589
4593
  }
4590
4594
  };
4591
4595
  }
@@ -4625,7 +4629,7 @@ var init_uuidv7 = __esm({
4625
4629
  });
4626
4630
 
4627
4631
  // src/typed-provider-http.ts
4628
- import { readFile as readFile7, unlink, writeFile as writeFile2 } from "node:fs/promises";
4632
+ import { readFile as readFile8, unlink, writeFile as writeFile2 } from "node:fs/promises";
4629
4633
  import { join as join9 } from "node:path";
4630
4634
  function typedProviderHttpPath(runDirectory) {
4631
4635
  return join9(runDirectory, TYPED_HTTP_FILE);
@@ -4659,7 +4663,7 @@ async function recordTypedProviderHttpStatus(runDirectory, observation) {
4659
4663
  async function readLatestTypedProviderHttpObservation(runDirectory) {
4660
4664
  let text;
4661
4665
  try {
4662
- text = await readFile7(typedProviderHttpPath(runDirectory), "utf8");
4666
+ text = await readFile8(typedProviderHttpPath(runDirectory), "utf8");
4663
4667
  } catch (error) {
4664
4668
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
4665
4669
  return void 0;
@@ -4746,8 +4750,8 @@ var init_engine_material = __esm({
4746
4750
  });
4747
4751
 
4748
4752
  // src/public-cli/run-lifecycle.ts
4749
- import { chmod, open, readdir as readdir2, readFile as readFile8, unlink as unlink2, writeFile as writeFile3 } from "node:fs/promises";
4750
- import { isAbsolute as isAbsolute4, join as join11 } from "node:path";
4753
+ import { chmod, open, readdir as readdir2, readFile as readFile9, unlink as unlink2, writeFile as writeFile3 } from "node:fs/promises";
4754
+ import { isAbsolute as isAbsolute5, join as join11 } from "node:path";
4751
4755
  function resumeRereadInstruction(materialPath, handbook) {
4752
4756
  return handbook ? `\u91CD\u65B0\u8BFB ${materialPath}\uFF0C\u518D\u7EC4\u88C5\u5916\u5305 argv` : `\u91CD\u65B0\u8BFB ${materialPath}`;
4753
4757
  }
@@ -4759,7 +4763,7 @@ function instructResumeHandbookRead(prompt, engineMaterial) {
4759
4763
  if (handbookPath !== void 0 && value === handbookPath) {
4760
4764
  return resumeRereadInstruction(handbookPath, true);
4761
4765
  }
4762
- if (isAbsolute4(value)) return resumeRereadInstruction(value, false);
4766
+ if (isAbsolute5(value)) return resumeRereadInstruction(value, false);
4763
4767
  return line2;
4764
4768
  }).join("\n");
4765
4769
  }
@@ -4845,7 +4849,7 @@ function parseCurrentCourtState(raw) {
4845
4849
  async function readRoleRunStateDisk(runDirectory) {
4846
4850
  let raw;
4847
4851
  try {
4848
- raw = JSON.parse(await readFile8(join11(runDirectory, RUN_STATE_FILE), "utf8"));
4852
+ raw = JSON.parse(await readFile9(join11(runDirectory, RUN_STATE_FILE), "utf8"));
4849
4853
  } catch {
4850
4854
  return void 0;
4851
4855
  }
@@ -5077,7 +5081,7 @@ function isProcessAlive(pid) {
5077
5081
  async function autopsyWriterLock(lockPath) {
5078
5082
  let content;
5079
5083
  try {
5080
- content = await readFile8(lockPath, "utf8");
5084
+ content = await readFile9(lockPath, "utf8");
5081
5085
  } catch (error) {
5082
5086
  if (errorCodeOf2(error) === "ENOENT") return { verdict: "absent" };
5083
5087
  return { verdict: "absent", readFailure: error };
@@ -5246,7 +5250,7 @@ async function readRunParentPath(runDirectory) {
5246
5250
  let raw;
5247
5251
  try {
5248
5252
  raw = JSON.parse(
5249
- await readFile8(join11(runDirectory, "admitted-request.json"), "utf8")
5253
+ await readFile9(join11(runDirectory, "admitted-request.json"), "utf8")
5250
5254
  );
5251
5255
  } catch (error) {
5252
5256
  if (errorCodeOf2(error) === "ENOENT") return void 0;
@@ -5357,7 +5361,7 @@ async function loadResumableRunRecord(home, runId, authority) {
5357
5361
  let sourceRun;
5358
5362
  try {
5359
5363
  const raw = JSON.parse(
5360
- await readFile8(run.admittedRequestPath, "utf8")
5364
+ await readFile9(run.admittedRequestPath, "utf8")
5361
5365
  );
5362
5366
  if (raw !== null && typeof raw === "object" && !Array.isArray(raw)) {
5363
5367
  const record4 = raw;
@@ -5448,11 +5452,10 @@ async function loadResumableRunRecord(home, runId, authority) {
5448
5452
  }
5449
5453
  if (record4.derived !== null && typeof record4.derived === "object" && !Array.isArray(record4.derived)) {
5450
5454
  const d = record4.derived;
5451
- if (typeof d.targetObjectId === "string" && typeof d.sourceObjectId === "string" && typeof d.automaticMergeTreeId === "string" && Array.isArray(d.expectedConflictPaths) && Array.isArray(d.resolutionScope) && d.expectedConflictPaths.every((p) => typeof p === "string") && d.resolutionScope.every((p) => typeof p === "string")) {
5455
+ if (typeof d.targetObjectId === "string" && typeof d.sourceObjectId === "string" && Array.isArray(d.expectedConflictPaths) && Array.isArray(d.resolutionScope) && d.expectedConflictPaths.every((p) => typeof p === "string") && d.resolutionScope.every((p) => typeof p === "string")) {
5452
5456
  derived = {
5453
5457
  targetObjectId: d.targetObjectId,
5454
5458
  sourceObjectId: d.sourceObjectId,
5455
- automaticMergeTreeId: d.automaticMergeTreeId,
5456
5459
  expectedConflictPaths: d.expectedConflictPaths,
5457
5460
  resolutionScope: d.resolutionScope
5458
5461
  };
@@ -5472,7 +5475,7 @@ async function loadResumableRunRecord(home, runId, authority) {
5472
5475
  let model;
5473
5476
  try {
5474
5477
  const invocationRaw = JSON.parse(
5475
- await readFile8(join11(run.runDirectory, "invocation.json"), "utf8")
5478
+ await readFile9(join11(run.runDirectory, "invocation.json"), "utf8")
5476
5479
  );
5477
5480
  if (invocationRaw !== null && typeof invocationRaw === "object" && !Array.isArray(invocationRaw)) {
5478
5481
  const rec = invocationRaw;
@@ -5671,7 +5674,7 @@ __export(notary_source_run_exports, {
5671
5674
  loadNotarySourceRunLocator: () => loadNotarySourceRunLocator,
5672
5675
  resolveNotarySourceRunLocator: () => resolveNotarySourceRunLocator
5673
5676
  });
5674
- import { dirname as dirname8, isAbsolute as isAbsolute5, join as join12, resolve as resolve8, basename as basename5 } from "node:path";
5677
+ import { dirname as dirname8, isAbsolute as isAbsolute6, join as join12, resolve as resolve9, basename as basename5 } from "node:path";
5675
5678
  import { lstat as lstat2, realpath as realpath4 } from "node:fs/promises";
5676
5679
  function parseRunDirectoryName(name) {
5677
5680
  const match = RUN_DIR_NAME.exec(name);
@@ -5723,7 +5726,7 @@ async function resolveNotarySourceRunLocator(options) {
5723
5726
  if (bare !== void 0 && !raw.includes("/") && !raw.includes("\\")) {
5724
5727
  candidate = join12(bookRunsRoot, `${bare.runId}@${bare.role}`);
5725
5728
  } else {
5726
- candidate = isAbsolute5(raw) ? raw : resolve8(options.projectRoot, raw);
5729
+ candidate = isAbsolute6(raw) ? raw : resolve9(options.projectRoot, raw);
5727
5730
  }
5728
5731
  const real = await requireRunDirectory(candidate, raw);
5729
5732
  const identity = parseRunDirectoryName(basename5(real));
@@ -6404,7 +6407,7 @@ var init_option_definitions = __esm({
6404
6407
  }
6405
6408
  ];
6406
6409
  MERGER_OPTIONS = [
6407
- // Merger project face differs: requires an in-progress ordinary merge root.
6410
+ // Merger project face: worktree whose Git materials are handed to the role.
6408
6411
  {
6409
6412
  id: "project",
6410
6413
  owner: "merger",
@@ -6415,8 +6418,8 @@ var init_option_definitions = __esm({
6415
6418
  repeatable: false,
6416
6419
  form: "option",
6417
6420
  description: {
6418
- en: "Project root with one ordinary in-progress merge (defaults to cwd).",
6419
- zh: "\u5DF2\u6709\u8FDB\u884C\u4E2D ordinary merge \u7684\u9879\u76EE\u6839\uFF08\u9ED8\u8BA4 cwd\uFF09\u3002"
6421
+ en: "Project root whose Git merge materials are read (defaults to cwd).",
6422
+ zh: "\u8BFB\u53D6 Git merge \u6750\u6599\u7684\u9879\u76EE\u6839\uFF08\u9ED8\u8BA4 cwd\uFF09\u3002"
6420
6423
  }
6421
6424
  },
6422
6425
  bindOwner("merger", SHARED_ATTACH_SEMANTICS)
@@ -6657,10 +6660,10 @@ var init_option_definitions = __esm({
6657
6660
  },
6658
6661
  merger: {
6659
6662
  command: "merger",
6660
- summary: "Resolve one ordinary merge already in conflict.",
6663
+ summary: "Reconcile merge materials in a worktree (escalate when nothing to merge).",
6661
6664
  usage: ["ak-role merger [options] <instruction>"],
6662
6665
  examples: [
6663
- 'ak-role merger --project /path/to/worktree "Reconcile the active merge."'
6666
+ 'ak-role merger --project /path/to/worktree "Reconcile the merge."'
6664
6667
  ]
6665
6668
  },
6666
6669
  inspector: {
@@ -6795,7 +6798,6 @@ var init_option_definitions = __esm({
6795
6798
  // src/public-cli/invocation.ts
6796
6799
  var invocation_exports = {};
6797
6800
  __export(invocation_exports, {
6798
- MergerEnvelopeDerivationError: () => MergerEnvelopeDerivationError,
6799
6801
  admitAuditorInvocation: () => admitAuditorInvocation,
6800
6802
  admitCoderInvocation: () => admitCoderInvocation,
6801
6803
  admitCollectorInvocation: () => admitCollectorInvocation,
@@ -6865,11 +6867,11 @@ import { existsSync as existsSync4 } from "node:fs";
6865
6867
  import {
6866
6868
  lstat as lstat3,
6867
6869
  mkdir,
6868
- readFile as readFile9,
6870
+ readFile as readFile10,
6869
6871
  realpath as realpath5,
6870
6872
  writeFile as writeFile4
6871
6873
  } from "node:fs/promises";
6872
- import { basename as basename6, isAbsolute as isAbsolute6, join as join13, resolve as resolve9, sep as sep3 } from "node:path";
6874
+ import { basename as basename6, isAbsolute as isAbsolute7, join as join13, resolve as resolve10, sep as sep3 } from "node:path";
6873
6875
  function issueAdmissionPlacement(authority, request) {
6874
6876
  const principal = authority.issue(request);
6875
6877
  const { sessionDirectory, sessionFile } = authority.decode(principal);
@@ -6929,7 +6931,7 @@ async function writeRoleInvocationLedger(source, role, effectiveModel) {
6929
6931
  }
6930
6932
  async function recordEffectiveInvocationModel(runDirectory, model, engine, host) {
6931
6933
  const ledgerPath = join13(runDirectory, "invocation.json");
6932
- const current = JSON.parse(await readFile9(ledgerPath, "utf8"));
6934
+ const current = JSON.parse(await readFile10(ledgerPath, "utf8"));
6933
6935
  const next = { ...current };
6934
6936
  if (model !== void 0) {
6935
6937
  next.provider = model.provider;
@@ -6957,7 +6959,7 @@ async function recordEffectiveInvocationModel(runDirectory, model, engine, host)
6957
6959
  }
6958
6960
  async function mergeInvocationIdentityPage(runDirectory, fields) {
6959
6961
  const ledgerPath = join13(runDirectory, "invocation.json");
6960
- const current = JSON.parse(await readFile9(ledgerPath, "utf8"));
6962
+ const current = JSON.parse(await readFile10(ledgerPath, "utf8"));
6961
6963
  await writeFile4(
6962
6964
  ledgerPath,
6963
6965
  `${JSON.stringify({
@@ -6973,7 +6975,7 @@ async function persistAdmittedSourceRunPath(admitted, sourceRunPath) {
6973
6975
  throw new Error("persistAdmittedSourceRunPath requires a non-empty sourceRunPath");
6974
6976
  }
6975
6977
  const admittedPath = admitted.admittedRequestPath;
6976
- const current = JSON.parse(await readFile9(admittedPath, "utf8"));
6978
+ const current = JSON.parse(await readFile10(admittedPath, "utf8"));
6977
6979
  if (typeof current.sourceRunPath === "string") {
6978
6980
  if (current.sourceRunPath === sourceRunPath) return;
6979
6981
  throw new Error(
@@ -7000,7 +7002,7 @@ async function bindAdmittedTicketNumber(admitted, ticketNumber) {
7000
7002
  admitted.ticketNumber = ticketNumber;
7001
7003
  await mergeInvocationIdentityPage(admitted.runDirectory, { ticketNumber });
7002
7004
  const admittedPath = admitted.admittedRequestPath;
7003
- const current = JSON.parse(await readFile9(admittedPath, "utf8"));
7005
+ const current = JSON.parse(await readFile10(admittedPath, "utf8"));
7004
7006
  await writeFile4(
7005
7007
  admittedPath,
7006
7008
  `${JSON.stringify({ ...current, ticketNumber }, null, 2)}
@@ -7016,7 +7018,7 @@ async function bindTicketNumberOnRunDirectory(runDirectory, ticketNumber) {
7016
7018
  }
7017
7019
  const admittedPath = join13(runDirectory, "admitted-request.json");
7018
7020
  const invocationPath = join13(runDirectory, "invocation.json");
7019
- const admitted = JSON.parse(await readFile9(admittedPath, "utf8"));
7021
+ const admitted = JSON.parse(await readFile10(admittedPath, "utf8"));
7020
7022
  const existing = admitted.ticketNumber;
7021
7023
  if (typeof existing === "number") {
7022
7024
  if (existing === ticketNumber) return;
@@ -7026,7 +7028,7 @@ async function bindTicketNumberOnRunDirectory(runDirectory, ticketNumber) {
7026
7028
  }
7027
7029
  if (existsSync4(invocationPath)) {
7028
7030
  const invocation = JSON.parse(
7029
- await readFile9(invocationPath, "utf8")
7031
+ await readFile10(invocationPath, "utf8")
7030
7032
  );
7031
7033
  if (typeof invocation.ticketNumber === "number" && invocation.ticketNumber !== ticketNumber) {
7032
7034
  throw new Error(
@@ -7051,7 +7053,7 @@ async function recordLaunchedPiIdentity(runDirectory, identity) {
7051
7053
  async function observeLaunchedRolePackageIdentity(packageRoot, selectedRoleEntry) {
7052
7054
  const rolePackageRoot = packageRoot;
7053
7055
  const raw = JSON.parse(
7054
- await readFile9(join13(rolePackageRoot, "package.json"), "utf8")
7056
+ await readFile10(join13(rolePackageRoot, "package.json"), "utf8")
7055
7057
  );
7056
7058
  if (typeof raw.version !== "string" || raw.version.trim() === "") {
7057
7059
  throw new Error(
@@ -7292,7 +7294,7 @@ function parseFixerArgv(args) {
7292
7294
  };
7293
7295
  }
7294
7296
  async function freezeRegularFileAttachment(sourcePath, destinationDir, index) {
7295
- const absolute = isAbsolute6(sourcePath) ? sourcePath : resolve9(sourcePath);
7297
+ const absolute = isAbsolute7(sourcePath) ? sourcePath : resolve10(sourcePath);
7296
7298
  let st;
7297
7299
  try {
7298
7300
  st = await lstat3(absolute);
@@ -7307,7 +7309,7 @@ async function freezeRegularFileAttachment(sourcePath, destinationDir, index) {
7307
7309
  `attachment must be a regular file (not a directory or symlink): ${sourcePath}`
7308
7310
  );
7309
7311
  }
7310
- const bytes = await readFile9(absolute);
7312
+ const bytes = await readFile10(absolute);
7311
7313
  const name = `${String(index).padStart(2, "0")}-${basename6(absolute)}`;
7312
7314
  const frozenPath = join13(destinationDir, name);
7313
7315
  await writeFile4(frozenPath, bytes);
@@ -7348,7 +7350,7 @@ async function admitStandardMaterialInvocation(role, options) {
7348
7350
  if (options.project !== void 0) {
7349
7351
  requireOptionPath("--project", options.project);
7350
7352
  }
7351
- const projectRoot = resolve9(options.project ?? options.cwd);
7353
+ const projectRoot = resolve10(options.project ?? options.cwd);
7352
7354
  const runId = (options.createRunId ?? uuidv7)();
7353
7355
  const {
7354
7356
  principal,
@@ -7451,7 +7453,7 @@ async function admitCountersignInvocation(options) {
7451
7453
  if (options.project !== void 0) {
7452
7454
  requireOptionPath("--project", options.project);
7453
7455
  }
7454
- const projectRoot = resolve9(options.project ?? options.cwd);
7456
+ const projectRoot = resolve10(options.project ?? options.cwd);
7455
7457
  const runId = (options.createRunId ?? uuidv7)();
7456
7458
  const {
7457
7459
  principal,
@@ -7516,7 +7518,7 @@ function buildCountersignTransportPrompt(admitted, engineMaterial) {
7516
7518
  async function loadAdmittedJudgeRequest(runDirectory) {
7517
7519
  try {
7518
7520
  const raw = JSON.parse(
7519
- await readFile9(join13(runDirectory, "admitted-request.json"), "utf8")
7521
+ await readFile10(join13(runDirectory, "admitted-request.json"), "utf8")
7520
7522
  );
7521
7523
  if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return void 0;
7522
7524
  const record4 = raw;
@@ -7551,7 +7553,7 @@ async function admitCoderInvocation(options) {
7551
7553
  if (options.phase !== "plan" && options.phase !== "apply") {
7552
7554
  throw new CliUsageError("coder phase must be plan or apply");
7553
7555
  }
7554
- const projectRoot = resolve9(options.project ?? options.cwd);
7556
+ const projectRoot = resolve10(options.project ?? options.cwd);
7555
7557
  const runId = (options.createRunId ?? uuidv7)();
7556
7558
  const {
7557
7559
  principal,
@@ -7639,9 +7641,9 @@ async function admitFixerInvocation(options) {
7639
7641
  let prerequisites = Object.freeze([]);
7640
7642
  let prerequisitesSource;
7641
7643
  if (options.prerequisitesPath !== void 0) {
7642
- const absolutePrereq = isAbsolute6(options.prerequisitesPath) ? options.prerequisitesPath : resolve9(options.prerequisitesPath);
7644
+ const absolutePrereq = isAbsolute7(options.prerequisitesPath) ? options.prerequisitesPath : resolve10(options.prerequisitesPath);
7643
7645
  try {
7644
- prerequisitesSource = await readFile9(absolutePrereq, "utf8");
7646
+ prerequisitesSource = await readFile10(absolutePrereq, "utf8");
7645
7647
  } catch (error) {
7646
7648
  throw new CliUsageError(
7647
7649
  `fixer prerequisites path is unreadable: ${options.prerequisitesPath}`,
@@ -7657,7 +7659,7 @@ async function admitFixerInvocation(options) {
7657
7659
  throw error;
7658
7660
  }
7659
7661
  }
7660
- const projectRoot = resolve9(options.project ?? options.cwd);
7662
+ const projectRoot = resolve10(options.project ?? options.cwd);
7661
7663
  const runId = (options.createRunId ?? uuidv7)();
7662
7664
  const {
7663
7665
  principal,
@@ -7882,7 +7884,7 @@ async function admitCollectorInvocation(options) {
7882
7884
  throw new CliUsageError(detail, { cause: error });
7883
7885
  }
7884
7886
  }
7885
- const projectRoot = resolve9(options.project ?? options.cwd);
7887
+ const projectRoot = resolve10(options.project ?? options.cwd);
7886
7888
  let repository;
7887
7889
  if (options.repo !== void 0) {
7888
7890
  try {
@@ -8070,12 +8072,12 @@ async function resolveDoctorCaseRunsPath(options) {
8070
8072
  if (raw === "") {
8071
8073
  throw new CliUsageError("doctor --runs requires a path");
8072
8074
  }
8073
- if (isAbsolute6(raw)) {
8075
+ if (isAbsolute7(raw)) {
8074
8076
  throw new CliUsageError(
8075
8077
  "doctor --runs must be a project-relative path"
8076
8078
  );
8077
8079
  }
8078
- const resolved = resolve9(options.projectRoot, raw);
8080
+ const resolved = resolve10(options.projectRoot, raw);
8079
8081
  if (resolved !== options.projectRoot && !pathContainedIn(options.projectRoot, resolved)) {
8080
8082
  throw new CliUsageError(
8081
8083
  "doctor --runs escapes the project root"
@@ -8114,7 +8116,7 @@ async function admitDoctorInvocation(options) {
8114
8116
  `doctor --issue must be a positive integer, got ${options.issueNumber}`
8115
8117
  );
8116
8118
  }
8117
- const projectRoot = resolve9(options.project ?? options.cwd);
8119
+ const projectRoot = resolve10(options.project ?? options.cwd);
8118
8120
  const runId = (options.createRunId ?? uuidv7)();
8119
8121
  const {
8120
8122
  principal,
@@ -8275,7 +8277,7 @@ async function admitNotaryInvocation(options) {
8275
8277
  if (options.project !== void 0) {
8276
8278
  requireOptionPath("--project", options.project);
8277
8279
  }
8278
- const projectRoot = resolve9(options.project ?? options.cwd);
8280
+ const projectRoot = resolve10(options.project ?? options.cwd);
8279
8281
  let sourceRun;
8280
8282
  try {
8281
8283
  sourceRun = await resolveNotarySourceRunLocator({
@@ -8393,7 +8395,7 @@ async function admitGleanerLeftInvocation(options) {
8393
8395
  if (options.baseRevision.trim() === "") {
8394
8396
  throw new CliUsageError("--base requires a nonempty revision");
8395
8397
  }
8396
- const projectRoot = resolve9(options.project ?? options.cwd);
8398
+ const projectRoot = resolve10(options.project ?? options.cwd);
8397
8399
  const runId = (options.createRunId ?? uuidv7)();
8398
8400
  const {
8399
8401
  principal,
@@ -8514,7 +8516,7 @@ async function admitReviewerInvocation(options) {
8514
8516
  const authorityRefs = Object.freeze(
8515
8517
  (options.authorityRefs ?? []).map((ref) => requireAuthorityRef(ref))
8516
8518
  );
8517
- const projectRoot = resolve9(options.project ?? options.cwd);
8519
+ const projectRoot = resolve10(options.project ?? options.cwd);
8518
8520
  const runId = (options.createRunId ?? uuidv7)();
8519
8521
  const {
8520
8522
  principal,
@@ -8609,7 +8611,7 @@ function parseMergerArgv(args) {
8609
8611
  const token = tokens.shift();
8610
8612
  if (isRejectedPublicSpelling("merger", token) || token === "--targetObjectId" || token.startsWith("--targetObjectId=") || token === "--sourceObjectId" || token.startsWith("--sourceObjectId=") || token === "--expectedConflictPaths" || token.startsWith("--expectedConflictPaths=") || token === "--resolutionScope" || token.startsWith("--resolutionScope=")) {
8611
8613
  throw new CliUsageError(
8612
- "merger does not accept public packet fields; the adapter derives the active-merge envelope"
8614
+ "merger does not accept public packet fields; the adapter reads Git merge materials"
8613
8615
  );
8614
8616
  }
8615
8617
  if (token.startsWith("-") && token !== "-") {
@@ -8632,24 +8634,12 @@ function mergerMaterialFromUtf8(text) {
8632
8634
  });
8633
8635
  }
8634
8636
  async function deriveMergerEnvelopeFromActiveMerge(projectRoot, gitState = createProductionMergerGitState(projectRoot)) {
8635
- let state;
8636
- try {
8637
- state = await gitState.activeMerge();
8638
- } catch (error) {
8639
- const message = error instanceof Error && error.message.trim() !== "" ? error.message : "Assigned repository does not have one ordinary in-progress merge";
8640
- throw new MergerEnvelopeDerivationError(message, { cause: error });
8641
- }
8642
- if (state.unmergedPaths.length === 0) {
8643
- throw new MergerEnvelopeDerivationError(
8644
- "Assigned repository does not have one ordinary in-progress merge with a complete conflict set"
8645
- );
8646
- }
8637
+ const state = await gitState.activeMerge();
8647
8638
  const expectedConflictPaths = Object.freeze([...state.unmergedPaths]);
8648
8639
  const resolutionScope = Object.freeze([...state.unmergedPaths]);
8649
8640
  return Object.freeze({
8650
8641
  targetObjectId: state.targetObjectId,
8651
8642
  sourceObjectId: state.sourceObjectId,
8652
- automaticMergeTreeId: state.automaticMergeTreeId,
8653
8643
  expectedConflictPaths,
8654
8644
  resolutionScope
8655
8645
  });
@@ -8662,7 +8652,7 @@ async function admitMergerInvocation(options) {
8662
8652
  if (instruction.trim() === "") {
8663
8653
  throw new CliUsageError("merger requires a nonblank task instruction");
8664
8654
  }
8665
- const projectRoot = resolve9(options.project ?? options.cwd);
8655
+ const projectRoot = resolve10(options.project ?? options.cwd);
8666
8656
  const derived = await deriveMergerEnvelopeFromActiveMerge(
8667
8657
  projectRoot,
8668
8658
  options.gitState ?? createProductionMergerGitState(projectRoot)
@@ -8685,16 +8675,17 @@ async function admitMergerInvocation(options) {
8685
8675
  ensureRealDirectoryTree(ledgerHome, sessionDirectory);
8686
8676
  ensureRealDirectoryTree(ledgerHome, attachmentsDirectory);
8687
8677
  const attachments = await freezeAttachments(options.attachmentPaths, attachmentsDirectory);
8678
+ const targetLabel = derived.targetObjectId === "" ? "(none observed)" : derived.targetObjectId;
8679
+ const sourceLabel = derived.sourceObjectId === "" ? "(none observed)" : derived.sourceObjectId;
8688
8680
  const targetIntent = mergerMaterialFromUtf8(
8689
- `Investigate primary sources for target parent ${derived.targetObjectId}. Do not invent intent.`
8681
+ `Investigate primary sources for target parent ${targetLabel}. Do not invent intent.`
8690
8682
  );
8691
8683
  const sourceIntent = mergerMaterialFromUtf8(
8692
- `Investigate primary sources for source parent ${derived.sourceObjectId}. Do not invent intent.`
8684
+ `Investigate primary sources for source parent ${sourceLabel}. Do not invent intent.`
8693
8685
  );
8694
8686
  const taskMaterial = mergerMaterialFromUtf8(instruction);
8695
8687
  const authorityMaterial = mergerMaterialFromUtf8(instruction);
8696
8688
  const mergerInput = validateMergerInput({
8697
- version: 1,
8698
8689
  attemptId: runId,
8699
8690
  targetObjectId: derived.targetObjectId,
8700
8691
  sourceObjectId: derived.sourceObjectId,
@@ -8706,7 +8697,6 @@ async function admitMergerInvocation(options) {
8706
8697
  },
8707
8698
  expectedConflictPaths: [...derived.expectedConflictPaths],
8708
8699
  resolutionScope: [...derived.resolutionScope],
8709
- // Authorized checks remain available on the assignment; default none.
8710
8700
  authorizedChecks: []
8711
8701
  });
8712
8702
  const mergerInputPath = join13(runDirectory, "merger-input.json");
@@ -8729,7 +8719,6 @@ async function admitMergerInvocation(options) {
8729
8719
  derived: {
8730
8720
  targetObjectId: derived.targetObjectId,
8731
8721
  sourceObjectId: derived.sourceObjectId,
8732
- automaticMergeTreeId: derived.automaticMergeTreeId,
8733
8722
  expectedConflictPaths: [...derived.expectedConflictPaths],
8734
8723
  resolutionScope: [...derived.resolutionScope]
8735
8724
  },
@@ -8993,7 +8982,7 @@ function parseAnalystArgv(args) {
8993
8982
  ...ticketRaw === void 0 ? {} : { ticket: parseAnalystTicketNumber(ticketRaw) }
8994
8983
  };
8995
8984
  }
8996
- var MergerEnvelopeDerivationError, DOCTOR_ISSUE_NUMBER_PATTERN, DOCTOR_CASE_RUNS_PATH_PATTERN, ANALYST_TICKET_NUMBER_PATTERN;
8985
+ var DOCTOR_ISSUE_NUMBER_PATTERN, DOCTOR_CASE_RUNS_PATH_PATTERN, ANALYST_TICKET_NUMBER_PATTERN;
8997
8986
  var init_invocation = __esm({
8998
8987
  "src/public-cli/invocation.ts"() {
8999
8988
  "use strict";
@@ -9014,15 +9003,6 @@ var init_invocation = __esm({
9014
9003
  init_engine_material();
9015
9004
  init_cli_errors();
9016
9005
  init_option_definitions();
9017
- MergerEnvelopeDerivationError = class extends Error {
9018
- code = "merger-envelope-derivation";
9019
- /** Typed cause for #107 classifyPostAdmissionFailure (isTypedActivationError). */
9020
- knownCause = "activation";
9021
- constructor(message, options) {
9022
- super(message, options);
9023
- this.name = "MergerEnvelopeDerivationError";
9024
- }
9025
- };
9026
9006
  DOCTOR_ISSUE_NUMBER_PATTERN = /^[1-9]\d*$/;
9027
9007
  DOCTOR_CASE_RUNS_PATH_PATTERN = /\/\.ak-roles\/books\/[^/]+\/issues\/([1-9]\d*)\/runs$/;
9028
9008
  ANALYST_TICKET_NUMBER_PATTERN = /^[1-9]\d*$/;
@@ -9583,7 +9563,7 @@ __export(config_exports, {
9583
9563
  setPersistentSeatHost: () => setPersistentSeatHost,
9584
9564
  validatePublicCliConfigAxes: () => validatePublicCliConfigAxes
9585
9565
  });
9586
- import { mkdir as mkdir2, readFile as readFile10, writeFile as writeFile5 } from "node:fs/promises";
9566
+ import { mkdir as mkdir2, readFile as readFile11, writeFile as writeFile5 } from "node:fs/promises";
9587
9567
  import { dirname as dirname9, join as join17 } from "node:path";
9588
9568
  function isGateOfficerSeat(value) {
9589
9569
  return GATE_OFFICER_SEATS.includes(value);
@@ -9597,7 +9577,7 @@ function publicCliConfigPath(home) {
9597
9577
  async function loadPublicCliConfig(home) {
9598
9578
  const path = publicCliConfigPath(home);
9599
9579
  try {
9600
- const raw = await readFile10(path, "utf8");
9580
+ const raw = await readFile11(path, "utf8");
9601
9581
  return parsePublicCliConfig(JSON.parse(raw));
9602
9582
  } catch (error) {
9603
9583
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -10001,7 +9981,7 @@ function credentialProvidersFromAuthData(data) {
10001
9981
  }
10002
9982
  async function loadCredentialProviders(agentDir) {
10003
9983
  try {
10004
- const raw = await readFile10(join17(agentDir, "auth.json"), "utf8");
9984
+ const raw = await readFile11(join17(agentDir, "auth.json"), "utf8");
10005
9985
  return credentialProvidersFromAuthData(JSON.parse(raw));
10006
9986
  } catch (error) {
10007
9987
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -10344,14 +10324,14 @@ var init_case_dossier_delivery = __esm({
10344
10324
  });
10345
10325
 
10346
10326
  // src/host-transition-prior-native.ts
10347
- import { access as access2, readdir as readdir3 } from "node:fs/promises";
10327
+ import { access as access3, readdir as readdir3 } from "node:fs/promises";
10348
10328
  import { dirname as dirname10, join as join19 } from "node:path";
10349
10329
  function isEnoent2(error) {
10350
10330
  return typeof error === "object" && error !== null && error.code === "ENOENT";
10351
10331
  }
10352
10332
  async function listPiNativeRecordPaths(sessionFile) {
10353
10333
  try {
10354
- await access2(sessionFile);
10334
+ await access3(sessionFile);
10355
10335
  return [sessionFile];
10356
10336
  } catch (error) {
10357
10337
  if (isEnoent2(error)) return [];
@@ -10372,7 +10352,7 @@ async function listSitianRecordPaths(sessionParent) {
10372
10352
  if (!entry.isDirectory()) continue;
10373
10353
  const recordFile = join19(sessionRoot, entry.name, "records.jsonl");
10374
10354
  try {
10375
- await access2(recordFile);
10355
+ await access3(recordFile);
10376
10356
  recordPaths.push(recordFile);
10377
10357
  } catch (error) {
10378
10358
  if (!isEnoent2(error)) throw error;
@@ -10754,12 +10734,12 @@ var init_submission_ledger = __esm({
10754
10734
  });
10755
10735
 
10756
10736
  // src/ledger-session-read.ts
10757
- import { readFile as readFile11 } from "node:fs/promises";
10737
+ import { readFile as readFile12 } from "node:fs/promises";
10758
10738
  function isRecord12(value) {
10759
10739
  return typeof value === "object" && value !== null && !Array.isArray(value);
10760
10740
  }
10761
10741
  async function readLedgerSessionJsonl(path) {
10762
- const text = await readFile11(path, "utf8");
10742
+ const text = await readFile12(path, "utf8");
10763
10743
  const lines = text.split("\n");
10764
10744
  const rows = [];
10765
10745
  for (let index = 0; index < lines.length; index += 1) {
@@ -11068,10 +11048,10 @@ function pairGateRounds(volumes) {
11068
11048
  return rounds.sort((a, b) => a.officerStartedAt.localeCompare(b.officerStartedAt)).map((round, index) => ({ ...round, roundIndex: index + 1 }));
11069
11049
  }
11070
11050
  async function resolveOfficerSessionFromPointerFile(pointerPath) {
11071
- const { readFile: readFile22 } = await import("node:fs/promises");
11051
+ const { readFile: readFile23 } = await import("node:fs/promises");
11072
11052
  let raw;
11073
11053
  try {
11074
- raw = JSON.parse(await readFile22(pointerPath, "utf8"));
11054
+ raw = JSON.parse(await readFile23(pointerPath, "utf8"));
11075
11055
  } catch (error) {
11076
11056
  throw new Error(
11077
11057
  `direct officer run pointer unreadable in ${pointerPath}: ${error instanceof Error ? error.message : String(error)}`,
@@ -11146,7 +11126,7 @@ var init_analyst_gate_cycles_read = __esm({
11146
11126
 
11147
11127
  // src/session-opening-materials.ts
11148
11128
  import { existsSync as existsSync7 } from "node:fs";
11149
- import { readFile as readFile12 } from "node:fs/promises";
11129
+ import { readFile as readFile13 } from "node:fs/promises";
11150
11130
  import { dirname as dirname12, join as join22 } from "node:path";
11151
11131
  import { fileURLToPath, pathToFileURL as pathToFileURL3 } from "node:url";
11152
11132
  function resolvePackageRootDir(moduleUrl = import.meta.url) {
@@ -11162,7 +11142,7 @@ function resolvePackageRootDir(moduleUrl = import.meta.url) {
11162
11142
  return fileURLToPath(new URL("..", moduleUrl));
11163
11143
  }
11164
11144
  async function readPackageMaterial(relativePath) {
11165
- return readFile12(fileURLToPath(new URL(relativePath, packageRootUrl)), "utf8");
11145
+ return readFile13(fileURLToPath(new URL(relativePath, packageRootUrl)), "utf8");
11166
11146
  }
11167
11147
  async function joinPackageMaterials(relativePaths) {
11168
11148
  const chunks = [];
@@ -11403,7 +11383,7 @@ var init_reviewer_preflight_error = __esm({
11403
11383
 
11404
11384
  // src/reviewer-pinned-git.ts
11405
11385
  import { execFile as execFile3 } from "node:child_process";
11406
- import { access as access3, realpath as realpath6 } from "node:fs/promises";
11386
+ import { access as access4, realpath as realpath6 } from "node:fs/promises";
11407
11387
  import { promisify as promisify3 } from "node:util";
11408
11388
  async function execGit(args, options) {
11409
11389
  try {
@@ -11437,7 +11417,7 @@ function isConfirmedPinnedPathAbsent(error, path) {
11437
11417
  }
11438
11418
  async function repositoryIsAvailable(root) {
11439
11419
  try {
11440
- await access3(`${root}/.git`);
11420
+ await access4(`${root}/.git`);
11441
11421
  return { available: true };
11442
11422
  } catch (cause) {
11443
11423
  return { available: false, cause };
@@ -12023,7 +12003,7 @@ var init_reviewer_dispatch = __esm({
12023
12003
 
12024
12004
  // src/public-cli/reviewer-dispatch-rejection.ts
12025
12005
  import { writeFileSync as writeFileSync4 } from "node:fs";
12026
- import { readFile as readFile13, unlink as unlink3 } from "node:fs/promises";
12006
+ import { readFile as readFile14, unlink as unlink3 } from "node:fs/promises";
12027
12007
  import { join as join23 } from "node:path";
12028
12008
  function isReviewerPreflightViolation(value) {
12029
12009
  return typeof value === "string" && REVIEWER_PREFLIGHT_VIOLATIONS.includes(value);
@@ -12042,7 +12022,7 @@ function recordReviewerDispatchRejectionSync(runDirectory, rejection) {
12042
12022
  async function readReviewerDispatchRejection(runDirectory) {
12043
12023
  let raw;
12044
12024
  try {
12045
- raw = await readFile13(reviewerDispatchRejectionPath(runDirectory), "utf8");
12025
+ raw = await readFile14(reviewerDispatchRejectionPath(runDirectory), "utf8");
12046
12026
  } catch (error) {
12047
12027
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
12048
12028
  return void 0;
@@ -12084,12 +12064,12 @@ function createSystemCollectorClock() {
12084
12064
  return {
12085
12065
  wallNow: () => /* @__PURE__ */ new Date(),
12086
12066
  monoNow: () => Number(process.hrtime.bigint() - start) / 1e6,
12087
- sleep: (ms, signal) => new Promise((resolve19, reject) => {
12067
+ sleep: (ms, signal) => new Promise((resolve20, reject) => {
12088
12068
  if (signal?.aborted) {
12089
12069
  reject(signal.reason ?? new Error("aborted"));
12090
12070
  return;
12091
12071
  }
12092
- const timer = setTimeout(resolve19, ms);
12072
+ const timer = setTimeout(resolve20, ms);
12093
12073
  const onAbort = () => {
12094
12074
  clearTimeout(timer);
12095
12075
  reject(signal?.reason ?? new Error("aborted"));
@@ -13433,7 +13413,7 @@ var init_collector_ledger = __esm({
13433
13413
 
13434
13414
  // src/package-resources/method-skill.ts
13435
13415
  import { createHash as createHash7 } from "node:crypto";
13436
- import { readFile as readFile14, realpath as realpath7 } from "node:fs/promises";
13416
+ import { readFile as readFile15, realpath as realpath7 } from "node:fs/promises";
13437
13417
  import { join as join24 } from "node:path";
13438
13418
  function gitBlobOid(bytes) {
13439
13419
  const body = typeof bytes === "string" ? Buffer.from(bytes, "utf8") : Buffer.from(bytes);
@@ -13552,7 +13532,7 @@ async function loadPackagedMethodSkillMaterial(packageRoot, name) {
13552
13532
  const provenancePath = join24(rootDirectory, "provenance.json");
13553
13533
  let provenanceRaw;
13554
13534
  try {
13555
- provenanceRaw = await readFile14(provenancePath, "utf8");
13535
+ provenanceRaw = await readFile15(provenancePath, "utf8");
13556
13536
  } catch (error) {
13557
13537
  throw new PackagedMethodSkillUnavailableError(name, provenancePath, error);
13558
13538
  }
@@ -13569,7 +13549,7 @@ async function loadPackagedMethodSkillMaterial(packageRoot, name) {
13569
13549
  const absolute = join24(rootDirectory, rel);
13570
13550
  let bytes;
13571
13551
  try {
13572
- bytes = await readFile14(absolute);
13552
+ bytes = await readFile15(absolute);
13573
13553
  } catch (error) {
13574
13554
  throw new PackagedMethodSkillUnavailableError(name, absolute, error);
13575
13555
  }
@@ -13585,7 +13565,7 @@ async function loadPackagedMethodSkillMaterial(packageRoot, name) {
13585
13565
  let raw;
13586
13566
  try {
13587
13567
  skillPath = await realpath7(skillPathConfigured);
13588
- raw = await readFile14(skillPath, "utf8");
13568
+ raw = await readFile15(skillPath, "utf8");
13589
13569
  } catch (error) {
13590
13570
  throw new PackagedMethodSkillUnavailableError(name, skillPathConfigured, error);
13591
13571
  }
@@ -13641,7 +13621,7 @@ var init_method_skill = __esm({
13641
13621
  });
13642
13622
 
13643
13623
  // src/work-subject-identity.ts
13644
- import { resolve as resolve10 } from "node:path";
13624
+ import { resolve as resolve11 } from "node:path";
13645
13625
  function issueRoot(value) {
13646
13626
  const normalized = value.replaceAll("\\", "/");
13647
13627
  const marker = ".ak/work/issues/";
@@ -13651,7 +13631,7 @@ function issueRoot(value) {
13651
13631
  return issue === void 0 || issue === "" ? void 0 : normalized.slice(0, index + marker.length) + issue;
13652
13632
  }
13653
13633
  function workIdentityFromCwd(cwd) {
13654
- const resolvedCwd = resolve10(cwd, ".");
13634
+ const resolvedCwd = resolve11(cwd, ".");
13655
13635
  const cwdIssue = issueRoot(resolvedCwd);
13656
13636
  if (cwdIssue !== void 0) return cwdIssue;
13657
13637
  if (resolvedCwd.includes("/.ak/work/")) return resolvedCwd;
@@ -13662,11 +13642,11 @@ function isMachineLedgerSessionPath(sessionPath) {
13662
13642
  }
13663
13643
  function subjectPath(sessionDir, cwd = process.cwd()) {
13664
13644
  if (sessionDir === "") {
13665
- return workIdentityFromCwd(cwd) ?? resolve10(cwd, ".ak/work");
13645
+ return workIdentityFromCwd(cwd) ?? resolve11(cwd, ".ak/work");
13666
13646
  }
13667
- const resolvedSession = resolve10(cwd, sessionDir || ".ak/work");
13647
+ const resolvedSession = resolve11(cwd, sessionDir || ".ak/work");
13668
13648
  if (isMachineLedgerSessionPath(resolvedSession)) {
13669
- return workIdentityFromCwd(cwd) ?? resolve10(cwd, ".ak/work");
13649
+ return workIdentityFromCwd(cwd) ?? resolve11(cwd, ".ak/work");
13670
13650
  }
13671
13651
  const issue = issueRoot(resolvedSession);
13672
13652
  if (issue !== void 0) return issue;
@@ -14081,7 +14061,7 @@ var init_terminal = __esm({
14081
14061
 
14082
14062
  // src/public-cli/settlement.ts
14083
14063
  import { randomUUID as randomUUID3 } from "node:crypto";
14084
- import { appendFile as appendFile2, readFile as readFile15, readdir as readdir5, writeFile as writeFile6 } from "node:fs/promises";
14064
+ import { appendFile as appendFile2, readFile as readFile16, readdir as readdir5, writeFile as writeFile6 } from "node:fs/promises";
14085
14065
  import { dirname as dirname13, join as join25 } from "node:path";
14086
14066
  function sealedLedgerHome(admitted) {
14087
14067
  return homeFromRunDirectory(admitted.runDirectory);
@@ -14194,7 +14174,7 @@ function presentStructuralRejection(error, io) {
14194
14174
  }
14195
14175
  async function inspectJudgeSession(sessionFile) {
14196
14176
  try {
14197
- await readFile15(sessionFile, "utf8");
14177
+ await readFile16(sessionFile, "utf8");
14198
14178
  return { state: "present" };
14199
14179
  } catch (error) {
14200
14180
  if (isMissingPathError2(error)) return { state: "missing" };
@@ -14410,7 +14390,7 @@ function sessionReadFailure(error, fallbackMessage) {
14410
14390
  return failed2;
14411
14391
  }
14412
14392
  async function readBoundSessionEntries(sessionFile) {
14413
- const text = await readFile15(sessionFile, "utf8");
14393
+ const text = await readFile16(sessionFile, "utf8");
14414
14394
  const entries = [];
14415
14395
  for (const line2 of text.trim().split("\n").filter(Boolean)) {
14416
14396
  try {
@@ -15803,10 +15783,10 @@ function presentFailureTerminal(terminal, io) {
15803
15783
  }
15804
15784
  function defaultNavigatorGraceSleep() {
15805
15785
  let timer;
15806
- const sleep = ((ms) => new Promise((resolve19) => {
15786
+ const sleep = ((ms) => new Promise((resolve20) => {
15807
15787
  timer = setTimeout(() => {
15808
15788
  timer = void 0;
15809
- resolve19();
15789
+ resolve20();
15810
15790
  }, ms);
15811
15791
  }));
15812
15792
  sleep.cancel = () => {
@@ -15818,7 +15798,7 @@ function defaultNavigatorGraceSleep() {
15818
15798
  return sleep;
15819
15799
  }
15820
15800
  function raceNavigatorGrace(work, graceMs = NAVIGATOR_POST_ROLE_GRACE_MS, sleep = defaultNavigatorGraceSleep()) {
15821
- return new Promise((resolve19, reject) => {
15801
+ return new Promise((resolve20, reject) => {
15822
15802
  let settled = false;
15823
15803
  const finish = (action) => {
15824
15804
  if (settled) return;
@@ -15827,11 +15807,11 @@ function raceNavigatorGrace(work, graceMs = NAVIGATOR_POST_ROLE_GRACE_MS, sleep
15827
15807
  action();
15828
15808
  };
15829
15809
  void work.then(
15830
- (value) => finish(() => resolve19({ status: "done", value })),
15810
+ (value) => finish(() => resolve20({ status: "done", value })),
15831
15811
  (error) => finish(() => reject(error))
15832
15812
  );
15833
15813
  void sleep(graceMs).then(() => {
15834
- finish(() => resolve19({ status: "timeout" }));
15814
+ finish(() => resolve20({ status: "timeout" }));
15835
15815
  });
15836
15816
  });
15837
15817
  }
@@ -15884,7 +15864,7 @@ var init_settlement = __esm({
15884
15864
  });
15885
15865
 
15886
15866
  // src/public-cli/auto-resume.ts
15887
- import { constants as fsConstants } from "node:fs";
15867
+ import { constants as fsConstants2 } from "node:fs";
15888
15868
  import { randomUUID as randomUUID4 } from "node:crypto";
15889
15869
  import { lstat as lstat5, mkdir as mkdir4, open as open2 } from "node:fs/promises";
15890
15870
  import { join as join26 } from "node:path";
@@ -16004,10 +15984,10 @@ async function retainDispatchError(admitted, principalAuthority, sessionAppender
16004
15984
  2
16005
15985
  )}
16006
15986
  `;
16007
- const noFollowFlag = typeof fsConstants.O_NOFOLLOW === "number" ? fsConstants.O_NOFOLLOW : 0;
15987
+ const noFollowFlag = typeof fsConstants2.O_NOFOLLOW === "number" ? fsConstants2.O_NOFOLLOW : 0;
16008
15988
  const handle = await open2(
16009
15989
  filePath,
16010
- fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL | noFollowFlag,
15990
+ fsConstants2.O_WRONLY | fsConstants2.O_CREAT | fsConstants2.O_EXCL | noFollowFlag,
16011
15991
  384
16012
15992
  );
16013
15993
  try {
@@ -16237,8 +16217,8 @@ var init_auto_resume = __esm({
16237
16217
 
16238
16218
  // src/public-cli/post-admission.ts
16239
16219
  import { randomUUID as randomUUID5 } from "node:crypto";
16240
- import { readFile as readFile16, writeFile as writeFile7 } from "node:fs/promises";
16241
- import { isAbsolute as isAbsolute7, join as join27, resolve as resolve11 } from "node:path";
16220
+ import { readFile as readFile17, writeFile as writeFile7 } from "node:fs/promises";
16221
+ import { isAbsolute as isAbsolute8, join as join27, resolve as resolve12 } from "node:path";
16242
16222
  function appendContinuationSection(continuation, section) {
16243
16223
  const prompt = `${continuation.prompt}
16244
16224
 
@@ -16247,7 +16227,7 @@ ${section}`;
16247
16227
  }
16248
16228
  async function readInvocationHost(runDirectory) {
16249
16229
  try {
16250
- const raw = JSON.parse(await readFile16(join27(runDirectory, "invocation.json"), "utf8"));
16230
+ const raw = JSON.parse(await readFile17(join27(runDirectory, "invocation.json"), "utf8"));
16251
16231
  return typeof raw.host === "string" && raw.host.trim() !== "" ? raw.host : void 0;
16252
16232
  } catch (error) {
16253
16233
  if (error.code === "ENOENT") return void 0;
@@ -16509,7 +16489,7 @@ function resumeTurnRequestProjectionOptions(admitted, request, env, summonsPrepa
16509
16489
  };
16510
16490
  }
16511
16491
  function isAlreadyFrozenSummonsAttachment(runDirectory, attachmentPath) {
16512
- const absolute = isAbsolute7(attachmentPath) ? attachmentPath : resolve11(attachmentPath);
16492
+ const absolute = isAbsolute8(attachmentPath) ? attachmentPath : resolve12(attachmentPath);
16513
16493
  return pathContainedIn(join27(runDirectory, "attachments"), absolute);
16514
16494
  }
16515
16495
  async function prepareSummonsResumeMaterials(runDirectory, summons) {
@@ -18139,13 +18119,13 @@ var init_compliance_transport = __esm({
18139
18119
 
18140
18120
  // src/dossier-resolution.ts
18141
18121
  import { existsSync as existsSync9, statSync as statSync2 } from "node:fs";
18142
- import { resolve as resolve12 } from "node:path";
18122
+ import { resolve as resolve13 } from "node:path";
18143
18123
  function resolveAuditDossier(env = process.env) {
18144
18124
  const raw = env[AUDIT_RUN_DIR_ENV];
18145
18125
  if (typeof raw !== "string" || raw.trim() === "") {
18146
18126
  return { status: "ok" };
18147
18127
  }
18148
- const runDirectory = resolve12(raw);
18128
+ const runDirectory = resolve13(raw);
18149
18129
  try {
18150
18130
  if (!existsSync9(runDirectory) || !statSync2(runDirectory).isDirectory()) {
18151
18131
  return { status: "incomplete", observation: { kind: "missing-dossier" } };
@@ -18426,7 +18406,7 @@ __export(archivist_record_entry_exports, {
18426
18406
  subjectKeyedRecordDirectory: () => subjectKeyedRecordDirectory
18427
18407
  });
18428
18408
  import { existsSync as existsSync10, mkdirSync as mkdirSync4, readFileSync as readFileSync3, realpathSync as realpathSync2, writeFileSync as writeFileSync5 } from "node:fs";
18429
- import { dirname as dirname14, resolve as resolve13, join as join30 } from "node:path";
18409
+ import { dirname as dirname14, resolve as resolve14, join as join30 } from "node:path";
18430
18410
  import { SessionManager } from "@earendil-works/pi-coding-agent";
18431
18411
  function readCurrentSession(sessionDir) {
18432
18412
  const ledger = join30(sessionDir, CURRENT_SESSION_LEDGER);
@@ -18456,8 +18436,8 @@ function writeCurrentSession(sessionDir, sessionFile) {
18456
18436
  }
18457
18437
  }
18458
18438
  function assertRecentFinalFileUnderSessionDir(sessionDir, recentFile) {
18459
- const absoluteSessionDir = resolve13(sessionDir);
18460
- const absoluteFile = resolve13(recentFile);
18439
+ const absoluteSessionDir = resolve14(sessionDir);
18440
+ const absoluteFile = resolve14(recentFile);
18461
18441
  if (absoluteFile !== absoluteSessionDir && !pathContainedIn(absoluteSessionDir, absoluteFile)) {
18462
18442
  throw new ActivationLedgerError(
18463
18443
  `archivist record session must be under the authorized nest (${sessionDir}): ${recentFile}`
@@ -18504,7 +18484,7 @@ function createRecordSessionOpen(options) {
18504
18484
  } else if (parentFile === void 0 || parentFile.length === 0) {
18505
18485
  return { session: SessionManager.inMemory(cwd), resumed: false };
18506
18486
  } else {
18507
- const parentResolved = resolve13(parentFile);
18487
+ const parentResolved = resolve14(parentFile);
18508
18488
  sessionDir = physicallyContainedIn(ledgerHome, parentResolved) ? join30(dirname14(parentResolved), options.kind) : join30(activationBookDirectory(ledgerHome, resolveBookKeyFromGit(cwd)), options.kind);
18509
18489
  parentSession = parentFile;
18510
18490
  }
@@ -18739,7 +18719,7 @@ var init_navigator_public_session = __esm({
18739
18719
 
18740
18720
  // src/navigator-attendance.ts
18741
18721
  import { createHash as createHash9 } from "node:crypto";
18742
- import { resolve as resolve14 } from "node:path";
18722
+ import { resolve as resolve15 } from "node:path";
18743
18723
  import "@earendil-works/pi-coding-agent";
18744
18724
  import { Type as Type15 } from "typebox";
18745
18725
  function resolveNavigatorAuthorityMaterial(roleInput, fileAuthority) {
@@ -18855,7 +18835,7 @@ function navigatorSubjectKey(subjectRoot, subject, provenance = "role_input") {
18855
18835
  }
18856
18836
  function navigatorSubjectKeyForInput(subjectRoot, reference, cwd = process.cwd()) {
18857
18837
  if (issueRoot(subjectRoot) !== void 0 || !subjectRoot.includes("/.ak/work/")) return subjectRoot;
18858
- const resolvedReference = resolve14(cwd, reference);
18838
+ const resolvedReference = resolve15(cwd, reference);
18859
18839
  const marker = "/runs/";
18860
18840
  if (resolvedReference.includes(marker)) {
18861
18841
  return subjectRoot;
@@ -19868,7 +19848,7 @@ import {
19868
19848
  statSync as statSync3,
19869
19849
  writeFileSync as writeFileSync6
19870
19850
  } from "node:fs";
19871
- import { isAbsolute as isAbsolute8, resolve as resolve16 } from "node:path";
19851
+ import { isAbsolute as isAbsolute9, resolve as resolve17 } from "node:path";
19872
19852
  function materializeDeferredSessionFile(sessionManager, resolvedFile) {
19873
19853
  const header = sessionManager.getHeader?.();
19874
19854
  if (header === null || header === void 0 || header.type !== "session") {
@@ -19896,12 +19876,12 @@ function durableSessionPointer(sessionManager) {
19896
19876
  "Workflow role activation requires a durable Pi session file principal (getSessionFile); directory-only or --no-session invocations are rejected"
19897
19877
  );
19898
19878
  }
19899
- if (!isAbsolute8(file)) {
19879
+ if (!isAbsolute9(file)) {
19900
19880
  throw new Error(
19901
19881
  `Workflow role activation requires an absolute durable session file path; got relative path: ${file}`
19902
19882
  );
19903
19883
  }
19904
- const resolvedFile = resolve16(file);
19884
+ const resolvedFile = resolve17(file);
19905
19885
  try {
19906
19886
  lstatSync2(resolvedFile);
19907
19887
  } catch (error) {
@@ -19975,7 +19955,7 @@ import {
19975
19955
  openSync,
19976
19956
  writeSync
19977
19957
  } from "node:fs";
19978
- import { dirname as dirname17, isAbsolute as isAbsolute9, resolve as resolve17 } from "node:path";
19958
+ import { dirname as dirname17, isAbsolute as isAbsolute10, resolve as resolve18 } from "node:path";
19979
19959
  function correlationIdentityFromEnv(env = process.env) {
19980
19960
  const raw = env.AK_CORRELATION_ID;
19981
19961
  if (typeof raw === "string" && raw.trim().length > 0) {
@@ -20004,13 +19984,13 @@ function serializeAcceptedActivationFact(fact) {
20004
19984
  `;
20005
19985
  }
20006
19986
  function appendActivationLedgerLine(ledgerPath, line2, options) {
20007
- if (!isAbsolute9(options.ledgerHome)) {
19987
+ if (!isAbsolute10(options.ledgerHome)) {
20008
19988
  throw new ActivationLedgerError(
20009
19989
  `activation ledger home must be absolute: ${options.ledgerHome}`
20010
19990
  );
20011
19991
  }
20012
- const resolvedLedger = resolve17(ledgerPath);
20013
- const resolvedHome = resolve17(options.ledgerHome);
19992
+ const resolvedLedger = resolve18(ledgerPath);
19993
+ const resolvedHome = resolve18(options.ledgerHome);
20014
19994
  const parent = dirname17(resolvedLedger);
20015
19995
  ensureRealDirectoryTree(resolvedHome, parent);
20016
19996
  assertLedgerFileInsideHome(resolvedLedger, resolvedHome);
@@ -20369,7 +20349,7 @@ var init_collector_tool_schemas = __esm({
20369
20349
  });
20370
20350
 
20371
20351
  // src/collector-handbook.ts
20372
- import { readFile as readFile18 } from "node:fs/promises";
20352
+ import { readFile as readFile19 } from "node:fs/promises";
20373
20353
  import { join as join33, sep as sep4 } from "node:path";
20374
20354
  function resolveCollectorHandbookRoot(sessionPath) {
20375
20355
  if (typeof sessionPath !== "string" || sessionPath.trim().length === 0) {
@@ -20423,7 +20403,7 @@ function createCollectorHandbookStore(input) {
20423
20403
  ensureRealDirectoryTree(input.ledgerHome, parentDir2);
20424
20404
  assertLedgerFileInsideHome(path, input.ledgerHome);
20425
20405
  try {
20426
- const body = await readFile18(path, "utf8");
20406
+ const body = await readFile19(path, "utf8");
20427
20407
  assertHandbookBudget(body, "\u6B63\u6587");
20428
20408
  return body;
20429
20409
  } catch (error) {
@@ -22103,7 +22083,7 @@ var init_reviewer_role = __esm({
22103
22083
  // src/worker-submission-gates.ts
22104
22084
  import { execFileSync as execFileSync4 } from "node:child_process";
22105
22085
  import { existsSync as existsSync11, lstatSync as lstatSync3, readdirSync as readdirSync2, readFileSync as readFileSync4, rmdirSync, rmSync } from "node:fs";
22106
- import { resolve as resolve18 } from "node:path";
22086
+ import { resolve as resolve19 } from "node:path";
22107
22087
  function git2(cwd, args) {
22108
22088
  return execFileSync4("git", args, {
22109
22089
  cwd,
@@ -22142,7 +22122,7 @@ function escapeGitConfigValueRegex(value) {
22142
22122
  function unsetOwnedHooksPath(file) {
22143
22123
  const owned = [];
22144
22124
  for (const value of tryGetAll(file, "core.hooksPath")) {
22145
- if (!ownedHook(resolve18(value, HOOK_FILE))) continue;
22125
+ if (!ownedHook(resolve19(value, HOOK_FILE))) continue;
22146
22126
  try {
22147
22127
  gitFile(file, [
22148
22128
  "--unset-all",
@@ -22157,15 +22137,15 @@ function unsetOwnedHooksPath(file) {
22157
22137
  return owned;
22158
22138
  }
22159
22139
  function rmOwnedDir(dir) {
22160
- const hookPath = resolve18(dir, HOOK_FILE);
22140
+ const hookPath = resolve19(dir, HOOK_FILE);
22161
22141
  if (!ownedHook(hookPath)) return;
22162
22142
  rmSync(hookPath, { force: true });
22163
22143
  if (existsSync11(dir) && readdirSync2(dir).length === 0) rmdirSync(dir);
22164
22144
  }
22165
22145
  function linkedGitDirs(commonDir) {
22166
- const root = resolve18(commonDir, "worktrees");
22146
+ const root = resolve19(commonDir, "worktrees");
22167
22147
  if (!existsSync11(root)) return [];
22168
- return readdirSync2(root).map((name) => resolve18(root, name)).filter((dir) => lstatSync3(dir).isDirectory());
22148
+ return readdirSync2(root).map((name) => resolve19(root, name)).filter((dir) => lstatSync3(dir).isDirectory());
22169
22149
  }
22170
22150
  function uninstallPackageWorkerHooks(cwd) {
22171
22151
  let inside;
@@ -22179,14 +22159,14 @@ function uninstallPackageWorkerHooks(cwd) {
22179
22159
  const clear = (configFile) => {
22180
22160
  for (const hooks of unsetOwnedHooksPath(configFile)) rmOwnedDir(hooks);
22181
22161
  };
22182
- clear(resolve18(commonDir, "config"));
22183
- clear(resolve18(commonDir, "config.worktree"));
22184
- rmOwnedDir(resolve18(commonDir, HOOKS_DIR));
22185
- const legacy = resolve18(commonDir, "hooks", HOOK_FILE);
22162
+ clear(resolve19(commonDir, "config"));
22163
+ clear(resolve19(commonDir, "config.worktree"));
22164
+ rmOwnedDir(resolve19(commonDir, HOOKS_DIR));
22165
+ const legacy = resolve19(commonDir, "hooks", HOOK_FILE);
22186
22166
  if (ownedHook(legacy)) rmSync(legacy, { force: true });
22187
22167
  for (const gitDir of linkedGitDirs(commonDir)) {
22188
- clear(resolve18(gitDir, "config.worktree"));
22189
- rmOwnedDir(resolve18(gitDir, HOOKS_DIR));
22168
+ clear(resolve19(gitDir, "config.worktree"));
22169
+ rmOwnedDir(resolve19(gitDir, HOOKS_DIR));
22190
22170
  }
22191
22171
  }
22192
22172
  function isRecord19(value) {
@@ -22755,63 +22735,42 @@ var init_worker_role = __esm({
22755
22735
  });
22756
22736
 
22757
22737
  // src/merger-role.ts
22758
- function same(a, b) {
22759
- return a.length === b.length && a.every((value, i) => value === b[i]);
22760
- }
22761
22738
  function materialText(input, key) {
22762
22739
  return exactUtf8(Buffer.from(input.materials[key].bytesBase64, "base64"), `Merger ${key}`);
22763
22740
  }
22764
- function createMergerRoleRuntime(pi, dependencies, host) {
22741
+ function createMergerRoleRuntime(pi, dependencies) {
22765
22742
  let activation;
22766
22743
  let registered = false;
22767
22744
  let accepted = false;
22768
22745
  pi.registerFlag(MERGER_INPUT_FLAG.name, MERGER_INPUT_FLAG.definition);
22769
- return { async activate() {
22770
- const path = pi.getFlag(MERGER_INPUT_FLAG.name);
22771
- if (typeof path !== "string" || path.trim().length === 0) throw new Error("Merger requires --ak-merger-input");
22772
- const soul = (await dependencies.loadSoul()).trim();
22773
- if (!soul) throw new Error("Merger soul is empty");
22774
- const input = validateMergerInput(await dependencies.loadInput(path));
22775
- const state = await dependencies.gitState.activeMerge();
22776
- if (state.targetObjectId !== input.targetObjectId || state.sourceObjectId !== input.sourceObjectId || !same(state.unmergedPaths, input.expectedConflictPaths) || state.unmergedPaths.length === 0 || !isFullGitObjectId(state.automaticMergeTreeId) || state.automaticMergeTreeId.length !== input.targetObjectId.length) throw new Error("Merger activation rejected repository parent, merge, automatic-result, or complete conflict-set drift");
22777
- activation = { soul, input, automaticMergeTreeId: state.automaticMergeTreeId };
22778
- accepted = false;
22779
- if (!registered) {
22780
- registered = true;
22781
- pi.registerTool({
22782
- name: MERGER_OUTPUT_TOOL_NAME,
22783
- label: "\u5408\u5E76\u8F93\u51FA",
22784
- description: "\u63D0\u4EA4\u5408\u5E76\u7ED3\u679C\uFF1B\u8F93\u51FA\u5206\u652F\u4E3A completed \u4E0E escalate\uFF1B\u57FA\u7840\u8BBE\u65BD\u53CA Git \u5931\u8D25\u7531 abort \u901A\u9053\u627F\u63A5\u3002",
22785
- promptSnippet: "\u63D0\u4EA4\u5408\u5E76\u7ED3\u679C",
22786
- parameters: mergerOutputSchema,
22787
- async execute(id, params, _signal, _update, ctx) {
22788
- if (!activation) throw new Error("\u6821\u4E66\u90CE\u672A\u6FC0\u6D3B");
22789
- if (accepted) throw new Error("\u5408\u5E76\u56DE\u6267\u5DF2\u53D7\u7406");
22790
- let output;
22791
- try {
22792
- output = validateMergerOutput(params, activation.input.attemptId);
22793
- } catch (error) {
22794
- host.failInfrastructure(error, ctx, id);
22795
- }
22796
- if (output.status === "completed") {
22797
- let state2;
22798
- try {
22799
- state2 = await dependencies.gitState.completedMerge(output.mergeCommitId, activation.automaticMergeTreeId);
22800
- } catch (error) {
22801
- host.failInfrastructure(error, ctx, id);
22802
- }
22803
- const scope = new Set(activation.input.resolutionScope);
22804
- if (state2.mergeCommitId !== output.mergeCommitId || !same(state2.parentObjectIds, [activation.input.targetObjectId, activation.input.sourceObjectId]) || state2.unmergedPaths.length !== 0 || !state2.worktreeClean || state2.resolutionChangedPaths.some((path2) => !scope.has(path2))) host.failInfrastructure(new Error("Merger completed-state verification failed"), ctx, id);
22746
+ return {
22747
+ async activate() {
22748
+ const path = pi.getFlag(MERGER_INPUT_FLAG.name);
22749
+ if (typeof path !== "string" || path.trim().length === 0) throw new Error("Merger requires --ak-merger-input");
22750
+ const soul = (await dependencies.loadSoul()).trim();
22751
+ if (!soul) throw new Error("Merger soul is empty");
22752
+ const input = validateMergerInput(await dependencies.loadInput(path));
22753
+ activation = { soul, input };
22754
+ accepted = false;
22755
+ if (!registered) {
22756
+ registered = true;
22757
+ pi.registerTool({
22758
+ name: MERGER_OUTPUT_TOOL_NAME,
22759
+ label: "\u5408\u5E76\u8F93\u51FA",
22760
+ description: "\u63D0\u4EA4\u5408\u5E76\u7ED3\u679C\uFF1B\u8F93\u51FA\u5206\u652F\u4E3A completed \u4E0E escalate\u3002",
22761
+ promptSnippet: "\u63D0\u4EA4\u5408\u5E76\u7ED3\u679C",
22762
+ parameters: mergerOutputSchema,
22763
+ async execute(_id, params, _signal, _update, _ctx) {
22764
+ if (!activation) throw new Error("\u6821\u4E66\u90CE\u672A\u6FC0\u6D3B");
22765
+ if (accepted) throw new Error("\u5408\u5E76\u56DE\u6267\u5DF2\u53D7\u7406");
22766
+ accepted = true;
22767
+ return { content: [{ type: "text", text: MERGER_ACCEPTED_TEXT }], details: params, terminate: true };
22805
22768
  }
22806
- accepted = true;
22807
- const acceptedDetails = output;
22808
- return { content: [{ type: "text", text: MERGER_ACCEPTED_TEXT }], details: acceptedDetails, terminate: true };
22809
- }
22810
- });
22811
- pi.on("before_agent_start", (event) => {
22812
- if (!activation) throw new Error("\u6821\u4E66\u90CE\u672A\u6FC0\u6D3B");
22813
- const admitted = { attemptId: activation.input.attemptId, targetObjectId: activation.input.targetObjectId, sourceObjectId: activation.input.sourceObjectId, task: materialText(activation.input, "task"), authority: materialText(activation.input, "authority"), targetIntent: materialText(activation.input, "targetIntent"), sourceIntent: materialText(activation.input, "sourceIntent"), expectedConflictPaths: activation.input.expectedConflictPaths, resolutionScope: activation.input.resolutionScope, authorizedChecks: activation.input.authorizedChecks };
22814
- return { systemPrompt: `${event.systemPrompt}
22769
+ });
22770
+ pi.on("before_agent_start", (event) => {
22771
+ if (!activation) throw new Error("\u6821\u4E66\u90CE\u672A\u6FC0\u6D3B");
22772
+ const admitted = { attemptId: activation.input.attemptId, targetObjectId: activation.input.targetObjectId, sourceObjectId: activation.input.sourceObjectId, task: materialText(activation.input, "task"), authority: materialText(activation.input, "authority"), targetIntent: materialText(activation.input, "targetIntent"), sourceIntent: materialText(activation.input, "sourceIntent"), expectedConflictPaths: activation.input.expectedConflictPaths, resolutionScope: activation.input.resolutionScope, authorizedChecks: activation.input.authorizedChecks };
22773
+ return { systemPrompt: `${event.systemPrompt}
22815
22774
 
22816
22775
  <merger_soul>
22817
22776
  ${activation.soul}
@@ -22820,13 +22779,14 @@ ${activation.soul}
22820
22779
  <merger_assignment>
22821
22780
  ${JSON.stringify(admitted)}
22822
22781
  </merger_assignment>` };
22823
- });
22824
- }
22825
- const all = pi.getAllTools().map((tool) => tool.name);
22826
- if (all.filter((item) => item === MERGER_OUTPUT_TOOL_NAME).length !== 1) {
22827
- throw new Error(`Merger required tool collision or missing: ${MERGER_OUTPUT_TOOL_NAME}`);
22782
+ });
22783
+ }
22784
+ const all = pi.getAllTools().map((tool) => tool.name);
22785
+ if (all.filter((item) => item === MERGER_OUTPUT_TOOL_NAME).length !== 1) {
22786
+ throw new Error(`Merger required tool collision or missing: ${MERGER_OUTPUT_TOOL_NAME}`);
22787
+ }
22828
22788
  }
22829
- } };
22789
+ };
22830
22790
  }
22831
22791
  var MERGER_INPUT_FLAG;
22832
22792
  var init_merger_role = __esm({
@@ -22834,8 +22794,7 @@ var init_merger_role = __esm({
22834
22794
  "use strict";
22835
22795
  init_merger_contracts();
22836
22796
  init_exact_utf8();
22837
- init_git_object_id();
22838
- MERGER_INPUT_FLAG = { name: "ak-merger-input", definition: { description: "Path to an immutable digest-bound Merger v1 input JSON file", type: "string" } };
22797
+ MERGER_INPUT_FLAG = { name: "ak-merger-input", definition: { description: "Path to Merger assignment materials JSON", type: "string" } };
22839
22798
  }
22840
22799
  });
22841
22800
 
@@ -23788,7 +23747,6 @@ function createRoleRuntimeExtension(dependencies) {
23788
23747
  }
23789
23748
  }
23790
23749
  );
23791
- let sessionMergerGitState = dependencies.mergerGitState;
23792
23750
  const merger = createMergerRoleRuntime(roleHost, {
23793
23751
  async loadSoul() {
23794
23752
  if (!dependencies.loadMergerSoul) throw new Error("Merger runtime dependencies are not configured");
@@ -23797,18 +23755,8 @@ function createRoleRuntimeExtension(dependencies) {
23797
23755
  async loadInput(path) {
23798
23756
  if (!dependencies.loadMergerInput) throw new Error("Merger runtime dependencies are not configured");
23799
23757
  return dependencies.loadMergerInput(path);
23800
- },
23801
- gitState: {
23802
- activeMerge() {
23803
- if (!sessionMergerGitState) throw new Error("Merger runtime dependencies are not configured");
23804
- return sessionMergerGitState.activeMerge();
23805
- },
23806
- completedMerge(mergeCommitId, automaticMergeTreeId) {
23807
- if (!sessionMergerGitState) throw new Error("Merger runtime dependencies are not configured");
23808
- return sessionMergerGitState.completedMerge(mergeCommitId, automaticMergeTreeId);
23809
- }
23810
23758
  }
23811
- }, hostActions);
23759
+ });
23812
23760
  let activeCollector;
23813
23761
  let collectorFirstDispatchDone = false;
23814
23762
  const collectorBusiness = createCollectorRoleRuntime(
@@ -24043,10 +23991,6 @@ function createRoleRuntimeExtension(dependencies) {
24043
23991
  auditor,
24044
23992
  diarist,
24045
23993
  merger: async () => {
24046
- if (dependencies.mergerGitState === void 0) {
24047
- sessionMergerGitState = dependencies.createMergerGitState?.(ctx.cwd);
24048
- }
24049
- if (sessionMergerGitState === void 0) throw new Error("Merger runtime dependencies are not configured");
24050
23994
  await merger.activate();
24051
23995
  }
24052
23996
  };
@@ -25416,7 +25360,7 @@ import { mkdtemp as mkdtemp3, rm as rm4 } from "node:fs/promises";
25416
25360
  import { tmpdir as tmpdir3 } from "node:os";
25417
25361
  import { join as join36 } from "node:path";
25418
25362
  async function runCommand(command, args, options = {}) {
25419
- return await new Promise((resolve19, reject) => {
25363
+ return await new Promise((resolve20, reject) => {
25420
25364
  const child = spawn4(command, args, { ...options.cwd === void 0 ? {} : { cwd: options.cwd }, stdio: ["ignore", "pipe", "pipe"], signal: options.signal });
25421
25365
  let stdout = "", stderr = "";
25422
25366
  child.stdout.setEncoding("utf8").on("data", (chunk) => {
@@ -25436,7 +25380,7 @@ async function runCommand(command, args, options = {}) {
25436
25380
  const actual = code ?? 1;
25437
25381
  if ((options.allowedCodes ?? [0]).includes(actual)) {
25438
25382
  settled = true;
25439
- resolve19({ stdout, stderr, code: actual });
25383
+ resolve20({ stdout, stderr, code: actual });
25440
25384
  } else fail5(void 0, code, signal);
25441
25385
  });
25442
25386
  });
@@ -25686,7 +25630,7 @@ var init_reviewer_agent = __esm({
25686
25630
  import { randomUUID as randomUUID9 } from "node:crypto";
25687
25631
 
25688
25632
  // src/role-runtime-dependencies.ts
25689
- import { readFile as readFile19 } from "node:fs/promises";
25633
+ import { readFile as readFile20 } from "node:fs/promises";
25690
25634
  import { fileURLToPath as fileURLToPath2 } from "node:url";
25691
25635
 
25692
25636
  // src/canonical-skill-binding.ts
@@ -25757,7 +25701,6 @@ async function loadCanonicalSkillBinding(name) {
25757
25701
  init_collector_github();
25758
25702
  init_doctor_auditor();
25759
25703
  init_doctor_evidence();
25760
- init_merger_git_state();
25761
25704
  init_navigator_attendance();
25762
25705
 
25763
25706
  // src/navigator-work-context.ts
@@ -25766,17 +25709,17 @@ init_navigator_attendance();
25766
25709
  init_notary_source_run();
25767
25710
  init_packaged_role_registry();
25768
25711
  init_invocation();
25769
- import { readFile as readFile17 } from "node:fs/promises";
25770
- import { resolve as resolve15 } from "node:path";
25712
+ import { readFile as readFile18 } from "node:fs/promises";
25713
+ import { resolve as resolve16 } from "node:path";
25771
25714
  function navigatorInputReference(getFlag, role) {
25772
25715
  if (getFlag === void 0) return void 0;
25773
25716
  const name = packagedRoleInputFlag(role);
25774
25717
  const value = name === void 0 ? void 0 : getFlag(name);
25775
- return typeof value === "string" && value !== "" ? resolve15(value) : void 0;
25718
+ return typeof value === "string" && value !== "" ? resolve16(value) : void 0;
25776
25719
  }
25777
25720
  async function loadNavigatorWorkContext(options) {
25778
25721
  const reference = navigatorInputReference(options.getFlag, options.role);
25779
- const input = reference === void 0 || options.role === "doctor" || options.role === "notary" ? void 0 : await readFile17(reference, "utf8");
25722
+ const input = reference === void 0 || options.role === "doctor" || options.role === "notary" ? void 0 : await readFile18(reference, "utf8");
25780
25723
  const subjectRoot = subjectPath(reference ?? options.context.sessionManager.getSessionDir(), options.context.cwd);
25781
25724
  let subjectKey = reference === void 0 ? subjectRoot : navigatorSubjectKeyForInput(subjectRoot, reference, options.context.cwd);
25782
25725
  let subject = input ?? `work subject: ${subjectKey}`;
@@ -25793,7 +25736,7 @@ async function loadNavigatorWorkContext(options) {
25793
25736
  }
25794
25737
  const publicRunDir = process.env.AK_ROLE_RUN_DIR;
25795
25738
  const currentSessionDir = options.context.sessionManager.getSessionDir();
25796
- const isBoundPublicRun = typeof publicRunDir === "string" && publicRunDir.trim() !== "" && resolve15(currentSessionDir) === resolve15(publicRunDir, "session");
25739
+ const isBoundPublicRun = typeof publicRunDir === "string" && publicRunDir.trim() !== "" && resolve16(currentSessionDir) === resolve16(publicRunDir, "session");
25797
25740
  if (options.role === "judge" && isBoundPublicRun) {
25798
25741
  let admitted;
25799
25742
  try {
@@ -25826,14 +25769,14 @@ async function loadNavigatorWorkContext(options) {
25826
25769
  }
25827
25770
  const workRoot = subjectRoot.includes("/.ak/work/") ? subjectRoot : void 0;
25828
25771
  const authorityFiles = workRoot === void 0 ? [] : [
25829
- resolve15(workRoot, "authority.md"),
25830
- resolve15(workRoot, "authority.txt"),
25831
- resolve15(workRoot, "design-v2/owner-direction.md")
25772
+ resolve16(workRoot, "authority.md"),
25773
+ resolve16(workRoot, "authority.txt"),
25774
+ resolve16(workRoot, "design-v2/owner-direction.md")
25832
25775
  ];
25833
25776
  let authorityMaterial;
25834
25777
  for (const path of authorityFiles) {
25835
25778
  try {
25836
- const content = await readFile17(path, "utf8");
25779
+ const content = await readFile18(path, "utf8");
25837
25780
  if (content.trim() !== "") {
25838
25781
  authorityMaterial = content;
25839
25782
  break;
@@ -25905,14 +25848,14 @@ function createRoleRuntimeDependencies(packageRoot) {
25905
25848
  return {
25906
25849
  loadJudgeSoul: () => loadMainRoleSessionMaterials("judge"),
25907
25850
  loadFixerSoul: () => loadMainRoleSessionMaterials("fixer"),
25908
- loadFixPacket: (path) => readFile19(path, "utf8"),
25851
+ loadFixPacket: (path) => readFile20(path, "utf8"),
25909
25852
  loadCoderSoul: () => loadMainRoleSessionMaterials("coder"),
25910
- loadCoderTask: (path) => readFile19(path, "utf8"),
25853
+ loadCoderTask: (path) => readFile20(path, "utf8"),
25911
25854
  loadReviewerSoul: () => loadMainRoleSessionMaterials("reviewer"),
25912
25855
  createReviewerPinnedGitReader: () => createReviewerPinnedGitReader(),
25913
25856
  createReviewerIssueFetcher: () => createGhIssueSoftFetcher(),
25914
25857
  loadCollectorSoul: () => loadMainRoleSessionMaterials("collector"),
25915
- loadCollectorHandbookSeed: () => readFile19(collectorHandbookSeedPath, "utf8"),
25858
+ loadCollectorHandbookSeed: () => readFile20(collectorHandbookSeedPath, "utf8"),
25916
25859
  createCollectorTransport: () => createGhCollectorGitHubTransport(),
25917
25860
  loadDoctorSoul: () => loadMainRoleSessionMaterials("doctor"),
25918
25861
  loadDoctorCase,
@@ -25926,8 +25869,7 @@ function createRoleRuntimeDependencies(packageRoot) {
25926
25869
  loadDiaristSoul: () => loadMainRoleSessionMaterials("diarist"),
25927
25870
  loadNotarySourceRun: loadNotarySourceRunLocator,
25928
25871
  loadMergerSoul: () => loadMainRoleSessionMaterials("merger"),
25929
- loadMergerInput: async (path) => JSON.parse(await readFile19(path, "utf8")),
25930
- createMergerGitState: (repositoryRoot) => createProductionMergerGitState(repositoryRoot),
25872
+ loadMergerInput: async (path) => JSON.parse(await readFile20(path, "utf8")),
25931
25873
  async loadCanonicalSkillBinding(name) {
25932
25874
  if (name === "tdd") {
25933
25875
  return loadPackagedCanonicalSkillBinding(packageRoot, "tdd");
@@ -25955,7 +25897,7 @@ function createRoleRuntimeDependencies(packageRoot) {
25955
25897
  authority: options.authority,
25956
25898
  invocationId: options.invocationId,
25957
25899
  loadSoul: () => loadMainRoleSessionMaterials("navigator"),
25958
- loadRoutePlaybook: () => readFile19(navigatorRoutePlaybookPath, "utf8"),
25900
+ loadRoutePlaybook: () => readFile20(navigatorRoutePlaybookPath, "utf8"),
25959
25901
  loadRoleHelp: async (role) => formatNavigatorRoleHelp(role),
25960
25902
  createSession: navigatorSessionFactory,
25961
25903
  ...options.contextError === void 0 ? {} : { contextError: options.contextError },
@@ -25974,7 +25916,7 @@ init_role_activation_flags();
25974
25916
  init_submission_correctable_error();
25975
25917
  init_navigator_invocation_identity();
25976
25918
  import { randomUUID as randomUUID7 } from "node:crypto";
25977
- import { mkdir as mkdir5, readFile as readFile20, writeFile as writeFile9 } from "node:fs/promises";
25919
+ import { mkdir as mkdir5, readFile as readFile21, writeFile as writeFile9 } from "node:fs/promises";
25978
25920
  import { createServer } from "node:net";
25979
25921
  import { basename as basename8, dirname as dirname19, join as join37 } from "node:path";
25980
25922
  import { fileURLToPath as fileURLToPath3 } from "node:url";
@@ -25994,11 +25936,11 @@ ${method.body}`,
25994
25936
  });
25995
25937
  }
25996
25938
  async function listen(server, path) {
25997
- await new Promise((resolve19, reject) => {
25939
+ await new Promise((resolve20, reject) => {
25998
25940
  server.once("error", reject);
25999
25941
  server.listen(path, () => {
26000
25942
  server.off("error", reject);
26001
- resolve19();
25943
+ resolve20();
26002
25944
  });
26003
25945
  });
26004
25946
  }
@@ -26036,7 +25978,7 @@ async function prepareRoleEnvelope(options) {
26036
25978
  for (const method of request.methods) {
26037
25979
  if (method.kind !== "skill") continue;
26038
25980
  const name = basename8(dirname19(method.path));
26039
- const raw = await readFile20(method.path, "utf8");
25981
+ const raw = await readFile21(method.path, "utf8");
26040
25982
  methodSkills.set(name, { path: method.path, body: stripSkillFrontmatter(raw).trim() });
26041
25983
  }
26042
25984
  let sessionFile = options.sessionFile ?? join37(request.runDirectory, "session", "session.jsonl");
@@ -26397,8 +26339,8 @@ async function prepareRoleEnvelope(options) {
26397
26339
  try {
26398
26340
  const closeAll = server.closeAllConnections;
26399
26341
  if (typeof closeAll === "function") closeAll.call(server);
26400
- await new Promise((resolve19, reject) => {
26401
- server.close((error) => error ? reject(error) : resolve19());
26342
+ await new Promise((resolve20, reject) => {
26343
+ server.close((error) => error ? reject(error) : resolve20());
26402
26344
  });
26403
26345
  } catch (error) {
26404
26346
  cleanupFailures.push(error);
@@ -26465,7 +26407,7 @@ async function prepareRoleEnvelope(options) {
26465
26407
  message: { role: "user", content: prompt }
26466
26408
  });
26467
26409
  }
26468
- const methodPrompt = (await Promise.all(request.methods.map(({ path }) => readFile20(path, "utf8")))).join("\n\n");
26410
+ const methodPrompt = (await Promise.all(request.methods.map(({ path }) => readFile21(path, "utf8")))).join("\n\n");
26469
26411
  const promptResults = await emit("before_agent_start", {
26470
26412
  prompt,
26471
26413
  systemPrompt: methodPrompt,
@@ -26524,7 +26466,7 @@ async function prepareRoleEnvelope(options) {
26524
26466
  }
26525
26467
 
26526
26468
  // src/session-identity.ts
26527
- import { mkdir as mkdir6, readFile as readFile21, rename as rename2, writeFile as writeFile10 } from "node:fs/promises";
26469
+ import { mkdir as mkdir6, readFile as readFile22, rename as rename2, writeFile as writeFile10 } from "node:fs/promises";
26528
26470
  import { dirname as dirname20, join as join38 } from "node:path";
26529
26471
  function createSessionIdentityAuthority(authority, sessionBindingFile) {
26530
26472
  const bindingPath = (principal) => join38(authority.decode(principal).sessionDirectory, sessionBindingFile);
@@ -26534,7 +26476,7 @@ function createSessionIdentityAuthority(authority, sessionBindingFile) {
26534
26476
  },
26535
26477
  async load(principal) {
26536
26478
  try {
26537
- const value = JSON.parse(await readFile21(bindingPath(principal), "utf8"));
26479
+ const value = JSON.parse(await readFile22(bindingPath(principal), "utf8"));
26538
26480
  if (typeof value !== "object" || value === null || typeof value.sessionId !== "string") {
26539
26481
  throw new Error("durable session binding is invalid");
26540
26482
  }
@@ -26782,7 +26724,7 @@ function resultCandidateText(line2) {
26782
26724
  }
26783
26725
  }
26784
26726
  function spawnHeadlessTurn(options) {
26785
- return new Promise((resolve19, reject) => {
26727
+ return new Promise((resolve20, reject) => {
26786
26728
  if (options.signal?.aborted) {
26787
26729
  reject(hostAbortedError("headless host aborted"));
26788
26730
  return;
@@ -26841,7 +26783,7 @@ function spawnHeadlessTurn(options) {
26841
26783
  settled = true;
26842
26784
  if (timer !== void 0) clearTimeout(timer);
26843
26785
  options.signal?.removeEventListener("abort", onAbort);
26844
- resolve19({ code, stdout: resultStdout, stderr, timedOut });
26786
+ resolve20({ code, stdout: resultStdout, stderr, timedOut });
26845
26787
  };
26846
26788
  const onAbort = () => {
26847
26789
  child.kill("SIGTERM");