Skip to content

fix(coverage): resolve npm workspace lock owners - #703

Draft
seonghobae wants to merge 51 commits into
mainfrom
fix/npm-workspace-coverage-root
Draft

fix(coverage): resolve npm workspace lock owners#703
seonghobae wants to merge 51 commits into
mainfrom
fix/npm-workspace-coverage-root

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

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/desktop can 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-scoped npm ci.

Security boundary

  • Resolve ownership from the exact validated HEAD tree and matching worktree.
  • Require an npm v2/v3 lock with an exact packages entry.
  • Match anchored workspace patterns while rejecting path traversal, unsafe glob syntax, control characters, and symlinks.
  • Hash worktree files with Git path-aware normalization.
  • Require an exact validated base-or-HEAD materialization receipt.
  • Keep npm installation offline, lifecycle-disabled, audit-disabled, and bounded to the selected workspace.
  • Pass the npm command as structured argv rather than interpolated shell code.
  • Keep the recursive workspace matcher in one bounded module-level cache.
  • Leave no PR-specific bootstrap workflow or self-modifying helper in the final tree.

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:

  • focused resolver and hardening tests pass;
  • resolver statement coverage is 100%;
  • resolver docstring coverage is 100%;
  • Python compile and Ruff checks pass for the resolver and shared fixture helpers;
  • a real temporary npm workspace fixture resolves apps/desktop to the repository root (.);
  • git diff --check passes;
  • security, dependency, CodeQL, Semgrep, secret-scan, SBOM, and Scorecard checks pass.

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.3 and cryptography==50.0.0 to 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

  • 새로운 기능

    • 검증된 npm workspace 기준으로 안전한 의존성 설치 경로를 자동 결정합니다.
    • workspace, lockfile, Git 변경 사항을 확인해 유효하지 않거나 안전하지 않은 설치를 차단합니다.
    • workspace 루트에서 오프라인 의존성 설치와 선택적 workspace 빌드를 지원합니다.
  • 개선 사항

    • CI 보안 분석 도구 버전을 업데이트했습니다.
    • CI 의존성 버전과 무결성 해시를 갱신했습니다.
  • 테스트

    • 정상적인 workspace 탐색과 다양한 경로·lockfile·Git 오류 상황에 대한 검증을 강화했습니다.

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e22f68cf-878a-4fde-90f1-65e73cfcabd8

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Git 기반 npm workspace 설치 루트 해석기와 보안 검증 테스트를 추가했습니다. CI는 검증된 workspace 루트에서 오프라인 설치를 수행합니다. CodeQL action과 Python dependency lock도 갱신했습니다.

Changes

npm workspace installation

Layer / File(s) Summary
설치 루트 해석 및 경로 검증
scripts/ci/npm_workspace_install_root.py
Git revision, worktree, workspace 패턴, lockfile을 검증하고 설치 루트를 반환합니다.
해석기 계약 및 보안 검증
tests/npm_workspace_test_support.py, tests/test_npm_workspace_install_root.py, tests/test_npm_workspace_install_root_hardening.py
정상 동작과 경로 탈출, symlink, malformed metadata, 잘못된 CLI 출력을 검증합니다.
CI 오프라인 설치 연결
.github/workflows/opencode-review-dispatch.yml, tests/test_opencode_agent_contract.py
검증된 루트에서 offline npm ci를 실행하고 workspace selector, lock receipt, 캐시 조건을 검증합니다.

CI 및 Python dependency maintenance

Layer / File(s) Summary
CodeQL action 갱신
.github/workflows/codeql-pr.yml, .github/workflows/scheduled-security-scan.yml
CodeQL initanalyze action 참조를 v4.37.4로 갱신했습니다.
Python dependency lock 갱신
requirements-strix-ci.txt, requirements-strix-ci-hashes.txt
여러 dependency 버전과 hash를 갱신하고 pyopenssl, typer를 제거했으며 semver를 추가했습니다.

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 실행
Loading

Possibly related PRs

Suggested labels: dependencies, github_actions

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 98.18% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 npm workspace lock owner를 해결하는 주요 변경 사항을 명확하고 간결하게 설명합니다.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/npm-workspace-coverage-root

Comment @coderabbitai help to get the list of available commands.

Copy link
Copy Markdown
Contributor Author

@jules Please finish this focused central coverage fix on the current branch.

