Establish baseline: core documentation and memory system

Adds foundational workspace documentation:
- Core identity and operating principles (SOUL.md, IDENTITY.md, AGENTS.md, USER.md)
- Memory management system specification (MEMORY.md)
- Development team context and workflow (CONTEXT.md, PROJECTS.md)
- Environment notes template (TOOLS.md)
- Heartbeat task template (HEARTBEAT.md)

Includes super-enhanced memory system:
- JavaScript memory engine implementation
- Memory initialization and test scripts
- Daily memory logs for 2026-07-03, 2026-07-04
- Project-level memory structure for site-survey-ai

Adds project templates:
- Standard Python Flask application template
This commit is contained in:
JC Beasley
2026-07-04 15:11:30 -07:00
commit a1aca9bfc6
47 changed files with 2693 additions and 0 deletions
@@ -0,0 +1,404 @@
/**
* Super-Enhanced Memory System Implementation
* Based on the specification provided by JC Beasley
*/
// Memory Categories
const MEMORY_CATEGORIES = {
IDENTITY: 'identity',
PREFERENCES: 'preferences',
GOALS: 'goals',
KNOWLEDGE: 'knowledge',
EPISODIC: 'episodic',
CORRECTION: 'correction'
};
// Memory Structure
class MemoryItem {
constructor(key, category, content, importance = 5, tags = []) {
this.key = key;
this.category = category;
this.content = content;
this.importance = importance;
this.tags = tags;
this.created = new Date().toISOString();
this.updated = new Date().toISOString();
this.access_count = 0;
this.expires = null;
this.confidence = 1.0;
}
}
// Memory Index
class MemoryIndex {
constructor() {
this.index = {};
}
async updateIndex(key, memory) {
try {
// In a real implementation, this would use window.storage
// For now, we'll simulate it with file-based storage
const indexPath = '/home/jcbeasley/.openclaw/workspace/memory/_index.json';
// Load existing index
let index = {};
try {
const indexContent = await this.readFile(indexPath);
if (indexContent) {
index = JSON.parse(indexContent);
}
} catch (e) {
// Index doesn't exist yet, start fresh
}
// Update index
index[key] = {
category: memory.category,
importance: memory.importance,
updated: memory.updated,
tags: memory.tags
};
// Save index
await this.writeFile(indexPath, JSON.stringify(index, null, 2));
} catch (e) {
console.error(`Failed to update memory index for ${key}:`, e);
}
}
async readFile(path) {
// Simulate file reading
// In real implementation, this would use actual file system or storage API
return null;
}
async writeFile(path, content) {
// Simulate file writing
// In real implementation, this would use actual file system or storage API
}
}
// Memory Manager
class MemoryManager {
constructor() {
this.index = new MemoryIndex();
this.storagePrefix = 'mem:';
}
// Create a memory item
async createMemory(key, category, content, importance = 5, tags = []) {
const memory = new MemoryItem(key, category, content, importance, tags);
await this.saveMemory(key, memory);
return memory;
}
// Save memory to storage
async saveMemory(key, memory) {
try {
// In a real implementation, this would use window.storage.set
// For now, we'll store in our project memory directory
const memoryPath = `/home/jcbeasley/.openclaw/workspace/memory/items/${key.replace(':', '_')}.json`;
// Ensure directory exists
await this.ensureDirectory('/home/jcbeasley/.openclaw/workspace/memory/items/');
// Save memory item
const fs = require('fs').promises;
await fs.writeFile(memoryPath, JSON.stringify(memory, null, 2));
// Update index
await this.index.updateIndex(key, memory);
console.log(`Memory saved: ${key}`);
} catch (e) {
console.error(`Failed to save memory ${key}:`, e);
}
}
// Load memory from storage
async loadMemory(key) {
try {
// In a real implementation, this would use window.storage.get
const memoryPath = `/home/jcbeasley/.openclaw/workspace/memory/items/${key.replace(':', '_')}.json`;
const fs = require('fs').promises;
const content = await fs.readFile(memoryPath, 'utf8');
const memory = JSON.parse(content);
// Update access count
memory.access_count = (memory.access_count || 0) + 1;
memory.updated = new Date().toISOString();
await this.saveMemory(key, memory);
return memory;
} catch (e) {
console.error(`Failed to load memory ${key}:`, e);
return null;
}
}
// Update existing memory (merge, don't overwrite)
async updateMemory(key, newContent) {
try {
let memory = await this.loadMemory(key);
if (memory) {
// Merge content
if (typeof memory.content === 'object' && typeof newContent === 'object') {
memory.content = { ...memory.content, ...newContent };
} else {
memory.content = newContent;
}
memory.updated = new Date().toISOString();
memory.access_count = (memory.access_count || 0) + 1;
await this.saveMemory(key, memory);
return memory;
} else {
// Create new memory
return await this.createMemory(key, MEMORY_CATEGORIES.KNOWLEDGE, newContent);
}
} catch (e) {
console.error(`Failed to update memory ${key}:`, e);
return null;
}
}
// Delete memory
async deleteMemory(key) {
try {
// In a real implementation, this would use window.storage.delete
const memoryPath = `/home/jcbeasley/.openclaw/workspace/memory/items/${key.replace(':', '_')}.json`;
const fs = require('fs').promises;
await fs.unlink(memoryPath);
console.log(`Memory deleted: ${key}`);
} catch (e) {
console.error(`Failed to delete memory ${key}:`, e);
}
}
// Expire memory (soft delete)
async expireMemory(key) {
try {
let memory = await this.loadMemory(key);
if (memory) {
memory.expires = new Date().toISOString();
await this.saveMemory(key, memory);
}
} catch (e) {
console.error(`Failed to expire memory ${key}:`, e);
}
}
// Ensure directory exists
async ensureDirectory(dirPath) {
const fs = require('fs').promises;
try {
await fs.mkdir(dirPath, { recursive: true });
} catch (e) {
// Directory might already exist
}
}
// Proactive memory behaviors
async conversationStart() {
console.log("Starting conversation with proactive memory loading...");
// Load memory index
const indexPath = '/home/jcbeasley/.openclaw/workspace/memory/_index.json';
let index = {};
try {
const fs = require('fs').promises;
const indexContent = await fs.readFile(indexPath, 'utf8');
index = JSON.parse(indexContent);
} catch (e) {
// Index doesn't exist yet
}
// Load high importance memories (>= 7)
const highImportanceMemories = [];
for (const [key, metadata] of Object.entries(index)) {
if (metadata.importance >= 7) {
const memory = await this.loadMemory(key);
if (memory) {
highImportanceMemories.push(memory);
}
}
}
console.log(`Loaded ${highImportanceMemories.length} high-importance memories`);
return highImportanceMemories;
}
// Auto-capture memories during conversation
async autoCapture(userMessage, context) {
// User states their name
if (userMessage.toLowerCase().includes("my name is") || userMessage.toLowerCase().includes("i'm") || userMessage.toLowerCase().includes("i am")) {
const nameMatch = userMessage.match(/(?:my name is|i'm|i am)\s+([a-zA-Z]+)/i);
if (nameMatch) {
await this.createMemory('mem:identity:name', MEMORY_CATEGORIES.IDENTITY, nameMatch[1], 10, ['name']);
}
}
// User corrects information
if (userMessage.toLowerCase().includes("actually") || userMessage.toLowerCase().includes("no,") || userMessage.toLowerCase().includes("correction")) {
await this.createMemory(`mem:correction:${Date.now()}`, MEMORY_CATEGORIES.CORRECTION, userMessage, 8, ['correction']);
}
// User expresses preferences
if (userMessage.toLowerCase().includes("prefer") || userMessage.toLowerCase().includes("like") || userMessage.toLowerCase().includes("want")) {
const prefMatch = userMessage.match(/(?:prefer|like|want)\s+(.+?)(?:\.|$)/i);
if (prefMatch) {
await this.createMemory(`mem:pref:${prefMatch[1].toLowerCase().replace(/\s+/g, '_')}`, MEMORY_CATEGORIES.PREFERENCES, prefMatch[1], 7, ['preference']);
}
}
// User mentions goals/projects
if (userMessage.toLowerCase().includes("goal") || userMessage.toLowerCase().includes("project") || userMessage.toLowerCase().includes("task")) {
const goalMatch = userMessage.match(/(?:goal|project|task)\s+(.+?)(?:\.|$)/i);
if (goalMatch) {
await this.createMemory(`mem:goal:${goalMatch[1].toLowerCase().replace(/\s+/g, '_')}`, MEMORY_CATEGORIES.GOALS, goalMatch[1], 8, ['goal']);
}
}
}
// Special commands handling
async handleSpecialCommand(command) {
switch (command.toLowerCase()) {
case "what do you remember about me?":
return await this.listIdentityMemories();
case "show my memory profile":
return await this.showMemoryProfile();
default:
if (command.toLowerCase().startsWith("remember that")) {
const content = command.substring("remember that".length).trim();
return await this.createMemory(`mem:episodic:${Date.now()}`, MEMORY_CATEGORIES.EPISODIC, content, 9, ['user-requested']);
} else if (command.toLowerCase().startsWith("forget")) {
const tag = command.substring("forget".length).trim();
return await this.forgetMemoriesWithTag(tag);
} else if (command.toLowerCase().startsWith("update your memory:")) {
const content = command.substring("update your memory:".length).trim();
return await this.updateMemoryByContent(content);
}
}
}
async listIdentityMemories() {
// List high-importance identity memories
const indexPath = '/home/jcbeasley/.openclaw/workspace/memory/_index.json';
let index = {};
try {
const fs = require('fs').promises;
const indexContent = await fs.readFile(indexPath, 'utf8');
index = JSON.parse(indexContent);
} catch (e) {
// Index doesn't exist yet
}
const identityMemories = [];
for (const [key, metadata] of Object.entries(index)) {
if (metadata.category === MEMORY_CATEGORIES.IDENTITY || metadata.importance >= 8) {
const memory = await this.loadMemory(key);
if (memory) {
identityMemories.push(memory);
}
}
}
return identityMemories;
}
async showMemoryProfile() {
const indexPath = '/home/jcbeasley/.openclaw/workspace/memory/_index.json';
let index = {};
try {
const fs = require('fs').promises;
const indexContent = await fs.readFile(indexPath, 'utf8');
index = JSON.parse(indexContent);
} catch (e) {
// Index doesn't exist yet
}
const profile = {
total: Object.keys(index).length,
byCategory: {},
byImportance: {},
recent: []
};
// Categorize memories
for (const [key, metadata] of Object.entries(index)) {
// By category
profile.byCategory[metadata.category] = (profile.byCategory[metadata.category] || 0) + 1;
// By importance
const importanceLevel = Math.floor(metadata.importance / 2) * 2; // Group by 2s
profile.byImportance[importanceLevel] = (profile.byImportance[importanceLevel] || 0) + 1;
// Recent memories (last 5)
if (profile.recent.length < 5) {
profile.recent.push({ key, ...metadata });
}
}
return profile;
}
async forgetMemoriesWithTag(tag) {
const indexPath = '/home/jcbeasley/.openclaw/workspace/memory/_index.json';
let index = {};
try {
const fs = require('fs').promises;
const indexContent = await fs.readFile(indexPath, 'utf8');
index = JSON.parse(indexContent);
} catch (e) {
// Index doesn't exist yet
}
const deletedKeys = [];
for (const [key, metadata] of Object.entries(index)) {
if (metadata.tags && metadata.tags.includes(tag)) {
await this.deleteMemory(key);
delete index[key];
deletedKeys.push(key);
}
}
// Save updated index
await this.index.writeFile(indexPath, JSON.stringify(index, null, 2));
return `Deleted ${deletedKeys.length} memories with tag '${tag}': ${deletedKeys.join(', ')}`;
}
async updateMemoryByContent(content) {
// This would search for related memories and update them
// For now, we'll create a new memory
return await this.createMemory(`mem:knowledge:${Date.now()}`, MEMORY_CATEGORIES.KNOWLEDGE, content, 6, ['user-updated']);
}
}
// Export for use
module.exports = { MemoryManager, MEMORY_CATEGORIES };
// Example usage:
/*
const memoryManager = new MemoryManager();
// At conversation start
await memoryManager.conversationStart();
// Auto-capture during conversation
await memoryManager.autoCapture("My name is JC", {});
// Create specific memories
await memoryManager.createMemory('mem:identity:name', MEMORY_CATEGORIES.IDENTITY, 'JC', 10, ['name']);
await memoryManager.createMemory('mem:pref:format', MEMORY_CATEGORIES.PREFERENCES, 'concise answers', 7, ['format']);
// Load memories
const nameMemory = await memoryManager.loadMemory('mem:identity:name');
console.log(`User's name: ${nameMemory.content}`);
*/