feat(system): seedgo v2 operational, full system audit, 14/15 branches at 99%
Three days of intensive work bringing seedgo to full operational status and driving all branches through comprehensive standards compliance. Seedgo v2.0.0: - 22 checkers active (up from 20), standards pack fully operational - New introspection standard researched from Dev-Pass, FPLAN-0017 open - Bypass system for false positives (.seedgo config) - Standards query and audit commands fully functional System-wide audit (FPLAN-0016): - All 14 auditable branches at 99%+ compliance - CLI imports standardized across all branches (console from cli.apps.modules) - handle_command(command, args) → bool contract added to all modules - print_help() function naming fixed for checker pattern matching - Handler extraction: large modules split, file I/O moved to handler layer - New handlers created across ai_mail, backup, daemon, flow, skills, spawn, seedgo Branch-specific highlights: - ai_mail: email.py split 840→420 lines, 4 new handlers - flow: dplan_flow.py 688→591 lines, 4 new handlers - seedgo: massive restructure — standards moved to handlers/aipass_standards/, old standards/ tree removed, bypass system added, diagnostics module - commons: database module added, CLI imports fixed - skills: 5 handle_commands added, help function renamed - trigger: error reporter handler, handle_command routing - All branches: consistent architecture, clean drone routing Culture doc (CLAUDE.md) added — documents AIPass philosophy, identity, memory system, and collaboration principles. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
09e759a8a4
commit
babedd9c64
@@ -1,6 +1,17 @@
|
||||
# Trigger
|
||||
|
||||
Event bus for AIPass. Branches fire events, registered handlers react. Decouples producers from consumers — the module that detects a condition doesn't need to know what should happen next.
|
||||
**Purpose:** Event bus for AIPass. Branches fire events, registered handlers react. Decouples producers from consumers — the module that detects a condition doesn't need to know what should happen next.
|
||||
**Module:** `aipass.trigger`
|
||||
**Last Updated:** 2026-03-08
|
||||
|
||||
## Commands / Usage
|
||||
|
||||
```bash
|
||||
drone @trigger fire <event> [data] # Fire an event
|
||||
drone @trigger list # List registered events
|
||||
drone @trigger status # Event bus status
|
||||
drone @trigger --help # Full help
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -74,12 +85,34 @@ Built-in error monitoring subsystem. Watches logs for errors, fingerprints them
|
||||
```
|
||||
trigger/
|
||||
├── apps/
|
||||
│ ├── trigger.py # Entry point (auto-discovers modules)
|
||||
│ ├── trigger.py # Entry point (auto-discovers modules)
|
||||
│ ├── modules/
|
||||
│ │ ├── core.py # Event bus (Trigger.fire/on/off)
|
||||
│ │ ├── errors.py # Error registry + cross-branch API
|
||||
│ │ └── medic.py # Error monitoring commands
|
||||
│ │ ├── core.py # Event bus (Trigger.fire/on/off)
|
||||
│ │ ├── errors.py # Error registry + cross-branch API
|
||||
│ │ ├── medic.py # Error monitoring commands
|
||||
│ │ ├── branch_log_events.py # Branch-level log event handling
|
||||
│ │ └── log_events.py # System-wide log event processing
|
||||
│ └── handlers/
|
||||
│ └── events/ # One handler per event type
|
||||
│ └── events/ # One handler per event type
|
||||
└── tests/
|
||||
```
|
||||
|
||||
**Note:** `branch_log_events` and `log_events` are auto-discovered modules that handle log-based event detection at branch and system levels respectively.
|
||||
|
||||
---
|
||||
|
||||
## Integration Points
|
||||
|
||||
### Depends On
|
||||
- `aipass.prax` — Logging via `system_logger`
|
||||
- `aipass.cli` — Console output and header formatting
|
||||
- Python stdlib (`sys`, `pathlib`, `importlib`)
|
||||
|
||||
### Provides To
|
||||
- All modules — event bus (`Trigger.fire`, `Trigger.on`, `Trigger.off`)
|
||||
- All modules — cross-branch error reporting (`report_error`)
|
||||
- All modules — medic error monitoring and dispatch
|
||||
|
||||
---
|
||||
|
||||
*Last Updated: 2026-03-08*
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
# =================== AIPass ====================
|
||||
# Name: config.py
|
||||
# Description: Trigger package path configuration
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-09
|
||||
# Modified: 2026-03-09
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
Trigger package path configuration.
|
||||
|
||||
|
||||
@@ -1,25 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: error_registry.py - Error Registry Handler
|
||||
# Date: 2026-02-25
|
||||
# =================== AIPass ====================
|
||||
# Name: error_registry.py
|
||||
# Description: Structured error tracking and registry for Medic v2
|
||||
# Version: 2.3.0
|
||||
# Category: trigger/handlers
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v2.4.0 (2026-02-27): FPLAN-0382 Phase 3 - Migrate stdlib logging to Prax direct_log() (no-event pipeline)
|
||||
# - v2.3.0 (2026-02-25): FPLAN-0371 Phase 5 - Persist circuit breaker state to trigger_config.json, add logging to silent failure paths
|
||||
# - v2.2.0 (2026-02-25): FPLAN-0371 Phase 2 - User-error rejection layer in report() (auto-suppress unknown commands, invalid args)
|
||||
# - v2.1.0 (2026-02-13): Phase 5 - Source fix pipeline (update_source_fix_status)
|
||||
# - v2.0.0 (2026-02-13): Phase 2 - Circuit breaker + per-fingerprint rate limiting
|
||||
# - v1.0.0 (2026-02-13): Created - Medic v2 Phase 1 error registry foundation
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follows AIPass Seed standards
|
||||
# - NO console.print() - handlers return data to modules
|
||||
# - Uses Prax direct_log() (no event pipeline) to avoid recursion
|
||||
# - Self-contained - no imports from other trigger modules
|
||||
# - JSON file-based storage for error registry
|
||||
# Created: 2026-02-13
|
||||
# Modified: 2026-02-27
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
# =================== AIPass ====================
|
||||
# Name: error_reporter.py
|
||||
# Description: Error reporting handler for registry and source fix email
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-08
|
||||
# Modified: 2026-03-08
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
Error Reporting Handler
|
||||
|
||||
Contains the core logic for reporting errors to the registry and
|
||||
dispatching error_detected events. Also handles source fix email
|
||||
pipeline for suppressed errors.
|
||||
|
||||
Purpose:
|
||||
Implementation logic for error reporting, separated from CLI/display
|
||||
layer to satisfy thin-module standard.
|
||||
"""
|
||||
|
||||
from aipass.prax import logger
|
||||
|
||||
# logger imported from aipass.prax
|
||||
|
||||
from aipass.trigger.apps.handlers.error_registry import (
|
||||
report as _registry_report,
|
||||
)
|
||||
|
||||
|
||||
def send_source_fix_email(entry: dict) -> bool:
|
||||
"""Send recommendation email to source branch about fixing log level.
|
||||
|
||||
When an error is suppressed, the source branch gets notified that
|
||||
their log level may be wrong. This closes the loop:
|
||||
error -> investigate -> suppress -> fix source -> error stops
|
||||
|
||||
Args:
|
||||
entry: Error registry entry dict
|
||||
|
||||
Returns:
|
||||
True if email sent successfully
|
||||
"""
|
||||
try:
|
||||
from aipass.ai_mail.apps.modules.email import send_email_direct
|
||||
except ImportError:
|
||||
logger.info("[ERRORS] Could not import send_email_direct - ai_mail not available")
|
||||
return False
|
||||
|
||||
try:
|
||||
component = entry.get("component", "").lower()
|
||||
if not component or component == "unknown":
|
||||
return False
|
||||
|
||||
recipient = f"@{component}"
|
||||
fingerprint = entry.get("fingerprint", "")[:12]
|
||||
error_type = entry.get("error_type", "?")
|
||||
message = entry.get("message", "?")[:200]
|
||||
suppress_reason = entry.get("suppress_reason", "No reason")
|
||||
log_path = entry.get("log_path", "unknown")
|
||||
count = entry.get("count", 0)
|
||||
|
||||
subject = f"[LOG FIX] {error_type} classified as non-critical"
|
||||
|
||||
body = f"""Your code is generating an error that has been classified as non-critical.
|
||||
|
||||
Error fingerprint: {fingerprint}
|
||||
Error type: {error_type}
|
||||
Occurrences: {count}
|
||||
Log file: {log_path}
|
||||
Suppress reason: {suppress_reason}
|
||||
|
||||
Error message:
|
||||
{message}
|
||||
|
||||
RECOMMENDATION:
|
||||
This error is currently logged as ERROR but appears to be non-critical based on
|
||||
investigation. Consider one of:
|
||||
1. Change the log level from ERROR to WARNING or INFO
|
||||
2. Add proper error handling to prevent this from being logged
|
||||
3. If this is actually critical, reply to @trigger explaining why
|
||||
|
||||
This will prevent unnecessary error dispatch for this issue.
|
||||
|
||||
---
|
||||
Automated recommendation from Medic v2 Error Registry.
|
||||
Reply to @trigger with your fix status."""
|
||||
|
||||
send_email_direct(
|
||||
to_branch=recipient,
|
||||
subject=subject,
|
||||
message=body,
|
||||
reply_to='@trigger',
|
||||
from_branch='@trigger'
|
||||
)
|
||||
|
||||
logger.info(f"[ERRORS] Source fix email sent to {recipient} for {fingerprint}")
|
||||
return True
|
||||
except Exception as exc:
|
||||
logger.info(f"[ERRORS] Failed to send source fix email: {exc}")
|
||||
return False
|
||||
|
||||
|
||||
def report_error(
|
||||
error_type: str,
|
||||
message: str,
|
||||
component: str,
|
||||
log_path: str = "",
|
||||
severity: str = "medium",
|
||||
fire_event: bool = True
|
||||
) -> dict:
|
||||
"""Report an error to the registry and optionally fire error_detected event.
|
||||
|
||||
Public API for cross-branch push reporting. Drone and other branches
|
||||
call this instead of importing from handlers directly.
|
||||
|
||||
Pipeline: report() -> registry stores -> fire event -> handler checks
|
||||
circuit breaker + rate limiting -> dispatch email if allowed.
|
||||
|
||||
Args:
|
||||
error_type: Error class name (e.g., 'ImportError', 'TimeoutError')
|
||||
message: Original error message text
|
||||
component: Branch that generated the error (e.g., 'FLOW', 'API')
|
||||
log_path: Path to source log file (optional)
|
||||
severity: Error severity - low, medium, high, critical (default: medium)
|
||||
fire_event: Whether to fire error_detected event (default: True).
|
||||
Set False for silent registration without dispatch.
|
||||
|
||||
Returns:
|
||||
Dict with error entry data + 'is_new' bool + 'dispatched' bool.
|
||||
"""
|
||||
result = _registry_report(
|
||||
error_type=error_type,
|
||||
message=message,
|
||||
component=component,
|
||||
log_path=log_path,
|
||||
severity=severity,
|
||||
)
|
||||
result["dispatched"] = False
|
||||
|
||||
# Fire event on first occurrence (count==1) for registration and on
|
||||
# second occurrence (count==2) so the handler can apply the dispatch
|
||||
# threshold. Skip all other counts (backoff handles later dispatches).
|
||||
error_count = result.get("count", 1)
|
||||
if not fire_event or (not result.get("is_new", False) and error_count != 2):
|
||||
return result
|
||||
|
||||
try:
|
||||
from aipass.trigger.apps.modules.core import trigger as _trigger_bus
|
||||
_trigger_bus.fire(
|
||||
"error_detected",
|
||||
branch=component,
|
||||
module=error_type,
|
||||
message=message,
|
||||
log_path=log_path,
|
||||
error_hash=result.get("id", ""),
|
||||
timestamp=result.get("last_seen", ""),
|
||||
fingerprint=result.get("fingerprint", ""),
|
||||
registry_id=result.get("id", ""),
|
||||
first_seen=result.get("first_seen", ""),
|
||||
last_seen=result.get("last_seen", ""),
|
||||
count=error_count,
|
||||
)
|
||||
result["dispatched"] = True
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return result
|
||||
@@ -1,19 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: bulletin_created.py - Bulletin Created Event Handler
|
||||
# Date: 2026-01-31
|
||||
# =================== AIPass ====================
|
||||
# Name: bulletin_created.py
|
||||
# Description: Bulletin created event handler for dashboard propagation
|
||||
# Version: 1.0.0
|
||||
# Category: trigger/handlers/events
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.0.0 (2026-01-31): Created - Phase 3 migration (FPLAN-0280)
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follows AIPass Seed standards
|
||||
# - NO logger imports (causes infinite recursion in event handlers)
|
||||
# - NO print statements (handlers must be silent)
|
||||
# - Silent failure - catch all exceptions, pass
|
||||
# Created: 2026-01-31
|
||||
# Modified: 2026-01-31
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
|
||||
@@ -1,17 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: cli.py - CLI Event Handler
|
||||
# Date: 2025-12-04
|
||||
# =================== AIPass ====================
|
||||
# Name: cli.py
|
||||
# Description: CLI event handler for header display events
|
||||
# Version: 0.1.0
|
||||
# Category: trigger/handlers/events
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v0.1.0 (2025-12-04): Created CLI event handler
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follows AIPass Seed standards
|
||||
# - Handlers must not import Prax logger
|
||||
# Created: 2025-12-04
|
||||
# Modified: 2025-12-04
|
||||
# =============================================
|
||||
|
||||
"""CLI Event Handler - Handle CLI display events"""
|
||||
|
||||
@@ -1,26 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: error_detected.py - Error Detected Event Handler
|
||||
# Date: 2026-02-14
|
||||
# =================== AIPass ====================
|
||||
# Name: error_detected.py
|
||||
# Description: Error detected event handler with Medic v2 dispatch gating
|
||||
# Version: 2.1.0
|
||||
# Category: trigger/handlers/events
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v2.1.0 (2026-02-14): Dispatch threshold - count >= 2 required (skip first occurrence)
|
||||
# - v2.0.0 (2026-02-13): Medic v2 Phase 3 - Circuit breaker + per-fingerprint backoff dispatch
|
||||
# - v1.3.0 (2026-02-12): Medic Phase 2 - per-branch mute/unmute check
|
||||
# - v1.2.0 (2026-02-12): Medic toggle - check medic_enabled before dispatching
|
||||
# - v1.1.1 (2026-02-10): Add Seed standards reminder to error dispatch template
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follows AIPass Seed standards
|
||||
# - NO console.print() - handlers return data to modules
|
||||
# - NO logger calls in handler (causes recursion with trigger)
|
||||
# - Silent failure pattern - catch all exceptions
|
||||
# - Responds to error_detected events from Trigger's log_watcher
|
||||
# - Dispatch threshold: count >= 2 required (first occurrence is silent)
|
||||
# - Dispatch gating: circuit breaker (global) + per-fingerprint backoff (Medic v2)
|
||||
# Created: 2026-02-10
|
||||
# Modified: 2026-02-14
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
|
||||
@@ -1,24 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: error_logged.py - Error Logged Event Handler (DEPRECATED)
|
||||
# Date: 2026-01-31
|
||||
# =================== AIPass ====================
|
||||
# Name: error_logged.py
|
||||
# Description: Legacy error logged event handler with medic gating (deprecated)
|
||||
# Version: 2.0.0
|
||||
# Category: trigger/handlers/events
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v2.0.0 (2026-02-25): FPLAN-0371 Phase 1 - Add medic gating, DEV_CENTRAL protection, rate limiting
|
||||
# - v1.0.2 (2026-02-06): Validate target branch exists before delivery (fixes @telegram spam)
|
||||
# - v1.0.1 (2026-02-03): Fixed cross-branch import - uses module API instead of handler
|
||||
# - v1.0.0 (2026-01-31): Created - Phase 2 migration (FPLAN-0279)
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follows AIPass Seed standards
|
||||
# - NO logger imports (causes infinite recursion in event handlers)
|
||||
# - NO print statements (handlers must be silent)
|
||||
# - Silent failure - catch all exceptions, pass
|
||||
# - DEPRECATED: error_detected.py (Medic v2) is the primary error dispatch handler
|
||||
# - This handler remains for backward compat with code that fires error_logged events
|
||||
# Created: 2026-01-31
|
||||
# Modified: 2026-02-25
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
|
||||
@@ -1,18 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: memory.py - Memory Event Handler
|
||||
# Date: 2025-12-04
|
||||
# =================== AIPass ====================
|
||||
# Name: memory.py
|
||||
# Description: Memory event handler placeholder for future rollover triggers
|
||||
# Version: 0.1.0
|
||||
# Category: trigger/handlers/events
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v0.1.0 (2025-12-04): Created memory event handler placeholder
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follows AIPass Seed standards
|
||||
# - Placeholder for future memory event handling
|
||||
# - Handlers must not import Prax logger
|
||||
# Created: 2025-12-04
|
||||
# Modified: 2025-12-04
|
||||
# =============================================
|
||||
|
||||
"""Memory Event Handler - Handle memory-related events
|
||||
|
||||
@@ -1,21 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: memory_template_updated.py - Memory Template Updated Event Handler
|
||||
# Date: 2026-02-14
|
||||
# =================== AIPass ====================
|
||||
# Name: memory_template_updated.py
|
||||
# Description: Memory template updated event handler for branch push
|
||||
# Version: 1.0.0
|
||||
# Category: trigger/handlers/events
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.0.0 (2026-02-14): Created - Phase 3 of FPLAN-0340
|
||||
# * Handles memory_template_updated event
|
||||
# * Pushes living template updates to all branches
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follows AIPass Seed standards
|
||||
# - NO logger imports (causes infinite recursion in event handlers)
|
||||
# - NO print statements (handlers must be silent)
|
||||
# - Silent failure - catch all exceptions, pass
|
||||
# Created: 2026-02-14
|
||||
# Modified: 2026-02-14
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
|
||||
@@ -1,19 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: memory_threshold_exceeded.py - Memory Threshold Exceeded Event Handler
|
||||
# Date: 2026-01-31
|
||||
# =================== AIPass ====================
|
||||
# Name: memory_threshold_exceeded.py
|
||||
# Description: Memory threshold exceeded event handler for compression notifications
|
||||
# Version: 1.0.0
|
||||
# Category: trigger/handlers/events
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.0.0 (2026-01-31): Created - Phase 3 migration (FPLAN-0280)
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follows AIPass Seed standards
|
||||
# - NO logger imports (causes infinite recursion in event handlers)
|
||||
# - NO print statements (handlers must be silent)
|
||||
# - Silent failure - catch all exceptions, pass
|
||||
# Created: 2026-01-31
|
||||
# Modified: 2026-01-31
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
|
||||
@@ -1,19 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: plan_file.py - PLAN file event handlers
|
||||
# Date: 2026-01-20
|
||||
# =================== AIPass ====================
|
||||
# Name: plan_file.py
|
||||
# Description: PLAN file event handlers for registry updates
|
||||
# Version: 1.0.0
|
||||
# Category: trigger/handlers/events
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.0.0 (2026-01-20): Migrated from Flow's registry_monitor.py
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follows AIPass Seed standards
|
||||
# - Handles plan_file_created, plan_file_deleted, plan_file_moved events
|
||||
# - Updates Flow's registry when PLAN files change
|
||||
# - No Prax logger imports (handler independence)
|
||||
# Created: 2026-01-20
|
||||
# Modified: 2026-01-20
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
|
||||
@@ -1,18 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: registry.py - Event Handler Registry
|
||||
# Date: 2025-12-04
|
||||
# =================== AIPass ====================
|
||||
# Name: registry.py
|
||||
# Description: Event handler registry for startup registration
|
||||
# Version: 0.1.0
|
||||
# Category: trigger/handlers/events
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v0.1.0 (2025-12-04): Created event handler registry
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follows AIPass Seed standards
|
||||
# - Registers all event handlers on startup
|
||||
# - Event-based trigger system
|
||||
# Created: 2025-12-04
|
||||
# Modified: 2025-12-04
|
||||
# =============================================
|
||||
|
||||
"""Event Handler Registry - Setup all event handlers on startup"""
|
||||
|
||||
@@ -1,21 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: startup.py - Startup Event Handler
|
||||
# Date: 2026-02-03
|
||||
# =================== AIPass ====================
|
||||
# Name: startup.py
|
||||
# Description: Startup event handler with error catch-up scanning
|
||||
# Version: 1.0.0
|
||||
# Category: trigger/handlers/events
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.0.0 (2026-02-26): DPLAN-037 - Add MAX_ERRORS, MAX_FILE_SIZE, time budget to error catchup
|
||||
# - v0.2.0 (2026-02-03): Added error catch-up on startup
|
||||
# - v0.1.0 (2025-12-04): Created startup event handler
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follows AIPass Seed standards
|
||||
# - Replaces Prax logger's hardcoded calls with event-based approach
|
||||
# - Handlers must not import Prax logger
|
||||
# - Handlers receive fire_event callback via kwargs (no module imports)
|
||||
# Created: 2025-12-04
|
||||
# Modified: 2026-02-26
|
||||
# =============================================
|
||||
|
||||
"""Startup Event Handler - Run startup checks
|
||||
|
||||
@@ -1,19 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: warning_logged.py - Warning Logged Event Handler
|
||||
# Date: 2026-01-31
|
||||
# =================== AIPass ====================
|
||||
# Name: warning_logged.py
|
||||
# Description: Warning logged event handler for monitoring hooks
|
||||
# Version: 1.0.0
|
||||
# Category: trigger/handlers/events
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.0.0 (2026-01-31): Created - Phase 2 migration (FPLAN-0279)
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follows AIPass Seed standards
|
||||
# - NO logger imports (causes infinite recursion in event handlers)
|
||||
# - NO print statements (handlers must be silent)
|
||||
# - Silent failure - catch all exceptions, pass
|
||||
# Created: 2026-01-31
|
||||
# Modified: 2026-01-31
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
|
||||
@@ -1,18 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: json_handler.py - JSON Auto-Creating Handler
|
||||
# Date: 2025-11-21
|
||||
# =================== AIPass ====================
|
||||
# Name: json_handler.py
|
||||
# Description: JSON auto-creating handler for trigger data files
|
||||
# Version: 1.1.0
|
||||
# Category: trigger/handlers/json
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.1.0 (2025-11-21): Refactored to comply with error handling
|
||||
# - v1.0.0 (2025-11-13): Initial JSON auto-creation system
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Pure functions with proper error raising
|
||||
# - No Prax imports (handler tier 3)
|
||||
# Created: 2025-11-13
|
||||
# Modified: 2025-11-21
|
||||
# =============================================
|
||||
|
||||
import json
|
||||
|
||||
@@ -1,28 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: log_watcher.py - Branch Log Watcher Event Producer
|
||||
# Date: 2026-02-25
|
||||
# =================== AIPass ====================
|
||||
# Name: log_watcher.py
|
||||
# Description: Branch log watcher event producer for error detection
|
||||
# Version: 2.3.0
|
||||
# Category: trigger/handlers
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v2.4.0 (2026-02-27): FPLAN-0382 Phase 3 - Migrate stdlib logging to Prax direct_log() (no-event pipeline)
|
||||
# - v2.3.0 (2026-02-25): FPLAN-0371 Phase 5 - Add logging when _fire_event callback is None (silent failure path)
|
||||
# - v2.2.0 (2026-02-25): FPLAN-0371 Phase 2 - False positive elimination: strict parser, semantic exclusion, case-insensitive excludes, stale default
|
||||
# - v2.1.0 (2026-02-23): Fix false positives - persist positions, exclude self-referential logs, timestamp guard
|
||||
# - v2.0.0 (2026-02-13): Medic v2 Phase 3 - Registry-based dedup via error_registry.report()
|
||||
# - v1.0.1 (2026-02-10): FPLAN-0310 Phase 2 - Persist dedup hashes to trigger_data.json, increase max to 2000
|
||||
# - v1.0.0 (2026-02-02): Created - FPLAN-0284 Phase 1
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follows AIPass Seed standards
|
||||
# - NO console.print() - handlers return data to modules
|
||||
# - Uses Prax direct_log() (no event pipeline) to avoid recursion
|
||||
# - Fires error_detected events when ERROR entries found in branch logs
|
||||
# - Primary dedup path: error_registry.report() (Medic v2)
|
||||
# - Fallback dedup: MD5 hash-based (Medic v1, kept for backward compat)
|
||||
# - Dispatch threshold: fires event on count==1 (register) AND count==2 (dispatch)
|
||||
# Created: 2026-02-02
|
||||
# Modified: 2026-02-27
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
|
||||
@@ -1,19 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: medic_state.py - Medic State Handler
|
||||
# Date: 2026-02-12
|
||||
# =================== AIPass ====================
|
||||
# Name: medic_state.py
|
||||
# Description: Medic state persistence and status collection handler
|
||||
# Version: 1.1.0
|
||||
# Category: trigger/handlers
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.1.0 (2026-02-12): Added mute/unmute per-branch support (Phase 2)
|
||||
# - v1.0.0 (2026-02-12): Created - Medic state persistence and status collection
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follows AIPass Seed standards
|
||||
# - NO console.print() - handlers return data to modules
|
||||
# - Handles file I/O for medic config and status
|
||||
# Created: 2026-02-12
|
||||
# Modified: 2026-02-12
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
|
||||
@@ -1,19 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: log_watcher.py - Centralized Log File Watcher
|
||||
# Date: 2026-01-31
|
||||
# =================== AIPass ====================
|
||||
# Name: log_watcher.py
|
||||
# Description: Centralized log file watcher for system_logs directory
|
||||
# Version: 1.0.0
|
||||
# Category: trigger/handlers/watchers
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.0.0 (2026-01-31): Created - Phase 2 migration from Prax/AI_Mail
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follows AIPass Seed standards
|
||||
# - Centralized log watching for entire system
|
||||
# - Fires events: error_logged, warning_logged, log_entry
|
||||
# - All log watching moves to Trigger, other branches respond to events
|
||||
# Created: 2026-01-31
|
||||
# Modified: 2026-01-31
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
@@ -35,13 +25,13 @@ Architecture:
|
||||
|
||||
import sys
|
||||
import hashlib
|
||||
import logging
|
||||
from aipass.prax import logger
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Dict, Any
|
||||
|
||||
# Logger - use standard logging to avoid circular imports with Prax
|
||||
logger = logging.getLogger(__name__)
|
||||
# Logger - use prax system_logger for Error_Handling and Log_Visibility standards
|
||||
# logger imported from aipass.prax
|
||||
|
||||
# System logs directory (package-relative via config)
|
||||
from aipass.trigger.apps.config import TRIGGER_ROOT
|
||||
|
||||
@@ -1,18 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: branch_log_events.py - Branch Log Events Module
|
||||
# Date: 2026-02-02
|
||||
# =================== AIPass ====================
|
||||
# Name: branch_log_events.py
|
||||
# Description: Branch log events module for log watcher public API
|
||||
# Version: 1.0.0
|
||||
# Category: trigger/modules
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.0.0 (2026-02-02): Created - FPLAN-0284 Phase 4
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follows AIPass Seed standards
|
||||
# - Module orchestrates, handlers contain logic
|
||||
# - Public API for branch log event watching
|
||||
# Created: 2026-02-02
|
||||
# Modified: 2026-02-02
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
@@ -44,6 +35,29 @@ from aipass.trigger.apps.handlers.log_watcher import (
|
||||
from aipass.trigger.apps.config import AIPASS_PKG_ROOT
|
||||
|
||||
|
||||
def print_introspection():
|
||||
"""Display module introspection info."""
|
||||
try:
|
||||
from aipass.cli.apps.modules.display import console
|
||||
except ImportError:
|
||||
from rich.console import Console
|
||||
console = Console()
|
||||
|
||||
console.print()
|
||||
console.print("branch_log_events Module")
|
||||
console.print("Branch log watcher — watches branch logs for ERROR entries and fires events")
|
||||
console.print()
|
||||
console.print("Connected Handlers:")
|
||||
console.print(" handlers/")
|
||||
console.print(" - log_watcher.py (set_event_callback — set callback for detected events)")
|
||||
console.print(" - log_watcher.py (start_branch_log_watcher — start filesystem watcher)")
|
||||
console.print(" - log_watcher.py (stop_branch_log_watcher — stop filesystem watcher)")
|
||||
console.print(" - log_watcher.py (is_branch_log_watcher_active — check watcher state)")
|
||||
console.print(" - log_watcher.py (get_watcher_status — get full status dict)")
|
||||
console.print(" - log_watcher.py (clear_seen_hashes — reset error deduplication)")
|
||||
console.print()
|
||||
|
||||
|
||||
def start() -> bool:
|
||||
"""
|
||||
Start the branch log watcher.
|
||||
|
||||
@@ -1,21 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: core.py - Trigger Event Bus
|
||||
# Date: 2026-02-03
|
||||
# =================== AIPass ====================
|
||||
# Name: core.py
|
||||
# Description: Trigger event bus for AIPass system-wide event handling
|
||||
# Version: 1.2.0
|
||||
# Category: trigger/modules
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.2.0 (2026-02-03): Add deferred queue for nested event firing (fixes catch-up blocking)
|
||||
# - v1.1.4 (2026-02-03): Pass fire_event callback to handlers (enables error catch-up)
|
||||
# - v1.1.3 (2026-02-03): Disable lazy-start watchers entirely (inotify exhaustion - use prax monitor)
|
||||
# - v1.1.2 (2026-02-03): Also start system log watcher (fixes missing system_logs monitoring)
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follows AIPass Seed standards
|
||||
# - Event bus pattern for system-wide events
|
||||
# - Lazy-start pattern from Prax logger
|
||||
# Created: 2026-02-03
|
||||
# Modified: 2026-02-03
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
@@ -34,6 +22,24 @@ from aipass.prax.apps.modules.logger import system_logger as logger
|
||||
from typing import Callable
|
||||
|
||||
|
||||
def print_introspection():
|
||||
"""Display module introspection info."""
|
||||
try:
|
||||
from aipass.cli.apps.modules.display import console
|
||||
except ImportError:
|
||||
from rich.console import Console
|
||||
console = Console()
|
||||
|
||||
console.print()
|
||||
console.print("core Module")
|
||||
console.print("Trigger event bus — fire events, register handlers, deferred queue processing")
|
||||
console.print()
|
||||
console.print("Connected Handlers:")
|
||||
console.print(" handlers/events/")
|
||||
console.print(" - registry.py (setup_handlers — auto-register all event handlers on first use)")
|
||||
console.print()
|
||||
|
||||
|
||||
def _get_caller() -> str:
|
||||
"""Get the calling module/file name"""
|
||||
stack = inspect.stack()
|
||||
@@ -123,9 +129,6 @@ class Trigger:
|
||||
cls._ensure_initialized()
|
||||
cls._ensure_log_watcher()
|
||||
handlers = cls._handlers.get(event, [])
|
||||
caller = _get_caller()
|
||||
logger.info(f"[TRIGGER] {caller} fired: {event}")
|
||||
logger.info(f"[TRIGGER] {len(handlers)} handlers responding")
|
||||
|
||||
# Provide fire_event callback so handlers can fire events without importing
|
||||
data['fire_event'] = cls.fire
|
||||
@@ -166,5 +169,82 @@ class Trigger:
|
||||
return {event: len(handlers) for event, handlers in cls._handlers.items()}
|
||||
|
||||
|
||||
def handle_command(command: str, args: list) -> bool:
|
||||
"""Handle commands routed by the entry point.
|
||||
|
||||
Commands:
|
||||
fire <event> [key=value ...] - Fire an event with optional data
|
||||
status - Show registered event handlers
|
||||
list - Alias for status
|
||||
|
||||
Args:
|
||||
command: Command to execute (fire, status, list)
|
||||
args: Additional arguments
|
||||
|
||||
Returns:
|
||||
True if command was handled, False otherwise
|
||||
"""
|
||||
from aipass.cli.apps.modules import console
|
||||
|
||||
if command not in ["fire", "status", "list"]:
|
||||
return False
|
||||
|
||||
if args and args[0] in ['--help', '-h', 'help']:
|
||||
_print_help(console)
|
||||
return True
|
||||
|
||||
if command == "fire":
|
||||
if not args:
|
||||
console.print("[red]Usage: drone @trigger fire <event> [key=value ...][/red]")
|
||||
return True
|
||||
event_name = args[0]
|
||||
# Parse key=value pairs from remaining args
|
||||
data = {}
|
||||
for arg in args[1:]:
|
||||
if "=" in arg:
|
||||
key, value = arg.split("=", 1)
|
||||
data[key] = value
|
||||
else:
|
||||
logger.warning(f"[TRIGGER] Ignoring unparseable arg: {arg}")
|
||||
Trigger.fire(event_name, **data)
|
||||
console.print(f"[green]Fired event:[/green] {event_name}")
|
||||
if data:
|
||||
for k, v in data.items():
|
||||
console.print(f" [dim]{k}={v}[/dim]")
|
||||
return True
|
||||
|
||||
elif command in ["status", "list"]:
|
||||
handler_map = Trigger.status()
|
||||
if not handler_map:
|
||||
console.print("[dim]No event handlers registered[/dim]")
|
||||
return True
|
||||
console.print("[bold cyan]Registered Event Handlers[/bold cyan]")
|
||||
console.print()
|
||||
for event, count in sorted(handler_map.items()):
|
||||
console.print(f" [green]{event:30}[/green] {count} handler(s)")
|
||||
console.print()
|
||||
console.print(f"[dim]Total: {len(handler_map)} events, "
|
||||
f"{sum(handler_map.values())} handlers[/dim]")
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def _print_help(console):
|
||||
"""Display help for core trigger commands."""
|
||||
console.print()
|
||||
console.print("[bold cyan]TRIGGER CORE - Event Bus[/bold cyan]")
|
||||
console.print()
|
||||
console.print("[bold]COMMANDS:[/bold]")
|
||||
console.print(" fire <event> [key=value ...] Fire an event with optional data")
|
||||
console.print(" status Show registered event handlers")
|
||||
console.print(" list Alias for status")
|
||||
console.print()
|
||||
console.print("[bold]EXAMPLES:[/bold]")
|
||||
console.print(" drone @trigger fire deploy_complete branch=main")
|
||||
console.print(" drone @trigger status")
|
||||
console.print()
|
||||
|
||||
|
||||
# Create instance for import
|
||||
trigger = Trigger()
|
||||
|
||||
@@ -1,20 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: errors.py - Error Registry Management Module
|
||||
# Date: 2026-02-13
|
||||
# Version: 1.2.0
|
||||
# Category: trigger/modules
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.2.0 (2026-02-14): Public API report_error() for cross-branch push reporting
|
||||
# - v1.1.0 (2026-02-13): Phase 5 - Source fix pipeline (email + fix status tracking)
|
||||
# - v1.0.0 (2026-02-13): Created - Phase 4 Medic v2 management commands
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follows AIPass Seed standards
|
||||
# - Module orchestrates, handler (error_registry.py) contains data logic
|
||||
# - No direct file operations - delegates to handler
|
||||
# =================== AIPass ====================
|
||||
# Name: errors.py
|
||||
# Description: Error registry management module for Medic v2 commands
|
||||
# Version: 1.3.0
|
||||
# Created: 2026-02-13
|
||||
# Modified: 2026-03-08
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
@@ -41,74 +30,38 @@ from aipass.trigger.apps.handlers.error_registry import (
|
||||
query, get_entry, update_status, clear_resolved, get_stats,
|
||||
get_circuit_breaker_status, circuit_breaker_reset,
|
||||
update_source_fix_status,
|
||||
report as _registry_report,
|
||||
)
|
||||
from aipass.trigger.apps.handlers.error_reporter import (
|
||||
report_error,
|
||||
send_source_fix_email as _send_source_fix_email,
|
||||
)
|
||||
|
||||
def report_error(
|
||||
error_type: str,
|
||||
message: str,
|
||||
component: str,
|
||||
log_path: str = "",
|
||||
severity: str = "medium",
|
||||
fire_event: bool = True
|
||||
) -> dict:
|
||||
"""Report an error to the registry and optionally fire error_detected event.
|
||||
|
||||
Public API for cross-branch push reporting. Drone and other branches
|
||||
call this instead of importing from handlers directly.
|
||||
|
||||
Pipeline: report() -> registry stores -> fire event -> handler checks
|
||||
circuit breaker + rate limiting -> dispatch email if allowed.
|
||||
|
||||
Args:
|
||||
error_type: Error class name (e.g., 'ImportError', 'TimeoutError')
|
||||
message: Original error message text
|
||||
component: Branch that generated the error (e.g., 'FLOW', 'API')
|
||||
log_path: Path to source log file (optional)
|
||||
severity: Error severity - low, medium, high, critical (default: medium)
|
||||
fire_event: Whether to fire error_detected event (default: True).
|
||||
Set False for silent registration without dispatch.
|
||||
|
||||
Returns:
|
||||
Dict with error entry data + 'is_new' bool + 'dispatched' bool.
|
||||
"""
|
||||
result = _registry_report(
|
||||
error_type=error_type,
|
||||
message=message,
|
||||
component=component,
|
||||
log_path=log_path,
|
||||
severity=severity,
|
||||
)
|
||||
result["dispatched"] = False
|
||||
|
||||
# Fire event on first occurrence (count==1) for registration and on
|
||||
# second occurrence (count==2) so the handler can apply the dispatch
|
||||
# threshold. Skip all other counts (backoff handles later dispatches).
|
||||
error_count = result.get("count", 1)
|
||||
if not fire_event or (not result.get("is_new", False) and error_count != 2):
|
||||
return result
|
||||
|
||||
def print_introspection():
|
||||
"""Display module introspection info."""
|
||||
try:
|
||||
from aipass.trigger.apps.modules.core import trigger as _trigger_bus
|
||||
_trigger_bus.fire(
|
||||
"error_detected",
|
||||
branch=component,
|
||||
module=error_type,
|
||||
message=message,
|
||||
log_path=log_path,
|
||||
error_hash=result.get("id", ""),
|
||||
timestamp=result.get("last_seen", ""),
|
||||
fingerprint=result.get("fingerprint", ""),
|
||||
registry_id=result.get("id", ""),
|
||||
first_seen=result.get("first_seen", ""),
|
||||
last_seen=result.get("last_seen", ""),
|
||||
count=error_count,
|
||||
)
|
||||
result["dispatched"] = True
|
||||
except Exception:
|
||||
pass
|
||||
from aipass.cli.apps.modules.display import console
|
||||
except ImportError:
|
||||
from rich.console import Console
|
||||
console = Console()
|
||||
|
||||
return result
|
||||
console.print()
|
||||
console.print("errors Module")
|
||||
console.print("Error registry management — view, filter, suppress, and resolve tracked errors")
|
||||
console.print()
|
||||
console.print("Connected Handlers:")
|
||||
console.print(" handlers/")
|
||||
console.print(" - error_registry.py (query — search/filter error entries)")
|
||||
console.print(" - error_registry.py (get_entry — get single error by fingerprint)")
|
||||
console.print(" - error_registry.py (update_status — change error status)")
|
||||
console.print(" - error_registry.py (clear_resolved — purge old resolved entries)")
|
||||
console.print(" - error_registry.py (get_stats — summary statistics)")
|
||||
console.print(" - error_registry.py (get_circuit_breaker_status — circuit breaker state)")
|
||||
console.print(" - error_registry.py (circuit_breaker_reset — reset circuit breaker)")
|
||||
console.print(" - error_registry.py (update_source_fix_status — update fix tracking)")
|
||||
console.print(" - error_reporter.py (report_error — cross-branch push error reporting)")
|
||||
console.print(" - error_reporter.py (send_source_fix_email — notify branch to fix error)")
|
||||
console.print()
|
||||
|
||||
|
||||
_STATUS_COLORS = {"new": "yellow", "investigating": "cyan", "suppressed": "dim", "resolved": "green"}
|
||||
@@ -222,83 +175,6 @@ def handle_command(command: str, args: list) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Source Fix Pipeline
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def _send_source_fix_email(entry: dict) -> bool:
|
||||
"""Send recommendation email to source branch about fixing log level.
|
||||
|
||||
When an error is suppressed, the source branch gets notified that
|
||||
their log level may be wrong. This closes the loop:
|
||||
error -> investigate -> suppress -> fix source -> error stops
|
||||
|
||||
Args:
|
||||
entry: Error registry entry dict
|
||||
|
||||
Returns:
|
||||
True if email sent successfully
|
||||
"""
|
||||
try:
|
||||
from aipass.ai_mail.apps.modules.email import send_email_direct
|
||||
except ImportError:
|
||||
logger.info("[ERRORS] Could not import send_email_direct - ai_mail not available")
|
||||
return False
|
||||
|
||||
try:
|
||||
component = entry.get("component", "").lower()
|
||||
if not component or component == "unknown":
|
||||
return False
|
||||
|
||||
recipient = f"@{component}"
|
||||
fingerprint = entry.get("fingerprint", "")[:12]
|
||||
error_type = entry.get("error_type", "?")
|
||||
message = entry.get("message", "?")[:200]
|
||||
suppress_reason = entry.get("suppress_reason", "No reason")
|
||||
log_path = entry.get("log_path", "unknown")
|
||||
count = entry.get("count", 0)
|
||||
|
||||
subject = f"[LOG FIX] {error_type} classified as non-critical"
|
||||
|
||||
body = f"""Your code is generating an error that has been classified as non-critical.
|
||||
|
||||
Error fingerprint: {fingerprint}
|
||||
Error type: {error_type}
|
||||
Occurrences: {count}
|
||||
Log file: {log_path}
|
||||
Suppress reason: {suppress_reason}
|
||||
|
||||
Error message:
|
||||
{message}
|
||||
|
||||
RECOMMENDATION:
|
||||
This error is currently logged as ERROR but appears to be non-critical based on
|
||||
investigation. Consider one of:
|
||||
1. Change the log level from ERROR to WARNING or INFO
|
||||
2. Add proper error handling to prevent this from being logged
|
||||
3. If this is actually critical, reply to @trigger explaining why
|
||||
|
||||
This will prevent unnecessary error dispatch for this issue.
|
||||
|
||||
---
|
||||
Automated recommendation from Medic v2 Error Registry.
|
||||
Reply to @trigger with your fix status."""
|
||||
|
||||
send_email_direct(
|
||||
to_branch=recipient,
|
||||
subject=subject,
|
||||
message=body,
|
||||
reply_to='@trigger',
|
||||
from_branch='@trigger'
|
||||
)
|
||||
|
||||
logger.info(f"[ERRORS] Source fix email sent to {recipient} for {fingerprint}")
|
||||
return True
|
||||
except Exception as exc:
|
||||
logger.info(f"[ERRORS] Failed to send source fix email: {exc}")
|
||||
return False
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Command implementations
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@@ -1,18 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: log_events.py - Log Events Module
|
||||
# Date: 2026-01-31
|
||||
# =================== AIPass ====================
|
||||
# Name: log_events.py
|
||||
# Description: Log events module for centralized log watcher public API
|
||||
# Version: 1.0.0
|
||||
# Category: trigger/modules
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.0.0 (2026-01-31): Created - Phase 2 migration (FPLAN-0279)
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follows AIPass Seed standards
|
||||
# - Module orchestrates, handlers contain logic
|
||||
# - Public API for log event watching
|
||||
# Created: 2026-01-31
|
||||
# Modified: 2026-01-31
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
@@ -40,6 +31,27 @@ from aipass.trigger.apps.handlers.watchers.log_watcher import (
|
||||
)
|
||||
|
||||
|
||||
def print_introspection():
|
||||
"""Display module introspection info."""
|
||||
try:
|
||||
from aipass.cli.apps.modules.display import console
|
||||
except ImportError:
|
||||
from rich.console import Console
|
||||
console = Console()
|
||||
|
||||
console.print()
|
||||
console.print("log_events Module")
|
||||
console.print("Centralized log watcher — watches system_logs/ for error and warning events")
|
||||
console.print()
|
||||
console.print("Connected Handlers:")
|
||||
console.print(" handlers/watchers/")
|
||||
console.print(" - log_watcher.py (start_log_watcher — start centralized log watcher)")
|
||||
console.print(" - log_watcher.py (stop_log_watcher — stop centralized log watcher)")
|
||||
console.print(" - log_watcher.py (is_log_watcher_active — check if watcher is running)")
|
||||
console.print(" - log_watcher.py (SYSTEM_LOGS_DIR — monitored log directory path)")
|
||||
console.print()
|
||||
|
||||
|
||||
def start() -> bool:
|
||||
"""
|
||||
Start the centralized log watcher.
|
||||
|
||||
@@ -1,22 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: medic.py - Medic Toggle Module
|
||||
# Date: 2026-03-01
|
||||
# =================== AIPass ====================
|
||||
# Name: medic.py
|
||||
# Description: Medic toggle module for auto-healing error dispatch control
|
||||
# Version: 1.4.0
|
||||
# Category: trigger/modules
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.4.0 (2026-03-01): Persistent watcher via systemd service (trigger-log-watcher.service)
|
||||
# - v1.3.0 (2026-02-25): FPLAN-0371 Phase 5 - Rich Panel formatting for on/off/mute/unmute output
|
||||
# - v1.2.0 (2026-02-12): Improved status wording: standby vs stopped, added explanation lines
|
||||
# - v1.1.0 (2026-02-12): Added mute/unmute per-branch commands (Phase 2)
|
||||
# - v1.0.0 (2026-02-12): Created - Medic on/off/status toggle for error dispatch
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Follows AIPass Seed standards
|
||||
# - Module orchestrates, handler (medic_state.py) contains logic
|
||||
# - No direct file operations - delegates to handler
|
||||
# Created: 2026-02-12
|
||||
# Modified: 2026-03-01
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
@@ -51,6 +38,30 @@ from aipass.trigger.apps.handlers.medic_state import (
|
||||
SERVICE_NAME = "trigger-log-watcher.service"
|
||||
|
||||
|
||||
def print_introspection():
|
||||
"""Display module introspection info."""
|
||||
try:
|
||||
from aipass.cli.apps.modules.display import console
|
||||
except ImportError:
|
||||
from rich.console import Console
|
||||
console = Console()
|
||||
|
||||
console.print()
|
||||
console.print("medic Module")
|
||||
console.print("Medic toggle — control auto-healing error dispatch on/off/mute/unmute")
|
||||
console.print()
|
||||
console.print("Connected Handlers:")
|
||||
console.print(" handlers/")
|
||||
console.print(" - medic_state.py (is_enabled — check if medic is enabled)")
|
||||
console.print(" - medic_state.py (set_enabled — toggle medic on/off)")
|
||||
console.print(" - medic_state.py (get_muted_branches — list muted branches)")
|
||||
console.print(" - medic_state.py (mute_branch — suppress dispatch for a branch)")
|
||||
console.print(" - medic_state.py (unmute_branch — resume dispatch for a branch)")
|
||||
console.print(" - medic_state.py (get_suppression_stats — suppression statistics)")
|
||||
console.print(" - medic_state.py (get_rate_limit_stats — rate limit statistics)")
|
||||
console.print()
|
||||
|
||||
|
||||
def _systemctl(action: str) -> bool:
|
||||
"""Run systemctl --user action on the log watcher service.
|
||||
|
||||
|
||||
@@ -1,16 +1,9 @@
|
||||
|
||||
# ===================AIPASS====================
|
||||
# META DATA HEADER
|
||||
# Name: trigger.py - TRIGGER Branch Entry Point
|
||||
# Date: 2025-11-30
|
||||
# =================== AIPass ====================
|
||||
# Name: trigger.py
|
||||
# Description: Entry point CLI for drone @trigger — event bus and error registry
|
||||
# Version: 1.0.0
|
||||
# Category: trigger
|
||||
#
|
||||
# CHANGELOG (Max 5 entries):
|
||||
# - v1.0.0 (2025-11-30): Initial branch creation
|
||||
#
|
||||
# CODE STANDARDS:
|
||||
# - Handlers implement logic, modules orchestrate
|
||||
# Created: 2026-03-08
|
||||
# Modified: 2026-03-08
|
||||
# =============================================
|
||||
|
||||
"""
|
||||
@@ -70,9 +63,9 @@ def discover_modules() -> List[Any]:
|
||||
# Check if module has handle_command function
|
||||
if hasattr(module, 'handle_command'):
|
||||
modules.append(module)
|
||||
logger.info(f"[TRIGGER] Loaded module: {file_path.stem}")
|
||||
pass # Module loaded successfully
|
||||
else:
|
||||
logger.info(f"[TRIGGER] Skipped {file_path.stem} - no handle_command()")
|
||||
pass # No handle_command() - skip silently
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[TRIGGER] Failed to load module {module_name}: {e}")
|
||||
|
||||
Reference in New Issue
Block a user