fix(ci): seedgo gate back to 100% — hooks handler logging + silent catches, memory governance modules/handlers split (import path frozen, bridge E2E green), devpulse README test count. All 17 branches 100%

This commit is contained in:
AIOSAI
2026-07-16 22:44:01 -07:00
parent e412cfed14
commit a89ddb30bd
8 changed files with 169 additions and 148 deletions
+9
View File
@@ -73,6 +73,15 @@ PyPI version — not the changelog header.
### Fixed
- **CI seedgo gate back to 100% across all 17 branches.** The Track 2 compass
recall code left three branches at 99%: @hooks' compass_recall handler was
missing json_handler operation logging and had two silent catches (now
logged); @memory's governance module held its implementation in modules/
(moved to handlers/governance/engine.py with modules/governance.py as the
thin re-export — the cross-branch import path is unchanged and live-E2E
verified through the real bridge); devpulse's README test count had drifted
(309 → 348). Audits re-run per branch: 100% overall, all suites green.
- **Plan-number memory search hits the exact plan.** Searching a plan ID
('DPLAN-0244', 'fplan 0332' — any case, dash or space) now pins the exact
plan as the top result at 100%, via a metadata lookup on the vector store's
+1 -1
View File
@@ -44,7 +44,7 @@ src/aipass/devpulse/
│ │ └── watchdog/ # Agent, timer, schedule, registry
│ └── plugins/ # Plugin extension point
├── devpulse_json/ # JSON handler storage (config, data, logs per module)
├── tests/ # 309 tests
├── tests/ # 348 tests
├── artifacts/ # Birth certificate, reports
├── dropbox/ # Received files, archived plans, install audit
├── docs/ # Transition notes
@@ -17,6 +17,7 @@ import tempfile
from pathlib import Path
from aipass.prax.apps.modules.logger import system_logger as logger
from aipass.hooks.apps.handlers.json import json_handler
_STATE_DIR = Path(tempfile.gettempdir())
@@ -38,7 +39,8 @@ def _load_state(hook_data: dict | None = None) -> dict:
return _fresh_state()
try:
return json.loads(path.read_text(encoding="utf-8"))
except (json.JSONDecodeError, OSError):
except (json.JSONDecodeError, OSError) as exc:
logger.info("[HOOKS] compass_recall: state read failed: %s", exc)
return _fresh_state()
@@ -47,7 +49,8 @@ def _fresh_state() -> dict:
from aipass.memory.apps.modules.governance import new_state
return new_state()
except Exception:
except Exception as exc:
logger.info("[HOOKS] compass_recall: governance import failed: %s", exc)
return {"surfaces_count": 0, "messages_since_last": 0, "last_surface_time": 0.0, "surfaced_ids": []}
@@ -105,6 +108,7 @@ def handle(hook_data: dict) -> dict:
lines.append(f"[{rating}] #{c['id']}: {c['decision']}")
mark_surfaced([c["id"] for c in approved])
json_handler.log_operation("compass_recall", {"count": len(approved)})
return {"stdout": "\n".join(lines), "exit_code": 0}
+10
View File
@@ -462,6 +462,16 @@
"functions": ["render_all_meta_tabs"],
"reason": "Cross-branch public API — called by @spawn's build_replacements_dict to resolve {{*_META}} placeholders at branch creation."
},
{
"file": "apps/modules/governance.py",
"standard": "unused_function",
"reason": "Cross-branch public API — should_surface, record_message, new_state re-exported for @hooks compass_recall and @devpulse recall query."
},
{
"file": "apps/handlers/governance/engine.py",
"standard": "unused_function",
"reason": "Implementation functions re-exported via modules/governance.py for cross-branch consumers."
},
{
"file": "apps/modules/templates.py",
"standard": "deep_nesting",
+4 -2
View File
@@ -45,15 +45,17 @@ drone @memory watch # Auto-rollover watcher daemon (Ctrl+
memory/
├── apps/
│ ├── memory.py # Entry point — auto-discovers modules
│ ├── modules/ # 6 modules
│ ├── modules/ # 7 modules
│ │ ├── governance.py # Surfacing governance — re-exports from handlers
│ │ ├── lint.py # Entry limit violation scanner (read-only)
│ │ ├── rollover.py # Rollover orchestration, status, sync-lines
│ │ ├── search.py # Semantic query routing
│ │ ├── symbolic.py # Fragmented memory extraction and search
│ │ ├── templates.py # Template push, diff, status
│ │ └── verify.py # Plan vectorization check
│ └── handlers/ # 14 handler groups
│ └── handlers/ # 15 handler groups
│ ├── archive/ # indexer.py
│ ├── governance/ # engine.py — surfacing decision logic
│ ├── intake/ # plans_processor.py, pool_processor.py
│ ├── json/ # json_handler.py, memory_files.py, entry_limits.py, lint_handler.py, config_loader.py
│ ├── learnings/ # manager.py
@@ -0,0 +1,125 @@
# =================== AIPass ====================
# Name: engine.py
# Description: Surfacing governance engine — implementation
# Version: 1.0.0
# Created: 2026-07-16
# Modified: 2026-07-16
# =============================================
"""
Surfacing Governance Engine
Pure decision functions for controlling when recalled items should be
surfaced. Implementation logic — public API re-exported from
modules/governance.py for cross-branch consumers.
"""
from typing import Any, Dict, Tuple
from aipass.prax import logger
from aipass.memory.apps.handlers.json import json_handler
# =============================================================================
# CONSTANTS — default config values
# =============================================================================
DEFAULT_CONFIG: Dict[str, Any] = {
"enabled": True,
"threshold": 0.3,
"max_surfaces_per_session": 5,
"min_messages_between": 10,
"cooldown_seconds": 300,
}
# =============================================================================
# STATE FACTORY
# =============================================================================
def new_state() -> Dict[str, Any]:
"""Create a fresh governance state dict."""
return {
"surfaces_count": 0,
"messages_since_last": 0,
"last_surface_time": 0.0,
"surfaced_ids": [],
}
# =============================================================================
# CORE GOVERNANCE
# =============================================================================
def should_surface(
item_id: str,
relevance_score: float,
state: Dict[str, Any],
config: Dict[str, Any] | None = None,
*,
current_time: float | None = None,
) -> Tuple[bool, str, Dict[str, Any]]:
"""
Decide whether an item should be surfaced, given current state.
Pure function — does not mutate the input state dict.
"""
import time
cfg = {**DEFAULT_CONFIG, **(config or {})}
now = current_time if current_time is not None else time.time()
if not cfg.get("enabled", True):
return False, "Surfacing disabled", state
threshold = cfg.get("threshold", 0.3)
if relevance_score < threshold:
return False, f"Below threshold ({relevance_score:.2f} < {threshold})", state
max_surfaces = cfg.get("max_surfaces_per_session", 5)
if state.get("surfaces_count", 0) >= max_surfaces:
return False, f"Session budget exhausted ({max_surfaces}/{max_surfaces})", state
min_messages = cfg.get("min_messages_between", 10)
messages_since = state.get("messages_since_last", 0)
last_time = state.get("last_surface_time", 0.0)
if last_time > 0 and messages_since < min_messages:
return False, f"Spacing not met ({messages_since}/{min_messages} messages)", state
cooldown = cfg.get("cooldown_seconds", 300)
elapsed = now - last_time
if last_time > 0 and elapsed < cooldown:
remaining = int(cooldown - elapsed)
return False, f"Cooldown active ({remaining}s remaining)", state
surfaced_ids = state.get("surfaced_ids", [])
if item_id in surfaced_ids:
return False, "Already surfaced this session", state
updated = {
"surfaces_count": state.get("surfaces_count", 0) + 1,
"messages_since_last": 0,
"last_surface_time": now,
"surfaced_ids": list(surfaced_ids) + [item_id],
}
logger.info(f"[governance] Surfacing {item_id} (score={relevance_score:.2f}, surfaces={updated['surfaces_count']})")
json_handler.log_operation(
"governance_surface",
{"item_id": item_id, "relevance_score": relevance_score, "surfaces_count": updated["surfaces_count"]},
)
return True, "Ready to surface", updated
# =============================================================================
# MESSAGE TRACKING
# =============================================================================
def record_message(state: Dict[str, Any]) -> Dict[str, Any]:
"""Record that a message was processed. Pure — returns updated state."""
return {
**state,
"messages_since_last": state.get("messages_since_last", 0) + 1,
}
+14 -143
View File
@@ -1,7 +1,7 @@
# =================== AIPass ====================
# Name: governance.py
# Description: Surfacing governance module — public API
# Version: 1.0.0
# Version: 1.1.0
# Created: 2026-07-16
# Modified: 2026-07-16
# =============================================
@@ -9,24 +9,14 @@
"""
Surfacing Governance Module — Public API
Pure decision functions for controlling when recalled items (compass
rulings, plans, fragments) should be surfaced to the user. Retrieval-
backend-agnostic: works with any store that produces an item_id and
a relevance_score.
Thin module re-exporting governance engine from handlers/governance/engine.py.
Cross-branch consumers import from here:
All functions are PURE — state dict in, decision + updated state out.
The caller owns persistence (file, JSONL, in-memory).
Public API:
should_surface(item_id, relevance_score, state, config)
-> (bool, reason, updated_state)
record_message(state) -> updated_state
new_state() -> state dict
from aipass.memory.apps.modules.governance import should_surface, record_message, new_state
"""
import os
import sys
from typing import Any, Dict, Tuple
if sys.platform == "win32":
os.environ.setdefault("PYTHONUTF8", "1")
@@ -35,137 +25,16 @@ if sys.platform == "win32":
if _reconfigure is not None:
_reconfigure(encoding="utf-8", errors="replace")
from aipass.prax import logger # noqa: F401
from aipass.memory.apps.handlers.json import json_handler
from aipass.memory.apps.handlers.governance.engine import (
DEFAULT_CONFIG,
new_state,
record_message,
should_surface,
)
# =============================================================================
# CONSTANTS — default config values
# =============================================================================
DEFAULT_CONFIG: Dict[str, Any] = {
"enabled": True,
"threshold": 0.3,
"max_surfaces_per_session": 5,
"min_messages_between": 10,
"cooldown_seconds": 300,
}
# =============================================================================
# STATE FACTORY
# =============================================================================
def new_state() -> Dict[str, Any]:
"""
Create a fresh governance state dict.
Returns:
State dict with zeroed counters and empty surfaced set.
"""
return {
"surfaces_count": 0,
"messages_since_last": 0,
"last_surface_time": 0.0,
"surfaced_ids": [],
}
# =============================================================================
# CORE GOVERNANCE
# =============================================================================
def should_surface(
item_id: str,
relevance_score: float,
state: Dict[str, Any],
config: Dict[str, Any] | None = None,
*,
current_time: float | None = None,
) -> Tuple[bool, str, Dict[str, Any]]:
"""
Decide whether an item should be surfaced, given current state.
Pure function — does not mutate the input state dict. Returns an
updated copy reflecting the decision (surfaced id recorded, counters
bumped) only when the answer is True; otherwise returns state unchanged.
Args:
item_id: Unique identifier of the item to surface.
relevance_score: Float score from the retrieval backend (0-1).
state: Current governance state (from new_state() or prior call).
config: Override config; merged with DEFAULT_CONFIG for missing keys.
current_time: Epoch seconds for cooldown check. Injected for testability;
falls back to time.time() in production.
Returns:
(should_surface, reason, updated_state)
"""
import time
cfg = {**DEFAULT_CONFIG, **(config or {})}
now = current_time if current_time is not None else time.time()
if not cfg.get("enabled", True):
return False, "Surfacing disabled", state
threshold = cfg.get("threshold", 0.3)
if relevance_score < threshold:
return False, f"Below threshold ({relevance_score:.2f} < {threshold})", state
max_surfaces = cfg.get("max_surfaces_per_session", 5)
if state.get("surfaces_count", 0) >= max_surfaces:
return False, f"Session budget exhausted ({max_surfaces}/{max_surfaces})", state
min_messages = cfg.get("min_messages_between", 10)
messages_since = state.get("messages_since_last", 0)
last_time = state.get("last_surface_time", 0.0)
if last_time > 0 and messages_since < min_messages:
return False, f"Spacing not met ({messages_since}/{min_messages} messages)", state
cooldown = cfg.get("cooldown_seconds", 300)
elapsed = now - last_time
if last_time > 0 and elapsed < cooldown:
remaining = int(cooldown - elapsed)
return False, f"Cooldown active ({remaining}s remaining)", state
surfaced_ids = state.get("surfaced_ids", [])
if item_id in surfaced_ids:
return False, "Already surfaced this session", state
updated = {
"surfaces_count": state.get("surfaces_count", 0) + 1,
"messages_since_last": 0,
"last_surface_time": now,
"surfaced_ids": list(surfaced_ids) + [item_id],
}
json_handler.log_operation(
"governance_surface",
{"item_id": item_id, "relevance_score": relevance_score, "surfaces_count": updated["surfaces_count"]},
)
return True, "Ready to surface", updated
# =============================================================================
# MESSAGE TRACKING
# =============================================================================
def record_message(state: Dict[str, Any]) -> Dict[str, Any]:
"""
Record that a message was processed. Pure — returns updated state.
Args:
state: Current governance state.
Returns:
New state dict with messages_since_last incremented.
"""
return {
**state,
"messages_since_last": state.get("messages_since_last", 0) + 1,
}
__all__ = ["should_surface", "record_message", "new_state", "DEFAULT_CONFIG"]
# =============================================================================
@@ -194,6 +63,8 @@ def handle_command(command: str, args: list) -> bool:
if command != "governance":
return False
json_handler.log_operation("governance_command", {"args": args})
if not args:
print_introspection()
return True