Skip to content

fix(ci): unblock scopeweave central gates (coverage evidence, trivy-fs, Semgrep) - #377

Closed
seonghobae wants to merge 3 commits into
developfrom
claude/contextualwisdomlab-audit-governance-5gowdn
Closed

fix(ci): unblock scopeweave central gates (coverage evidence, trivy-fs, Semgrep)#377
seonghobae wants to merge 3 commits into
developfrom
claude/contextualwisdomlab-audit-governance-5gowdn

Conversation

@seonghobae

@seonghobae seonghobae commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Every scopeweave PR is currently blocked by three pre-existing central-gate failures on develop. Each fails on every PR (repo-wide scans / base materialization), so the whole queue is stuck. This PR remediates all three at base.

1. coverage-evidence (OpenCode review) — stray pnpm-lock.yaml

The central materializer (ContextualWisdomLab/.githubscripts/ci/materialize_base_javascript_packages.py) hard-fails (exit 1) when a base pnpm-lock.yaml exists whose sibling package.json does not pin an exact packageManager: pnpm@X.Y.Z. scopeweave is an npm project (server-tests.yml / fuzz.yml use cache: 'npm' + npm ci; package-lock.json is canonical; no workflow/Dockerfile/compose references pnpm), so the committed pnpm-lock.yaml is a vestigial second lockfile that only misleads the materializer into pnpm mode.

Fix: remove pnpm-lock.yaml. The materializer then reports "no pnpm locks" and the sandbox installs via npm ci --ignore-scripts.

2. trivy-fs — real MEDIUM CVE in @hono/node-server

trivy-fs reports GHSA-frvp-7c67-39w9 (security-severity 5.9) — a Windows path-traversal in @hono/node-server < 2.0.5 (encoded %5C decodes to \, bypassing middleware to read protected static files). scopeweave was pinned to 1.19.14.

Fix: bump the existing runtime dependency (not a new one — the two-runtime-deps contract is preserved) to ^2.0.12. @hono/node-server 2.x declares peerDependencies { hono: "^4" }, already satisfied (hono ^4.12.27), and scopeweave only uses the stable serve({ fetch, port }, cb) entry point. Verified locally (Node v22.22.2): npm install0 vulnerabilities, npm run test:unit and npm run test:api (which boots the Hono app through serve()) both pass.

3. Semgrep — verified false-positive ReDoS in the MS Project parser

Semgrep blocks on one WARNING: detect-non-literal-regexp at cloud-sync.js:743, inside parseMsProjectXml's tag() helper. This is a verified false positive: the non-literal argument name is only ever a hardcoded literal tag ('UID', 'Name', 'OutlineLevel', ...), never user input, and the [^<]* body is a single linear character-class star (no nested quantifiers) → no catastrophic backtracking, no injection surface.

Fix: a narrow, documented nosemgrep directive on the finding line, with the reasoning in-line. The gate is designed to honor suppressions (it filters SARIF results whose suppressions array is non-empty). tests/unit/msproject.test.mjs still passes.

Why this is safe

No central gate is weakened — the pnpm supply-chain rule and Semgrep engine are untouched; the trivy finding is genuinely remediated, not ignored. All three changes align scopeweave with its own documented toolchain and remove real security debt. Local verification: test:unit + test:api pass, npm install reports 0 vulnerabilities.

🤖 Generated with Claude Code

https://claude.ai/code/session_01SEAGtwNR96cia2djq7XFCo

The central OpenCode review's coverage-evidence job materializes base
JavaScript locks with scripts/ci/materialize_base_javascript_packages.py
(in ContextualWisdomLab/.github), which hard-fails (exit 1) when a base
pnpm-lock.yaml exists whose sibling package.json does not pin an exact
`packageManager: pnpm@X.Y.Z`. That aborts every scopeweave PR's coverage
evidence before any test runs.

scopeweave is an npm project: .github/workflows/server-tests.yml and
fuzz.yml use `cache: 'npm'` + `npm ci` + `npm run ...`, package-lock.json is
the canonical lock, and no workflow, Dockerfile, or compose file references
pnpm. The committed pnpm-lock.yaml is a vestigial second lockfile that only
misleads the central materializer into pnpm mode.

