Skip to content

feat(communication): Agent Mesh Network — comunicação P2P descentralizada entre agentes#577

Closed
nikolasdehor wants to merge 0 commit intoSynkraAI:mainfrom
nikolasdehor:feat/agent-mesh-network
Closed

feat(communication): Agent Mesh Network — comunicação P2P descentralizada entre agentes#577
nikolasdehor wants to merge 0 commit intoSynkraAI:mainfrom
nikolasdehor:feat/agent-mesh-network

Conversation

@nikolasdehor
Copy link
Contributor

@nikolasdehor nikolasdehor commented Mar 10, 2026

Resumo

Rede mesh descentralizada para comunicação peer-to-peer entre agentes. Sem orquestrador central — agentes se descobrem, formam grupos ad-hoc, enviam mensagens e roteiam através da mesh.

Funcionalidades

  • Peer Discovery: registro e descoberta automática de peers
  • Direct Messaging: comunicação direta entre agentes
  • Broadcast & Topics: pub/sub com grupos por tópico
  • Message Routing: roteamento multi-hop via BFS shortest path
  • Heartbeat & Pruning: detecção de peers desconectados
  • Message Queue: buffer para peers temporariamente offline
  • Rate Limiting: token bucket por agente
  • Network Partitioning: detecção de splits na rede
  • Mesh Topology: grafo de adjacência com métricas

Arquivos

Arquivo Descrição
.aiox-core/core/communication/agent-mesh-network.js Módulo principal
.aios-core/core/communication/agent-mesh-network.js Wrapper retrocompatível
tests/core/communication/agent-mesh-network.test.js Testes unitários

Test plan

  • Todos os 103 testes passam localmente
  • CI pipeline passa
  • Padrão EventEmitter consistente com módulos existentes
  • Uso de `??` para defaults (nullish coalescing)

Summary by CodeRabbit

  • New Features

    • Added Agent Mesh Network for peer-to-peer communication, supporting discovery, topology management, topic-based pub/sub, direct messaging with routing, and health monitoring.
    • Added Decision Memory system for persistent storage and retrieval of agent decisions with pattern detection and context injection.
  • Tests

    • Added comprehensive test suites for Agent Mesh Network and Decision Memory modules.

@vercel
Copy link

vercel bot commented Mar 10, 2026

@nikolasdehor is attempting to deploy a commit to the Pedro Valério Lopez's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link

coderabbitai bot commented Mar 10, 2026

Walkthrough

This PR introduces two major core features: an Agent Mesh Network implementation providing peer-to-peer mesh networking with discovery, pub/sub, routing, rate limiting, and health monitoring; and a Decision Memory system for persistent storage and pattern detection of agent decisions. Both include comprehensive test suites and registry updates.

Changes

Cohort / File(s) Summary
Agent Mesh Network Implementation
aios-core/core/communication/agent-mesh-network.js, .aiox-core/core/communication/agent-mesh-network.js
Introduces peer-to-peer mesh network with peer discovery, lifecycle management, topic-based pub/sub, direct/broadcast messaging, request/response semantics, BFS-based routing, per-peer rate limiting, message queuing with TTL, heartbeat health checks, partition detection, and topology persistence. Public wrapper re-exports canonical implementation from hidden directory.
Agent Mesh Network Tests
tests/core/communication/agent-mesh-network.test.js
Comprehensive test suite covering constructor behavior, peer management, messaging (direct/broadcast), routing, topology, partition detection, health metrics, persistence, and resource cleanup.
Decision Memory Implementation
.aiox-core/core/memory/decision-memory.js
Introduces persistent decision memory system with decision recording, outcome tracking, confidence management, keyword-based retrieval, pattern detection, context injection, time-decay scoring, and event-driven architecture.
Decision Memory Tests
tests/core/memory/decision-memory.test.js
Comprehensive test suite covering constructor, persistence roundtrip, decision recording, outcome updates, relevance retrieval, context injection, pattern detection, and time-decay behavior.
Registry & Manifest Updates
.aiox-core/data/entity-registry.yaml, .aiox-core/install-manifest.yaml
Registers new agent-mesh-network entity with metadata (path, layer, keywords, lifecycle) and updates install manifest with new core files, metadata timestamps, and file counts.

