Add memory rollout feature flags and docs

This commit is contained in:
thePR0M3TH3AN committed 2026-02-14 15:23:51 -05:00
1 parent ab680f8b7b
commit d1586228be
10 files changed
+274 -27

No files matched your search

+29
View File
@@ -8,6 +8,7 @@ import {
listMemories,
memoryStats,
pinMemory,
runPruneCycle,
triggerPruneDryRun,
unpinMemory,
} from '../src/services/memory/index.js';
@@ -104,3 +105,31 @@ test('memoryStats reports counts/rates and retrieval telemetry remains redaction
assert.ok(stats.indexSizeEstimateBytes >= 0);
assert.ok(Number.isFinite(stats.ingestThroughputPerMinute));
});
test('runPruneCycle respects prune feature-flag modes', async () => {
const repository = {
async listPruneCandidates() {
return [
{ id: 'old-1', agent_id: 'agent-z', type: 'event', pinned: false, last_seen: 1, merged_into: null },
];
},
};
const dryRunResult = await runPruneCycle({
repository,
env: { TORCH_MEMORY_PRUNE_ENABLED: 'dry-run' },
retentionMs: 1000,
});
assert.equal(dryRunResult.mode, 'dry-run');
assert.equal(dryRunResult.pruned.length, 0);
assert.equal(dryRunResult.candidates.length, 1);
const offResult = await runPruneCycle({
repository,
env: { TORCH_MEMORY_PRUNE_ENABLED: 'false' },
retentionMs: 1000,
});
assert.equal(offResult.mode, 'off');
assert.equal(offResult.pruned.length, 0);
});
+28
View File
@@ -0,0 +1,28 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import {
getMemoryPruneMode,
isMemoryEnabled,
isMemoryIngestEnabled,
isMemoryPruneEnabled,
} from '../src/services/memory/feature-flags.js';
test('memory feature flags parse defaults and canary allow-lists', () => {
assert.equal(isMemoryEnabled({}), true);
assert.equal(isMemoryEnabled({ TORCH_MEMORY_ENABLED: 'false' }), false);
assert.equal(isMemoryIngestEnabled('agent-a', {}), true);
assert.equal(isMemoryIngestEnabled('agent-a', { TORCH_MEMORY_INGEST_ENABLED: 'false' }), false);
assert.equal(isMemoryIngestEnabled('agent-a', { TORCH_MEMORY_INGEST_ENABLED: 'agent-a,agent-b' }), true);
assert.equal(isMemoryIngestEnabled('agent-c', { TORCH_MEMORY_INGEST_ENABLED: 'agent-a,agent-b' }), false);
});
test('memory prune flag supports off, dry-run, and active modes', () => {
assert.equal(getMemoryPruneMode({}), 'active');
assert.equal(getMemoryPruneMode({ TORCH_MEMORY_PRUNE_ENABLED: 'false' }), 'off');
assert.equal(getMemoryPruneMode({ TORCH_MEMORY_PRUNE_ENABLED: 'dry-run' }), 'dry-run');
assert.equal(getMemoryPruneMode({ TORCH_MEMORY_PRUNE_ENABLED: 'true' }), 'active');
assert.equal(isMemoryPruneEnabled({ TORCH_MEMORY_PRUNE_ENABLED: 'dry-run' }), false);
assert.equal(isMemoryPruneEnabled({ TORCH_MEMORY_PRUNE_ENABLED: 'true' }), true);
});
+7
View File
@@ -143,6 +143,13 @@ test('isMemoryRetrievalEnabled supports global toggle and agent canary list', ()
isMemoryRetrievalEnabled('agent-c', { TORCH_MEMORY_RETRIEVAL_ENABLED: 'agent-a,agent-b' }),
false,
);
assert.equal(
isMemoryRetrievalEnabled('agent-a', {
TORCH_MEMORY_ENABLED: 'false',
TORCH_MEMORY_RETRIEVAL_ENABLED: 'true',
}),
false,
);
});
test('renderPromptWithMemoryContext injects bounded memory block before base prompt', async () => {
+34
View File
@@ -90,3 +90,37 @@ test('startMemoryMaintenanceScheduler runs all jobs and emits metrics including
assert.equal(byJob.pruningCycle[0].payload.status, 'success');
assert.equal(byJob.deepMergeArchivalMaintenance[0].payload.status, 'success');
});
test('startMemoryMaintenanceScheduler skips jobs when feature flags disable memory', async () => {
const metrics = [];
const called = [];
const scheduler = startMemoryMaintenanceScheduler({
runImmediately: true,
env: { TORCH_MEMORY_ENABLED: 'false' },
emitMetric(name, payload) {
metrics.push({ name, payload });
},
handlers: {
async ingestRecentRuntimeEvents() {
called.push('ingest');
},
async consolidateObservations() {
called.push('consolidate');
},
async pruningCycle() {
called.push('prune');
},
async deepMergeArchivalMaintenance() {
called.push('merge');
},
},
});
await wait(10);
scheduler.stop();
assert.deepEqual(called, []);
assert.ok(metrics.some((entry) => entry.payload.status === 'skipped_flag_disabled'));
});