squads-cli 0.5.0 → 0.6.1

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 (127) hide show
  1. package/README.md +161 -4
  2. package/dist/{chunk-HKWCBCEK.js → chunk-4CMAEQQY.js} +6 -2
  3. package/dist/chunk-4CMAEQQY.js.map +1 -0
  4. package/dist/{chunk-NA3IECJA.js → chunk-N7KDWU4W.js} +155 -58
  5. package/dist/chunk-N7KDWU4W.js.map +1 -0
  6. package/dist/{chunk-7PRYDHZW.js → chunk-NHGLXN2F.js} +8 -6
  7. package/dist/chunk-NHGLXN2F.js.map +1 -0
  8. package/dist/{chunk-QPH5OR7J.js → chunk-O7UV3FWI.js} +139 -21
  9. package/dist/chunk-O7UV3FWI.js.map +1 -0
  10. package/dist/{chunk-BV6S5AWZ.js → chunk-ZTQ7ISUR.js} +28 -109
  11. package/dist/chunk-ZTQ7ISUR.js.map +1 -0
  12. package/dist/cli.js +5493 -7665
  13. package/dist/cli.js.map +1 -1
  14. package/dist/index.d.ts +110 -2
  15. package/dist/index.js +302 -26
  16. package/dist/index.js.map +1 -1
  17. package/dist/{memory-ZXDXF6KF.js → memory-VNF2VFRB.js} +2 -2
  18. package/dist/{sessions-F6LRY7EN.js → sessions-6PB7ALCE.js} +3 -3
  19. package/dist/{squad-parser-MSYE4PXL.js → squad-parser-4BI3G4RS.js} +4 -2
  20. package/dist/templates/seed/BUSINESS_BRIEF.md.template +27 -0
  21. package/dist/templates/seed/CLAUDE.md.template +69 -0
  22. package/dist/templates/seed/config/provider.yaml +4 -0
  23. package/dist/templates/seed/hooks/settings.json.template +31 -0
  24. package/dist/templates/seed/memory/company/manager/state.md +16 -0
  25. package/dist/templates/seed/memory/engineering/issue-solver/state.md +12 -0
  26. package/dist/templates/seed/memory/intelligence/intel-lead/state.md +9 -0
  27. package/dist/templates/seed/memory/marketing/content-drafter/state.md +12 -0
  28. package/dist/templates/seed/memory/operations/ops-lead/state.md +12 -0
  29. package/dist/templates/seed/memory/research/researcher/state.md +10 -0
  30. package/dist/templates/seed/skills/gh/SKILL.md +57 -0
  31. package/dist/templates/seed/skills/squads-cli/SKILL.md +88 -0
  32. package/dist/templates/seed/squads/company/SQUAD.md +49 -0
  33. package/dist/templates/seed/squads/company/company-critic.md +21 -0
  34. package/dist/templates/seed/squads/company/company-eval.md +21 -0
  35. package/dist/templates/seed/squads/company/event-dispatcher.md +21 -0
  36. package/dist/templates/seed/squads/company/goal-tracker.md +21 -0
  37. package/dist/templates/seed/squads/company/manager.md +66 -0
  38. package/dist/templates/seed/squads/engineering/SQUAD.md +48 -0
  39. package/dist/templates/seed/squads/engineering/code-reviewer.md +57 -0
  40. package/dist/templates/seed/squads/engineering/issue-solver.md +58 -0
  41. package/dist/templates/seed/squads/engineering/test-writer.md +50 -0
  42. package/dist/templates/seed/squads/intelligence/SQUAD.md +37 -0
  43. package/dist/templates/seed/squads/intelligence/intel-critic.md +36 -0
  44. package/dist/templates/seed/squads/intelligence/intel-eval.md +31 -0
  45. package/dist/templates/seed/squads/intelligence/intel-lead.md +71 -0
  46. package/dist/templates/seed/squads/marketing/SQUAD.md +47 -0
  47. package/dist/templates/seed/squads/marketing/content-drafter.md +71 -0
  48. package/dist/templates/seed/squads/marketing/growth-analyst.md +49 -0
  49. package/dist/templates/seed/squads/marketing/social-poster.md +44 -0
  50. package/dist/templates/seed/squads/operations/SQUAD.md +45 -0
  51. package/dist/templates/seed/squads/operations/finance-tracker.md +47 -0
  52. package/dist/templates/seed/squads/operations/goal-tracker.md +48 -0
  53. package/dist/templates/seed/squads/operations/ops-lead.md +58 -0
  54. package/dist/templates/seed/squads/research/SQUAD.md +38 -0
  55. package/dist/templates/seed/squads/research/analyst.md +27 -0
  56. package/dist/templates/seed/squads/research/research-critic.md +20 -0
  57. package/dist/templates/seed/squads/research/research-eval.md +20 -0
  58. package/dist/templates/seed/squads/research/researcher.md +28 -0
  59. package/dist/{terminal-JZSAQSN7.js → terminal-YKA4O5CX.js} +4 -2
  60. package/dist/{update-MAY6EXFQ.js → update-ALJKFFM7.js} +3 -2
  61. package/package.json +9 -22
  62. package/templates/seed/BUSINESS_BRIEF.md.template +27 -0
  63. package/templates/seed/CLAUDE.md.template +69 -0
  64. package/templates/seed/config/provider.yaml +4 -0
  65. package/templates/seed/hooks/settings.json.template +31 -0
  66. package/templates/seed/memory/company/manager/state.md +16 -0
  67. package/templates/seed/memory/engineering/issue-solver/state.md +12 -0
  68. package/templates/seed/memory/intelligence/intel-lead/state.md +9 -0
  69. package/templates/seed/memory/marketing/content-drafter/state.md +12 -0
  70. package/templates/seed/memory/operations/ops-lead/state.md +12 -0
  71. package/templates/seed/memory/research/researcher/state.md +10 -0
  72. package/templates/seed/skills/gh/SKILL.md +57 -0
  73. package/templates/seed/skills/squads-cli/SKILL.md +88 -0
  74. package/templates/seed/squads/company/SQUAD.md +49 -0
  75. package/templates/seed/squads/company/company-critic.md +21 -0
  76. package/templates/seed/squads/company/company-eval.md +21 -0
  77. package/templates/seed/squads/company/event-dispatcher.md +21 -0
  78. package/templates/seed/squads/company/goal-tracker.md +21 -0
  79. package/templates/seed/squads/company/manager.md +66 -0
  80. package/templates/seed/squads/engineering/SQUAD.md +48 -0
  81. package/templates/seed/squads/engineering/code-reviewer.md +57 -0
  82. package/templates/seed/squads/engineering/issue-solver.md +58 -0
  83. package/templates/seed/squads/engineering/test-writer.md +50 -0
  84. package/templates/seed/squads/intelligence/SQUAD.md +37 -0
  85. package/templates/seed/squads/intelligence/intel-critic.md +36 -0
  86. package/templates/seed/squads/intelligence/intel-eval.md +31 -0
  87. package/templates/seed/squads/intelligence/intel-lead.md +71 -0
  88. package/templates/seed/squads/marketing/SQUAD.md +47 -0
  89. package/templates/seed/squads/marketing/content-drafter.md +71 -0
  90. package/templates/seed/squads/marketing/growth-analyst.md +49 -0
  91. package/templates/seed/squads/marketing/social-poster.md +44 -0
  92. package/templates/seed/squads/operations/SQUAD.md +45 -0
  93. package/templates/seed/squads/operations/finance-tracker.md +47 -0
  94. package/templates/seed/squads/operations/goal-tracker.md +48 -0
  95. package/templates/seed/squads/operations/ops-lead.md +58 -0
  96. package/templates/seed/squads/research/SQUAD.md +38 -0
  97. package/templates/seed/squads/research/analyst.md +27 -0
  98. package/templates/seed/squads/research/research-critic.md +20 -0
  99. package/templates/seed/squads/research/research-eval.md +20 -0
  100. package/templates/seed/squads/research/researcher.md +28 -0
  101. package/dist/chunk-7PRYDHZW.js.map +0 -1
  102. package/dist/chunk-BV6S5AWZ.js.map +0 -1
  103. package/dist/chunk-HKWCBCEK.js.map +0 -1
  104. package/dist/chunk-NA3IECJA.js.map +0 -1
  105. package/dist/chunk-QPH5OR7J.js.map +0 -1
  106. package/docker/.env.example +0 -17
  107. package/docker/README.md +0 -92
  108. package/docker/docker-compose.engram.yml +0 -304
  109. package/docker/docker-compose.yml +0 -250
  110. package/docker/init-db.sql +0 -478
  111. package/docker/init-engram-db.sql +0 -148
  112. package/docker/init-langfuse-db.sh +0 -10
  113. package/docker/otel-collector.yaml +0 -34
  114. package/docker/squads-bridge/Dockerfile +0 -14
  115. package/docker/squads-bridge/Dockerfile.proxy +0 -14
  116. package/docker/squads-bridge/anthropic_proxy.py +0 -313
  117. package/docker/squads-bridge/requirements.txt +0 -7
  118. package/docker/squads-bridge/squads_bridge.py +0 -2299
  119. package/docker/telemetry-ping/Dockerfile +0 -10
  120. package/docker/telemetry-ping/deploy.sh +0 -69
  121. package/docker/telemetry-ping/main.py +0 -136
  122. package/docker/telemetry-ping/requirements.txt +0 -3
  123. /package/dist/{memory-ZXDXF6KF.js.map → memory-VNF2VFRB.js.map} +0 -0
  124. /package/dist/{sessions-F6LRY7EN.js.map → sessions-6PB7ALCE.js.map} +0 -0
  125. /package/dist/{squad-parser-MSYE4PXL.js.map → squad-parser-4BI3G4RS.js.map} +0 -0
  126. /package/dist/{terminal-JZSAQSN7.js.map → terminal-YKA4O5CX.js.map} +0 -0
  127. /package/dist/{update-MAY6EXFQ.js.map → update-ALJKFFM7.js.map} +0 -0
