fix(coverage): resolve npm workspace lock owners - #703
Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughGit 기반 npm workspace 설치 루트 해석기와 보안 검증 테스트를 추가했습니다. CI는 검증된 workspace 루트에서 오프라인 설치를 수행합니다. CodeQL action과 Python dependency lock도 갱신했습니다. Changesnpm workspace installation
CI 및 Python dependency maintenance
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant ReviewWorkflow
participant Resolver
participant Git
participant npm
ReviewWorkflow->>Resolver: package path와 base/head SHA 전달
Resolver->>Git: manifest와 lockfile blob 검증
Resolver-->>ReviewWorkflow: 검증된 install root 반환
ReviewWorkflow->>npm: workspace 루트에서 offline npm ci 실행
Possibly related PRs
Suggested labels: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
@jules Please finish this focused central coverage fix on the current branch. Wire
The intended verified command shape is equivalent to: npm_install_root_relative="$(python3 -I "$GITHUB_WORKSPACE/scripts/ci/npm_workspace_install_root.py" --repo-root "$COVERAGE_SOURCE_WORKDIR" --package-dir "$PWD")"
# map `.` or a safe relative result beneath COVERAGE_SOURCE_WORKDIR
trusted_npm_lock_is_materialized "$npm_install_root"
run_and_capture "JavaScript/TypeScript dependencies (npm workspace-root offline ci, lifecycle hooks disabled)" \
bash -c 'cd "$1" && npm ci --offline --ignore-scripts --cache "$2" --no-audit --no-fund' \
bash "$npm_install_root" "$writable_npm_cache_dir"Verify the resolver at 100% line coverage and docstring coverage, the full relevant pytest contract set, Bash syntax of extracted workflow run blocks, and |
|
@jules While completing the workflow wiring, also close these resolver trust/correctness gaps on the same branch:
Keep the PR focused on the resolver, workflow integration, contracts/tests, and one accurate 2026 journal entry. |
|
@jules Complete this PR now rather than leaving the resolver unwired. Required implementation:
Keep the patch fail-closed and limited to the central coverage path. Push the completed implementation to this PR branch. |
|
One fail-closed bug remains in the current resolver head Replace |
|
A second compatibility/security-contract issue is visible in the current resolver: The workspace resolver should establish ownership from the live-validated HEAD tree/worktree and return the lock-owner path; the workflow's existing |
|
@jules Complete this PR into its final reviewable state. Run |
|
@jules The branch now has the resolver and focused tests, but the actual central workflow wiring is still absent from the PR diff. Please apply the existing |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (7)
tests/test_npm_workspace_install_root_hardening.py (2)
15-67: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value테스트 헬퍼가 중복됩니다.
_git,_write_json,_commit은tests/test_npm_workspace_install_root.py의 동일한 헬퍼와 중복됩니다. 두 픽스처 구현이 시간이 지나며 달라질 수 있습니다. 헬퍼를tests/conftest.py의 공유 픽스처나 작은 헬퍼 모듈로 이동하십시오.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/test_npm_workspace_install_root_hardening.py` around lines 15 - 67, Remove the duplicated _git, _write_json, and _commit helpers from this test module and reuse shared implementations from tests/conftest.py or a small helper module, updating _workspace_repo and its callers to use them while preserving existing fixture behavior.
193-193: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
rm -rf서브프로세스 대신shutil.rmtree를 사용하십시오.이 호출은 외부
rm실행 파일에 의존합니다. Windows 개발 환경에서는 실패합니다. 또한 Ruff가 S603과 S607로 표시합니다. 표준 라이브러리shutil.rmtree가 동일한 작업을 이식 가능하게 수행합니다.♻️ 제안 리팩터링
import json +import shutil import subprocess- subprocess.run(["rm", "-rf", str(repo / "apps")], check=True) + shutil.rmtree(repo / "apps")🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/test_npm_workspace_install_root_hardening.py` at line 193, Replace the subprocess-based recursive deletion in the test with the standard-library shutil.rmtree call, updating imports as needed. Preserve deletion of the repo / "apps" directory and its current test behavior without invoking an external rm executable.Source: Linters/SAST tools
scripts/ci/npm_workspace_install_root.py (2)
195-218: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value루프 내부에서
lru_cache데코레이터를 정의하지 마십시오.
matches는 루프 반복마다 새로 정의됩니다. 이 함수는 자유 변수pattern_parts를 캡처합니다. Ruff는 이를 B023으로 표시합니다. 현재는 함수가 정의된 반복 안에서만 호출되므로 동작은 정확합니다. 그러나 이 구조는 향후 리팩터링에서 늦은 바인딩 버그를 유발할 수 있습니다. 또한 반복마다 새 캐시 객체를 생성합니다.매처를 모듈 수준 헬퍼로 추출하고 인자를 튜플로 전달하십시오. 그러면 캐시를 패턴 간에 재사용할 수 있고 B023 경고도 사라집니다.
♻️ 제안 리팩터링
+@lru_cache(maxsize=4096) +def _segments_match( + path_parts: tuple[str, ...], + pattern_parts: tuple[str, ...], +) -> bool: + """Match anchored single-segment globs and recursive ``**`` tokens.""" + if not pattern_parts: + return not path_parts + token = pattern_parts[0] + if token == "**": + return _segments_match(path_parts, pattern_parts[1:]) or ( + bool(path_parts) and _segments_match(path_parts[1:], pattern_parts) + ) + if not path_parts: + return False + return fnmatch.fnmatchcase(path_parts[0], token) and _segments_match( + path_parts[1:], + pattern_parts[1:], + ) + + def _is_declared_workspace(relative_package: PurePosixPath, patterns: list[str]) -> bool: """Return whether a path fully matches one anchored workspace pattern.""" path_parts = relative_package.parts - - for pattern in patterns: - pattern_parts = tuple(pattern.split("/")) - - `@lru_cache`(maxsize=None) - def matches(path_index: int, pattern_index: int) -> bool: - ... - - if matches(0, 0): - return True - return False + return any( + _segments_match(path_parts, tuple(pattern.split("/"))) for pattern in patterns + )🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/ci/npm_workspace_install_root.py` around lines 195 - 218, Move the nested matches function out of the patterns loop into a module-level cached helper, passing path_parts and pattern_parts as explicit tuple arguments. Update the loop to call this helper for each pattern, preserving the existing anchored glob and recursive ** matching behavior while allowing the cache to be reused across patterns and eliminating the B023 warning.Source: Linters/SAST tools
334-337: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value중복 조건을 단순화하십시오.
PurePosixPath("")는PurePosixPath(".")로 정규화됩니다. 따라서parent != PurePosixPath("")조건의 두 분기가 동일한 값PurePosixPath(".")를 만듭니다. 이 조건은 동작에 영향을 주지 않습니다. 조건을 제거하면 상위 경로 탐색 의도가 명확해집니다.♻️ 제안 리팩터링
if candidate == PurePosixPath("."): break - parent = candidate.parent - candidate = parent if parent != PurePosixPath("") else PurePosixPath(".") + candidate = candidate.parent🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/ci/npm_workspace_install_root.py` around lines 334 - 337, Update the parent-path assignment in the candidate traversal loop to remove the redundant PurePosixPath("") conditional. After the existing candidate == PurePosixPath(".") termination check, assign candidate directly to candidate.parent while preserving the current traversal behavior.tests/test_npm_workspace_install_root.py (1)
480-487: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
module.PurePosixPath대신 직접 임포트를 사용하십시오.이 테스트는 프로덕션 모듈의 임포트 재노출에 의존합니다.
npm_workspace_install_root.py가PurePosixPath임포트를 제거하거나 이름을 바꾸면, 실제 동작 변경이 없어도 테스트가 실패합니다. 이 파일은 이미pathlib에서Path를 임포트합니다.PurePosixPath도 같은 방식으로 임포트하십시오.♻️ 제안 리팩터링
-from pathlib import Path +from pathlib import Path, PurePosixPathmodule._tree_blob( tmp_path, "a" * 40, - module.PurePosixPath("package.json"), + PurePosixPath("package.json"), "fixture manifest", )🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/test_npm_workspace_install_root.py` around lines 480 - 487, Update the test invoking _tree_blob to use a directly imported PurePosixPath from pathlib instead of module.PurePosixPath. Add PurePosixPath alongside the existing Path import and pass it directly, removing the dependency on the production module’s re-export..github/workflows/pr703-focused-tests.yml (1)
42-62: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winPython 버전을 명시적으로 설정하십시오.
이 파일은
bootstrap_patch_workflow.py가 성공하면 삭제하는 일회성 워크플로이므로 별도 중앙 워크플로로 이관할 대상이 아닙니다. 그러나 현재ubuntu-latest의 기본python3에 의존합니다.actions/setup-python을 추가하고python-version: "3.12"를 설정하십시오.bootstrap-npm-workspace-wiring.yml에도 동일한 설정을 적용하십시오.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/pr703-focused-tests.yml around lines 42 - 62, Explicitly configure Python 3.12 in the workflow by adding actions/setup-python with python-version set to "3.12" before the Python-based steps, and apply the same setup to bootstrap-npm-workspace-wiring.yml. Keep the existing test and coverage commands unchanged..github/workflows/bootstrap-npm-workspace-wiring.yml (1)
64-70: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win실패 로그를 저장소에 커밋하지 말고 job summary로 보내세요.
현재 실패 로그는
.github/bootstrap-npm-workspace-failure.log로 기록되고, 이후 단계가 이를 브랜치에 push합니다. 이 파일은 저장소에 잔여 아티팩트로 남습니다.$GITHUB_STEP_SUMMARY또는 업로드 아티팩트를 사용하세요.♻️ 제안 변경
if [ "$patch_rc" -ne 0 ]; then { echo "bootstrap_patch_workflow.py failed with exit code $patch_rc" echo sed -n '1,200p' "$RUNNER_TEMP/bootstrap-patch.log" - } > .github/bootstrap-npm-workspace-failure.log + } >>"$GITHUB_STEP_SUMMARY" fi🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/bootstrap-npm-workspace-wiring.yml around lines 64 - 70, Update the failure-handling block around patch_rc in the workflow to stop writing bootstrap failures to .github/bootstrap-npm-workspace-failure.log, which is later committed and pushed. Send the existing failure message and contents of $RUNNER_TEMP/bootstrap-patch.log to $GITHUB_STEP_SUMMARY instead, preserving the diagnostic details without leaving a repository artifact.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/bootstrap-npm-workspace-wiring.yml:
- Line 124: Update the condition in the workflow’s patch result check to pass
steps.patch.outputs.patch_rc through the step’s env configuration, then
reference the resulting shell environment variable inside the if statement
instead of interpolating the GitHub Actions expression directly.
In @.github/workflows/pr703-focused-tests.yml:
- Around line 1-25: Move the resolver tests and coverage gate from the
PR-specific workflow into the repository’s central test workflow, preserving
their required triggers and checks. Then delete the temporary workflow defined
by “PR 703 Focused Resolver Tests,” including its PR-specific branch and path
configuration, so no one-off bootstrap or workflow remains under
.github/workflows.
In `@scripts/ci/bootstrap_patch_workflow.py`:
- Around line 278-289: Remove the one-time self-modifying bootstrap path: run
scripts/ci/bootstrap_patch_workflow.py locally, commit its generated final
contents into .github/workflows/opencode-review-dispatch.yml and
tests/test_opencode_agent_contract.py, then delete
scripts/ci/bootstrap_patch_workflow.py. Also delete
.github/workflows/bootstrap-npm-workspace-wiring.yml, including its contents:
write permission and branch-push behavior.
In `@scripts/ci/npm_workspace_install_root.py`:
- Around line 113-126: Update _worktree_blob to hash the worktree file with
Git’s path-aware normalization by passing the repository-relative relative_path
via --path to hash-object, instead of using --no-filters. Preserve the existing
regular-file validation and expected-blob comparison.
---
Nitpick comments:
In @.github/workflows/bootstrap-npm-workspace-wiring.yml:
- Around line 64-70: Update the failure-handling block around patch_rc in the
workflow to stop writing bootstrap failures to
.github/bootstrap-npm-workspace-failure.log, which is later committed and
pushed. Send the existing failure message and contents of
$RUNNER_TEMP/bootstrap-patch.log to $GITHUB_STEP_SUMMARY instead, preserving the
diagnostic details without leaving a repository artifact.
In @.github/workflows/pr703-focused-tests.yml:
- Around line 42-62: Explicitly configure Python 3.12 in the workflow by adding
actions/setup-python with python-version set to "3.12" before the Python-based
steps, and apply the same setup to bootstrap-npm-workspace-wiring.yml. Keep the
existing test and coverage commands unchanged.
In `@scripts/ci/npm_workspace_install_root.py`:
- Around line 195-218: Move the nested matches function out of the patterns loop
into a module-level cached helper, passing path_parts and pattern_parts as
explicit tuple arguments. Update the loop to call this helper for each pattern,
preserving the existing anchored glob and recursive ** matching behavior while
allowing the cache to be reused across patterns and eliminating the B023
warning.
- Around line 334-337: Update the parent-path assignment in the candidate
traversal loop to remove the redundant PurePosixPath("") conditional. After the
existing candidate == PurePosixPath(".") termination check, assign candidate
directly to candidate.parent while preserving the current traversal behavior.
In `@tests/test_npm_workspace_install_root_hardening.py`:
- Around line 15-67: Remove the duplicated _git, _write_json, and _commit
helpers from this test module and reuse shared implementations from
tests/conftest.py or a small helper module, updating _workspace_repo and its
callers to use them while preserving existing fixture behavior.
- Line 193: Replace the subprocess-based recursive deletion in the test with the
standard-library shutil.rmtree call, updating imports as needed. Preserve
deletion of the repo / "apps" directory and its current test behavior without
invoking an external rm executable.
In `@tests/test_npm_workspace_install_root.py`:
- Around line 480-487: Update the test invoking _tree_blob to use a directly
imported PurePosixPath from pathlib instead of module.PurePosixPath. Add
PurePosixPath alongside the existing Path import and pass it directly, removing
the dependency on the production module’s re-export.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 9607ef19-06dd-4eed-b62e-96958f32cc8d
📒 Files selected for processing (6)
.github/workflows/bootstrap-npm-workspace-wiring.yml.github/workflows/pr703-focused-tests.ymlscripts/ci/bootstrap_patch_workflow.pyscripts/ci/npm_workspace_install_root.pytests/test_npm_workspace_install_root.pytests/test_npm_workspace_install_root_hardening.py
|
@coderabbitai autofix |
|
Note Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it. The agent ran but didn't make any changes. The issues may already be fixed or require manual intervention. |
|
@jules Finalize this PR directly on the current branch. Replace the temporary self-modifying bootstrap with the actual central workflow and contract changes it was meant to produce; delete |
|
@coderabbitai review Please review the exact current head |
|
✅ Action performedReview finished.
|
Pull request was converted to draft
Pull request was converted to draft
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Pull request overview
OpenCode cannot approve yet because required coverage evidence did not pass.
Review outcome
1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence
-
Problem: The required coverage-evidence job result was
failure, so OpenCode cannot establish approval sufficiency for this head. -
Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.
-
Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports
successwith required evidence or explicit no-source not-applicable evidence. -
Regression test: Keep the approval branch checking
needs.coverage-evidence.result == successbefore posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present. -
Result: REQUEST_CHANGES
-
Reason: coverage-evidence result was
failure, so required test/docstring evidence was not proven for current heade23cba9368b5b7048b62b7c52adbd94bb306ef36. -
Head SHA:
e23cba9368b5b7048b62b7c52adbd94bb306ef36 -
Workflow run: 30885183632
-
Workflow attempt: 1
Coverage evidence
Coverage Decision
- Result: FAIL
- Test evidence: not proven passing
- Docstring evidence: not proven passing when configured
- Failure count: 1
Changed-File Evidence Map
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Workflow: opencode-review-dispatch.yml"]
S1 --> I1["GitHub Actions review job"]
I1 --> R1["Review risk: Workflow: opencode-review-dispatch.yml"]
R1 --> V1["actionlint plus required checks"]
Evidence --> S2["Changed file (2 files)"]
S2 --> I2["repository behavior"]
I2 --> R2["Review risk: Changed file (2 files)"]
R2 --> V2["required checks"]
Evidence --> S3["CI script: npm_workspace_install_root.py"]
S3 --> I3["review and security gate shell path"]
I3 --> R3["Review risk: CI script: npm_workspace_install_root.py"]
R3 --> V3["bash -n plus Strix self-test"]
Evidence --> S4["Test (4 files)"]
S4 --> I4["regression suite"]
I4 --> R4["Review risk: Test (4 files)"]
R4 --> V4["targeted test run"]
OpenCode Review Overview
Pull request overviewOpenCode cannot approve yet because required coverage evidence did not pass. Review outcome1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence
Coverage evidenceCoverage Decision
Changed-File Evidence Mapflowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Workflow: opencode-review-dispatch.yml"]
S1 --> I1["GitHub Actions review job"]
I1 --> R1["Review risk: Workflow: opencode-review-dispatch.yml"]
R1 --> V1["actionlint plus required checks"]
Evidence --> S2["Changed file (2 files)"]
S2 --> I2["repository behavior"]
I2 --> R2["Review risk: Changed file (2 files)"]
R2 --> V2["required checks"]
Evidence --> S3["CI script: npm_workspace_install_root.py"]
S3 --> I3["review and security gate shell path"]
I3 --> R3["Review risk: CI script: npm_workspace_install_root.py"]
R3 --> V3["bash -n plus Strix self-test"]
Evidence --> S4["Test (4 files)"]
S4 --> I4["regression suite"]
I4 --> R4["Review risk: Test (4 files)"]
R4 --> V4["targeted test run"]
|
There was a problem hiding this comment.
Pull request overview
OpenCode cannot approve yet because required coverage evidence did not pass.
Review outcome
1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence
-
Problem: The required coverage-evidence job result was
failure, so OpenCode cannot establish approval sufficiency for this head. -
Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.
-
Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports
successwith required evidence or explicit no-source not-applicable evidence. -
Regression test: Keep the approval branch checking
needs.coverage-evidence.result == successbefore posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present. -
Result: REQUEST_CHANGES
-
Reason: coverage-evidence result was
failure, so required test/docstring evidence was not proven for current heade23cba9368b5b7048b62b7c52adbd94bb306ef36. -
Head SHA:
e23cba9368b5b7048b62b7c52adbd94bb306ef36 -
Workflow run: 30886213715
-
Workflow attempt: 1
Coverage evidence
Coverage Decision
- Result: FAIL
- Test evidence: not proven passing
- Docstring evidence: not proven passing when configured
- Failure count: 1
Changed-File Evidence Map
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Workflow: opencode-review-dispatch.yml"]
S1 --> I1["GitHub Actions review job"]
I1 --> R1["Review risk: Workflow: opencode-review-dispatch.yml"]
R1 --> V1["actionlint plus required checks"]
Evidence --> S2["Changed file (2 files)"]
S2 --> I2["repository behavior"]
I2 --> R2["Review risk: Changed file (2 files)"]
R2 --> V2["required checks"]
Evidence --> S3["CI script: npm_workspace_install_root.py"]
S3 --> I3["review and security gate shell path"]
I3 --> R3["Review risk: CI script: npm_workspace_install_root.py"]
R3 --> V3["bash -n plus Strix self-test"]
Evidence --> S4["Test (4 files)"]
S4 --> I4["regression suite"]
I4 --> R4["Review risk: Test (4 files)"]
R4 --> V4["targeted test run"]
The exact #703 merge tree failed the existing workflow contract because CodeQL init/analyze remained at v4.37.0 while upload-sarif used v4.37.4. Align both central CodeQL workflows to the already-vetted immutable v4.37.4 SHA so the npm workspace resolver can be measured by the full repository coverage gate instead of failing on an unrelated protected-base defect.
|
@coderabbitai review Please review exact head |
|
✅ Action performedReview finished.
|
|
@opencode-agent @cwl-noema-review Please independently re-review exact head |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
tests/test_npm_workspace_install_root.py (1)
15-45: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winGit 픽스처 헬퍼가 두 곳에 중복 정의되어 있습니다. 새 공유 모듈이 추가되었지만 리졸버 테스트는 동일 기능의 로컬 헬퍼를 계속 정의합니다. 픽스처 동작이 갈라질 수 있습니다.
tests/test_npm_workspace_install_root.py#L15-L45:_git,_write_json,_commit을 제거하고tests/npm_workspace_test_support.py의run_git,write_json,commit_all을 import하십시오.tests/npm_workspace_test_support.py#L10-L32: 테스트가 이 모듈을 사용하지 않는다면 모듈을 삭제하십시오.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/test_npm_workspace_install_root.py` around lines 15 - 45, Remove the duplicate _git, _write_json, and _commit helpers from tests/test_npm_workspace_install_root.py lines 15-45, import and use run_git, write_json, and commit_all from tests/npm_workspace_test_support.py instead, updating all call sites. Keep tests/npm_workspace_test_support.py lines 10-32 because it becomes the shared implementation; delete that module only if no tests use it after the migration.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/opencode-review-dispatch.yml:
- Around line 1249-1268: Redirect all four diagnostic echo calls in
resolve_npm_package_root to stderr so they remain visible when stdout is
captured by install_package_dependencies. Apply the same >&2 redirection to all
four diagnostic echo calls in resolve_npm_install_root; no other behavior should
change.
In `@tests/test_npm_workspace_install_root.py`:
- Around line 454-487: _workspace_patterns의 미지원 선언 분기를 직접 검증하는 테스트를 추가하십시오.
workspaces 인자로 list/dict가 아닌 값을 전달하는 경우와 packages 키가 없는 dict를 전달하는 경우를 각각 테스트하고,
두 경우 모두 기대하는 오류가 발생하는지 확인하십시오. _validated_cli_output 관련 분기는 기존 테스트로 커버되므로 변경하지
마십시오.
---
Nitpick comments:
In `@tests/test_npm_workspace_install_root.py`:
- Around line 15-45: Remove the duplicate _git, _write_json, and _commit helpers
from tests/test_npm_workspace_install_root.py lines 15-45, import and use
run_git, write_json, and commit_all from tests/npm_workspace_test_support.py
instead, updating all call sites. Keep tests/npm_workspace_test_support.py lines
10-32 because it becomes the shared implementation; delete that module only if
no tests use it after the migration.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 36c4fa6f-b7c9-4288-8723-7377cd89ad82
📒 Files selected for processing (10)
.github/workflows/codeql-pr.yml.github/workflows/opencode-review-dispatch.yml.github/workflows/scheduled-security-scan.ymlrequirements-strix-ci-hashes.txtrequirements-strix-ci.txtscripts/ci/npm_workspace_install_root.pytests/npm_workspace_test_support.pytests/test_npm_workspace_install_root.pytests/test_npm_workspace_install_root_hardening.pytests/test_opencode_agent_contract.py
🚧 Files skipped from review as they are similar to previous changes (1)
- tests/test_npm_workspace_install_root_hardening.py
| echo "::error::Selected npm package directory is not a safe repository-relative path." | ||
| return 1 | ||
| ;; | ||
| *) | ||
| candidate_root="$COVERAGE_SOURCE_WORKDIR/$selected_package_dir" | ||
| ;; | ||
| esac | ||
| if [ ! -d "$candidate_root" ] || [ -L "$candidate_root" ]; then | ||
| echo "::error::Selected npm package directory must be a real non-symlink directory." | ||
| return 1 | ||
| fi | ||
| candidate_root="$(realpath -e -- "$candidate_root")" || { | ||
| echo "::error::Could not canonicalize the selected npm package directory." | ||
| return 1 | ||
| } | ||
| case "$candidate_root" in | ||
| "$COVERAGE_SOURCE_WORKDIR" | "$COVERAGE_SOURCE_WORKDIR"/*) ;; | ||
| *) | ||
| echo "::error::Selected npm package directory escaped the validated coverage worktree." | ||
| return 1 |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
명령 치환으로 호출되는 두 해석 함수가 진단을 stdout으로 출력합니다. install_package_dependencies는 두 함수의 stdout을 결과 값으로 캡처합니다. 따라서 ::error:: 메시지는 로그에 남지 않고 버려집니다.
.github/workflows/opencode-review-dispatch.yml#L1249-L1268:resolve_npm_package_root의echo "::error::..."4곳에>&2를 추가하십시오..github/workflows/opencode-review-dispatch.yml#L1286-L1312:resolve_npm_install_root의echo "::error::..."4곳에>&2를 추가하십시오.
📍 Affects 1 file
.github/workflows/opencode-review-dispatch.yml#L1249-L1268(this comment).github/workflows/opencode-review-dispatch.yml#L1286-L1312
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/opencode-review-dispatch.yml around lines 1249 - 1268,
Redirect all four diagnostic echo calls in resolve_npm_package_root to stderr so
they remain visible when stdout is captured by install_package_dependencies.
Apply the same >&2 redirection to all four diagnostic echo calls in
resolve_npm_install_root; no other behavior should change.
| @pytest.mark.parametrize( | ||
| ("git_output", "match"), | ||
| [ | ||
| ( | ||
| b"100644 blob aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\tpackage.json\0" | ||
| b"100644 blob bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\tpackage.json\0", | ||
| "multiple Git tree entries", | ||
| ), | ||
| (b"malformed\tpackage.json\0", "malformed Git tree metadata"), | ||
| ( | ||
| b"100644 blob aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\tother.json\0", | ||
| "path did not match exactly", | ||
| ), | ||
| ( | ||
| b"120000 blob aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\tpackage.json\0", | ||
| "regular non-symlink Git blob", | ||
| ), | ||
| ], | ||
| ) | ||
| def test_tree_blob_rejects_malformed_or_unsafe_git_metadata( | ||
| tmp_path: Path, | ||
| monkeypatch: pytest.MonkeyPatch, | ||
| git_output: bytes, | ||
| match: str, | ||
| ) -> None: | ||
| """Git tree evidence must be singular, exact, and regular-file metadata.""" | ||
| monkeypatch.setattr(module, "_git", lambda *_args: git_output) | ||
| with pytest.raises(ResolutionError, match=match): | ||
| module._tree_blob( | ||
| tmp_path, | ||
| "a" * 40, | ||
| module.PurePosixPath("package.json"), | ||
| "fixture manifest", | ||
| ) |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Measure branch coverage of the resolver from its own tests.
set -eu
python3 -m pip install --quiet coverage pytest
python3 -m coverage run --branch -m pytest \
tests/test_npm_workspace_install_root.py \
tests/test_npm_workspace_install_root_hardening.py
python3 -m coverage report --show-missing --include='scripts/ci/npm_workspace_install_root.py'Repository: ContextualWisdomLab/.github
Length of output: 203
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- target source ---'
git ls-files 'scripts/ci/npm_workspace_install_root.py' 'tests/test_npm_workspace_install_root.py' 'tests/test_npm_workspace_install_root_hardening.py'
printf '%s\n' '--- source outline ---'
ast-grep outline scripts/ci/npm_workspace_install_root.py --view compact
printf '%s\n' '--- relevant definitions and tests ---'
rg -n -A35 -B8 '_validated_cli_output|_workspace_patterns|resolve_install_root|test_tree_blob_rejects_malformed_or_unsafe_git_metadata' \
scripts/ci/npm_workspace_install_root.py \
tests/test_npm_workspace_install_root.py \
tests/test_npm_workspace_install_root_hardening.pyRepository: ContextualWisdomLab/.github
Length of output: 494
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- relevant definitions and tests ---'
rg -n -A45 -B10 '_validated_cli_output|_workspace_patterns|resolve_install_root|test_tree_blob_rejects_malformed_or_unsafe_git_metadata' \
scripts/ci/npm_workspace_install_root.py \
tests/test_npm_workspace_install_root.py \
tests/test_npm_workspace_install_root_hardening.pyRepository: ContextualWisdomLab/.github
Length of output: 50383
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- direct helper coverage candidates ---'
rg -n '_validated_cli_output|_workspace_patterns|main\(' \
tests scripts/ci/npm_workspace_install_root.py
printf '%s\n' '--- CLI and workspace tests ---'
sed -n '175,240p' tests/test_npm_workspace_install_root_hardening.py
sed -n '330,390p' tests/test_npm_workspace_install_root.py
printf '%s\n' '--- helper implementations ---'
sed -n '145,195p' scripts/ci/npm_workspace_install_root.py
sed -n '340,380p' scripts/ci/npm_workspace_install_root.pyRepository: ContextualWisdomLab/.github
Length of output: 21455
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- all workspace fixture inputs ---'
rg -n -C2 'workspaces|patterns=' tests/test_npm_workspace_install_root.py tests/test_npm_workspace_install_root_hardening.py
printf '%s\n' '--- relevant test bodies ---'
sed -n '210,235p' tests/test_npm_workspace_install_root_hardening.py
sed -n '350,410p' tests/test_npm_workspace_install_root.pyRepository: ContextualWisdomLab/.github
Length of output: 11348
_workspace_patterns의 미지원 선언 분기를 직접 테스트하십시오.
workspaces가 list/dict가 아니거나 dict에 packages 키가 없는 경우를 _workspace_patterns에 직접 전달하는 테스트를 추가하십시오. _validated_cli_output의 두 오류 분기는 기존 CLI 제어 문자 테스트와 정규화 경로 테스트에서 이미 실행됩니다.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@tests/test_npm_workspace_install_root.py` around lines 454 - 487,
_workspace_patterns의 미지원 선언 분기를 직접 검증하는 테스트를 추가하십시오. workspaces 인자로 list/dict가
아닌 값을 전달하는 경우와 packages 키가 없는 dict를 전달하는 경우를 각각 테스트하고, 두 경우 모두 기대하는 오류가 발생하는지
확인하십시오. _validated_cli_output 관련 분기는 기존 테스트로 커버되므로 변경하지 마십시오.
Source: Coding guidelines
What
Add a fail-closed resolver for nested npm workspace packages and wire it into the central OpenCode coverage sandbox. A selected package such as
apps/desktopcan now install from its nearest validated npm workspace lock owner instead of requiring an invalid duplicate lockfile beside every workspace package.Why
BandScope correctly owns one root npm workspace lock. The previous central coverage path selected
apps/desktop, attempted isolated installation there, failed to materialize Vitest, and consequently blocked every current-head approval. The implementation resolves and validates the ancestor lock owner before running a lifecycle-disabled, networkless workspace-scopednpm ci.Security boundary
packagesentry.Verification contract
The current head includes a repair for a malformed hardening test that previously prevented valid test collection. Earlier pass-count claims are therefore superseded; exact-current-head GitHub checks are authoritative.
Before merge, the current head must prove all of the following:
apps/desktopto the repository root (.);git diff --checkpasses;The final PR contains only canonical workflows, dependency locks, resolver code, and permanent contract tests. The Strix CI lock is refreshed to
aiohttp==3.14.3andcryptography==50.0.0to remove current high-severity audit blockers.Product impact
This removes the organization-level coverage deadlock for BandScope and other modular npm workspace repositories while preserving standalone package selection and centralized governance.
Summary by CodeRabbit
새로운 기능
개선 사항
테스트