Sequence Diagram(s)

sequenceDiagram
    participant PeerA as Peer A
    participant Router as Mesh Router
    participant PeerB as Peer B
    participant Queue as Message Queue
    
    PeerA->>Router: send(peerId, message)
    alt Adjacent Peer
        Router->>PeerB: deliver message
        PeerB->>PeerB: emit messageReceived
    else Non-Adjacent Peer
        Router->>Router: compute shortest path (BFS)
        Router->>Router: find intermediary peers
        loop For each hop
            Router->>Queue: enqueue if offline
            Router->>Router: forward to next peer
        end
    end
    PeerB-->>PeerA: messageSent event
Loading
sequenceDiagram
    participant Agent as Agent
    participant Memory as Decision Memory
    participant Store as JSON Persistence
    participant Detector as Pattern Detector
    
    Agent->>Memory: recordDecision(task, action, context)
    Memory->>Memory: auto-detect category
    Memory->>Memory: extract keywords
    Memory->>Memory: emit decisionRecorded
    Memory->>Store: save to decisions.json
    
    Agent->>Memory: getRelevantDecisions(task)
    Memory->>Memory: compute keyword similarity
    Memory->>Memory: apply time decay
    Memory->>Memory: filter by outcome/category
    Memory-->>Agent: return ranked decisions
    
    Memory->>Detector: detectPatterns(category)
    Detector->>Detector: identify recurring decisions
    Detector->>Memory: emit patternDetected
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main addition: an Agent Mesh Network module for decentralized peer-to-peer communication. It accurately reflects the primary change across multiple files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (5)
.aios-core/core/communication/agent-mesh-network.js (1)

1-2: Use an absolute module path for the compatibility wrapper.

This re-export works, but the ../../../... traversal hard-codes the directory layout and violates the repo import rule.

Proposed change
+const path = require('path');
+
 // Wrapper retrocompativel — modulo real em .aiox-core/
-module.exports = require('../../../.aiox-core/core/communication/agent-mesh-network');
+module.exports = require(path.resolve(__dirname, '../../../.aiox-core/core/communication/agent-mesh-network'));

As per coding guidelines, "**/*.{js,jsx,ts,tsx}: Use absolute imports instead of relative imports in all code".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.aios-core/core/communication/agent-mesh-network.js around lines 1 - 2,
Replace the hard-coded relative require in the compatibility wrapper: instead of
module.exports =
require('../../../.aiox-core/core/communication/agent-mesh-network'); use the
project's absolute module import for the aiox-core package (e.g., the canonical
package alias defined in the repo's module resolution) so the wrapper re-exports
the same module via an absolute path; update the single module.exports line to
require/import the absolute module identifier per the repo import rule.
tests/core/memory/decision-memory.test.js (1)

1-9: Use an absolute module path in the test import.

This relative traverse into .aiox-core violates the repo import rule and makes the suite brittle to directory layout changes.

Proposed change
 const path = require('path');
 const fs = require('fs');
+const decisionMemoryModule = path.resolve(__dirname, '../../../.aiox-core/core/memory/decision-memory');
 const {
   DecisionMemory,
   DecisionCategory,
   Outcome,
   Events,
   CONFIG,
-} = require('../../../.aiox-core/core/memory/decision-memory');
+} = require(decisionMemoryModule);

