agent-working-memory 0.5.5 → 0.6.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 (82) hide show
  1. package/README.md +428 -399
  2. package/dist/api/routes.d.ts.map +1 -1
  3. package/dist/api/routes.js +60 -5
  4. package/dist/api/routes.js.map +1 -1
  5. package/dist/cli.js +468 -68
  6. package/dist/cli.js.map +1 -1
  7. package/dist/coordination/index.d.ts +11 -0
  8. package/dist/coordination/index.d.ts.map +1 -0
  9. package/dist/coordination/index.js +39 -0
  10. package/dist/coordination/index.js.map +1 -0
  11. package/dist/coordination/mcp-tools.d.ts +8 -0
  12. package/dist/coordination/mcp-tools.d.ts.map +1 -0
  13. package/dist/coordination/mcp-tools.js +221 -0
  14. package/dist/coordination/mcp-tools.js.map +1 -0
  15. package/dist/coordination/routes.d.ts +9 -0
  16. package/dist/coordination/routes.d.ts.map +1 -0
  17. package/dist/coordination/routes.js +573 -0
  18. package/dist/coordination/routes.js.map +1 -0
  19. package/dist/coordination/schema.d.ts +12 -0
  20. package/dist/coordination/schema.d.ts.map +1 -0
  21. package/dist/coordination/schema.js +125 -0
  22. package/dist/coordination/schema.js.map +1 -0
  23. package/dist/coordination/schemas.d.ts +227 -0
  24. package/dist/coordination/schemas.d.ts.map +1 -0
  25. package/dist/coordination/schemas.js +125 -0
  26. package/dist/coordination/schemas.js.map +1 -0
  27. package/dist/coordination/stale.d.ts +27 -0
  28. package/dist/coordination/stale.d.ts.map +1 -0
  29. package/dist/coordination/stale.js +58 -0
  30. package/dist/coordination/stale.js.map +1 -0
  31. package/dist/engine/activation.d.ts.map +1 -1
  32. package/dist/engine/activation.js +119 -23
  33. package/dist/engine/activation.js.map +1 -1
  34. package/dist/engine/consolidation.d.ts.map +1 -1
  35. package/dist/engine/consolidation.js +27 -6
  36. package/dist/engine/consolidation.js.map +1 -1
  37. package/dist/index.js +100 -4
  38. package/dist/index.js.map +1 -1
  39. package/dist/mcp.js +149 -80
  40. package/dist/mcp.js.map +1 -1
  41. package/dist/storage/sqlite.d.ts +21 -0
  42. package/dist/storage/sqlite.d.ts.map +1 -1
  43. package/dist/storage/sqlite.js +331 -282
  44. package/dist/storage/sqlite.js.map +1 -1
  45. package/dist/types/engram.d.ts +24 -0
  46. package/dist/types/engram.d.ts.map +1 -1
  47. package/dist/types/engram.js.map +1 -1
  48. package/package.json +57 -55
  49. package/src/api/index.ts +3 -3
  50. package/src/api/routes.ts +600 -536
  51. package/src/cli.ts +850 -397
  52. package/src/coordination/index.ts +47 -0
  53. package/src/coordination/mcp-tools.ts +318 -0
  54. package/src/coordination/routes.ts +846 -0
  55. package/src/coordination/schema.ts +120 -0
  56. package/src/coordination/schemas.ts +155 -0
  57. package/src/coordination/stale.ts +97 -0
  58. package/src/core/decay.ts +63 -63
  59. package/src/core/embeddings.ts +88 -88
  60. package/src/core/hebbian.ts +93 -93
  61. package/src/core/index.ts +5 -5
  62. package/src/core/logger.ts +36 -36
  63. package/src/core/query-expander.ts +66 -66
  64. package/src/core/reranker.ts +101 -101
  65. package/src/engine/activation.ts +758 -656
  66. package/src/engine/connections.ts +103 -103
  67. package/src/engine/consolidation-scheduler.ts +125 -125
  68. package/src/engine/consolidation.ts +29 -6
  69. package/src/engine/eval.ts +102 -102
  70. package/src/engine/eviction.ts +101 -101
  71. package/src/engine/index.ts +8 -8
  72. package/src/engine/retraction.ts +100 -100
  73. package/src/engine/staging.ts +74 -74
  74. package/src/index.ts +208 -121
  75. package/src/mcp.ts +1093 -1013
  76. package/src/storage/index.ts +3 -3
  77. package/src/storage/sqlite.ts +1017 -963
  78. package/src/types/agent.ts +67 -67
  79. package/src/types/checkpoint.ts +46 -46
  80. package/src/types/engram.ts +245 -217
  81. package/src/types/eval.ts +100 -100
  82. package/src/types/index.ts +6 -6
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // Copyright 2026 Robert Winter / Complete Ideas
2
2
  // SPDX-License-Identifier: Apache-2.0
