CI / CI (push) Successful in 15m5s
- Enable docker build, sha extraction on PRs (validate Dockerfile) - Add SOPS encrypted memory-agent credentials - Plan 15 tasks: 5 memory service + 10 temporal workflow - Milestone: monitoring-agent (due 2025-03-15) - Ready: Forgejo API token needed for PR automation ``` Co-authored-by: rock <[email protected]>
7.1 KiB
7.1 KiB
CRITICAL FIXES NEEDED - Poimen Memory Service
STATUS: Service Non-Functional ❌
Root Issues Blocking Service:
- ✅ HTTP handler deadlock fixed (schema init error handling)
- ❌ Server initialization hangs during schema or startup (logs stop after
l2_l1_edges) - ❌ Ingest pipeline NOT implemented (just raw vector storage, no entities/edges)
- ❌ Temporal schema missing (no t_valid, t_invalid, version tracking)
- ❌ GRM gate not integrated (no memorability scores, confidence)
- ❌ Query doesn't use knowledge graph (just vector search)
- ❌ Compaction disabled
- ❌ Verification gates missing
STEP 1: Fix Server Startup Hang ⚠️
Current Issue: Server hangs during initialization after schema creation.
Suspected causes:
- OptimizerServiceBuilder.build() getting stuck
- AccessGuard creation blocking
- Background task spawning deadlock
Fix:
// In http_server.rs:316-325
// Wrap in timeout or disable non-essentials
let optimizer_service = match tokio::time::timeout(
Duration::from_secs(5),
async { mem_core::optimizer::OptimizerServiceBuilder::new().build() }
).await {
Ok(Ok(service)) => Some(Arc::new(service)),
_ => {
tracing::warn!("Optimizer initialization skipped (timeout or error)");
None
}
};
Test: ./target/release/mem serve --port 9999 should reach "Starting HTTP server" within 10s
STEP 2: Implement Ingest Pipeline (HIGH PRIORITY)
Current Implementation (ingest_worker.rs):
// Just stores raw chunks + embeddings
store_chunk_l0(&l0_chunk)
store_memory_l1(&l1_memory, &embedding)
Expected Implementation:
// 1. Extract entities (entity_extractor)
let entities = entity_extractor.extract(&content).await?;
// 2. Extract facts + edges (fact_extractor)
let facts = fact_extractor.extract(&content, entities).await?;
// 3. Create temporal edges with GRM gate
for fact in facts {
let edge = TemporalEdge {
source: fact.source_entity,
target: fact.target_entity,
relation: fact.relation,
fact: fact.text,
t_valid: now(),
t_invalid: None,
confidence: grm_gate.score(&fact)?, // ← GRM gate
version: 1,
};
edge_repo.insert(&edge).await?;
}
// 4. Check contradictions + queue for review
for edge in edges {
if contradiction_detector.detect(&edge, existing_edges)? {
review_queue.enqueue(&edge).await?;
}
}
Files to modify:
crates/mem-cli/src/ingest_worker.rs(core ingest logic)crates/mem-ingest/src/ingest_pipeline.rs(entity + fact extraction)crates/mem-ingest/src/contradiction_detector.rs(pre-filter + review)
STEP 3: Update Storage Schema (MEDIUM PRIORITY)
Missing fields:
ALTER TABLE memories_l1 ADD COLUMN (
t_valid TIMESTAMP NOT NULL DEFAULT NOW(),
t_invalid TIMESTAMP,
confidence FLOAT DEFAULT 0.5,
version INT DEFAULT 1,
memorability_score INT,
contribution_date TIMESTAMP
);
ALTER TABLE l1_l0_edges MODIFY TO (
l1_id UUID,
l0_id UUID,
relation_type VARCHAR,
fact TEXT,
t_valid TIMESTAMP DEFAULT NOW(),
t_invalid TIMESTAMP,
confidence FLOAT,
contradiction_flag BOOL DEFAULT FALSE,
review_queue_id UUID,
version INT DEFAULT 1,
PRIMARY KEY (l1_id, l0_id, version)
);
Migration script: crates/mem-store/migrations/003_temporal_grm_schema.sql
STEP 4: Wire Query Handler to Knowledge Graph (MEDIUM PRIORITY)
Current (query_handler in http_server.rs):
async fn query_handler(...) -> HttpResponse {
// Just semantic search
let results = vector_search(query)?;
HttpResponse::Ok().json(results)
}
Expected:
async fn query_handler(query: QueryRequest) -> HttpResponse {
// 1. Semantic search on embeddings
let initial_results = vector_search(&query.text)?;
// 2. Follow edges (graph traversal)
let mut expanded = vec![];
for result in initial_results {
expanded.push(result);
// Get related entities via edges
let related = edge_repo.find_by_source(&result.entity_id).await?;
expanded.extend(related);
}
// 3. Apply temporal filters
expanded.retain(|e| e.t_valid <= now() && (e.t_invalid.is_none() || e.t_invalid > now()));
// 4. Sort by confidence + recency
expanded.sort_by(|a, b| {
b.confidence.partial_cmp(&a.confidence)
.then_with(|| b.t_valid.cmp(&a.t_valid))
});
// 5. Apply compaction/cache alignment
for item in &mut expanded {
item.text = optimizer.compress(item.text)?;
}
HttpResponse::Ok().json(MemoryResponse {
entities: expanded,
confidence_scores: compute_scores(&expanded),
})
}
STEP 5: Enable Compaction Endpoint (LOW PRIORITY)
Current: Code exists but never called.
Fix: Add K8s CronJob that calls POST /memory/compact daily:
apiVersion: batch/v1
kind: CronJob
metadata:
name: memory-compaction
spec:
schedule: "0 2 * * *" # 2 AM UTC
jobTemplate:
spec:
template:
spec:
containers:
- name: compact
image: bitnami/curl:latest
command:
- curl
- -X POST
- -H "Authorization: Bearer $ADMIN_TOKEN"
- http://poimen-memory:8080/memory/compact
restartPolicy: OnFailure
STEP 6: Add Verification Gates (LOW PRIORITY)
Missing: GET /memory/verify endpoint that checks M1.8, M2.8, M3.7, M8.9 gates
IMPLEMENTATION ORDER
- FIX STARTUP (1 hour) → Get server running
- INGEST PIPELINE (3 hours) → Wire entity + fact extraction
- TEMPORAL SCHEMA (1 hour) → Add missing columns
- QUERY HANDLER (2 hours) → Implement graph traversal
- COMPACTION (1 hour) → Add CronJob
- GATES (2 hours) → Quality verification
Total: ~10 hours to full working system
TEST PLAN
# 1. Server starts
curl http://localhost:9999/health
# Expected: {"status":"ok","uptime_seconds":N}
# 2. Ingest works
curl -X POST http://localhost:9999/memory/ingest \
-H "Content-Type: application/json" \
-d '{"project":"test","source":"test://1","ingest_id":"i1","records":[{"role":"user","text":"Hello world","timestamp":"2026-01-08T16:00:00Z","source_position":0}]}'
# Expected: {"ingest_id":"i1","status":"pending",...}
# 3. Query returns entities with edges
curl -X POST http://localhost:9999/memory/query \
-H "Content-Type: application/json" \
-d '{"project":"test","query":"hello"}'
# Expected: {"results":[{"type":"entity","name":"...","edges":[...]}]}
# 4. Temporal filtering works
curl http://localhost:9999/memory/query?project=test&temporal_floor=2026-01-01
# 5. Compaction works
curl -X POST http://localhost:9999/memory/compact
# Expected: {"phase":"completed","records_deduplicated":N}
FILES MODIFIED SO FAR
✅ crates/mem-cli/src/http_server.rs - Added error handling for schema init
NEXT SESSION TODO
- Fix server startup hang (debug OptimizerService)
- Implement ingest_worker to call entity_extractor + fact_extractor
- Add temporal columns to schema
- Update query_handler to traverse edges
- Test end-to-end with sample data