As per coding guidelines, "**/*.{js,jsx,ts,tsx}: Use absolute imports instead of relative imports in all code".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/core/memory/decision-memory.test.js` around lines 1 - 9, The test
currently imports DecisionMemory, DecisionCategory, Outcome, Events, and CONFIG
via a relative path that traverses into .aiox-core; update the import to use the
project's absolute module path (the package or export that exposes
DecisionMemory, DecisionCategory, Outcome, Events, CONFIG) so the test imports
those symbols via an absolute module name instead of
"../../../.aiox-core/core/memory/decision-memory"; locate the import line
referencing DecisionMemory/DecisionCategory/Outcome/Events/CONFIG and replace it
with the corresponding absolute import according to your repo's module
aliases/exports.
tests/core/communication/agent-mesh-network.test.js (3)

442-446: Remove unused sentEvents variable and handler.

The sentEvents array is populated by the event handler but never used in any assertions. This appears to be dead code that should be removed.

       const promise = mesh.request('a1', 'a2', { q: 'status?' });
 
-      // Pegar o messageId da request enviada
-      const sentEvents = [];
-      mesh.on(MeshEvent.MESSAGE_SENT, (e) => sentEvents.push(e));
-
       // O promise ja foi criado, precisamos encontrar o pending request
       const [requestId] = Array.from(mesh.pendingRequests.keys());
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/core/communication/agent-mesh-network.test.js` around lines 442 - 446,
Remove the dead event handler and array by deleting the sentEvents declaration
and the mesh.on(MeshEvent.MESSAGE_SENT, (e) => sentEvents.push(e)) line; this
cleans up unused variables and listeners (search for sentEvents and the
MeshEvent.MESSAGE_SENT handler in the test to locate the exact lines to remove).

36-42: Consider logging or documenting suppressed errors in cleanup.

