Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
cc6a54a
fix(coverage): add trusted npm workspace lock resolver
seonghobae Aug 3, 2026
fb013f8
test(coverage): cover npm workspace lock resolution
seonghobae Aug 3, 2026
dc2fcbf
fix(coverage): bind npm workspace ownership to validated git blobs
seonghobae Aug 3, 2026
840d1d0
test(coverage): prove npm workspace resolver trust boundaries
seonghobae Aug 3, 2026
9f524d6
chore(coverage): bootstrap focused workspace wiring
seonghobae Aug 3, 2026
1f44fd6
chore(ci): retrigger workspace coverage bootstrap
seonghobae Aug 3, 2026
a7f34fd
test(coverage): specify npm workspace trust hardening
seonghobae Aug 3, 2026
838346a
ci: exercise npm workspace resolver hardening
seonghobae Aug 3, 2026
18c65da
ci: expose focused resolver tests on pull requests
seonghobae Aug 3, 2026
a281b36
chore(coverage): publish bounded bootstrap diagnostics
seonghobae Aug 3, 2026
b7b2a54
test(coverage): fix resolver fixture initialization
seonghobae Aug 3, 2026
af14b7b
ci: run coverage bootstrap on same-repo PR synchronize
seonghobae Aug 3, 2026
b9976fb
fix(coverage): harden npm workspace glob and CLI contracts
seonghobae Aug 3, 2026
99a96bd
test(coverage): close resolver branch coverage gaps
seonghobae Aug 3, 2026
ab50cc3
chore(coverage): trigger one-shot workspace wiring
seonghobae Aug 3, 2026
2623938
fix(coverage): trust validated HEAD workspace ownership
seonghobae Aug 3, 2026
89a6ff0
test(coverage): accept bounded HEAD workspace updates
seonghobae Aug 3, 2026
ab51380
test(coverage): harden anchored workspace matching
seonghobae Aug 3, 2026
fbc0a91
fix(coverage): scope offline npm installs to selected workspace
seonghobae Aug 3, 2026
f1ee192
ci(coverage): verify workspace wiring before commit
seonghobae Aug 3, 2026
05d3b84
fix(coverage): honor Git clean filters when validating npm workspace …
seonghobae Aug 3, 2026
96dade5
test(coverage): pin path-aware npm worktree hashing
seonghobae Aug 3, 2026
72f4088
fix(coverage): preserve Git path filters in generated npm lock verifi…
seonghobae Aug 3, 2026
d573869
fix(ci): pass bootstrap result through the step environment
seonghobae Aug 3, 2026
ad8a9ae
chore(coverage): trigger verified workspace wiring bootstrap
seonghobae Aug 3, 2026
558d448
chore(ci): retrigger verified npm workspace bootstrap
seonghobae Aug 3, 2026
d0323b1
chore(ci): retrigger verified npm workspace wiring
seonghobae Aug 3, 2026
b7f12da
chore(ci): add bounded PR 703 final repair
seonghobae Aug 3, 2026
69e5fcc
chore(ci): trigger bounded PR 703 final repair
seonghobae Aug 3, 2026
a70578a
ci(pr703): generate reviewed repair artifact without write credentials
seonghobae Aug 3, 2026
d3abaa7
ci(pr703): run final repair validation for the pull request
seonghobae Aug 3, 2026
8e5b5fd
fix(pr703): emit valid structured invocation contract
seonghobae Aug 3, 2026
20c3ce6
fix(pr703): parse the complete nested npm case contract
seonghobae Aug 3, 2026
04a23b7
fix(pr703): keep generated nested-case delimiter syntactically valid
seonghobae Aug 3, 2026
309ed34
fix(pr703): assert every npm failure path in the complete case
seonghobae Aug 3, 2026
accbf69
fix(pr703): assert all bounded npm returns
seonghobae Aug 4, 2026
964ea61
fix(pr703): publish verified canonical final state
seonghobae Aug 4, 2026
2661025
ci(pr703): preserve verified canonical final state
seonghobae Aug 4, 2026
e292fa8
fix(coverage): finalize npm workspace lock resolution
seonghobae Aug 4, 2026
cf65dee
ci(deps): refresh vulnerable Strix dependency lock
seonghobae Aug 4, 2026
6ad0ffe
fix(deps): update Strix cryptography and aiohttp
github-actions[bot] Aug 4, 2026
8af1d77
chore(ci): remove temporary Strix lock refresher
seonghobae Aug 4, 2026
f6acae6
fix(coverage): prepare resolver review cleanup
seonghobae Aug 4, 2026
40d794a
ci(coverage): verify resolver review cleanup
seonghobae Aug 4, 2026
6b43ac5
refactor(coverage): address npm resolver review feedback
seonghobae Aug 4, 2026
6e29a57
test(coverage): repair resolver hardening regression
seonghobae Aug 4, 2026
e9a4583
test(coverage): restore complete resolver contract suite
seonghobae Aug 4, 2026
bb129fe
fix(security): align scheduled CodeQL action version
seonghobae Aug 4, 2026
e23cba9
chore(coverage): remove unrelated scheduled security drift
seonghobae Aug 4, 2026
b824259
fix(ci): align CodeQL action refs for coverage
seonghobae Aug 4, 2026
c26f40c
ci(repair): verify PR 703 review feedback
seonghobae Aug 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/codeql-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,13 @@ jobs:
ref: ${{ github.event.pull_request.head.sha }}

