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:
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user