The empty catch block silently ignores all errors during directory cleanup. While acceptable for test cleanup, consider adding a brief comment explaining the intent or logging at debug level for easier troubleshooting.

 function cleanupDir(dir) {
   try {
     fs.rmSync(dir, { recursive: true, force: true });
-  } catch {
-    // ignore
+  } catch (err) {
+    // Cleanup errors are non-fatal in tests; directory may already be removed
   }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/core/communication/agent-mesh-network.test.js` around lines 36 - 42,
The catch in function cleanupDir currently swallows all errors silently; update
the catch block in cleanupDir to either log the caught error at debug/verbose
level (e.g., using console.debug or the project test logger) or add a clear
comment explaining that errors are intentionally ignored for test teardown;
ensure you reference the caught error (e.g., catch (err)) so the logger or
comment can include context like the dir path and error message for easier
debugging.

11-11: Use absolute import instead of relative import.

The coding guidelines require absolute imports. This relative path traverses multiple directories, making it harder to maintain and refactor.

-const AgentMeshNetwork = require('../../../.aiox-core/core/communication/agent-mesh-network');
+const AgentMeshNetwork = require('.aiox-core/core/communication/agent-mesh-network');

As per coding guidelines: "Use absolute imports instead of relative imports in all code."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/core/communication/agent-mesh-network.test.js` at line 11, The test
currently uses a relative
require('../../../.aiox-core/core/communication/agent-mesh-network') for
AgentMeshNetwork; replace it with the project’s absolute import path/alias (e.g.
require('core/communication/agent-mesh-network') or the configured package alias
like require('@aiox/core/communication/agent-mesh-network')) so the test uses
the canonical absolute module import for AgentMeshNetwork and follows the coding
guideline.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.aiox-core/core/communication/agent-mesh-network.js:
- Around line 32-44: DEFAULT_OPTIONS sets autoStart: true but the constructor
never triggers the heartbeat machinery; update the constructor of the
AgentMeshNetwork class (or whatever constructor initializes DEFAULT_OPTIONS) to
check options.autoStart and call this.startHeartbeat() when true, ensuring
startHeartbeat() is idempotent and that it wires up heartbeat pruning, TTL
cleanup and partition detection as currently implemented; also preserve existing
behavior when autoStart is false so callers who expect manual start still work.
- Around line 868-890: The save() method currently writes topology.json directly
and can corrupt state on I/O failure; update save() (and the related persist
call path used by _schedulePersist) to use the existing atomicWriteSync from
core/synapse/utils/atomic-write (require it at top) and replace
fs.writeFileSync(filePath, ...) with atomicWriteSync(filePath,
JSON.stringify(data, null, 2), 'utf-8'); wrap the atomic write in a try/catch
that logs or re-throws a contextual error (include filePath and operation)
instead of silently swallowing it so callers/_schedulePersist can observe
failures.
- Around line 910-924: The heartbeat logic can permanently isolate peers because
lastSeen is only updated on outbound activity; update _deliverMessage to call
the same last-seen/activation path as _updateLastSeen (or call _updateLastSeen
directly) so inbound traffic refreshes lastSeen/state and triggers adjacency
restoration; modify _runHeartbeat to, when re-activating a peer via
_updateLastSeen or similar, also rebuild adjacency/edges and flush any queued
messages for that peer (ensure queued messages are drained when state becomes
ACTIVE), and audit other occurrences noted (around lines referenced: 946-964,
986-991, 1030-1045) to apply the same fix where inbound messages should refresh
lastSeen and restore routing/queued-message delivery.
- Around line 681-725: detectPartitions() should be a pure reader: remove the
side-effects inside detectPartitions by deleting the stats increment
(this.stats.partitionsDetected++) and the event emission
(this._emitSafe(MeshEvent.PARTITION_DETECTED, ...)); leave the algorithm that
computes and returns partitions unchanged. Ensure callers that need to
record/emit on partition detection (e.g., getNetworkHealth(), getMeshStats())
explicitly check the returned partitions length and perform the stats increment
and this._emitSafe(MeshEvent.PARTITION_DETECTED, { partitions }) there instead.

In @.aiox-core/core/memory/decision-memory.js:
- Around line 138-181: The save() method currently writes decisions.json
in-place and can corrupt the file on partial writes; update save() to use the
existing atomic write helper by requiring atomicWriteSync from
'../synapse/utils/atomic-write' and replace fs.writeFileSync(filePath,
JSON.stringify(...), 'utf-8') with an atomicWriteSync(filePath,
JSON.stringify(data, null, 2), 'utf-8') call; keep the existing directory
creation logic, and ensure any I/O errors from atomicWriteSync are allowed to
surface or are caught and logged consistently with the class's error handling
(refer to the save() and load() methods and the atomicWriteSync symbol to locate
changes).

In @.aiox-core/data/entity-registry.yaml:
- Around line 12781-12797: The registry entry for agent-mesh-network (path
.aiox-core/core/communication/agent-mesh-network.js) is missing the standard
fields `externalDeps`, `plannedDeps`, and `lifecycle`; add those keys to the
entry using the same shapes as sibling entries (e.g., `externalDeps: []`,
`plannedDeps: []` and a `lifecycle` object with the usual lifecycle properties
your registry uses) so the record matches the expected schema and
validators/consumers do not need special-casing for agent-mesh-network.

---

Nitpick comments:
In @.aios-core/core/communication/agent-mesh-network.js:
- Around line 1-2: Replace the hard-coded relative require in the compatibility
wrapper: instead of module.exports =
require('../../../.aiox-core/core/communication/agent-mesh-network'); use the
project's absolute module import for the aiox-core package (e.g., the canonical
package alias defined in the repo's module resolution) so the wrapper re-exports
the same module via an absolute path; update the single module.exports line to
require/import the absolute module identifier per the repo import rule.

In `@tests/core/communication/agent-mesh-network.test.js`:
- Around line 442-446: Remove the dead event handler and array by deleting the
sentEvents declaration and the mesh.on(MeshEvent.MESSAGE_SENT, (e) =>
sentEvents.push(e)) line; this cleans up unused variables and listeners (search
for sentEvents and the MeshEvent.MESSAGE_SENT handler in the test to locate the
exact lines to remove).
- Around line 36-42: The catch in function cleanupDir currently swallows all
errors silently; update the catch block in cleanupDir to either log the caught
error at debug/verbose level (e.g., using console.debug or the project test
logger) or add a clear comment explaining that errors are intentionally ignored
for test teardown; ensure you reference the caught error (e.g., catch (err)) so
the logger or comment can include context like the dir path and error message
for easier debugging.
- Line 11: The test currently uses a relative
require('../../../.aiox-core/core/communication/agent-mesh-network') for
AgentMeshNetwork; replace it with the project’s absolute import path/alias (e.g.
require('core/communication/agent-mesh-network') or the configured package alias
like require('@aiox/core/communication/agent-mesh-network')) so the test uses
the canonical absolute module import for AgentMeshNetwork and follows the coding
guideline.

In `@tests/core/memory/decision-memory.test.js`:
- Around line 1-9: The test currently imports DecisionMemory, DecisionCategory,
Outcome, Events, and CONFIG via a relative path that traverses into .aiox-core;
update the import to use the project's absolute module path (the package or
export that exposes DecisionMemory, DecisionCategory, Outcome, Events, CONFIG)
so the test imports those symbols via an absolute module name instead of
"../../../.aiox-core/core/memory/decision-memory"; locate the import line
referencing DecisionMemory/DecisionCategory/Outcome/Events/CONFIG and replace it
with the corresponding absolute import according to your repo's module
aliases/exports.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 08afb71f-f4bc-4a88-84bd-b23095ea08a5

