feat(system): S68 bonus: commons datetime deprecation fix + HERALD update (#163)

* feat(system): STATUS.md update

Co-Authored-By: @devpulse <devpulse@aipass>

* feat(system): S68 night shift: test log isolation + audit fixes (zero scanner output)

Co-Authored-By: @devpulse <devpulse@aipass>

* feat(system): S68 bonus: commons datetime deprecation fix + HERALD update

Co-Authored-By: @devpulse <devpulse@aipass>

---------

Co-authored-by: @devpulse <devpulse@aipass>
This commit is contained in:
AIPass
2026-03-31 16:27:13 -07:00
committed by GitHub
co-authored by @devpulse
parent c4377cc2e5
commit f2eefc3d39
24 changed files with 164 additions and 27 deletions
+8 -1
View File
@@ -15,9 +15,16 @@
# =============================================
"""Shared pytest fixtures for ai_mail tests"""
import os
import tempfile
# Redirect prax logs to temp directory during tests
# Must be set before any prax imports to catch logger initialization
if "AIPASS_TEST_LOG_DIR" not in os.environ:
os.environ["AIPASS_TEST_LOG_DIR"] = tempfile.mkdtemp(prefix="aipass_test_logs_")
import pytest
import shutil
import tempfile
from pathlib import Path
from typing import Generator
from unittest.mock import MagicMock
@@ -48,6 +48,7 @@ GENERATION_ENDPOINT = f"{OPENROUTER_BASE_URL}/generation"
# Default configuration values
DEFAULT_GENERATION_CHECK_DELAY = 2 # seconds to wait before querying metrics
DEFAULT_REQUEST_TIMEOUT = 30 # seconds for HTTP request timeout
# =============================================
@@ -148,7 +149,7 @@ def get_generation_metrics(generation_id: str, api_key: str) -> Optional[Dict[st
GENERATION_ENDPOINT,
params={"id": generation_id},
headers=headers,
timeout=30
timeout=DEFAULT_REQUEST_TIMEOUT
)
# Check response status
+4 -1
View File
@@ -140,10 +140,13 @@ def validate_key(args: List[str]):
def list_providers():
"""Orchestrate list providers workflow"""
from aipass.api.apps.handlers.config.provider import PROVIDER_DEFAULTS
header("Available Providers")
console.print()
console.print(" - openrouter")
for provider_name in sorted(PROVIDER_DEFAULTS):
console.print(f" - {provider_name}")
console.print()
+8
View File
@@ -16,6 +16,14 @@
# =============================================
"""Shared pytest fixtures for api tests"""
import os
import tempfile
# Redirect prax logs to temp directory during tests
# Must be set before any prax imports to catch logger initialization
if "AIPASS_TEST_LOG_DIR" not in os.environ:
os.environ["AIPASS_TEST_LOG_DIR"] = tempfile.mkdtemp(prefix="aipass_test_logs_")
import importlib
import logging
import sys
+8 -1
View File
@@ -1,8 +1,15 @@
"""Shared pytest fixtures for backup branch tests."""
import os
import tempfile
# Redirect prax logs to temp directory during tests
# Must be set before any prax imports to catch logger initialization
if "AIPASS_TEST_LOG_DIR" not in os.environ:
os.environ["AIPASS_TEST_LOG_DIR"] = tempfile.mkdtemp(prefix="aipass_test_logs_")
import pytest
import shutil
import sys
import tempfile
from collections.abc import Generator
from pathlib import Path
from unittest.mock import MagicMock
+7
View File
@@ -7,6 +7,13 @@
# =============================================
"""Shared pytest fixtures for CLI tests."""
import os
import tempfile
# Redirect prax logs to temp directory during tests
# Must be set before any prax imports to catch logger initialization
if "AIPASS_TEST_LOG_DIR" not in os.environ:
os.environ["AIPASS_TEST_LOG_DIR"] = tempfile.mkdtemp(prefix="aipass_test_logs_")
import pytest
+8 -1
View File
@@ -15,9 +15,16 @@
#@Meta header not seedgo standards
"""Shared pytest fixtures for daemon tests"""
import os
import tempfile
# Redirect prax logs to temp directory during tests
# Must be set before any prax imports to catch logger initialization
if "AIPASS_TEST_LOG_DIR" not in os.environ:
os.environ["AIPASS_TEST_LOG_DIR"] = tempfile.mkdtemp(prefix="aipass_test_logs_")
import pytest
import shutil
import tempfile
from pathlib import Path
from typing import Generator
from unittest.mock import MagicMock
+7 -1
View File
@@ -1,9 +1,15 @@
"""Shared pytest fixtures for drone tests."""
import os
import tempfile
# Redirect prax logs to temp directory during tests
# Must be set before any prax imports to catch logger initialization
if "AIPASS_TEST_LOG_DIR" not in os.environ:
os.environ["AIPASS_TEST_LOG_DIR"] = tempfile.mkdtemp(prefix="aipass_test_logs_")
import json
import logging
import shutil
import tempfile
from pathlib import Path
from typing import Generator
from unittest.mock import MagicMock
+8 -1
View File
@@ -1,8 +1,15 @@
"""Shared pytest fixtures for flow tests"""
import os
import tempfile
# Redirect prax logs to temp directory during tests
# Must be set before any prax imports to catch logger initialization
if "AIPASS_TEST_LOG_DIR" not in os.environ:
os.environ["AIPASS_TEST_LOG_DIR"] = tempfile.mkdtemp(prefix="aipass_test_logs_")
import pytest
import json
import shutil
import tempfile
from pathlib import Path
from typing import Generator
from unittest.mock import MagicMock, patch
+8 -1
View File
@@ -7,10 +7,17 @@
# =============================================
"""Shared pytest fixtures for memory tests."""
import os
import tempfile
# Redirect prax logs to temp directory during tests
# Must be set before any prax imports to catch logger initialization
if "AIPASS_TEST_LOG_DIR" not in os.environ:
os.environ["AIPASS_TEST_LOG_DIR"] = tempfile.mkdtemp(prefix="aipass_test_logs_")
import json
import pytest
import shutil
import tempfile
from pathlib import Path
from typing import Generator
from unittest.mock import MagicMock
@@ -29,6 +29,7 @@ Usage:
import json
import logging
import os
logger = logging.getLogger(__name__)
from pathlib import Path
from typing import Dict, Any
@@ -64,6 +65,11 @@ def get_system_logs_dir() -> Path:
Central aggregation: all branches log here for system-wide monitoring.
Per-module logs use get_module_logs_dir() for local debugging.
"""
test_log_dir = os.environ.get("AIPASS_TEST_LOG_DIR")
if test_log_dir:
p = Path(test_log_dir) / "system"
p.mkdir(parents=True, exist_ok=True)
return p
global _system_logs_dir_cache
if _system_logs_dir_cache is None:
repo_root = _find_repo_root()
@@ -87,6 +93,11 @@ def get_module_logs_dir(module_name: str) -> Path:
Returns:
Path to the module's branch-root logs directory
"""
test_log_dir = os.environ.get("AIPASS_TEST_LOG_DIR")
if test_log_dir:
p = Path(test_log_dir) / module_name
p.mkdir(parents=True, exist_ok=True)
return p
# Standard: src/aipass/{module}/logs
branch_dir = ECOSYSTEM_ROOT / module_name
if branch_dir.exists():
+7
View File
@@ -11,6 +11,13 @@
Provides infrastructure mocking so test modules can import prax code
without triggering real logging, file watching, or CLI dependencies.
"""
import os
import tempfile
# Redirect prax logs to temp directory during tests
# Must be set before any prax imports to catch logger initialization
if "AIPASS_TEST_LOG_DIR" not in os.environ:
os.environ["AIPASS_TEST_LOG_DIR"] = tempfile.mkdtemp(prefix="aipass_test_logs_")
import sys
import pytest
+2
View File
@@ -49,6 +49,8 @@ def _fresh_import_load(monkeypatch, tmp_path):
monkeypatch.setattr(load_mod, "PRAX_LOGGER_CONFIG_FILE", prax_json_dir / "prax_logger_config.json")
# Reset the lazy cache so get_system_logs_dir() re-resolves
monkeypatch.setattr(load_mod, "_system_logs_dir_cache", None)
# Clear test log redirect so tests exercise real path resolution
monkeypatch.delenv("AIPASS_TEST_LOG_DIR", raising=False)
return load_mod
+8 -1
View File
@@ -8,9 +8,16 @@
# Modified: 2026-03-05
# =============================================
import os
import tempfile
# Redirect prax logs to temp directory during tests
# Must be set before any prax imports to catch logger initialization
if "AIPASS_TEST_LOG_DIR" not in os.environ:
os.environ["AIPASS_TEST_LOG_DIR"] = tempfile.mkdtemp(prefix="aipass_test_logs_")
import pytest
import shutil
import tempfile
from pathlib import Path
from typing import Generator
+7
View File
@@ -1,4 +1,11 @@
"""Shared test fixtures for spawn test suite."""
import os
import tempfile
# Redirect prax logs to temp directory during tests
# Must be set before any prax imports to catch logger initialization
if "AIPASS_TEST_LOG_DIR" not in os.environ:
os.environ["AIPASS_TEST_LOG_DIR"] = tempfile.mkdtemp(prefix="aipass_test_logs_")
import json
import shutil
@@ -7,13 +7,18 @@
# =============================================
import json
import os
from pathlib import Path
from datetime import datetime, timezone
from typing import Dict, List, Any, Optional
import inspect
# Infrastructure
_LOG_FILE = Path(__file__).parent.parent.parent.parent / "logs" / "json_handler.log"
# Infrastructure — redirect to temp dir during tests
_test_log_dir = os.environ.get("AIPASS_TEST_LOG_DIR")
if _test_log_dir:
_LOG_FILE = Path(_test_log_dir) / "trigger" / "json_handler.log"
else:
_LOG_FILE = Path(__file__).parent.parent.parent.parent / "logs" / "json_handler.log"
def _log_warning(msg: str) -> None:
@@ -158,6 +158,11 @@ def handle_command(command: str, args: list) -> bool:
remaining = args[1:]
return handle_command(subcommand, remaining)
# Help gate — catch --help passed as direct command
if command in ['--help', '-h', 'help']:
print_help()
return True
# Handle direct subcommands
if command not in ["start", "stop", "status", "reset"]:
return False
+15 -6
View File
@@ -19,6 +19,7 @@ Phase 5: Suppress triggers source fix pipeline (email + fix status tracking)
Architecture: Module orchestrates, error_registry handler manages data
"""
import json
import sys
import time
from pathlib import Path
@@ -84,12 +85,15 @@ def _parse_args(args: list) -> dict:
def _find_by_id_or_fp(identifier: str) -> Optional[dict]:
"""Look up error by fingerprint (prefix ok) or short ID field."""
entry = get_entry(identifier)
if entry:
return entry
for entry in query(limit=1000):
if entry.get("id") == identifier:
try:
entry = get_entry(identifier)
if entry:
return entry
for entry in query(limit=1000):
if entry.get("id") == identifier:
return entry
except (json.JSONDecodeError, KeyError, TypeError) as exc:
logger.warning("Failed to look up error '%s': %s", identifier, exc)
return None
@@ -238,7 +242,12 @@ def _cmd_detail(console, args: list) -> bool:
error("Missing error ID or fingerprint", suggestion="Usage: drone @trigger errors detail <id_or_fingerprint>")
return True
entry = _find_by_id_or_fp(args[0])
try:
entry = _find_by_id_or_fp(args[0])
except (json.JSONDecodeError, TypeError, KeyError) as exc:
error(f"Failed to read error registry: {exc}", suggestion="Registry may be corrupted — try 'drone @trigger errors list' first")
return True
if not entry:
error(f"Error not found: {args[0]}", suggestion="Try a fingerprint prefix, full fingerprint, or short ID")
return True
+8 -1
View File
@@ -14,9 +14,16 @@
# =============================================
"""Shared pytest fixtures for cortex tests"""
import os
import tempfile
# Redirect prax logs to temp directory during tests
# Must be set before any prax imports to catch logger initialization
if "AIPASS_TEST_LOG_DIR" not in os.environ:
os.environ["AIPASS_TEST_LOG_DIR"] = tempfile.mkdtemp(prefix="aipass_test_logs_")
import pytest
import shutil
import tempfile
from pathlib import Path
from typing import Generator
+3 -3
View File
@@ -13,7 +13,7 @@ Data retrieval and mutation for spatial room commands: enter, look, decorate, vi
Returns structured dicts for module-layer rendering.
"""
from datetime import datetime, timedelta
from datetime import datetime, timedelta, timezone
from typing import Dict, Any
from aipass.prax.apps.modules.logger import system_logger as logger
@@ -52,7 +52,7 @@ def get_room_enter_data(room_name: str) -> Dict[str, Any]:
"SELECT COUNT(*) FROM posts WHERE room_name = ?", (room_name,)
).fetchone()[0]
cutoff = (datetime.utcnow() - timedelta(hours=48)).strftime("%Y-%m-%dT%H:%M:%SZ")
cutoff = (datetime.now(timezone.utc) - timedelta(hours=48)).strftime("%Y-%m-%dT%H:%M:%SZ")
recent_count = conn.execute(
"SELECT COUNT(*) FROM posts WHERE room_name = ? AND created_at > ?",
(room_name, cutoff),
@@ -205,7 +205,7 @@ def get_visitors_data(room_name: str) -> Dict[str, Any]:
result["error"] = f"Room '{room_name}' not found"
return result
cutoff = (datetime.utcnow() - timedelta(hours=48)).strftime("%Y-%m-%dT%H:%M:%SZ")
cutoff = (datetime.now(timezone.utc) - timedelta(hours=48)).strftime("%Y-%m-%dT%H:%M:%SZ")
# Primary source: explicit room visits
visit_rows = conn.execute(
+7 -1
View File
@@ -19,8 +19,14 @@ The Commons - Test Configuration
Provides pytest fixtures for database setup, teardown,
and test isolation using temporary databases.
"""
import os
import tempfile
# Redirect prax logs to temp directory during tests
# Must be set before any prax imports to catch logger initialization
if "AIPASS_TEST_LOG_DIR" not in os.environ:
os.environ["AIPASS_TEST_LOG_DIR"] = tempfile.mkdtemp(prefix="aipass_test_logs_")
from pathlib import Path
import pytest
+7
View File
@@ -15,6 +15,13 @@
# =============================================
"""Skills test configuration."""
import os
import tempfile
# Redirect prax logs to temp directory during tests
# Must be set before any prax imports to catch logger initialization
if "AIPASS_TEST_LOG_DIR" not in os.environ:
os.environ["AIPASS_TEST_LOG_DIR"] = tempfile.mkdtemp(prefix="aipass_test_logs_")
import importlib
import logging