3
- import { readFileSync, copyFileSync, existsSync, mkdirSync } from 'node:fs';
3
+ import { readFileSync, copyFileSync, existsSync, mkdirSync, readdirSync, unlinkSync } from 'node:fs';
4
4
  import { resolve, dirname, basename } from 'node:path';
5
5
  import Fastify from 'fastify';
6
6
  // Load .env file if present (no external dependency)
@@ -59,6 +59,37 @@ async function main() {
59
59
  initLogger(DB_PATH);
60
60
  // Storage
61
61
  const store = new EngramStore(DB_PATH);
62
+ // Integrity check
63
+ const integrity = store.integrityCheck();
64
+ if (!integrity.ok) {
65
+ console.error(`DB integrity check FAILED: ${integrity.result}`);
66
+ // Close corrupt DB, restore from backup, and exit for process manager to restart
67
+ store.close();
68
+ const dbDir = dirname(resolve(DB_PATH));
69
+ const backupDir = resolve(dbDir, 'backups');
70
+ if (existsSync(backupDir)) {
71
+ const backups = readdirSync(backupDir)
72
+ .filter(f => f.endsWith('.db'))
73
+ .sort()
74
+ .reverse();
75
+ if (backups.length > 0) {
76
+ const restorePath = resolve(backupDir, backups[0]);
77
+ console.error(`Attempting restore from: ${restorePath}`);
78
+ try {
79
+ copyFileSync(restorePath, resolve(DB_PATH));
80
+ console.error('Restore complete — exiting for restart with restored DB');
81
+ process.exit(1);
82
+ }
83
+ catch (restoreErr) {
84
+ console.error(`Restore failed: ${restoreErr.message}`);
85
+ }
86
+ }
87
+ }
88
+ console.error('No backup available — continuing with potentially corrupt DB');
89
+ }
90
+ else {
91
+ console.log(' DB integrity check: ok');
92
+ }
62
93
  // Engines
63
94
  const activationEngine = new ActivationEngine(store);
64
95
  const connectionEngine = new ConnectionEngine(store, activationEngine);
@@ -68,8 +99,8 @@ async function main() {
68
99
  const evalEngine = new EvalEngine(store);
69
100
  const consolidationEngine = new ConsolidationEngine(store);
70
101
  const consolidationScheduler = new ConsolidationScheduler(store, consolidationEngine);
71
- // API
72
- const app = Fastify({ logger: true });
102
+ // API — disable Fastify's default request logging (too noisy for hive polling)
103
+ const app = Fastify({ logger: false });
73
104
  // Bearer token auth — only enforced when AWM_API_KEY is explicitly set and non-empty
74
105
  if (API_KEY && API_KEY !== 'NONE' && API_KEY.length > 1) {
75
106
  app.addHook('onRequest', async (req, reply) => {
@@ -88,20 +119,85 @@ async function main() {
88
119
  evictionEngine, retractionEngine, evalEngine,
89
120
  consolidationEngine, consolidationScheduler,
90
121
  });
122
+ // Coordination module (opt-in via AWM_COORDINATION=true)
123
+ let heartbeatPruneTimer = null;
124
+ const { isCoordinationEnabled, initCoordination } = await import('./coordination/index.js');
125
+ if (isCoordinationEnabled()) {
126
+ initCoordination(app, store.getDb());
127
+ // Prune stale heartbeat events every 30s (keeps assignment/command events permanently)
128
+ // Purge dead agents older than 24h every 30s to prevent table bloat
129
+ const { pruneOldHeartbeats, purgeDeadAgents } = await import('./coordination/stale.js');
130
+ heartbeatPruneTimer = setInterval(() => {
131
+ const pruned = pruneOldHeartbeats(store.getDb());
132
+ if (pruned > 0)
133
+ console.log(`[coordination] pruned ${pruned} old heartbeat event(s)`);
134
+ const purged = purgeDeadAgents(store.getDb());
135
+ if (purged > 0)
136
+ console.log(`[coordination] purged ${purged} dead agent(s) older than 24h`);
137
+ }, 30_000);
138
+ }
139
+ else {
140
+ console.log(' Coordination module disabled (set AWM_COORDINATION=true to enable)');
141
+ }
91
142
  // Background tasks
92
143
  stagingBuffer.start(DEFAULT_AGENT_CONFIG.stagingTtlMs);
93
144
  consolidationScheduler.start();
145
+ // Periodic hot backup every 10 minutes (keep last 6 = 1hr coverage)
146
+ const dbDir = dirname(resolve(DB_PATH));
147
+ const backupDir = resolve(dbDir, 'backups');
148
+ mkdirSync(backupDir, { recursive: true });
149
+ // Cleanup old backups on startup (older than 2 hours)
150
+ try {
151
+ const TWO_HOURS_MS = 2 * 60 * 60 * 1000;
152
+ const now = Date.now();
153
+ for (const f of readdirSync(backupDir).filter(f => f.endsWith('.db'))) {
154
+ const match = f.match(/(\d{4})-(\d{2})-(\d{2})T(\d{2})-(\d{2})-(\d{2})/);
155
+ if (match) {
156
+ const fileDate = new Date(`${match[1]}-${match[2]}-${match[3]}T${match[4]}:${match[5]}:${match[6]}Z`);
157
+ if (now - fileDate.getTime() > TWO_HOURS_MS) {
158
+ unlinkSync(resolve(backupDir, f));
159
+ }
160
+ }
161
+ }
162
+ }
163
+ catch { /* cleanup is non-fatal */ }
164
+ const backupTimer = setInterval(() => {
165
+ try {
166
+ const ts = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
167
+ const backupPath = resolve(backupDir, `${basename(DB_PATH, '.db')}-${ts}.db`);
168
+ store.backup(backupPath);
169
+ // Prune: keep only last 6 backups
170
+ const backups = readdirSync(backupDir).filter(f => f.endsWith('.db')).sort();
171
+ while (backups.length > 6) {
172
+ const old = backups.shift();
173
+ try {
174
+ unlinkSync(resolve(backupDir, old));
175
+ }
176
+ catch { /* non-fatal */ }
177
+ }
178
+ }
179
+ catch (err) {
180
+ console.warn(`[backup] failed: ${err.message}`);
181
+ }
182
+ }, 10 * 60_000); // 10 minutes
94
183
  // Pre-load ML models (downloads on first run: embeddings ~22MB, reranker ~22MB, expander ~80MB)
95
184
  getEmbedder().catch(err => console.warn('Embedding model unavailable:', err.message));
96
185
  getReranker().catch(err => console.warn('Reranker model unavailable:', err.message));
97
186
  getExpander().catch(err => console.warn('Query expander model unavailable:', err.message));
98
187
  // Start server
99
188
  await app.listen({ port: PORT, host: '0.0.0.0' });
100
- console.log(`AgentWorkingMemory v0.5.4 listening on port ${PORT}`);
189
+ console.log(`AgentWorkingMemory v0.6.0 listening on port ${PORT}`);
101
190
  // Graceful shutdown
102
191
  const shutdown = () => {
192
+ clearInterval(backupTimer);
193
+ if (heartbeatPruneTimer)
194
+ clearInterval(heartbeatPruneTimer);
103
195
  consolidationScheduler.stop();
104
196
  stagingBuffer.stop();
197
+ try {
198
+ store.walCheckpoint();
199
+ }
200
+ catch { /* non-fatal */ }
105
201
  store.close();
106
202
  process.exit(0);
107
203
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/mcp.js CHANGED
@@ -66,7 +66,7 @@ import { initLogger, log, getLogPath } from './core/logger.js';
66
66
  const INCOGNITO = process.env.AWM_INCOGNITO === '1' || process.env.AWM_INCOGNITO === 'true';
67
67
  if (INCOGNITO) {
68
68
  console.error('AWM: incognito mode — all memory tools disabled, nothing will be recorded');
69
- const server = new McpServer({ name: 'agent-working-memory', version: '0.5.4' });
69
+ const server = new McpServer({ name: 'agent-working-memory', version: '0.6.0' });
70
70
  const transport = new StdioServerTransport();
71
71
  server.connect(transport).catch(err => {
72
72
  console.error('MCP server failed:', err);
@@ -93,20 +93,39 @@ else {
93
93
  const consolidationScheduler = new ConsolidationScheduler(store, consolidationEngine);
94
94
  stagingBuffer.start(DEFAULT_AGENT_CONFIG.stagingTtlMs);
95
95
  consolidationScheduler.start();
96
+ // Coordination DB handle — set when AWM_COORDINATION=true, used by memory_write for decision propagation
97
+ let coordDb = null;
96
98
  const server = new McpServer({
97
99
  name: 'agent-working-memory',
98
- version: '0.5.4',
100
+ version: '0.6.0',
99
101
  });
102
+ // --- Auto-classification for memory types ---
103
+ function classifyMemoryType(content) {
104
+ const lower = content.toLowerCase();
105
+ // Procedural: how-to, steps, numbered lists
106
+ if (/\bhow to\b|\bsteps?:/i.test(content) || /^\s*\d+[\.\)]\s/m.test(content) || /\bthen run\b|\bfirst,?\s/i.test(content)) {
107
+ return 'procedural';
108
+ }
109
+ // Episodic: past tense events, incidents, specific time references
110
+ if (/\b(discovered|debugged|fixed|encountered|happened|resolved|found that|we did|i did|yesterday|last week|today)\b/i.test(content)) {
111
+ return 'episodic';
112
+ }
113
+ // Semantic: facts, decisions, rules, patterns
114
+ if (/\b(is|are|should|always|never|must|uses?|requires?|means|pattern|decision|rule|convention)\b/i.test(content) && content.length < 500) {
115
+ return 'semantic';
116
+ }
117
+ return 'unclassified';
118
+ }
100
119
  // --- Tools ---
101
- server.tool('memory_write', `Store a memory. The salience filter decides whether it's worth keeping (active), needs more evidence (staging), or should be discarded.
102
-
103
- CALL THIS PROACTIVELY — do not wait to be asked. Write memories when you:
104
- - Discover something about the codebase, bugs, or architecture
105
- - Make a decision and want to remember why
106
- - Encounter and resolve an error
107
- - Learn a user preference or project pattern
108
- - Complete a significant piece of work
109
-
120
+ server.tool('memory_write', `Store a memory. The salience filter decides whether it's worth keeping (active), needs more evidence (staging), or should be discarded.
121
+
122
+ CALL THIS PROACTIVELY — do not wait to be asked. Write memories when you:
123
+ - Discover something about the codebase, bugs, or architecture
124
+ - Make a decision and want to remember why
125
+ - Encounter and resolve an error
126
+ - Learn a user preference or project pattern
127
+ - Complete a significant piece of work
128
+
110
129
  The concept should be a short label (3-8 words). The content should be the full detail.`, {
111
130
  concept: z.string().describe('Short label for this memory (3-8 words)'),
112
131
  content: z.string().describe('Full detail of what was learned'),
@@ -124,6 +143,8 @@ The concept should be a short label (3-8 words). The content should be the full
124
143
  .describe('How much effort to resolve? 0=trivial, 1=significant debugging'),
125
144
  memory_class: z.enum(['canonical', 'working', 'ephemeral']).optional().default('working')
126
145
  .describe('Memory class: canonical (source-of-truth, never stages), working (default), ephemeral (temporary, decays faster)'),
146
+ memory_type: z.enum(['episodic', 'semantic', 'procedural', 'unclassified']).optional()
147
+ .describe('Memory type: episodic (events/incidents), semantic (facts/decisions), procedural (how-to/steps). Auto-classified if omitted.'),
127
148
  supersedes: z.string().optional()
128
149
  .describe('ID of an older memory this one replaces. The old memory is down-ranked, not deleted.'),
129
150
  }, async (params) => {
@@ -190,6 +211,7 @@ The concept should be a short label (3-8 words). The content should be the full
190
211
  : salience.disposition === 'staging'
191
212
  ? 0.40
192
213
  : CONFIDENCE_PRIORS[params.event_type ?? 'observation'] ?? 0.45;
214
+ const memoryType = params.memory_type ?? classifyMemoryType(params.content);
193
215
  const engram = store.createEngram({
194
216
  agentId: AGENT_ID,
195
217
  concept: params.concept,
@@ -201,6 +223,7 @@ The concept should be a short label (3-8 words). The content should be the full
201
223
  reasonCodes: salience.reasonCodes,
202
224
  ttl: salience.disposition === 'staging' ? DEFAULT_AGENT_CONFIG.stagingTtlMs : undefined,
203
225
  memoryClass: params.memory_class,
226
+ memoryType,
204
227
  supersedes: params.supersedes,
205
228
  });
206
229
  if (salience.disposition === 'staging') {
@@ -227,24 +250,35 @@ The concept should be a short label (3-8 words). The content should be the full
227
250
  store.updateAutoCheckpointWrite(AGENT_ID, engram.id);
228
251
  }
229
252
  catch { /* non-fatal */ }
253
+ // Decision propagation: when decision_made=true and coordination is enabled,
254
+ // broadcast to coord_decisions so other agents can discover it
255
+ if (params.decision_made && coordDb) {
256
+ try {
257
+ const agent = coordDb.prepare(`SELECT id, current_task FROM coord_agents WHERE name = ? AND status != 'dead' ORDER BY last_seen DESC LIMIT 1`).get(AGENT_ID);
258
+ if (agent) {
259
+ coordDb.prepare(`INSERT INTO coord_decisions (author_id, assignment_id, tags, summary) VALUES (?, ?, ?, ?)`).run(agent.id, agent.current_task, params.tags ? JSON.stringify(params.tags) : null, params.concept);
260
+ }
261
+ }
262
+ catch { /* decision propagation is non-fatal */ }
263
+ }
230
264
  const logDisposition = isLowSalience ? 'low-salience' : salience.disposition;
231
265
  log(AGENT_ID, `write:${logDisposition}`, `"${params.concept}" salience=${salience.score.toFixed(2)} novelty=${novelty.toFixed(1)} id=${engram.id}`);
232
266
  return {
233
267
  content: [{
234
268
  type: 'text',
235
- text: `Stored (${salience.disposition}) "${params.concept}" [${salience.score.toFixed(2)}]`,
269
+ text: `Stored (${salience.disposition}) "${params.concept}" [${salience.score.toFixed(2)}]\nID: ${engram.id}`,
236
270
  }],
237
271
  };
238
272
  });
239
- server.tool('memory_recall', `Recall memories relevant to a query. Uses cognitive activation — not keyword search.
240
-
241
- ALWAYS call this when:
242
- - Starting work on a project or topic (recall what you know)
243
- - Debugging (recall similar errors and solutions)
244
- - Making decisions (recall past decisions and outcomes)
245
- - The user mentions a topic you might have stored memories about
246
-
247
- Accepts either "query" or "context" parameter — both work identically.
273
+ server.tool('memory_recall', `Recall memories relevant to a query. Uses cognitive activation — not keyword search.
274
+
275
+ ALWAYS call this when:
276
+ - Starting work on a project or topic (recall what you know)
277
+ - Debugging (recall similar errors and solutions)
278
+ - Making decisions (recall past decisions and outcomes)
279
+ - The user mentions a topic you might have stored memories about
280
+
281
+ Accepts either "query" or "context" parameter — both work identically.
248
282
  Returns the most relevant memories ranked by text relevance, temporal recency, and associative strength.`, {
249
283
  query: z.string().optional().describe('What to search for — describe the situation, question, or topic'),
250
284
  context: z.string().optional().describe('Alias for query (either works)'),
@@ -253,6 +287,7 @@ Returns the most relevant memories ranked by text relevance, temporal recency, a
253
287
  include_staging: z.boolean().optional().default(false).describe('Include weak/unconfirmed memories?'),
254
288
  use_reranker: z.boolean().optional().default(true).describe('Use cross-encoder re-ranking for better relevance (default true)'),
255
289
  use_expansion: z.boolean().optional().default(true).describe('Expand query with synonyms for better recall (default true)'),
290
+ memory_type: z.enum(['episodic', 'semantic', 'procedural']).optional().describe('Filter by memory type (omit to search all types)'),
256
291
  }, async (params) => {
257
292
  const queryText = params.query ?? params.context;
258
293
  if (!queryText) {
@@ -271,6 +306,7 @@ Returns the most relevant memories ranked by text relevance, temporal recency, a
271
306
  includeStaging: params.include_staging,
272
307
  useReranker: params.use_reranker,
273
308
  useExpansion: params.use_expansion,
309
+ memoryType: params.memory_type,
274
310
  });
275
311
  // Auto-checkpoint: track recall
276
312
  try {
@@ -297,8 +333,8 @@ Returns the most relevant memories ranked by text relevance, temporal recency, a
297
333
  }],
298
334
  };
299
335
  });
300
- server.tool('memory_feedback', `Report whether a recalled memory was actually useful. This updates the memory's confidence score — useful memories become stronger, useless ones weaken.
301
-
336
+ server.tool('memory_feedback', `Report whether a recalled memory was actually useful. This updates the memory's confidence score — useful memories become stronger, useless ones weaken.
337
+
302
338
  Always call this after using a recalled memory so the system learns what's valuable.`, {
303
339
  engram_id: z.string().describe('ID of the memory (from memory_recall results)'),
304
340
  useful: z.boolean().describe('Was this memory actually helpful?'),
@@ -319,8 +355,8 @@ Always call this after using a recalled memory so the system learns what's valua
319
355
  }],
320
356
  };
321
357
  });
322
- server.tool('memory_retract', `Retract a memory that turned out to be wrong. Creates a correction and reduces confidence of related memories.
323
-
358
+ server.tool('memory_retract', `Retract a memory that turned out to be wrong. Creates a correction and reduces confidence of related memories.
359
+
324
360
  Use this when you discover a memory contains incorrect information.`, {
325
361
  engram_id: z.string().describe('ID of the wrong memory'),
326
362
  reason: z.string().describe('Why is this memory wrong?'),
@@ -344,13 +380,13 @@ Use this when you discover a memory contains incorrect information.`, {
344
380
  }],
345
381
  };
346
382
  });
