pi-fabric 0.76.2 → 0.77.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.
@@ -9,7 +9,7 @@ import {
9
9
  agentParticipantRecords,
10
10
  lifecycleSourceIdentity,
11
11
  useBudgetLedger
12
- } from "./chunk-F2GKEXGI.js";
12
+ } from "./chunk-4DRVOAFY.js";
13
13
  import {
14
14
  parseFabricOwnedModelGuidance,
15
15
  resolveFabricModelGuidance
@@ -662,4 +662,4 @@ if (isMain) {
662
662
  export {
663
663
  runResidentHostFromConfigPath
664
664
  };
665
- //# sourceMappingURL=chunk-BT6UELLP.js.map
665
+ //# sourceMappingURL=chunk-SBHF6CVR.js.map
@@ -69,15 +69,17 @@ import {
69
69
  ParticipantDirectory,
70
70
  actorDeliveryNotice,
71
71
  actorParticipantRecord,
72
+ addCloneFirstWorktree,
72
73
  agentParticipantRecords,
73
74
  effectiveAgentTimeoutMs,
74
75
  isFabricLifecycleEventType,
76
+ isFabricWorktreePath,
75
77
  lifecycleSourceIdentity,
76
78
  resolveActorDeliveryPolicy,
77
79
  resolveAgentCwd,
78
80
  resolvePiBinary,
79
81
  validateAgentCwdRequest
80
- } from "./chunk-F2GKEXGI.js";
82
+ } from "./chunk-4DRVOAFY.js";
81
83
  import "./chunk-PM5I335G.js";
82
84
  import "./chunk-VPPIJRNZ.js";
83
85
  import {
@@ -149,7 +151,7 @@ import {
149
151
  } from "./chunk-IDTQ2B5W.js";
150
152
 
151
153
  // src/fabric-runtime-state.ts
152
- import path14 from "node:path";
154
+ import path15 from "node:path";
153
155
  import { fileURLToPath as fileURLToPath2 } from "node:url";
154
156
 
155
157
  // src/actors/global-registry.ts
@@ -2196,10 +2198,10 @@ var FabricComponentSupervisor = class {
2196
2198
  adjacent.set(edge.from, targets);
2197
2199
  }
2198
2200
  const cycles = /* @__PURE__ */ new Map();
2199
- const visit = (node, path15, positions) => {
2201
+ const visit = (node, path16, positions) => {
2200
2202
  const position = positions.get(node);
2201
2203
  if (position !== void 0) {
2202
- const cycle = path15.slice(position);
2204
+ const cycle = path16.slice(position);
2203
2205
  const rotations = cycle.map((_, index) => [
2204
2206
  ...cycle.slice(index),
2205
2207
  ...cycle.slice(0, index)
@@ -2209,10 +2211,10 @@ var FabricComponentSupervisor = class {
2209
2211
  cycles.set(canonical.join("\0"), canonical);
2210
2212
  return;
2211
2213
  }
2212
- if (path15.length > this.#components.size) return;
2213
- const nextPositions = new Map(positions).set(node, path15.length);
2214
+ if (path16.length > this.#components.size) return;
2215
+ const nextPositions = new Map(positions).set(node, path16.length);
2214
2216
  for (const target of adjacent.get(node) ?? []) {
2215
- visit(target, [...path15, node], nextPositions);
2217
+ visit(target, [...path16, node], nextPositions);
2216
2218
  }
2217
2219
  };
2218
2220
  for (const id of this.#components.keys()) visit(id, [], /* @__PURE__ */ new Map());
@@ -4469,7 +4471,6 @@ var AGENTS_ACTION_DESCRIPTORS = [
4469
4471
  // src/residency/client.ts
4470
4472
  import { randomUUID as randomUUID2 } from "node:crypto";
4471
4473
  import fs3 from "node:fs";
4472
- import os from "node:os";
4473
4474
  import path4 from "node:path";
4474
4475
  import { fileURLToPath } from "node:url";
4475
4476
  var STARTUP_TIMEOUT_MS = 3e4;
@@ -4794,7 +4795,7 @@ var ResidencyClient = class {
4794
4795
  if (metadata?.format !== RESIDENT_HOST_FORMAT || metadata.rootId !== this.options.config.rootId || metadata.id !== id || metadata.handle.id !== id || metadata.worktreeGitRoot !== void 0 && typeof metadata.worktreeGitRoot !== "string" || path4.resolve(metadata.runDirectory) !== path4.resolve(this.options.config.residencyRoot, "runs", id)) {
4795
4796
  return void 0;
4796
4797
  }
4797
- if (metadata.handle.worktree && path4.resolve(metadata.handle.worktree) !== path4.resolve(os.tmpdir(), "pi-fabric-worktrees", id)) {
4798
+ if (metadata.handle.worktree && !isFabricWorktreePath(metadata.handle.worktree, id)) {
4798
4799
  return void 0;
4799
4800
  }
4800
4801
  if (metadata.handle.branch && (!metadata.handle.branch.startsWith("pi-fabric/") || !metadata.handle.branch.endsWith(`-${id.slice(0, 8)}`))) {
@@ -6486,19 +6487,19 @@ var ComponentsProvider = class {
6486
6487
  // src/providers/mcp-descriptor-cache.ts
6487
6488
  import fs4 from "node:fs/promises";
6488
6489
  import fsSync from "node:fs";
6489
- import os2 from "node:os";
6490
+ import os from "node:os";
6490
6491
  import path6 from "node:path";
6491
6492
  var MCP_DESCRIPTOR_CACHE_VERSION = 1;
6492
6493
  var expandHome = (input) => {
6493
6494
  if (!input.startsWith("~")) return input;
6494
- const home = os2.homedir();
6495
+ const home = os.homedir();
6495
6496
  if (input === "~") return home;
6496
6497
  if (input.startsWith("~/") || input.startsWith("~\\")) {
6497
6498
  return path6.join(home, input.slice(2));
6498
6499
  }
6499
6500
  return input;
6500
6501
  };
6501
- var legacyMcporterDir = () => path6.join(os2.homedir(), ".mcporter");
6502
+ var legacyMcporterDir = () => path6.join(os.homedir(), ".mcporter");
6502
6503
  var mcporterConfigDir = () => {
6503
6504
  const raw = process.env.XDG_CONFIG_HOME;
6504
6505
  if (raw && raw.trim().length > 0) {
@@ -7615,7 +7616,7 @@ var MeshProvider = class {
7615
7616
 
7616
7617
  // src/providers/pi-tools-provider.ts
7617
7618
  import { readFileSync as readFileSync2 } from "node:fs";
7618
- import path9 from "node:path";
7619
+ import path10 from "node:path";
7619
7620
  import {
7620
7621
  createBashToolDefinition as createBashToolDefinition2,
7621
7622
  createEditToolDefinition,
@@ -7625,9 +7626,102 @@ import {
7625
7626
  createReadToolDefinition
7626
7627
  } from "@earendil-works/pi-coding-agent";
7627
7628
 
7629
+ // src/agents/bash-worktree-add.ts
7630
+ import fs5 from "node:fs";
7631
+ import path8 from "node:path";
7632
+ var BARE_SAFE = /^[A-Za-z0-9_./:@%+=,-]+$/;
7633
+ var parseGitWorktreeAdd = (command) => {
7634
+ const trimmed = command.trim();
7635
+ if (!trimmed || /[|&;()\n]/.test(trimmed)) return void 0;
7636
+ const tokens = trimmed.split(/\s+/);
7637
+ if (tokens[0] !== "git") return void 0;
7638
+ if (tokens.some((token) => !BARE_SAFE.test(token))) return void 0;
7639
+ let index = 1;
7640
+ let gitCwd;
7641
+ if (tokens[index] === "-C") {
7642
+ gitCwd = tokens[index + 1];
7643
+ if (!gitCwd) return void 0;
7644
+ index += 2;
7645
+ }
7646
+ if (tokens[index] !== "worktree" || tokens[index + 1] !== "add") return void 0;
7647
+ index += 2;
7648
+ let branch;
7649
+ let detach = false;
7650
+ let quiet = false;
7651
+ let flagsEnded = false;
7652
+ const positionals = [];
7653
+ while (index < tokens.length) {
7654
+ const token = tokens[index++];
7655
+ if (token === void 0) break;
7656
+ if (!flagsEnded && token === "--") {
7657
+ flagsEnded = true;
7658
+ continue;
7659
+ }
7660
+ if (!flagsEnded && (token === "-b" || token === "-B")) {
7661
+ if (branch) return void 0;
7662
+ const name = tokens[index++];
7663
+ if (!name) return void 0;
7664
+ branch = { flag: token, name };
7665
+ continue;
7666
+ }
7667
+ if (!flagsEnded && (token === "--detach" || token === "-d")) {
7668
+ detach = true;
7669
+ continue;
7670
+ }
7671
+ if (!flagsEnded && (token === "-q" || token === "--quiet")) {
7672
+ quiet = true;
7673
+ continue;
7674
+ }
7675
+ if (!flagsEnded && token.startsWith("-")) return void 0;
7676
+ positionals.push(token);
7677
+ }
7678
+ if (detach && branch) return void 0;
7679
+ if (positionals.length < 1 || positionals.length > 2) return void 0;
7680
+ return {
7681
+ ...gitCwd ? { gitCwd } : {},
7682
+ ...branch ? { branch } : {},
7683
+ detach,
7684
+ quiet,
7685
+ dest: positionals[0],
7686
+ ...positionals[1] ? { startPoint: positionals[1] } : {}
7687
+ };
7688
+ };
7689
+ var tryExecuteGitWorktreeAdd = async (args, sessionCwd) => {
7690
+ const command = args.command;
7691
+ if (typeof command !== "string") return void 0;
7692
+ const parsed = parseGitWorktreeAdd(command);
7693
+ if (!parsed) return void 0;
7694
+ const gitCwd = parsed.gitCwd ? path8.resolve(sessionCwd, parsed.gitCwd) : typeof args.cwd === "string" ? args.cwd : sessionCwd;
7695
+ const dest = path8.resolve(gitCwd, parsed.dest);
7696
+ let gitRoot;
7697
+ try {
7698
+ const root = await executeFile("git", ["rev-parse", "--show-toplevel"], {
7699
+ cwd: gitCwd,
7700
+ timeoutMs: 1e4
7701
+ });
7702
+ const output = root.stdout.trim();
7703
+ if (!output) return void 0;
7704
+ gitRoot = fs5.realpathSync(output);
7705
+ } catch {
7706
+ return void 0;
7707
+ }
7708
+ const result = await addCloneFirstWorktree({
7709
+ gitRoot,
7710
+ dest,
7711
+ ...parsed.branch ? { branch: parsed.branch } : {},
7712
+ detach: parsed.detach,
7713
+ quiet: parsed.quiet,
7714
+ ...parsed.startPoint ? { startPoint: parsed.startPoint } : {}
7715
+ });
7716
+ return {
7717
+ content: [{ type: "text", text: result.message || `Preparing worktree (${dest})` }],
7718
+ details: { exitCode: 0, cloned: result.cloned }
7719
+ };
7720
+ };
7721
+
7628
7722
  // src/providers/pi-bash-cwd.ts
7629
7723
  import { accessSync, constants, statSync } from "node:fs";
7630
- import path8 from "node:path";
7724
+ import path9 from "node:path";
7631
7725
  import { createBashToolDefinition } from "@earendil-works/pi-coding-agent";
7632
7726
  import { Type as Type2 } from "typebox";
7633
7727
  var PI_BASH_CWD_KEY = "cwd";
@@ -7637,7 +7731,7 @@ var resolvePiBashCwd = (sessionCwd, requested) => {
7637
7731
  `Invalid pi.bash cwd ${JSON.stringify(requested)}: path must be a non-empty string`
7638
7732
  );
7639
7733
  }
7640
- const resolved = path8.isAbsolute(requested) ? path8.resolve(requested) : path8.resolve(sessionCwd, requested);
7734
+ const resolved = path9.isAbsolute(requested) ? path9.resolve(requested) : path9.resolve(sessionCwd, requested);
7641
7735
  try {
7642
7736
  if (!statSync(resolved).isDirectory()) throw new Error("path is not a directory");
7643
7737
  accessSync(resolved, constants.R_OK | constants.X_OK);
@@ -7736,14 +7830,14 @@ var createPreviewWriteToolDefinition = (cwd) => {
7736
7830
  return {
7737
7831
  ...original,
7738
7832
  async execute(_toolCallId, params, signal) {
7739
- const { path: path15, content } = params;
7740
- const absolutePath = resolvePreviewPath(path15, cwd);
7833
+ const { path: path16, content } = params;
7834
+ const absolutePath = resolvePreviewPath(path16, cwd);
7741
7835
  return withFileMutationQueue(absolutePath, async () => {
7742
7836
  const throwIfAborted2 = () => {
7743
7837
  if (signal?.aborted) throw new Error("Operation aborted");
7744
7838
  };
7745
7839
  throwIfAborted2();
7746
- const before = await readExistingFileForPreview(path15, cwd, content);
7840
+ const before = await readExistingFileForPreview(path16, cwd, content);
7747
7841
  throwIfAborted2();
7748
7842
  await mkdir(dirname(absolutePath), { recursive: true });
7749
7843
  throwIfAborted2();
@@ -7753,7 +7847,7 @@ var createPreviewWriteToolDefinition = (cwd) => {
7753
7847
  content: [
7754
7848
  {
7755
7849
  type: "text",
7756
- text: `Successfully wrote ${Buffer.byteLength(content, "utf8")} bytes to ${path15}`
7850
+ text: `Successfully wrote ${Buffer.byteLength(content, "utf8")} bytes to ${path16}`
7757
7851
  }
7758
7852
  ],
7759
7853
  details: { codePreviewBeforeWrite: before }
@@ -7787,7 +7881,7 @@ var expandReplaceAllEdit = (cwd, args, allForEveryEdit) => {
7787
7881
  }
7788
7882
  return { oldText, newText, all: allForEveryEdit || record.all === true };
7789
7883
  });
7790
- const resolvedPath = path9.resolve(
7884
+ const resolvedPath = path10.resolve(
7791
7885
  cwd,
7792
7886
  filePath.startsWith("@") ? filePath.slice(1) : filePath
7793
7887
  );
@@ -7929,6 +8023,13 @@ var PiToolsProvider = class {
7929
8023
  async invoke(actionName, args, context) {
7930
8024
  if (!(actionName in this.#tools)) throw new Error(`Unknown Pi tool: ${actionName}`);
7931
8025
  const name = actionName;
8026
+ if (name === "bash") {
8027
+ const intercepted = await tryExecuteGitWorktreeAdd(args, this.#cwd);
8028
+ if (intercepted) {
8029
+ this.#attachPreview(name, intercepted, args, context);
8030
+ return this.#normalizeResult(name, intercepted, args);
8031
+ }
8032
+ }
7932
8033
  if (this.#catalog?.get(name)) {
7933
8034
  const result = await this.#capturedTools.invoke(name, args, context);
7934
8035
  this.#attachReadMedia(name, result, context);
@@ -8149,8 +8250,8 @@ var PiToolsProvider = class {
8149
8250
  // src/schema/controller.ts
8150
8251
  import { spawn } from "node:child_process";
8151
8252
  import { createHash as createHash3, randomBytes, randomUUID as randomUUID3 } from "node:crypto";
8152
- import fs6 from "node:fs";
8153
- import path11 from "node:path";
8253
+ import fs7 from "node:fs";
8254
+ import path12 from "node:path";
8154
8255
 
8155
8256
  // src/schema/types.ts
8156
8257
  var stateBinding = (head) => head ? { transitionId: head.transitionId, version: head.version, to: head.to } : null;
@@ -8158,8 +8259,8 @@ var stateBinding = (head) => head ? { transitionId: head.transitionId, version:
8158
8259
  // src/schema/workspace.ts
8159
8260
  import { execFileSync } from "node:child_process";
8160
8261
  import { createHash as createHash2 } from "node:crypto";
8161
- import fs5 from "node:fs";
8162
- import path10 from "node:path";
8262
+ import fs6 from "node:fs";
8263
+ import path11 from "node:path";
8163
8264
  var SNAPSHOT_MAX_FILES = 2e4;
8164
8265
  var SNAPSHOT_MAX_BYTES = 512 * 1024 * 1024;
8165
8266
  var FALLBACK_SKIPPED_DIRECTORIES = /* @__PURE__ */ new Set([
@@ -8177,16 +8278,16 @@ var git = (cwd, args) => execFileSync("git", ["-C", cwd, ...args], {
8177
8278
  stdio: ["ignore", "pipe", "ignore"]
8178
8279
  });
8179
8280
  var nulPaths = (buffer) => buffer.toString("utf8").split("\0").filter((item) => item.length > 0);
8180
- var normalizeRelative = (value) => value.split(path10.sep).join("/");
8281
+ var normalizeRelative = (value) => value.split(path11.sep).join("/");
8181
8282
  var isInside = (root, candidate) => {
8182
- const relative = path10.relative(root, candidate);
8183
- return relative === "" || !path10.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path10.sep}`);
8283
+ const relative = path11.relative(root, candidate);
8284
+ return relative === "" || !path11.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path11.sep}`);
8184
8285
  };
8185
8286
  var excluded = (absolute, exclusions) => exclusions.some((root) => isInside(root, absolute));
8186
8287
  var entryDigest = (absolute) => {
8187
8288
  let stat2;
8188
8289
  try {
8189
- stat2 = fs5.lstatSync(absolute);
8290
+ stat2 = fs6.lstatSync(absolute);
8190
8291
  } catch (error) {
8191
8292
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
8192
8293
  return { marker: "absent", bytes: 0 };
@@ -8194,24 +8295,24 @@ var entryDigest = (absolute) => {
8194
8295
  throw error;
8195
8296
  }
8196
8297
  if (stat2.isSymbolicLink()) {
8197
- return { marker: `symlink:${digest(fs5.readlinkSync(absolute))}`, bytes: 0 };
8298
+ return { marker: `symlink:${digest(fs6.readlinkSync(absolute))}`, bytes: 0 };
8198
8299
  }
8199
8300
  if (!stat2.isFile()) {
8200
8301
  throw new Error(`Schema workspace snapshot does not support non-file entry: ${absolute}`);
8201
8302
  }
8202
- return { marker: `file:${stat2.mode & 511}:${digest(fs5.readFileSync(absolute))}`, bytes: stat2.size };
8303
+ return { marker: `file:${stat2.mode & 511}:${digest(fs6.readFileSync(absolute))}`, bytes: stat2.size };
8203
8304
  };
8204
8305
  var buildSnapshot = (cwd, paths, metadata, exclusions) => {
8205
8306
  const entries = {};
8206
8307
  let bytes = 0;
8207
8308
  const unique = [...new Set(paths)].sort((left, right) => left.localeCompare(right));
8208
8309
  for (const relativeInput of unique) {
8209
- const absolute = path10.resolve(cwd, relativeInput);
8310
+ const absolute = path11.resolve(cwd, relativeInput);
8210
8311
  if (!isInside(cwd, absolute) || excluded(absolute, exclusions)) continue;
8211
8312
  if (Object.keys(entries).length >= SNAPSHOT_MAX_FILES) {
8212
8313
  throw new Error(`Schema workspace snapshot exceeds ${SNAPSHOT_MAX_FILES} files`);
8213
8314
  }
8214
- const relative = normalizeRelative(path10.relative(cwd, absolute));
8315
+ const relative = normalizeRelative(path11.relative(cwd, absolute));
8215
8316
  const entry = entryDigest(absolute);
8216
8317
  bytes += entry.bytes;
8217
8318
  if (bytes > SNAPSHOT_MAX_BYTES) {
@@ -8237,12 +8338,12 @@ var buildSnapshot = (cwd, paths, metadata, exclusions) => {
8237
8338
  var fallbackPaths = (cwd, exclusions) => {
8238
8339
  const paths = [];
8239
8340
  const visit = (directory) => {
8240
- const entries = fs5.readdirSync(directory, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name));
8341
+ const entries = fs6.readdirSync(directory, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name));
8241
8342
  for (const entry of entries) {
8242
8343
  if (FALLBACK_SKIPPED_DIRECTORIES.has(entry.name)) continue;
8243
- const absolute = path10.join(directory, entry.name);
8344
+ const absolute = path11.join(directory, entry.name);
8244
8345
  if (excluded(absolute, exclusions)) continue;
8245
- const relative = normalizeRelative(path10.relative(cwd, absolute));
8346
+ const relative = normalizeRelative(path11.relative(cwd, absolute));
8246
8347
  if (entry.isDirectory()) visit(absolute);
8247
8348
  else paths.push(relative);
8248
8349
  if (paths.length > SNAPSHOT_MAX_FILES) {
@@ -8254,11 +8355,11 @@ var fallbackPaths = (cwd, exclusions) => {
8254
8355
  return paths;
8255
8356
  };
8256
8357
  var snapshotWorkspace = (cwdInput, excludedRoots = []) => {
8257
- const cwd = fs5.realpathSync(cwdInput);
8358
+ const cwd = fs6.realpathSync(cwdInput);
8258
8359
  const exclusions = excludedRoots.map((root) => {
8259
- const absolute = path10.resolve(root);
8360
+ const absolute = path11.resolve(root);
8260
8361
  try {
8261
- return fs5.realpathSync(absolute);
8362
+ return fs6.realpathSync(absolute);
8262
8363
  } catch {
8263
8364
  return absolute;
8264
8365
  }
@@ -8294,29 +8395,29 @@ var snapshotWorkspace = (cwdInput, excludedRoots = []) => {
8294
8395
  );
8295
8396
  };
8296
8397
  var resolveWorkspaceFile = (cwdInput, requestedPath, options) => {
8297
- if (!requestedPath.trim() || path10.isAbsolute(requestedPath)) {
8398
+ if (!requestedPath.trim() || path11.isAbsolute(requestedPath)) {
8298
8399
  throw new Error(`Schema paths must be non-empty project-relative paths: ${requestedPath}`);
8299
8400
  }
8300
- const cwd = fs5.realpathSync(cwdInput);
8301
- const absolute = path10.resolve(cwd, requestedPath);
8401
+ const cwd = fs6.realpathSync(cwdInput);
8402
+ const absolute = path11.resolve(cwd, requestedPath);
8302
8403
  if (!isInside(cwd, absolute) || absolute === cwd) {
8303
8404
  throw new Error(`Schema path escapes the project workspace: ${requestedPath}`);
8304
8405
  }
8305
- const relativeParts = path10.relative(cwd, absolute).split(path10.sep);
8406
+ const relativeParts = path11.relative(cwd, absolute).split(path11.sep);
8306
8407
  let cursor = cwd;
8307
8408
  for (let index = 0; index < relativeParts.length; index++) {
8308
- cursor = path10.join(cursor, relativeParts[index]);
8409
+ cursor = path11.join(cursor, relativeParts[index]);
8309
8410
  let stat2;
8310
8411
  try {
8311
- stat2 = fs5.lstatSync(cursor);
8412
+ stat2 = fs6.lstatSync(cursor);
8312
8413
  } catch (error) {
8313
8414
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
8314
8415
  if (index !== relativeParts.length - 1 || !options.allowAbsent) {
8315
8416
  throw new Error(`Schema path does not exist: ${requestedPath}`);
8316
8417
  }
8317
- const parentReal = fs5.realpathSync(path10.dirname(cursor));
8418
+ const parentReal = fs6.realpathSync(path11.dirname(cursor));
8318
8419
  if (!isInside(cwd, parentReal)) throw new Error(`Schema path parent escapes the workspace: ${requestedPath}`);
8319
- return { absolute, relative: normalizeRelative(path10.relative(cwd, absolute)), exists: false };
8420
+ return { absolute, relative: normalizeRelative(path11.relative(cwd, absolute)), exists: false };
8320
8421
  }
8321
8422
  throw error;
8322
8423
  }
@@ -8328,9 +8429,9 @@ var resolveWorkspaceFile = (cwdInput, requestedPath, options) => {
8328
8429
  throw new Error(`Schema transaction paths must name regular files: ${requestedPath}`);
8329
8430
  }
8330
8431
  }
8331
- return { absolute, relative: normalizeRelative(path10.relative(cwd, absolute)), exists: true };
8432
+ return { absolute, relative: normalizeRelative(path11.relative(cwd, absolute)), exists: true };
8332
8433
  };
8333
- var sha256File = (absolute) => `sha256:${digest(fs5.readFileSync(absolute))}`;
8434
+ var sha256File = (absolute) => `sha256:${digest(fs6.readFileSync(absolute))}`;
8334
8435
 
8335
8436
  // src/schema/controller.ts
8336
8437
  var SCHEMA_TOPIC = "fabric.schema";
@@ -8378,9 +8479,9 @@ var SchemaController = class {
8378
8479
  this.mesh = mesh;
8379
8480
  this.identity = identity;
8380
8481
  this.state = state;
8381
- this.cwd = fs6.realpathSync(cwd);
8382
- this.#journalRoot = path11.join(mesh.root, "schema-transactions");
8383
- this.#lockPath = path11.join(this.#journalRoot, ".commit.lock");
8482
+ this.cwd = fs7.realpathSync(cwd);
8483
+ this.#journalRoot = path12.join(mesh.root, "schema-transactions");
8484
+ this.#lockPath = path12.join(this.#journalRoot, ".commit.lock");
8384
8485
  this.#recoverJournals();
8385
8486
  }
8386
8487
  #activeHypotheses = /* @__PURE__ */ new Map();
@@ -8579,7 +8680,7 @@ var SchemaController = class {
8579
8680
  this.#assertPayloadBound(input);
8580
8681
  const release = this.#acquireCommitLock();
8581
8682
  const transactionId = randomUUID3();
8582
- const journalPath = path11.join(this.#journalRoot, `${transactionId}.json`);
8683
+ const journalPath = path12.join(this.#journalRoot, `${transactionId}.json`);
8583
8684
  let journal;
8584
8685
  let consumed = false;
8585
8686
  let committed = false;
@@ -8619,14 +8720,14 @@ var SchemaController = class {
8619
8720
  before.push({ path: resolved.relative, absolute: resolved.absolute, existed: false });
8620
8721
  continue;
8621
8722
  }
8622
- const content = fs6.readFileSync(resolved.absolute);
8723
+ const content = fs7.readFileSync(resolved.absolute);
8623
8724
  beforeBytes += content.byteLength;
8624
8725
  before.push({
8625
8726
  path: resolved.relative,
8626
8727
  absolute: resolved.absolute,
8627
8728
  existed: true,
8628
8729
  content: content.toString("base64"),
8629
- mode: fs6.statSync(resolved.absolute).mode & 511
8730
+ mode: fs7.statSync(resolved.absolute).mode & 511
8630
8731
  });
8631
8732
  }
8632
8733
  if (payloadBytes + beforeBytes > this.config.maxBytes) {
@@ -8870,7 +8971,7 @@ var SchemaController = class {
8870
8971
  observedSha256: sha256File(resolved.absolute)
8871
8972
  });
8872
8973
  } else if (item.kind === "file_contains") {
8873
- const confirmed = fs6.readFileSync(resolved.absolute, "utf8").includes(item.literal);
8974
+ const confirmed = fs7.readFileSync(resolved.absolute, "utf8").includes(item.literal);
8874
8975
  results.push({
8875
8976
  evidence: item,
8876
8977
  status: confirmed ? "confirmed" : "nonconfirmed",
@@ -8941,22 +9042,22 @@ var SchemaController = class {
8941
9042
  throw new Error(`Schema precondition SHA-256 mismatch: ${operation.path}`);
8942
9043
  }
8943
9044
  }
8944
- fs6.writeFileSync(resolved.absolute, operation.content, "utf8");
9045
+ fs7.writeFileSync(resolved.absolute, operation.content, "utf8");
8945
9046
  return;
8946
9047
  }
8947
9048
  if (sha256File(resolved.absolute) !== operation.expectedSha256) {
8948
9049
  throw new Error(`Schema precondition SHA-256 mismatch: ${operation.path}`);
8949
9050
  }
8950
9051
  if (operation.kind === "delete") {
8951
- fs6.unlinkSync(resolved.absolute);
9052
+ fs7.unlinkSync(resolved.absolute);
8952
9053
  return;
8953
9054
  }
8954
- const content = fs6.readFileSync(resolved.absolute, "utf8");
9055
+ const content = fs7.readFileSync(resolved.absolute, "utf8");
8955
9056
  const first = content.indexOf(operation.oldText);
8956
9057
  if (first < 0 || content.indexOf(operation.oldText, first + operation.oldText.length) >= 0) {
8957
9058
  throw new Error(`Schema edit requires oldText to occur exactly once: ${operation.path}`);
8958
9059
  }
8959
- fs6.writeFileSync(resolved.absolute, `${content.slice(0, first)}${operation.newText}${content.slice(first + operation.oldText.length)}`, "utf8");
9060
+ fs7.writeFileSync(resolved.absolute, `${content.slice(0, first)}${operation.newText}${content.slice(first + operation.oldText.length)}`, "utf8");
8960
9061
  }
8961
9062
  #assertNoOutsideDrift(before, after, declared) {
8962
9063
  if (before.git !== after.git || before.head !== after.head || before.indexDigest !== after.indexDigest) {
@@ -8976,10 +9077,10 @@ var SchemaController = class {
8976
9077
  try {
8977
9078
  const resolved = resolveWorkspaceFile(this.cwd, image.path, { allowAbsent: true });
8978
9079
  if (!image.existed) {
8979
- if (resolved.exists) fs6.unlinkSync(resolved.absolute);
9080
+ if (resolved.exists) fs7.unlinkSync(resolved.absolute);
8980
9081
  } else {
8981
- fs6.writeFileSync(resolved.absolute, Buffer.from(image.content ?? "", "base64"));
8982
- if (image.mode !== void 0) fs6.chmodSync(resolved.absolute, image.mode);
9082
+ fs7.writeFileSync(resolved.absolute, Buffer.from(image.content ?? "", "base64"));
9083
+ if (image.mode !== void 0) fs7.chmodSync(resolved.absolute, image.mode);
8983
9084
  }
8984
9085
  } catch (error) {
8985
9086
  errors.push(`${image.path}: ${errorMessage3(error)}`);
@@ -9027,25 +9128,25 @@ var SchemaController = class {
9027
9128
  return this.mesh.publish({ topic: SCHEMA_TOPIC, kind, from: this.identity, data });
9028
9129
  }
9029
9130
  #acquireCommitLock() {
9030
- fs6.mkdirSync(this.#journalRoot, { recursive: true, mode: 448 });
9131
+ fs7.mkdirSync(this.#journalRoot, { recursive: true, mode: 448 });
9031
9132
  try {
9032
- const descriptor = fs6.openSync(this.#lockPath, "wx", 384);
9033
- fs6.writeFileSync(descriptor, `${process.pid}
9133
+ const descriptor = fs7.openSync(this.#lockPath, "wx", 384);
9134
+ fs7.writeFileSync(descriptor, `${process.pid}
9034
9135
  ${Date.now()}
9035
9136
  `);
9036
- fs6.closeSync(descriptor);
9137
+ fs7.closeSync(descriptor);
9037
9138
  } catch (error) {
9038
9139
  if (error instanceof Error && "code" in error && error.code === "EEXIST") {
9039
9140
  throw new Error("Another Schema transaction is in progress");
9040
9141
  }
9041
9142
  throw error;
9042
9143
  }
9043
- return () => fs6.rmSync(this.#lockPath, { force: true });
9144
+ return () => fs7.rmSync(this.#lockPath, { force: true });
9044
9145
  }
9045
9146
  #recoverJournals() {
9046
- fs6.mkdirSync(this.#journalRoot, { recursive: true, mode: 448 });
9147
+ fs7.mkdirSync(this.#journalRoot, { recursive: true, mode: 448 });
9047
9148
  try {
9048
- const [pidText] = fs6.readFileSync(this.#lockPath, "utf8").split("\n");
9149
+ const [pidText] = fs7.readFileSync(this.#lockPath, "utf8").split("\n");
9049
9150
  const pid = Number(pidText);
9050
9151
  if (Number.isSafeInteger(pid) && pid > 0) {
9051
9152
  try {
@@ -9054,15 +9155,15 @@ ${Date.now()}
9054
9155
  } catch {
9055
9156
  }
9056
9157
  }
9057
- fs6.rmSync(this.#lockPath, { force: true });
9158
+ fs7.rmSync(this.#lockPath, { force: true });
9058
9159
  } catch (error) {
9059
9160
  if (!(error instanceof Error && "code" in error && error.code === "ENOENT")) throw error;
9060
9161
  }
9061
- for (const name of fs6.readdirSync(this.#journalRoot)) {
9162
+ for (const name of fs7.readdirSync(this.#journalRoot)) {
9062
9163
  if (!name.endsWith(".json")) continue;
9063
- const filePath = path11.join(this.#journalRoot, name);
9164
+ const filePath = path12.join(this.#journalRoot, name);
9064
9165
  try {
9065
- const journal = JSON.parse(fs6.readFileSync(filePath, "utf8"));
9166
+ const journal = JSON.parse(fs7.readFileSync(filePath, "utf8"));
9066
9167
  if (journal.format !== 1 || journal.status !== "applying" || !Array.isArray(journal.before)) continue;
9067
9168
  const workspace = this.#workspaceEntry()?.value;
9068
9169
  if (workspace?.lastOutcome === "committed" && workspace.lastTransactionId === journal.id) {
@@ -9314,11 +9415,11 @@ var SchemaProvider = class {
9314
9415
 
9315
9416
  // src/state/store.ts
9316
9417
  import { createHash as createHash5 } from "node:crypto";
9317
- import path13 from "node:path";
9418
+ import path14 from "node:path";
9318
9419
 
9319
9420
  // src/state/complexity.ts
9320
- import fs7 from "node:fs";
9321
- import path12 from "node:path";
9421
+ import fs8 from "node:fs";
9422
+ import path13 from "node:path";
9322
9423
  var isWordStart = (character) => character !== void 0 && (character >= "a" && character <= "z" || character >= "A" && character <= "Z" || character === "_" || character === "$");
9323
9424
  var isWordPart = (character) => isWordStart(character) || character !== void 0 && character >= "0" && character <= "9";
9324
9425
  var regularExpressionPrefixWords = /* @__PURE__ */ new Set([
@@ -9550,7 +9651,7 @@ var languageComplexities = [
9550
9651
  typeScriptJavaScriptComplexity
9551
9652
  ];
9552
9653
  var complexityForFile = (file, languages = languageComplexities) => {
9553
- const extension = path12.extname(file).toLowerCase();
9654
+ const extension = path13.extname(file).toLowerCase();
9554
9655
  return languages.find((language) => language.extensions.includes(extension));
9555
9656
  };
9556
9657
  var countFileComplexity = (file) => {
@@ -9559,7 +9660,7 @@ var countFileComplexity = (file) => {
9559
9660
  return {
9560
9661
  file,
9561
9662
  language: language.language,
9562
- count: language.count(fs7.readFileSync(file, "utf8"))
9663
+ count: language.count(fs8.readFileSync(file, "utf8"))
9563
9664
  };
9564
9665
  };
9565
9666
 
@@ -10441,7 +10542,7 @@ var StateStore = class {
10441
10542
  const files = [];
10442
10543
  let netDelta = 0;
10443
10544
  for (const file of this.normalizeComplexityFiles(requestedFiles, input.cwd)) {
10444
- const measured = countFileComplexity(path13.resolve(input.cwd, file));
10545
+ const measured = countFileComplexity(path14.resolve(input.cwd, file));
10445
10546
  if (!measured) {
10446
10547
  files.push({ file, supported: false });
10447
10548
  continue;
@@ -10468,7 +10569,7 @@ var StateStore = class {
10468
10569
  const updates = [];
10469
10570
  let netDelta = 0;
10470
10571
  for (const file of this.normalizeComplexityFiles(files, cwd)) {
10471
- const measured = countFileComplexity(path13.resolve(cwd, file));
10572
+ const measured = countFileComplexity(path14.resolve(cwd, file));
10472
10573
  if (!measured) {
10473
10574
  deltas.push({ file, supported: false });
10474
10575
  continue;
@@ -10518,11 +10619,11 @@ var StateStore = class {
10518
10619
  const normalized = /* @__PURE__ */ new Set();
10519
10620
  for (const file of files) {
10520
10621
  if (!file.trim()) continue;
10521
- const relative = path13.relative(cwd, path13.resolve(cwd, file));
10522
- if (relative === ".." || relative.startsWith(`..${path13.sep}`) || path13.isAbsolute(relative)) {
10622
+ const relative = path14.relative(cwd, path14.resolve(cwd, file));
10623
+ if (relative === ".." || relative.startsWith(`..${path14.sep}`) || path14.isAbsolute(relative)) {
10523
10624
  throw new Error(`State complexity file must be inside the project cwd: ${file}`);
10524
10625
  }
10525
- normalized.add(relative.split(path13.sep).join("/"));
10626
+ normalized.add(relative.split(path14.sep).join("/"));
10526
10627
  }
10527
10628
  return [...normalized];
10528
10629
  }
@@ -11468,7 +11569,7 @@ var FabricRuntimeState = class {
11468
11569
  create: () => new McpProvider(context.cwd, this.#config.mcp, {
11469
11570
  ...this.#config.mcp.cache.enabled ? {
11470
11571
  cache: new McpDescriptorCacheStore(
11471
- path14.join(
11572
+ path15.join(
11472
11573
  process.env.PI_FABRIC_PROJECT_ROOT ?? context.cwd,
11473
11574
  ".pi",
11474
11575
  "fabric",
@@ -11512,7 +11613,7 @@ var FabricRuntimeState = class {
11512
11613
  this.#mainAgent = mainAgent;
11513
11614
  const projectRoot = process.env.PI_FABRIC_PROJECT_ROOT ?? context.cwd;
11514
11615
  const configuredMeshRoot = this.#config.mesh.root;
11515
- const meshRoot = process.env.PI_FABRIC_MESH_ROOT ?? (configuredMeshRoot ? path14.resolve(projectRoot, configuredMeshRoot) : path14.join(projectRoot, ".pi", "fabric", "mesh"));
11616
+ const meshRoot = process.env.PI_FABRIC_MESH_ROOT ?? (configuredMeshRoot ? path15.resolve(projectRoot, configuredMeshRoot) : path15.join(projectRoot, ".pi", "fabric", "mesh"));
11516
11617
  this.#mesh = new MeshStore(
11517
11618
  meshRoot,
11518
11619
  this.#config.mesh.maxEventBytes,
@@ -11630,7 +11731,7 @@ var FabricRuntimeState = class {
11630
11731
  return participant ? participant.ownerHostId === hostId : void 0;
11631
11732
  };
11632
11733
  const lineageAlive = (rootId) => this.#participants?.get(rootId) !== void 0;
11633
- const persistentActorRoot = this.#config.mesh.actorScope === "session" ? path14.join(meshRoot, "actors", sessionId) : path14.join(meshRoot, "actors");
11734
+ const persistentActorRoot = this.#config.mesh.actorScope === "session" ? path15.join(meshRoot, "actors", sessionId) : path15.join(meshRoot, "actors");
11634
11735
  const acquireActorCapabilityView = (requirements, signal) => this.#registry.acquireCapabilityView(requirements, {
11635
11736
  cwd: context.cwd,
11636
11737
  signal,
@@ -12249,4 +12350,4 @@ var deepAssign = (target, source) => {
12249
12350
  export {
12250
12351
  FabricRuntimeState
12251
12352
  };
12252
- //# sourceMappingURL=fabric-runtime-state-VCLWTB55.js.map
12353
+ //# sourceMappingURL=fabric-runtime-state-H7UA3DJC.js.map