From c94e231e8467ef28e529ea3176ea96334e3dbb42 Mon Sep 17 00:00:00 2001 From: patrick Date: Sun, 3 May 2026 21:51:27 -0700 Subject: [PATCH] feat(system): ai_mail vectorization: sys.executable fallback when memory venv missing + mechanical-guardrails prompt docs Co-Authored-By: @devpulse --- .aipass/aipass_global_prompt.md | 9 +++++---- src/aipass/ai_mail/apps/handlers/email/purge.py | 16 +++++++++++++++- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/.aipass/aipass_global_prompt.md b/.aipass/aipass_global_prompt.md index e6f21256..777ec850 100644 --- a/.aipass/aipass_global_prompt.md +++ b/.aipass/aipass_global_prompt.md @@ -79,10 +79,11 @@ Allowed: - `drone @git fix` — repair broken git states (devpulse only) - `git status`, `git diff`, `git log` — read-only, always fine -Forbidden (denied system-wide in `.claude/settings.json`): - - `git checkout*` — any form, including `-b`, `-`, branch names - - `git add -f*` / `--force*` - - Culturally avoid `git commit`, `git push`, `gh pr create` directly — go through drone +Mechanically blocked by the `git_gate.py` PreToolUse hook (applies to ALL sessions including dispatched agents — bypassPermissions does not skip hooks): + - All raw `git` write verbs: `commit`, `push`, `pull`, `merge`, `rebase`, `reset`, `checkout`, `switch`, `branch`, `cherry-pick`, `revert`, `rm`, `mv`, `restore`, `clean`, `config`, `tag`, `stash drop|clear|pop|apply` + - All raw `gh` write subcommands (`pr`, `issue`, `repo`, `release`, `workflow`, `run`, `cache`, `secret`, `variable`, `gist`) and any `gh api` call + - Edits to `**/.claude/settings*.json`, `**/.claude/hooks/**`, `**/.git/hooks/**` (the enforcement layer itself) + - Use `drone @git pr "msg"` instead. Drone calls git via Python subprocess so its operations don't pass through this hook. If `drone @git system-pr` fails to return HEAD to main, that's a drone bug — report it, don't work around it by staying on a branch. diff --git a/src/aipass/ai_mail/apps/handlers/email/purge.py b/src/aipass/ai_mail/apps/handlers/email/purge.py index f6319a4e..8b1804c8 100644 --- a/src/aipass/ai_mail/apps/handlers/email/purge.py +++ b/src/aipass/ai_mail/apps/handlers/email/purge.py @@ -20,6 +20,8 @@ v2.0.0: deleted/ now uses directory structure (like sent/). """ import json +import os +import sys import subprocess from pathlib import Path from datetime import datetime @@ -35,12 +37,24 @@ MAX_EMAILS = 10 # Memory branch paths for subprocess vectorization (optional external service) # These are resolved relative to repo root if available; vectorization is best-effort _REPO_ROOT = find_repo_root() -MEMORY_PYTHON = _REPO_ROOT / "src" / "aipass" / "memory" / ".venv" / "bin" / "python3" +_MEMORY_VENV_PYTHON = _REPO_ROOT / "src" / "aipass" / "memory" / ".venv" / "bin" / "python3" CHROMA_SUBPROCESS_SCRIPT = ( _REPO_ROOT / "src" / "aipass" / "memory" / "apps" / "handlers" / "storage" / "chroma_subprocess.py" ) +def _get_memory_python() -> str: + env = os.environ.get("AIPASS_MEMORY_PYTHON") + if env: + return env + if _MEMORY_VENV_PYTHON.exists(): + return str(_MEMORY_VENV_PYTHON) + return sys.executable + + +MEMORY_PYTHON = _get_memory_python() + + def purge_sent_folder(mailbox_path: Path) -> Dict[str, Any]: """ Purge sent folder if count exceeds threshold.