fix(review): validate base Python lock closures - #661
Conversation
📝 WalkthroughWalkthrough신뢰된 base Python 잠금 후보를 검증·preflight·그룹 복구 후 설치하는 CI 설치기가 추가되었습니다. Coverage Docker 빌드는 기존 inline pip 루프 대신 이 설치기를 사용하며, 관련 materializer 메시지와 계약 테스트가 갱신되었습니다. ChangesBase Python 잠금 설치
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Coverage workflow
participant Docker build
participant install-base-python-locks.py
participant pip
Coverage workflow->>Docker build: 설치기와 base requirements 준비
Docker build->>install-base-python-locks.py: --requirements-root 전달
install-base-python-locks.py->>pip: 잠금 후보 preflight
install-base-python-locks.py->>pip: 검증된 후보 설치
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
d81c649 to
52f53e9
Compare
|
Added a fail-closed preflight classification on current head Local evidence: focused lock/materializer/agent suite |
|
Current-head follow-up for
Local evidence:
Hosted checks are running on this exact head. No user-owned |
|
Merge audit for exact head
|
… can run The central coverage-evidence sandbox installs the hash-pinned Python locks the materializer extracts from the PR base commit, then runs each repo's `pytest tests` offline. Repositories managed entirely by uv expose only a `uv.lock` (no `requirements*.txt` / `requirements.lock`), so the content-based discovery from #657 finds nothing, no dependencies install, and the suite fails at import (`ModuleNotFoundError`). coverage-evidence then reports `failure` and OpenCode posts a deterministic REQUEST_CHANGES, permanently blocking every uv-managed repo's PR queue even when the repo's own CI is green. Observed on newsdom-api#464 and pg-llm-batch#17. Fix: when a base `uv.lock` is discovered, reconstruct it and its sibling `pyproject.toml` from the exact validated base SHA in an isolated temp dir and run `uv export --frozen --no-emit-project` to produce a fully hash-pinned dependency closure the existing #661 installer consumes like any other lock. `--frozen` forbids lock mutation and network resolution, and both inputs are read only from the base commit, so no PR-mutable content reaches uv and the trust boundary is unchanged. It is best-effort: if `uv` is absent, the base `pyproject.toml` is missing, the export fails, or its output is not fully hash-pinned, the lock is skipped exactly as before, so this can never break an otherwise-working build. Flat-layout and requirements-based repos are unaffected. Verification (against the real newsdom-api base tree): `uv.lock` -> `requirements-000.txt` with 225 `--hash=` pins. Full suite: 710 passed; scripts/ci line coverage 100% (materializer 114/114); interrogate 100%. Scope: this covers uv.lock-only repos on runners where `uv` is available (GitHub's ubuntu-latest ships it). Native-extension repos that need a maturin build of a compiled module (e.g. fast-mlsirm's `_core`) remain a separate, harder gap and are not addressed here. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HdCssGnNMhKHNu3TXFstWH
… can run The central coverage-evidence sandbox installs the hash-pinned Python locks the materializer extracts from the PR base commit, then runs each repo's `pytest tests` offline. Repositories managed entirely by uv expose only a `uv.lock` (no `requirements*.txt` / `requirements.lock`), so the content-based discovery from #657 finds nothing, no dependencies install, and the suite fails at import (`ModuleNotFoundError`). coverage-evidence then reports `failure` and OpenCode posts a deterministic REQUEST_CHANGES, permanently blocking every uv-managed repo's PR queue even when the repo's own CI is green. Observed on newsdom-api#464 and pg-llm-batch#17. Fix: when a base `uv.lock` is discovered, reconstruct it and its sibling `pyproject.toml` from the exact validated base SHA in an isolated temp dir and run `uv export --frozen --no-emit-project` to produce a fully hash-pinned dependency closure the existing #661 installer consumes like any other lock. `--frozen` forbids lock mutation and network resolution, and both inputs are read only from the base commit, so no PR-mutable content reaches uv and the trust boundary is unchanged. It is best-effort: if `uv` is absent, the base `pyproject.toml` is missing, the export fails, or its output is not fully hash-pinned, the lock is skipped exactly as before, so this can never break an otherwise-working build. Flat-layout and requirements-based repos are unaffected. Verification (against the real newsdom-api base tree): `uv.lock` -> `requirements-000.txt` with 225 `--hash=` pins. Full suite: 710 passed; scripts/ci line coverage 100% (materializer 114/114); interrogate 100%. Scope: this covers uv.lock-only repos on runners where `uv` is available (GitHub's ubuntu-latest ships it). Native-extension repos that need a maturin build of a compiled module (e.g. fast-mlsirm's `_core`) remain a separate, harder gap and are not addressed here. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HdCssGnNMhKHNu3TXFstWH
…verage (#668) * fix(review): materialize uv.lock-only repos so their offline coverage can run The central coverage-evidence sandbox installs the hash-pinned Python locks the materializer extracts from the PR base commit, then runs each repo's `pytest tests` offline. Repositories managed entirely by uv expose only a `uv.lock` (no `requirements*.txt` / `requirements.lock`), so the content-based discovery from #657 finds nothing, no dependencies install, and the suite fails at import (`ModuleNotFoundError`). coverage-evidence then reports `failure` and OpenCode posts a deterministic REQUEST_CHANGES, permanently blocking every uv-managed repo's PR queue even when the repo's own CI is green. Observed on newsdom-api#464 and pg-llm-batch#17. Fix: when a base `uv.lock` is discovered, reconstruct it and its sibling `pyproject.toml` from the exact validated base SHA in an isolated temp dir and run `uv export --frozen --no-emit-project` to produce a fully hash-pinned dependency closure the existing #661 installer consumes like any other lock. `--frozen` forbids lock mutation and network resolution, and both inputs are read only from the base commit, so no PR-mutable content reaches uv and the trust boundary is unchanged. It is best-effort: if `uv` is absent, the base `pyproject.toml` is missing, the export fails, or its output is not fully hash-pinned, the lock is skipped exactly as before, so this can never break an otherwise-working build. Flat-layout and requirements-based repos are unaffected. Verification (against the real newsdom-api base tree): `uv.lock` -> `requirements-000.txt` with 225 `--hash=` pins. Full suite: 710 passed; scripts/ci line coverage 100% (materializer 114/114); interrogate 100%. Scope: this covers uv.lock-only repos on runners where `uv` is available (GitHub's ubuntu-latest ships it). Native-extension repos that need a maturin build of a compiled module (e.g. fast-mlsirm's `_core`) remain a separate, harder gap and are not addressed here. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HdCssGnNMhKHNu3TXFstWH * fix(coverage): force uv lock exports offline * fix(coverage): bound trusted uv export --------- Co-authored-by: Claude <noreply@anthropic.com>
Root cause
OpenCode coverage run 30502031874, job 90743664244 selected Naruon
backend/requirements-agent.txtas a standalone hash lock. Pip correctly rejected it under--require-hashesbecause its transitivehttpx>=0.27requirement is supplied by the siblingbackend/requirements-hashes.txtclosure.Fix
--dry-run --ignore-installed --require-hashes --only-binary=:all:.OpenCode Review Dispatchworkflow/title alias.Current-head evidence
Head:
bc00945e8b664c8000f8c94554790c89e5c9c6c7; base:68e573e92561919bddcf529e5593e64888d595a0.git diff --check: passed.httpx>=0.27) is classified as an incomplete supplement; hash mismatch/network/unknown failures are fatal.The hosted OpenCode/coverage rerun on this exact head is required before merge. Because repository-dispatch workflows execute the current default-branch workflow, the final production-path proof is a post-merge Naruon #1184 rerun that must log the recovered same-directory closure and pass coverage.