@@ -4,47 +4,19 @@ import {
4
4
  } from "./chunk-7OCVIDC7.js";
5
5
 
6
6
  // src/lib/memory.ts
7
- import { readFileSync, writeFileSync as writeFileSync2, existsSync as existsSync2, readdirSync, mkdirSync as mkdirSync2 } from "fs";
7
+ import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, existsSync as existsSync2, readdirSync, mkdirSync as mkdirSync2 } from "fs";
8
8
  import { join as join2, dirname as dirname2 } from "path";
9
9
 
10
10
  // src/lib/lock.ts
11
- import Redis from "ioredis";
12
- import { existsSync, writeFileSync, unlinkSync, mkdirSync } from "fs";
11
+ import { existsSync, writeFileSync, unlinkSync, mkdirSync, statSync, readFileSync, openSync, closeSync } from "fs";
13
12
  import { join, dirname } from "path";
14
13
  import { createHash } from "crypto";
15
14
  var LOCK_TTL_MS = 3e4;
16
15
  var LOCK_RETRY_DELAY_MS = 100;
17
16
  var LOCK_MAX_RETRIES = 50;
18
- var redisClient = null;
19
- var redisAvailable = null;
20
- async function getRedis() {
21
- if (redisAvailable === false) return null;
22
- if (!redisClient) {
23
- try {
24
- redisClient = new Redis({
25
- host: process.env.REDIS_HOST || "localhost",
26
- port: parseInt(process.env.REDIS_PORT || "6379"),
27
- connectTimeout: 1e3,
28
- maxRetriesPerRequest: 1,
29
- lazyConnect: true
30
- });
31
- await redisClient.connect();
32
- redisAvailable = true;
33
- } catch {
34
- redisAvailable = false;
35
- redisClient = null;
36
- return null;
37
- }
38
- }
39
- return redisClient;
40
- }
41
17
  function generateLockId() {
42
18
  return `${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
43
19
  }
44
- function getLockKey(filePath) {
45
- const hash = createHash("md5").update(filePath).digest("hex").slice(0, 12);
46
- return `squads:lock:${hash}`;
47
- }
48
20
  function getFileLockPath(filePath) {
49
21
  const lockDir = join(dirname(filePath), ".locks");
50
22
  const hash = createHash("md5").update(filePath).digest("hex").slice(0, 12);
@@ -53,33 +25,6 @@ function getFileLockPath(filePath) {
53
25
  function sleep(ms) {
54
26
  return new Promise((resolve) => setTimeout(resolve, ms));
55
27
  }
56
- async function acquireRedisLock(key, lockId) {
57
- const redis = await getRedis();
58
- if (!redis) return false;
59
- try {
60
- const result = await redis.set(key, lockId, "PX", LOCK_TTL_MS, "NX");
61
- return result === "OK";
62
- } catch {
63
- return false;
64
- }
65
- }
66
- async function releaseRedisLock(key, lockId) {
67
- const redis = await getRedis();
68
- if (!redis) return false;
69
- try {
70
- const script = `
71
- if redis.call("get", KEYS[1]) == ARGV[1] then
72
- return redis.call("del", KEYS[1])
73
- else
74
- return 0
75
- end
76
- `;
77
- const result = await redis.eval(script, 1, key, lockId);
78
- return result === 1;
79
- } catch {
80
- return false;
81
- }
82
- }
83
28
  function acquireFileLock(lockPath, lockId) {
84
29
  try {
85
30
  const lockDir = dirname(lockPath);
@@ -87,7 +32,6 @@ function acquireFileLock(lockPath, lockId) {
87
32
  mkdirSync(lockDir, { recursive: true });
88
33
  }
89
34
  if (existsSync(lockPath)) {
90
- const { statSync, readFileSync: readFileSync2 } = __require("fs");
91
35
  const stats = statSync(lockPath);
92
36
  const ageMs = Date.now() - stats.mtimeMs;
93
37
  if (ageMs > LOCK_TTL_MS) {
@@ -96,7 +40,6 @@ function acquireFileLock(lockPath, lockId) {
96
40
  return false;
97
41
  }
98
42
  }
99
- const { openSync, closeSync } = __require("fs");
100
43
  const fd = openSync(lockPath, "wx");
101
44
  writeFileSync(fd, lockId);
102
45
  closeSync(fd);
@@ -108,8 +51,7 @@ function acquireFileLock(lockPath, lockId) {
108
51
  function releaseFileLock(lockPath, lockId) {
109
52
  try {
110
53
  if (!existsSync(lockPath)) return true;
111
- const { readFileSync: readFileSync2 } = __require("fs");
112
- const currentId = readFileSync2(lockPath, "utf-8").trim();
54
+ const currentId = readFileSync(lockPath, "utf-8").trim();
113
55
  if (currentId === lockId) {
114
56
  unlinkSync(lockPath);
115
57
  return true;
@@ -121,51 +63,22 @@ function releaseFileLock(lockPath, lockId) {
121
63
  }
122
64
  async function acquireLock(filePath) {
123
65
  const lockId = generateLockId();
124
- const redisKey = getLockKey(filePath);
125
66
  const fileLockPath = getFileLockPath(filePath);
126
- let useRedis = false;
67
+ let gotLock = false;
127
68
  for (let attempt = 0; attempt < LOCK_MAX_RETRIES; attempt++) {
128
- if (await acquireRedisLock(redisKey, lockId)) {
129
- useRedis = true;
130
- break;
131
- }
132
- if (redisAvailable === false && acquireFileLock(fileLockPath, lockId)) {
133
- useRedis = false;
69
+ if (acquireFileLock(fileLockPath, lockId)) {
70
+ gotLock = true;
134
71
  break;
135
72
  }
136
73
  if (attempt < LOCK_MAX_RETRIES - 1) {
137
74
  await sleep(LOCK_RETRY_DELAY_MS);
138
75
  }
139
76
  }
140
- const redis = await getRedis();
141
- let gotLock = false;
142
- if (redis) {
143
- try {
144
- const currentOwner = await redis.get(redisKey);
145
- gotLock = currentOwner === lockId;
146
- } catch {
147
- gotLock = false;
148
- }
149
- } else {
150
- try {
151
- if (existsSync(fileLockPath)) {
152
- const { readFileSync: readFileSync2 } = __require("fs");
153
- const currentId = readFileSync2(fileLockPath, "utf-8").trim();
154
- gotLock = currentId === lockId;
155
- }
156
- } catch {
157
- gotLock = false;
158
- }
159
- }
160
77
  if (!gotLock) {
161
78
  return null;
162
79
  }
163
80
  return async () => {
164
- if (useRedis) {
165
- await releaseRedisLock(redisKey, lockId);
166
- } else {
167
- releaseFileLock(fileLockPath, lockId);
168
- }
81
+ releaseFileLock(fileLockPath, lockId);
169
82
  };
170
83
  }
171
84
  async function withLock(filePath, fn) {
@@ -210,7 +123,7 @@ function listMemoryEntries(memoryDir) {
210
123
  squad,
211
124
  agent,
212
125
  type,
213
- content: readFileSync(filePath, "utf-8"),
126
+ content: readFileSync2(filePath, "utf-8"),
214
127
  path: filePath
215
128
  });
216
129
  }
@@ -244,8 +157,8 @@ function expandQuery(query) {
244
157
  }
245
158
  function getFileAge(filePath) {
246
159
  try {
247
- const { statSync } = __require("fs");
248
- const stats = statSync(filePath);
160
+ const { statSync: statSync2 } = __require("fs");
161
+ const stats = statSync2(filePath);
249
162
  const ageMs = Date.now() - stats.mtimeMs;
250
163
  const ageDays = ageMs / (1e3 * 60 * 60 * 24);
251
164
  return ageDays;
@@ -328,7 +241,7 @@ function getSquadState(squadName) {
328
241
  squad: squadName,
329
242
  agent,
330
243
  type: "state",
331
- content: readFileSync(statePath, "utf-8"),
244
+ content: readFileSync2(statePath, "utf-8"),
332
245
  path: statePath
333
246
  });
334
247
  }
@@ -370,15 +283,18 @@ async function appendToMemory(squadName, agentName, type, addition) {
370
283
  await withLock(filePath, () => {
371
284
  let existing = "";
372
285
  if (existsSync2(filePath)) {
373
- existing = readFileSync(filePath, "utf-8");
286
+ existing = readFileSync2(filePath, "utf-8");
374
287
  }
375
288
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
376
- const newContent = existing + `
289
+ const lines = addition.trim().split("\n");
290
+ const heading = lines[0].replace(/^#+\s*/, "").replace(/^\*\*/, "").replace(/\*\*$/, "");
291
+ const body = lines.slice(1).join("\n").trim();
292
+ const entry = body ? `## ${timestamp}: ${heading}
377
293
 
378
- ---
379
- _Added: ${timestamp}_
294
+ ${body}` : `## ${timestamp}: ${heading}`;
295
+ const newContent = existing + `
380
296
 
381
- ${addition}`;
297
+ ${entry}`;
382
298
  const dir = dirname2(filePath);
383
299
  if (!existsSync2(dir)) {
384
300
  mkdirSync2(dir, { recursive: true });
@@ -394,15 +310,18 @@ function appendToMemorySync(squadName, agentName, type, addition) {
394
310
  const filePath = join2(memoryDir, squadName, agentName, `${type}.md`);
395
311
  let existing = "";
396
312
  if (existsSync2(filePath)) {
397
- existing = readFileSync(filePath, "utf-8");
313
+ existing = readFileSync2(filePath, "utf-8");
398
314
  }
399
315
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
400
- const newContent = existing + `
316
+ const lines = addition.trim().split("\n");
317
+ const heading = lines[0].replace(/^#+\s*/, "").replace(/^\*\*/, "").replace(/\*\*$/, "");
318
+ const body = lines.slice(1).join("\n").trim();
319
+ const entry = body ? `## ${timestamp}: ${heading}
401
320
 
402
- ---
403
- _Added: ${timestamp}_
321
+ ${body}` : `## ${timestamp}: ${heading}`;
322
+ const newContent = existing + `
404
323
 
405
- ${addition}`;
324
+ ${entry}`;
406
325
  updateMemorySync(squadName, agentName, type, newContent.trim());
407
326
  }
408
327
 
@@ -416,4 +335,4 @@ export {
416
335
  appendToMemory,
417
336
  appendToMemorySync
418
337
  };
419
- //# sourceMappingURL=chunk-BV6S5AWZ.js.map
338
+ //# sourceMappingURL=chunk-ZTQ7ISUR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/memory.ts","../src/lib/lock.ts"],"sourcesContent":["import { readFileSync, writeFileSync, existsSync, readdirSync, mkdirSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { withLock } from './lock.js';\n\nexport interface MemoryEntry {\n squad: string;\n agent: string;\n type: 'state' | 'output' | 'learnings' | 'feedback';\n content: string;\n path: string;\n lastUpdated?: string;\n}\n\nexport interface SearchResult {\n entry: MemoryEntry;\n matches: string[];\n score: number;\n}\n\nexport function findMemoryDir(): string | null {\n let dir = process.cwd();\n\n for (let i = 0; i < 5; i++) {\n const memoryPath = join(dir, '.agents', 'memory');\n if (existsSync(memoryPath)) {\n return memoryPath;\n }\n const parent = join(dir, '..');\n if (parent === dir) break;\n dir = parent;\n }\n\n return null;\n}\n\nexport function listMemoryEntries(memoryDir: string): MemoryEntry[] {\n const entries: MemoryEntry[] = [];\n\n const squads = readdirSync(memoryDir, { withFileTypes: true })\n .filter(e => e.isDirectory())\n .map(e => e.name);\n\n for (const squad of squads) {\n const squadPath = join(memoryDir, squad);\n const agents = readdirSync(squadPath, { withFileTypes: true })\n .filter(e => e.isDirectory())\n .map(e => e.name);\n\n for (const agent of agents) {\n const agentPath = join(squadPath, agent);\n const files = readdirSync(agentPath).filter(f => f.endsWith('.md'));\n\n for (const file of files) {\n const filePath = join(agentPath, file);\n const type = file.replace('.md', '') as MemoryEntry['type'];\n\n entries.push({\n squad,\n agent,\n type,\n content: readFileSync(filePath, 'utf-8'),\n path: filePath\n });\n }\n }\n }\n\n return entries;\n}\n\n// Semantic expansions for common business terms\nconst SEMANTIC_EXPANSIONS: Record<string, string[]> = {\n 'pricing': ['price', 'cost', '$', 'revenue', 'fee', 'rate'],\n 'price': ['pricing', 'cost', '$', 'fee'],\n 'revenue': ['income', 'sales', 'mrr', 'arr', '$'],\n 'cost': ['expense', 'spend', 'budget', '$', 'price'],\n 'customer': ['client', 'lead', 'prospect', 'user'],\n 'client': ['customer', 'lead', 'prospect'],\n 'lead': ['prospect', 'customer', 'client', 'pipeline'],\n 'agent': ['squad', 'bot', 'ai'],\n 'squad': ['team', 'agent', 'group'],\n 'status': ['state', 'progress', 'health'],\n 'bug': ['issue', 'error', 'problem', 'fix'],\n 'feature': ['capability', 'function', 'ability'],\n};\n\nfunction expandQuery(query: string): string[] {\n const words = query.toLowerCase().split(/\\s+/);\n const expanded = new Set(words);\n\n for (const word of words) {\n if (SEMANTIC_EXPANSIONS[word]) {\n SEMANTIC_EXPANSIONS[word].forEach(syn => expanded.add(syn));\n }\n }\n\n return Array.from(expanded);\n}\n\nfunction getFileAge(filePath: string): number {\n try {\n const { statSync } = require('fs');\n const stats = statSync(filePath);\n const ageMs = Date.now() - stats.mtimeMs;\n const ageDays = ageMs / (1000 * 60 * 60 * 24);\n return ageDays;\n } catch {\n return 999;\n }\n}\n\nexport function searchMemory(query: string, memoryDir?: string): SearchResult[] {\n const dir = memoryDir || findMemoryDir();\n if (!dir) return [];\n\n const entries = listMemoryEntries(dir);\n const results: SearchResult[] = [];\n const queryLower = query.toLowerCase();\n const expandedTerms = expandQuery(queryLower);\n\n for (const entry of entries) {\n const contentLower = entry.content.toLowerCase();\n const lines = entry.content.split('\\n');\n const matches: string[] = [];\n let score = 0;\n let directHits = 0;\n let expandedHits = 0;\n\n // Check direct query words first\n const directWords = queryLower.split(/\\s+/);\n for (const word of directWords) {\n if (contentLower.includes(word)) {\n directHits += 1;\n score += 2; // Direct matches worth more\n }\n }\n\n // Check expanded terms\n for (const term of expandedTerms) {\n if (contentLower.includes(term)) {\n expandedHits += 1;\n score += 0.5; // Expanded matches worth less but still count\n\n // Find matching lines with context\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (line.toLowerCase().includes(term) && line.trim() && !matches.includes(line.trim())) {\n matches.push(line.trim());\n }\n }\n }\n }\n\n // Boost score for exact phrase match\n if (contentLower.includes(queryLower)) {\n score += 5;\n }\n\n // Recency boost - files updated recently are more relevant\n const ageDays = getFileAge(entry.path);\n if (ageDays < 1) {\n score *= 1.5; // Updated today\n } else if (ageDays < 7) {\n score *= 1.2; // Updated this week\n } else if (ageDays > 30) {\n score *= 0.8; // Stale data penalty\n }\n\n // Type weighting - balanced across types\n const typeWeights: Record<string, number> = {\n 'state': 1.2, // Current state slightly preferred\n 'learnings': 1.1, // Learnings are valuable\n 'output': 1.0, // Recent outputs\n 'feedback': 0.9, // Feedback less commonly needed\n };\n score *= typeWeights[entry.type] || 1.0;\n\n if (score > 0 && (directHits > 0 || expandedHits > 1)) {\n results.push({ entry, matches: matches.slice(0, 7), score });\n }\n }\n\n // Sort by score descending\n return results.sort((a, b) => b.score - a.score);\n}\n\nexport function getSquadState(squadName: string): MemoryEntry[] {\n const memoryDir = findMemoryDir();\n if (!memoryDir) return [];\n\n const squadPath = join(memoryDir, squadName);\n if (!existsSync(squadPath)) return [];\n\n const entries: MemoryEntry[] = [];\n const agents = readdirSync(squadPath, { withFileTypes: true })\n .filter(e => e.isDirectory())\n .map(e => e.name);\n\n for (const agent of agents) {\n const statePath = join(squadPath, agent, 'state.md');\n if (existsSync(statePath)) {\n entries.push({\n squad: squadName,\n agent,\n type: 'state',\n content: readFileSync(statePath, 'utf-8'),\n path: statePath\n });\n }\n }\n\n return entries;\n}\n\n/**\n * Update memory file with distributed locking\n * Safe for concurrent access from multiple agents\n */\nexport async function updateMemory(\n squadName: string,\n agentName: string,\n type: MemoryEntry['type'],\n content: string\n): Promise<void> {\n const memoryDir = findMemoryDir();\n if (!memoryDir) {\n throw new Error('No .agents/memory directory found');\n }\n\n const filePath = join(memoryDir, squadName, agentName, `${type}.md`);\n const dir = dirname(filePath);\n\n await withLock(filePath, () => {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(filePath, content);\n });\n}\n\n/**\n * Sync version for backward compatibility (no locking - use with caution)\n * @deprecated Use async updateMemory() for safe concurrent access\n */\nexport function updateMemorySync(\n squadName: string,\n agentName: string,\n type: MemoryEntry['type'],\n content: string\n): void {\n const memoryDir = findMemoryDir();\n if (!memoryDir) {\n throw new Error('No .agents/memory directory found');\n }\n\n const filePath = join(memoryDir, squadName, agentName, `${type}.md`);\n const dir = dirname(filePath);\n\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n writeFileSync(filePath, content);\n}\n\n/**\n * Append to memory file with distributed locking\n * Safe for concurrent access from multiple agents\n */\nexport async function appendToMemory(\n squadName: string,\n agentName: string,\n type: MemoryEntry['type'],\n addition: string\n): Promise<void> {\n const memoryDir = findMemoryDir();\n if (!memoryDir) {\n throw new Error('No .agents/memory directory found');\n }\n\n const filePath = join(memoryDir, squadName, agentName, `${type}.md`);\n\n await withLock(filePath, () => {\n let existing = '';\n if (existsSync(filePath)) {\n existing = readFileSync(filePath, 'utf-8');\n }\n\n const timestamp = new Date().toISOString().split('T')[0];\n // Format: ## YYYY-MM-DD: First line as heading (synthesizer-friendly)\n const lines = addition.trim().split('\\n');\n const heading = lines[0].replace(/^#+\\s*/, '').replace(/^\\*\\*/, '').replace(/\\*\\*$/, '');\n const body = lines.slice(1).join('\\n').trim();\n const entry = body\n ? `## ${timestamp}: ${heading}\\n\\n${body}`\n : `## ${timestamp}: ${heading}`;\n const newContent = existing + `\\n\\n${entry}`;\n\n const dir = dirname(filePath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(filePath, newContent.trim());\n });\n}\n\n/**\n * Sync version for backward compatibility (no locking - use with caution)\n * @deprecated Use async appendToMemory() for safe concurrent access\n */\nexport function appendToMemorySync(\n squadName: string,\n agentName: string,\n type: MemoryEntry['type'],\n addition: string\n): void {\n const memoryDir = findMemoryDir();\n if (!memoryDir) {\n throw new Error('No .agents/memory directory found');\n }\n\n const filePath = join(memoryDir, squadName, agentName, `${type}.md`);\n\n let existing = '';\n if (existsSync(filePath)) {\n existing = readFileSync(filePath, 'utf-8');\n }\n\n const timestamp = new Date().toISOString().split('T')[0];\n // Format: ## YYYY-MM-DD: First line as heading (synthesizer-friendly)\n const lines = addition.trim().split('\\n');\n const heading = lines[0].replace(/^#+\\s*/, '').replace(/^\\*\\*/, '').replace(/\\*\\*$/, '');\n const body = lines.slice(1).join('\\n').trim();\n const entry = body\n ? `## ${timestamp}: ${heading}\\n\\n${body}`\n : `## ${timestamp}: ${heading}`;\n const newContent = existing + `\\n\\n${entry}`;\n\n updateMemorySync(squadName, agentName, type, newContent.trim());\n}\n","/**\n * File-based locking for safe concurrent file access\n */\n\nimport { existsSync, writeFileSync, unlinkSync, mkdirSync, statSync, readFileSync, openSync, closeSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { createHash } from 'crypto';\n\n// Lock configuration\nconst LOCK_TTL_MS = 30000; // 30 seconds max lock hold time\nconst LOCK_RETRY_DELAY_MS = 100;\nconst LOCK_MAX_RETRIES = 50; // 5 seconds max wait\n\n/**\n * Generate a unique lock ID for this process\n */\nfunction generateLockId(): string {\n return `${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n}\n\n/**\n * Get file lock path\n */\nfunction getFileLockPath(filePath: string): string {\n const lockDir = join(dirname(filePath), '.locks');\n const hash = createHash('md5').update(filePath).digest('hex').slice(0, 12);\n return join(lockDir, `${hash}.lock`);\n}\n\n/**\n * Sleep helper\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * Acquire a file-based lock\n */\nfunction acquireFileLock(lockPath: string, lockId: string): boolean {\n try {\n const lockDir = dirname(lockPath);\n if (!existsSync(lockDir)) {\n mkdirSync(lockDir, { recursive: true });\n }\n\n // Check if lock exists and is still valid\n if (existsSync(lockPath)) {\n const stats = statSync(lockPath);\n const ageMs = Date.now() - stats.mtimeMs;\n\n // Lock expired - clean it up\n if (ageMs > LOCK_TTL_MS) {\n unlinkSync(lockPath);\n } else {\n return false; // Lock held by another process\n }\n }\n\n // Create lock file atomically using O_EXCL flag\n const fd = openSync(lockPath, 'wx');\n writeFileSync(fd, lockId);\n closeSync(fd);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Release a file-based lock\n */\nfunction releaseFileLock(lockPath: string, lockId: string): boolean {\n try {\n if (!existsSync(lockPath)) return true;\n\n const currentId = readFileSync(lockPath, 'utf-8').trim();\n\n if (currentId === lockId) {\n unlinkSync(lockPath);\n return true;\n }\n return false;\n } catch {\n return false;\n }\n}\n\n/**\n * Acquire a lock for a file path\n * Returns a release function, or null if lock couldn't be acquired\n */\nexport async function acquireLock(filePath: string): Promise<(() => Promise<void>) | null> {\n const lockId = generateLockId();\n const fileLockPath = getFileLockPath(filePath);\n\n let gotLock = false;\n\n for (let attempt = 0; attempt < LOCK_MAX_RETRIES; attempt++) {\n if (acquireFileLock(fileLockPath, lockId)) {\n gotLock = true;\n break;\n }\n\n // Wait and retry\n if (attempt < LOCK_MAX_RETRIES - 1) {\n await sleep(LOCK_RETRY_DELAY_MS);\n }\n }\n\n if (!gotLock) {\n return null;\n }\n\n // Return release function\n return async () => {\n releaseFileLock(fileLockPath, lockId);\n };\n}\n\n/**\n * Execute a function while holding a lock\n * Automatically acquires and releases the lock\n */\nexport async function withLock<T>(\n filePath: string,\n fn: () => T | Promise<T>\n): Promise<T> {\n const release = await acquireLock(filePath);\n\n if (!release) {\n throw new Error(`Failed to acquire lock for: ${filePath}`);\n }\n\n try {\n return await fn();\n } finally {\n await release();\n }\n}\n\n/**\n * Graceful shutdown - no-op (file locks don't need explicit cleanup)\n */\nexport async function closeLockClient(): Promise<void> {\n // No-op: file-based locks are self-cleaning via TTL\n}\n"],"mappings":"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","names":["readFileSync","writeFileSync","existsSync","mkdirSync","join","dirname","join","existsSync","readFileSync","statSync","dirname","mkdirSync","writeFileSync"]}