347
- server.tool('memory_supersede', `Replace an outdated memory with a newer one. Unlike retraction (which marks memories as wrong), supersession marks the old memory as outdated but historically correct.
348
-
349
- Use this when:
350
- - A status or count has changed (e.g., "5 reviews done" → "7 reviews done")
351
- - Architecture or infrastructure evolved (e.g., "two-repo model" → "three-repo model")
352
- - A schedule or plan was updated
353
-
383
+ server.tool('memory_supersede', `Replace an outdated memory with a newer one. Unlike retraction (which marks memories as wrong), supersession marks the old memory as outdated but historically correct.
384
+
385
+ Use this when:
386
+ - A status or count has changed (e.g., "5 reviews done" → "7 reviews done")
387
+ - Architecture or infrastructure evolved (e.g., "two-repo model" → "three-repo model")
388
+ - A schedule or plan was updated
389
+
354
390
  The old memory stays in the database (searchable for history) but is heavily down-ranked in recall so the current version dominates.`, {
355
391
  old_engram_id: z.string().describe('ID of the outdated memory'),
356
392
  new_engram_id: z.string().describe('ID of the replacement memory'),
@@ -377,7 +413,7 @@ The old memory stays in the database (searchable for history) but is heavily dow
377
413
  }],
378
414
  };
379
415
  });
380
- server.tool('memory_stats', `Get memory health stats — how many memories, confidence levels, association count, and system performance.
416
+ server.tool('memory_stats', `Get memory health stats — how many memories, confidence levels, association count, and system performance.
381
417
  Also shows the activity log path so the user can tail it to see what's happening.`, {}, async () => {
382
418
  const metrics = evalEngine.computeMetrics(AGENT_ID);
383
419
  const checkpoint = store.getCheckpoint(AGENT_ID);
@@ -408,13 +444,13 @@ Also shows the activity log path so the user can tail it to see what's happening
408
444
  };
409
445
  });
