Add cross-project pattern registry for retrieval-augmented generalization

- Create patterns/ directory with README, manifest, and 10 initial patterns
  covering Ollama JSON fallback, API escaping, deprecation, PTY auth,
  queue-poll, LLM-as-parser, credential rotation, reverse proxy binding,
  human approval gates, and transient retry.
- Wire pattern loading into architecture/pipeline.js based on task tags.
- Update architecture/orchestrator.js to load patterns and surface them in
  the system prompt.
- Update MEMORY.md, ARCHITECTURE.md, and CONTEXT.md to document the registry
  and record the decision.
This commit is contained in:
JC Beasley
2026-08-06 12:46:09 -07:00
parent d8989f9371
commit 0bd719ab91
17 changed files with 676 additions and 32 deletions
+15 -2
View File
@@ -98,6 +98,9 @@ class AgentOrchestrator {
// Load relevant memory
await this.pipeline.loadRelevantMemory(userInput, 5);
// Load cross-project patterns based on task input
await this.pipeline.loadPatterns(userInput);
// Build final packet
const packet = this.pipeline.buildPacket(userInput);
@@ -130,10 +133,20 @@ class AgentOrchestrator {
'',
'---',
'',
'# Memory',
contextPacket.memory.substring(0, 1000) // Truncate for brevity
'# Preferences',
contextPacket.preferences.substring(0, 2000) // Truncate for brevity
];
if (contextPacket.memory && contextPacket.memory.trim()) {
parts.push(
'',
'---',
'',
'# Memory',
contextPacket.memory.substring(0, 1000) // Truncate for brevity
);
}
return parts.join('\n');
}
+48 -3
View File
@@ -14,9 +14,51 @@ class ContextPipeline {
this.rules = [];
this.preferences = [];
this.memory = [];
this.patterns = [];
this.context = {};
}
/**
* Step 3b: Load Relevant Cross-Project Patterns
*/
async loadPatterns(taskInput) {
const manifestPath = path.join('/home/jcbeasley/.openclaw/workspace', 'patterns', 'patterns.json');
try {
const manifestRaw = fs.readFileSync(manifestPath, 'utf8');
const manifest = JSON.parse(manifestRaw);
const query = (taskInput || '').toLowerCase();
for (const pattern of manifest.patterns || []) {
const tokens = [
...(pattern.tags || []),
...(pattern.affected_projects || []),
pattern.id,
pattern.name
].map(t => t.toLowerCase());
const matched = tokens.some(token => query.includes(token));
if (!matched) continue;
const patternFile = path.join('/home/jcbeasley/.openclaw/workspace', pattern.file);
try {
const content = fs.readFileSync(patternFile, 'utf8');
this.patterns.push({
source: pattern.file,
content: content,
priority: 6,
id: pattern.id
});
} catch (err) {
// Pattern file missing; skip
}
}
} catch (err) {
// Manifest missing or invalid; skip pattern loading
}
return this;
}
/**
* Step 1: Load Behavior Rules (always injected)
*/
@@ -83,7 +125,7 @@ class ContextPipeline {
}
/**
* Step 3: Load Relevant Memory
* Step 3a: Load Relevant Memory
*/
async loadRelevantMemory(query, maxResults = 5) {
// For now, load recent episodic memories
@@ -129,7 +171,8 @@ class ContextPipeline {
const allContext = [
...this.rules,
...this.preferences.sort((a, b) => b.priority - a.priority),
...this.memory
...this.memory,
...this.patterns
];
const packet = {
@@ -140,7 +183,8 @@ class ContextPipeline {
metadata: {
rules_count: this.rules.length,
prefs_count: this.preferences.length,
memory_count: this.memory.length
memory_count: this.memory.length,
patterns_count: this.patterns.length
}
};
@@ -184,6 +228,7 @@ if (require.main === module) {
.loadRules()
.then(() => pipeline.loadPreferences())
.then(() => pipeline.loadRelevantMemory(process.argv[2] || ''))
.then(() => pipeline.loadPatterns(process.argv[2] || ''))
.then(() => {
const packet = pipeline.buildPacket(process.argv[2] || 'No task specified');
console.log(JSON.stringify(packet, null, 2));