Wire scripts/ci/npm_workspace_install_root.py into .github/workflows/opencode-review-dispatch.yml without weakening any trust boundary:

  1. In install_package_dependencies() for npm, resolve the selected package's install root with the trusted helper using --repo-root "$COVERAGE_SOURCE_WORKDIR" --package-dir "$PWD".
  2. Make trusted_npm_lock_is_materialized() accept that resolved absolute install root, derive the repository-relative lock path from it, and preserve the current HEAD blob/hash-bounded manifest checks.
  3. Run lifecycle-disabled offline npm ci from the resolved lock owner, while continuing to run the package's test/coverage script from the originally selected nested package directory.
  4. Fail closed when no validated local/ancestor workspace lock owns the package. Do not add a package-local duplicate lock, use network fallback, run lifecycle hooks, or relax path/symlink/hash checks.
  5. Add the new resolver and its test file to the central fallback changed-file allowlist.
  6. Update tests/test_opencode_agent_contract.py and any shell/security contract tests for the workspace-root invocation.

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 git diff --check, then push the focused changes.

Copy link
Copy Markdown
Contributor Author

@jules While completing the workflow wiring, also close these resolver trust/correctness gaps on the same branch:

  • Do not use Python fnmatch directly for npm workspace patterns because * can match / and over-authorize deeper packages. Implement repository-path segment semantics: * matches one segment, ** may match multiple segments, and reject unsupported/ambiguous patterns fail-closed. Add positive and negative nested-path tests.
  • Reject symlinks in every existing path component from repo_root through package_dir and through the selected lock-owner manifest/lock, not only a symlink at the final package directory. Add an ancestor-symlink escape test.
  • Fix the test fixture helper so an explicit empty workspace list/object is preserved instead of being replaced by defaults (workspaces if workspaces is not None else ...). Add an empty-declaration rejection case.
  • Validate lockfile shape/version conservatively and ensure the exact workspace package entry is a JSON object. If both npm-shrinkwrap.json and package-lock.json exist, apply npm's deterministic precedence and test it.
  • Keep all paths repository-relative/canonical, reject newline/control characters in CLI output, and verify the workflow maps ./relative output beneath the validated coverage tree before use.

Keep the PR focused on the resolver, workflow integration, contracts/tests, and one accurate 2026 journal entry.

Copy link
Copy Markdown
Contributor Author

@jules Complete this PR now rather than leaving the resolver unwired.

Required implementation:

  1. In .github/workflows/opencode-review-dispatch.yml, resolve each selected npm package directory through scripts/ci/npm_workspace_install_root.py before dependency installation.
  2. Validate the resolved lock-owner path against the trusted worktree, current PR_HEAD_SHA, and /opt/javascript-package-locks/manifest.json; do not weaken the existing registry/integrity or non-symlink checks.
  3. Run npm ci --offline --ignore-scripts from the validated lock owner. For a nested workspace, target only the selected package with --workspace <repo-relative-package-dir>; retain standalone-package behavior.
  4. Use the same resolver for Tauri frontend dependency installation/build so apps/desktop/src-tauri can build from the root workspace lock.
  5. Add contract tests covering BandScope's root workspaces: ["apps/*", "packages/*"] + apps/desktop layout, a standalone npm package, workspace mismatch, missing lock packages entry, symlink/path escape, and unchanged local-lock behavior.
  6. Rebase/merge current main (5983b41ace75040c1d81818171ca7d0f3653254e) first so the recently merged uv-lock coverage support remains intact.
  7. Run the focused resolver tests, workflow/contract tests, 100% line coverage for the changed Python modules, 100% docstrings, and git diff --check.

Keep the patch fail-closed and limited to the central coverage path. Push the completed implementation to this PR branch.

@seonghobae
seonghobae enabled auto-merge (squash) August 3, 2026 02:33

Copy link
Copy Markdown
Contributor Author

One fail-closed bug remains in the current resolver head 8d1da716c2e4bac968df16a525bc3ecd002d1d6e: PurePosixPath.match() is suffix-oriented rather than repository-root anchored. For example, PurePosixPath("foo/apps/desktop").match("apps/*") is true, so an ancestor declaring only apps/* could incorrectly claim foo/apps/desktop if the lock map contains that exact path.

Replace _is_declared_workspace with an anchored, path-segment-aware matcher: ordinary *, ?, and character classes must stay within one segment; ** may consume zero or more complete segments; the entire package path must be consumed from the first segment. Add regression tests proving apps/* accepts apps/desktop but rejects both foo/apps/desktop and apps/team/desktop, while apps/**/desktop accepts the intended nested form. Keep negated and traversal patterns rejected. Please include this in the same workflow-wiring commit and retain 100% resolver coverage.

Copy link
Copy Markdown
Contributor Author