410
446
  // --- Checkpointing Tools ---
411
- server.tool('memory_checkpoint', `Save your current execution state so you can recover after context compaction.
412
-
413
- ALWAYS call this before:
414
- - Long operations (multi-file generation, large refactors, overnight work)
415
- - Anything that might fill the context window
416
- - Switching to a different task
417
-
447
+ server.tool('memory_checkpoint', `Save your current execution state so you can recover after context compaction.
448
+
449
+ ALWAYS call this before:
450
+ - Long operations (multi-file generation, large refactors, overnight work)
451
+ - Anything that might fill the context window
452
+ - Switching to a different task
453
+
418
454
  Also call periodically during long sessions to avoid losing state. The state is saved per-agent and overwrites any previous checkpoint.`, {
419
455
  current_task: z.string().describe('What you are currently working on'),
420
456
  decisions: z.array(z.string()).optional().default([])
@@ -448,14 +484,14 @@ Also call periodically during long sessions to avoid losing state. The state is
448
484
  }],
449
485
  };
450
486
  });
451
- server.tool('memory_restore', `Restore your previous execution state after context compaction or at session start.
452
-
453
- Returns:
454
- - Your saved execution state (task, decisions, next steps, files)
455
- - Recently recalled memories for context
456
- - Your last write for continuity
457
- - How long you were idle
458
-
487
+ server.tool('memory_restore', `Restore your previous execution state after context compaction or at session start.
488
+
489
+ Returns:
490
+ - Your saved execution state (task, decisions, next steps, files)
491
+ - Recently recalled memories for context
492
+ - Your last write for continuity
493
+ - How long you were idle
494
+
459
495
  Use this at the start of every session or after compaction to pick up where you left off.`, {}, async () => {
460
496
  const checkpoint = store.getCheckpoint(AGENT_ID);
461
497
  const now = Date.now();
@@ -558,6 +594,23 @@ Use this at the start of every session or after compaction to pick up where you
558
594
  parts.push(`- **${m.concept}** (${m.score.toFixed(3)}): ${m.content.slice(0, 150)}${m.content.length > 150 ? '...' : ''}`);
559
595
  }
560
596
  }
597
+ // Peer decisions: show recent decisions from other agents (last 30 min)
598
+ if (coordDb) {
599
+ try {
600
+ const myAgent = coordDb.prepare(`SELECT id FROM coord_agents WHERE name = ? AND status != 'dead' ORDER BY last_seen DESC LIMIT 1`).get(AGENT_ID);
601
+ const peerDecisions = coordDb.prepare(`SELECT d.summary, a.name AS author_name, d.created_at
602
+ FROM coord_decisions d JOIN coord_agents a ON d.author_id = a.id
603
+ WHERE d.author_id != ? AND d.created_at > datetime('now', '-30 minutes')
604
+ ORDER BY d.created_at DESC LIMIT 10`).all(myAgent?.id ?? '');
605
+ if (peerDecisions.length > 0) {
606
+ parts.push(`\n**Peer decisions (last 30 min):**`);
607
+ for (const d of peerDecisions) {
608
+ parts.push(`- [${d.author_name}] ${d.summary} (${d.created_at})`);
609
+ }
610
+ }
611
+ }
612
+ catch { /* peer decisions are non-fatal */ }
613
+ }
561
614
  return {
562
615
  content: [{
563
616
  type: 'text',
@@ -566,13 +619,13 @@ Use this at the start of every session or after compaction to pick up where you
566
619
  };
567
620
  });
568
621
  // --- Task Management Tools ---
569
- server.tool('memory_task_add', `Create a task that you need to come back to. Tasks are memories with status and priority tracking.
570
-
571
- Use this when:
572
- - You identify work that needs doing but can't do it right now
573
- - The user mentions something to do later
574
- - You want to park a sub-task while focusing on something more urgent
575
-
622
+ server.tool('memory_task_add', `Create a task that you need to come back to. Tasks are memories with status and priority tracking.
623
+
624
+ Use this when:
625
+ - You identify work that needs doing but can't do it right now
626
+ - The user mentions something to do later
627
+ - You want to park a sub-task while focusing on something more urgent
628
+
576
629
  Tasks automatically get high salience so they won't be discarded.`, {
577
630
  concept: z.string().describe('Short task title (3-10 words)'),
578
631
  content: z.string().describe('Full task description — what needs doing, context, acceptance criteria'),
@@ -612,11 +665,11 @@ Tasks automatically get high salience so they won't be discarded.`, {
612
665
  }],