- name: Initialize CodeQL
uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
uses: github/codeql-action/init@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
uses: github/codeql-action/analyze@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
with:
category: "/language:${{ matrix.language }}"
upload: false
Expand Down Expand Up @@ -197,13 +197,13 @@ jobs:
ref: ${{ format('refs/pull/{0}/merge', github.event.pull_request.number) }}

- name: Initialize CodeQL
uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
uses: github/codeql-action/init@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
uses: github/codeql-action/analyze@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
with:
category: "/language:${{ matrix.language }}-merge"
upload: false
Expand Down
181 changes: 152 additions & 29 deletions .github/workflows/opencode-review-dispatch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1234,32 +1234,119 @@ jobs:

writable_npm_cache_dir=""
writable_pnpm_store_dir=""
resolve_npm_package_root() {
local selected_package_dir="$1"
local candidate_root

case "$selected_package_dir" in
"$COVERAGE_SOURCE_WORKDIR" | "$COVERAGE_SOURCE_WORKDIR"/*)
candidate_root="$selected_package_dir"
;;
.)
candidate_root="$PWD"
;;
"" | /* | ../* | */../* | */.. | *\\* | *$'\n'* | *$'\r'*)
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
Comment on lines +1249 to +1268

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.

;;
esac
printf '%s\n' "$candidate_root"
}