A second compatibility/security-contract issue is visible in the current resolver: _validated_lock() requires the npm lock blob to be identical at base and HEAD, and ancestor manifests are also required to be identical. That regresses the existing bounded-HEAD npm contract in materialize_base_javascript_packages.py, which intentionally validates changed HEAD locks (registry.npmjs.org-only, SHA-512 integrity, safe links), materializes them, and records revision_sha=head_sha plus the exact lock_blob in /opt/javascript-package-locks/manifest.json.

The workspace resolver should establish ownership from the live-validated HEAD tree/worktree and return the lock-owner path; the workflow's existing trusted_npm_lock_is_materialized(resolved_root) must remain the authority that accepts only an exact manifest entry from either validated base or validated HEAD. Do not reject legitimate dependency-update PRs merely because package-lock.json or the workspace declaration changed. Add tests for: unchanged base lock, bounded changed HEAD lock, PR-added workspace package already represented by the HEAD lock map, and rejection when the resolved lock lacks the exact base/HEAD manifest receipt. Preserve the no-network/ignore-scripts boundary.

Copy link
Copy Markdown
Contributor Author

@jules Complete this PR into its final reviewable state. Run scripts/ci/bootstrap_patch_workflow.py against the current branch, verify the intended opencode-review-dispatch.yml and contract-test wiring, remove the temporary bootstrap workflow/script and any PR-number-specific focused workflow that should not land on main, run the focused resolver/coverage/docstring tests plus relevant central workflow contracts, and push the minimal final commit. Do not leave a self-modifying bootstrap path in the merge diff.

Copy link
Copy Markdown
Contributor Author

@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 scripts/ci/bootstrap_patch_workflow.py transformation directly on this branch, update .github/workflows/opencode-review-dispatch.yml and tests/test_opencode_agent_contract.py, remove the temporary bootstrap workflow/script and focused branch-only workflow, run the full relevant contract suite with 100% resolver coverage/docstrings plus workflow shell syntax and git diff --check, then push the final focused diff.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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, _committests/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.pyPurePosixPath 임포트를 제거하거나 이름을 바꾸면, 실제 동작 변경이 없어도 테스트가 실패합니다. 이 파일은 이미 pathlib에서 Path를 임포트합니다. PurePosixPath도 같은 방식으로 임포트하십시오.

♻️ 제안 리팩터링
-from pathlib import Path
+from pathlib import Path, PurePosixPath
         module._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 win

Python 버전을 명시적으로 설정하십시오.

이 파일은 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

📥 Commits

Reviewing files that changed from the base of the PR and between 5983b41 and ecc6134.

📒 Files selected for processing (6)
  • .github/workflows/bootstrap-npm-workspace-wiring.yml
  • .github/workflows/pr703-focused-tests.yml
  • scripts/ci/bootstrap_patch_workflow.py
  • scripts/ci/npm_workspace_install_root.py
  • tests/test_npm_workspace_install_root.py
  • tests/test_npm_workspace_install_root_hardening.py

Comment thread .github/workflows/bootstrap-npm-workspace-wiring.yml Outdated
Comment thread .github/workflows/pr703-focused-tests.yml Outdated
Comment thread scripts/ci/bootstrap_patch_workflow.py Outdated
Comment thread scripts/ci/npm_workspace_install_root.py
@opencode-agent
opencode-agent Bot disabled auto-merge August 3, 2026 04:02

Copy link
Copy Markdown
Contributor Author

@coderabbitai autofix

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

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.

Copy link
Copy Markdown
Contributor Author

@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 .github/workflows/bootstrap-npm-workspace-wiring.yml, .github/workflows/pr703-focused-tests.yml, and scripts/ci/bootstrap_patch_workflow.py. Address all current unresolved review findings, including passing the bootstrap return code through env rather than direct expression interpolation if any bootstrap remains, integrating resolver tests into the normal central test/coverage contract, and making _worktree_blob use path-aware Git clean hashing (git hash-object --path=<repo-relative-path> -- <file>) instead of --no-filters. Preserve fail-closed path, workspace, lock receipt, and symlink checks. Run the focused resolver tests, central workflow contracts, 100% line/docstring coverage, actionlint, and diff checks; push the minimized final diff and resolve only findings actually addressed.

Comment thread .github/workflows/bootstrap-npm-workspace-wiring.yml Fixed
Comment thread .github/workflows/pr703-final-repair.yml Fixed

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Please review the exact current head 6e29a57608a0d739d1750b7229c6e974bd46c225. The latest commit repairs the malformed hardening regression test; all prior inline findings remain addressed, and cancelled exact-head security jobs have been requeued.

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

