Skip to content

fix(test,agents): WinError 448 pytest symlink fix + AGENTS.md BOM-safe PS rule (#281, #283)#287

Merged
MScottAdams merged 1 commit intomasterfrom
agent4/fix/281-283-pyproject-agents-fixes
Apr 10, 2026
Merged

fix(test,agents): WinError 448 pytest symlink fix + AGENTS.md BOM-safe PS rule (#281, #283)#287
MScottAdams merged 1 commit intomasterfrom
agent4/fix/281-283-pyproject-agents-fixes

Conversation

@MScottAdams
Copy link
Copy Markdown
Collaborator

Summary

Two Phase 1 fixes: pytest WinError 448 symlink cleanup (#281) and AGENTS.md BOM-safe PowerShell write rule (#283).

Changes

fix(test): WinError 448 pytest-current symlink cleanup (#281, t1.18.1)

  • Added mp_path_retention_count = 0 to [tool.pytest.ini_options] in pyproject.toml -- prevents old-session temp dir retention
  • Added module-level monkeypatch in ests/conftest.py wrapping cleanup_dead_symlinks and cleanup_numbered_dir in _pytest.pathlib and _pytest.tmpdir to suppress OSError during session-finish and atexit cleanup
  • Root cause: pytest creates *current directory symlinks; Windows 11 24H2+ security policy flags them as untrusted mount points (WinError 448)

fix(agents): BOM-safe PowerShell file write rule (#283, t1.20.1)

  • Added ## PowerShell section to AGENTS.md with ! rule: use New-Object System.Text.UTF8Encoding False -- never [System.Text.Encoding]::UTF8 (writes BOM)
  • Cross-references scm/github.md PS 5.1 section for full encoding guidance

Checklist

  • SPECIFICATION.md has task coverage (t1.18.1, t1.20.1)
  • CHANGELOG.md entries under [Unreleased]
  • ask check passes (985 passed, 19 xfailed)
  • Feature branch (not master)

Closes #281, Closes #283

Comment thread tests/conftest.py
def _make_safe(fn): # type: ignore[no-untyped-def] # noqa: ANN001
"""Wrap a pytest cleanup function to swallow OSError (WinError 448)."""

def _safe_wrapper(*args, **kwargs): # type: ignore[no-untyped-def]
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 10, 2026

Greptile Summary

This PR delivers two Phase 1 fixes: a Windows 11 24H2+ pytest WinError 448 workaround (via tmp_path_retention_count = 0 in pyproject.toml and a module-level OSError-suppressing monkey-patch in tests/conftest.py), and a BOM-safe PowerShell write rule added to AGENTS.md. Both changes are narrow, well-documented, and accompanied by correct CHANGELOG entries.

Confidence Score: 5/5

Safe to merge; all findings are P2 style/hardening suggestions with no blocking correctness issues.

Both changes are minimal and well-contained. The OSError catch being broader than WinError 448 is a hardening suggestion (P2) — in practice these pytest-internal cleanup functions are only called in teardown contexts where suppressing unexpected OS errors is low risk. The AGENTS.md syntax inconsistency is cosmetic. No P0/P1 findings.

tests/conftest.py — OSError filter could be narrowed to winerror 448 specifically.

Important Files Changed

Filename Overview
tests/conftest.py Adds Windows-only module-level monkey-patch to suppress OSError on pytest symlink cleanup; catch is broader than the targeted WinError 448, silently hiding other OS errors.
AGENTS.md Adds ## PowerShell BOM-safe write rule; prescribed syntax (New-Object) differs slightly from the example form in the cross-referenced scm/github.md.
pyproject.toml Adds tmp_path_retention_count = 0 to pytest ini options with a clear comment; correct option name and value for pytest >= 7.3.
CHANGELOG.md Entries for both fixes added under [Unreleased] with correct task IDs and issue references; format matches established conventions.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[pytest session starts] --> B[conftest.py loaded]
    B --> C{sys.platform == win32?}
    C -- No --> D[Normal cleanup functions]
    C -- Yes --> E[Wrap cleanup_dead_symlinks\nand cleanup_numbered_dir\nwith _make_safe]
    E --> F[tmp_path_retention_count=0\npyproject.toml]
    F --> G[No old-session dirs retained]
    D & G --> H[Tests run]
    H --> I[Session finish / atexit]
    I --> J[Cleanup called]
    J --> K{OSError raised?}
    K -- No --> L[Clean exit]
    K -- Yes, win32 --> M[Swallow OSError\nlog nothing]
    M --> L
Loading
Prompt To Fix All With AI
This is a comment left during a code review.
Path: tests/conftest.py
Line: 30-35

Comment:
**Overly broad OSError catch; docstring overpromises specificity**

The wrapper catches _all_ `OSError`, but the PR targets only `WinError 448`. Any unrelated cleanup failure (e.g., disk full, permission denied for a real reason) will now be silently swallowed on every call to `cleanup_dead_symlinks` / `cleanup_numbered_dir`, and the docstring says "WinError 448" when the code is wider than that.

Narrow the filter to the specific winerror value so genuine failures surface:

```suggestion
        try:
            return fn(*args, **kwargs)
        except OSError as exc:
            if not (hasattr(exc, "winerror") and exc.winerror == 448):
                raise
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: AGENTS.md
Line: 96

Comment:
**Syntax inconsistency with `scm/github.md` reference**

AGENTS.md prescribes `New-Object System.Text.UTF8Encoding $false`, but every code example in the cross-referenced `scm/github.md` section uses `[System.Text.UTF8Encoding]::new($false)`. Both forms construct the same object, but an agent reading both files sees two different spellings for the canonical pattern, which can introduce variation in generated scripts. Aligning the snippet in AGENTS.md to the scm/github.md form removes the ambiguity.

```suggestion
! When writing files using PowerShell, MUST use `[System.Text.UTF8Encoding]::new($false)` -- never `[System.Text.Encoding]::UTF8` (writes BOM). See `scm/github.md` PS 5.1 section.
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (2): Last reviewed commit: "fix(test,agents): WinError 448 pytest sy..." | Re-trigger Greptile

… rule (#281, #283)

- Add tmp_path_retention_count = 0 to [tool.pytest.ini_options] in pyproject.toml
  to prevent old-session temp dir retention on Windows 11 24H2+ (#281, t1.18.1)
- Add conftest.py monkeypatch wrapping cleanup_dead_symlinks and
  cleanup_numbered_dir in _pytest.pathlib/_pytest.tmpdir to suppress OSError
  during session-finish and atexit cleanup (WinError 448 untrusted mount point)
- Add ## PowerShell section to AGENTS.md with ! rule requiring
  New-Object System.Text.UTF8Encoding False for file writes -- never
  [System.Text.Encoding]::UTF8 which writes a BOM (#283, t1.20.1)
- Add CHANGELOG.md entries under [Unreleased] for both fixes
@MScottAdams MScottAdams force-pushed the agent4/fix/281-283-pyproject-agents-fixes branch from ae3b8b3 to 4ff24f7 Compare April 10, 2026 17:20
@MScottAdams
Copy link
Copy Markdown
Collaborator Author

Rebase-only force-push onto updated master (PRs #284, #285, #286 merged). No logic changes -- rebased to resolve CHANGELOG.md insertion-point conflicts.

@MScottAdams MScottAdams merged commit 1b7b572 into master Apr 10, 2026
9 checks passed
@MScottAdams MScottAdams deleted the agent4/fix/281-283-pyproject-agents-fixes branch April 10, 2026 17:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant