diff --git a/src/aipass/trigger/.seedgo/bypass.json b/src/aipass/trigger/.seedgo/bypass.json index 1e350e05..01cba2ea 100644 --- a/src/aipass/trigger/.seedgo/bypass.json +++ b/src/aipass/trigger/.seedgo/bypass.json @@ -361,6 +361,18 @@ "standard": "trigger", "pattern": "handle_pr", "reason": "PR event handlers (handle_pr_created, handle_pr_merged) are event handlers registered in registry.py, not trigger-specific naming violations." + }, + { + "file": "apps/handlers/log_watcher.py", + "standard": "silent_catch", + "lines": [236], + "reason": "Timestamp parsing loop tries multiple formats. except ValueError: continue is intentional \u2014 on failure, tries next format. Logger.warning fires once after ALL formats fail (line 240)." + }, + { + "file": "apps/modules/errors.py", + "standard": "silent_catch", + "lines": [247], + "reason": "Exception is handled: calls error() to display user-facing message with suggestion. Not a silent catch \u2014 the user sees the error output." } ], "notes": { diff --git a/src/aipass/trigger/apps/handlers/log_watcher.py b/src/aipass/trigger/apps/handlers/log_watcher.py index 0125a10d..2c790c68 100644 --- a/src/aipass/trigger/apps/handlers/log_watcher.py +++ b/src/aipass/trigger/apps/handlers/log_watcher.py @@ -228,16 +228,16 @@ def _is_stale_entry(timestamp_str: str) -> bool: '%Y-%m-%dT%H:%M:%S', # ISO simple: 2026-02-13T22:51:25 ] + stripped = timestamp_str.strip() for fmt in formats: try: - entry_time = datetime.strptime(timestamp_str.strip(), fmt) + entry_time = datetime.strptime(stripped, fmt) return entry_time < cutoff - except ValueError as exc: - logger.warning("Failed to parse timestamp '%s': %s", timestamp_str.strip(), exc) + except ValueError: continue - # If we can't parse the timestamp, treat as STALE to avoid re-flagging - # garbage or malformed entries as new errors (false positive prevention). + # All formats failed — log once and treat as stale + logger.warning("Failed to parse timestamp '%s' (no matching format)", stripped) return True diff --git a/src/aipass/trigger/apps/modules/branch_log_events.py b/src/aipass/trigger/apps/modules/branch_log_events.py index b727ca2b..b029330b 100644 --- a/src/aipass/trigger/apps/modules/branch_log_events.py +++ b/src/aipass/trigger/apps/modules/branch_log_events.py @@ -18,7 +18,6 @@ Architecture: Module orchestrates handlers """ import sys -from pathlib import Path from aipass.prax.apps.modules.logger import system_logger as logger @@ -116,21 +115,34 @@ def reset_hashes() -> None: def print_help() -> None: """Print module help.""" from aipass.cli.apps.modules import console + from rich.panel import Panel - console.print("Branch Log Events - Branch Log Watcher\n") - console.print("USAGE:") - console.print(" drone @trigger branch_log_events \n") - console.print("COMMANDS:") - console.print(" start - Start watching branch logs for errors") - console.print(" stop - Stop the branch log watcher") - console.print(" status - Show watcher status") - console.print(" reset - Clear error deduplication hashes\n") - console.print("MONITORING:") - console.print(f" Path: {AIPASS_PKG_ROOT}/*/logs/*.log") - console.print(" Format: Prax log format (timestamp | module | LEVEL | message)\n") - console.print("EVENTS FIRED:") - console.print(" error_detected - When ERROR/CRITICAL level log detected") - console.print(" Handled by AI_Mail's error_handler\n") + console.print(Panel("Branch Log Events - Branch Log Watcher", style="bold")) + console.print() + console.print("Watches branch log directories for ERROR entries.") + console.print("Fires error_detected events for the Medic dispatch pipeline.") + console.print() + console.rule("USAGE") + console.print() + console.print(" drone @trigger branch_log_events ") + console.print() + console.rule("COMMANDS") + console.print() + console.print(" [bold]start[/bold] Start watching branch logs for errors") + console.print(" [bold]stop[/bold] Stop the branch log watcher") + console.print(" [bold]status[/bold] Show watcher status") + console.print(" [bold]reset[/bold] Clear error deduplication hashes") + console.print() + console.rule("MONITORING") + console.print() + console.print(f" [dim]Path:[/dim] {AIPASS_PKG_ROOT}/*/logs/*.log") + console.print(" [dim]Format:[/dim] Prax log format (timestamp | module | LEVEL | message)") + console.print() + console.rule("EVENTS FIRED") + console.print() + console.print(" [bold]error_detected[/bold] When ERROR/CRITICAL level log detected") + console.print(" Handled by Medic dispatch pipeline") + console.print() def handle_command(command: str, args: list) -> bool: diff --git a/src/aipass/trigger/apps/modules/log_events.py b/src/aipass/trigger/apps/modules/log_events.py index 1883f0dc..45f03ee2 100644 --- a/src/aipass/trigger/apps/modules/log_events.py +++ b/src/aipass/trigger/apps/modules/log_events.py @@ -17,7 +17,6 @@ Architecture: Module orchestrates handlers """ import sys -from pathlib import Path from aipass.prax.apps.modules.logger import system_logger as logger @@ -102,17 +101,28 @@ def status() -> dict: def print_help() -> None: """Print module help.""" from aipass.cli.apps.modules import console + from rich.panel import Panel - console.print("Log Events - Centralized Log Watcher\n") - console.print("USAGE:") - console.print(" drone @trigger log_events \n") - console.print("COMMANDS:") - console.print(" start - Start watching logs for errors/warnings") - console.print(" stop - Stop the log watcher") - console.print(" status - Show watcher status\n") - console.print("EVENTS FIRED:") - console.print(" error_logged - When ERROR level log detected") - console.print(" warning_logged - When WARNING level log detected\n") + console.print(Panel("Log Events - Centralized Log Watcher", style="bold")) + console.print() + console.print("Watches system_logs/ for ERROR and WARNING entries.") + console.print("Fires events for downstream handlers to process.") + console.print() + console.rule("USAGE") + console.print() + console.print(" drone @trigger log_events ") + console.print() + console.rule("COMMANDS") + console.print() + console.print(" [bold]start[/bold] Start watching logs for errors/warnings") + console.print(" [bold]stop[/bold] Stop the log watcher") + console.print(" [bold]status[/bold] Show watcher status") + console.print() + console.rule("EVENTS FIRED") + console.print() + console.print(" [bold]error_logged[/bold] When ERROR level log detected") + console.print(" [bold]warning_logged[/bold] When WARNING level log detected") + console.print() def handle_command(command: str, args: list) -> bool: