python-architect — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited python-architect (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Targets Python 3.14. See STACK.md for pinned dependency versions.
list[str], dict[K, V], X | None). Never the legacy typing.List / typing.Optional.def f(arg: NotYetDefined) works). Inspect via annotationlib.get_annotations(), not __annotations__ directly.typing.NewType to separate distinct concepts (UserId vs OrderId).Literal for string flags; Enum (with __str__) for states.TypedDict over dict[str, Any] for known-shape mappings.typing.override decorator (3.12+) on every overriding method — mypy flags broken overrides.@dataclass(slots=True, frozen=True) for DTOs and value objects.__slots__ (explicit or via dataclass(slots=True)) on high-volume instances.typing.Protocol (structural typing) over deep abc.ABC inheritance. Define protocols where consumed.__init__. Never instantiate external clients inside a class.contextvars only when request-scoped state is unavoidable.asyncio.to_thread().asyncio.TaskGroup for concurrent coroutines — handles cancellation and exception aggregation properly. Avoid bare asyncio.gather.concurrent.interpreters for CPU-bound parallelism — true multi-core without multiprocessing's overhead, no GIL contention.python -m asyncio ps <PID> / pstree <PID> (3.14).with / async with. Use contextlib for compositions.__all__ = [...] to declare the public API explicitly.importlib.resources.files(__package__).joinpath("...").read_text() for embedded files (SQL, templates). Survives wheel and zipapp packaging — never use __file__-relative paths for shipped assets.raise NewError(...) from err). Never bare except:.except TimeoutError, ConnectionRefusedError: is now valid without parens when no as clause.return / break / continue inside finally now emits SyntaxWarning — refactor it out.map(strict=True) (3.14) when consuming parallel iterables, matching zip(strict=True).pytest 9 with conftest.py fixtures. Never the legacy unittest module. pytest-asyncio for async tests.Prefer stdlib when it covers the use case.
pathlib.Path for all paths — never os.path strings. New in 3.14: Path.copy(), Path.move(), Path.copy_into(), Path.move_into() for recursive operations.compression.zstd (3.14) over gzip / bz2 for new payloads — gzip / bz2 / lzma / zlib are now re-exported under compression.*.importlib.resources for shipped files (see §5).contextlib for resource lifecycle composition.dataclasses for data containers (see §2).importlib.resourcesRecommended pattern, not mandatory. Mirrors the Go sqlx + //go:embed philosophy: raw SQL in .sql files, loaded once at module import, executed via psycopg 3. No ORM by default — keeps queries auditable in git and gives editors full SQL syntax highlighting and linting.
from importlib.resources import files
import psycopg
from psycopg.rows import class_row
GET_USER_BY_ID = files(__package__).joinpath("queries/get_user_by_id.sql").read_text()
class UserRepo:
def __init__(self, conn: psycopg.AsyncConnection) -> None:
self._conn = conn
async def get_by_id(self, user_id: int) -> User | None:
async with self._conn.cursor(row_factory=class_row(User)) as cur:
await cur.execute(GET_USER_BY_ID, (user_id,))
return await cur.fetchone()Layout:
src/myapp/userrepo/
├── __init__.py
├── repo.py
└── queries/
├── get_user_by_id.sql
├── insert_user.sql
└── list_users.sqlpsycopg 3 — sync + async, server-side cursors, COPY, prepared statements.alembic — versioned, works with raw SQL (no SQLAlchemy ORM required)..sql fragments in Python; never concatenate user input — bind parameters.uv — replaces pip, pip-tools, virtualenv, pyenv. Single binary, fast.ruff — replaces black, isort, flake8, pyupgrade. One config, one tool. Drop-in template: assets/ruff.toml — copy to your project root as ruff.toml (or fold into pyproject.toml under [tool.ruff]) and set known-first-party to your package name.mypy --strict as the baseline. No Any-by-default escape hatches.pytest 9 + pytest-asyncio for async paths.See STACK.md for the full pinned list — pydantic, pydantic-settings, fastapi, uvicorn, httpx, pytest, pytest-asyncio, mypy, ruff, uv, typer, psycopg, alembic.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.