📥 Commits

Reviewing files that changed from the base of the PR and between fcfb757 and aa89169.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (7)
  • .aios-core/core/communication/agent-mesh-network.js
  • .aiox-core/core/communication/agent-mesh-network.js
  • .aiox-core/core/memory/decision-memory.js
  • .aiox-core/data/entity-registry.yaml
  • .aiox-core/install-manifest.yaml
  • tests/core/communication/agent-mesh-network.test.js
  • tests/core/memory/decision-memory.test.js

Comment on lines +32 to +44
const DEFAULT_OPTIONS = {
heartbeatInterval: 30000,
peerTimeout: 90000,
maxQueueSize: 100,
messageTTL: 300000,
requestTimeout: 10000,
rateLimit: {
tokensPerInterval: 50,
interval: 60000,
},
persistenceDir: '.aiox/mesh',
autoStart: true,
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Honor the documented autoStart default.

DEFAULT_OPTIONS.autoStart is true, but the constructor never calls startHeartbeat(). As written, heartbeat pruning, TTL cleanup, and partition detection stay off unless every caller remembers to start them manually.

Proposed change
   /** `@type` {Promise} Cadeia de persistencia serializada */
   this._writeChain = Promise.resolve();

   this._started = false;
+
+  if (this.options.autoStart) {
+    this.startHeartbeat();
+  }
 }

As per coding guidelines, ".aiox-core/core/**: Ensure backwards compatibility — core modules are consumed by all agents."

Also applies to: 89-141

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.aiox-core/core/communication/agent-mesh-network.js around lines 32 - 44,
DEFAULT_OPTIONS sets autoStart: true but the constructor never triggers the
heartbeat machinery; update the constructor of the AgentMeshNetwork class (or
whatever constructor initializes DEFAULT_OPTIONS) to check options.autoStart and
call this.startHeartbeat() when true, ensuring startHeartbeat() is idempotent
and that it wires up heartbeat pruning, TTL cleanup and partition detection as
currently implemented; also preserve existing behavior when autoStart is false
so callers who expect manual start still work.

