Skip to content

Commit 38a4441

Browse files
author
JayLin
committed
fix: preserve posix pytest environment
1 parent b28100a commit 38a4441

5 files changed

Lines changed: 19 additions & 4 deletions

File tree

docs/architecture/governed-test-execution.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ The capability has four boundaries:
1717
## Composition
1818

1919
```python
20+
import sys
2021
from pathlib import Path
2122

2223
from mini_code_agent.policy import (
@@ -38,7 +39,7 @@ workspace = WorkspaceBoundary(root)
3839
runner = PytestRunner(
3940
root,
4041
profile=PytestProfile(
41-
python_executable=Path(".venv/Scripts/python.exe").resolve(),
42+
python_executable=Path(sys.executable),
4243
default_targets=("tests",),
4344
trusted_plugins=("pytest_asyncio.plugin",),
4445
),
@@ -63,8 +64,9 @@ executor = GovernedToolExecutor(
6364
)
6465
```
6566

66-
Windows and POSIX environments need different virtual-environment executable paths. The path is
67-
host configuration, never a ToolCall argument.
67+
Use the active environment's `sys.executable` path without resolving symlinks. On POSIX, resolving
68+
`.venv/bin/python` can erase virtual-environment identity and select the base interpreter. The path
69+
is host configuration, never a ToolCall argument.
6870

6971
## Model and Host Control
7072

docs/learning/knowledge-map.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,8 @@
558558
配置,模型不能构造命令。
559559
- `python -I` 隔离用户 site 与 `PYTHON*` 启动影响;
560560
`PYTEST_DISABLE_PLUGIN_AUTOLOAD=1` 禁止环境中的 entry-point 插件自动扩展执行面。
561+
- POSIX 的 `.venv/bin/python` 可能是 symlink;不能对 `sys.executable` 调用
562+
`resolve()`,否则会丢失 venv identity,`-I` 下会落到不含 Pytest 的 base Python。
561563
- `-p no:cacheprovider` 避免 Harness 自己创建 `.pytest_cache`;不代表测试代码只读。
562564
- model target 经 `WorkspaceBoundary` 解析为现存文件/目录,并在 `--` 后传给 Pytest。
563565
- 进程状态和报告状态拆成两个 failure domain:测试 exit code 仍可保留,即使 JUnit

docs/learning/progress.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,8 @@
482482
plugins. Profile models are immutable and validated before execution.
483483
- Fixed argv uses `python -I -m pytest`, disables ambient plugin autoload and Pytest cache writes,
484484
and places `--` before validated targets.
485+
- The host preserves the active `sys.executable` path. Resolving a POSIX venv symlink selects the
486+
base interpreter and loses environment-local Pytest under isolated startup.
485487
- Execute remains denied by default. Interactive `ASK` requires independent approval;
486488
non-interactive `ASK`, rejection, and approval exceptions start no process.
487489
- Pytest exit classification is separate from JUnit report status. A missing or invalid report

src/mini_code_agent/testing/junit.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,15 @@ def parse_junit_report(
116116

117117

118118
def _read_report(path: Path, limit: int) -> bytes:
119+
try:
120+
initial_mode = path.lstat().st_mode
121+
except FileNotFoundError:
122+
raise _report_error(PytestReportErrorCode.MISSING) from None
123+
except OSError:
124+
raise _report_error(PytestReportErrorCode.UNSAFE) from None
125+
if not stat.S_ISREG(initial_mode):
126+
raise _report_error(PytestReportErrorCode.UNSAFE)
127+
119128
flags = os.O_RDONLY | getattr(os, "O_BINARY", 0) | getattr(os, "O_NOFOLLOW", 0)
120129
try:
121130
descriptor = os.open(path, flags)

tests/integration/test_governed_pytest_agent.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ def executor_for(
100100
runner = PytestRunner(
101101
root,
102102
profile=PytestProfile(
103-
python_executable=Path(sys.executable).resolve(),
103+
python_executable=Path(sys.executable),
104104
timeout_seconds=30,
105105
max_failures=5,
106106
),

0 commit comments

Comments
 (0)