Commit a390e1e
chore: PEP 440 compliance, mypy --strict cleanliness, lint/format pass (#120)
* chore: PEP 440 compliance, mypy --strict cleanliness, lint/format pass
- Replace non-PEP-440 `0.1.0-draft` with `0.1.0.dev0`; dynamic
version sourced from `geno_lewm/__init__.py` (Hatch).
- Curate top-level `geno_lewm.__all__` so the implemented surface
(errors, observability, attestation, action specs, decorators)
is reachable from the package root.
- Add `py.typed` marker and `tools/__init__.py` so downstream type
checkers and `python -m tools.*` work as documented.
- Make `tools/api/snapshot.py` produce a Python-version-stable enum
signature; regenerate `tests/api/public_surface.json`.
- Tighten `pyproject.toml`: ruff lint+format with strong rule set,
mypy strict (now zero errors across `geno_lewm/` and `tools/`),
pytest strict markers + filterwarnings=error, branch coverage at
95% gate, optional dep groups split into `train/eval/deploy/dev/
docs/all`.
- Resolve every ruff (B, C4, UP, N, RUF, SIM, PIE, PTH, PERF, FURB,
PLR, LOG, ASYNC) finding across `geno_lewm/`, `tools/`, `tests/`.
- Resolve every mypy `--strict` error: TypedDict for histogram
snapshot, IO[str] stream typing in the verify CLI, Iterator
return type on ErrorCodeEntry, `setattr` for method reassignment
in decorators.
- Add format-skip directives where deliberate same-line statements
exercise the per-call-site dedupe in `@deprecated`.
All 417 tests pass; ruff format/check, mypy --strict,
check_error_codes, check_event_names, check_no_print,
check_network_confined, and the public-API snapshot gate are clean.
* build: comprehensive CI/CD, docs site, and OSS hygiene
CI/CD pipeline
- .github/workflows/ci.yml: matrix tests on Python 3.10/3.11/3.12/3.13
across Linux/macOS/Windows, ruff lint+format, mypy --strict, the
five contract gates (errors / events / surface / print / network),
build smoke test (sdist+wheel + import sanity), mkdocs --strict
build, codecov upload, single required-check fan-in.
- .github/workflows/release.yml: tag-driven PyPI publish via OIDC
trusted publishing (no API tokens), TestPyPI dry-run on manual
dispatch, GitHub release with extracted changelog notes.
- .github/workflows/codeql.yml: weekly + per-PR static analysis with
security-extended queries.
- .github/workflows/docs.yml: GitHub Pages deploy.
- Removed legacy .github/workflows/lint-errors.yml (superseded by ci.yml).
Documentation site
- mkdocs.yml with material theme, mkdocstrings, gen-files, literate-nav.
- docs/index.md, docs/quickstart.md: actually-runnable walkthrough
hitting the implemented surface.
- docs/_gen/ scripts that build the public API reference, the error-code
table, the log-event table, RFC mirror with rewritten links, and the
project-root pages (changelog / contributing / security / privacy /
code-of-conduct) at mkdocs build time so docs cannot drift from the
runtime registries or the canonical repo sources.
- docs/api/{experimental,metrics}.md hubs.
- docs/release/signing-keys.md trust-anchor placeholder.
- Rewrote all repo-root-relative links across docs/spec/, docs/rfcs/,
docs/{faq,design-decisions,glossary,maintainers}.md, and the roadmap
tracker so mkdocs --strict passes with zero warnings.
OSS hygiene
- .pre-commit-config.yaml mirrors every CI gate (large files, line
endings, ruff, mypy, the five contract linters, snapshot drift).
- .editorconfig, .gitattributes for cross-editor / cross-platform
consistency.
- .github/CODEOWNERS, .github/FUNDING.yml, .github/dependabot.yml
(weekly minor/patch + security updates, scoped to pip + actions).
* docs: refreshed README + CHANGELOG with the new infrastructure
- README badges (CI / CodeQL / Docs / PyPI / Python / License / mypy
strict / ruff / pre-commit), a sharper "what ships today" table
for the implemented surface, a real quickstart (EditSpec /
apply_edit / verify CLI), and a dev-loop block that mirrors the CI
gates.
- CHANGELOG: full [Unreleased] entry for the packaging /
tooling / CI / docs / OSS-hygiene work, plus rolled the previously
separate [Unreleased] block into the [0.1.0-draft] section.
* build: add Makefile mirroring the CI gates
\`make ci\` runs format-check, ruff lint, mypy --strict, every AST
gate, pytest -n auto, and mkdocs --strict — the exact set CI runs.
Individual targets (\`make types\`, \`make docs\`, \`make build-check\`,
…) are available for targeted iteration. \`make snapshot\` is the
documented way to regenerate the public-surface snapshot when an API
change is intentional.
* test: lift coverage above the 95% gate
Add tests/unit/test_coverage_extras.py covering the small branches
the per-module suites don't exercise: counter/gauge/histogram reset,
snapshot_all kind tagging, exporter NaN/+Inf/-Inf rendering, default
exporter path env+home fallback, logger level rejection, unknown
event passthrough, pretty stderr formatter (incl. step + error_code
columns), trace-context round-trip, get_logger caching, logged_run's
both-paths exception flushing, shutdown_run sink close, looks_like_sha256
positive/negative branches, redaction_stats helpers, every synthetic
sampler validation branch (negative n, type_mix=0, malformed length_dist,
N-anchor skipping), receipt schema rejections, and to_json timestamp
shape.
Coverage rises from 92.89 % to 96.07 % branch; the 95 % gate now passes
on a clean run. Total tests: 462 (was 417).
* build: supply-chain hardening + project hygiene
Supply-chain
- .github/workflows/scorecard.yml — OpenSSF Scorecard weekly + on
push to main. SARIF lands in the Security tab; results publish to
the OpenSSF dashboard for the README badge.
- release.yml now produces a CycloneDX SBOM (cyclonedx-py environment)
alongside the wheel + sdist, computes SHA256SUMS for the dist
bundle, and emits a SLSA-3 provenance attestation
(slsa-framework/slsa-github-generator) so consumers can verify the
build claim from a single intoto.jsonl.
License header gate
- tools/lint/check_license_headers.py: AST-free linter that requires
`# SPDX-License-Identifier: Apache-2.0` in the head of every shipped
.py file under geno_lewm/ and tools/.
- Apply the header to every existing module.
- Wire into Makefile (\`make gates\`), .pre-commit-config.yaml, and CI
(.github/workflows/ci.yml).
Project hygiene
- .github/labels.yml — declarative label set covering the triage /
type / area / priority / effort / status taxonomy referenced from
CONTRIBUTING.md and the issue templates.
- .github/workflows/labels.yml — sync labels on push, prune
out-of-config entries.
- .github/workflows/stale.yml — 90-day stale / 120-day close cadence
for issues and PRs. RFCs, "good first issue", "help wanted", any
"priority:high|medium", and "status:blocked" are exempt so the
long-tail design work is never pruned.
* ci: fix all jobs by giving uv a system Python to target
Every CI job was failing in ~5 seconds because the previous setup
used \`uv python install\` (which downloads Python into uv's managed
cache without adding it to PATH) followed by \`uv pip install
--system\` (which targets the PATH-discovered interpreter). The two
calls don't compose; uv reported "no system Python found" and the
step exited immediately.
Fix: prepend \`actions/setup-python@v5\` to every job so a Python
interpreter is on PATH, set \`UV_SYSTEM_PYTHON=1\` at the workflow
env level so \`uv pip install\` implicitly targets it, and drop the
now-redundant \`uv python install\` / \`--system\` flag.
Applied to ci.yml (lint, types, gates, tests, build, docs),
docs.yml, and release.yml.
* ci: drop uv from CI, use pip + setup-python's built-in cache
The astral-sh/setup-uv@v3 + uv pip install --system combo was failing
every job in <10s on every runner (Linux/macOS/Windows) regardless of
the PATH-fix attempt. The CI workload is 13 small jobs — pip's speed
is not the bottleneck, and removing uv eliminates a moving piece.
Replace with the boring pattern that always works:
- actions/setup-python@v5 (cache: pip, cache-dependency-path: pyproject.toml)
- python -m pip install -e ".[dev]"
Applied uniformly to ci.yml, docs.yml, release.yml.
Local development still uses uv (Makefile, CONTRIBUTING, pyproject
dev extra unchanged).
* test: make metrics_path fallback assertion Windows-safe
\`str(Path.home() / \".geno-lewm\" / \"logs\" / \"metrics.prom\")\` produces
backslash-separated output on Windows, so the previous
\`.endswith(\".geno-lewm/logs/metrics.prom\")\` assertion failed there.
Compare path components via \`.parts\` instead; the check is identical
on POSIX and works on Windows.
* ci: run pytest serially on Windows + upload pytest output on failure
Windows + pytest-xdist's spawn-based workers re-import the package
per worker, which surfaces flaky failures around the module-level
state in geno_lewm.observability and geno_lewm.metrics. Disable
xdist on Windows only (still -n auto on Linux/macOS, where xdist
uses fork-based workers and the state isn't reimported).
Also upload pytest stdout/stderr as an artifact on failure so the
exact failing test surfaces without needing log-stream access.
* lint: make check_no_print path-allowlist Windows-safe
The CLI-print allowlist compared paths via
\`str(rel).startswith(str(p) + \"/\")\`. On Windows this never
matched because \`str(rel)\` uses backslashes, so the CLI
allowlist silently failed and every \`print()\` in
\`geno_lewm/cli/verify.py\` was flagged as a violation, breaking
the gates job + two unit tests on every Windows runner.
Switch to component-tuple comparison (\`rel.parts[:n] == p.parts\`)
so the same allowlist matches on POSIX and Windows.
Confirmed by downloading the pytest artifact from the prior
Windows run; both failures (\`test_print_in_cli_dir_is_allowed\` and
\`test_real_package_passes\`) trace to this single AST-linter
regression. Local Linux suite still passes.
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 8d32ee6 commit a390e1e
89 files changed
Lines changed: 3678 additions & 559 deletions
File tree
- .github
- workflows
- docs
- _gen
- api
- release
- roadmap
- spec
- geno_lewm
- action
- attestation
- cli
- tests
- api
- lint
- property
- unit
- tools
- api
- lint
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
0 commit comments