Skip to content

Commit a390e1e

Browse files
AbdelStarkclaude
andauthored
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

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.editorconfig

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# EditorConfig — keep editors consistent across the team.
2+
# https://editorconfig.org
3+
4+
root = true
5+
6+
[*]
7+
charset = utf-8
8+
end_of_line = lf
9+
indent_style = space
10+
indent_size = 4
11+
insert_final_newline = true
12+
trim_trailing_whitespace = true
13+
max_line_length = 100
14+
15+
[*.{yml,yaml,json,toml}]
16+
indent_size = 2
17+
18+
[*.md]
19+
trim_trailing_whitespace = false # markdown linebreaks use trailing spaces
20+
indent_size = 2
21+
22+
[Makefile]
23+
indent_style = tab
24+
25+
[*.{patch,diff}]
26+
trim_trailing_whitespace = false

.gitattributes

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Normalize line endings across platforms.
2+
* text=auto eol=lf
3+
4+
# Vendored / generated content: do not gate on diff noise.
5+
tests/api/public_surface.json linguist-generated=true
6+
docs/_build/** linguist-generated=true
7+
site/** linguist-generated=true
8+
9+
# Binary / large blobs.
10+
*.png binary
11+
*.jpg binary
12+
*.jpeg binary
13+
*.gif binary
14+
*.ico binary
15+
*.pdf binary
16+
*.safetensors binary
17+
*.onnx binary
18+
*.bin binary
19+
*.gguf binary
20+
*.parquet binary
21+
*.feather binary
22+
23+
# Documentation is the bulk of this repo today — let GitHub's
24+
# linguist render it accurately rather than letting code files
25+
# dominate the language stats.
26+
*.md linguist-detectable=true
27+
docs/** linguist-documentation=true
28+
rfcs/** linguist-documentation=true

.github/CODEOWNERS

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# CODEOWNERS — auto-assigns reviewers on PRs.
2+
# Order matters: later patterns override earlier ones.
3+
#
4+
# When you add a maintainer, add them in docs/maintainers.md too.
5+
6+
# Default owner: project lead.
7+
* @AbdelStark
8+
9+
# Specifications and RFCs need lead review.
10+
/SPEC.md @AbdelStark
11+
/SPECIFICATION.md @AbdelStark
12+
/ARCHITECTURE.md @AbdelStark
13+
/ROADMAP.md @AbdelStark
14+
/docs/spec/ @AbdelStark
15+
/rfcs/ @AbdelStark
16+
17+
# Privacy / security posture.
18+
/PRIVACY.md @AbdelStark
19+
/SECURITY.md @AbdelStark
20+
/docs/spec/06-security.md @AbdelStark
21+
/geno_lewm/_redaction.py @AbdelStark
22+
/geno_lewm/attestation/ @AbdelStark
23+
24+
# Build, release, and CI.
25+
/pyproject.toml @AbdelStark
26+
/.github/ @AbdelStark
27+
/.pre-commit-config.yaml @AbdelStark

.github/FUNDING.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
github: [AbdelStark]

.github/dependabot.yml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
version: 2
2+
updates:
3+
# Python dependencies (pyproject.toml).
4+
- package-ecosystem: "pip"
5+
directory: "/"
6+
schedule:
7+
interval: "weekly"
8+
day: "monday"
9+
time: "06:00"
10+
timezone: "UTC"
11+
open-pull-requests-limit: 5
12+
labels:
13+
- "type:dependency"
14+
- "triage:reviewed"
15+
groups:
16+
python-minor-and-patch:
17+
applies-to: version-updates
18+
update-types: ["minor", "patch"]
19+
python-security:
20+
applies-to: security-updates
21+
patterns: ["*"]
22+
commit-message:
23+
prefix: "deps"
24+
include: "scope"
25+
26+
# GitHub Actions.
27+
- package-ecosystem: "github-actions"
28+
directory: "/"
29+
schedule:
30+
interval: "weekly"
31+
day: "monday"
32+
time: "06:00"
33+
timezone: "UTC"
34+
open-pull-requests-limit: 5
35+
labels:
36+
- "type:ci"
37+
- "triage:reviewed"
38+
groups:
39+
actions:
40+
applies-to: version-updates
41+
update-types: ["minor", "patch"]
42+
commit-message:
43+
prefix: "ci"
44+
include: "scope"

.github/labels.yml

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# Declarative issue / PR label config. Synced by `.github/workflows/labels.yml`
2+
# so the labels referenced from issue templates, CONTRIBUTING.md, and
3+
# triage docs are always present.
4+
5+
# Triage workflow
6+
- name: "triage:needs-info"
7+
description: Author has not yet provided enough context.
8+
color: c5def5
9+
- name: "triage:reproduction"
10+
description: A synthetic reproducer would unblock triage.
11+
color: c5def5
12+
- name: "triage:reviewed"
13+
description: Triaged into the backlog.
14+
color: 0e8a16
15+
- name: "triage:wontfix"
16+
description: Closed with reason; not actionable.
17+
color: cccccc
18+
19+
# Type
20+
- name: "type:bug"
21+
description: A defect in shipped behaviour.
22+
color: d73a4a
23+
- name: "type:feature"
24+
description: New user-visible capability.
25+
color: a2eeef
26+
- name: "type:refactor"
27+
description: Internal change, no user-visible behaviour delta.
28+
color: cfd3d7
29+
- name: "type:docs"
30+
description: Documentation, spec, or RFC.
31+
color: 0075ca
32+
- name: "type:ci"
33+
description: CI / build / release tooling.
34+
color: 1d76db
35+
- name: "type:dependency"
36+
description: Dependency upgrade or addition.
37+
color: 0366d6
38+
- name: "type:test"
39+
description: Test changes only.
40+
color: bfd4f2
41+
- name: "type:rfc"
42+
description: An RFC PR or RFC-process change.
43+
color: 7057ff
44+
- name: "type:performance"
45+
description: Latency, throughput, or memory budget.
46+
color: e99695
47+
- name: "type:security"
48+
description: Security or supply-chain.
49+
color: b60205
50+
51+
# Area
52+
- name: "area:errors"
53+
color: fef2c0
54+
- name: "area:observability"
55+
color: fef2c0
56+
- name: "area:attestation"
57+
color: fef2c0
58+
- name: "area:action"
59+
color: fef2c0
60+
- name: "area:training"
61+
color: fef2c0
62+
- name: "area:eval"
63+
color: fef2c0
64+
- name: "area:deploy"
65+
color: fef2c0
66+
- name: "area:cli"
67+
color: fef2c0
68+
- name: "area:docs"
69+
color: fef2c0
70+
- name: "area:ci"
71+
color: fef2c0
72+
73+
# Priority
74+
- name: "priority:high"
75+
description: Should land within the current iteration.
76+
color: b60205
77+
- name: "priority:medium"
78+
description: Should land within the current phase.
79+
color: e99695
80+
- name: "priority:low"
81+
description: Nice-to-have.
82+
color: fbca04
83+
84+
# Effort
85+
- name: "effort:small"
86+
description: One sitting.
87+
color: 0e8a16
88+
- name: "effort:medium"
89+
description: A few days.
90+
color: fbca04
91+
- name: "effort:large"
92+
description: One or more weeks.
93+
color: b60205
94+
95+
# Status
96+
- name: "status:blocked"
97+
color: 5319e7
98+
- name: "status:in-progress"
99+
color: 1d76db
100+
- name: "status:in-review"
101+
color: 1d76db
102+
- name: "status:waiting-on-author"
103+
color: e99695
104+
105+
# Good first / help-wanted
106+
- name: "good first issue"
107+
description: A new contributor's onboarding ramp.
108+
color: 7057ff
109+
- name: "help wanted"
110+
color: 008672

0 commit comments

Comments
 (0)