dc00a4f8f5
Wave 5-1 mypy adoption (D-058 relaxed-first): mypy 2.3.1, [tool.mypy] check_untyped_defs + no_implicit_optional + warn_unused_ignores + warn_redundant_casts + warn_unreachable, no overrides (every dep ships py.typed), files = ai_service + scripts/sandbox-agent.py + tests (not excluded). 215 errors → 0: ~140 fixed at source incl. genuine bugs found by the gate (LLMProvider protocol async-generator shape, SessionStore protocol sync/async mismatch, structured_reply genericity, get_args migrations, sandbox-agent Optional guard honesty, proctor test arg-order, dead ExecResult kwarg, 16 sqlmodel col() sites); 34 live suppressions scoped-coded + reasoned. Original 27 type:ignore dispositioned: 12 dead removed, 15 scoped (warn_unused_ignores self-eliminates the rest). Wired: scripts/typecheck.sh + package.json + turbo task + root ai:typecheck — pnpm typecheck now 5 tsc + mypy. Wave 5-2 recharts 2.15.4 → 3.10.1 (D-049/D-059): one breaking class (Tooltip formatter ValueType typing); 2 one-line inference fixes on the 2 chart files; no rollback needed (well inside the G-106 timebox). Deprecated direct dep resolved; uuid@9 gone from the tree. Build 248/248 with chart SSR markers verified in exported employer + dashboard pages. Wave 5-3 deprecated-transitive audit (G-109): 4 lockfile entries remain, all dev-only, none actionable within NFR budget — glob@7.2.3 + inflight + rimraf@3 via Storybook docgen chain (flat-cache@3); glob@10.5.0 via c8→test-exclude (D-052-binding coverage tool — swapping it is out of budget). Python: no EOL packages; zero-warning regime under filterwarnings=error is the machine-checked proof. Counts: 670 py / 44 web / 64 cli, zero warnings, G-104 allowlist still exactly 2. ---ci--- phase: 5 milestone: v0.7 status: execute ---/ci---
53 lines
2.4 KiB
Python
53 lines
2.4 KiB
Python
"""Sandbox-suite conftest: session-end droppings sweep (P2 Task 2-1-03, G-110).
|
|
|
|
Why the repo-anchored root exists at all (fabric constraint, NOT an oversight):
|
|
|
|
The userns suites anchor per-test sandbox roots IN-REPO at ``tests/sandboxes/``
|
|
(``test_isolation.py`` / ``test_resource_limits.py`` via their ``sandbox_dir``
|
|
fixtures, ``test_manager.py``'s real-backend smoke, and
|
|
``api/test_sandboxes.py``'s ``REAL_SANDBOXES_ROOT``). They must NOT use
|
|
pytest's ``tmp_path`` (a /tmp subtree): the unshare shim tmpfs-mounts /tmp
|
|
inside every namespace (unshare_backend.py: ``mount -t tmpfs tmpfs /tmp``),
|
|
which shadows any host /tmp subtree — a workspace rooted there is invisible
|
|
in-namespace and every bind-mount guarantee fails (G-110).
|
|
|
|
Those suites' ``sandbox_dir`` fixtures return a ``Settings`` object and
|
|
deliberately do NOT tear the workdir down (several tests assert post-destroy
|
|
survival of workdirs/snapshots), so droppings accumulate under the anchored
|
|
root run after run. This session fixture sweeps the root ONCE, after the
|
|
last test of the session ends.
|
|
|
|
Safety (G-110): the sweep removes the exact test-created root
|
|
``<tests>/sandboxes`` and nothing else — it can never touch a user's real
|
|
sandboxes (production roots are ``~/.nextcraft/sandboxes`` per ``Settings``,
|
|
outside the repo and never swept here). The app-dir default root
|
|
(``ai_service/sandboxes`` — see the sweep in ``tests/conftest.py``, which owns
|
|
the session for suites outside ``tests/sandbox/``) is handled there.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import shutil
|
|
from collections.abc import Iterator
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
#: The repo-anchored test sandbox root every userns suite anchors to — the
|
|
#: same expression the suites use (``Path(__file__).resolve().parents[1] /
|
|
#: "sandboxes"`` from tests/sandbox/* resolves here).
|
|
_SANDBOX_DROPPINGS_ROOT = Path(__file__).resolve().parents[1] / "sandboxes"
|
|
|
|
|
|
@pytest.fixture(autouse=True, scope="session")
|
|
def _sweep_repo_sandbox_droppings() -> Iterator[None]:
|
|
"""After the session's last test, remove the anchored sandbox root.
|
|
|
|
``rmtree(ignore_errors=True)``: the whole ``tests/sandboxes/`` tree is
|
|
test-created runtime state (untracked + gitignored via
|
|
``apps/ai-service/**/sandboxes/``) — best-effort removal is enough, and a
|
|
lingering namespace mount must never fail the run's exit path.
|
|
"""
|
|
yield
|
|
shutil.rmtree(_SANDBOX_DROPPINGS_ROOT, ignore_errors=True)
|