Python project standard
Skill VoldemortGin/AI-Coding-Skill-Bible/python-project-standard
Project-standard skills for AI coding agents — engineering charters (Rust / Swift / Python / TypeScript / Kotlin + polyglot core) that make agent output trustworthy by construction.
npx -y skills add VoldemortGin/AI-Coding-Skill-Bible --skill python-project-standardAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Enforce a strict, type-safe, model-agnostic, AI-navigable Python project standard: mypy --strict + beartype runtime type-checking + pydantic at boundaries + provider Protocol seams (zero-SDK core) + src layout with a real package name + domain-first deep structure + centralized config/logging/prompts + a one-command zero-warning gate + drift guards. Use this whenever starting or scaffolding a new Python project, service, or package; setting up pyproject/ruff/mypy/pytest; deciding where code, config, or prompts belong; adding type checking, runtime validation, or an LLM/embedding/vector-store dependency; organizing or deepening package structure; wiring providers; setting up CI or pre-commit; or checking that an existing Python project conforms. Apply it even when the user only says "start a Python project", "set up the repo", "add types", "wire up an LLM", or "structure this", without naming the standard.
SKILL.md
10.0 KB, as published. Nobody here has run it
Python Project Standard
This skill is the guiding standard for any Python work. Apply it by default; don't wait to be asked.
Its spine: trust is placed not in the model, but in the machine-checkable code that constrains it. Dynamic Python's signal is too weak — code runs while doing the wrong thing. Tighten the scaffold instead: static types (mypy), runtime types (beartype), behavior (tests), a name-navigable layout, model-agnostic seams, and failing artifacts that mechanize the implicit knowledge a human would otherwise hold in their head. The agent's output ceiling equals the tightness of that feedback loop.
Baseline: Python 3.13, mypy --strict, ruff, beartype, pydantic v2 + pydantic-settings, Jinja2, Hypothesis. Modern idioms only (no from __future__ import annotations — it stringifies all annotations and fights beartype's runtime resolution; quote forward/self references as needed; no typing.List, prefer PEP 695 type/class Box[T]).
When starting a new project
python scripts/scaffold.py <package_name> --target <dir> --domains ingestion retrieval generation agents
This mirrors assets/templates/ into a conforming project (src layout, core/, ports/+adapters/, prompts, CLAUDE.md, ADR, ci.sh, drift check, smoke/conformance tests) and substitutes __PACKAGE_NAME__. When adapting an existing repo, copy from assets/templates/ by hand — the Python templates use relative imports and __name__, so only pyproject.toml carries the literal name.
Then: uv sync once (editable install), and ./ci.sh (or make check) to verify.
When working on existing code
Apply the rules below, keep new code strict, and verify structural invariants:
python scripts/check_conformance.py <project_root>
It checks the mechanically enforceable invariants (src layout, real package name, claw hook present, core/__init__.py empty, settings.py is a leaf, no vendor SDK imported outside adapters/, mypy strict). Everything else is enforced by the gate and by applying the standard.
The non-negotiables
Full rationale in references/standard.md.
-
Static: mypy
--strict, no bareAny. Annotate every parameter and return; parameterize generics; PEP 695typealiases;# type: ignoreneeds a code, a reason, and is tracked debt. -
Runtime: beartype via a central switch + claw hook — never hand-applied
@beartype, never commented out. Switch issettings.beartype_on(default on; only production setsAPP_BEARTYPE_ON=false). Hook at the very top of the package__init__.py;Onstrategy whenCIis set, elseO1. -
beartype import-ordering (top footgun). The hook only instruments modules imported after it, and
sys.modulescaching makes anything loaded before it permanently unchecked. So: before the hook, import onlysettings;core/settings.pyis a leaf (no first-party imports);core/__init__.py(and any package on the path from the top__init__.pytosettings) is empty. This is automatic for every entry point because importing anything from the package runs__init__.pyfirst — as long as you enter through the package (import pkg.X,python -m pkg.cli, console script,uv run). Never run a package module as a loose file. -
Boundaries: pydantic. Every value crossing a process boundary (LLM output, tool results, HTTP, files, deserialization) is parsed and validated by a pydantic model at the entry point. Rule: crossing a process boundary → pydantic (validate + coerce); internal contract → beartype.
-
Model-agnostic: every external AI dependency behind a
ports/Protocol; SDKs only inadapters/. Core and domain code import zero vendor SDKs (the checker enforces this). One assembly seam (ports/factory.py) selects the impl by env; SDKs are lazy-imported inside adapters; vendor errors normalize toProviderError(program errors propagate — neverexcept Exceptioninto a fallback). A deterministic MockProvider is the default (not a test stub) so the main path runs offline/CI with no SDK or key. A conformance kit binds Mock and real backends to the same invariants. -
No silent failures. beartype violations, Jinja2
StrictUndefined, normalized provider errors — all prefer a loud, located failure over silently-wrong behavior. No bareexcept. -
Completion = one zero-warning gate, the agent's only correctness judge.
./ci.shrunsruff format --check→ruff check→mypy→check_drift.py→CI=1 pytest(beartypeOn+ smoke +filterwarnings=["error"]),set -euo pipefail. Run it after every change; fix until green; never "looks fine, commit". Pin it with a pre-push hook.
Structure: src layout, named package, no rootutils
- Always src layout (
src/<name>/) with a real package name from day one (neverimport src). Norootutils/.project-root— install editable (uv sync) andimport pkgworks everywhere. Find files viaimportlib.resources/PackageLoader(package-shipped) and settings+env (root content). - All reusable logic in
src/<pkg>/, even if onlyscripts//tests/call it (maximizes beartype coverage). Test-only scaffolding stays intests/. core/= cross-cutting infra:settings.py(pydantic-settings, leaf),paths.py,logging.py(setup_logging()once at the entry; library code onlygetLogger;log_provenance()+SENSITIVE_FIELDSkeep payloads out of logs),prompts.py.ports/+adapters/= the model-agnostic seam (rule 5).configs/settings.yamlmerged intoSettingsviaYamlConfigSettingsSource(typed replacement for Hydra config files).prompts/inside the package, loaded byPackageLoader, shipped in the wheel.
Navigability: domain-first, names map to locations
Naming-as-path is to navigation what types are to interface contracts. "Fix the reranker" should resolve to retrieval/reranking/ with no search.
- Domain-first, not layer-first (group by capability, not by
models//utils/). Nest 3–4 levels; leaf modules have real content. A domain package holdsmodels.py(its pydantic contracts) + impl + a thin-re-exporting__init__.py(post-hook, so re-export is fine and aids navigation). Cross-domain contracts → top-levelschemas/. Seereferences/standard.md§7.9.
Principles for AI-touching code (advisory)
Beyond types — for any code where a model produces output. These are upper-level discipline; not all mechanically checkable.
- Constrain, don't ask. Push non-negotiable properties (no fabrication, must-cite, no privilege escalation) into deterministic control flow so the model physically cannot violate them — don't rely on the prompt. Synthesize answers from structured values in code; discard model prose on the critical path.
- Narrow the emission surface. Don't let the model freely generate key payloads — make it pick from controlled options or call tools that return tri-state (found/not_found/unrecognized); take final numbers from tool results, not model text.
- Guardrails are deterministic, independent, never pluggable. Intent parsing can be swapped; safety decisions are deterministic code re-evaluated from raw input, not trusting a pluggable component's output.
Driving AI on big work (advisory)
Treat AI as supervisable labor, not unsupervised autopilot. (A heavier version is arguably a sibling skill.)
- Decision-first: write a numbered, immutable ADR (
docs/adr/) before coding — context + chosen option + rejected alternatives and why. AI fills within locked boundaries; rejected-reasons stop it re-walking excluded paths. - TDD red-light first; tests are the immutable spec. Write the failing test, then implement to green; never weaken a test to pass. Attach the failing test as a subagent's acceptance criteria.
- Numbered steps, each independently green; one commit per step through the full gate. No giant diffs.
- Adversarial independent review. After writing, run a separate, hostile, multi-perspective review ("assume it's wrong; falsify it"), prioritizing artifacts tests can't cover (diagrams, docs, tradeoffs) — the same agent that writes and praises confirms its own bias.
Scale to project size
The model-agnostic layer, ADRs, and drift guards are real overhead — overkill for a 200-line tool. Present them as triggered, scalable patterns ("the moment you call an LLM/embedding/vector store, put it behind a Protocol"; "drill a package down the moment it takes a second responsibility"), not blanket mandates.
Resources
references/standard.md— the full standard with rationale and complete code for every module (read for the why, edge cases, or exact module contents).assets/templates/— exact boilerplate, mirroring a project layout;__PACKAGE_NAME__is the only placeholder. Includesports/+adapters/(model-agnostic seam),ci.sh,CLAUDE.md,docs/adr/,scripts/check_drift.py, and smoke/conformance tests.scripts/scaffold.py— generate a conforming new project.scripts/check_conformance.py— verify structural invariants (incl. zero-SDK-outside-adapters).