opencode-swarm 6.68.1 → 6.69.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.
Files changed (2) hide show
  1. package/dist/index.js +471 -40
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -42117,17 +42117,17 @@ function normalizeSeparators(filePath) {
42117
42117
  }
42118
42118
  function matchesDocPattern(filePath, patterns) {
42119
42119
  const normalizedPath = normalizeSeparators(filePath);
42120
- const basename7 = path56.basename(filePath);
42120
+ const basename8 = path56.basename(filePath);
42121
42121
  for (const pattern of patterns) {
42122
42122
  if (!pattern.includes("/") && !pattern.includes("\\")) {
42123
- if (basename7 === pattern) {
42123
+ if (basename8 === pattern) {
42124
42124
  return true;
42125
42125
  }
42126
42126
  continue;
42127
42127
  }
42128
42128
  if (pattern.startsWith("**/")) {
42129
42129
  const filenamePattern = pattern.slice(3);
42130
- if (basename7 === filenamePattern) {
42130
+ if (basename8 === filenamePattern) {
42131
42131
  return true;
42132
42132
  }
42133
42133
  continue;
@@ -59425,6 +59425,324 @@ function isInDeclaredScope(filePath, scopeEntries, cwd) {
59425
59425
  return rel.length > 0 && !rel.startsWith("..") && !path41.isAbsolute(rel);
59426
59426
  });
59427
59427
  }
59428
+ var DC_MAX_UNWRAP_DEPTH = 5;
59429
+ var DC_SAFE_TARGETS = new Set([
59430
+ "node_modules",
59431
+ ".git",
59432
+ "dist",
59433
+ "build",
59434
+ "coverage",
59435
+ ".next",
59436
+ ".turbo",
59437
+ ".cache",
59438
+ ".venv",
59439
+ "venv",
59440
+ "__pycache__",
59441
+ "target",
59442
+ "out",
59443
+ ".parcel-cache",
59444
+ ".svelte-kit",
59445
+ ".nuxt",
59446
+ ".output",
59447
+ ".angular",
59448
+ ".gradle",
59449
+ "vendor"
59450
+ ]);
59451
+ var DC_BLOCKED_ABSOLUTE_PREFIXES = [
59452
+ "/root",
59453
+ "/home",
59454
+ "/Users",
59455
+ "/etc",
59456
+ "/var",
59457
+ "/usr",
59458
+ "/opt",
59459
+ "/bin",
59460
+ "/sbin",
59461
+ "/lib",
59462
+ "/boot",
59463
+ "/proc",
59464
+ "/sys",
59465
+ "/dev",
59466
+ "/run",
59467
+ "/System",
59468
+ "/Library",
59469
+ "/Applications",
59470
+ "C:\\Windows",
59471
+ "C:\\Users",
59472
+ "C:\\Program Files",
59473
+ "C:\\ProgramData",
59474
+ "C:/Windows",
59475
+ "C:/Users",
59476
+ "C:/Program Files",
59477
+ "C:/ProgramData"
59478
+ ];
59479
+ var DC_FS_ROOTS = new Set(["/", "C:\\", "C:/", "D:\\", "D:/", "E:\\", "E:/"]);
59480
+ var DC_REMOTE_PREFIXES = [
59481
+ "\\\\",
59482
+ "/Volumes/",
59483
+ "/net/",
59484
+ "/nfs/",
59485
+ "/smb/",
59486
+ "/run/user/"
59487
+ ];
59488
+ function dcNormalizeCommand(cmd) {
59489
+ let s = cmd.normalize("NFKC");
59490
+ s = s.replace(/`(.)/g, "$1");
59491
+ s = s.replace(/\^([a-zA-Z0-9 ])/g, "$1");
59492
+ s = s.replace(/""/g, "");
59493
+ s = s.replace(/''/g, "");
59494
+ return s;
59495
+ }
59496
+ function dcStripOneWrapper(cmd) {
59497
+ const t = cmd.trim();
59498
+ const cmdExeMatch = /^cmd(?:\.exe)?\s+\/[ckCK]\s+"?(.*?)"?\s*$/is.exec(t);
59499
+ if (cmdExeMatch)
59500
+ return cmdExeMatch[1].trim();
59501
+ const psCommandMatch = /^(?:powershell|pwsh)(?:\.exe)?\s+(?:-(?:Command|command|c)\s+)(.+)$/is.exec(t);
59502
+ if (psCommandMatch)
59503
+ return psCommandMatch[1].replace(/^["']|["']$/g, "").trim();
59504
+ const psEncMatch = /^(?:powershell|pwsh)(?:\.exe)?\s+(?:-(?:EncodedCommand|encodedcommand|enc|e)\s+)([A-Za-z0-9+/=]+)\s*$/.exec(t);
59505
+ if (psEncMatch) {
59506
+ try {
59507
+ const decoded = Buffer.from(psEncMatch[1], "base64").toString("utf16le");
59508
+ return decoded.trim();
59509
+ } catch {
59510
+ return t;
59511
+ }
59512
+ }
59513
+ const shellMatch = /^(?:bash|sh|zsh|dash|fish)(?:\.exe)?\s+-c\s+"?(.*?)"?\s*$/is.exec(t);
59514
+ if (shellMatch)
59515
+ return shellMatch[1].trim();
59516
+ const prefixMatch = /^(?:sudo|time|nohup)\s+(.+)$/is.exec(t) ?? /^env(?:\s+[A-Za-z_][A-Za-z0-9_]*=[^\s]*)*\s+(.+)$/is.exec(t) ?? /^nice\s+(?:-n\s+\d+\s+)?(.+)$/is.exec(t);
59517
+ if (prefixMatch)
59518
+ return prefixMatch[1].trim();
59519
+ const wslMatch = /^wsl(?:\.exe)?\s+(?:-e|--)\s+(.+)$/is.exec(t);
59520
+ if (wslMatch)
59521
+ return wslMatch[1].trim();
59522
+ const scriptBlockMatch = /^&\s*\{(.+)\}$/s.exec(t);
59523
+ if (scriptBlockMatch)
59524
+ return scriptBlockMatch[1].trim();
59525
+ const iexMatch = /^(?:Invoke-Expression|iex)\s+(.+)$/is.exec(t);
59526
+ if (iexMatch)
59527
+ return iexMatch[1].replace(/^["'`]|["'`]$/g, "").trim();
59528
+ const invokeCommandMatch = /^Invoke-Command\s+.*-ScriptBlock\s*\{(.+)\}$/is.exec(t);
59529
+ if (invokeCommandMatch)
59530
+ return invokeCommandMatch[1].trim();
59531
+ const callMatch = /^call\s+(.+)$/is.exec(t);
59532
+ if (callMatch)
59533
+ return callMatch[1].trim();
59534
+ return null;
59535
+ }
59536
+ function dcUnwrapWrappers(cmd) {
59537
+ let current = cmd.trim();
59538
+ for (let depth = 0;depth < DC_MAX_UNWRAP_DEPTH; depth++) {
59539
+ const inner = dcStripOneWrapper(current);
59540
+ if (inner === null || inner === current)
59541
+ break;
59542
+ current = inner.trim();
59543
+ }
59544
+ return current;
59545
+ }
59546
+ function dcSplitSegments(cmd) {
59547
+ const segments = [];
59548
+ let current = "";
59549
+ let inDoubleQuote = false;
59550
+ let inSingleQuote = false;
59551
+ for (let i2 = 0;i2 < cmd.length; i2++) {
59552
+ const ch = cmd[i2];
59553
+ const next = cmd[i2 + 1];
59554
+ if (ch === '"' && !inSingleQuote) {
59555
+ inDoubleQuote = !inDoubleQuote;
59556
+ current += ch;
59557
+ continue;
59558
+ }
59559
+ if (ch === "'" && !inDoubleQuote) {
59560
+ inSingleQuote = !inSingleQuote;
59561
+ current += ch;
59562
+ continue;
59563
+ }
59564
+ if (!inDoubleQuote && !inSingleQuote) {
59565
+ if (ch === "&" && next === "&" || ch === "|" && next === "|") {
59566
+ segments.push(current.trim());
59567
+ current = "";
59568
+ i2++;
59569
+ continue;
59570
+ }
59571
+ if (ch === "|" || ch === ";" || ch === `
59572
+ ` || ch === "\r") {
59573
+ segments.push(current.trim());
59574
+ current = "";
59575
+ continue;
59576
+ }
59577
+ }
59578
+ current += ch;
59579
+ }
59580
+ if (current.trim())
59581
+ segments.push(current.trim());
59582
+ return segments.filter((s) => s.length > 0);
59583
+ }
59584
+ function dcHasUnresolvableVars(p) {
59585
+ return /(%[A-Za-z_][A-Za-z0-9_]*%|\$\{?[A-Za-z_]|\$env:)/i.test(p);
59586
+ }
59587
+ function dcIsRemotePath(p) {
59588
+ return DC_REMOTE_PREFIXES.some((pfx) => p.startsWith(pfx));
59589
+ }
59590
+ function dcLstatAncestorWalk(targetPath, cwd) {
59591
+ const normalizedTarget = path41.resolve(cwd, targetPath);
59592
+ const normalizedCwd = path41.resolve(cwd);
59593
+ const ancestors = [];
59594
+ let current = normalizedTarget;
59595
+ while (true) {
59596
+ ancestors.push(current);
59597
+ const parent = path41.dirname(current);
59598
+ if (parent === current)
59599
+ break;
59600
+ const rel = path41.relative(normalizedCwd, current);
59601
+ if (rel === "" || rel.startsWith(".."))
59602
+ break;
59603
+ current = parent;
59604
+ }
59605
+ for (const ancestor of ancestors) {
59606
+ let stat2 = null;
59607
+ try {
59608
+ stat2 = fsSync.lstatSync(ancestor);
59609
+ } catch (err2) {
59610
+ const code = err2.code;
59611
+ if (code === "ENOENT") {
59612
+ break;
59613
+ }
59614
+ return `lstat failed on "${ancestor}": ${String(err2)} \u2014 refusing to allow destructive operation on unverifiable path`;
59615
+ }
59616
+ if (stat2.isSymbolicLink()) {
59617
+ return `BLOCKED: "${ancestor}" is a symlink/junction \u2014 deleting recursively through it would destroy the link target. Use platform-specific junction deletion (fsutil reparsepoint delete, Remove-Item without -Recurse) instead.`;
59618
+ }
59619
+ }
59620
+ return null;
59621
+ }
59622
+ function dcValidateTargets(targets, cwd) {
59623
+ for (const raw of targets) {
59624
+ const t = raw.trim().replace(/^["']|["']$/g, "");
59625
+ if (!t || t === ".")
59626
+ continue;
59627
+ if (dcHasUnresolvableVars(t)) {
59628
+ return `BLOCKED: Destructive command targets path with unexpanded variable "${t}" \u2014 cannot verify safety. Resolve variables before using destructive operations.`;
59629
+ }
59630
+ if (dcIsRemotePath(t)) {
59631
+ return `BLOCKED: Destructive command targets remote/network filesystem path "${t}" \u2014 refusing to execute remote destructive operations.`;
59632
+ }
59633
+ if (/^\\\\/.test(t)) {
59634
+ return `BLOCKED: Destructive command targets UNC path "${t}" \u2014 UNC paths in destructive operations are not allowed.`;
59635
+ }
59636
+ const lstatBlock = dcLstatAncestorWalk(t, cwd);
59637
+ if (lstatBlock)
59638
+ return lstatBlock;
59639
+ const basename6 = path41.basename(t);
59640
+ if (t === basename6 && DC_SAFE_TARGETS.has(t)) {
59641
+ continue;
59642
+ }
59643
+ if (DC_FS_ROOTS.has(t) || DC_FS_ROOTS.has(t.replace(/\//g, "\\"))) {
59644
+ return `BLOCKED: Destructive command targets filesystem root "${t}"`;
59645
+ }
59646
+ if (path41.isAbsolute(t) || /^[A-Za-z]:/.test(t)) {
59647
+ for (const blocked of DC_BLOCKED_ABSOLUTE_PREFIXES) {
59648
+ if (t.startsWith(blocked)) {
59649
+ return `BLOCKED: Destructive command targets system path "${t}" which is under protected prefix "${blocked}"`;
59650
+ }
59651
+ }
59652
+ }
59653
+ }
59654
+ return null;
59655
+ }
59656
+ function dcCheckJunctionCreation(segment, cwd) {
59657
+ const mklinkMatch = /^mklink(?:\.exe)?\s+\/[JjDd]\s+"?([^"\s]+)"?\s+"?([^"\s]+)"?/i.exec(segment);
59658
+ if (mklinkMatch) {
59659
+ const target = mklinkMatch[2].trim();
59660
+ if (!dcHasUnresolvableVars(target)) {
59661
+ const resolved = path41.resolve(cwd, target);
59662
+ const rel = path41.relative(cwd, resolved);
59663
+ if (rel.startsWith("..") || path41.isAbsolute(rel)) {
59664
+ return `BLOCKED: Junction/symlink creation targeting path outside working directory: mklink target "${target}" resolves to "${resolved}" which is outside "${cwd}". Creating junctions to external paths and then deleting them recursively can destroy data.`;
59665
+ }
59666
+ }
59667
+ return null;
59668
+ }
59669
+ const newItemTypeMatch = /New-Item\b.*-ItemType\s+(?:Junction|SymbolicLink|HardLink)\b/i.test(segment);
59670
+ const newItemTargetMatch = /-Target\s+"?([^"\s;]+)"?/i.exec(segment);
59671
+ const newItemMatch = newItemTypeMatch ? newItemTargetMatch : null;
59672
+ if (newItemMatch) {
59673
+ const target = newItemMatch[1].trim();
59674
+ if (!dcHasUnresolvableVars(target)) {
59675
+ const resolved = path41.resolve(cwd, target);
59676
+ const rel = path41.relative(cwd, resolved);
59677
+ if (rel.startsWith("..") || path41.isAbsolute(rel)) {
59678
+ return `BLOCKED: Junction/symlink creation targeting path outside working directory: New-Item target "${target}" resolves to "${resolved}" which is outside "${cwd}". This pattern caused the K2.6 data-loss incident.`;
59679
+ }
59680
+ }
59681
+ return null;
59682
+ }
59683
+ const lnMatch = /^ln\s+(?:-[sfnv]*s[sfnv]*|-s)\s+"?([^"\s]+)"?(?:\s+"?[^"\s]+"?)?\s*$/.exec(segment);
59684
+ if (lnMatch) {
59685
+ const target = lnMatch[1].trim();
59686
+ if (!dcHasUnresolvableVars(target)) {
59687
+ const resolved = path41.resolve(cwd, target);
59688
+ const rel = path41.relative(cwd, resolved);
59689
+ if (rel.startsWith("..") || path41.isAbsolute(rel)) {
59690
+ return `BLOCKED: Symlink creation targeting path outside working directory: ln -s target "${target}" resolves to "${resolved}" which is outside "${cwd}". Symlinks to external paths combined with recursive deletion can destroy data.`;
59691
+ }
59692
+ }
59693
+ return null;
59694
+ }
59695
+ return null;
59696
+ }
59697
+ function dcExtractWindowsCmdTargets(segment) {
59698
+ const rmdirMatch = /^(?:rmdir|rd)(?:\.exe)?\s+(?:\/[sqSQ]\s+)*"?(.+?)"?\s*$/i.exec(segment);
59699
+ if (rmdirMatch)
59700
+ return [rmdirMatch[1].trim()];
59701
+ const delMatch = /^del(?:\.exe)?\s+(?:\/[sqfSQF]\s+)*"?(.+?)"?\s*$/i.exec(segment);
59702
+ if (delMatch)
59703
+ return [delMatch[1].trim()];
59704
+ return [];
59705
+ }
59706
+ function dcExtractPowerShellTargets(segment) {
59707
+ const verbMatch = /^(?:Remove-Item|ri|rm|rmdir|del|erase|rd)\s+/i.exec(segment);
59708
+ if (!verbMatch)
59709
+ return [];
59710
+ const rest = segment.slice(verbMatch[0].length);
59711
+ const tokens = rest.match(/"[^"]*"|'[^']*'|[^\s]+/g) ?? [];
59712
+ const targets = [];
59713
+ const valueFlags = new Set([
59714
+ "-literalpath",
59715
+ "-path",
59716
+ "-filter",
59717
+ "-include",
59718
+ "-exclude",
59719
+ "-lp"
59720
+ ]);
59721
+ let skipNext = false;
59722
+ for (const tok of tokens) {
59723
+ if (skipNext) {
59724
+ skipNext = false;
59725
+ continue;
59726
+ }
59727
+ if (tok.startsWith("-")) {
59728
+ if (valueFlags.has(tok.toLowerCase())) {
59729
+ skipNext = true;
59730
+ const idx = tokens.indexOf(tok);
59731
+ if (idx !== -1 && idx + 1 < tokens.length) {
59732
+ const val = tokens[idx + 1].replace(/^["']|["']$/g, "");
59733
+ if (val)
59734
+ targets.push(val);
59735
+ skipNext = true;
59736
+ }
59737
+ }
59738
+ } else {
59739
+ const cleaned = tok.replace(/^["']|["']$/g, "");
59740
+ if (cleaned)
59741
+ targets.push(cleaned);
59742
+ }
59743
+ }
59744
+ return targets;
59745
+ }
59428
59746
  function createGuardrailsHooks(directory, directoryOrConfig, config3, authorityConfig) {
59429
59747
  let guardrailsConfig;
59430
59748
  if (directory && typeof directory === "object" && "enabled" in directory) {
@@ -59459,46 +59777,159 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3, authorityC
59459
59777
  if (cfg.block_destructive_commands === false)
59460
59778
  return;
59461
59779
  const toolArgs = args2;
59462
- const command = typeof toolArgs?.command === "string" ? toolArgs.command.trim() : "";
59463
- if (!command)
59780
+ const rawCommand = typeof toolArgs?.command === "string" ? toolArgs.command.trim() : "";
59781
+ if (!rawCommand)
59464
59782
  return;
59783
+ const cwd = effectiveDirectory;
59784
+ const command = dcNormalizeCommand(rawCommand);
59465
59785
  if (/:\s*\(\s*\)\s*\{[^}]*\|[^}]*:/.test(command)) {
59466
59786
  throw new Error(`BLOCKED: Potentially destructive shell command detected: fork bomb pattern`);
59467
59787
  }
59468
- const rmFlagPattern = /^rm\s+(-r\s+-f|-f\s+-r|-rf|-fr)\s+(.+)$/;
59469
- const rmMatch = rmFlagPattern.exec(command);
59470
- if (rmMatch) {
59471
- const targetPart = rmMatch[2].trim();
59472
- const targets = targetPart.split(/\s+/);
59473
- const safeTargets = /^(node_modules|\.git)$/;
59474
- const allSafe = targets.every((t) => safeTargets.test(t));
59475
- if (!allSafe) {
59476
- throw new Error(`BLOCKED: Potentially destructive shell command: rm -rf on unsafe path(s): ${targetPart}`);
59788
+ const unwrapped = dcUnwrapWrappers(command);
59789
+ const outerSegments = dcSplitSegments(command);
59790
+ const innerSegments = dcSplitSegments(unwrapped);
59791
+ const perSegmentUnwrapped = outerSegments.map((s) => dcUnwrapWrappers(s));
59792
+ const allSegments = [
59793
+ ...new Set([...outerSegments, ...innerSegments, ...perSegmentUnwrapped])
59794
+ ];
59795
+ for (const segment of allSegments) {
59796
+ const seg = segment.trim();
59797
+ if (!seg)
59798
+ continue;
59799
+ const junctionBlock = dcCheckJunctionCreation(seg, cwd);
59800
+ if (junctionBlock)
59801
+ throw new Error(junctionBlock);
59802
+ const rmShortMatch = /^rm\s+(-[rRfF]+(?:\s+-[rRfF]+)*|-r\s+-f|-f\s+-r)\s+(.+)$/.exec(seg);
59803
+ const rmLongMatch = /^rm\s+(?:--(?:recursive|force)\s+){1,2}(.+)$/.exec(seg);
59804
+ const rmAnyMatch = rmShortMatch ?? rmLongMatch;
59805
+ if (rmAnyMatch) {
59806
+ const targetPart = rmAnyMatch[rmShortMatch ? 2 : 1].trim();
59807
+ const targets = targetPart.split(/\s+/);
59808
+ const validateBlock = dcValidateTargets(targets, cwd);
59809
+ if (validateBlock)
59810
+ throw new Error(validateBlock);
59811
+ const allSafe = targets.every((t) => DC_SAFE_TARGETS.has(t.replace(/^["']|["']$/g, "").trim()));
59812
+ if (!allSafe) {
59813
+ throw new Error(`BLOCKED: Potentially destructive shell command: rm with recursive/force flags on unsafe path(s): ${targetPart}`);
59814
+ }
59815
+ }
59816
+ if (/^(?:rmdir|rd)(?:\.exe)?\s+.*\/[sS]/i.test(seg)) {
59817
+ const targets = dcExtractWindowsCmdTargets(seg);
59818
+ if (targets.length === 0) {
59819
+ throw new Error(`BLOCKED: Windows recursive directory delete (rmdir /s or rd /s) detected. Verify the target is not a junction/symlink.`);
59820
+ }
59821
+ const validateBlock = dcValidateTargets(targets, cwd);
59822
+ if (validateBlock)
59823
+ throw new Error(validateBlock);
59824
+ const allSafe = targets.every((t) => DC_SAFE_TARGETS.has(t.trim()));
59825
+ if (!allSafe) {
59826
+ throw new Error(`BLOCKED: Windows recursive directory delete on unsafe path(s): ${targets.join(", ")}`);
59827
+ }
59828
+ }
59829
+ if (/^del(?:\.exe)?\s+.*\/[sS]/i.test(seg)) {
59830
+ const targets = dcExtractWindowsCmdTargets(seg);
59831
+ if (targets.length > 0) {
59832
+ const validateBlock = dcValidateTargets(targets, cwd);
59833
+ if (validateBlock)
59834
+ throw new Error(validateBlock);
59835
+ const allSafe = targets.every((t) => DC_SAFE_TARGETS.has(t.trim()));
59836
+ if (!allSafe) {
59837
+ throw new Error(`BLOCKED: Windows recursive file delete (del /s) on unsafe path(s): ${targets.join(", ")}`);
59838
+ }
59839
+ }
59840
+ }
59841
+ if (/^(?:Remove-Item|ri|rm|rmdir|del|erase|rd)\b.*-[Rr]ecurse\b/i.test(seg) || /^(?:Remove-Item|ri|rm|rmdir|del|erase|rd)\b.*-[Rr]\b/i.test(seg)) {
59842
+ const targets = dcExtractPowerShellTargets(seg);
59843
+ if (targets.length > 0) {
59844
+ const validateBlock = dcValidateTargets(targets, cwd);
59845
+ if (validateBlock)
59846
+ throw new Error(validateBlock);
59847
+ const allSafe = targets.every((t) => DC_SAFE_TARGETS.has(t.trim()));
59848
+ if (!allSafe) {
59849
+ throw new Error(`BLOCKED: PowerShell recursive delete on unsafe path(s): ${targets.join(", ")}`);
59850
+ }
59851
+ } else {
59852
+ throw new Error(`BLOCKED: PowerShell Remove-Item with -Recurse detected \u2014 cannot verify target safety`);
59853
+ }
59854
+ }
59855
+ if (/Get-ChildItem\b.*\|\s*Remove-Item\b.*-[Rr]ecurse/i.test(seg) || /gci\b.*\|\s*ri\b.*-[Rr]ecurse/i.test(seg)) {
59856
+ throw new Error(`BLOCKED: PowerShell pipeline "Get-ChildItem | Remove-Item -Recurse" detected \u2014 verify target safety and avoid recursive deletion through symlinks/junctions`);
59857
+ }
59858
+ if (/^vssadmin(?:\.exe)?\s+delete\b/i.test(seg)) {
59859
+ throw new Error(`BLOCKED: "vssadmin delete" detected \u2014 deletes Volume Shadow Copies (ransomware-grade operation)`);
59860
+ }
59861
+ if (/^wbadmin(?:\.exe)?\s+delete\b/i.test(seg)) {
59862
+ throw new Error(`BLOCKED: "wbadmin delete" detected \u2014 deletes Windows backup catalog (ransomware-grade operation)`);
59863
+ }
59864
+ if (/^diskpart(?:\.exe)?$/i.test(seg)) {
59865
+ throw new Error(`BLOCKED: "diskpart" detected \u2014 interactive disk partitioning tool`);
59866
+ }
59867
+ if (/^bcdedit(?:\.exe)?\s+\/delete\b/i.test(seg)) {
59868
+ throw new Error(`BLOCKED: "bcdedit /delete" detected \u2014 modifies Windows boot configuration`);
59869
+ }
59870
+ if (/^sdelete(?:\.exe)?\s+/i.test(seg)) {
59871
+ throw new Error(`BLOCKED: "sdelete" detected \u2014 secure file deletion (Sysinternals)`);
59872
+ }
59873
+ if (/^fsutil(?:\.exe)?\s+reparsepoint\s+delete\b/i.test(seg) || /^fsutil(?:\.exe)?\s+file\s+setzerodata\b/i.test(seg)) {
59874
+ throw new Error(`BLOCKED: "fsutil" destructive subcommand detected`);
59875
+ }
59876
+ if (/^takeown(?:\.exe)?\s+.*\/[rR]\b/i.test(seg)) {
59877
+ throw new Error(`BLOCKED: "takeown /R" (recursive ownership takeover) detected \u2014 often precedes destructive operations`);
59878
+ }
59879
+ if (/^cipher(?:\.exe)?\s+\/[wW]\b/i.test(seg)) {
59880
+ throw new Error(`BLOCKED: "cipher /w" detected \u2014 overwrites free disk space (data wipe operation)`);
59881
+ }
59882
+ if (/^format\s+[A-Za-z]:/i.test(seg)) {
59883
+ throw new Error(`BLOCKED: Windows disk format command detected`);
59884
+ }
59885
+ if (/^robocopy(?:\.exe)?\s+.*\/(?:MIR|mir)\b/.test(seg)) {
59886
+ throw new Error(`BLOCKED: "robocopy /MIR" (mirror) detected \u2014 can delete files in the destination that don't exist in the source`);
59887
+ }
59888
+ if (/^chmod\s+.*-[rR]\b.*000\b/.test(seg)) {
59889
+ throw new Error(`BLOCKED: "chmod -R 000" detected \u2014 removes all permissions recursively`);
59890
+ }
59891
+ if (/^chattr\s+.*\+i\b/.test(seg)) {
59892
+ throw new Error(`BLOCKED: "chattr +i" detected \u2014 makes files immutable`);
59893
+ }
59894
+ if (/^icacls(?:\.exe)?\s+.*\/deny\b/i.test(seg)) {
59895
+ throw new Error(`BLOCKED: "icacls /deny" detected \u2014 denies filesystem permissions`);
59896
+ }
59897
+ if (/^dd\b.*\bif=\/dev\/(zero|null|urandom)\b/.test(seg)) {
59898
+ throw new Error(`BLOCKED: "dd" with /dev/zero, /dev/null, or /dev/urandom as input detected \u2014 data wipe operation`);
59899
+ }
59900
+ if (/^git\s+push\b.*?(--force|-f)\b/.test(seg)) {
59901
+ throw new Error(`BLOCKED: Force push detected \u2014 git push --force is not allowed`);
59902
+ }
59903
+ if (/^git\s+reset\s+--hard/.test(seg)) {
59904
+ throw new Error(`BLOCKED: "git reset --hard" detected \u2014 use --soft or --mixed with caution`);
59905
+ }
59906
+ if (/^git\s+reset\s+--mixed\s+\S+/.test(seg)) {
59907
+ throw new Error(`BLOCKED: "git reset --mixed" with a target branch/commit is not allowed`);
59908
+ }
59909
+ if (/^git\s+clean\s+.*-[fF].*[dD]/.test(seg)) {
59910
+ throw new Error(`BLOCKED: "git clean -fd" detected \u2014 permanently deletes untracked files and directories`);
59911
+ }
59912
+ if (/^git\s+worktree\s+remove\s+.*--force\b/i.test(seg)) {
59913
+ throw new Error(`BLOCKED: "git worktree remove --force" detected \u2014 can delete working tree contents`);
59914
+ }
59915
+ if (/^rsync\b.*--delete(?:-after|-before|-during|-delay)?\b/.test(seg)) {
59916
+ throw new Error(`BLOCKED: "rsync --delete" detected \u2014 can delete files in the destination. Verify source is not empty.`);
59917
+ }
59918
+ if (/^kubectl\s+delete\b/.test(seg)) {
59919
+ throw new Error(`BLOCKED: "kubectl delete" detected \u2014 destructive cluster operation`);
59920
+ }
59921
+ if (/^docker\s+system\s+prune\b/.test(seg)) {
59922
+ throw new Error(`BLOCKED: "docker system prune" detected \u2014 destructive container operation`);
59923
+ }
59924
+ if (/^\s*DROP\s+(TABLE|DATABASE|SCHEMA)\b/i.test(seg)) {
59925
+ throw new Error(`BLOCKED: SQL DROP command detected \u2014 destructive database operation`);
59926
+ }
59927
+ if (/^\s*TRUNCATE\s+TABLE\b/i.test(seg)) {
59928
+ throw new Error(`BLOCKED: SQL TRUNCATE command detected \u2014 destructive database operation`);
59929
+ }
59930
+ if (/^mkfs[./]/.test(seg)) {
59931
+ throw new Error(`BLOCKED: Disk format command (mkfs) detected \u2014 disk formatting operation`);
59477
59932
  }
59478
- }
59479
- if (/^git\s+push\b.*?(--force|-f)\b/.test(command)) {
59480
- throw new Error(`BLOCKED: Force push detected \u2014 git push --force is not allowed`);
59481
- }
59482
- if (/^git\s+reset\s+--hard/.test(command)) {
59483
- throw new Error(`BLOCKED: "git reset --hard" detected \u2014 use --soft or --mixed with caution`);
59484
- }
59485
- if (/^git\s+reset\s+--mixed\s+\S+/.test(command)) {
59486
- throw new Error(`BLOCKED: "git reset --mixed" with a target branch/commit is not allowed`);
59487
- }
59488
- if (/^kubectl\s+delete\b/.test(command)) {
59489
- throw new Error(`BLOCKED: "kubectl delete" detected \u2014 destructive cluster operation`);
59490
- }
59491
- if (/^docker\s+system\s+prune\b/.test(command)) {
59492
- throw new Error(`BLOCKED: "docker system prune" detected \u2014 destructive container operation`);
59493
- }
59494
- if (/^\s*DROP\s+(TABLE|DATABASE|SCHEMA)\b/i.test(command)) {
59495
- throw new Error(`BLOCKED: SQL DROP command detected \u2014 destructive database operation`);
59496
- }
59497
- if (/^\s*TRUNCATE\s+TABLE\b/i.test(command)) {
59498
- throw new Error(`BLOCKED: SQL TRUNCATE command detected \u2014 destructive database operation`);
59499
- }
59500
- if (/^mkfs[./]/.test(command)) {
59501
- throw new Error(`BLOCKED: Disk format command (mkfs) detected \u2014 disk formatting operation`);
59502
59933
  }
59503
59934
  }
59504
59935
  async function checkGateLimits(params) {
@@ -68884,7 +69315,7 @@ function countCodeLines(content) {
68884
69315
  return lines.length;
68885
69316
  }
68886
69317
  function isTestFile(filePath) {
68887
- const basename9 = path65.basename(filePath);
69318
+ const basename10 = path65.basename(filePath);
68888
69319
  const _ext = path65.extname(filePath).toLowerCase();
68889
69320
  const testPatterns = [
68890
69321
  ".test.",
@@ -68900,7 +69331,7 @@ function isTestFile(filePath) {
68900
69331
  ".spec.jsx"
68901
69332
  ];
68902
69333
  for (const pattern of testPatterns) {
68903
- if (basename9.includes(pattern)) {
69334
+ if (basename10.includes(pattern)) {
68904
69335
  return true;
68905
69336
  }
68906
69337
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "6.68.1",
3
+ "version": "6.69.0",
4
4
  "description": "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",