gossipcat 0.4.6 → 0.4.8

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.
@@ -4116,13 +4116,31 @@ var init_git_tools = __esm({
4116
4116
  constructor(cwd) {
4117
4117
  this.cwd = cwd;
4118
4118
  }
4119
+ async execGit(args) {
4120
+ const opts = { cwd: this.cwd, env: { ...process.env } };
4121
+ try {
4122
+ return await execFileAsync2("git", args, opts);
4123
+ } catch (err) {
4124
+ const code = err.code;
4125
+ if (code === "ENOENT") {
4126
+ await new Promise((r) => setTimeout(r, 100));
4127
+ return await execFileAsync2("git", args, opts);
4128
+ }
4129
+ throw err;
4130
+ }
4131
+ }
4119
4132
  async git(...args) {
4120
4133
  try {
4121
- const { stdout } = await execFileAsync2("git", args, { cwd: this.cwd });
4134
+ const { stdout } = await this.execGit(args);
4122
4135
  return stdout.trim();
4123
4136
  } catch (err) {
4124
4137
  const error48 = err;
4125
- const msg = error48.stderr ? error48.stderr.trim() : error48.message;
4138
+ let msg = "Unknown error";
4139
+ if (error48 && typeof error48.stderr === "string") {
4140
+ msg = error48.stderr.trim();
4141
+ } else if (error48 && typeof error48.message === "string") {
4142
+ msg = error48.message;
4143
+ }
4126
4144
  throw new Error(`git ${args[0]} failed: ${msg}`);
4127
4145
  }
4128
4146
  }
@@ -4144,13 +4162,11 @@ var init_git_tools = __esm({
4144
4162
  }
4145
4163
  for (const file2 of untrackedFiles) {
4146
4164
  try {
4147
- const { stdout } = await execFileAsync2(
4148
- "git",
4149
- ["diff", "--no-index", "/dev/null", file2],
4150
- { cwd: this.cwd }
4165
+ const { stdout } = await this.execGit(
4166
+ ["diff", "--no-index", "/dev/null", file2]
4151
4167
  ).catch((err) => {
4152
4168
  const e = err;
4153
- return { stdout: e.stdout || "" };
4169
+ return { stdout: e.stdout || "", stderr: e.stderr || "" };
4154
4170
  });
4155
4171
  if (stdout) diffs.push(stdout.trim());
4156
4172
  } catch (err) {
@@ -4266,7 +4282,8 @@ var init_sandbox = __esm({
4266
4282
  * callers are unchanged.
4267
4283
  */
4268
4284
  validatePath(filePath, allowedRoots = []) {
4269
- const resolved = (0, import_path5.resolve)(this.root, filePath);
4285
+ const resolutionBase = allowedRoots[0] || this.root;
4286
+ const resolved = (0, import_path5.resolve)(resolutionBase, filePath);
4270
4287
  let checkPath = resolved;
4271
4288
  while (!(0, import_fs4.existsSync)(checkPath)) {
4272
4289
  const parent = (0, import_path5.dirname)(checkPath);
@@ -11901,6 +11918,19 @@ var init_scope_tracker = __esm({
11901
11918
  });
11902
11919
 
11903
11920
  // packages/orchestrator/src/worktree-manager.ts
11921
+ async function execGit(args, cwd) {
11922
+ const opts = { cwd, env: { ...process.env } };
11923
+ try {
11924
+ return await execFileAsync3("git", args, opts);
11925
+ } catch (err) {
11926
+ const code = err.code;
11927
+ if (code === "ENOENT") {
11928
+ await new Promise((r) => setTimeout(r, 100));
11929
+ return await execFileAsync3("git", args, opts);
11930
+ }
11931
+ throw err;
11932
+ }
11933
+ }
11904
11934
  var import_child_process3, import_util8, import_promises2, import_path19, import_os, execFileAsync3, WorktreeManager;
11905
11935
  var init_worktree_manager = __esm({
11906
11936
  "packages/orchestrator/src/worktree-manager.ts"() {
@@ -11918,12 +11948,12 @@ var init_worktree_manager = __esm({
11918
11948
  async create(taskId) {
11919
11949
  const branch = `gossip-${taskId}`;
11920
11950
  const wtPath = await (0, import_promises2.mkdtemp)((0, import_path19.join)((0, import_os.tmpdir)(), "gossip-wt-"));
11921
- await execFileAsync3("git", ["branch", branch, "HEAD"], { cwd: this.projectRoot });
11951
+ await execGit(["branch", branch, "HEAD"], this.projectRoot);
11922
11952
  try {
11923
- await execFileAsync3("git", ["worktree", "add", wtPath, branch], { cwd: this.projectRoot });
11953
+ await execGit(["worktree", "add", wtPath, branch], this.projectRoot);
11924
11954
  } catch (err) {
11925
11955
  try {
11926
- await execFileAsync3("git", ["branch", "-D", branch], { cwd: this.projectRoot });
11956
+ await execGit(["branch", "-D", branch], this.projectRoot);
11927
11957
  } catch {
11928
11958
  }
11929
11959
  throw err;
@@ -11932,14 +11962,14 @@ var init_worktree_manager = __esm({
11932
11962
  }
11933
11963
  async merge(taskId) {
11934
11964
  const branch = `gossip-${taskId}`;
11935
- const log4 = await execFileAsync3("git", ["log", `HEAD..${branch}`, "--oneline"], { cwd: this.projectRoot });
11965
+ const log4 = await execGit(["log", `HEAD..${branch}`, "--oneline"], this.projectRoot);
11936
11966
  if (!log4.stdout.trim()) return { merged: true };
11937
11967
  try {
11938
- await execFileAsync3("git", ["merge", branch, "--no-edit"], { cwd: this.projectRoot });
11968
+ await execGit(["merge", branch, "--no-edit"], this.projectRoot);
11939
11969
  return { merged: true };
11940
11970
  } catch {
11941
- await execFileAsync3("git", ["merge", "--abort"], { cwd: this.projectRoot });
11942
- const diff = await execFileAsync3("git", ["diff", "--name-only", `HEAD...${branch}`], { cwd: this.projectRoot });
11971
+ await execGit(["merge", "--abort"], this.projectRoot);
11972
+ const diff = await execGit(["diff", "--name-only", `HEAD...${branch}`], this.projectRoot);
11943
11973
  const files = diff.stdout.trim();
11944
11974
  return { merged: false, conflicts: files ? files.split("\n") : [] };
11945
11975
  }
@@ -11947,30 +11977,30 @@ var init_worktree_manager = __esm({
11947
11977
  async cleanup(taskId, wtPath) {
11948
11978
  const branch = `gossip-${taskId}`;
11949
11979
  try {
11950
- await execFileAsync3("git", ["worktree", "remove", wtPath, "--force"], { cwd: this.projectRoot });
11980
+ await execGit(["worktree", "remove", wtPath, "--force"], this.projectRoot);
11951
11981
  } catch {
11952
11982
  }
11953
11983
  try {
11954
- await execFileAsync3("git", ["branch", "-D", branch], { cwd: this.projectRoot });
11984
+ await execGit(["branch", "-D", branch], this.projectRoot);
11955
11985
  } catch {
11956
11986
  }
11957
11987
  }
11958
11988
  async pruneOrphans() {
11959
11989
  try {
11960
- const result = await execFileAsync3("git", ["worktree", "list", "--porcelain"], { cwd: this.projectRoot });
11990
+ const result = await execGit(["worktree", "list", "--porcelain"], this.projectRoot);
11961
11991
  const orphans = result.stdout.split("\n\n").filter((block) => block.includes("gossip-wt-")).map((block) => block.match(/worktree (.+)/)?.[1]).filter(Boolean);
11962
11992
  for (const wtPath of orphans) {
11963
11993
  try {
11964
- await execFileAsync3("git", ["worktree", "remove", wtPath, "--force"], { cwd: this.projectRoot });
11994
+ await execGit(["worktree", "remove", wtPath, "--force"], this.projectRoot);
11965
11995
  } catch {
11966
11996
  }
11967
11997
  }
11968
- await execFileAsync3("git", ["worktree", "prune"], { cwd: this.projectRoot });
11969
- const branchResult = await execFileAsync3("git", ["branch", "--list", "gossip-*"], { cwd: this.projectRoot });
11998
+ await execGit(["worktree", "prune"], this.projectRoot);
11999
+ const branchResult = await execGit(["branch", "--list", "gossip-*"], this.projectRoot);
11970
12000
  const branches = branchResult.stdout.trim().split("\n").map((b) => b.trim().replace(/^\*\s*/, "")).filter(Boolean);
11971
12001
  for (const b of branches) {
11972
12002
  try {
11973
- await execFileAsync3("git", ["branch", "-D", b], { cwd: this.projectRoot });
12003
+ await execGit(["branch", "-D", b], this.projectRoot);
11974
12004
  } catch {
11975
12005
  }
11976
12006
  }
@@ -21314,6 +21344,7 @@ __export(sandbox_exports, {
21314
21344
  auditDispatchBoundary: () => auditDispatchBoundary,
21315
21345
  auditFilesystemSinceSentinel: () => auditFilesystemSinceSentinel,
21316
21346
  buildAuditExclusions: () => buildAuditExclusions,
21347
+ buildFindPruneArgs: () => buildFindPruneArgs,
21317
21348
  cleanupTaskSentinel: () => cleanupTaskSentinel,
21318
21349
  defaultScanRoots: () => defaultScanRoots,
21319
21350
  detectBoundaryEscapes: () => detectBoundaryEscapes,
@@ -21588,8 +21619,15 @@ function canonicalize(p) {
21588
21619
  return p.replace(/\/+$/, "") || "/";
21589
21620
  }
21590
21621
  }
21591
- function defaultScanRoots() {
21622
+ function defaultScanRoots(writeMode, projectRoot) {
21592
21623
  const out = /* @__PURE__ */ new Set();
21624
+ if (writeMode === "scoped") {
21625
+ try {
21626
+ out.add(canonicalize(projectRoot));
21627
+ } catch {
21628
+ }
21629
+ return Array.from(out);
21630
+ }
21593
21631
  try {
21594
21632
  out.add(canonicalize((0, import_os2.homedir)()));
21595
21633
  } catch {
@@ -21612,24 +21650,49 @@ function expandTmpVariants(path2) {
21612
21650
  }
21613
21651
  return [p];
21614
21652
  }
21615
- function buildAuditExclusions(projectRoot, ownWorktree) {
21653
+ function buildAuditExclusions(projectRoot, ownWorktree, scope) {
21616
21654
  const excl = /* @__PURE__ */ new Set();
21617
21655
  const root = canonicalize(projectRoot);
21618
21656
  for (const v of expandTmpVariants(`${root}/.gossip`)) excl.add(v);
21619
21657
  for (const v of expandTmpVariants(`${root}/.claude`)) excl.add(v);
21658
+ for (const v of expandTmpVariants(`${root}/.git`)) excl.add(v);
21620
21659
  try {
21621
21660
  const home = canonicalize((0, import_os2.homedir)());
21622
- for (const sub of ["Library", ".cache", ".npm", ".claude/projects"]) {
21661
+ for (const sub of ["Library", ".cache", ".npm", ".claude"]) {
21623
21662
  for (const v of expandTmpVariants(`${home}/${sub}`)) excl.add(v);
21624
21663
  }
21625
21664
  } catch {
21626
21665
  }
21666
+ try {
21667
+ const tmp = canonicalize((0, import_os2.tmpdir)());
21668
+ for (const pat of ["com.apple.*", "itunescloudd", "TemporaryItems", "node-compile-cache"]) {
21669
+ for (const v of expandTmpVariants(`${tmp}/${pat}`)) excl.add(v);
21670
+ }
21671
+ } catch {
21672
+ }
21627
21673
  if (ownWorktree) {
21628
21674
  const wt = canonicalize(ownWorktree);
21629
21675
  for (const v of expandTmpVariants(wt)) excl.add(v);
21630
21676
  }
21677
+ if (scope) {
21678
+ const s = canonicalize((0, import_path38.join)(projectRoot, scope));
21679
+ for (const v of expandTmpVariants(s)) excl.add(v);
21680
+ }
21631
21681
  return Array.from(excl);
21632
21682
  }
21683
+ function buildFindPruneArgs(scanRoot, exclusions, sentinel) {
21684
+ const args = [scanRoot];
21685
+ if (exclusions.length > 0) {
21686
+ args.push("(");
21687
+ for (let i = 0; i < exclusions.length; i++) {
21688
+ if (i > 0) args.push("-o");
21689
+ args.push("-path", exclusions[i]);
21690
+ }
21691
+ args.push(")", "-prune", "-o");
21692
+ }
21693
+ args.push("-type", "f", "-newer", sentinel, "-print");
21694
+ return args;
21695
+ }
21633
21696
  function auditFilesystemSinceSentinel(projectRoot, meta3, options = {}) {
21634
21697
  const platform2 = options.platform ?? process.platform;
21635
21698
  const logFailures = options.logFailures ?? true;
@@ -21654,20 +21717,19 @@ function auditFilesystemSinceSentinel(projectRoot, meta3, options = {}) {
21654
21717
  if (sentinelMtimeMs === 0) {
21655
21718
  return { violations: [], skipped: "sentinel stat failed" };
21656
21719
  }
21657
- const scanRoots = options.scanRoots ?? defaultScanRoots();
21658
- const exclusions = buildAuditExclusions(projectRoot, meta3.worktreePath);
21720
+ const scanRoots = options.scanRoots ?? defaultScanRoots(
21721
+ options.writeMode ?? meta3.writeMode,
21722
+ projectRoot
21723
+ );
21724
+ const exclusions = buildAuditExclusions(projectRoot, meta3.worktreePath, options.scope);
21659
21725
  const findBin = options.findBinary ?? "find";
21660
21726
  const violations = [];
21661
21727
  for (const root of scanRoots) {
21662
21728
  if (!(0, import_fs34.existsSync)(root)) continue;
21663
21729
  const canonRoot = canonicalize(root);
21664
- const args = [canonRoot, "-type", "f", "-newer", sentinel];
21665
21730
  const sentinelDir = canonicalize((0, import_path38.join)(projectRoot, ".gossip", SENTINEL_DIR));
21666
21731
  const allExcl = [...exclusions, ...expandTmpVariants(sentinelDir)];
21667
- for (const e of allExcl) {
21668
- args.push("-not", "-path", e);
21669
- args.push("-not", "-path", `${e}/*`);
21670
- }
21732
+ const args = buildFindPruneArgs(canonRoot, allExcl, sentinel);
21671
21733
  try {
21672
21734
  const out = (0, import_child_process5.execFileSync)(findBin, args, {
21673
21735
  encoding: "utf-8",
@@ -21739,7 +21801,10 @@ function runLayer3Audit(projectRoot, taskId) {
21739
21801
  return { blockError, warnPrefix };
21740
21802
  }
21741
21803
  try {
21742
- const l3 = auditFilesystemSinceSentinel(projectRoot, meta3);
21804
+ const l3 = auditFilesystemSinceSentinel(projectRoot, meta3, {
21805
+ writeMode: meta3.writeMode,
21806
+ scope: meta3.scope
21807
+ });
21743
21808
  if (l3.violations && l3.violations.length > 0) {
21744
21809
  const list = l3.violations.slice(0, 20).join(", ");
21745
21810
  if (enforcement === "block") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gossipcat",
3
- "version": "0.4.6",
3
+ "version": "0.4.8",
4
4
  "description": "Multi-agent orchestration for Claude Code — parallel review, consensus, adaptive dispatch",
5
5
  "mcpName": "io.github.ataberk-xyz/gossipcat",
6
6
  "repository": {