613
666
  };
614
667
  });
615
- server.tool('memory_task_update', `Update a task's status or priority. Use this to:
616
- - Start working on a task (open → in_progress)
617
- - Mark a task done (→ done)
618
- - Block a task on another (→ blocked)
619
- - Reprioritize (change priority)
668
+ server.tool('memory_task_update', `Update a task's status or priority. Use this to:
669
+ - Start working on a task (open → in_progress)
670
+ - Mark a task done (→ done)
671
+ - Block a task on another (→ blocked)
672
+ - Reprioritize (change priority)
620
673
  - Unblock a task (clear blocked_by)`, {
621
674
  task_id: z.string().describe('ID of the task to update'),
622
675
  status: z.enum(['open', 'in_progress', 'blocked', 'done']).optional()
@@ -646,8 +699,8 @@ Tasks automatically get high salience so they won't be discarded.`, {
646
699
  }],
647
700
  };
648
701
  });
649
- server.tool('memory_task_list', `List tasks with optional status filter. Shows tasks ordered by priority (urgent first).
650
-
702
+ server.tool('memory_task_list', `List tasks with optional status filter. Shows tasks ordered by priority (urgent first).
703
+
651
704
  Use at the start of a session to see what's pending, or to check blocked/done tasks.`, {
652
705
  status: z.enum(['open', 'in_progress', 'blocked', 'done']).optional()
653
706
  .describe('Filter by status (omit to see all active tasks)'),
@@ -673,10 +726,10 @@ Use at the start of a session to see what's pending, or to check blocked/done ta
673
726
  }],
