Root cause: get_module_logs_dir() last fallback unconditionally created
src/aipass/{name}/logs/ for any unknown module name, causing AIPL polyglot
agents (running with AIPASS_HOME set for cross-project access) to dump logs
into src/aipass/unknown_branch/logs/ inside the AIPass source tree.
Fix in apps/handlers/config/load.py:
- Check AIPASS_CALLER_CWD env var (set by drone during cross-project dispatch,
DPLAN-0121) and walk up to caller project root (.git or pyproject.toml)
- Final fallback: system_logs/external/{module_name} — never creates unknown
directories in ECOSYSTEM_ROOT
- Added inspect.stack() auto-detection when module_name is not provided
- Added _warn_routing() helper for lazy prax logger access (avoids circular
import: logger.py imports load.py at module level)
Also in this PR:
- Regression tests: test_unknown_module_routes_to_system_logs_external and
test_aipass_caller_cwd_routes_to_caller_project (38 tests, all green)
- bypass.json: architecture + documentation exemptions for tests/test_config.py
Cleanup (done separately on main): 27 leaked AIPL polyglot logs moved from
src/aipass/unknown_branch/ to /tmp/aipl_leaked_logs/; directory removed.
CC @polyglot: if AIPL sets AIPASS_CALLER_CWD during drone dispatch, logs will
route to ~/Projects/AIPL/ automatically. No AIPL changes required for the base
fix — the system_logs/external/ fallback already prevents pollution.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Root cause: get_module_logs_dir() last fallback unconditionally created
src/aipass/{name}/logs/ for any unknown module, causing external projects
(AIPL polyglot) running with AIPASS_HOME set to pollute the AIPass src tree
with src/aipass/unknown_branch/logs/*.
Fix (already committed in 3c5ac29):
- Check AIPASS_CALLER_CWD env var (set by drone during cross-project dispatch,
DPLAN-0121) and walk up to the caller's project root (.git/pyproject.toml)
- Final fallback: system_logs/external/{module_name} — never create unknown
dirs in the AIPass source tree
- Added inspect.stack() auto-detection when module_name is not provided
- Added _warn_routing() helper for lazy prax logger access (avoids circular
imports — logger.py imports load.py at module level)
This PR:
- Regression tests: test_unknown_module_routes_to_system_logs_external and
test_aipass_caller_cwd_routes_to_caller_project (both green)
- Cleanup: moved 27 leaked AIPL polyglot logs from src/aipass/unknown_branch/
to /tmp/aipl_leaked_logs/ for AIPass Developer review; removed directory
- bypass.json: architecture + documentation exemptions for tests/test_config.py
CC @polyglot: AIPL-side logger config may need AIPASS_CALLER_CWD set during
cross-project dispatch so logs route to ~/Projects/AIPL/ correctly. The fix
is transparent if drone sets AIPASS_CALLER_CWD; no AIPL changes required for
the basic fix, but explicit env var support improves log placement accuracy.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Background processes (trigger Medic, prax watchdog) inherit a restricted PATH
that omits ~/.local/bin, causing FileNotFoundError when wake_branch() tries to
spawn claude (pip-installed at ~/.local/bin/claude).
Fix: add _find_claude_bin() to locate claude via shutil.which() with fallback
to known install paths; use _CLAUDE_BIN constant in both fresh/resume commands;
explicitly prepend ~/.local/bin to spawn_env PATH in both wake.py and
dispatch_monitor.py. Confirmed by logs: 'Failed to spawn @trigger/@flow:
[Errno 2] No such file or directory: claude'.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
BLOCKER 1 (bootstrap.py): Replace bash dirname/while loop in _claude_settings()
with a cross-platform python3 -c one-liner using pathlib.Path.parents. The bash
loop broke on Windows because root is 'C:\' not '/'. Python pathlib handles all
OS path separators correctly.
BLOCKER 2 (setup.sh): Add OS detection (IS_WINDOWS via OSTYPE/uname). On Windows
(Git Bash/MSYS2/Cygwin), skip the sudo ln -sf symlink step and print manual
PATH-extension instructions for PowerShell, CMD, and Git Bash. Also make venv
activation OS-aware (Scripts/activate on Windows, bin/activate elsewhere).
BLOCKER 3 (setup.py): New cross-platform Python installer at repo root. Does
everything setup.sh does — create venv, install editable, verify entry points,
seed secrets dir, .env, registry, bootstrap branch identity files — and works
natively on Windows without Git Bash. Uses sys.executable (no python3 vs python
ambiguity), pathlib throughout, and prints PATH instructions on Windows instead
of attempting symlink creation.
Closes#261.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
TRIGGER_ROOT.parent.parent resolves to src/, not the project root.
Fix to TRIGGER_ROOT.parent.parent.parent so all three SYSTEM_LOGS_DIR
constants resolve to /home/patrick/Projects/AIPass/system_logs.
Fixes recurring 'Failed to start log watcher' on every service start.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>