immune-brain 4.2.0 → 4.4.0

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.
@@ -39,7 +39,7 @@ function probeHost(env = process.env, platform = process.platform, hostVersion)
39
39
  }
40
40
 
41
41
  // plugins/immune-brain/runtime/plugin_version.ts
42
- var PLUGIN_VERSION = "4.2.0";
42
+ var PLUGIN_VERSION = "4.4.0";
43
43
 
44
44
  // plugins/immune-brain/runtime/claude/interaction.ts
45
45
  import { createHash, randomUUID } from "node:crypto";
@@ -678,7 +678,7 @@ function parseHookStdin(raw) {
678
678
  // plugins/immune-brain/runtime/claude/kernel_ports.ts
679
679
  import { randomUUID as randomUUID9 } from "node:crypto";
680
680
  import { existsSync as existsSync10, readFileSync as readFileSync14, writeFileSync as writeFileSync8 } from "node:fs";
681
- import { execFileSync as execFileSync6 } from "node:child_process";
681
+ import { execFileSync as execFileSync7 } from "node:child_process";
682
682
  import { join as join15 } from "node:path";
683
683
 
684
684
  // plugins/immune-brain/runtime/assurance/coordinator.ts
@@ -7782,11 +7782,84 @@ function enrollCanaryTask(root, input, registry) {
7782
7782
  }
7783
7783
  }
7784
7784
 
7785
+ // plugins/immune-brain/runtime/assurance/enrollment_git_base.ts
7786
+ import { execFileSync as execFileSync4, spawnSync as spawnSync4 } from "node:child_process";
7787
+ function git2(root, args, input, env = process.env) {
7788
+ return execFileSync4("git", args, { cwd: root, encoding: "utf8", input, env, stdio: ["pipe", "pipe", "pipe"] }).trim();
7789
+ }
7790
+ function inspectEnrollmentGitBase(root) {
7791
+ if (git2(root, ["rev-parse", "--is-inside-work-tree"]) !== "true")
7792
+ throw new Error("Enrollment requires a Git working tree");
7793
+ try {
7794
+ return { state: "committed", head: readGitHead(root) };
7795
+ } catch {}
7796
+ const branch = git2(root, ["symbolic-ref", "--no-recurse", "HEAD"]);
7797
+ if (!branch.startsWith("refs/heads/"))
7798
+ throw new Error("Enrollment HEAD must name a local branch");
7799
+ const ref = spawnSync4("git", ["show-ref", "--verify", "--quiet", branch], { cwd: root });
7800
+ const symbolic = spawnSync4("git", ["symbolic-ref", "-q", branch], { cwd: root });
7801
+ if (ref.status !== 1 || symbolic.status !== 1)
7802
+ throw new Error("Enrollment Git HEAD is invalid; only an absent branch can be initialized");
7803
+ return { state: "unborn", branch };
7804
+ }
7805
+ function enrollmentGitBaseNotice(base) {
7806
+ return base.state === "unborn" ? `Git: create an empty initial commit on ${base.branch} before Enrollment; staged files and working tree remain unchanged. This commit remains if later Enrollment fails or is cancelled.` : undefined;
7807
+ }
7808
+ function identityEnv(root) {
7809
+ const configured = (key) => {
7810
+ const result = spawnSync4("git", ["config", "--get", key], { cwd: root, encoding: "utf8" });
7811
+ if (result.status !== 0 && result.status !== 1)
7812
+ throw new Error(`Cannot read Git identity: ${key}`);
7813
+ return result.stdout?.trim() ?? "";
7814
+ };
7815
+ const name = configured("user.name") || "Immune-Brain Enrollment";
7816
+ const email = configured("user.email") || "enrollment@immune-brain.local";
7817
+ return {
7818
+ ...process.env,
7819
+ GIT_AUTHOR_NAME: process.env.GIT_AUTHOR_NAME || name,
7820
+ GIT_AUTHOR_EMAIL: process.env.GIT_AUTHOR_EMAIL || email,
7821
+ GIT_COMMITTER_NAME: process.env.GIT_COMMITTER_NAME || name,
7822
+ GIT_COMMITTER_EMAIL: process.env.GIT_COMMITTER_EMAIL || email
7823
+ };
7824
+ }
7825
+ function initializeEnrollmentGitBase(root, input, previous, base, signal) {
7826
+ const assertUnchanged = () => {
7827
+ signal?.throwIfAborted();
7828
+ if (!revalidatePiCanary(root, input, previous).unchanged || JSON.stringify(inspectEnrollmentGitBase(root)) !== JSON.stringify(base))
7829
+ throw new Error("Workspace or Git branch changed after confirmation; retry Enrollment");
7830
+ };
7831
+ assertUnchanged();
7832
+ if (base.state === "committed")
7833
+ return previous;
7834
+ return withKernelStoreLock(root, () => {
7835
+ let created;
7836
+ try {
7837
+ assertUnchanged();
7838
+ if (!previous.intent || previous.backend_claim.present || previous.task_record_v3?.present || previous.workspace.current_working !== null)
7839
+ throw new Error("Empty Git base initialization requires an unowned workspace and a tracked TaskIntent");
7840
+ const tree = git2(root, ["hash-object", "-t", "tree", "-w", "--stdin"], "");
7841
+ const commit = git2(root, ["commit-tree", tree, "-m", "chore: initialize empty Enrollment base"], undefined, identityEnv(root));
7842
+ assertUnchanged();
7843
+ git2(root, ["update-ref", "--no-deref", base.branch, commit, "0".repeat(commit.length)]);
7844
+ created = commit;
7845
+ const current = preparePiCanary(root, input);
7846
+ const withoutGit = ({ digest, git_base_head, git_error, ...owners }) => owners;
7847
+ if (git2(root, ["symbolic-ref", "--no-recurse", "HEAD"]) !== base.branch || current.git_base_head !== commit || JSON.stringify(withoutGit(current)) !== JSON.stringify(withoutGit(previous)))
7848
+ throw new Error("Workspace changed during empty Git base initialization; retry Enrollment");
7849
+ return current;
7850
+ } catch (error) {
7851
+ if (created)
7852
+ throw new Error(`${error instanceof Error ? error.message : String(error)}; empty initial commit ${created} remains`);
7853
+ throw error;
7854
+ }
7855
+ });
7856
+ }
7857
+
7785
7858
  // plugins/immune-brain/runtime/assurance/qa.ts
7786
7859
  import { createHash as createHash17 } from "node:crypto";
7787
7860
 
7788
7861
  // plugins/immune-brain/runtime/assurance/delivery_workspace.ts
7789
- import { execFileSync as execFileSync4 } from "node:child_process";
7862
+ import { execFileSync as execFileSync5 } from "node:child_process";
7790
7863
  import { createHash as createHash16 } from "node:crypto";