Removing it lets the central materializer report "no pnpm locks" and exit
cleanly, then the coverage sandbox installs via the npm path
(`npm ci --ignore-scripts` when package-lock.json is present). No central gate
is weakened; this aligns the repo with its own documented and enforced npm
toolchain and removes lockfile-drift risk between two competing lockfiles.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEAGtwNR96cia2djq7XFCo
@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@seonghobae, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 7 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ec68b243-6085-4aff-888a-65def24b2460

📥 Commits

Reviewing files that changed from the base of the PR and between a756b7e and de680cd.

⛔ Files ignored due to path filters (2)
  • package-lock.json is excluded by !**/package-lock.json
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (2)
  • cloud-sync.js
  • package.json

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

claude added 2 commits July 29, 2026 23:08
…39w9

The central trivy-fs security gate reports a real MEDIUM finding
(security-severity 5.9) on scopeweave: @hono/node-server 1.19.14 is affected by
GHSA-frvp-7c67-39w9 (Windows path-traversal — an encoded backslash %5C in the
request path decodes to `\`, which the Windows path resolver treats as a
separator, letting an attacker bypass middleware and read static files that
should be protected). The advisory's first patched release is 2.0.5.

Bump the existing runtime dependency (not a new one — scopeweave's two-runtime-
dependency contract is preserved) to ^2.0.12. @hono/node-server 2.x declares
peerDependencies { hono: "^4" }, which scopeweave already satisfies
(hono ^4.12.27), and scopeweave only uses the stable `serve({ fetch, port }, cb)`
entry point, unchanged across the 1.x -> 2.x major.

Verified locally on Node v22.22.2:
- npm install -> found 0 vulnerabilities
- npm run test:unit -> all pure-math suites pass
- npm run test:api -> API smoke + rate-limit tests pass (boots the Hono app
  through @hono/node-server serve(), the exact 2.x-compatibility surface)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEAGtwNR96cia2djq7XFCo
…ct parser

The central Semgrep SAST gate blocks scopeweave PRs on a single WARNING-level
finding: javascript.lang.security.audit.detect-non-literal-regexp at
cloud-sync.js:743, inside parseMsProjectXml's `tag()` helper.

This is a verified false positive. The non-literal RegExp argument `name` is
only ever a hardcoded literal tag from this function ('UID', 'Name',
'OutlineLevel', 'PercentComplete', 'PredecessorUID', ...), never user input, so
the compiled pattern is fixed. The captured body `[^<]*` is a single linear
character-class star with no nested or overlapping quantifiers, so it cannot
backtrack catastrophically even on adversarial XML `block` input — there is no
ReDoS or regex-injection surface.

Add a narrow, documented `nosemgrep` directive on the finding line (the gate is
designed to honor suppressions: it filters SARIF results whose suppressions
array is non-empty). No behavior change; the MS Project import tests
(tests/unit/msproject.test.mjs) still pass. The gate is not weakened — only this
one audited false positive is annotated, with the reasoning in-line.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEAGtwNR96cia2djq7XFCo
@seonghobae seonghobae changed the title ci: remove stray pnpm-lock.yaml so central coverage evidence passes fix(ci): unblock scopeweave central gates (coverage evidence, trivy-fs, Semgrep) Jul 29, 2026

@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 de680cd002392f436362d129d6a64a1c0163ac90.

  • Head SHA: de680cd002392f436362d129d6a64a1c0163ac90

  • Workflow run: 30501351847

  • Workflow attempt: 1

Coverage evidence

Coverage evidence job did not run or did not publish coverage evidence.

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Changed file (4 files)"]
  S1 --> I1["repository behavior"]
  I1 --> R1["Review risk: Changed file (4 files)"]
  R1 --> V1["required checks"]
Loading

@opencode-agent

Copy link
Copy Markdown
Contributor

OpenCode Review Overview

  • Head SHA: de680cd002392f436362d129d6a64a1c0163ac90
  • Workflow run: 30501351847
  • 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 de680cd002392f436362d129d6a64a1c0163ac90.

  • Head SHA: de680cd002392f436362d129d6a64a1c0163ac90

  • Workflow run: 30501351847

  • Workflow attempt: 1

Coverage evidence

Coverage evidence job did not run or did not publish coverage evidence.

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Changed file (4 files)"]
  S1 --> I1["repository behavior"]
  I1 --> R1["Review risk: Changed file (4 files)"]
  R1 --> V1["required checks"]
Loading

Copy link
Copy Markdown
Contributor Author

coverage-evidence blocker is a base-fix bootstrap, not a head-side defect

OpenCode's REQUEST_CHANGES on de680cd is driven solely by coverage-evidence: failure. The job log for run 30501351847 shows the failure is at base materialization, before any test runs:

PR_BASE_SHA: a756b7e (develop)   PR_HEAD_SHA: de680cd
##[error]Could not materialize base JavaScript package locks: trusted base
package manifest package.json must declare an exact pnpm packageManager version

scripts/ci/materialize_base_javascript_packages.py reads the base SHA, and develop still contains the stray root pnpm-lock.yaml that this PR removes. So the fix cannot clear its own coverage-evidence until it is on develop — the same base-fix bootstrap that required an admin bypass-merge for the central coverage fixes #642–647 earlier today. Base history is immutable from the PR, so there is no head-side change that makes this pass first.

The three head-side changes are verified locally (Node v22.22.2):

  • Removed stray pnpm-lock.yaml — the repo is npm-only (server-tests.yml/fuzz.yml use cache: 'npm' + npm ci; zero pnpm refs anywhere); this is the exact file the base materializer chokes on.
  • @hono/node-server^2.0.12 (remediates trivy-fs MEDIUM GHSA-frvp-7c67-39w9): npm install → 0 vulnerabilities; npm run test:unit and npm run test:api (boots the Hono app via serve()) both pass.
  • nosemgrep on cloud-sync.js:743 for the verified false-positive detect-non-literal-regexp (the arg is only ever a hardcoded literal tag; [^<]* is linear): tests/unit/msproject.test.mjs passes.

Resolution: this needs the same bypass-merge path as #642–647. Once it lands on develop, coverage-evidence materializes cleanly for every scopeweave PR (no stray pnpm lock), and the repo's central gates go green org-wide.


Generated by Claude Code

seonghobae pushed a commit that referenced this pull request Jul 30, 2026
… uses npm

Every ScopeWeave PR's OpenCode review is REQUEST_CHANGES because the central
coverage-evidence job fails, which gates approval — blocking the whole PR
train. Root cause is a lockfile-detection asymmetry in the central
ContextualWisdomLab/.github OpenCode dispatch:

- The build-time base materializer (scripts/ci/materialize_base_javascript_packages.py,
  fixed in .github#658) already treats a pnpm-lock.yaml with a sibling
  package-lock.json and no exact `packageManager: pnpm@X.Y.Z` as a VESTIGIAL
  second lockfile and skips pnpm, deferring to the npm path.
- The RUNTIME coverage runner (opencode-review-dispatch.yml select_package_runner)
  does NOT mirror that: it selects pnpm the moment a pnpm-lock.yaml exists, then
  refuses with "Coverage package runner pnpm requires an exact packageManager
  version" and exits 1 ("Coverage sandbox did not publish a regular
  authenticated output file; sandbox exit=1").

ScopeWeave is an npm project — package-lock.json is canonical, server-tests.yml
and fuzz.yml use `cache: 'npm'` + `npm ci`, and no workflow / Dockerfile /
compose references pnpm — so the committed pnpm-lock.yaml was a second, unused
lockfile that only pushed the runtime runner into pnpm mode. Removing it lets
the runner use the canonical npm path, so coverage-evidence can run and the
whole develop queue is unblocked (this is the same base-clearing fix as #377).

This is the missing piece of this PR: the @hono/node-server trivy-fs CVE and the
cloud-sync.js ReDoS Semgrep finding were already cleared here; coverage-evidence
was the remaining central-gate blocker.

Verification: `npm run test:unit` passes (all 13 suites); package-lock.json is
untouched and still resolves @hono/node-server 2.0.12.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Msz8Dni5zRaqPatNCmZJZ8

Copy link
Copy Markdown
Contributor Author

Superseded by #379, which carries the same three base-clearing fixes and goes a bit further:

Closing to avoid two competing PRs contending for the same base and the rate-limited reviewer. All work continues on #379.


Generated by Claude Code

@seonghobae seonghobae closed this Jul 30, 2026
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