diff --git a/src/aipass/memory/README.md b/src/aipass/memory/README.md index b6008dd2..7e468e8e 100644 --- a/src/aipass/memory/README.md +++ b/src/aipass/memory/README.md @@ -3,7 +3,7 @@ **Purpose:** Central memory archive with semantic search, rollover, and archival across all AIPass branches. **Module:** `aipass.memory` **Created:** 2026-03-07 -**Last Updated:** 2026-03-08 +**Last Updated:** 2026-03-17 **Citizen Class:** builder --- @@ -74,9 +74,10 @@ memory/ │ │ ├── search/ # Search implementation (vector/semantic) │ │ ├── storage/ # Storage backend operations │ │ ├── tracking/ # Line count and metadata tracking +│ │ ├── symbolic/ # Symbolic dimension extraction +│ │ ├── templates/ # Template management │ │ └── vector/ # Vector DB (ChromaDB) operations │ ├── extensions/ # Extension plugins -│ ├── json_templates/ # JSON template files │ └── plugins/ # Plugin system ├── artifacts/ # Build/output artifacts ├── docs/ # Documentation @@ -117,4 +118,4 @@ The rollover module monitors memory files across all branches registered in `AIP --- -*Last Updated: 2026-03-08* +*Last Updated: 2026-03-17* diff --git a/src/aipass/memory/apps/handlers/archive/indexer.py b/src/aipass/memory/apps/handlers/archive/indexer.py index def8a57a..42abb80f 100644 --- a/src/aipass/memory/apps/handlers/archive/indexer.py +++ b/src/aipass/memory/apps/handlers/archive/indexer.py @@ -25,7 +25,7 @@ from datetime import datetime from typing import Dict, Any, List from aipass.prax.apps.modules.logger import get_system_logger -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler logger = get_system_logger() @@ -272,7 +272,7 @@ def check_for_new_files() -> Dict[str, Any]: save_index(index) - log_operation("index_sync", {"new_files": len(new_files), "deleted_files": len(deleted_files), "success": True}) + json_handler.log_operation("index_sync", {"new_files": len(new_files), "deleted_files": len(deleted_files), "success": True}) return { 'success': True, diff --git a/src/aipass/memory/apps/handlers/central_writer.py b/src/aipass/memory/apps/handlers/central_writer.py index 97897997..1f2974f4 100644 --- a/src/aipass/memory/apps/handlers/central_writer.py +++ b/src/aipass/memory/apps/handlers/central_writer.py @@ -24,7 +24,7 @@ from datetime import datetime from typing import Dict, Any from aipass.prax.apps.modules.logger import get_system_logger -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler logger = get_system_logger() @@ -260,7 +260,7 @@ def update_central(verbose: bool = False) -> Dict[str, Any]: if verbose: result["stats"] = stats - log_operation("update_central", {"vectors": stats.get("total_vectors", 0), "success": True}) + json_handler.log_operation("update_central", {"vectors": stats.get("total_vectors", 0), "success": True}) return result diff --git a/src/aipass/memory/apps/handlers/dashboard_push.py b/src/aipass/memory/apps/handlers/dashboard_push.py index 718dbd2c..22d9881d 100644 --- a/src/aipass/memory/apps/handlers/dashboard_push.py +++ b/src/aipass/memory/apps/handlers/dashboard_push.py @@ -26,7 +26,7 @@ from datetime import datetime from typing import Dict, Any, List from aipass.prax.apps.modules.logger import get_system_logger -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler logger = get_system_logger() @@ -431,7 +431,7 @@ def push_memory_bank_dashboard() -> bool: "memory_bank", section_data, branch_paths ) - log_operation("dashboard_push", {"branches_updated": success_count, "success": success_count > 0}) + json_handler.log_operation("dashboard_push", {"branches_updated": success_count, "success": success_count > 0}) return success_count > 0 diff --git a/src/aipass/memory/apps/handlers/intake/plans_processor.py b/src/aipass/memory/apps/handlers/intake/plans_processor.py index dae73a8e..84ffa05e 100644 --- a/src/aipass/memory/apps/handlers/intake/plans_processor.py +++ b/src/aipass/memory/apps/handlers/intake/plans_processor.py @@ -27,7 +27,7 @@ from datetime import datetime from typing import Dict, Any, List from aipass.prax import logger -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler # Subprocess scripts _HANDLERS_DIR = Path(__file__).resolve().parent.parent @@ -322,6 +322,6 @@ def process_plans() -> Dict[str, Any]: if errors: result['errors'] = errors - log_operation("process_plans", {"files_processed": files_processed, "total_chunks": total_chunks, "success": result['success']}) + json_handler.log_operation("process_plans", {"files_processed": files_processed, "total_chunks": total_chunks, "success": result['success']}) return result diff --git a/src/aipass/memory/apps/handlers/intake/pool_processor.py b/src/aipass/memory/apps/handlers/intake/pool_processor.py index ed522dad..38a5cfd6 100644 --- a/src/aipass/memory/apps/handlers/intake/pool_processor.py +++ b/src/aipass/memory/apps/handlers/intake/pool_processor.py @@ -1,18 +1,9 @@ -# ===================AIPASS==================== -# META DATA HEADER -# Name: pool_processor.py - Memory Pool Intake Handler -# Date: 2025-11-27 -# Version: 0.2.0 -# Category: memory/handlers/intake -# -# CHANGELOG (Max 5 entries): -# - v0.2.0 (2026-03-16): Modernize imports, paths, remove MEMORY_BANK references -# - v0.1.0 (2025-11-27): Initial version - process memory_pool files to vectors -# -# CODE STANDARDS: -# - Pure handler: No orchestration, just processing logic -# - Stateless functions -# - Returns dict with success/error +# =================== AIPass ==================== +# Name: pool_processor.py +# Description: Memory Pool Processor +# Version: 0.1.0 +# Created: 2026-03-17 +# Modified: 2026-03-17 # ============================================= """ @@ -34,7 +25,7 @@ from pathlib import Path from datetime import datetime from typing import List, Dict, Any -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler # Paths _MEMORY_ROOT = Path(__file__).resolve().parent.parent.parent.parent # handlers/intake/ → handlers/ → apps/ → memory/ @@ -448,7 +439,7 @@ def process_memory_pool() -> dict: if results['files_processed'] > 0: _update_central_and_dashboard() - log_operation("process_memory_pool", {"files_processed": results['files_processed'], "total_chunks": results['total_chunks'], "success": results['success']}) + json_handler.log_operation("process_memory_pool", {"files_processed": results['files_processed'], "total_chunks": results['total_chunks'], "success": results['success']}) return results diff --git a/src/aipass/memory/apps/handlers/json/memory_files.py b/src/aipass/memory/apps/handlers/json/memory_files.py index 4d6ae3a6..e9b668de 100644 --- a/src/aipass/memory/apps/handlers/json/memory_files.py +++ b/src/aipass/memory/apps/handlers/json/memory_files.py @@ -33,7 +33,7 @@ from typing import Dict, Any, Optional from datetime import datetime from aipass.prax.apps.modules.logger import get_system_logger -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler logger = get_system_logger() @@ -152,7 +152,7 @@ def write_memory_file(file_path: Path, data: Dict[str, Any]) -> Dict[str, Any]: # Atomic rename (overwrites original) Path(temp_path).rename(file_path) - log_operation("write_memory_file", {"file": file_path.name, "success": True}) + json_handler.log_operation("write_memory_file", {"file": file_path.name, "success": True}) return { 'success': True, diff --git a/src/aipass/memory/apps/handlers/learnings/manager.py b/src/aipass/memory/apps/handlers/learnings/manager.py index 154edff5..1064f0a5 100644 --- a/src/aipass/memory/apps/handlers/learnings/manager.py +++ b/src/aipass/memory/apps/handlers/learnings/manager.py @@ -34,7 +34,7 @@ from typing import Dict, Any, List, Tuple from datetime import datetime from aipass.prax.apps.modules.logger import get_system_logger -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler logger = get_system_logger() @@ -597,7 +597,7 @@ def enforce_limit(file_path: Path) -> Dict[str, Any]: except Exception as e: return {'success': False, 'error': f'Failed to write file: {e}'} - log_operation("enforce_limit", {"removed": to_remove_count, "remaining": len(to_keep), "success": True}) + json_handler.log_operation("enforce_limit", {"removed": to_remove_count, "remaining": len(to_keep), "success": True}) return { 'success': True, @@ -791,7 +791,7 @@ def add_learning( # Enforce limit after adding enforce_result = enforce_limit(file_path) - log_operation("add_learning", {"key": key, "action": "updated" if is_update else "added", "success": True}) + json_handler.log_operation("add_learning", {"key": key, "action": "updated" if is_update else "added", "success": True}) return { 'success': True, diff --git a/src/aipass/memory/apps/handlers/monitor/detector.py b/src/aipass/memory/apps/handlers/monitor/detector.py index a3c7d430..f4c8bbf5 100644 --- a/src/aipass/memory/apps/handlers/monitor/detector.py +++ b/src/aipass/memory/apps/handlers/monitor/detector.py @@ -27,7 +27,7 @@ from typing import List, Dict, Any from dataclasses import dataclass from aipass.prax.apps.modules.logger import get_system_logger -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler logger = get_system_logger() @@ -328,6 +328,8 @@ def check_all_branches() -> Dict[str, Any]: ) triggers.append(trigger) + json_handler.log_operation("check_all_branches", {"branches_checked": len(branches), "triggers_found": len(triggers)}) + return { 'success': True, 'triggers': triggers, diff --git a/src/aipass/memory/apps/handlers/monitor/memory_watcher.py b/src/aipass/memory/apps/handlers/monitor/memory_watcher.py index 6ff6e990..ffe467d0 100644 --- a/src/aipass/memory/apps/handlers/monitor/memory_watcher.py +++ b/src/aipass/memory/apps/handlers/monitor/memory_watcher.py @@ -43,7 +43,7 @@ except ImportError: from aipass.memory.apps.handlers.tracking.line_counter import update_line_count from aipass.memory.apps.handlers.monitor.detector import check_single_file from aipass.prax.apps.modules.logger import get_system_logger -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler logger = get_system_logger() @@ -227,7 +227,7 @@ def check_and_rollover() -> Dict[str, Any]: # Check code_archive for new files to index results['code_archive'] = _check_code_archive() - log_operation("check_and_rollover", {"files_checked": results.get('files_checked', 0), "rollover_triggered": results.get('rollover_triggered', False)}) + json_handler.log_operation("check_and_rollover", {"files_checked": results.get('files_checked', 0), "rollover_triggered": results.get('rollover_triggered', False)}) return results diff --git a/src/aipass/memory/apps/handlers/rollover/extractor.py b/src/aipass/memory/apps/handlers/rollover/extractor.py index a9b0e5cf..07c630ad 100644 --- a/src/aipass/memory/apps/handlers/rollover/extractor.py +++ b/src/aipass/memory/apps/handlers/rollover/extractor.py @@ -33,7 +33,7 @@ from typing import Dict, List, Any, Tuple from datetime import datetime # Handler imports (relative within package) -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler from aipass.memory.apps.handlers.json.memory_files import read_memory_file_data, write_memory_file_simple from aipass.prax.apps.modules.logger import get_system_logger @@ -453,6 +453,8 @@ def extract_items( # Derive branch and type from path branch_name, memory_type = _derive_branch_and_type(file_path) + json_handler.log_operation("extract_items", {"branch": branch_name, "type": memory_type, "extracted_count": items_to_extract}) + return { 'success': True, 'file': str(file_path), diff --git a/src/aipass/memory/apps/handlers/rollover/orchestrator.py b/src/aipass/memory/apps/handlers/rollover/orchestrator.py index 5a3daa5c..cac41502 100644 --- a/src/aipass/memory/apps/handlers/rollover/orchestrator.py +++ b/src/aipass/memory/apps/handlers/rollover/orchestrator.py @@ -26,7 +26,7 @@ from pathlib import Path from typing import List, Dict, Any from aipass.prax import logger -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler # logger imported from aipass.prax @@ -503,7 +503,7 @@ def execute_rollover() -> Dict[str, Any]: except Exception as e: logger.info(f"[rollover] Memory pool check: {e}") - log_operation("rollover_execute", { + json_handler.log_operation("rollover_execute", { "triggers": len(triggers), "success_count": success_count, "failed_count": len(failed), diff --git a/src/aipass/memory/apps/handlers/schema/normalize.py b/src/aipass/memory/apps/handlers/schema/normalize.py index b24a5290..18a02350 100644 --- a/src/aipass/memory/apps/handlers/schema/normalize.py +++ b/src/aipass/memory/apps/handlers/schema/normalize.py @@ -28,7 +28,7 @@ from typing import Dict, Any from datetime import datetime from aipass.prax.apps.modules.logger import get_system_logger -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler logger = get_system_logger() @@ -125,7 +125,7 @@ def normalize_memory_file(file_path: Path, dry_run: bool = False) -> Dict[str, A except Exception as e: return {'success': False, 'error': f"Failed to write: {e}"} - log_operation("normalize_memory_file", {"file": file_path.name, "changes": len(changes), "success": True}) + json_handler.log_operation("normalize_memory_file", {"file": file_path.name, "changes": len(changes), "success": True}) return { 'success': True, diff --git a/src/aipass/memory/apps/handlers/search/query_executor.py b/src/aipass/memory/apps/handlers/search/query_executor.py index c5c0e27e..ab8f797d 100644 --- a/src/aipass/memory/apps/handlers/search/query_executor.py +++ b/src/aipass/memory/apps/handlers/search/query_executor.py @@ -26,7 +26,7 @@ from pathlib import Path from typing import Dict, Any from aipass.prax import logger -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler # Subprocess scripts for ML operations (run in memory venv) _HANDLERS_DIR = Path(__file__).resolve().parent.parent @@ -275,7 +275,7 @@ def execute_search( logger.info(f"[search] Filtered to {len(filtered_results)} relevant results") - log_operation("search_execute", {"query_len": len(query), "results": len(filtered_results), "success": True}) + json_handler.log_operation("search_execute", {"query_len": len(query), "results": len(filtered_results), "success": True}) return { 'success': True, 'query': query, diff --git a/src/aipass/memory/apps/handlers/search/vector_search.py b/src/aipass/memory/apps/handlers/search/vector_search.py index fa000510..5be6cdb3 100644 --- a/src/aipass/memory/apps/handlers/search/vector_search.py +++ b/src/aipass/memory/apps/handlers/search/vector_search.py @@ -33,7 +33,7 @@ from typing import List, Dict, Any from pathlib import Path from aipass.prax.apps.modules.logger import get_system_logger -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler logger = get_system_logger() @@ -318,7 +318,7 @@ def search_collection( 'collection': collection_name } - log_operation("vector_search_collection", {"collection": collection_name, "count": result.get('count', 0), "success": True}) + json_handler.log_operation("vector_search_collection", {"collection": collection_name, "count": result.get('count', 0), "success": True}) return { 'success': True, **result @@ -488,7 +488,7 @@ def search_all_collections( } total = sum(r['count'] for r in results.values()) - log_operation("vector_search_all", {"collections": len(results), "total_results": total, "success": True}) + json_handler.log_operation("vector_search_all", {"collections": len(results), "total_results": total, "success": True}) return { 'success': True, 'results': results, diff --git a/src/aipass/memory/apps/handlers/storage/chroma.py b/src/aipass/memory/apps/handlers/storage/chroma.py index d67e8e4a..de18bee1 100644 --- a/src/aipass/memory/apps/handlers/storage/chroma.py +++ b/src/aipass/memory/apps/handlers/storage/chroma.py @@ -33,7 +33,7 @@ from pathlib import Path from datetime import datetime from aipass.prax.apps.modules.logger import get_system_logger -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler logger = get_system_logger() @@ -316,7 +316,7 @@ def store_vectors( service = _get_service(db_path) result = service.store_vectors(branch, memory_type, embeddings, documents, metadatas) - log_operation("chroma_store_vectors", {"collection": result.get('collection'), "count": result.get('count', 0), "success": True}) + json_handler.log_operation("chroma_store_vectors", {"collection": result.get('collection'), "count": result.get('count', 0), "success": True}) return { 'success': True, **result @@ -494,7 +494,7 @@ def search_vectors( # Sort by distance (lower is better) all_results.sort(key=lambda x: x['distance'] if x['distance'] is not None else float('inf')) - log_operation("chroma_search_vectors", {"collections": len(collection_names), "results": len(all_results), "success": True}) + json_handler.log_operation("chroma_search_vectors", {"collections": len(collection_names), "results": len(all_results), "success": True}) return { 'success': True, 'results': all_results[:n_results * len(collection_names)] if all_results else [], diff --git a/src/aipass/memory/apps/handlers/symbolic/chroma_client.py b/src/aipass/memory/apps/handlers/symbolic/chroma_client.py index c78a1d6f..8c166868 100644 --- a/src/aipass/memory/apps/handlers/symbolic/chroma_client.py +++ b/src/aipass/memory/apps/handlers/symbolic/chroma_client.py @@ -1,18 +1,9 @@ -# ===================AIPASS==================== -# META DATA HEADER -# Name: chroma_client.py - Shared ChromaDB Client Handler -# Date: 2026-02-04 -# Version: 0.2.0 -# Category: memory_bank/handlers/symbolic -# -# CHANGELOG (Max 5 entries): -# - v0.2.0 (2026-02-15): Canonical singleton client for all ChromaDB access, -# added get_client() alias, embedding_function=None, cosine distance metadata -# - v0.1.0 (2026-02-04): Initial version - shared singleton ChromaDB client -# -# CODE STANDARDS: -# - Handler independence: No module imports -# - Error handling: Return status dicts (3-tier architecture) +# =================== AIPass ==================== +# Name: chroma_client.py +# Description: Symbolic ChromaDB Client +# Version: 0.1.0 +# Created: 2026-03-17 +# Modified: 2026-03-17 # ============================================= """ @@ -34,7 +25,7 @@ Key Functions: from typing import Dict, Any from pathlib import Path -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler # ============================================================================= @@ -130,7 +121,7 @@ def get_collection( embedding_function=None ) - log_operation("chroma_get_collection", {"collection": collection_name, "create": create, "success": True}) + json_handler.log_operation("chroma_get_collection", {"collection": collection_name, "create": create, "success": True}) return { 'success': True, 'collection': collection diff --git a/src/aipass/memory/apps/handlers/symbolic/deduplicator.py b/src/aipass/memory/apps/handlers/symbolic/deduplicator.py index d5f5683d..14a37e69 100644 --- a/src/aipass/memory/apps/handlers/symbolic/deduplicator.py +++ b/src/aipass/memory/apps/handlers/symbolic/deduplicator.py @@ -1,17 +1,9 @@ -# ===================AIPASS==================== -# META DATA HEADER -# Name: deduplicator.py - Symbolic Fragment Deduplication Handler -# Date: 2026-02-15 +# =================== AIPass ==================== +# Name: deduplicator.py +# Description: Symbolic Fragment Deduplicator # Version: 0.1.0 -# Category: memory_bank/handlers/symbolic -# -# CHANGELOG (Max 5 entries): -# - v0.1.0 (2026-02-15): Initial version - FPLAN-0341 Phase 3 AUDN dedup -# -# CODE STANDARDS: -# - Handler independence: No module imports (OpenRouter lazy-imported) -# - Error handling: Return status dicts (3-tier architecture) -# - File size: <300 lines target +# Created: 2026-03-17 +# Modified: 2026-03-17 # ============================================= """ @@ -32,7 +24,7 @@ import re from typing import Dict, List, Any, Optional from pathlib import Path -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler # memory/ root resolved from symbolic/deduplicator.py _MEMORY_ROOT = Path(__file__).resolve().parent.parent.parent.parent @@ -191,7 +183,7 @@ def deduplicate_fragment( action = parsed['action'] reason = parsed.get('reason', 'No reason provided') - log_operation("symbolic_dedup", {"action": action, "existing_count": len(existing_fragments), "success": True}) + json_handler.log_operation("symbolic_dedup", {"action": action, "existing_count": len(existing_fragments), "success": True}) # Apply action to fragment if action == 'UPDATE': diff --git a/src/aipass/memory/apps/handlers/symbolic/extractor.py b/src/aipass/memory/apps/handlers/symbolic/extractor.py index 151aae3d..4a8cae15 100644 --- a/src/aipass/memory/apps/handlers/symbolic/extractor.py +++ b/src/aipass/memory/apps/handlers/symbolic/extractor.py @@ -1,18 +1,9 @@ -# ===================AIPASS==================== -# META DATA HEADER -# Name: extractor.py - Symbolic Memory Extractor Handler -# Date: 2026-02-04 -# Version: 0.2.0 -# Category: memory_bank/handlers/symbolic -# -# CHANGELOG (Max 5 entries): -# - v0.2.0 (2026-02-15): Phase 2 - LLM-based extraction via OpenRouter (FPLAN-0341) -# - v0.1.0 (2026-02-04): Initial version - ported from symbolic_memory.py -# -# CODE STANDARDS: -# - Handler independence: No module imports (OpenRouter lazy-imported) -# - Error handling: Return status dicts (3-tier architecture) -# - File size: <400 lines target +# =================== AIPass ==================== +# Name: extractor.py +# Description: Symbolic Dimension Extractor +# Version: 0.1.0 +# Created: 2026-03-17 +# Modified: 2026-03-17 # ============================================= """ @@ -31,7 +22,7 @@ from datetime import datetime from pathlib import Path from typing import Dict, List, Any, Optional -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler # memory/ root resolved from symbolic/extractor.py _MEMORY_ROOT = Path(__file__).resolve().parent.parent.parent.parent @@ -464,5 +455,5 @@ def analyze_conversation_llm(chat_history: List[Dict[str, Any]]) -> Dict[str, An 'chunk_count': llm.get('chunk_count', 0)}, 'message_count': reg.get('message_count', len(chat_history)), 'error': llm.get('error')} - log_operation("symbolic_extract", {"fragments": len(result['fragments']), "messages": result['message_count'], "success": True}) + json_handler.log_operation("symbolic_extract", {"fragments": len(result['fragments']), "messages": result['message_count'], "success": True}) return result diff --git a/src/aipass/memory/apps/handlers/symbolic/hook.py b/src/aipass/memory/apps/handlers/symbolic/hook.py index 964c10ac..9b7e31c9 100644 --- a/src/aipass/memory/apps/handlers/symbolic/hook.py +++ b/src/aipass/memory/apps/handlers/symbolic/hook.py @@ -1,18 +1,9 @@ -# ===================AIPASS==================== -# META DATA HEADER -# Name: hook.py - Fragmented Memory Hook Handler -# Date: 2026-02-04 -# Version: 0.2.0 -# Category: memory_bank/handlers/symbolic -# -# CHANGELOG (Max 5 entries): -# - v0.2.0 (2026-02-15): v2 schema support in format_fragment_recall/format_multiple_recalls -# - v0.1.0 (2026-02-04): Initial version - Fragmented Memory Phase 4 -# -# CODE STANDARDS: -# - Handler independence: No module imports -# - Error handling: Return status dicts (3-tier architecture) -# - File size: <300 lines target +# =================== AIPass ==================== +# Name: hook.py +# Description: Symbolic Hook Handler +# Version: 0.1.0 +# Created: 2026-03-17 +# Modified: 2026-03-17 # ============================================= """ @@ -37,7 +28,7 @@ from typing import Dict, List, Any, Tuple # Handler imports (domain-organized, no modules) from aipass.memory.apps.handlers.symbolic import retriever from aipass.memory.apps.handlers.json import memory_files -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler # memory/ root resolved from symbolic/hook.py _MEMORY_ROOT = Path(__file__).resolve().parent.parent.parent.parent @@ -635,7 +626,7 @@ def process_hook( # Record the surface record_surface(fragment) - log_operation("symbolic_hook", {"fragment_id": fragment.get('id'), "surfaced": True, "success": True}) + json_handler.log_operation("symbolic_hook", {"fragment_id": fragment.get('id'), "surfaced": True, "success": True}) return { 'success': True, 'surfaced': True, diff --git a/src/aipass/memory/apps/handlers/symbolic/retriever.py b/src/aipass/memory/apps/handlers/symbolic/retriever.py index e910042b..a801fe7c 100644 --- a/src/aipass/memory/apps/handlers/symbolic/retriever.py +++ b/src/aipass/memory/apps/handlers/symbolic/retriever.py @@ -1,20 +1,9 @@ -# ===================AIPASS==================== -# META DATA HEADER -# Name: retriever.py - Symbolic Fragment Retrieval Handler -# Date: 2026-02-04 -# Version: 0.2.0 -# Category: memory_bank/handlers/symbolic -# -# CHANGELOG (Max 5 entries): -# - v0.2.0 (2026-02-15): Add relevance_tier labels to query/get results (FPLAN-0341 P4) -# - v0.1.1 (2026-02-15): Fix: embedding_function=None on all get_collection(), -# cosine similarity formula, use shared chroma_client singleton -# - v0.1.0 (2026-02-04): Initial version - Fragmented Memory Phase 3 -# -# CODE STANDARDS: -# - Handler independence: No module imports -# - Error handling: Return status dicts (3-tier architecture) -# - File size: <300 lines target +# =================== AIPass ==================== +# Name: retriever.py +# Description: Symbolic Fragment Retriever +# Version: 0.1.0 +# Created: 2026-03-17 +# Modified: 2026-03-17 # ============================================= """ @@ -38,7 +27,7 @@ from pathlib import Path # Handler imports (domain-organized, no modules) from aipass.memory.apps.handlers.vector import embedder from aipass.memory.apps.handlers.symbolic.chroma_client import get_chroma_client -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler # ============================================================================= @@ -403,7 +392,7 @@ def retrieve_fragments( # Return top n_results final_results = ranked[:n_results] - log_operation("symbolic_retrieve", {"results": len(final_results), "methods": search_methods_used, "success": True}) + json_handler.log_operation("symbolic_retrieve", {"results": len(final_results), "methods": search_methods_used, "success": True}) return { 'success': True, 'results': final_results, diff --git a/src/aipass/memory/apps/handlers/symbolic/storage.py b/src/aipass/memory/apps/handlers/symbolic/storage.py index 12c154c7..3685f08a 100644 --- a/src/aipass/memory/apps/handlers/symbolic/storage.py +++ b/src/aipass/memory/apps/handlers/symbolic/storage.py @@ -1,18 +1,9 @@ -# ===================AIPASS==================== -# META DATA HEADER -# Name: storage.py - Symbolic Fragment Storage Handler -# Date: 2026-02-04 -# Version: 0.2.0 -# Category: memory_bank/handlers/symbolic -# -# CHANGELOG (Max 5 entries): -# - v0.2.0 (2026-02-15): Add store_llm_fragment/batch for v2 LLM schema (FPLAN-0341 P3) -# - v0.1.0 (2026-02-04): Initial version - Fragmented Memory Phase 2 -# -# CODE STANDARDS: -# - Handler independence: No module imports -# - Error handling: Return status dicts (3-tier architecture) -# - File size: <300 lines target +# =================== AIPass ==================== +# Name: storage.py +# Description: Symbolic Storage Handler +# Version: 0.1.0 +# Created: 2026-03-17 +# Modified: 2026-03-17 # ============================================= """ @@ -40,7 +31,7 @@ from pathlib import Path # Handler imports (domain-organized, no modules) from aipass.memory.apps.handlers.vector import embedder -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler # ============================================================================= @@ -308,7 +299,7 @@ def store_fragment( ) total = collection.count() - log_operation("symbolic_store_fragment", {"fragment_id": frag_id, "total": total, "success": True}) + json_handler.log_operation("symbolic_store_fragment", {"fragment_id": frag_id, "total": total, "success": True}) return { 'success': True, 'fragment_id': frag_id, @@ -420,7 +411,7 @@ def store_fragments_batch( ) total = collection.count() - log_operation("symbolic_store_batch", {"stored": len(batch_ids), "total": total, "success": True}) + json_handler.log_operation("symbolic_store_batch", {"stored": len(batch_ids), "total": total, "success": True}) return { 'success': True, 'stored': len(batch_ids), @@ -540,7 +531,7 @@ def store_llm_fragment( ) total = collection.count() - log_operation("symbolic_store_llm_fragment", {"fragment_id": frag_id, "total": total, "success": True}) + json_handler.log_operation("symbolic_store_llm_fragment", {"fragment_id": frag_id, "total": total, "success": True}) return { 'success': True, 'fragment_id': frag_id, @@ -668,7 +659,7 @@ def store_llm_fragments_batch( ) total = collection.count() - log_operation("symbolic_store_llm_batch", {"stored": len(frag_ids), "total": total, "success": True}) + json_handler.log_operation("symbolic_store_llm_batch", {"stored": len(frag_ids), "total": total, "success": True}) return { 'success': True, 'stored': len(frag_ids), @@ -713,7 +704,7 @@ def delete_fragment( collection.delete(ids=[fragment_id]) total = collection.count() - log_operation("symbolic_delete_fragment", {"deleted_id": fragment_id, "total": total, "success": True}) + json_handler.log_operation("symbolic_delete_fragment", {"deleted_id": fragment_id, "total": total, "success": True}) return { 'success': True, 'deleted_id': fragment_id, diff --git a/src/aipass/memory/apps/handlers/templates/differ.py b/src/aipass/memory/apps/handlers/templates/differ.py index d0ad2499..b076f5cf 100644 --- a/src/aipass/memory/apps/handlers/templates/differ.py +++ b/src/aipass/memory/apps/handlers/templates/differ.py @@ -28,7 +28,7 @@ from pathlib import Path from typing import Dict, Any, List, Optional from aipass.prax import logger -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler # ============================================================================= # PATH SETUP @@ -298,7 +298,7 @@ def diff_template_vs_branch(branch_path: str | Path) -> dict: if file_diff["additions"] or file_diff["removals"] or file_diff["modifications"]: result["observations"].append(file_diff) - log_operation("template_diff", {"branch": branch_name, "local_diffs": len(result["local"]), "obs_diffs": len(result["observations"]), "success": True}) + json_handler.log_operation("template_diff", {"branch": branch_name, "local_diffs": len(result["local"]), "obs_diffs": len(result["observations"]), "success": True}) return result diff --git a/src/aipass/memory/apps/handlers/templates/pusher.py b/src/aipass/memory/apps/handlers/templates/pusher.py index 6044cbe5..0f76e0f2 100644 --- a/src/aipass/memory/apps/handlers/templates/pusher.py +++ b/src/aipass/memory/apps/handlers/templates/pusher.py @@ -30,7 +30,7 @@ from typing import Dict, Any, List, Tuple, Optional from datetime import datetime from aipass.prax import logger -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler # Handler imports (same-branch allowed per handler boundaries) from aipass.memory.apps.handlers.json.memory_files import ( @@ -420,7 +420,7 @@ def push_templates(dry_run: bool = False) -> dict: if not _update_version_file(result["branches_list"]): result["errors"].append("Failed to update template version file") - log_operation("template_push", {"branches": result["branches_updated"], "files": result["files_modified"], "dry_run": dry_run, "success": True}) + json_handler.log_operation("template_push", {"branches": result["branches_updated"], "files": result["files_modified"], "dry_run": dry_run, "success": True}) return result diff --git a/src/aipass/memory/apps/handlers/templates/spawn_pusher.py b/src/aipass/memory/apps/handlers/templates/spawn_pusher.py index 408dff85..8777ae27 100644 --- a/src/aipass/memory/apps/handlers/templates/spawn_pusher.py +++ b/src/aipass/memory/apps/handlers/templates/spawn_pusher.py @@ -29,7 +29,7 @@ from pathlib import Path from typing import Any, Dict, List from aipass.prax import logger -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler # ============================================================================= # PATH SETUP @@ -230,7 +230,7 @@ def push_to_spawn_templates(dry_run: bool = False) -> dict: f"{result['files_modified']} files modified" ) - log_operation("spawn_template_push", {"sets_updated": result["template_sets_updated"], "files": result["files_modified"], "dry_run": dry_run, "success": True}) + json_handler.log_operation("spawn_template_push", {"sets_updated": result["template_sets_updated"], "files": result["files_modified"], "dry_run": dry_run, "success": True}) return result diff --git a/src/aipass/memory/apps/handlers/tracking/line_counter.py b/src/aipass/memory/apps/handlers/tracking/line_counter.py index 85547ce9..1b416abc 100644 --- a/src/aipass/memory/apps/handlers/tracking/line_counter.py +++ b/src/aipass/memory/apps/handlers/tracking/line_counter.py @@ -28,7 +28,7 @@ from datetime import datetime # Handler imports (relative within package) from aipass.memory.apps.handlers.json.memory_files import update_metadata from aipass.prax.apps.modules.logger import get_system_logger -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler logger = get_system_logger() @@ -92,7 +92,7 @@ def update_line_count(file_path: Path) -> Dict[str, Any]: 'error': f"Failed to update metadata: {result['error']}" } - log_operation("update_line_count", {"file": file_path.name, "lines": line_count, "success": True}) + json_handler.log_operation("update_line_count", {"file": file_path.name, "lines": line_count, "success": True}) return { 'success': True, diff --git a/src/aipass/memory/apps/handlers/vector/embedder.py b/src/aipass/memory/apps/handlers/vector/embedder.py index f6001de5..f3cd9e4a 100644 --- a/src/aipass/memory/apps/handlers/vector/embedder.py +++ b/src/aipass/memory/apps/handlers/vector/embedder.py @@ -33,7 +33,7 @@ from typing import List, Dict, Any from pathlib import Path from aipass.prax.apps.modules.logger import get_system_logger -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler logger = get_system_logger() @@ -197,7 +197,7 @@ def encode_batch(texts: List[str]) -> Dict[str, Any]: service = _get_service() result = service.encode_batch(texts) - log_operation("vector_encode_batch", {"count": result.get('count', 0), "dimension": result.get('dimension', 0), "success": True}) + json_handler.log_operation("vector_encode_batch", {"count": result.get('count', 0), "dimension": result.get('dimension', 0), "success": True}) return { 'success': True, **result diff --git a/src/aipass/memory/apps/json_templates/__init__.py b/src/aipass/memory/apps/json_templates/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/src/aipass/memory/apps/modules/rollover.py b/src/aipass/memory/apps/modules/rollover.py index ccf6d77d..fefb2945 100755 --- a/src/aipass/memory/apps/modules/rollover.py +++ b/src/aipass/memory/apps/modules/rollover.py @@ -29,7 +29,7 @@ from rich import box from aipass.prax import logger from aipass.cli.apps.modules import console, error, warning -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler # ============================================================================= # INFRASTRUCTURE SETUP @@ -222,7 +222,7 @@ def run_rollover() -> bool: for fail in failed: error(f"{fail['trigger']} - {fail['stage']}: {fail['error']}") - log_operation("rollover_execute", {"triggers": triggers_count, "success_count": success_count}) + json_handler.log_operation("rollover_execute", {"triggers": triggers_count, "success_count": success_count}) return success_count > 0 @@ -255,7 +255,7 @@ def sync_line_counts() -> None: warning(f"{result['failed']} files failed") for branch, mem_type, err_msg in result.get('failures', []): error(f"{branch}.{mem_type}: {err_msg}") - log_operation("rollover_sync_lines", {"updated": result['updated'], "failed": result['failed']}) + json_handler.log_operation("rollover_sync_lines", {"updated": result['updated'], "failed": result['failed']}) else: error("Failed to sync line counts") @@ -328,7 +328,7 @@ def show_status() -> None: console.print() - log_operation("rollover_status", {"branches_checked": stats['total_branches'], "files_ready": stats['files_ready']}) + json_handler.log_operation("rollover_status", {"branches_checked": stats['total_branches'], "files_ready": stats['files_ready']}) def check_triggers() -> None: @@ -356,7 +356,7 @@ def check_triggers() -> None: if not triggers: console.print("[green]>[/green] No files need rollover") - log_operation("rollover_check", {"files_needing_rollover": 0}) + json_handler.log_operation("rollover_check", {"files_needing_rollover": 0}) return console.print(f"[bold cyan]Found {len(triggers)} files ready for rollover:[/bold cyan]") @@ -368,7 +368,7 @@ def check_triggers() -> None: console.print() console.print("[dim]Run 'drone @memory rollover' to process these files[/dim]") console.print() - log_operation("rollover_check", {"files_needing_rollover": len(triggers)}) + json_handler.log_operation("rollover_check", {"files_needing_rollover": len(triggers)}) # ============================================================================= diff --git a/src/aipass/memory/apps/modules/search.py b/src/aipass/memory/apps/modules/search.py index 71f4643e..39810c74 100755 --- a/src/aipass/memory/apps/modules/search.py +++ b/src/aipass/memory/apps/modules/search.py @@ -28,7 +28,7 @@ from rich import box from aipass.prax import logger from aipass.cli.apps.modules import console, error, warning -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler # ============================================================================= # INFRASTRUCTURE SETUP @@ -257,7 +257,7 @@ def show_search_results( )) console.print() - log_operation("search_query", {"query": query, "results": len(filtered_results)}) + json_handler.log_operation("search_query", {"query": query, "results": len(filtered_results)}) return True diff --git a/src/aipass/memory/apps/modules/symbolic.py b/src/aipass/memory/apps/modules/symbolic.py index f544b1a0..59d7b6f5 100644 --- a/src/aipass/memory/apps/modules/symbolic.py +++ b/src/aipass/memory/apps/modules/symbolic.py @@ -1,19 +1,9 @@ -# ===================AIPASS==================== -# META DATA HEADER -# Name: symbolic.py - Symbolic Memory Orchestration Module -# Date: 2026-02-04 -# Version: 0.3.0 -# Category: memory_bank/modules -# -# CHANGELOG (Max 5 entries): -# - v0.3.0 (2026-02-15): v2 schema display in CLI, extract command, v2 demo/hook-test (FPLAN-0341 P4) -# - v0.2.0 (2026-02-15): Add LLM dedup pipeline extract_and_store_llm (FPLAN-0341 P3) -# - v0.1.0 (2026-02-04): Initial version - Fragmented Memory Phase 1 -# -# CODE STANDARDS: -# - Thin orchestration: Delegate all logic to handlers -# - No business logic: Only coordinate workflow -# - handle_command() pattern +# =================== AIPass ==================== +# Name: symbolic.py +# Description: Symbolic Memory Module +# Version: 0.1.0 +# Created: 2026-03-17 +# Modified: 2026-03-17 # ============================================= """ @@ -34,8 +24,8 @@ from typing import List, Dict, Any # Service imports from aipass.prax import logger -from aipass.cli.apps.modules import console, header -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.cli.apps.modules import console, error, header, warning +from aipass.memory.apps.handlers.json import json_handler # Handler imports (domain-organized) from aipass.memory.apps.handlers.symbolic import extractor @@ -981,7 +971,7 @@ def run_demo() -> None: console.print("[dim]Note: Run 'symbolic extract ' to use the real LLM pipeline[/dim]") console.print() - log_operation("symbolic_demo", {"success": True}) + json_handler.log_operation("symbolic_demo", {"success": True}) def search_fragments_cli(args: List[str]) -> None: @@ -1063,7 +1053,7 @@ def search_fragments_cli(args: List[str]) -> None: console.print() if not results: - console.print("[yellow]No matching fragments found[/yellow]") + warning("No matching fragments found") console.print() console.print("[dim]Try:[/dim]") console.print(" Different search terms") @@ -1139,7 +1129,7 @@ def search_fragments_cli(args: List[str]) -> None: console.print() logger.info(f"[symbolic] Displayed {len(results)} fragment results") - log_operation("symbolic_fragments", {"query": query or "", "results": len(results)}) + json_handler.log_operation("symbolic_fragments", {"query": query or "", "results": len(results)}) def run_hook_test(args: List[str]) -> None: @@ -1270,7 +1260,7 @@ def run_hook_test(args: List[str]) -> None: console.print(f" [dim]Fragments surfaced:[/dim] {state.get('fragments_surfaced', 0)}") console.print(f" [dim]Messages since last:[/dim] {state.get('messages_since_last', 0)}") console.print() - log_operation("symbolic_hook_test", {"surfaced": result.get('surfaced', False), "success": result.get('success', False)}) + json_handler.log_operation("symbolic_hook_test", {"surfaced": result.get('surfaced', False), "success": result.get('success', False)}) def analyze_file(file_path: str) -> None: @@ -1319,7 +1309,7 @@ def analyze_file(file_path: str) -> None: console.print(f" [dim]Words:[/dim] {meta.get('total_words', 0)}") console.print(f" [dim]Depth:[/dim] {meta.get('depth', 'unknown')}") console.print() - log_operation("symbolic_analyze", {"file": path.name, "messages": result['message_count']}) + json_handler.log_operation("symbolic_analyze", {"file": path.name, "messages": result['message_count']}) else: console.print(f"[red]✗[/red] Analysis failed: {result.get('error', 'Unknown error')}") @@ -1386,7 +1376,7 @@ def extract_file(file_path: str, source_branch: str | None = None) -> None: console.print() logger.info(f"[symbolic] extract_file complete: {result}") if result.get('success'): - log_operation("symbolic_extract", {"file": path.name, "added": result.get('added', 0), "updated": result.get('updated', 0)}) + json_handler.log_operation("symbolic_extract", {"file": path.name, "added": result.get('added', 0), "updated": result.get('updated', 0)}) # ============================================================================= @@ -1557,7 +1547,7 @@ def bootstrap_from_jsonl(max_sessions: int = 8) -> None: sessions = _find_bootstrap_sessions(max_sessions) if not sessions: - console.print("[red]No suitable session files found in ~/.claude/projects/[/red]") + error("No suitable session files found in ~/.claude/projects/") return console.print(f"[cyan]Found {len(sessions)} sessions to process[/cyan]") @@ -1657,7 +1647,7 @@ def bootstrap_from_jsonl(max_sessions: int = 8) -> None: f"{total_added} added, {total_updated} updated, " f"{total_skipped} skipped, {total_errors} errors" ) - log_operation("symbolic_bootstrap", {"sessions": processed_count, "added": total_added, "errors": total_errors}) + json_handler.log_operation("symbolic_bootstrap", {"sessions": processed_count, "added": total_added, "errors": total_errors}) # ============================================================================= diff --git a/src/aipass/memory/apps/modules/templates.py b/src/aipass/memory/apps/modules/templates.py index 34c4cd48..7f407ec9 100644 --- a/src/aipass/memory/apps/modules/templates.py +++ b/src/aipass/memory/apps/modules/templates.py @@ -28,7 +28,7 @@ from rich import box from aipass.prax import logger from aipass.cli.apps.modules import console, error, warning -from aipass.memory.apps.handlers.json.json_handler import log_operation +from aipass.memory.apps.handlers.json import json_handler # ============================================================================= # INFRASTRUCTURE SETUP @@ -287,7 +287,7 @@ def _display_push_results(result: dict, dry_run: bool) -> None: f"{result['branches_updated']}/{result['branches_scanned']} branches, " f"{result['files_modified']} files" ) - log_operation("templates_push", {"branches_updated": result['branches_updated'], "files_modified": result['files_modified']}) + json_handler.log_operation("templates_push", {"branches_updated": result['branches_updated'], "files_modified": result['files_modified']}) console.print() @@ -420,13 +420,13 @@ def _display_diff_results(branch_name: str | None = None) -> None: console.print("[green]All branches are up to date with templates.[/green]") else: if total_diffs > 0: - console.print(f"[yellow]{total_diffs} branches have template differences[/yellow]") + warning(f"{total_diffs} branches have template differences") console.print("[dim]Run 'push-templates --dry-run' to preview changes[/dim]") if total_errors > 0: console.print(f"[red]{total_errors} errors encountered[/red]") logger.info(f"[templates] Diff complete: {total_diffs} branches with diffs, {total_errors} errors") - log_operation("templates_diff", {"branches_compared": len(branches), "branches_with_diffs": total_diffs}) + json_handler.log_operation("templates_diff", {"branches_compared": len(branches), "branches_with_diffs": total_diffs}) console.print() @@ -484,7 +484,7 @@ def _display_status(status: dict) -> None: console.print("[cyan]Branches pushed:[/cyan] none") logger.info(f"[templates] Status checked - version: {version}, last push: {last_push}") - log_operation("templates_status", {"version": version, "branches_pushed": len(pushed)}) + json_handler.log_operation("templates_status", {"version": version, "branches_pushed": len(pushed)}) console.print()