feat: Agent Swarm Intelligence module (ORCH-5)#572
feat: Agent Swarm Intelligence module (ORCH-5)#572nikolasdehor wants to merge 3 commits intoSynkraAI:mainfrom
Conversation
|
@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. |
WalkthroughAdds a new SwarmIntelligence core module (full implementation), a backward-compatible wrapper re-exporting it, comprehensive tests for the module, and updates the install manifest to include the new asset and adjusted template sizes/hashes. Changes
Sequence Diagram(s)sequenceDiagram
participant Client as Client
participant Swarm as SwarmIntelligence
participant VoteEngine as VotingEngine
participant Persist as Persistence
Client->>Swarm: createSwarm(name, config)
Swarm->>Persist: _persistAsync/_saveToDisk()
Swarm-->>Client: returns swarmId
Client->>Swarm: proposeDecision(swarmId, proposal)
Swarm-->>Client: emit proposal:created
Client->>Swarm: vote(swarmId, proposalId, agentId, vote, confidence)
Swarm->>VoteEngine: validate & record vote
VoteEngine-->>Swarm: vote recorded
Swarm-->>Client: emit proposal:voted
Client->>Swarm: resolveProposal(swarmId, proposalId)
Swarm->>VoteEngine: evaluate according to strategy
VoteEngine-->>Swarm: outcome
Swarm->>Swarm: update reputations/stats
Swarm->>Persist: _persistAsync/_saveToDisk()
Swarm-->>Client: emit proposal:resolved
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (1)
tests/core/orchestration/swarm-intelligence.test.js (1)
11-18: Use the repo's absolute import form in these tests.Both
require()calls reach into.aiox-corevia relative paths, which makes the tests brittle and violates the project import convention. As per coding guidelines, "Use absolute imports instead of relative imports in all code".Also applies to: 934-934
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/core/orchestration/swarm-intelligence.test.js` around lines 11 - 18, Replace the relative require('../../../.aiox-core/core/orchestration/swarm-intelligence') with the repo's absolute import form (e.g. require('aiox-core/core/orchestration/swarm-intelligence') or whatever project absolute module name is used) so the test imports SwarmIntelligence, and update any other occurrences (the similar import at line ~934) to the same absolute import; ensure the destructured symbols (VOTING_STRATEGIES, PROPOSAL_STATUS, SWARM_STATUS, LEADER_CRITERIA, VOTE_OPTIONS) remain sourced from the imported SwarmIntelligence.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.aios-core/core/orchestration/swarm-intelligence.js:
- Around line 1-1004: This file duplicates the full implementation; replace it
with a thin compatibility wrapper that re-exports the canonical implementation
so both import paths stay in sync: require the canonical swarm-intelligence
module and then export it and its named exports (ensure SwarmIntelligence,
VOTING_STRATEGIES, PROPOSAL_STATUS, SWARM_STATUS, LEADER_CRITERIA, VOTE_OPTIONS
are forwarded). Remove the duplicated class/function definitions and keep only
the require + module.exports re-exports to avoid drift.
In @.aiox-core/core/orchestration/swarm-intelligence.js:
- Around line 868-897: The catch in loadFromDisk currently swallows all errors
and returns false; change it to only treat ENOENT as a "fresh start" and handle
all other errors with context: in async loadFromDisk(), catch the error object,
if error.code === 'ENOENT' return false, otherwise call this._log (or
processLogger if available) with a contextual message including
this._persistPath and the error, then rethrow the error (or return a rejected
Promise) so callers can handle it; keep references to loadFromDisk,
this._persistPath, this._log and ensure JSON.parse and fs.readFile errors are
surfaced.
- Around line 664-673: queryKnowledge() currently increments entry.citations in
memory (via the loop that finds original in swarm.knowledgeBase and does
original.citations++) but never persists the change; update the function to
persist these bumps by calling swarm._persistAsync() (or the existing
persistence helper) after updating the limited results, or alternatively
document/guard the path as read-only and skip increments when persistence is
disabled; ensure you reference the in-memory mutation (swarm.knowledgeBase /
original.citations) and only call swarm._persistAsync() when persistence is
enabled to avoid errors in read-only modes.
- Around line 837-843: Multiple concurrent calls to _persistAsync() start
overlapping _saveToDisk() operations causing write-order races; serialize writes
by introducing a per-instance pending save promise (e.g., this._pendingSave) and
chain save operations instead of firing them concurrently. Update
_persistAsync() to no-op when !this.options.persist, otherwise replace the
fire-and-forget call with: set this._pendingSave = (this._pendingSave ||
Promise.resolve()).then(() => this._saveToDisk()).catch(err =>
this._log(`Persistence error: ${err.message}`)); ensure errors do not break the
chain (handle in catch) and reuse the same mechanism for other persistence call
sites referenced around lines 850-861 that currently call _persistAsync() so all
writes to swarms.json go through the same serialized chain.
- Around line 533-539: The quorum check in _quorumStrategy is using
base.totalVotes to decide if quorum is met, which allows abstains/rejects to
satisfy the threshold; change the logic so quorumRequired
(Math.ceil(swarm.agents.size * swarm.config.consensusThreshold)) is compared
against base.approveCount (not base.totalVotes) to ensure the required number of
approvals is present, and then compute approved by combining that
approval-quorum check with the existing approve/reject comparison (e.g.,
hasQuorum = base.approveCount >= quorumRequired; approved = hasQuorum &&
base.approveCount > base.rejectCount).
- Around line 403-416: In resolveProposal, first validate the proposal deadline
(compare new Date() to proposal.deadline) before calling _applyVotingStrategy so
expired proposals can't be resolved from stale input; if expired, set
proposal.status to PROPOSAL_STATUS.REJECTED, proposal.resolvedAt = new
Date().toISOString(), set proposal.resolution = { approved: false, reason:
'deadline_expired' } (or similar), increment this._stats.proposalsResolved and
return early; otherwise continue with the existing _applyVotingStrategy flow.
Reference resolveProposal, _getActiveSwarm, _getProposal and
_applyVotingStrategy.
---
Nitpick comments:
In `@tests/core/orchestration/swarm-intelligence.test.js`:
- Around line 11-18: Replace the relative
require('../../../.aiox-core/core/orchestration/swarm-intelligence') with the
repo's absolute import form (e.g.
require('aiox-core/core/orchestration/swarm-intelligence') or whatever project
absolute module name is used) so the test imports SwarmIntelligence, and update
any other occurrences (the similar import at line ~934) to the same absolute
import; ensure the destructured symbols (VOTING_STRATEGIES, PROPOSAL_STATUS,
SWARM_STATUS, LEADER_CRITERIA, VOTE_OPTIONS) remain sourced from the imported
SwarmIntelligence.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 87b7c880-3837-4ab7-b9ae-70352276ff05
📒 Files selected for processing (3)
.aios-core/core/orchestration/swarm-intelligence.js.aiox-core/core/orchestration/swarm-intelligence.jstests/core/orchestration/swarm-intelligence.test.js
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (2)
tests/core/orchestration/swarm-intelligence.test.js (1)
1014-1019: Add a regression test for the legacy.aios-coreentrypoint.The export assertions only cover the canonical
.aiox-coremodule. If the compatibility wrapper breaks, this suite still stays green even though the PR promises legacy imports keep working.As per coding guidelines, "Ensure backwards compatibility — core modules are consumed by all agents."Suggested test
describe('exports', () => { it('should export SwarmIntelligence as default and named', () => { const mod = require('../../../.aiox-core/core/orchestration/swarm-intelligence'); expect(mod).toBe(SwarmIntelligence); expect(mod.SwarmIntelligence).toBe(SwarmIntelligence); }); + + it('should preserve the legacy .aios-core import path', () => { + const legacy = require('../../../.aios-core/core/orchestration/swarm-intelligence'); + expect(legacy).toBe(SwarmIntelligence); + expect(legacy.SwarmIntelligence).toBe(SwarmIntelligence); + }); it('should export constants', () => { expect(VOTING_STRATEGIES).toBeDefined(); expect(PROPOSAL_STATUS).toBeDefined();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/core/orchestration/swarm-intelligence.test.js` around lines 1014 - 1019, Add a regression test that verifies the legacy compatibility wrapper export for SwarmIntelligence: require the legacy entrypoint (the `.aios-core` wrapper for core/orchestration/swarm-intelligence) in the same way the existing test requires the canonical module, and assert that the required module equals the SwarmIntelligence symbol and that its .SwarmIntelligence property also equals SwarmIntelligence; update the describe('exports') test to include this additional require/assertion so both canonical ('.aiox-core') and legacy ('.aios-core') entrypoints are validated..aios-core/core/orchestration/swarm-intelligence.js (1)
1-2: Use the project’s absolute import convention in this wrapper.This re-export works, but it adds another deep relative require in a new JS file. That makes the compatibility entrypoint brittle to future moves and diverges from the repo’s import standard.
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 @.aios-core/core/orchestration/swarm-intelligence.js around lines 1 - 2, The wrapper currently re-exports the canonical implementation with a deep relative require (module.exports = require('../../../.aiox-core/core/orchestration/swarm-intelligence')); replace that relative require with the project’s absolute import for the canonical module (use the repo’s absolute import alias for the .aiox-core package and import '.aiox-core/core/orchestration/swarm-intelligence' or the equivalent alias used across the codebase) so the file exports the same module without brittle ../../ paths.
🤖 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/orchestration/swarm-intelligence.js:
- Around line 880-891: In _saveToDisk(), make the persistence atomic by writing
JSON to a temporary file in the same directory (e.g., deriving a temp name from
this._persistPath), fsyncing/flushing if available, then renaming (fs.rename)
the temp file onto this._persistPath; wrap the write/fsync/rename sequence in
try/catch and include contextual info (this._persistPath, error) in any thrown
or logged error; continue to use this._serializeSwarms() and this._stats to
build the payload but replace the direct fs.writeFile(this._persistPath, ...)
with the safe temp-write-and-rename flow so a partial write cannot leave
truncated JSON.
- Around line 319-330: The code uses proposal.deadlineMs directly when building
created.deadline, which allows NaN, Infinity, or negative values to produce an
invalid or already-expired Date; validate proposal.deadlineMs (e.g., use
Number.isFinite and > 0) before assigning deadlineMs and fall back to the
default 300000 if invalid, then compute created.deadline from that sanitized
deadlineMs (references: generateId and the created.deadline construction).
- Around line 372-375: The code currently sets proposal.status =
PROPOSAL_STATUS.EXPIRED and then throws, which prevents the usual resolution
flow (resolveProposal(), setting resolvedAt/resolution, stats updates, event
emission and persistence) from running; instead, when detecting an expired
proposal (use proposal and proposalId), set proposal.status =
PROPOSAL_STATUS.EXPIRED and then perform the normal resolution steps rather than
throwing: populate proposal.resolvedAt, proposal.resolution (use the existing
resolution enum/value used elsewhere), update any proposal statistics, emit the
resolution event, and persist the proposal (i.e., invoke the same
resolution/cleanup logic that resolveProposal() would perform) so the expired
state is fully recorded and processed.
- Around line 631-644: Reject non-serializable knowledge.content before creating
the entry: add a validation step in the function handling incoming knowledge
(before calling generateId() and building entry) that attempts to
JSON.stringify(knowledge.content) (or otherwise checks for JSON-serializability)
and throws a clear Error if serialization fails (covering circular refs, BigInt,
etc.), so _saveToDisk() will not later fail due to a stored non-serializable
value; keep existing tag handling and error message consistent with other API
validations.
---
Nitpick comments:
In @.aios-core/core/orchestration/swarm-intelligence.js:
- Around line 1-2: The wrapper currently re-exports the canonical implementation
with a deep relative require (module.exports =
require('../../../.aiox-core/core/orchestration/swarm-intelligence')); replace
that relative require with the project’s absolute import for the canonical
module (use the repo’s absolute import alias for the .aiox-core package and
import '.aiox-core/core/orchestration/swarm-intelligence' or the equivalent
alias used across the codebase) so the file exports the same module without
brittle ../../ paths.
In `@tests/core/orchestration/swarm-intelligence.test.js`:
- Around line 1014-1019: Add a regression test that verifies the legacy
compatibility wrapper export for SwarmIntelligence: require the legacy
entrypoint (the `.aios-core` wrapper for core/orchestration/swarm-intelligence)
in the same way the existing test requires the canonical module, and assert that
the required module equals the SwarmIntelligence symbol and that its
.SwarmIntelligence property also equals SwarmIntelligence; update the
describe('exports') test to include this additional require/assertion so both
canonical ('.aiox-core') and legacy ('.aios-core') entrypoints are validated.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 225034e4-1eb4-43ee-b49e-03220fe8ce60
📒 Files selected for processing (4)
.aios-core/core/orchestration/swarm-intelligence.js.aiox-core/core/orchestration/swarm-intelligence.js.aiox-core/install-manifest.yamltests/core/orchestration/swarm-intelligence.test.js
| const id = generateId(); | ||
| const deadlineMs = proposal.deadlineMs ?? 300000; | ||
| const created = { | ||
| id, | ||
| swarmId, | ||
| proposedBy: proposal.proposedBy, | ||
| description: proposal.description, | ||
| type: proposal.type ?? 'general', | ||
| votes: new Map(), | ||
| status: PROPOSAL_STATUS.PENDING, | ||
| createdAt: new Date().toISOString(), | ||
| deadline: new Date(Date.now() + deadlineMs).toISOString(), |
There was a problem hiding this comment.
Validate deadlineMs before building the deadline.
proposal.deadlineMs = NaN, Infinity, or a negative value can produce an invalid or already-expired ISO timestamp. An Invalid Date never compares < new Date(), so the proposal can remain pending forever and bypass both expiry checks.
Suggested fix
const id = generateId();
const deadlineMs = proposal.deadlineMs ?? 300000;
+ if (!Number.isFinite(deadlineMs) || deadlineMs < 0) {
+ throw new Error('proposal.deadlineMs must be a non-negative finite number');
+ }
const created = {
id,
swarmId,
proposedBy: proposal.proposedBy,📝 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.
| const id = generateId(); | |
| const deadlineMs = proposal.deadlineMs ?? 300000; | |
| const created = { | |
| id, | |
| swarmId, | |
| proposedBy: proposal.proposedBy, | |
| description: proposal.description, | |
| type: proposal.type ?? 'general', | |
| votes: new Map(), | |
| status: PROPOSAL_STATUS.PENDING, | |
| createdAt: new Date().toISOString(), | |
| deadline: new Date(Date.now() + deadlineMs).toISOString(), | |
| const id = generateId(); | |
| const deadlineMs = proposal.deadlineMs ?? 300000; | |
| if (!Number.isFinite(deadlineMs) || deadlineMs < 0) { | |
| throw new Error('proposal.deadlineMs must be a non-negative finite number'); | |
| } | |
| const created = { | |
| id, | |
| swarmId, | |
| proposedBy: proposal.proposedBy, | |
| description: proposal.description, | |
| type: proposal.type ?? 'general', | |
| votes: new Map(), | |
| status: PROPOSAL_STATUS.PENDING, | |
| createdAt: new Date().toISOString(), | |
| deadline: new Date(Date.now() + deadlineMs).toISOString(), |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.aiox-core/core/orchestration/swarm-intelligence.js around lines 319 - 330,
The code uses proposal.deadlineMs directly when building created.deadline, which
allows NaN, Infinity, or negative values to produce an invalid or
already-expired Date; validate proposal.deadlineMs (e.g., use Number.isFinite
and > 0) before assigning deadlineMs and fall back to the default 300000 if
invalid, then compute created.deadline from that sanitized deadlineMs
(references: generateId and the created.deadline construction).
| // Check deadline | ||
| if (new Date(proposal.deadline) < new Date()) { | ||
| proposal.status = PROPOSAL_STATUS.EXPIRED; | ||
| throw new Error(`Proposal ${proposalId} has expired`); |
There was a problem hiding this comment.
Don't strand expired proposals in EXPIRED state.
A late vote currently mutates proposal.status and then throws. After that, resolveProposal() fails fast as “already resolved”, so resolvedAt, resolution, stats, event emission, and persistence never happen for that proposal.
Suggested fix
// Check deadline
if (new Date(proposal.deadline) < new Date()) {
- proposal.status = PROPOSAL_STATUS.EXPIRED;
throw new Error(`Proposal ${proposalId} has expired`);
}📝 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.
| // Check deadline | |
| if (new Date(proposal.deadline) < new Date()) { | |
| proposal.status = PROPOSAL_STATUS.EXPIRED; | |
| throw new Error(`Proposal ${proposalId} has expired`); | |
| // Check deadline | |
| if (new Date(proposal.deadline) < new Date()) { | |
| throw new Error(`Proposal ${proposalId} has expired`); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.aiox-core/core/orchestration/swarm-intelligence.js around lines 372 - 375,
The code currently sets proposal.status = PROPOSAL_STATUS.EXPIRED and then
throws, which prevents the usual resolution flow (resolveProposal(), setting
resolvedAt/resolution, stats updates, event emission and persistence) from
running; instead, when detecting an expired proposal (use proposal and
proposalId), set proposal.status = PROPOSAL_STATUS.EXPIRED and then perform the
normal resolution steps rather than throwing: populate proposal.resolvedAt,
proposal.resolution (use the existing resolution enum/value used elsewhere),
update any proposal statistics, emit the resolution event, and persist the
proposal (i.e., invoke the same resolution/cleanup logic that resolveProposal()
would perform) so the expired state is fully recorded and processed.
| if (knowledge.content === undefined || knowledge.content === null) { | ||
| throw new Error('knowledge.content is required'); | ||
| } | ||
|
|
||
| const id = generateId(); | ||
| const entry = { | ||
| id, | ||
| sharedBy: agentId, | ||
| topic: knowledge.topic, | ||
| content: knowledge.content, | ||
| tags: Array.isArray(knowledge.tags) ? [...knowledge.tags] : [], | ||
| timestamp: new Date().toISOString(), | ||
| citations: 0, | ||
| }; |
There was a problem hiding this comment.
Reject non-serializable knowledge before storing it.
knowledge.content can currently be any value, but _saveToDisk() JSON-stringifies the whole swarm state. A circular object or BigInt here will cause every subsequent persistence write to fail once the entry is in memory.
Suggested fix
if (knowledge.content === undefined || knowledge.content === null) {
throw new Error('knowledge.content is required');
}
+ if (this.options.persist) {
+ try {
+ JSON.stringify(knowledge.content);
+ } catch (err) {
+ throw new Error(`knowledge.content must be JSON-serializable: ${err.message}`);
+ }
+ }
const id = generateId();
const entry = {📝 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.
| if (knowledge.content === undefined || knowledge.content === null) { | |
| throw new Error('knowledge.content is required'); | |
| } | |
| const id = generateId(); | |
| const entry = { | |
| id, | |
| sharedBy: agentId, | |
| topic: knowledge.topic, | |
| content: knowledge.content, | |
| tags: Array.isArray(knowledge.tags) ? [...knowledge.tags] : [], | |
| timestamp: new Date().toISOString(), | |
| citations: 0, | |
| }; | |
| if (knowledge.content === undefined || knowledge.content === null) { | |
| throw new Error('knowledge.content is required'); | |
| } | |
| if (this.options.persist) { | |
| try { | |
| JSON.stringify(knowledge.content); | |
| } catch (err) { | |
| throw new Error(`knowledge.content must be JSON-serializable: ${err.message}`); | |
| } | |
| } | |
| const id = generateId(); | |
| const entry = { | |
| id, | |
| sharedBy: agentId, | |
| topic: knowledge.topic, | |
| content: knowledge.content, | |
| tags: Array.isArray(knowledge.tags) ? [...knowledge.tags] : [], | |
| timestamp: new Date().toISOString(), | |
| citations: 0, | |
| }; |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.aiox-core/core/orchestration/swarm-intelligence.js around lines 631 - 644,
Reject non-serializable knowledge.content before creating the entry: add a
validation step in the function handling incoming knowledge (before calling
generateId() and building entry) that attempts to
JSON.stringify(knowledge.content) (or otherwise checks for JSON-serializability)
and throws a clear Error if serialization fails (covering circular refs, BigInt,
etc.), so _saveToDisk() will not later fail due to a stored non-serializable
value; keep existing tag handling and error message consistent with other API
validations.
| async _saveToDisk() { | ||
| const dir = path.dirname(this._persistPath); | ||
| await fs.mkdir(dir, { recursive: true }); | ||
|
|
||
| const data = { | ||
| version: '1.0.0', | ||
| savedAt: new Date().toISOString(), | ||
| stats: this._stats, | ||
| swarms: this._serializeSwarms(), | ||
| }; | ||
|
|
||
| await fs.writeFile(this._persistPath, JSON.stringify(data, null, 2), 'utf8'); |
There was a problem hiding this comment.
Make the persistence write atomic.
fs.writeFile() updates swarms.json in place. If the process exits mid-write, the next loadFromDisk() sees truncated JSON and throws, which turns a transient interruption into permanent state loss until the file is repaired.
Suggested fix
async _saveToDisk() {
const dir = path.dirname(this._persistPath);
+ const tempPath = `${this._persistPath}.tmp`;
await fs.mkdir(dir, { recursive: true });
const data = {
version: '1.0.0',
savedAt: new Date().toISOString(),
stats: this._stats,
swarms: this._serializeSwarms(),
};
- await fs.writeFile(this._persistPath, JSON.stringify(data, null, 2), 'utf8');
+ await fs.writeFile(tempPath, JSON.stringify(data, null, 2), 'utf8');
+ await fs.rename(tempPath, this._persistPath);
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.aiox-core/core/orchestration/swarm-intelligence.js around lines 880 - 891,
In _saveToDisk(), make the persistence atomic by writing JSON to a temporary
file in the same directory (e.g., deriving a temp name from this._persistPath),
fsyncing/flushing if available, then renaming (fs.rename) the temp file onto
this._persistPath; wrap the write/fsync/rename sequence in try/catch and include
contextual info (this._persistPath, error) in any thrown or logged error;
continue to use this._serializeSwarms() and this._stats to build the payload but
replace the direct fs.writeFile(this._persistPath, ...) with the safe
temp-write-and-rename flow so a partial write cannot leave truncated JSON.
There was a problem hiding this comment.
🧹 Nitpick comments (2)
tests/core/orchestration/swarm-intelligence.test.js (2)
26-44: Consider more explicit error handling in test setup/teardown.The empty catch blocks silently ignore all errors. While the comments explain intent, being more explicit helps avoid masking unexpected failures during test runs.
♻️ Optional improvement
beforeEach(async () => { try { await fs.rm(TEST_PROJECT_ROOT, { recursive: true, force: true }); - } catch { - // Ignore if doesn't exist + } catch (err) { + if (err.code !== 'ENOENT') throw err; } await fs.mkdir(TEST_PROJECT_ROOT, { recursive: true });afterEach(async () => { si.removeAllListeners(); try { await fs.rm(TEST_PROJECT_ROOT, { recursive: true, force: true }); - } catch { - // Ignore cleanup errors + } catch (err) { + if (err.code !== 'ENOENT' && err.code !== 'EBUSY') throw err; } });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/core/orchestration/swarm-intelligence.test.js` around lines 26 - 44, The beforeEach/afterEach blocks currently swallow all errors with empty catch clauses; update them to explicitly handle expected "not found" behavior while surfacing unexpected errors by checking the caught error (when calling fs.rm on TEST_PROJECT_ROOT and when recreating/removing the test dir) and only ignore errors that indicate the path does not exist (e.g., ENOENT), otherwise rethrow or fail the test; do this for the fs.rm calls in the setup/teardown surrounding the SwarmIntelligence(TEST_PROJECT_ROOT, { persist: false, debug: false }) creation and the si.removeAllListeners() cleanup so unexpected IO errors don’t get masked.
8-18: Use absolute imports instead of relative imports.The coding guidelines require absolute imports for all code. The relative import path
../../../.aiox-core/core/orchestration/swarm-intelligenceshould be converted to an absolute import.♻️ Suggested fix
Configure Jest's
moduleNameMapperormodulePathsinjest.config.jsto support absolute imports, then update:-const SwarmIntelligence = require('../../../.aiox-core/core/orchestration/swarm-intelligence'); +const SwarmIntelligence = require('.aiox-core/core/orchestration/swarm-intelligence');Alternatively, if the project uses path aliases, use the configured alias pattern.
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/orchestration/swarm-intelligence.test.js` around lines 8 - 18, Replace the relative require for SwarmIntelligence with an absolute import and ensure Jest resolves it: change the import that currently requires '../../../.aiox-core/core/orchestration/swarm-intelligence' to the project’s absolute module name (e.g. require('@aiox-core/core/orchestration/swarm-intelligence') or your configured alias) so SwarmIntelligence and its exports (VOTING_STRATEGIES, PROPOSAL_STATUS, SWARM_STATUS, LEADER_CRITERIA, VOTE_OPTIONS) are loaded via absolute path, and update jest.config.js to add the corresponding moduleNameMapper or modulePaths entry so Jest can resolve the alias in tests.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@tests/core/orchestration/swarm-intelligence.test.js`:
- Around line 26-44: The beforeEach/afterEach blocks currently swallow all
errors with empty catch clauses; update them to explicitly handle expected "not
found" behavior while surfacing unexpected errors by checking the caught error
(when calling fs.rm on TEST_PROJECT_ROOT and when recreating/removing the test
dir) and only ignore errors that indicate the path does not exist (e.g.,
ENOENT), otherwise rethrow or fail the test; do this for the fs.rm calls in the
setup/teardown surrounding the SwarmIntelligence(TEST_PROJECT_ROOT, { persist:
false, debug: false }) creation and the si.removeAllListeners() cleanup so
unexpected IO errors don’t get masked.
- Around line 8-18: Replace the relative require for SwarmIntelligence with an
absolute import and ensure Jest resolves it: change the import that currently
requires '../../../.aiox-core/core/orchestration/swarm-intelligence' to the
project’s absolute module name (e.g.
require('@aiox-core/core/orchestration/swarm-intelligence') or your configured
alias) so SwarmIntelligence and its exports (VOTING_STRATEGIES, PROPOSAL_STATUS,
SWARM_STATUS, LEADER_CRITERIA, VOTE_OPTIONS) are loaded via absolute path, and
update jest.config.js to add the corresponding moduleNameMapper or modulePaths
entry so Jest can resolve the alias in tests.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 05544382-eb7c-4040-b10a-8d42b531f51a
📒 Files selected for processing (2)
.aiox-core/install-manifest.yamltests/core/orchestration/swarm-intelligence.test.js
|
@Pedrovaleriolopez @oalanicolas, Swarm Intelligence completo — agentes podem formar enxames, compartilhar conhecimento e tomar decisões coletivas por votação. Persistência em disco, 50+ testes. Esse e o Cognitive Load Balancer (#571) se complementam pro ORCH-5/ORCH-6. |
Implementa inteligencia emergente via coordenacao de enxame (ORCH-5): - Criacao e gestao de swarms com configuracao de votacao - Sistema de decisao coletiva com 4 estrategias (majority, weighted, unanimous, quorum) - Base de conhecimento compartilhado com busca por topico/tags - Eleicao de lider (most-capable, highest-reputation, round-robin) - Metricas de saude e reputacao dinamica de agentes - Persistencia em .aiox/swarms.json - 83 testes cobrindo todos os metodos, estrategias e edge cases
- Converte .aios-core wrapper para re-export do .aiox-core (elimina duplicacao) - Rejeita proposals expiradas antes de aplicar voting strategy em resolveProposal() - Corrige quorum strategy: conta apenas approves para atingir quorum (nao total de votos) - Persiste citation bumps apos queryKnowledge() - Serializa escritas de persistencia com promise chain (_persistAsync) - Diferencia ENOENT de outros erros em loadFromDisk() (rethrow erros reais) - Adiciona 4 novos testes cobrindo todas as correcoes (87 total, todos passando)
- Teste 'save and load state from disk' agora aguarda _pendingSave antes de chamar _saveToDisk(), evitando escrita concorrente que corrompia JSON - Removida entrada cognitive-load-balancer.js do install-manifest (não pertence a este branch)
3fab3c1 to
3fa46df
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (4)
.aiox-core/core/orchestration/swarm-intelligence.js (4)
631-644:⚠️ Potential issue | 🟠 MajorReject non-serializable knowledge before storing it.
With persistence enabled, a circular object or
BigIntinknowledge.contentwill make every later save fail once the entry is in memory.As per coding guidelines, "Check for proper input validation on public API methods."Suggested fix
if (knowledge.content === undefined || knowledge.content === null) { throw new Error('knowledge.content is required'); } + if (this.options.persist) { + try { + JSON.stringify(knowledge.content); + } catch (err) { + throw new Error(`knowledge.content must be JSON-serializable: ${err.message}`); + } + } const id = generateId();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.aiox-core/core/orchestration/swarm-intelligence.js around lines 631 - 644, The code currently only checks for null/undefined content but doesn't ensure the content is JSON-serializable; update the validation before generating an entry (around the existing knowledge.content checks and before generateId()) to proactively reject non-serializable values (circular structures, BigInt, etc.) by attempting to serialize knowledge.content (e.g., JSON.stringify) inside a try/catch and throwing a descriptive Error if serialization fails; keep the rest of the entry creation (generateId(), sharedBy/ topic/ tags cloning, timestamp) unchanged.
880-891:⚠️ Potential issue | 🟠 MajorWrite
swarms.jsonatomically.This updates the persistence file in place. If the process exits mid-write, the next
loadFromDisk()can hit truncated JSON and hard-fail until the file is repaired.As per coding guidelines, "Verify error handling is comprehensive with proper try/catch and error context."Suggested fix
async _saveToDisk() { const dir = path.dirname(this._persistPath); + const tempPath = `${this._persistPath}.tmp`; await fs.mkdir(dir, { recursive: true }); const data = { version: '1.0.0', savedAt: new Date().toISOString(), stats: this._stats, swarms: this._serializeSwarms(), }; - await fs.writeFile(this._persistPath, JSON.stringify(data, null, 2), 'utf8'); + await fs.writeFile(tempPath, JSON.stringify(data, null, 2), 'utf8'); + await fs.rename(tempPath, this._persistPath); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.aiox-core/core/orchestration/swarm-intelligence.js around lines 880 - 891, In _saveToDisk(), avoid overwriting this._persistPath directly; instead write the JSON to a temp file in the same directory (e.g., this._persistPath + '.tmp' or use a UUID suffix), fs.writeFile the temp, fs.fsync (or ensure write is flushed), then fs.rename the temp to this._persistPath to make the update atomic; wrap the whole sequence in try/catch and include contextual info (persistPath, temp name) in the thrown/logged error so loadFromDisk() never sees a partially-written file.
319-330:⚠️ Potential issue | 🟠 MajorValidate
proposal.deadlineMsbefore computing the deadline.
NaN,Infinity, or negative values produce invalid or already-expired timestamps here.Invalid Datethen bypasses both expiry checks because the comparison is always false.As per coding guidelines, "Check for proper input validation on public API methods."Suggested fix
const id = generateId(); const deadlineMs = proposal.deadlineMs ?? 300000; + if (!Number.isFinite(deadlineMs) || deadlineMs < 0) { + throw new Error('proposal.deadlineMs must be a non-negative finite number'); + } const created = { id, swarmId, proposedBy: proposal.proposedBy,🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.aiox-core/core/orchestration/swarm-intelligence.js around lines 319 - 330, Validate proposal.deadlineMs before using it to compute the deadline: in the code path that creates the proposal object (where id is set via generateId() and the created object is built), check that proposal.deadlineMs is a finite positive number (Number.isFinite and > 0); if it is NaN, Infinity, negative, or otherwise invalid, fall back to the default (300000) or clamp to a safe minimum, then use that sanitized value when computing deadline (new Date(Date.now() + deadlineMs)). Ensure the same validated value is used both for assigning deadlineMs and for constructing created.deadline so expired/invalid Date objects are never produced.
372-375:⚠️ Potential issue | 🟠 MajorDon't mark the proposal
EXPIREDand then throw.That strands the proposal outside the normal resolution path:
resolveProposal()will now reject it as already resolved, soresolvedAt, stats, event emission, and persistence never happen.Suggested fix
// Check deadline if (new Date(proposal.deadline) < new Date()) { - proposal.status = PROPOSAL_STATUS.EXPIRED; throw new Error(`Proposal ${proposalId} has expired`); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.aiox-core/core/orchestration/swarm-intelligence.js around lines 372 - 375, Don’t mutate proposal.status to PROPOSAL_STATUS.EXPIRED and then throw — that bypasses the normal resolution flow. Instead, when the deadline check fails either (a) throw before changing proposal.status (leave the mutation to the caller/handler), or preferably (b) call the existing resolveProposal(proposalId, PROPOSAL_STATUS.EXPIRED) (or resolveProposal(proposalId) if it accepts a status) so the expired state is applied through the normal resolution path that sets resolvedAt, updates stats, emits events and persists; remove the direct assignment to proposal.status in the deadline check and use resolveProposal/proposalId/PROPOSAL_STATUS.EXPIRED accordingly.
🤖 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/orchestration/swarm-intelligence.js:
- Around line 864-872: The _persistAsync() implementation currently swallows
disk errors by only calling this._log(), which is disabled by default; update
the .catch on this._pendingSave (and any path in _saveToDisk()) to both log with
full error context and surface the failure: call a persistent logger or error
handler (e.g., this._logError or this.emit('error', err)) and rethrow or reject
so callers can handle it; ensure _pendingSave resolves to a rejected Promise on
failure (do not suppress the error), include identifying context (e.g.,
this.options.persist, method _saveToDisk(), and this._pendingSave) in the logged
message, and preserve the original error stack when propagating.
- Around line 151-163: The current validation for consensusThreshold, minAgents,
and maxAgents allows NaN and non-integer values; update the checks so
consensusThreshold uses Number.isFinite(consensusThreshold) (not just typeof)
and still enforces 0 <= consensusThreshold <= 1, and enforce minAgents and
maxAgents with Number.isInteger(minAgents) and Number.isInteger(maxAgents) plus
the existing bounds (minAgents >= 1 and maxAgents >= minAgents); reference the
existing symbols consensusThreshold, minAgents, and maxAgents and reject/throw
if any of these validations fail.
In `@tests/core/orchestration/swarm-intelligence.test.js`:
- Around line 1015-1028: Add an assertion to the existing exports test to verify
the backward-compatibility wrapper at the .aios-core entrypoint exports the same
things as the canonical module:
require('../../../.aios-core/core/orchestration/swarm-intelligence') should
equal SwarmIntelligence and its .SwarmIntelligence property should also equal
SwarmIntelligence; also assert the same constants (VOTING_STRATEGIES,
PROPOSAL_STATUS, SWARM_STATUS, LEADER_CRITERIA, VOTE_OPTIONS) are defined when
loaded via the .aios-core require path to ensure the wrapper remains compatible.
---
Duplicate comments:
In @.aiox-core/core/orchestration/swarm-intelligence.js:
- Around line 631-644: The code currently only checks for null/undefined content
but doesn't ensure the content is JSON-serializable; update the validation
before generating an entry (around the existing knowledge.content checks and
before generateId()) to proactively reject non-serializable values (circular
structures, BigInt, etc.) by attempting to serialize knowledge.content (e.g.,
JSON.stringify) inside a try/catch and throwing a descriptive Error if
serialization fails; keep the rest of the entry creation (generateId(),
sharedBy/ topic/ tags cloning, timestamp) unchanged.
- Around line 880-891: In _saveToDisk(), avoid overwriting this._persistPath
directly; instead write the JSON to a temp file in the same directory (e.g.,
this._persistPath + '.tmp' or use a UUID suffix), fs.writeFile the temp,
fs.fsync (or ensure write is flushed), then fs.rename the temp to
this._persistPath to make the update atomic; wrap the whole sequence in
try/catch and include contextual info (persistPath, temp name) in the
thrown/logged error so loadFromDisk() never sees a partially-written file.
- Around line 319-330: Validate proposal.deadlineMs before using it to compute
the deadline: in the code path that creates the proposal object (where id is set
via generateId() and the created object is built), check that
proposal.deadlineMs is a finite positive number (Number.isFinite and > 0); if it
is NaN, Infinity, negative, or otherwise invalid, fall back to the default
(300000) or clamp to a safe minimum, then use that sanitized value when
computing deadline (new Date(Date.now() + deadlineMs)). Ensure the same
validated value is used both for assigning deadlineMs and for constructing
created.deadline so expired/invalid Date objects are never produced.
- Around line 372-375: Don’t mutate proposal.status to PROPOSAL_STATUS.EXPIRED
and then throw — that bypasses the normal resolution flow. Instead, when the
deadline check fails either (a) throw before changing proposal.status (leave the
mutation to the caller/handler), or preferably (b) call the existing
resolveProposal(proposalId, PROPOSAL_STATUS.EXPIRED) (or
resolveProposal(proposalId) if it accepts a status) so the expired state is
applied through the normal resolution path that sets resolvedAt, updates stats,
emits events and persists; remove the direct assignment to proposal.status in
the deadline check and use resolveProposal/proposalId/PROPOSAL_STATUS.EXPIRED
accordingly.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 5f6f1edc-8136-4237-9055-37cc76790a2b
📒 Files selected for processing (4)
.aios-core/core/orchestration/swarm-intelligence.js.aiox-core/core/orchestration/swarm-intelligence.js.aiox-core/install-manifest.yamltests/core/orchestration/swarm-intelligence.test.js
| const consensusThreshold = config.consensusThreshold ?? 0.6; | ||
| if (typeof consensusThreshold !== 'number' || consensusThreshold < 0 || consensusThreshold > 1) { | ||
| throw new Error('consensusThreshold must be a number between 0 and 1'); | ||
| } | ||
|
|
||
| const minAgents = config.minAgents ?? 2; | ||
| const maxAgents = config.maxAgents ?? 50; | ||
|
|
||
| if (minAgents < 1) { | ||
| throw new Error('minAgents must be at least 1'); | ||
| } | ||
| if (maxAgents < minAgents) { | ||
| throw new Error('maxAgents must be >= minAgents'); |
There was a problem hiding this comment.
Reject NaN and non-integer swarm config values.
These checks allow NaN through today because typeof NaN === 'number' and all the comparisons return false. That can silently disable capacity/quorum logic and poison health calculations.
Suggested fix
const votingStrategy = config.votingStrategy ?? VOTING_STRATEGIES.MAJORITY;
if (!Object.values(VOTING_STRATEGIES).includes(votingStrategy)) {
throw new Error(`Invalid voting strategy: ${votingStrategy}. Must be one of: ${Object.values(VOTING_STRATEGIES).join(', ')}`);
}
const consensusThreshold = config.consensusThreshold ?? 0.6;
- if (typeof consensusThreshold !== 'number' || consensusThreshold < 0 || consensusThreshold > 1) {
+ if (!Number.isFinite(consensusThreshold) || consensusThreshold < 0 || consensusThreshold > 1) {
throw new Error('consensusThreshold must be a number between 0 and 1');
}
const minAgents = config.minAgents ?? 2;
const maxAgents = config.maxAgents ?? 50;
- if (minAgents < 1) {
+ if (!Number.isInteger(minAgents) || minAgents < 1) {
throw new Error('minAgents must be at least 1');
}
- if (maxAgents < minAgents) {
+ if (!Number.isInteger(maxAgents) || maxAgents < minAgents) {
throw new Error('maxAgents must be >= minAgents');
}As per coding guidelines, "Check for proper input validation on public API methods."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.aiox-core/core/orchestration/swarm-intelligence.js around lines 151 - 163,
The current validation for consensusThreshold, minAgents, and maxAgents allows
NaN and non-integer values; update the checks so consensusThreshold uses
Number.isFinite(consensusThreshold) (not just typeof) and still enforces 0 <=
consensusThreshold <= 1, and enforce minAgents and maxAgents with
Number.isInteger(minAgents) and Number.isInteger(maxAgents) plus the existing
bounds (minAgents >= 1 and maxAgents >= minAgents); reference the existing
symbols consensusThreshold, minAgents, and maxAgents and reject/throw if any of
these validations fail.
| _persistAsync() { | ||
| if (!this.options.persist) return; | ||
|
|
||
| // Serialize writes to prevent concurrent fs operations | ||
| this._pendingSave = (this._pendingSave || Promise.resolve()) | ||
| .then(() => this._saveToDisk()) | ||
| .catch((err) => { | ||
| this._log(`Persistence error: ${err.message}`); | ||
| }); |
There was a problem hiding this comment.
Persistence failures are silently swallowed by default.
_persistAsync() catches save errors, but it only routes them through _log(), and _log() is disabled when debug is false by default. Disk/permission failures become silent data loss.
Suggested fix
this._pendingSave = (this._pendingSave || Promise.resolve())
.then(() => this._saveToDisk())
.catch((err) => {
- this._log(`Persistence error: ${err.message}`);
+ const message = `Failed to persist swarm state to ${this._persistPath}: ${err.message}`;
+ console.error(`[SwarmIntelligence] ${message}`);
+ this.emit('swarm:persistence-error', {
+ path: this._persistPath,
+ error: err,
+ message,
+ });
});As per coding guidelines, "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/orchestration/swarm-intelligence.js around lines 864 - 872,
The _persistAsync() implementation currently swallows disk errors by only
calling this._log(), which is disabled by default; update the .catch on
this._pendingSave (and any path in _saveToDisk()) to both log with full error
context and surface the failure: call a persistent logger or error handler
(e.g., this._logError or this.emit('error', err)) and rethrow or reject so
callers can handle it; ensure _pendingSave resolves to a rejected Promise on
failure (do not suppress the error), include identifying context (e.g.,
this.options.persist, method _saveToDisk(), and this._pendingSave) in the logged
message, and preserve the original error stack when propagating.
| describe('exports', () => { | ||
| it('should export SwarmIntelligence as default and named', () => { | ||
| const mod = require('../../../.aiox-core/core/orchestration/swarm-intelligence'); | ||
| expect(mod).toBe(SwarmIntelligence); | ||
| expect(mod.SwarmIntelligence).toBe(SwarmIntelligence); | ||
| }); | ||
|
|
||
| it('should export constants', () => { | ||
| expect(VOTING_STRATEGIES).toBeDefined(); | ||
| expect(PROPOSAL_STATUS).toBeDefined(); | ||
| expect(SWARM_STATUS).toBeDefined(); | ||
| expect(LEADER_CRITERIA).toBeDefined(); | ||
| expect(VOTE_OPTIONS).toBeDefined(); | ||
| }); |
There was a problem hiding this comment.
Add an export assertion for the .aios-core compatibility entrypoint.
The suite only proves the canonical .aiox-core path. The new backward-compat wrapper can still drift or break without any red test.
Suggested test addition
describe('exports', () => {
it('should export SwarmIntelligence as default and named', () => {
const mod = require('../../../.aiox-core/core/orchestration/swarm-intelligence');
expect(mod).toBe(SwarmIntelligence);
expect(mod.SwarmIntelligence).toBe(SwarmIntelligence);
});
it('should export constants', () => {
expect(VOTING_STRATEGIES).toBeDefined();
expect(PROPOSAL_STATUS).toBeDefined();
expect(SWARM_STATUS).toBeDefined();
expect(LEADER_CRITERIA).toBeDefined();
expect(VOTE_OPTIONS).toBeDefined();
});
+
+ it('should expose the same API through the .aios-core compatibility entrypoint', () => {
+ const compat = require('../../../.aios-core/core/orchestration/swarm-intelligence');
+ expect(compat).toBe(SwarmIntelligence);
+ expect(compat.SwarmIntelligence).toBe(SwarmIntelligence);
+ expect(compat.VOTING_STRATEGIES).toBe(VOTING_STRATEGIES);
+ expect(compat.PROPOSAL_STATUS).toBe(PROPOSAL_STATUS);
+ expect(compat.SWARM_STATUS).toBe(SWARM_STATUS);
+ expect(compat.LEADER_CRITERIA).toBe(LEADER_CRITERIA);
+ expect(compat.VOTE_OPTIONS).toBe(VOTE_OPTIONS);
+ });
});As per coding guidelines, "Ensure backwards compatibility — core modules are consumed by all agents." and "Verify test coverage exists for new/modified functions."
📝 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.
| describe('exports', () => { | |
| it('should export SwarmIntelligence as default and named', () => { | |
| const mod = require('../../../.aiox-core/core/orchestration/swarm-intelligence'); | |
| expect(mod).toBe(SwarmIntelligence); | |
| expect(mod.SwarmIntelligence).toBe(SwarmIntelligence); | |
| }); | |
| it('should export constants', () => { | |
| expect(VOTING_STRATEGIES).toBeDefined(); | |
| expect(PROPOSAL_STATUS).toBeDefined(); | |
| expect(SWARM_STATUS).toBeDefined(); | |
| expect(LEADER_CRITERIA).toBeDefined(); | |
| expect(VOTE_OPTIONS).toBeDefined(); | |
| }); | |
| describe('exports', () => { | |
| it('should export SwarmIntelligence as default and named', () => { | |
| const mod = require('../../../.aiox-core/core/orchestration/swarm-intelligence'); | |
| expect(mod).toBe(SwarmIntelligence); | |
| expect(mod.SwarmIntelligence).toBe(SwarmIntelligence); | |
| }); | |
| it('should export constants', () => { | |
| expect(VOTING_STRATEGIES).toBeDefined(); | |
| expect(PROPOSAL_STATUS).toBeDefined(); | |
| expect(SWARM_STATUS).toBeDefined(); | |
| expect(LEADER_CRITERIA).toBeDefined(); | |
| expect(VOTE_OPTIONS).toBeDefined(); | |
| }); | |
| it('should expose the same API through the .aios-core compatibility entrypoint', () => { | |
| const compat = require('../../../.aios-core/core/orchestration/swarm-intelligence'); | |
| expect(compat).toBe(SwarmIntelligence); | |
| expect(compat.SwarmIntelligence).toBe(SwarmIntelligence); | |
| expect(compat.VOTING_STRATEGIES).toBe(VOTING_STRATEGIES); | |
| expect(compat.PROPOSAL_STATUS).toBe(PROPOSAL_STATUS); | |
| expect(compat.SWARM_STATUS).toBe(SWARM_STATUS); | |
| expect(compat.LEADER_CRITERIA).toBe(LEADER_CRITERIA); | |
| expect(compat.VOTE_OPTIONS).toBe(VOTE_OPTIONS); | |
| }); | |
| }); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@tests/core/orchestration/swarm-intelligence.test.js` around lines 1015 -
1028, Add an assertion to the existing exports test to verify the
backward-compatibility wrapper at the .aios-core entrypoint exports the same
things as the canonical module:
require('../../../.aios-core/core/orchestration/swarm-intelligence') should
equal SwarmIntelligence and its .SwarmIntelligence property should also equal
SwarmIntelligence; also assert the same constants (VOTING_STRATEGIES,
PROPOSAL_STATUS, SWARM_STATUS, LEADER_CRITERIA, VOTE_OPTIONS) are defined when
loaded via the .aios-core require path to ensure the wrapper remains compatible.
Summary
ORCH-5) for emergent intelligence from multi-agent collaboration.aios-core/core/orchestration/Details
.aiox-core/core/orchestration/swarm-intelligence.js.aios-core/core/orchestration/swarm-intelligence.jstests/core/orchestration/swarm-intelligence.test.js??for defaults per codebase conventionfs.promisesto.aiox/swarms.jsonswarm:created,swarm:joined,swarm:left,proposal:created,proposal:voted,proposal:resolved,knowledge:shared,leader:elected,swarm:dissolvedTest plan
npx jest tests/core/orchestration/swarm-intelligence.test.js)Summary by CodeRabbit