resolve_npm_install_root() {
local selected_package_dir="$1"
local relative_root
local candidate_root

if ! relative_root="$(
python3 -I "$GITHUB_WORKSPACE/scripts/ci/npm_workspace_install_root.py" \
--repo-root "$COVERAGE_SOURCE_WORKDIR" \
--package-dir "$selected_package_dir" \
--base-sha "$PR_BASE_SHA" \
--head-sha "$PR_HEAD_SHA"
)"; then
echo "::error::Could not resolve a validated npm workspace lock owner for ${selected_package_dir}."
return 1
fi
case "$relative_root" in
.)
candidate_root="$COVERAGE_SOURCE_WORKDIR"
;;
"" | /* | ../* | */../* | */.. | *\\* | *$'\n'* | *$'\r'*)
echo "::error::Resolved npm workspace lock owner is not a safe repository-relative path."
return 1
;;
*)
candidate_root="$COVERAGE_SOURCE_WORKDIR/$relative_root"
;;
esac
if [ ! -d "$candidate_root" ] || [ -L "$candidate_root" ]; then
echo "::error::Resolved npm workspace lock owner must be a real non-symlink directory."
return 1
fi
candidate_root="$(realpath -e -- "$candidate_root")" || {
echo "::error::Could not canonicalize the resolved npm workspace lock owner."
return 1
}
case "$candidate_root" in
"$COVERAGE_SOURCE_WORKDIR" | "$COVERAGE_SOURCE_WORKDIR"/*) ;;
*)
echo "::error::Resolved npm workspace lock owner escaped the validated coverage worktree."
return 1
;;
esac
printf '%s\n' "$candidate_root"
}

trusted_npm_lock_is_materialized() {
local install_root="$1"
local relative_dir
local lock_name
local relative_lock
local head_blob
local worktree_blob
local trust_manifest

case "$PWD" in
case "$install_root" in
"$COVERAGE_SOURCE_WORKDIR")
relative_dir=""
;;
"$COVERAGE_SOURCE_WORKDIR"/*)
relative_dir="${PWD#"$COVERAGE_SOURCE_WORKDIR"/}"
relative_dir="${install_root#"$COVERAGE_SOURCE_WORKDIR"/}"
;;
*)
echo "::error::npm project directory escaped the validated coverage worktree."
echo "::error::npm install root escaped the validated coverage worktree."
return 1
;;
esac
if [ -f npm-shrinkwrap.json ] && [ ! -L npm-shrinkwrap.json ]; then
if [ ! -d "$install_root" ] || [ -L "$install_root" ]; then
echo "::error::npm install root must be a real non-symlink directory."
return 1
fi
if [ -f "$install_root/npm-shrinkwrap.json" ] && [ ! -L "$install_root/npm-shrinkwrap.json" ]; then
lock_name="npm-shrinkwrap.json"
elif [ -f package-lock.json ] && [ ! -L package-lock.json ]; then
elif [ -f "$install_root/package-lock.json" ] && [ ! -L "$install_root/package-lock.json" ]; then
lock_name="package-lock.json"
else
echo "::error::Current npm lock must be a regular non-symlink package-lock.json or npm-shrinkwrap.json."
echo "::error::Resolved npm lock owner must contain a regular non-symlink package-lock.json or npm-shrinkwrap.json."
return 1
fi
relative_lock="${relative_dir:+${relative_dir}/}${lock_name}"
Expand All @@ -1269,8 +1356,7 @@ jobs:
return 1
}
worktree_blob="$(
trusted_git hash-object --no-filters -- \
"$COVERAGE_SOURCE_WORKDIR/$relative_lock"
trusted_git hash-object --path="$relative_lock" -- "$install_root/$lock_name"
)" || {
echo "::error::Could not hash current npm lock ${relative_lock}."
return 1
Expand All @@ -1297,7 +1383,7 @@ jobs:
and .lock_blob == $lock_blob
and (.revision_sha == $base_sha or .revision_sha == $head_sha)
)' "$trust_manifest" >/dev/null; then
echo "::error::Current npm lock ${relative_lock} was not hash-bounded and materialized from the validated base or HEAD."
echo "::error::Current npm lock ${relative_lock} was not hash-bounded and materialized from the validated base or HEAD with an exact receipt."
return 1
fi
}
Expand Down Expand Up @@ -1388,34 +1474,68 @@ jobs:

install_package_dependencies() {
local package_runner="$1"
local selected_package_dir="${2:-$PWD}"
case "$package_runner" in
npm)
if [ -f package-lock.json ] || [ -f npm-shrinkwrap.json ]; then
if ! trusted_npm_lock_is_materialized || ! prepare_writable_npm_cache; then
append "### JavaScript/TypeScript dependencies (npm)"
append ""
append "- Result: FAIL"
append "- Reason: the current npm lock is not hash-bounded to the validated base or HEAD, or the trusted npm cache is unavailable."
append ""
failures=$((failures + 1))
return 0
fi
run_and_capture "JavaScript/TypeScript dependencies (npm offline ci, lifecycle hooks disabled)" \
npm ci \
--offline \
--ignore-scripts \
--cache "$writable_npm_cache_dir" \
--no-audit \
--no-fund
else
local selected_package_root
local npm_install_root
local npm_workspace_selector=""
local npm_workspace_args=()

if ! selected_package_root="$(resolve_npm_package_root "$selected_package_dir")" ||
! npm_install_root="$(resolve_npm_install_root "$selected_package_root")"; then
append "### JavaScript/TypeScript dependencies (npm)"
append ""
append "- Result: FAIL"
append "- Reason: no validated local or ancestor npm workspace lock owns the selected package."
append ""
failures=$((failures + 1))
return 0
fi
if ! trusted_npm_lock_is_materialized "$npm_install_root" || ! prepare_writable_npm_cache; then
append "### JavaScript/TypeScript dependencies (npm)"
append ""
append "- Result: FAIL"
append "- Reason: offline npm coverage requires a tracked package-lock.json or npm-shrinkwrap.json at the validated base and current head."
append "- Reason: the resolved npm lock lacks an exact validated base-or-HEAD receipt, or the trusted npm cache is unavailable."
append ""
failures=$((failures + 1))
return 0
fi

case "$selected_package_root" in
"$npm_install_root")
;;
"$npm_install_root"/*)
npm_workspace_selector="${selected_package_root#"$npm_install_root"/}"
case "$npm_workspace_selector" in
"" | /* | ../* | */../* | */.. | *\\* | *$'\n'* | *$'\r'*)
append "### JavaScript/TypeScript dependencies (npm)"
append ""
append "- Result: FAIL"
append "- Reason: the selected npm workspace path is not a safe lock-root-relative selector."
append ""
failures=$((failures + 1))
return 0
;;
esac
npm_workspace_args=(--workspace "$npm_workspace_selector")
;;
*)
append "### JavaScript/TypeScript dependencies (npm)"
append ""
append "- Result: FAIL"
append "- Reason: the selected npm package is outside its validated lock owner."
append ""
failures=$((failures + 1))
return 0
;;
esac

