From efc0056be8a4e54068bbb9902a809f582014bb72 Mon Sep 17 00:00:00 2001 From: AIOSAI Date: Tue, 14 Apr 2026 13:28:06 -0700 Subject: [PATCH] =?UTF-8?q?fix(prax):=20AIPL=20polyglot=20log=20leak=20?= =?UTF-8?q?=E2=80=94=20path=20resolver=20fix=20+=20regression=20tests=20(D?= =?UTF-8?q?PLAN-0125=20Track=20G)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- src/aipass/prax/.seedgo/bypass.json | 12 ++++++++++- src/aipass/prax/tests/test_config.py | 30 +++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/aipass/prax/.seedgo/bypass.json b/src/aipass/prax/.seedgo/bypass.json index 46ade39f..5c986be2 100644 --- a/src/aipass/prax/.seedgo/bypass.json +++ b/src/aipass/prax/.seedgo/bypass.json @@ -3,9 +3,19 @@ "version": "2.0.0", "created": "2026-03-07T22:43:24.315842", "description": "Standards bypass configuration for prax branch", - "last_updated": "2026-03-24" + "last_updated": "2026-04-14" }, "bypass": [ + { + "file": "tests/test_config.py", + "standard": "documentation", + "reason": "Test functions follow pytest naming conventions (test_*). Docstrings on test functions are non-standard in this codebase — only new tests added in DPLAN-0125 Track G have them. Pre-existing 36 functions comply with project test style." + }, + { + "file": "tests/test_config.py", + "standard": "architecture", + "reason": "Test files live in tests/ by convention, not in the 3-layer apps/ structure. This is a false positive for the test directory." + }, { "file": "apps/modules/logger.py", "standard": "cli", diff --git a/src/aipass/prax/tests/test_config.py b/src/aipass/prax/tests/test_config.py index 4ae48b1d..e1aec7f8 100644 --- a/src/aipass/prax/tests/test_config.py +++ b/src/aipass/prax/tests/test_config.py @@ -149,12 +149,36 @@ class TestGetModuleLogsDir: assert result.name == "logs" assert result.exists() - def test_creates_logs_dir_for_new_branch(self, mock_prax_infrastructure, monkeypatch, tmp_path): + def test_unknown_module_routes_to_system_logs_external(self, mock_prax_infrastructure, monkeypatch, tmp_path): + """Unknown modules must NOT create dirs in ECOSYSTEM_ROOT (log-leak regression).""" load_mod = _fresh_import_load(monkeypatch, tmp_path) - result = load_mod.get_module_logs_dir("newbranch") + monkeypatch.setattr(load_mod, "_find_repo_root", lambda: tmp_path) + monkeypatch.delenv("AIPASS_CALLER_CWD", raising=False) + result = load_mod.get_module_logs_dir("unknown_branch") + # Must route to system_logs/external/, NOT create src/aipass/unknown_branch/ + assert result == tmp_path / "system_logs" / "external" / "unknown_branch" assert result.exists() assert result.is_dir() - assert result.name == "logs" + # Verify ECOSYSTEM_ROOT is not polluted + assert not (tmp_path / "unknown_branch").exists() + + def test_aipass_caller_cwd_routes_to_caller_project(self, mock_prax_infrastructure, monkeypatch, tmp_path): + """Regression: AIPASS_CALLER_CWD directs logs to caller project root, not ECOSYSTEM_ROOT.""" + load_mod = _fresh_import_load(monkeypatch, tmp_path) + monkeypatch.setattr(load_mod, "_find_repo_root", lambda: tmp_path) + # Set up a mock caller project with a .git marker + caller_project = tmp_path / "caller_project" + caller_project.mkdir() + (caller_project / ".git").mkdir() + caller_cwd = str(caller_project / "src" / "polyglot") + monkeypatch.setenv("AIPASS_CALLER_CWD", caller_cwd) + result = load_mod.get_module_logs_dir("polyglot") + # Must resolve to caller project's logs/, not ECOSYSTEM_ROOT + assert result == caller_project / "logs" / "polyglot" + assert result.exists() + assert result.is_dir() + # ECOSYSTEM_ROOT must not be polluted + assert not (tmp_path / "polyglot").exists() # =============================================