Merge pull request #75 from AIOSAI/feat/memory-seedgo-100-json-structure
feat(memory): seedgo 100% — json_structure + full audit pass
This commit is contained in:
@@ -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*
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 [],
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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':
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)})
|
||||
|
||||
|
||||
# =============================================================================
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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 <file>' 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})
|
||||
|
||||
|
||||
# =============================================================================
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user