@seonghobae I will review the current PR head 6e29a57608a0d739d1750b7229c6e974bd46c225. I will verify the workflow wiring, resolver trust boundaries, regression test repair, and relevant contract coverage.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@seonghobae
seonghobae marked this pull request as draft August 4, 2026 06:18
auto-merge was automatically disabled August 4, 2026 06:18

Pull request was converted to draft

@seonghobae
seonghobae marked this pull request as ready for review August 4, 2026 06:20
@seonghobae
seonghobae enabled auto-merge (squash) August 4, 2026 06:20
@seonghobae
seonghobae marked this pull request as draft August 4, 2026 06:49
auto-merge was automatically disabled August 4, 2026 06:49

Pull request was converted to draft

@seonghobae
seonghobae marked this pull request as ready for review August 4, 2026 06:49
@seonghobae
seonghobae enabled auto-merge (squash) August 4, 2026 06:49

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before 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 head e23cba9368b5b7048b62b7c52adbd94bb306ef36.

  • 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"]
Loading

@opencode-agent

opencode-agent Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

OpenCode Review Overview

  • Head SHA: e23cba9368b5b7048b62b7c52adbd94bb306ef36
  • Workflow run: 30886213715
  • Workflow attempt: 1
  • Gate result: REQUEST_CHANGES (approval step)

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 success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before 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 head e23cba9368b5b7048b62b7c52adbd94bb306ef36.

  • 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"]
Loading

@opencode-agent
opencode-agent Bot disabled auto-merge August 4, 2026 07:05

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before 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 head e23cba9368b5b7048b62b7c52adbd94bb306ef36.

  • 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"]
Loading

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.
@seonghobae
seonghobae enabled auto-merge (squash) August 4, 2026 07:39

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Please review exact head b824259d3503fd357bf38ec7ce5a855f67005e1b. The previous central coverage failure was reproduced on the materialized merge tree: test_codeql_action_steps_use_one_version_per_workflow failed because CodeQL init/analyze used v4.37.0 while upload-sarif used v4.37.4. The current head aligns both canonical CodeQL workflows to the immutable v4.37.4 SHA. Focused verification now passes 118 tests; the npm resolver remains at 100% statement and branch coverage.

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

@seonghobae I will review exact head b824259d3503fd357bf38ec7ce5a855f67005e1b. I will check the CodeQL action pin alignment and the central coverage workflow changes.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor Author

@opencode-agent @cwl-noema-review Please independently re-review exact head b824259d3503fd357bf38ec7ce5a855f67005e1b after current-head checks complete. The materialized merge-tree root cause is now fixed and the formal coverage/review results for this head must supersede earlier REQUEST_CHANGES reviews.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
tests/test_npm_workspace_install_root.py (1)

15-45: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Git 픽스처 헬퍼가 두 곳에 중복 정의되어 있습니다. 새 공유 모듈이 추가되었지만 리졸버 테스트는 동일 기능의 로컬 헬퍼를 계속 정의합니다. 픽스처 동작이 갈라질 수 있습니다.

  • tests/test_npm_workspace_install_root.py#L15-L45: _git, _write_json, _commit을 제거하고 tests/npm_workspace_test_support.pyrun_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

📥 Commits

Reviewing files that changed from the base of the PR and between ecc6134 and b824259.

📒 Files selected for processing (10)
  • .github/workflows/codeql-pr.yml
  • .github/workflows/opencode-review-dispatch.yml
  • .github/workflows/scheduled-security-scan.yml
  • requirements-strix-ci-hashes.txt
  • requirements-strix-ci.txt
  • scripts/ci/npm_workspace_install_root.py
  • tests/npm_workspace_test_support.py
  • tests/test_npm_workspace_install_root.py
  • tests/test_npm_workspace_install_root_hardening.py
  • tests/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

Comment on lines +1249 to +1268
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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

명령 치환으로 호출되는 두 해석 함수가 진단을 stdout으로 출력합니다. install_package_dependencies는 두 함수의 stdout을 결과 값으로 캡처합니다. 따라서 ::error:: 메시지는 로그에 남지 않고 버려집니다.

  • .github/workflows/opencode-review-dispatch.yml#L1249-L1268: resolve_npm_package_rootecho "::error::..." 4곳에 >&2를 추가하십시오.
  • .github/workflows/opencode-review-dispatch.yml#L1286-L1312: resolve_npm_install_rootecho "::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.

Comment on lines +454 to +487
@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",
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 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.py

Repository: 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.py

Repository: 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.py

Repository: 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.py

Repository: 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants