opencode-swarm 7.50.1 → 7.50.2

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.
package/dist/cli/index.js CHANGED
@@ -52,7 +52,7 @@ var package_default;
52
52
  var init_package = __esm(() => {
53
53
  package_default = {
54
54
  name: "opencode-swarm",
55
- version: "7.50.1",
55
+ version: "7.50.2",
56
56
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
57
57
  main: "dist/index.js",
58
58
  types: "dist/index.d.ts",
@@ -52594,47 +52594,90 @@ function batchAppendTestRuns(records, workingDir) {
52594
52594
  if (!fs19.existsSync(historyDir)) {
52595
52595
  fs19.mkdirSync(historyDir, { recursive: true });
52596
52596
  }
52597
- const existingRecords = readAllRecords(historyPath);
52598
- const sanitizedRecords = records.map((record3) => ({
52599
- ...record3,
52600
- timestamp: record3.timestamp || new Date().toISOString(),
52601
- durationMs: Math.max(0, record3.durationMs),
52602
- errorMessage: sanitizeErrorMessage(record3.errorMessage),
52603
- stackPrefix: sanitizeStackPrefix(record3.stackPrefix),
52604
- changedFiles: sanitizeChangedFiles(record3.changedFiles || [])
52605
- }));
52606
- existingRecords.push(...sanitizedRecords);
52607
- const recordsByTest = new Map;
52608
- for (const rec of existingRecords) {
52609
- const normalizedKey = `${rec.testFile.toLowerCase()}|${rec.testName.toLowerCase()}`;
52610
- if (!recordsByTest.has(normalizedKey)) {
52611
- recordsByTest.set(normalizedKey, []);
52612
- }
52613
- recordsByTest.get(normalizedKey).push(rec);
52614
- }
52615
- const prunedRecords = [];
52616
- for (const [, recs] of recordsByTest) {
52617
- recs.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
52618
- const toKeep = recs.slice(-MAX_HISTORY_PER_TEST);
52619
- prunedRecords.push(...toKeep);
52620
- }
52621
- prunedRecords.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
52622
- try {
52623
- const lines = prunedRecords.map((rec) => JSON.stringify(rec));
52624
- const content = `${lines.join(`
52597
+ withHistoryWriteLock(historyPath, () => {
52598
+ const existingRecords = readAllRecords(historyPath);
52599
+ const sanitizedRecords = records.map((record3) => ({
52600
+ ...record3,
52601
+ timestamp: record3.timestamp || new Date().toISOString(),
52602
+ durationMs: Math.max(0, record3.durationMs),
52603
+ errorMessage: sanitizeErrorMessage(record3.errorMessage),
52604
+ stackPrefix: sanitizeStackPrefix(record3.stackPrefix),
52605
+ changedFiles: sanitizeChangedFiles(record3.changedFiles || [])
52606
+ }));
52607
+ existingRecords.push(...sanitizedRecords);
52608
+ const recordsByTest = new Map;
52609
+ for (const rec of existingRecords) {
52610
+ const normalizedKey = `${rec.testFile.toLowerCase()}|${rec.testName.toLowerCase()}`;
52611
+ if (!recordsByTest.has(normalizedKey)) {
52612
+ recordsByTest.set(normalizedKey, []);
52613
+ }
52614
+ recordsByTest.get(normalizedKey).push(rec);
52615
+ }
52616
+ const prunedRecords = [];
52617
+ for (const [, recs] of recordsByTest) {
52618
+ recs.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
52619
+ const toKeep = recs.slice(-MAX_HISTORY_PER_TEST);
52620
+ prunedRecords.push(...toKeep);
52621
+ }
52622
+ prunedRecords.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
52623
+ try {
52624
+ const lines = prunedRecords.map((rec) => JSON.stringify(rec));
52625
+ const content = `${lines.join(`
52625
52626
  `)}
52626
52627
  `;
52627
- const tempPath = `${historyPath}.tmp`;
52628
- fs19.writeFileSync(tempPath, content, "utf-8");
52629
- fs19.renameSync(tempPath, historyPath);
52630
- } catch (err) {
52631
- try {
52632
52628
  const tempPath = `${historyPath}.tmp`;
52633
- if (fs19.existsSync(tempPath)) {
52634
- fs19.unlinkSync(tempPath);
52629
+ fs19.writeFileSync(tempPath, content, "utf-8");
52630
+ fs19.renameSync(tempPath, historyPath);
52631
+ } catch (err) {
52632
+ try {
52633
+ const tempPath = `${historyPath}.tmp`;
52634
+ if (fs19.existsSync(tempPath)) {
52635
+ fs19.unlinkSync(tempPath);
52636
+ }
52637
+ } catch {}
52638
+ throw new Error(`Failed to write test history: ${err instanceof Error ? err.message : String(err)}`);
52639
+ }
52640
+ });
52641
+ }
52642
+ function withHistoryWriteLock(historyPath, fn) {
52643
+ const lockPath = `${historyPath}.write-lock`;
52644
+ const deadline = Date.now() + HISTORY_WRITE_LOCK_TIMEOUT_MS;
52645
+ while (true) {
52646
+ try {
52647
+ fs19.mkdirSync(lockPath);
52648
+ break;
52649
+ } catch (error93) {
52650
+ const code = error93 instanceof Error && "code" in error93 ? error93.code : undefined;
52651
+ if (code !== "EEXIST") {
52652
+ throw new Error(`Failed to acquire test history lock: ${error93 instanceof Error ? error93.message : String(error93)}`);
52653
+ }
52654
+ if (Date.now() >= deadline) {
52655
+ throw new Error(`Timed out waiting for test history lock: ${historyPath}`);
52656
+ }
52657
+ try {
52658
+ const lockStat = fs19.statSync(lockPath);
52659
+ if (Date.now() - lockStat.mtimeMs >= HISTORY_WRITE_LOCK_STALE_MS) {
52660
+ fs19.rmSync(lockPath, { recursive: true, force: true });
52661
+ continue;
52662
+ }
52663
+ } catch {}
52664
+ const remainingMs = Math.max(0, deadline - Date.now());
52665
+ const sleepMs = Math.min(HISTORY_WRITE_LOCK_BACKOFF_MS, remainingMs);
52666
+ if (sleepMs > 0) {
52667
+ sleepSync(sleepMs);
52635
52668
  }
52669
+ }
52670
+ }
52671
+ try {
52672
+ return fn();
52673
+ } finally {
52674
+ try {
52675
+ fs19.rmSync(lockPath, { recursive: true, force: true });
52636
52676
  } catch {}
52637
- throw new Error(`Failed to write test history: ${err instanceof Error ? err.message : String(err)}`);
52677
+ }
52678
+ function sleepSync(ms) {
52679
+ const until = Date.now() + ms;
52680
+ while (Date.now() < until) {}
52638
52681
  }
52639
52682
  }
52640
52683
  function readAllRecords(historyPath) {
@@ -52670,7 +52713,7 @@ function getAllHistory(workingDir) {
52670
52713
  records.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
52671
52714
  return records;
52672
52715
  }
52673
- var MAX_HISTORY_PER_TEST = 20, MAX_ERROR_LENGTH = 500, MAX_STACK_LENGTH = 200, MAX_CHANGED_FILES = 50, DANGEROUS_PROPERTY_NAMES, _internals26;
52716
+ var MAX_HISTORY_PER_TEST = 20, MAX_ERROR_LENGTH = 500, MAX_STACK_LENGTH = 200, MAX_CHANGED_FILES = 50, HISTORY_WRITE_LOCK_TIMEOUT_MS = 5000, HISTORY_WRITE_LOCK_STALE_MS = 60000, HISTORY_WRITE_LOCK_BACKOFF_MS = 10, DANGEROUS_PROPERTY_NAMES, _internals26;
52674
52717
  var init_history_store = __esm(() => {
52675
52718
  init_manager2();
52676
52719
  DANGEROUS_PROPERTY_NAMES = new Set([
package/dist/index.js CHANGED
@@ -69,7 +69,7 @@ var package_default;
69
69
  var init_package = __esm(() => {
70
70
  package_default = {
71
71
  name: "opencode-swarm",
72
- version: "7.50.1",
72
+ version: "7.50.2",
73
73
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
74
74
  main: "dist/index.js",
75
75
  types: "dist/index.d.ts",
@@ -75964,47 +75964,90 @@ function batchAppendTestRuns(records, workingDir) {
75964
75964
  if (!fs29.existsSync(historyDir)) {
75965
75965
  fs29.mkdirSync(historyDir, { recursive: true });
75966
75966
  }
75967
- const existingRecords = readAllRecords(historyPath);
75968
- const sanitizedRecords = records.map((record3) => ({
75969
- ...record3,
75970
- timestamp: record3.timestamp || new Date().toISOString(),
75971
- durationMs: Math.max(0, record3.durationMs),
75972
- errorMessage: sanitizeErrorMessage(record3.errorMessage),
75973
- stackPrefix: sanitizeStackPrefix(record3.stackPrefix),
75974
- changedFiles: sanitizeChangedFiles(record3.changedFiles || [])
75975
- }));
75976
- existingRecords.push(...sanitizedRecords);
75977
- const recordsByTest = new Map;
75978
- for (const rec of existingRecords) {
75979
- const normalizedKey = `${rec.testFile.toLowerCase()}|${rec.testName.toLowerCase()}`;
75980
- if (!recordsByTest.has(normalizedKey)) {
75981
- recordsByTest.set(normalizedKey, []);
75982
- }
75983
- recordsByTest.get(normalizedKey).push(rec);
75984
- }
75985
- const prunedRecords = [];
75986
- for (const [, recs] of recordsByTest) {
75987
- recs.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
75988
- const toKeep = recs.slice(-MAX_HISTORY_PER_TEST);
75989
- prunedRecords.push(...toKeep);
75990
- }
75991
- prunedRecords.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
75992
- try {
75993
- const lines = prunedRecords.map((rec) => JSON.stringify(rec));
75994
- const content = `${lines.join(`
75967
+ withHistoryWriteLock(historyPath, () => {
75968
+ const existingRecords = readAllRecords(historyPath);
75969
+ const sanitizedRecords = records.map((record3) => ({
75970
+ ...record3,
75971
+ timestamp: record3.timestamp || new Date().toISOString(),
75972
+ durationMs: Math.max(0, record3.durationMs),
75973
+ errorMessage: sanitizeErrorMessage(record3.errorMessage),
75974
+ stackPrefix: sanitizeStackPrefix(record3.stackPrefix),
75975
+ changedFiles: sanitizeChangedFiles(record3.changedFiles || [])
75976
+ }));
75977
+ existingRecords.push(...sanitizedRecords);
75978
+ const recordsByTest = new Map;
75979
+ for (const rec of existingRecords) {
75980
+ const normalizedKey = `${rec.testFile.toLowerCase()}|${rec.testName.toLowerCase()}`;
75981
+ if (!recordsByTest.has(normalizedKey)) {
75982
+ recordsByTest.set(normalizedKey, []);
75983
+ }
75984
+ recordsByTest.get(normalizedKey).push(rec);
75985
+ }
75986
+ const prunedRecords = [];
75987
+ for (const [, recs] of recordsByTest) {
75988
+ recs.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
75989
+ const toKeep = recs.slice(-MAX_HISTORY_PER_TEST);
75990
+ prunedRecords.push(...toKeep);
75991
+ }
75992
+ prunedRecords.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
75993
+ try {
75994
+ const lines = prunedRecords.map((rec) => JSON.stringify(rec));
75995
+ const content = `${lines.join(`
75995
75996
  `)}
75996
75997
  `;
75997
- const tempPath = `${historyPath}.tmp`;
75998
- fs29.writeFileSync(tempPath, content, "utf-8");
75999
- fs29.renameSync(tempPath, historyPath);
76000
- } catch (err2) {
76001
- try {
76002
75998
  const tempPath = `${historyPath}.tmp`;
76003
- if (fs29.existsSync(tempPath)) {
76004
- fs29.unlinkSync(tempPath);
75999
+ fs29.writeFileSync(tempPath, content, "utf-8");
76000
+ fs29.renameSync(tempPath, historyPath);
76001
+ } catch (err2) {
76002
+ try {
76003
+ const tempPath = `${historyPath}.tmp`;
76004
+ if (fs29.existsSync(tempPath)) {
76005
+ fs29.unlinkSync(tempPath);
76006
+ }
76007
+ } catch {}
76008
+ throw new Error(`Failed to write test history: ${err2 instanceof Error ? err2.message : String(err2)}`);
76009
+ }
76010
+ });
76011
+ }
76012
+ function withHistoryWriteLock(historyPath, fn2) {
76013
+ const lockPath = `${historyPath}.write-lock`;
76014
+ const deadline = Date.now() + HISTORY_WRITE_LOCK_TIMEOUT_MS;
76015
+ while (true) {
76016
+ try {
76017
+ fs29.mkdirSync(lockPath);
76018
+ break;
76019
+ } catch (error93) {
76020
+ const code = error93 instanceof Error && "code" in error93 ? error93.code : undefined;
76021
+ if (code !== "EEXIST") {
76022
+ throw new Error(`Failed to acquire test history lock: ${error93 instanceof Error ? error93.message : String(error93)}`);
76023
+ }
76024
+ if (Date.now() >= deadline) {
76025
+ throw new Error(`Timed out waiting for test history lock: ${historyPath}`);
76026
+ }
76027
+ try {
76028
+ const lockStat = fs29.statSync(lockPath);
76029
+ if (Date.now() - lockStat.mtimeMs >= HISTORY_WRITE_LOCK_STALE_MS) {
76030
+ fs29.rmSync(lockPath, { recursive: true, force: true });
76031
+ continue;
76032
+ }
76033
+ } catch {}
76034
+ const remainingMs = Math.max(0, deadline - Date.now());
76035
+ const sleepMs = Math.min(HISTORY_WRITE_LOCK_BACKOFF_MS, remainingMs);
76036
+ if (sleepMs > 0) {
76037
+ sleepSync(sleepMs);
76005
76038
  }
76039
+ }
76040
+ }
76041
+ try {
76042
+ return fn2();
76043
+ } finally {
76044
+ try {
76045
+ fs29.rmSync(lockPath, { recursive: true, force: true });
76006
76046
  } catch {}
76007
- throw new Error(`Failed to write test history: ${err2 instanceof Error ? err2.message : String(err2)}`);
76047
+ }
76048
+ function sleepSync(ms) {
76049
+ const until = Date.now() + ms;
76050
+ while (Date.now() < until) {}
76008
76051
  }
76009
76052
  }
76010
76053
  function readAllRecords(historyPath) {
@@ -76040,7 +76083,7 @@ function getAllHistory(workingDir) {
76040
76083
  records.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
76041
76084
  return records;
76042
76085
  }
76043
- var MAX_HISTORY_PER_TEST = 20, MAX_ERROR_LENGTH = 500, MAX_STACK_LENGTH = 200, MAX_CHANGED_FILES = 50, DANGEROUS_PROPERTY_NAMES, _internals36;
76086
+ var MAX_HISTORY_PER_TEST = 20, MAX_ERROR_LENGTH = 500, MAX_STACK_LENGTH = 200, MAX_CHANGED_FILES = 50, HISTORY_WRITE_LOCK_TIMEOUT_MS = 5000, HISTORY_WRITE_LOCK_STALE_MS = 60000, HISTORY_WRITE_LOCK_BACKOFF_MS = 10, DANGEROUS_PROPERTY_NAMES, _internals36;
76044
76087
  var init_history_store = __esm(() => {
76045
76088
  init_manager2();
76046
76089
  DANGEROUS_PROPERTY_NAMES = new Set([
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "7.50.1",
3
+ "version": "7.50.2",
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",