run_and_capture "JavaScript/TypeScript dependencies (npm workspace-root offline ci, lifecycle hooks disabled)" \
bash -c 'cd "$1" && shift && exec "$@"' \
bash "$npm_install_root" \
npm ci --offline --ignore-scripts --cache "$writable_npm_cache_dir" --no-audit --no-fund \
"${npm_workspace_args[@]}"
;;
pnpm)
trusted_pnpm_lock_matches_base
Expand Down Expand Up @@ -1512,7 +1632,7 @@ jobs:
return 1
fi

install_package_dependencies "$package_runner"
install_package_dependencies "$package_runner" "$package_dir"
package_name="$(jq -r '.name // empty' "${package_dir}/package.json")"
# A named package is not necessarily a workspace member: the default
# single-package Tauri layout (root package.json + src-tauri/) has a
Expand Down Expand Up @@ -2329,6 +2449,7 @@ jobs:
ContextualWisdomLab/.github:scripts/ci/changed_file_syntax_gate.py | \
ContextualWisdomLab/.github:scripts/ci/javascript_coverage_gate.py | \
ContextualWisdomLab/.github:scripts/ci/materialize_base_javascript_packages.py | \
ContextualWisdomLab/.github:scripts/ci/npm_workspace_install_root.py | \
ContextualWisdomLab/.github:scripts/ci/opencode_review_approve_gate.sh | \
ContextualWisdomLab/.github:scripts/ci/pr_head_replay_guard.py | \
ContextualWisdomLab/.github:scripts/ci/pr_review_merge_scheduler.py | \
Expand All @@ -2339,6 +2460,8 @@ jobs:
ContextualWisdomLab/.github:tests/test_changed_file_syntax_gate.py | \
ContextualWisdomLab/.github:tests/test_javascript_coverage_gate.py | \
ContextualWisdomLab/.github:tests/test_materialize_base_javascript_packages.py | \
ContextualWisdomLab/.github:tests/test_npm_workspace_install_root.py | \
ContextualWisdomLab/.github:tests/test_npm_workspace_install_root_hardening.py | \
ContextualWisdomLab/.github:tests/test_opencode_agent_contract.py | \
ContextualWisdomLab/.github:tests/test_opencode_model_pool_runner.py | \
ContextualWisdomLab/.github:tests/test_pr_head_replay_guard.py | \
Expand Down
Loading
Loading