Comment on lines +681 to +725
detectPartitions() {
const visited = new Set();
const partitions = [];

const activePeers = Array.from(this.peers.entries())
.filter(([, p]) => p.state === PeerState.ACTIVE)
.map(([id]) => id);

for (const peerId of activePeers) {
if (visited.has(peerId)) continue;

const component = [];
const stack = [peerId];

while (stack.length > 0) {
const current = stack.pop();
if (visited.has(current)) continue;
visited.add(current);
component.push(current);

const neighbors = this.adjacency.get(current);
if (neighbors) {
for (const neighbor of neighbors) {
if (!visited.has(neighbor)) {
const neighborPeer = this.peers.get(neighbor);
if (neighborPeer && neighborPeer.state === PeerState.ACTIVE) {
stack.push(neighbor);
}
}
}
}
}

if (component.length > 0) {
partitions.push(component.sort());
}
}

if (partitions.length > 1) {
this.stats.partitionsDetected++;
this._emitSafe(MeshEvent.PARTITION_DETECTED, { partitions });
}

return partitions;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Make detectPartitions() a pure read.

This method increments stats.partitionsDetected and emits PARTITION_DETECTED every time it finds multiple components. Since getNetworkHealth() and getMeshStats() call it, simple health polling will inflate metrics and spam partition events.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.aiox-core/core/communication/agent-mesh-network.js around lines 681 - 725,
detectPartitions() should be a pure reader: remove the side-effects inside
detectPartitions by deleting the stats increment
(this.stats.partitionsDetected++) and the event emission
(this._emitSafe(MeshEvent.PARTITION_DETECTED, ...)); leave the algorithm that
computes and returns partitions unchanged. Ensure callers that need to
record/emit on partition detection (e.g., getNetworkHealth(), getMeshStats())
explicitly check the returned partitions length and perform the stats increment
and this._emitSafe(MeshEvent.PARTITION_DETECTED, { partitions }) there instead.

Comment on lines +868 to +890
async save() {
const filePath = this._getTopologyPath();
const dir = path.dirname(filePath);

const data = {
schemaVersion: 'agent-mesh-v1',
version: '1.0.0',
savedAt: new Date().toISOString(),
peers: Array.from(this.peers.values()).map(p => ({
id: p.id,
capabilities: p.capabilities,
topics: Array.from(p.topics),
state: p.state,
joinedAt: p.joinedAt,
})),
stats: this.stats,
};

if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Don't silently lose topology state on failed writes.

save() overwrites topology.json directly, and _schedulePersist() discards any resulting error. A crash or I/O failure can therefore leave a truncated file with no signal to the caller. The repo already has .aiox-core/core/synapse/utils/atomic-write.js for this write pattern.

Proposed change
-    fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');
+    atomicWriteSync(filePath, JSON.stringify(data, null, 2), 'utf-8');
@@
-    this._writeChain = this._writeChain.then(() => this.save()).catch(() => {
-      // Falha silenciosa na persistencia
-    });
+    this._writeChain = this._writeChain
+      .then(() => this.save())
+      .catch((error) => {
+        this._emitSafe('error', new Error(`Failed to persist mesh topology: ${error.message}`));
+      });
const { atomicWriteSync } = require(path.resolve(__dirname, '../synapse/utils/atomic-write'));

As per coding guidelines, ".aiox-core/core/**: Verify error handling is comprehensive with proper try/catch and error context."

Also applies to: 1059-1063

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.aiox-core/core/communication/agent-mesh-network.js around lines 868 - 890,
The save() method currently writes topology.json directly and can corrupt state
on I/O failure; update save() (and the related persist call path used by
_schedulePersist) to use the existing atomicWriteSync from
core/synapse/utils/atomic-write (require it at top) and replace
fs.writeFileSync(filePath, ...) with atomicWriteSync(filePath,
JSON.stringify(data, null, 2), 'utf-8'); wrap the atomic write in a try/catch
that logs or re-throws a contextual error (include filePath and operation)
instead of silently swallowing it so callers/_schedulePersist can observe
failures.

Comment on lines +910 to +924
_deliverMessage(msg) {
const toPeer = this.peers.get(msg.to);
if (toPeer) {
toPeer.messageCount++;
}

this.stats.messagesReceived++;
this._emitSafe(MeshEvent.MESSAGE_RECEIVED, {
messageId: msg.id,
from: msg.from,
to: msg.to,
type: msg.type,
payload: msg.payload,
});
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Heartbeat can permanently isolate healthy peers.

lastSeen only changes on outbound activity, so a peer that only receives traffic will eventually time out. After that, _runHeartbeat() clears its adjacency, but _updateLastSeen() only flips state back to ACTIVE; it never rebuilds edges or drain queued messages. Once a peer times out, routing to/from that peer stays broken and queued traffic never flushes.

Proposed change
   _deliverMessage(msg) {
     const toPeer = this.peers.get(msg.to);
     if (toPeer) {
       toPeer.messageCount++;
+      this._updateLastSeen(msg.to);
     }
@@
   _updateLastSeen(agentId) {
     const peer = this.peers.get(agentId);
     if (peer) {
+      const wasInactive = peer.state !== PeerState.ACTIVE;
       peer.lastSeen = Date.now();
       peer.state = PeerState.ACTIVE;
+
+      if (wasInactive) {
+        if (!this.adjacency.has(agentId)) {
+          this.adjacency.set(agentId, new Set());
+        }
+
+        for (const [otherId, otherPeer] of this.peers) {
+          if (otherId !== agentId && otherPeer.state === PeerState.ACTIVE) {
+            this.adjacency.get(agentId).add(otherId);
+            this.adjacency.get(otherId)?.add(agentId);
+          }
+        }
+
+        this._drainQueue(agentId);
+      }
     }
   }

Also applies to: 946-964, 986-991, 1030-1045

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.aiox-core/core/communication/agent-mesh-network.js around lines 910 - 924,
The heartbeat logic can permanently isolate peers because lastSeen is only
updated on outbound activity; update _deliverMessage to call the same
last-seen/activation path as _updateLastSeen (or call _updateLastSeen directly)
so inbound traffic refreshes lastSeen/state and triggers adjacency restoration;
modify _runHeartbeat to, when re-activating a peer via _updateLastSeen or
similar, also rebuild adjacency/edges and flush any queued messages for that
peer (ensure queued messages are drained when state becomes ACTIVE), and audit
other occurrences noted (around lines referenced: 946-964, 986-991, 1030-1045)
to apply the same fix where inbound messages should refresh lastSeen and restore
routing/queued-message delivery.

Comment on lines +138 to +181
async load() {
const filePath = path.resolve(this.projectRoot, this.config.decisionsJsonPath);

try {
if (fs.existsSync(filePath)) {
const raw = fs.readFileSync(filePath, 'utf-8');
const data = JSON.parse(raw);

if (data.schemaVersion === this.config.schemaVersion) {
this.decisions = data.decisions || [];
this.patterns = data.patterns || [];
}
}
} catch {
// Corrupted file — start fresh
this.decisions = [];
this.patterns = [];
}

this._loaded = true;
}

/**
* Save decisions to disk
* @returns {Promise<void>}
*/
async save() {
const filePath = path.resolve(this.projectRoot, this.config.decisionsJsonPath);
const dir = path.dirname(filePath);

if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}

const data = {
schemaVersion: this.config.schemaVersion,
version: this.config.version,
updatedAt: new Date().toISOString(),
stats: this.getStats(),
decisions: this.decisions.slice(-this.config.maxDecisions),
patterns: this.patterns,
};

fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Make decision persistence crash-safe.

save() replaces .aiox/decisions.json in place, while load() treats parse failures as "start fresh". A partial write will therefore wipe the decision history on the next startup. Reuse the existing atomic write helper here too.

Proposed change
-    fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');
+    atomicWriteSync(filePath, JSON.stringify(data, null, 2), 'utf-8');
const { atomicWriteSync } = require(path.resolve(__dirname, '../synapse/utils/atomic-write'));

As per coding guidelines, ".aiox-core/core/**: Verify error handling is comprehensive with proper try/catch and error context."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.aiox-core/core/memory/decision-memory.js around lines 138 - 181, The save()
method currently writes decisions.json in-place and can corrupt the file on
partial writes; update save() to use the existing atomic write helper by
requiring atomicWriteSync from '../synapse/utils/atomic-write' and replace
fs.writeFileSync(filePath, JSON.stringify(...), 'utf-8') with an
atomicWriteSync(filePath, JSON.stringify(data, null, 2), 'utf-8') call; keep the
existing directory creation logic, and ensure any I/O errors from
atomicWriteSync are allowed to surface or are caught and logged consistently
with the class's error handling (refer to the save() and load() methods and the
atomicWriteSync symbol to locate changes).

Comment on lines +12781 to +12797
agent-mesh-network:
path: .aiox-core/core/communication/agent-mesh-network.js
layer: L1
type: module
purpose: Entity at .aiox-core/core/communication/agent-mesh-network.js
keywords:
- agent
- mesh
- network
usedBy: []
dependencies: []
adaptability:
score: 0.4
constraints: []
extensionPoints: []
checksum: sha256:9149abe1f1cc874d8c5d48d4e00846c617eaf416c93bc0f075a78def17b1e99d
lastVerified: '2026-03-10T14:29:32.610Z'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add the missing standard registry fields.

This entry is missing externalDeps, plannedDeps, and lifecycle, while sibling entities in this file include them. Leaving this row with a different shape makes registry consumers and validators handle a special case for just this module.

Suggested fix
     agent-mesh-network:
       path: .aiox-core/core/communication/agent-mesh-network.js
       layer: L1
       type: module
       purpose: Entity at .aiox-core/core/communication/agent-mesh-network.js
       keywords:
         - agent
         - mesh
         - network
       usedBy: []
       dependencies: []
+      externalDeps: []
+      plannedDeps: []
+      lifecycle: production
       adaptability:
         score: 0.4
         constraints: []
         extensionPoints: []
       checksum: sha256:9149abe1f1cc874d8c5d48d4e00846c617eaf416c93bc0f075a78def17b1e99d
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
agent-mesh-network:
path: .aiox-core/core/communication/agent-mesh-network.js
layer: L1
type: module
purpose: Entity at .aiox-core/core/communication/agent-mesh-network.js
keywords:
- agent
- mesh
- network
usedBy: []
dependencies: []
adaptability:
score: 0.4
constraints: []
extensionPoints: []
checksum: sha256:9149abe1f1cc874d8c5d48d4e00846c617eaf416c93bc0f075a78def17b1e99d
lastVerified: '2026-03-10T14:29:32.610Z'
agent-mesh-network:
path: .aiox-core/core/communication/agent-mesh-network.js
layer: L1
type: module
purpose: Entity at .aiox-core/core/communication/agent-mesh-network.js
keywords:
- agent
- mesh
- network
usedBy: []
dependencies: []
externalDeps: []
plannedDeps: []
lifecycle: production
adaptability:
score: 0.4
constraints: []
extensionPoints: []
checksum: sha256:9149abe1f1cc874d8c5d48d4e00846c617eaf416c93bc0f075a78def17b1e99d
lastVerified: '2026-03-10T14:29:32.610Z'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.aiox-core/data/entity-registry.yaml around lines 12781 - 12797, The
registry entry for agent-mesh-network (path
.aiox-core/core/communication/agent-mesh-network.js) is missing the standard
fields `externalDeps`, `plannedDeps`, and `lifecycle`; add those keys to the
entry using the same shapes as sibling entries (e.g., `externalDeps: []`,
`plannedDeps: []` and a `lifecycle` object with the usual lifecycle properties
your registry uses) so the record matches the expected schema and
validators/consumers do not need special-casing for agent-mesh-network.

@nikolasdehor
Copy link
Contributor Author

@Pedrovaleriolopez @oalanicolas, Agent Mesh Network — comunicação P2P descentralizada entre agentes com roteamento BFS, detecção de partições, rate limiting por token bucket, e pub/sub por tópicos. 103 testes. Junto com o Immortality Protocol (#576), fecha o ciclo de resiliência do framework.

@nikolasdehor nikolasdehor force-pushed the feat/agent-mesh-network branch from aa89169 to ff711c1 Compare March 11, 2026 02:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant