Anto01 fb4d55cbcd fix(memory): SQL-aggregate dashboard counts, project on update, id-based invalidate
Three bugs surfaced by the 2026-04-29 Codex review of the state-of-the-service
plan, all in the memory write/read path:

1. /admin/dashboard memory counts were derived from a confidence-sorted
   get_memories(limit=500) sample. With prod at 1091 active memories the
   dashboard reported 315 ("active in the top 500"), while integrity
   reported the SQL aggregate 1091. Replaced the sampling block with a
   new get_memory_count_summary() helper that does straight SQL aggregates
   over status/type/project. Dashboard memories.{active,candidates,...}
   now match integrity. Adds memories.{by_status,total} for completeness.

2. PUT /memory/{id} silently dropped project changes because
   MemoryUpdateRequest had no project field and update_memory() didn't
   accept one. auto_triage.py:407 detects suggested_project drift and
   issues a PUT to fix it; the fix never landed. Added project to the
   request schema and the service signature, with resolve_project_name
   canonicalization, before/after audit snapshot, and the existing
   duplicate-active check now scoped to the new project.

3. POST /memory/{id}/invalidate did _get_memories(status="active",
   limit=1) and looked for the target inside that single
   highest-confidence row. Any other active memory 404'd. Replaced with
   a direct id lookup via the new get_memory(id) helper; status branching
   stays the same (404 unknown / 200 already-invalid / 409 wrong-status /
   200 invalidated).

Tests added (9):
- test_get_memory_count_summary_returns_full_table_aggregates
- test_get_memory_returns_single_row_or_none
- test_update_memory_can_change_project_with_canonicalization
- test_update_memory_project_unchanged_when_not_passed
- test_api_invalidate_finds_active_memory_outside_top_one
- test_api_invalidate_already_invalid_is_idempotent
- test_api_invalidate_candidate_returns_409
- test_api_invalidate_unknown_id_is_404
- test_admin_dashboard_active_count_matches_full_table

Test count: 572 -> 581. Full suite green locally.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 21:40:10 -04:00

AtoCore

Personal context engine that enriches LLM interactions with durable memory, structured context, and project knowledge.

Quick Start

pip install -e .
uvicorn atocore.main:app --port 8100

Usage

# Ingest markdown files
curl -X POST http://localhost:8100/ingest \
  -H "Content-Type: application/json" \
  -d '{"path": "/path/to/notes"}'

# Build enriched context for a prompt
curl -X POST http://localhost:8100/context/build \
  -H "Content-Type: application/json" \
  -d '{"prompt": "What is the project status?", "project": "myproject"}'

# CLI ingestion
python scripts/ingest_folder.py --path /path/to/notes

# Live operator client
python scripts/atocore_client.py health
python scripts/atocore_client.py audit-query "gigabit" 5

API Endpoints

Method Path Description
POST /ingest Ingest markdown file or folder
POST /query Retrieve relevant chunks
POST /context/build Build full context pack
POST /interactions Capture prompt/response interactions
GET/POST /memory List/create durable memories
GET/POST /entities Engineering entity graph surface
GET /admin/dashboard Operator dashboard
GET /health Health check
GET /debug/context Inspect last context pack

API versioning

The public contract for external clients (AKC, OpenClaw, future tools) is served under a /v1 prefix. Every public endpoint is available at both its unversioned path and under /v1 — e.g. POST /entities and POST /v1/entities route to the same handler.

Rules:

  • New public endpoints land at the latest version prefix.
  • Backwards-compatible additions stay on the current version.
  • Breaking schema changes to an existing endpoint bump the prefix (/v2/...) and leave the prior version in place until clients migrate.
  • Unversioned paths are retained for internal callers (hooks, scripts, the wiki/admin UI). Do not rely on them from external clients — use /v1.

The authoritative list of versioned paths is in src/atocore/main.py (_V1_PUBLIC_PATHS). GET /openapi.json reflects both the versioned and unversioned forms.

Architecture

FastAPI (port 8100)
  |- Ingestion: markdown -> parse -> chunk -> embed -> store
  |- Retrieval: query -> embed -> vector search -> rank
  |- Context Builder: project state -> memories -> entities -> retrieval -> budget
  |- Reflection: capture -> reinforce -> extract -> triage -> promote/expire
  |- Engineering: typed entities, relationships, conflicts, wiki/mirror
  |- SQLite (documents, chunks, memories, projects, interactions, entities)
  '- ChromaDB (vector embeddings)

Configuration

Set via environment variables (prefix ATOCORE_):

Variable Default Description
ATOCORE_DEBUG false Enable debug logging
ATOCORE_PORT 8100 Server port
ATOCORE_CHUNK_MAX_SIZE 800 Max chunk size (chars)
ATOCORE_CONTEXT_BUDGET 3000 Context pack budget (chars)
ATOCORE_EMBEDDING_MODEL paraphrase-multilingual-MiniLM-L12-v2 Embedding model
ATOCORE_RANK_PROJECT_MATCH_BOOST 2.0 Soft boost for chunks whose metadata matches the project hint
ATOCORE_RANK_PROJECT_SCOPE_FILTER true Filter project-hinted retrieval away from other registered project corpora
ATOCORE_RANK_PROJECT_SCOPE_CANDIDATE_MULTIPLIER 4 Widen candidate pull before project-scope filtering
ATOCORE_RANK_QUERY_TOKEN_STEP 0.08 Per-token boost when query terms appear in high-signal metadata
ATOCORE_RANK_QUERY_TOKEN_CAP 1.32 Maximum query-token boost multiplier
ATOCORE_RANK_PATH_HIGH_SIGNAL_BOOST 1.18 Boost current decision/status/requirements-like paths
ATOCORE_RANK_PATH_LOW_SIGNAL_PENALTY 0.72 Down-rank archive/history-like paths

ATOCORE_RANK_PROJECT_SCOPE_FILTER gates the hard cross-project filter only. ATOCORE_RANK_PROJECT_MATCH_BOOST remains the separate soft-ranking knob.

Testing

pip install -e ".[dev]"
pytest

Operations

  • scripts/atocore_client.py provides a live API client for project refresh, project-state inspection, and retrieval-quality audits.
  • scripts/retrieval_eval.py runs the live retrieval/context harness, separates blocking failures from known content gaps, and stamps JSON output with target/build metadata.
  • scripts/live_status.py renders a compact read-only status report from /health, /stats, /projects, and /admin/dashboard; set ATOCORE_AUTH_TOKEN or --auth-token when those endpoints are gated.
  • scripts/backfill_chunk_project_ids.py dry-runs or applies explicit project_id metadata backfills for SQLite chunks and Chroma vectors; --apply requires a confirmed Chroma snapshot.
  • docs/operations.md captures the current operational priority order: retrieval quality, Wave 2 trusted-operational ingestion, AtoDrive scoping, and restore validation.
  • DEV-LEDGER.md is the fast-moving source of operational truth during active development; copy claims into docs only after checking the live service.

Architecture Notes

Implementation-facing architecture notes live under docs/architecture/.

Current additions:

  • docs/architecture/engineering-knowledge-hybrid-architecture.md — 5-layer hybrid model
  • docs/architecture/engineering-ontology-v1.md — V1 object and relationship inventory
  • docs/architecture/engineering-query-catalog.md — 20 v1-required queries
  • docs/architecture/memory-vs-entities.md — canonical home split
  • docs/architecture/promotion-rules.md — Layer 0 to Layer 2 pipeline
  • docs/architecture/conflict-model.md — contradictory facts detection and resolution
Description
ATODrive project repository
Readme 4.3 MiB
Languages
Python 95.6%
Shell 3.4%
JavaScript 0.8%
PowerShell 0.2%