7791
7864
  import { chmodSync as chmodSync2, lstatSync as lstatSync8, mkdirSync as mkdirSync5, mkdtempSync as mkdtempSync2, readdirSync as readdirSync5, readFileSync as readFileSync10, readlinkSync as readlinkSync2, realpathSync as realpathSync9, rmSync as rmSync5 } from "node:fs";
7792
7865
  import { tmpdir as tmpdir3 } from "node:os";
@@ -7833,8 +7906,8 @@ function isolatedGitEnv(extra = {}) {
7833
7906
  ...extra
7834
7907
  };
7835
7908
  }
7836
- function git2(cwd, args, extra = {}) {
7837
- return execFileSync4("git", args, {
7909
+ function git3(cwd, args, extra = {}) {
7910
+ return execFileSync5("git", args, {
7838
7911
  cwd,
7839
7912
  encoding: "utf8",
7840
7913
  stdio: ["ignore", "pipe", "pipe"],
@@ -7898,24 +7971,24 @@ function assertNoEscapingSymlinks(root, dir = root) {
7898
7971
  function writeDeliveryTree(sourceRoot, snapshot) {
7899
7972
  const indexDirectory = mkdtempSync2(join8(tmpdir3(), "imm-delivery-index-"));
7900
7973
  try {
7901
- git2(sourceRoot, ["read-tree", snapshot.base_tree], {
7974
+ git3(sourceRoot, ["read-tree", snapshot.base_tree], {
7902
7975
  GIT_INDEX_FILE: join8(indexDirectory, "index"),
7903
7976
  GIT_DIR: join8(sourceRoot, ".git")
7904
7977
  });
7905
7978
  for (const [path, entry] of Object.entries(snapshot.changed_paths)) {
7906
7979
  if (entry.oid && entry.mode) {
7907
- git2(sourceRoot, ["update-index", "--add", "--cacheinfo", `${entry.mode},${entry.oid},${path}`], {
7980
+ git3(sourceRoot, ["update-index", "--add", "--cacheinfo", `${entry.mode},${entry.oid},${path}`], {
7908
7981
  GIT_INDEX_FILE: join8(indexDirectory, "index"),
7909
7982
  GIT_DIR: join8(sourceRoot, ".git")
7910
7983
  });
7911
7984
  } else {
7912
- git2(sourceRoot, ["update-index", "--force-remove", "--", path], {
7985
+ git3(sourceRoot, ["update-index", "--force-remove", "--", path], {
7913
7986
  GIT_INDEX_FILE: join8(indexDirectory, "index"),
7914
7987
  GIT_DIR: join8(sourceRoot, ".git")
7915
7988
  });
7916
7989
  }
7917
7990
  }
7918
- const next = git2(sourceRoot, ["write-tree"], {
7991
+ const next = git3(sourceRoot, ["write-tree"], {
7919
7992
  GIT_INDEX_FILE: join8(indexDirectory, "index"),
7920
7993
  GIT_DIR: join8(sourceRoot, ".git")
7921
7994
  });
@@ -7949,9 +8022,9 @@ function workspaceSeal(root) {
7949
8022
  function assertDeliveryClean(root, tree, seal, writablePaths = []) {
7950
8023
  assertTree(tree);
7951
8024
  if (seal === undefined) {
7952
- if (git2(root, ["status", "--porcelain", "--untracked-files=all", "--ignored=matching"]))
8025
+ if (git3(root, ["status", "--porcelain", "--untracked-files=all", "--ignored=matching"]))
7953
8026
  throw new DeliveryWorkspaceError("delivery workspace was contaminated");
7954
- if (git2(root, ["rev-parse", "HEAD^{tree}"]) !== tree)
8027
+ if (git3(root, ["rev-parse", "HEAD^{tree}"]) !== tree)
7955
8028
  throw new DeliveryWorkspaceError("delivery workspace tree drifted from the frozen identity");
7956
8029
  return;
7957
8030
  }
@@ -7989,7 +8062,7 @@ function materializeDeliveryWorkspace(sourceRoot, tree) {
7989
8062
  const cleanup = () => removeTaskOwnedTree(dest);
7990
8063
  try {
7991
8064
  mkdirSync5(dest, { recursive: true });
7992
- const commit = git2(sourceRoot, ["commit-tree", tree, "-m", `delivery ${tree}`], {
8065
+ const commit = git3(sourceRoot, ["commit-tree", tree, "-m", `delivery ${tree}`], {
7993
8066
  GIT_DIR: join8(sourceRoot, ".git"),
7994
8067
  GIT_AUTHOR_NAME: "Immune-Brain Assurance",
7995
8068
  GIT_AUTHOR_EMAIL: "assurance@immune-brain.local",
@@ -8000,10 +8073,10 @@ function materializeDeliveryWorkspace(sourceRoot, tree) {
8000
8073
  });
8001
8074
  if (!GIT_OBJECT_ID4.test(commit))
8002
8075
  throw new DeliveryWorkspaceError("delivery commit write failed");
8003
- git2(dest, ["init", "-q"]);
8004
- git2(dest, ["fetch", "--depth=1", `file://${resolve9(sourceRoot)}`, `${commit}:refs/heads/delivery`]);
8005
- git2(dest, ["checkout", "-q", "delivery"]);
8006
- const got = git2(dest, ["rev-parse", "HEAD^{tree}"]);
8076
+ git3(dest, ["init", "-q"]);
8077
+ git3(dest, ["fetch", "--depth=1", `file://${resolve9(sourceRoot)}`, `${commit}:refs/heads/delivery`]);
8078
+ git3(dest, ["checkout", "-q", "delivery"]);
8079
+ const got = git3(dest, ["rev-parse", "HEAD^{tree}"]);
8007
8080
  if (got !== tree)
8008
8081
  throw new DeliveryWorkspaceError("delivery materialization does not match the frozen tree");
8009
8082
  assertNoEscapingSymlinks(dest);
@@ -8372,14 +8445,14 @@ function deriveAuthorizationOperation(input) {
8372
8445
  }
8373
8446
 
8374
8447
  // plugins/immune-brain/runtime/staged_intent.ts
8375
- import { execFileSync as execFileSync5 } from "node:child_process";
8448
+ import { execFileSync as execFileSync6 } from "node:child_process";
8376
8449
  import { readFileSync as readFileSync11, writeFileSync as writeFileSync5 } from "node:fs";
8377
8450
  import { join as join10 } from "node:path";
8378
8451
  function captureStagedIntent(root, relativePath) {
8379
8452
  return {
8380
8453
  path: relativePath,
8381
8454
  bytes: readFileSync11(join10(root, relativePath)),
8382
- index_state: execFileSync5("git", ["ls-files", "--stage", "-z", "--", relativePath], {
8455
+ index_state: execFileSync6("git", ["ls-files", "--stage", "-z", "--", relativePath], {
8383
8456
  cwd: root,
8384
8457
  stdio: ["ignore", "pipe", "pipe"]
8385
8458
  })
@@ -8387,12 +8460,12 @@ function captureStagedIntent(root, relativePath) {
8387
8460
  }
8388
8461
  function restoreStagedIntent(root, snapshot) {
8389
8462
  writeFileSync5(join10(root, snapshot.path), snapshot.bytes);
8390
- execFileSync5("git", ["update-index", "--force-remove", "--", snapshot.path], {
8463
+ execFileSync6("git", ["update-index", "--force-remove", "--", snapshot.path], {
8391
8464
  cwd: root,
8392
8465
  stdio: ["ignore", "pipe", "pipe"]
8393
8466
  });
8394
8467
  if (snapshot.index_state.length > 0) {
8395
- execFileSync5("git", ["update-index", "-z", "--index-info"], {
8468
+ execFileSync6("git", ["update-index", "-z", "--index-info"], {
8396
8469
  cwd: root,
8397
8470
  input: snapshot.index_state,
8398
8471
  stdio: ["pipe", "ignore", "pipe"]
@@ -8402,7 +8475,7 @@ function restoreStagedIntent(root, snapshot) {
8402
8475
  if (!restoredBytes.equals(snapshot.bytes)) {
8403
8476
  throw new Error("failed to restore prior intent bytes");
8404
8477
  }
8405
- const restoredIndex = execFileSync5("git", ["ls-files", "--stage", "-z", "--", snapshot.path], {
8478
+ const restoredIndex = execFileSync6("git", ["ls-files", "--stage", "-z", "--", snapshot.path], {
8406
8479
  cwd: root,
8407
8480
  stdio: ["ignore", "pipe", "pipe"]
8408
8481
  });
@@ -9709,7 +9782,7 @@ async function revalidatePendingChildBeforeWrite(root, gh, childNumber, childTas
9709
9782
  import { existsSync as existsSync7, readdirSync as readdirSync6, readFileSync as readFileSync13 } from "node:fs";
9710
9783
  import { randomUUID as randomUUID7 } from "node:crypto";
9711
9784
  import { join as join12 } from "node:path";
9712
- import { spawnSync as spawnSync4 } from "node:child_process";
9785
+ import { spawnSync as spawnSync5 } from "node:child_process";
9713
9786
 
9714
9787
  // plugins/immune-brain/runtime/kernel/batch_authority.ts
9715
9788
  import { createHash as createHash18 } from "node:crypto";
@@ -10486,7 +10559,7 @@ function isOwnBatchClaim(root, existingBatch, taskId, batchBranch) {
10486
10559
  const currentTaskId = workspaceOwner || (claim?.lifecycle_status === "active" ? claim?.task_id : null);
10487
10560
  if (currentTaskId !== taskId || !claim)
10488
10561
  return false;
10489
- const branch = spawnSync4("git", ["-C", root, "branch", "--show-current"], { encoding: "utf8" }).stdout.trim();
10562
+ const branch = spawnSync5("git", ["-C", root, "branch", "--show-current"], { encoding: "utf8" }).stdout.trim();
10490
10563
  if (branch !== batchBranch)
10491
10564
  return false;
10492
10565
  const childInBatch = existingBatch.children.find((c) => c.task_id === taskId);
@@ -10543,7 +10616,7 @@ function authorizedScopeOf(root, taskId, state) {
10543
10616
  return scope;
10544
10617
  }
10545
10618
  function porcelainEntries(root) {
10546
- const statusProc = spawnSync4("git", ["-C", root, "status", "--porcelain=v1", "-z", "--no-renames", "--untracked-files=all"], { encoding: "utf8" });
10619
+ const statusProc = spawnSync5("git", ["-C", root, "status", "--porcelain=v1", "-z", "--no-renames", "--untracked-files=all"], { encoding: "utf8" });
10547
10620
  if (statusProc.status !== 0)
10548
10621
  return null;
10549
10622
  const entries = [];
@@ -10674,7 +10747,7 @@ async function projectBatchPreflight(options) {
10674
10747
  } catch (err) {
10675
10748
  return reject("git_head_unreadable", err instanceof Error ? err.message : String(err));
10676
10749
  }
10677
- const branchExists = spawnSync4("git", ["-C", root, "show-ref", "--verify", "--quiet", `refs/heads/${batchBranch}`]);
10750
+ const branchExists = spawnSync5("git", ["-C", root, "show-ref", "--verify", "--quiet", `refs/heads/${batchBranch}`]);
10678
10751
  if (branchExists.status === 0 && !existingBatch)
10679
10752
  return reject("branch_already_exists", batchBranch);
10680
10753
  const statusEntries = porcelainEntries(root);
@@ -10859,12 +10932,12 @@ async function authorizeBatch(options) {
10859
10932
  }
10860
10933
 
10861
10934
  // plugins/immune-brain/runtime/unattended/batch_runner.ts
10862
- import { spawnSync as spawnSync6 } from "node:child_process";
10935
+ import { spawnSync as spawnSync7 } from "node:child_process";
10863
10936
  import { existsSync as existsSync9 } from "node:fs";
10864
10937
  import { join as join14 } from "node:path";
10865
10938
 
10866
10939
  // plugins/immune-brain/runtime/unattended/batch_git.ts
10867
- import { spawnSync as spawnSync5 } from "node:child_process";
10940
+ import { spawnSync as spawnSync6 } from "node:child_process";
10868
10941
  import { createHash as createHash20, randomUUID as randomUUID8 } from "node:crypto";
10869
10942
  import {
10870
10943
  constants as constants6,
@@ -10889,7 +10962,7 @@ var DEFAULT_GIT_ENV = {
10889
10962
  function runBatchGitPreflight(input) {
10890
10963
  const { root, initiative_slug: initiativeSlug, base_head: baseHead } = input;
10891
10964
  const branch = `imm/${initiativeSlug}`;
10892
- const toplevelResult = spawnSync5("git", ["-C", root, "rev-parse", "--show-toplevel"], {
10965
+ const toplevelResult = spawnSync6("git", ["-C", root, "rev-parse", "--show-toplevel"], {
10893
10966
  encoding: "utf8",
10894
10967
  stdio: ["ignore", "pipe", "pipe"]
10895
10968
  });
@@ -10927,7 +11000,7 @@ function runBatchGitPreflight(input) {
10927
11000
  message: `unsupported index flags (assume-unchanged/skip-worktree) detected: ${flaggedPreflight.join(", ")}`
10928
11001
  };
10929
11002
  }
10930
- const statusResult = spawnSync5("git", ["-C", root, "status", "--porcelain", "--untracked-files=all", "--ignore-submodules=none"], {
11003
+ const statusResult = spawnSync6("git", ["-C", root, "status", "--porcelain", "--untracked-files=all", "--ignore-submodules=none"], {
10931
11004
  encoding: "utf8",
10932
11005
  stdio: ["ignore", "pipe", "pipe"]
10933
11006
  });
@@ -10945,7 +11018,7 @@ function runBatchGitPreflight(input) {
10945
11018
  message: "working tree is dirty before batch preflight"
10946
11019
  };
10947
11020
  }
10948
- const headResult = spawnSync5("git", ["-C", root, "rev-parse", "--verify", "HEAD^{commit}"], {
11021
+ const headResult = spawnSync6("git", ["-C", root, "rev-parse", "--verify", "HEAD^{commit}"], {
10949
11022
  encoding: "utf8",
10950
11023
  stdio: ["ignore", "pipe", "pipe"]
10951
11024
  });
@@ -10956,11 +11029,11 @@ function runBatchGitPreflight(input) {
10956
11029
  message: "HEAD is uncommitted or not a valid commit"
10957
11030
  };
10958
11031
  }
10959
- const branchCheck = spawnSync5("git", ["-C", root, "show-ref", "--verify", "--quiet", `refs/heads/${branch}`], { stdio: ["ignore", "ignore", "ignore"] });
11032
+ const branchCheck = spawnSync6("git", ["-C", root, "show-ref", "--verify", "--quiet", `refs/heads/${branch}`], { stdio: ["ignore", "ignore", "ignore"] });
10960
11033
  if (branchCheck.status === 0) {
10961
11034
  const settled = findSettledBatchRecord(root, initiativeSlug);
10962
- const currentBranch = spawnSync5("git", ["-C", root, "symbolic-ref", "--short", "HEAD"], { encoding: "utf8" });
10963
- if (findExistingActiveBatch(root, initiativeSlug) === null && settled?.branch === branch && currentBranch.status === 0 && currentBranch.stdout.trim() === branch && headResult.stdout.trim() === baseHead && spawnSync5("git", ["-C", root, "merge-base", "--is-ancestor", expectedBatchHead(settled), baseHead]).status === 0)
11035
+ const currentBranch = spawnSync6("git", ["-C", root, "symbolic-ref", "--short", "HEAD"], { encoding: "utf8" });
11036
+ if (findExistingActiveBatch(root, initiativeSlug) === null && settled?.branch === branch && currentBranch.status === 0 && currentBranch.stdout.trim() === branch && headResult.stdout.trim() === baseHead && spawnSync6("git", ["-C", root, "merge-base", "--is-ancestor", expectedBatchHead(settled), baseHead]).status === 0)
10964
11037
  return { ok: true, branch };
10965
11038
  return {
10966
11039
  ok: false,
@@ -10968,25 +11041,25 @@ function runBatchGitPreflight(input) {
10968
11041
  message: `branch refs/heads/${branch} already exists`
10969
11042
  };
10970
11043
  }
10971
- const originalBranchResult = spawnSync5("git", ["-C", root, "symbolic-ref", "--short", "HEAD"], {
11044
+ const originalBranchResult = spawnSync6("git", ["-C", root, "symbolic-ref", "--short", "HEAD"], {
10972
11045
  encoding: "utf8",
10973
11046
  stdio: ["ignore", "pipe", "pipe"]
10974
11047
  });
10975
11048
  const originalBranch = originalBranchResult.stdout.trim();
10976
- const checkoutResult = spawnSync5("git", ["-C", root, "-c", "core.hooksPath=/dev/null", "checkout", "-b", branch, baseHead], {
11049
+ const checkoutResult = spawnSync6("git", ["-C", root, "-c", "core.hooksPath=/dev/null", "checkout", "-b", branch, baseHead], {
10977
11050
  encoding: "utf8",
10978
11051
  stdio: ["ignore", "pipe", "pipe"],
10979
11052
  env: DEFAULT_GIT_ENV
10980
11053
  });
10981
11054
  if (checkoutResult.status !== 0) {
10982
11055
  const stderr = checkoutResult.stderr?.trim() || "";
10983
- const branchExists = stderr.includes("already exists") || spawnSync5("git", ["-C", root, "show-ref", "--verify", "--quiet", `refs/heads/${branch}`]).status === 0;
10984
- const currentBranchCheck = spawnSync5("git", ["-C", root, "symbolic-ref", "--short", "HEAD"], {
11056
+ const branchExists = stderr.includes("already exists") || spawnSync6("git", ["-C", root, "show-ref", "--verify", "--quiet", `refs/heads/${branch}`]).status === 0;
11057
+ const currentBranchCheck = spawnSync6("git", ["-C", root, "symbolic-ref", "--short", "HEAD"], {
10985
11058
  encoding: "utf8",
10986
11059
  stdio: ["ignore", "pipe", "pipe"]
10987
11060
  }).stdout.trim();
10988
11061
  if (currentBranchCheck === branch && originalBranch && originalBranch !== branch) {
10989
- spawnSync5("git", ["-C", root, "-c", "core.hooksPath=/dev/null", "checkout", originalBranch], {
11062
+ spawnSync6("git", ["-C", root, "-c", "core.hooksPath=/dev/null", "checkout", originalBranch], {
10990
11063
  stdio: ["ignore", "ignore", "ignore"]
10991
11064
  });
10992
11065
  }
@@ -11009,7 +11082,7 @@ function hasBoundaryWhitespace(path) {
11009
11082
  return path.split("/").some((segment) => segment.trim() !== segment || segment.length === 0);
11010
11083
  }
11011
11084
  function getUnsupportedIndexFlags(root) {
11012
- const result = spawnSync5("git", ["-C", root, "ls-files", "-v", "-z", "--"], {
11085
+ const result = spawnSync6("git", ["-C", root, "ls-files", "-v", "-z", "--"], {
11013
11086
  encoding: "utf8",
11014
11087
  stdio: ["ignore", "pipe", "pipe"]
11015
11088
  });
@@ -11043,13 +11116,13 @@ function isPathAllowedForChild(path, taskId, scopeHint) {
11043
11116
  });
11044
11117
  }
11045
11118
  function getChangedProjectPaths(root) {
11046
- const tracked = spawnSync5("git", ["-C", root, "diff-index", "--name-only", "-z", "--ignore-submodules=none", "HEAD", "--"], {
11119
+ const tracked = spawnSync6("git", ["-C", root, "diff-index", "--name-only", "-z", "--ignore-submodules=none", "HEAD", "--"], {
11047
11120
  encoding: "utf8",
11048
11121
  stdio: ["ignore", "pipe", "pipe"]
11049
11122
  });
11050
11123
  if (tracked.status !== 0)
11051
11124
  throw new Error("failed to inspect tracked diff vs HEAD");
11052
- const untracked = spawnSync5("git", ["-C", root, "ls-files", "--others", "--exclude-standard", "-z", "--"], {
11125
+ const untracked = spawnSync6("git", ["-C", root, "ls-files", "--others", "--exclude-standard", "-z", "--"], {
11053
11126
  encoding: "utf8",
11054
11127
  stdio: ["ignore", "pipe", "pipe"]
11055
11128
  });
@@ -11059,7 +11132,7 @@ function getChangedProjectPaths(root) {
11059
11132
  return [...new Set([...splitZ(tracked.stdout), ...splitZ(untracked.stdout)])];
11060
11133
  }
11061
11134
  function getStagedProjectPaths(root) {
11062
- const staged = spawnSync5("git", ["-C", root, "diff-index", "--cached", "--name-only", "-z", "--ignore-submodules=none", "HEAD", "--"], {
11135
+ const staged = spawnSync6("git", ["-C", root, "diff-index", "--cached", "--name-only", "-z", "--ignore-submodules=none", "HEAD", "--"], {
11063
11136
  encoding: "utf8",
11064
11137
  stdio: ["ignore", "pipe", "pipe"]
11065
11138
  });
@@ -11068,13 +11141,13 @@ function getStagedProjectPaths(root) {
11068
11141
  return staged.stdout.split("\x00").filter((p) => p.length > 0);
11069
11142
  }
11070
11143
  function getUnstagedProjectPaths(root) {
11071
- const diffFiles = spawnSync5("git", ["-C", root, "diff-files", "--name-only", "-z", "--ignore-submodules=none", "--"], {
11144
+ const diffFiles = spawnSync6("git", ["-C", root, "diff-files", "--name-only", "-z", "--ignore-submodules=none", "--"], {
11072
11145
  encoding: "utf8",
11073
11146
  stdio: ["ignore", "pipe", "pipe"]
11074
11147
  });
11075
11148
  if (diffFiles.status !== 0)
11076
11149
  throw new Error("failed to inspect unstaged tracked changes");
11077
- const untracked = spawnSync5("git", ["-C", root, "ls-files", "--others", "--exclude-standard", "-z", "--"], {
11150
+ const untracked = spawnSync6("git", ["-C", root, "ls-files", "--others", "--exclude-standard", "-z", "--"], {
11078
11151
  encoding: "utf8",
11079
11152
  stdio: ["ignore", "pipe", "pipe"]
11080
11153
  });
@@ -11084,7 +11157,7 @@ function getUnstagedProjectPaths(root) {
11084
11157
  return [...new Set([...splitZ(diffFiles.stdout), ...splitZ(untracked.stdout)])];
11085
11158
  }
11086
11159
  function getCommittedDeltaPaths(root) {
11087
- const delta = spawnSync5("git", ["-C", root, "diff-tree", "--no-commit-id", "--name-only", "-z", "-r", "HEAD~1", "HEAD"], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
11160
+ const delta = spawnSync6("git", ["-C", root, "diff-tree", "--no-commit-id", "--name-only", "-z", "-r", "HEAD~1", "HEAD"], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
11088
11161
  if (delta.status !== 0)
11089
11162
  throw new Error("failed to inspect committed tree delta");
11090
11163
  return delta.stdout.split("\x00").filter((p) => p.length > 0);
@@ -11190,7 +11263,7 @@ async function commitBatchChild(input) {
11190
11263
  const goal = typeof intentSnapshot.goal === "string" ? intentSnapshot.goal : "";
11191
11264
  const scopeHint = Array.isArray(intentSnapshot.scope_hint) ? intentSnapshot.scope_hint.filter((s) => typeof s === "string") : [];
11192
11265
  if (expectedBranch !== undefined) {
11193
- const currentBranchResult = spawnSync5("git", ["-C", root, "symbolic-ref", "--short", "HEAD"], {
11266
+ const currentBranchResult = spawnSync6("git", ["-C", root, "symbolic-ref", "--short", "HEAD"], {
11194
11267
  encoding: "utf8",
11195
11268
  stdio: ["ignore", "pipe", "pipe"]
11196
11269
  });
@@ -11199,7 +11272,7 @@ async function commitBatchChild(input) {
11199
11272
  throw new Error(`batch_head_lineage_broken: current branch ${currentBranch} does not match expected branch ${expectedBranch}`);
11200
11273
  }
11201
11274
  }
11202
- const currentHeadResult = spawnSync5("git", ["-C", root, "rev-parse", "HEAD"], {
11275
+ const currentHeadResult = spawnSync6("git", ["-C", root, "rev-parse", "HEAD"], {
11203
11276
  encoding: "utf8",
11204
11277
  stdio: ["ignore", "pipe", "pipe"]
11205
11278
  });
@@ -11218,7 +11291,7 @@ async function commitBatchChild(input) {
11218
11291
  }
11219
11292
  const pathsToStage = getUnstagedProjectPaths(root);
11220
11293
  if (pathsToStage.length > 0) {
11221
- const addResult = spawnSync5("git", ["-C", root, "--literal-pathspecs", "add", "-A", "--", ...pathsToStage], {
11294
+ const addResult = spawnSync6("git", ["-C", root, "--literal-pathspecs", "add", "-A", "--", ...pathsToStage], {
11222
11295
  encoding: "utf8",
11223
11296
  stdio: ["ignore", "pipe", "pipe"]
11224
11297
  });
@@ -11233,7 +11306,7 @@ async function commitBatchChild(input) {
11233
11306
  const staged = getStagedProjectPaths(root);
11234
11307
  const stagedOutside = staged.filter((p) => !isPathAllowedForChild(p, taskId, scopeHint));
11235
11308
  if (stagedOutside.length > 0) {
11236
- spawnSync5("git", ["-C", root, "reset", "--quiet"], { stdio: ["ignore", "ignore", "ignore"] });
11309
+ spawnSync6("git", ["-C", root, "reset", "--quiet"], { stdio: ["ignore", "ignore", "ignore"] });
11237
11310
  throw new Error("dirty_outside_scope");
11238
11311
  }
11239
11312
  const record = auditPair.record;
@@ -11251,7 +11324,7 @@ async function commitBatchChild(input) {
11251
11324
 
11252
11325
  Immune-Brain-Batch: ${batchId}
11253
11326
  `;
11254
- const commitResult = spawnSync5("git", ["-C", root, "-c", "core.hooksPath=/dev/null", "commit", "--no-verify", "-F", "-"], {
11327
+ const commitResult = spawnSync6("git", ["-C", root, "-c", "core.hooksPath=/dev/null", "commit", "--no-verify", "-F", "-"], {
11255
11328
  input: commitMessage,
11256
11329
  encoding: "utf8",
11257
11330
  stdio: ["pipe", "pipe", "pipe"],
@@ -11260,7 +11333,7 @@ Immune-Brain-Batch: ${batchId}
11260
11333
  if (commitResult.status !== 0) {
11261
11334
  throw new Error(`commit failed for child ${taskId}: ${commitResult.stderr?.trim() || "git commit failed"}`);
11262
11335
  }
11263
- const newHeadResult = spawnSync5("git", ["-C", root, "rev-parse", "HEAD"], {
11336
+ const newHeadResult = spawnSync6("git", ["-C", root, "rev-parse", "HEAD"], {
11264
11337
  encoding: "utf8",
11265
11338
  stdio: ["ignore", "pipe", "pipe"]
11266
11339
  });
@@ -11268,7 +11341,7 @@ Immune-Brain-Batch: ${batchId}
11268
11341
  if (newHeadResult.status !== 0 || !newHead || newHead === expectedHead) {
11269
11342
  throw new Error("commit_failed");
11270
11343
  }
11271
- const parentsResult = spawnSync5("git", ["-C", root, "rev-parse", "HEAD^@"], {
11344
+ const parentsResult = spawnSync6("git", ["-C", root, "rev-parse", "HEAD^@"], {
11272
11345
  encoding: "utf8",
11273
11346
  stdio: ["ignore", "pipe", "pipe"]
11274
11347
  });
@@ -11301,7 +11374,7 @@ async function lookupBatchCommit(input) {
11301
11374
  let candidates = [];
11302
11375
  let evidenceBacked = false;
11303
11376
  if (evidence && evidence.commit) {
11304
- const direct = spawnSync5("git", ["-C", root, "log", "-n", "1", `--format=${FORMAT}`, evidence.commit, "--"], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
11377
+ const direct = spawnSync6("git", ["-C", root, "log", "-n", "1", `--format=${FORMAT}`, evidence.commit, "--"], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
11305
11378
  if (direct.status !== 0) {
11306
11379
  throw new Error(`failed to inspect batch commit for ${taskId}: ${direct.stderr?.trim() || "git log failed"}`);
11307
11380
  }
@@ -11314,7 +11387,7 @@ async function lookupBatchCommit(input) {
11314
11387
  }
11315
11388
  }
11316
11389
  if (!candidates.length) {
11317
- const result = spawnSync5("git", [
11390
+ const result = spawnSync6("git", [
11318
11391
  "-C",
11319
11392
  root,
11320
11393
  "log",
@@ -11351,7 +11424,7 @@ async function lookupBatchCommit(input) {
11351
11424
  throw new Error(`batch_head_lineage_broken: adopted commit author ${match.authorName} does not match batch authority ${DEFAULT_GIT_ENV.GIT_AUTHOR_NAME}`);
11352
11425
  }
11353
11426
  if (expectedBranch !== undefined) {
11354
- const currentBranchResult = spawnSync5("git", ["-C", root, "symbolic-ref", "--short", "HEAD"], {
11427
+ const currentBranchResult = spawnSync6("git", ["-C", root, "symbolic-ref", "--short", "HEAD"], {
11355
11428
  encoding: "utf8",
11356
11429
  stdio: ["ignore", "pipe", "pipe"]
11357
11430
  });
@@ -11361,7 +11434,7 @@ async function lookupBatchCommit(input) {
11361
11434
  }
11362
11435
  }
11363
11436
  if (expectedHead !== undefined) {
11364
- const currentHeadResult = spawnSync5("git", ["-C", root, "rev-parse", "HEAD"], {
11437
+ const currentHeadResult = spawnSync6("git", ["-C", root, "rev-parse", "HEAD"], {
11365
11438
  encoding: "utf8",
11366
11439
  stdio: ["ignore", "pipe", "pipe"]
11367
11440
  });
@@ -11369,7 +11442,7 @@ async function lookupBatchCommit(input) {
11369
11442
  if (currentHead !== commit) {
11370
11443
  throw new Error(`batch_head_lineage_broken: current HEAD ${currentHead} diverged from adopted commit ${commit}`);
11371
11444
  }
11372
- const parentsResult = spawnSync5("git", ["-C", root, "rev-parse", `${commit}^@`], {
11445
+ const parentsResult = spawnSync6("git", ["-C", root, "rev-parse", `${commit}^@`], {
11373
11446
  encoding: "utf8",
11374
11447
  stdio: ["ignore", "pipe", "pipe"]
11375
11448
  });
@@ -11387,7 +11460,7 @@ async function lookupBatchCommit(input) {
11387
11460
  throw new Error(`batch_head_lineage_broken: adopted commit task lifecycle is not done: ${lifecycle}`);
11388
11461
  }
11389
11462
  const scopeHint = Array.isArray(auditPair.record.intent_snapshot.scope_hint) ? auditPair.record.intent_snapshot.scope_hint.filter((s) => typeof s === "string") : [];
11390
- const deltaResult = spawnSync5("git", ["-C", root, "diff-tree", "--no-commit-id", "--name-only", "-z", "-r", expectedHead, commit], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
11463
+ const deltaResult = spawnSync6("git", ["-C", root, "diff-tree", "--no-commit-id", "--name-only", "-z", "-r", expectedHead, commit], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
11391
11464
  if (deltaResult.status !== 0) {
11392
11465
  throw new Error("batch_head_lineage_broken: failed to inspect adopted commit delta");
11393
11466
  }
@@ -11484,14 +11557,14 @@ function externalHeadDriftMessage(root, record) {
11484
11557
  if (!existsSync9(join14(root, ".git")))
11485
11558
  return null;
11486
11559
  const head = record.commits.length ? record.commits[record.commits.length - 1] : record.base_head;
11487
- const headCheck = spawnSync6("git", ["-C", root, "rev-parse", "HEAD"], {
11560
+ const headCheck = spawnSync7("git", ["-C", root, "rev-parse", "HEAD"], {
11488
11561
  encoding: "utf8",
11489
11562
  stdio: ["ignore", "pipe", "pipe"]
11490
11563
  });
11491
11564
  if (headCheck.status === 0 && headCheck.stdout.trim() && headCheck.stdout.trim() !== head) {
11492
11565
  return `batch_head_lineage_broken: current HEAD ${headCheck.stdout.trim()} does not match expected batch head ${head}`;
11493
11566
  }
11494
- const branchCheck = spawnSync6("git", ["-C", root, "symbolic-ref", "--short", "HEAD"], {
11567
+ const branchCheck = spawnSync7("git", ["-C", root, "symbolic-ref", "--short", "HEAD"], {
11495
11568
  encoding: "utf8",
11496
11569
  stdio: ["ignore", "pipe", "pipe"]
11497
11570
  });
@@ -11523,7 +11596,7 @@ async function validatePersistedRun(input, record) {
11523
11596
  });
11524
11597
  if (!evidence || evidence.commit !== child.commit) {
11525
11598
  if (evidence === null && typeof child.commit === "string" && child.commit.length > 0 && existsSync9(join14(input.root, ".git"))) {
11526
- const reach = spawnSync6("git", ["-C", input.root, "merge-base", "--is-ancestor", child.commit, "HEAD"], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
11599
+ const reach = spawnSync7("git", ["-C", input.root, "merge-base", "--is-ancestor", child.commit, "HEAD"], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
11527
11600
  if (reach.status !== 0) {
11528
11601
  throw new Error(`batch_head_lineage_broken: recorded commit ${child.commit} for ${child.task_id} is no longer reachable from HEAD`);
11529
11602
  }
@@ -12275,10 +12348,10 @@ function stagePlanningArtifactTransition(root, record) {
12275
12348
  intentArchive,
12276
12349
  ...specActive ? [specActive, specActive.replace("docs/specs/", "docs/specs/archive/")] : []
12277
12350
  ];
12278
- const paths = candidates.filter((path) => existsSync10(join15(root, path)) || execFileSync6("git", ["ls-files", "--cached", "--", path], { cwd: root, encoding: "utf8" }).trim().length > 0);
12351
+ const paths = candidates.filter((path) => existsSync10(join15(root, path)) || execFileSync7("git", ["ls-files", "--cached", "--", path], { cwd: root, encoding: "utf8" }).trim().length > 0);
12279
12352
  if (paths.length === 0)
12280
12353
  return;
12281
- execFileSync6("git", ["add", "--", ...paths], { cwd: root, stdio: ["ignore", "pipe", "pipe"] });
12354
+ execFileSync7("git", ["add", "--", ...paths], { cwd: root, stdio: ["ignore", "pipe", "pipe"] });
12282
12355
  }
12283
12356
  async function mintCapability(registry, input) {
12284
12357
  const action = capabilityActionFor({
@@ -12412,13 +12485,15 @@ class ClaudeRuntime {
12412
12485
  }
12413
12486
  async enroll(taskId, meta) {
12414
12487
  const now = new Date().toISOString();
12415
- const preparation = await preparePiCanary(this.cwd, { task_id: taskId, now });
12488
+ let preparation = await preparePiCanary(this.cwd, { task_id: taskId, now });
12416
12489
  const intent = await readTaskIntentForRecord(this.cwd, taskId);
12490
+ const gitBase = inspectEnrollmentGitBase(this.cwd);
12417
12491
  const gate = await this.gate("enroll", { ...meta, taskId }, {
12418
12492
  risk: intent.intent.risk,
12419
12493
  intentRevision: preparation.intent?.revision,
12420
12494
  intentContentHash: preparation.intent?.content_hash,
12421
- bindingDigest: preparation.digest
12495
+ bindingDigest: preparation.digest,
12496
+ gitBaseNotice: enrollmentGitBaseNotice(gitBase)
12422
12497
  });
12423
12498
  const { unchanged } = await revalidatePiCanary(this.cwd, { task_id: taskId, now }, preparation);
12424
12499
  if (!unchanged)
@@ -12426,33 +12501,43 @@ class ClaudeRuntime {
12426
12501
  if (!preparation.intent)
12427
12502
  throw new Error("enrollment requires a readable TaskIntent");
12428
12503
  throwIfCancelled(meta.signal);
12429
- const nonce = enrollmentNonce();
12430
- const binding = {
12431
- task_id: taskId,
12432
- intent_path: preparation.intent.path,
12433
- intent_revision: preparation.intent.revision,
12434
- intent_content_hash: preparation.intent.content_hash,
12435
- preparation_digest: preparation.digest,
12436
- actor_id: LITERAL_USER_ACTOR_ID,
12437
- confirmation_ref: gate.confirmation_ref,
12438
- expires_at: new Date(Date.now() + 10 * 60 * 1000).toISOString(),
12439
- nonce
12440
- };
12441
- const capability = this.enrollmentRegistry.issue(binding);
12442
- const input = {
12443
- task_id: taskId,
12444
- intent_path: binding.intent_path,
12445
- intent_revision: binding.intent_revision,
12446
- preparation_digest: binding.preparation_digest,
12447
- capability,
12448
- capability_binding: binding,
12449
- now
12450
- };
12451
- const rehearsal = runEnrollmentRehearsal(this.cwd, input, capability, this.enrollmentRegistry);
12452
- if (!rehearsal.rehearsed || rehearsal.evidence.outcome !== "ready") {
12453
- throw new Error(`Kernel enrollment rehearsal failed: ${rehearsal.evidence.blockers.join("; ")}`);
12504
+ preparation = initializeEnrollmentGitBase(this.cwd, { task_id: taskId, now }, preparation, gitBase, meta.signal);
12505
+ const gitBaseNote = gitBase.state === "unborn" ? `; empty initial commit ${preparation.git_base_head} remains` : "";
12506
+ try {
12507
+ if (!preparation.intent)
12508
+ throw new Error("Enrollment requires a readable TaskIntent");
12509
+ const nonce = enrollmentNonce();
12510
+ const binding = {
12511
+ task_id: taskId,
12512
+ intent_path: preparation.intent.path,
12513
+ intent_revision: preparation.intent.revision,
12514
+ intent_content_hash: preparation.intent.content_hash,
12515
+ preparation_digest: preparation.digest,
12516
+ actor_id: LITERAL_USER_ACTOR_ID,
12517
+ confirmation_ref: gate.confirmation_ref,
12518
+ expires_at: new Date(Date.now() + 10 * 60 * 1000).toISOString(),
12519
+ nonce
12520
+ };
12521
+ const capability = this.enrollmentRegistry.issue(binding);
12522
+ const input = {
12523
+ task_id: taskId,
12524
+ intent_path: binding.intent_path,
12525
+ intent_revision: binding.intent_revision,
12526
+ preparation_digest: binding.preparation_digest,
12527
+ capability,
12528
+ capability_binding: binding,
12529
+ now
12530
+ };
12531
+ const rehearsal = runEnrollmentRehearsal(this.cwd, input, capability, this.enrollmentRegistry);
12532
+ if (!rehearsal.rehearsed || rehearsal.evidence.outcome !== "ready") {
12533
+ throw new Error(`Kernel enrollment rehearsal failed: ${rehearsal.evidence.blockers.join("; ")}`);
12534
+ }
12535
+ return enrollCanaryTask(this.cwd, input, this.enrollmentRegistry);
12536
+ } catch (error) {
12537
+ if (gitBaseNote)
12538
+ throw new Error(`${error instanceof Error ? error.message : String(error)}${gitBaseNote}`);
12539
+ throw error;
12454
12540
  }
12455
- return enrollCanaryTask(this.cwd, input, this.enrollmentRegistry);
12456
12541
  }
12457
12542
  async advance(taskId, signal) {
12458
12543
  return this.withTerminalTracker(taskId, await this.coordinator.advance(taskId, { cwd: this.cwd }, signal));
@@ -12479,6 +12564,12 @@ class ClaudeRuntime {
12479
12564
  return { ...result, tracker: TRACKER_PROJECTION_FAILURE };
12480
12565
  }
12481
12566
  }
12567
+ async reviseIntent(taskId, nextIntent) {
12568
+ return this.executeOrdinary({ cwd: this.cwd }, {
12569
+ taskId,
12570
+ operation: { op: "revise_intent", next_intent: nextIntent, actor_id: "executor" }
12571
+ });
12572
+ }
12482
12573
  async resolveFinding(taskId, findingId) {
12483
12574
  return this.executeOrdinary({ cwd: this.cwd }, {
12484
12575
  taskId,
@@ -12549,7 +12640,7 @@ class ClaudeRuntime {
12549
12640
  if (sidecar && nextIntent) {
12550
12641
  writeFileSync8(sidecar, `${JSON.stringify(nextIntent, null, 2)}
12551
12642
  `);
12552
- execFileSync6("git", ["add", "--", priorIntent.intent_ref.path], { cwd: this.cwd, stdio: ["ignore", "pipe", "pipe"] });
12643
+ execFileSync7("git", ["add", "--", priorIntent.intent_ref.path], { cwd: this.cwd, stdio: ["ignore", "pipe", "pipe"] });
12553
12644
  const preparedRecord = await readTaskRecord(this.cwd, taskId);
12554
12645
  if (!preparedRecord.record) {
12555
12646
  throw new NativeAuthorityError("workspace_changed", "TaskRecord changed before the breaking revision digest");
@@ -12729,7 +12820,7 @@ class ClaudeRuntime {
12729
12820
  if (priorBytes) {
12730
12821
  writeFileSync8(sidecar, `${JSON.stringify(operation.next_intent, null, 2)}
12731
12822
  `);
12732
- execFileSync6("git", ["add", "--", priorIntent.intent_ref.path], {
12823
+ execFileSync7("git", ["add", "--", priorIntent.intent_ref.path], {
12733
12824
  cwd: ctx.cwd,
12734
12825
  stdio: ["ignore", "pipe", "pipe"]
12735
12826
  });
@@ -12987,6 +13078,7 @@ var TOOLS = [
12987
13078
  { name: "advance_assurance", description: "Advance frozen Assurance through deterministic QA and Review reservation.", privileged: false },
12988
13079
  { name: "submit_review", description: "Submit the Parent-mediated Review verdict bound to the correlated receipt.", privileged: false },
12989
13080
  { name: "request_authorization", description: "Apply exact literal-user authorization.", privileged: true },
13081
+ { name: "revise_intent", description: "Apply a compatible TaskIntent revision.", privileged: false },
12990
13082
  { name: "approve_breaking_intent_revision", description: "Approve a breaking TaskIntent revision.", privileged: true },
12991
13083
  { name: "stop", description: "Stop the active task with literal-user authority.", privileged: true },
12992
13084
  { name: "start_unattended_batch", description: "Start an unattended serial batch run for an Initiative after native confirmation.", privileged: true },
@@ -13003,14 +13095,14 @@ function listMcpTools() {
13003
13095
  properties: {
13004
13096
  ...tool.name === "start_unattended_batch" ? { initiative_slug: { type: "string" } } : {
13005
13097
  task_id: { type: "string" },
13006
- ...tool.name === "approve_breaking_intent_revision" ? { next_intent: { type: "object" } } : {},
13098
+ ...tool.name === "approve_breaking_intent_revision" || tool.name === "revise_intent" ? { next_intent: { type: "object" } } : {},
13007
13099
  ...tool.name === "stop" ? { reason: { type: "string" } } : {},
13008
13100
  ...tool.name === "submit_review" ? { verdict: { type: "object" } } : {},
13009
13101
  ...tool.name === "resolve_finding" ? { finding_id: { type: "string" } } : {},
13010
13102
  ...tool.name === "refute_finding" ? { finding_id: { type: "string" }, attestation_id: { type: "string" } } : {}
13011
13103
  }
13012
13104
  },
13013
- required: tool.name === "start_unattended_batch" ? ["initiative_slug"] : tool.name === "submit_review" ? ["task_id", "verdict"] : tool.name === "resolve_finding" ? ["task_id", "finding_id"] : tool.name === "refute_finding" ? ["task_id", "finding_id", "attestation_id"] : ["task_id"]
13105
+ required: tool.name === "start_unattended_batch" ? ["initiative_slug"] : tool.name === "submit_review" ? ["task_id", "verdict"] : tool.name === "resolve_finding" ? ["task_id", "finding_id"] : tool.name === "refute_finding" ? ["task_id", "finding_id", "attestation_id"] : tool.name === "revise_intent" ? ["task_id", "next_intent"] : ["task_id"]
13014
13106
  },
13015
13107
  annotations: tool.privileged ? privilegedAnnotations() : { readOnlyHint: tool.name === "status" }
13016
13108
  }));
@@ -13104,6 +13196,11 @@ function createMcpRuntime(options = {}) {
13104
13196
  throw new Error("verdict is required");
13105
13197
  return runtime.submitReview(taskId, args.verdict);
13106
13198
  }
13199
+ if (name === "revise_intent") {
13200
+ if (!Object.hasOwn(args, "next_intent"))
13201
+ throw new Error("next_intent is required");
13202
+ return runtime.reviseIntent(taskId, args.next_intent);
13203
+ }
13107
13204
  if (name === "resolve_finding") {
13108
13205
  if (typeof args.finding_id !== "string" || !args.finding_id)
13109
13206
  throw new Error("finding_id is required");
@@ -13311,7 +13408,8 @@ ${details.join(`
13311
13408
  input.risk ? `Risk: ${input.risk}` : null,
13312
13409
  input.intentRevision !== undefined ? `Intent revision: ${input.intentRevision}` : null,
13313
13410
  input.intentContentHash ? `Intent hash: ${input.intentContentHash}` : null,
13314
- input.bindingDigest ? `Binding digest: ${input.bindingDigest}` : null
13411
+ input.bindingDigest ? `Binding digest: ${input.bindingDigest}` : null,
13412
+ input.gitBaseNotice
13315
13413
  ].filter(Boolean);
13316
13414
  return {
13317
13415
  mode: "form",