674
727
  };
675
728
  });
676
- server.tool('memory_task_next', `Get the single most important task to work on next.
677
-
678
- Prioritizes: in_progress tasks first (finish what you started), then by priority level, then oldest first. Skips blocked and done tasks.
679
-
729
+ server.tool('memory_task_next', `Get the single most important task to work on next.
730
+
731
+ Prioritizes: in_progress tasks first (finish what you started), then by priority level, then oldest first. Skips blocked and done tasks.
732
+
680
733
  Use this when you finish a task or need to decide what to do next.`, {}, async () => {
681
734
  const next = store.getNextTask(AGENT_ID);
682
735
  if (!next) {
@@ -692,13 +745,13 @@ Use this when you finish a task or need to decide what to do next.`, {}, async (
692
745
  };
693
746
  });
694
747
  // --- Task Bracket Tools ---
695
- server.tool('memory_task_begin', `Signal that you're starting a significant task. Auto-checkpoints current state and recalls relevant memories.
696
-
697
- CALL THIS when starting:
698
- - A multi-step operation (doc generation, large refactor, migration)
699
- - Work on a new topic or project area
700
- - Anything that might fill the context window
701
-
748
+ server.tool('memory_task_begin', `Signal that you're starting a significant task. Auto-checkpoints current state and recalls relevant memories.
749
+
750
+ CALL THIS when starting:
751
+ - A multi-step operation (doc generation, large refactor, migration)
752
+ - Work on a new topic or project area
753
+ - Anything that might fill the context window
754
+
702
755
  This ensures your state is saved before you start, and primes recall with relevant context.`, {
703
756
  topic: z.string().describe('What task are you starting? (3-15 words)'),
704
757
  files: z.array(z.string()).optional().default([])
@@ -748,13 +801,13 @@ This ensures your state is saved before you start, and primes recall with releva
748
801
  }],
749
802
  };
750
803
  });
751
- server.tool('memory_task_end', `Signal that you've finished a significant task. Writes a summary memory and auto-checkpoints.
752
-
753
- CALL THIS when you finish:
754
- - A multi-step operation
755
- - Before switching to a different topic
756
- - At the end of a work session
757
-
804
+ server.tool('memory_task_end', `Signal that you've finished a significant task. Writes a summary memory and auto-checkpoints.
805
+
806
+ CALL THIS when you finish:
807
+ - A multi-step operation
808
+ - Before switching to a different topic
809
+ - At the end of a work session
810
+
758
811
  This captures what was accomplished so future sessions can recall it.`, {
759
812
  summary: z.string().describe('What was accomplished? Include key outcomes, decisions, and any issues.'),
760
813
  tags: z.array(z.string()).optional().default([])
@@ -844,6 +897,18 @@ This captures what was accomplished so future sessions can recall it.`, {
844
897
  console.error(`[mcp] consolidation done: ${result.edgesStrengthened} strengthened, ${result.memoriesForgotten} forgotten`);
845
898
  },
846
899
  });
900
+ // Coordination MCP tools (opt-in via AWM_COORDINATION=true)
901
+ const coordEnabled = process.env.AWM_COORDINATION === 'true' || process.env.AWM_COORDINATION === '1';
902
+ if (coordEnabled) {
903
+ const { initCoordinationTables } = await import('./coordination/schema.js');
904
+ const { registerCoordinationTools } = await import('./coordination/mcp-tools.js');
905
+ initCoordinationTables(store.getDb());
906
+ registerCoordinationTools(server, store.getDb());
907
+ coordDb = store.getDb();
908
+ }
909
+ else {
910
+ console.error('AWM: coordination tools disabled (set AWM_COORDINATION=true to enable)');
911
+ }
847
912
  // Log to stderr (stdout is reserved for MCP protocol)
848
913
  console.error(`AgentWorkingMemory MCP server started (agent: ${AGENT_ID}, db: ${DB_PATH})`);
849
914
  console.error(`Hook sidecar on 127.0.0.1:${HOOK_PORT}${HOOK_SECRET ? ' (auth enabled)' : ' (no auth — set AWM_HOOK_SECRET)'}`);
@@ -852,6 +917,10 @@ This captures what was accomplished so future sessions can recall it.`, {
852
917
  sidecar.close();
853
918
  consolidationScheduler.stop();
854
919
  stagingBuffer.stop();
920
+ try {
921
+ store.walCheckpoint();
922
+ }
923
+ catch { /* non-fatal */ }
855
924
  store.close();
856
925
  };
857
926
  process.on('SIGINT', () => { cleanup(); process.exit(0); });