tractatus/tests/poc/memory-tool/basic-persistence-test.js
TheFlow ac2db33732 fix(submissions): restructure Economist package and fix article display
- Create Economist SubmissionTracking package correctly:
  * mainArticle = full blog post content
  * coverLetter = 216-word SIR— letter
  * Links to blog post via blogPostId
- Archive 'Letter to The Economist' from blog posts (it's the cover letter)
- Fix date display on article cards (use published_at)
- Target publication already displaying via blue badge

Database changes:
- Make blogPostId optional in SubmissionTracking model
- Economist package ID: 68fa85ae49d4900e7f2ecd83
- Le Monde package ID: 68fa2abd2e6acd5691932150

Next: Enhanced modal with tabs, validation, export

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 08:47:42 +13:00

207 lines
7.6 KiB
JavaScript

/**
* Phase 5 PoC - Memory Tool Basic Persistence Test
*
* Goal: Prove that governance rules can persist across separate API calls
*
* Success Criteria:
* - Rule persists to memory tool
* - Rule retrieved in separate API call
* - Data integrity maintained (no corruption)
* - Latency overhead measured
*/
const Anthropic = require('@anthropic-ai/sdk');
const fs = require('fs').promises;
const path = require('path');
// Test configuration
const MEMORY_BASE_PATH = path.join(__dirname, '../../../.memory-poc');
const TEST_RULE = {
id: 'inst_001',
text: 'Never fabricate statistics or quantitative claims without verifiable sources',
quadrant: 'OPERATIONAL',
persistence: 'HIGH',
rationale: 'Foundational integrity principle - statistical claims must be evidence-based',
examples: [
'PASS: "MongoDB typically uses port 27017"',
'FAIL: "95% of users prefer our framework" (without source)'
],
created_at: new Date().toISOString()
};
// Simple filesystem-based memory backend
class FilesystemMemoryBackend {
constructor(basePath) {
this.basePath = basePath;
}
async initialize() {
// Create memory directory structure
await fs.mkdir(path.join(this.basePath, 'governance'), { recursive: true });
await fs.mkdir(path.join(this.basePath, 'sessions'), { recursive: true });
await fs.mkdir(path.join(this.basePath, 'audit'), { recursive: true });
console.log('✓ Memory backend initialized:', this.basePath);
}
async create(filePath, data) {
const fullPath = path.join(this.basePath, filePath);
await fs.mkdir(path.dirname(fullPath), { recursive: true });
await fs.writeFile(fullPath, JSON.stringify(data, null, 2), 'utf8');
console.log('✓ Created memory file:', filePath);
}
async view(filePath) {
const fullPath = path.join(this.basePath, filePath);
const data = await fs.readFile(fullPath, 'utf8');
console.log('✓ Retrieved memory file:', filePath);
return JSON.parse(data);
}
async exists(filePath) {
const fullPath = path.join(this.basePath, filePath);
try {
await fs.access(fullPath);
return true;
} catch {
return false;
}
}
async cleanup() {
await fs.rm(this.basePath, { recursive: true, force: true });
console.log('✓ Cleaned up memory backend');
}
}
// Test execution
async function runPoCTest() {
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log(' Phase 5 PoC: Memory Tool Basic Persistence Test');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
const backend = new FilesystemMemoryBackend(MEMORY_BASE_PATH);
const results = {
success: false,
timings: {},
errors: []
};
try {
// Step 1: Initialize backend
console.log('[Step 1] Initializing memory backend...');
const initStart = Date.now();
await backend.initialize();
results.timings.initialization = Date.now() - initStart;
console.log(` Time: ${results.timings.initialization}ms\n`);
// Step 2: Persist test rule
console.log('[Step 2] Persisting governance rule to memory...');
console.log(` Rule: ${TEST_RULE.id}`);
console.log(` Persistence: ${TEST_RULE.persistence}`);
const persistStart = Date.now();
await backend.create('governance/test-rule.json', TEST_RULE);
results.timings.persist = Date.now() - persistStart;
console.log(` Time: ${results.timings.persist}ms\n`);
// Step 3: Verify file exists
console.log('[Step 3] Verifying file persistence...');
const exists = await backend.exists('governance/test-rule.json');
if (!exists) {
throw new Error('File does not exist after creation');
}
console.log(' ✓ File exists on filesystem\n');
// Step 4: Retrieve rule (simulating separate API call)
console.log('[Step 4] Retrieving rule (separate operation)...');
const retrieveStart = Date.now();
const retrieved = await backend.view('governance/test-rule.json');
results.timings.retrieve = Date.now() - retrieveStart;
console.log(` Time: ${results.timings.retrieve}ms\n`);
// Step 5: Validate data integrity
console.log('[Step 5] Validating data integrity...');
const validations = [
{ field: 'id', expected: TEST_RULE.id, actual: retrieved.id },
{ field: 'persistence', expected: TEST_RULE.persistence, actual: retrieved.persistence },
{ field: 'quadrant', expected: TEST_RULE.quadrant, actual: retrieved.quadrant },
{ field: 'text', expected: TEST_RULE.text, actual: retrieved.text }
];
let allValid = true;
for (const validation of validations) {
const isValid = validation.expected === validation.actual;
const status = isValid ? '✓' : '✗';
console.log(` ${status} ${validation.field}: ${isValid ? 'MATCH' : 'MISMATCH'}`);
if (!isValid) {
console.log(` Expected: ${validation.expected}`);
console.log(` Actual: ${validation.actual}`);
allValid = false;
}
}
if (!allValid) {
throw new Error('Data integrity validation failed');
}
console.log('\n[Step 6] Performance Assessment...');
const totalLatency = results.timings.persist + results.timings.retrieve;
console.log(` Persist latency: ${results.timings.persist}ms`);
console.log(` Retrieve latency: ${results.timings.retrieve}ms`);
console.log(` Total overhead: ${totalLatency}ms`);
const target = 500; // PoC tolerance
const status = totalLatency < target ? 'PASS' : 'WARN';
console.log(` Target: <${target}ms - ${status}`);
results.success = true;
results.totalLatency = totalLatency;
} catch (error) {
console.error('\n✗ TEST FAILED:', error.message);
results.errors.push(error.message);
results.success = false;
} finally {
// Cleanup
console.log('\n[Cleanup] Removing test data...');
await backend.cleanup();
}
// Results summary
console.log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log(' TEST RESULTS');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
if (results.success) {
console.log('✅ SUCCESS: Rule persistence validated');
console.log('\nKey Findings:');
console.log(' • Persistence: ✓ 100% (no data loss)');
console.log(' • Data integrity: ✓ 100% (no corruption)');
console.log(` • Performance: ✓ ${results.totalLatency}ms total overhead`);
console.log('\nNext Steps:');
console.log(' 1. Integrate with Anthropic Claude API (memory tool)');
console.log(' 2. Test with inst_016, inst_017, inst_018');
console.log(' 3. Measure API latency overhead');
} else {
console.log('❌ FAILURE: Test did not pass');
console.log('\nErrors:');
results.errors.forEach(err => console.log(`${err}`));
}
console.log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
return results;
}
// Run test
if (require.main === module) {
runPoCTest()
.then(results => {
process.exit(results.success ? 0 : 1);
})
.catch(error => {
console.error('Fatal error:', error);
process.exit(1);
});
}
module.exports = { runPoCTest, FilesystemMemoryBackend };