From 232daf73ef3c41f4488ca431ace206ca2f22d8e6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 4 Sep 2026 23:45:15 +0900 Subject: [PATCH 1/7] ci(actions): reduce pull request runner contention Signed-off-by: Seongho Bae Commit-Message-Assisted-by: Codex --- .github/workflows/codeql.yml | 4 +- .github/workflows/dependency-review.yml | 72 ------------------- .github/workflows/fuzz.yml | 4 +- .github/workflows/osvscanner.yml | 39 ---------- .github/workflows/pages.yml | 4 +- .github/workflows/server-tests.yml | 4 +- .../test_strix_static_repo_adaptations.py | 26 ++++--- 7 files changed, 25 insertions(+), 128 deletions(-) delete mode 100644 .github/workflows/dependency-review.yml delete mode 100644 .github/workflows/osvscanner.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 1a9461d5..0aafe367 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -12,8 +12,8 @@ permissions: contents: read concurrency: - group: codeql-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true + group: ${{ github.workflow }}-${{ github.repository }}-${{ github.event.pull_request.number || github.run_id }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: analyze: diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml deleted file mode 100644 index 6795d40e..00000000 --- a/.github/workflows/dependency-review.yml +++ /dev/null @@ -1,72 +0,0 @@ -name: Dependency Review - -on: - pull_request: - workflow_dispatch: - -permissions: - contents: read - pull-requests: read - -concurrency: - group: dependency-review-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -jobs: - dependency-review: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - with: - persist-credentials: false - - - name: Check dependency review support - id: dependency_review_support - env: - GH_TOKEN: ${{ github.token }} - BASE_SHA: ${{ github.event.pull_request.base.sha }} - HEAD_SHA: ${{ github.event.pull_request.head.sha }} - REPOSITORY: ${{ github.repository }} - shell: bash - run: | - set -euo pipefail - - if [ "${{ github.event_name }}" != "pull_request" ]; then - echo "supported=false" >>"$GITHUB_OUTPUT" - echo "Dependency review only runs as a hard gate for pull_request events." - exit 0 - fi - - api_url="${GITHUB_API_URL:-https://api.github.com}" - response_file="$(mktemp)" - status="$( - curl -fsS -o "$response_file" -w '%{http_code}' \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${GH_TOKEN}" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - "${api_url}/repos/${REPOSITORY}/dependency-graph/compare/${BASE_SHA}...${HEAD_SHA}" \ - || true - )" - - if [ "$status" = "200" ]; then - echo "supported=true" >>"$GITHUB_OUTPUT" - exit 0 - fi - - if [ "$status" = "403" ] || [ "$status" = "404" ]; then - echo "::warning::Dependency review is unavailable for ${REPOSITORY}; skipping dependency-review hard gate." - echo "supported=false" >>"$GITHUB_OUTPUT" - exit 0 - fi - - echo "::error::Dependency review support check failed with HTTP ${status}." - cat "$response_file" - exit 1 - - - name: Dependency review - if: steps.dependency_review_support.outputs.supported == 'true' - uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0 - with: - fail-on-severity: moderate - comment-summary-in-pr: on-failure diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index 10f85b8b..34d8d040 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -22,8 +22,8 @@ permissions: contents: read concurrency: - group: fuzz-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true + group: ${{ github.workflow }}-${{ github.repository }}-${{ github.event.pull_request.number || github.run_id }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: fuzz: diff --git a/.github/workflows/osvscanner.yml b/.github/workflows/osvscanner.yml deleted file mode 100644 index 806c8086..00000000 --- a/.github/workflows/osvscanner.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: OSV Scanner - -on: - pull_request: - workflow_dispatch: - -permissions: - actions: read - contents: read - -concurrency: - group: osvscanner-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -jobs: - osv-scan: - if: github.event_name == 'pull_request' - # Companion SCA lane for manifest evidence. Central .github still owns the - # required review/security/scheduler workflows. - uses: google/osv-scanner-action/.github/workflows/osv-scanner-reusable-pr.yml@3a7550f43ba5b58905a821ce3a0ed24c4858b3f4 # v2.3.8 + export-results gate - permissions: - actions: read - contents: read - security-events: write - with: - scan-args: |- - --maven-registry=https://maven-central.storage-download.googleapis.com/maven2 - --no-resolve - -r - ./ - fail-on-vuln: false - - manifest-pattern-coverage: - if: github.event_name == 'workflow_dispatch' - runs-on: ubuntu-latest - steps: - - name: Document manifest coverage - run: | - echo 'Recursive OSV scanning covers package-lock.json and requirements(-[A-Za-z0-9._-]+)?\.txt manifests when present.' diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 8b0fba65..c24e05b1 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -12,8 +12,8 @@ permissions: id-token: write concurrency: - group: pages - cancel-in-progress: true + group: ${{ github.workflow }}-${{ github.repository }}-${{ github.run_id }} + cancel-in-progress: false jobs: deploy: diff --git a/.github/workflows/server-tests.yml b/.github/workflows/server-tests.yml index 458d3aa9..673d08a2 100644 --- a/.github/workflows/server-tests.yml +++ b/.github/workflows/server-tests.yml @@ -14,8 +14,8 @@ permissions: contents: read concurrency: - group: server-tests-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true + group: ${{ github.workflow }}-${{ github.repository }}-${{ github.event.pull_request.number || github.run_id }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: unit-and-api: diff --git a/tests/config/test_strix_static_repo_adaptations.py b/tests/config/test_strix_static_repo_adaptations.py index 5707b278..3db8adeb 100644 --- a/tests/config/test_strix_static_repo_adaptations.py +++ b/tests/config/test_strix_static_repo_adaptations.py @@ -4,14 +4,15 @@ from pathlib import Path REPO_ROOT = Path(__file__).resolve().parents[2] -DEPENDENCY_REVIEW_WORKFLOW = REPO_ROOT / ".github" / "workflows" / "dependency-review.yml" -OSV_WORKFLOW = REPO_ROOT / ".github" / "workflows" / "osvscanner.yml" +WORKFLOW_DIR = REPO_ROOT / ".github" / "workflows" K8S_DEPLOYMENT = REPO_ROOT / "infra" / "k8s" / "deployment.yaml" K8S_SERVICE = REPO_ROOT / "infra" / "k8s" / "service.yaml" def test_central_review_workflows_are_not_copied_into_this_repository() -> None: central_only_paths = [ + WORKFLOW_DIR / "dependency-review.yml", + WORKFLOW_DIR / "osvscanner.yml", REPO_ROOT / ".github" / "workflows" / "opencode-review.yml", REPO_ROOT / ".github" / "workflows" / "pr-review-merge-scheduler.yml", REPO_ROOT / ".github" / "workflows" / "strix-selftest.yml", @@ -56,11 +57,18 @@ def test_kubernetes_deployment_uses_non_root_versioned_runtime() -> None: assert 'targetPort: 8080' in service_source -def test_companion_workflows_cover_named_requirements_manifests_and_full_history() -> None: - dependency_review_source = DEPENDENCY_REVIEW_WORKFLOW.read_text(encoding="utf-8") - osv_source = OSV_WORKFLOW.read_text(encoding="utf-8") +def test_workflow_concurrency_is_trigger_aware() -> None: + pull_request_workflows = ("codeql.yml", "fuzz.yml", "server-tests.yml") + expected_group = ( + "${{ github.workflow }}-${{ github.repository }}-" + "${{ github.event.pull_request.number || github.run_id }}" + ) - assert "actions/dependency-review-action@" in dependency_review_source - assert 'requirements(-[A-Za-z0-9._-]+)?\\.txt' in osv_source - assert "google/osv-scanner-action" in osv_source - assert "-r" in osv_source + for workflow_name in pull_request_workflows: + source = (WORKFLOW_DIR / workflow_name).read_text(encoding="utf-8") + assert f"group: {expected_group}" in source + assert "cancel-in-progress: ${{ github.event_name == 'pull_request' }}" in source + + deploy_source = (WORKFLOW_DIR / "pages.yml").read_text(encoding="utf-8") + assert "group: ${{ github.workflow }}-${{ github.repository }}-${{ github.run_id }}" in deploy_source + assert "cancel-in-progress: false" in deploy_source From 7cb4e53f56c78492861fb5f4b659e6dd66a1dc7e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 4 Sep 2026 23:46:28 +0900 Subject: [PATCH 2/7] ci(actions): remove disabled local CodeQL duplicate Signed-off-by: Seongho Bae Commit-Message-Assisted-by: Codex --- .github/workflows/codeql.yml | 45 ------------------- .../test_strix_static_repo_adaptations.py | 3 +- 2 files changed, 2 insertions(+), 46 deletions(-) delete mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml deleted file mode 100644 index 0aafe367..00000000 --- a/.github/workflows/codeql.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: CodeQL - -on: - pull_request: - branches: ["develop"] - push: - branches: ["develop", "master"] - schedule: - - cron: "15 2 * * 6" - -permissions: - contents: read - -concurrency: - group: ${{ github.workflow }}-${{ github.repository }}-${{ github.event.pull_request.number || github.run_id }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} - -jobs: - analyze: - name: Analyze (${{ matrix.language }}) - runs-on: ubuntu-latest - permissions: - contents: read - security-events: write - strategy: - fail-fast: false - matrix: - language: - - javascript-typescript - - python - steps: - - name: Checkout repository - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - with: - persist-credentials: false - - - name: Initialize CodeQL - uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 - with: - languages: ${{ matrix.language }} - - - name: Perform CodeQL analysis - uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 - with: - category: "/language:${{ matrix.language }}" diff --git a/tests/config/test_strix_static_repo_adaptations.py b/tests/config/test_strix_static_repo_adaptations.py index 3db8adeb..740ba2cb 100644 --- a/tests/config/test_strix_static_repo_adaptations.py +++ b/tests/config/test_strix_static_repo_adaptations.py @@ -12,6 +12,7 @@ def test_central_review_workflows_are_not_copied_into_this_repository() -> None: central_only_paths = [ WORKFLOW_DIR / "dependency-review.yml", + WORKFLOW_DIR / "codeql.yml", WORKFLOW_DIR / "osvscanner.yml", REPO_ROOT / ".github" / "workflows" / "opencode-review.yml", REPO_ROOT / ".github" / "workflows" / "pr-review-merge-scheduler.yml", @@ -58,7 +59,7 @@ def test_kubernetes_deployment_uses_non_root_versioned_runtime() -> None: def test_workflow_concurrency_is_trigger_aware() -> None: - pull_request_workflows = ("codeql.yml", "fuzz.yml", "server-tests.yml") + pull_request_workflows = ("fuzz.yml", "server-tests.yml") expected_group = ( "${{ github.workflow }}-${{ github.repository }}-" "${{ github.event.pull_request.number || github.run_id }}" From 9fcf0a235171ecabd7d5a6396b212ffddcdd15ae Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 01:12:09 +0900 Subject: [PATCH 3/7] ci: serialize Pages deployments without cancellation Signed-off-by: Seongho Bae --- .github/workflows/pages.yml | 2 +- tests/config/test_strix_static_repo_adaptations.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index c24e05b1..444072af 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -12,7 +12,7 @@ permissions: id-token: write concurrency: - group: ${{ github.workflow }}-${{ github.repository }}-${{ github.run_id }} + group: ${{ github.workflow }}-${{ github.repository }} cancel-in-progress: false jobs: diff --git a/tests/config/test_strix_static_repo_adaptations.py b/tests/config/test_strix_static_repo_adaptations.py index 740ba2cb..48016836 100644 --- a/tests/config/test_strix_static_repo_adaptations.py +++ b/tests/config/test_strix_static_repo_adaptations.py @@ -71,5 +71,5 @@ def test_workflow_concurrency_is_trigger_aware() -> None: assert "cancel-in-progress: ${{ github.event_name == 'pull_request' }}" in source deploy_source = (WORKFLOW_DIR / "pages.yml").read_text(encoding="utf-8") - assert "group: ${{ github.workflow }}-${{ github.repository }}-${{ github.run_id }}" in deploy_source + assert "group: ${{ github.workflow }}-${{ github.repository }}" in deploy_source assert "cancel-in-progress: false" in deploy_source From ac62d97a02cf043d53cf79fc8d5f592077fc0acc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 01:32:29 +0900 Subject: [PATCH 4/7] test(ci): require code-current workflow ownership docs --- .../test_strix_static_repo_adaptations.py | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/config/test_strix_static_repo_adaptations.py b/tests/config/test_strix_static_repo_adaptations.py index 48016836..d8f234e0 100644 --- a/tests/config/test_strix_static_repo_adaptations.py +++ b/tests/config/test_strix_static_repo_adaptations.py @@ -36,6 +36,30 @@ def test_central_review_workflows_are_not_copied_into_this_repository() -> None: assert not central_only_path.exists(), central_only_path +def test_ci_documentation_matches_central_sca_ownership() -> None: + documentation_paths = ( + REPO_ROOT / "ARCHITECTURE.md", + REPO_ROOT / "CLAUDE.md", + REPO_ROOT / "README.md", + ) + + for documentation_path in documentation_paths: + source = documentation_path.read_text(encoding="utf-8") + assert "dependency-review.yml" not in source, documentation_path + assert "osvscanner.yml" not in source, documentation_path + assert "codeql.yml" not in source, documentation_path + + architecture = (REPO_ROOT / "ARCHITECTURE.md").read_text(encoding="utf-8") + claude = (REPO_ROOT / "CLAUDE.md").read_text(encoding="utf-8") + readme = (REPO_ROOT / "README.md").read_text(encoding="utf-8") + + for source in (architecture, claude, readme): + assert "CodeQL" in source + assert "Dependency Review" in source + assert "OSV" in source + assert "ContextualWisdomLab/.github" in source + + def test_kubernetes_deployment_uses_non_root_versioned_runtime() -> None: deployment_source = K8S_DEPLOYMENT.read_text(encoding="utf-8") service_source = K8S_SERVICE.read_text(encoding="utf-8") From 6e967af3fa76f2cfe1ec5adc5ed68dae8f14e58c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 01:32:44 +0900 Subject: [PATCH 5/7] docs(ci): record central security workflow ownership --- ARCHITECTURE.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 4688d27b..5e9aa4f5 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -17,12 +17,12 @@ - `.github/workflows/pages.yml`: GitHub Pages deployment workflow for the static app. -- OpenCode Review, Strix Security Scan, and PR Review Merge Scheduler: - organization-level required workflows from `ContextualWisdomLab/.github`. -- `.github/workflows/dependency-review.yml`: authoritative manifest-diff - review workflow for repository dependency changes. -- `.github/workflows/osvscanner.yml`: authoritative OSV/SARIF workflow - for dependency scanning. +- `.github/workflows/server-tests.yml` and `.github/workflows/fuzz.yml`: + repository-owned product/runtime validation. +- OpenCode Review, Strix Security Scan, PR Review Merge Scheduler, CodeQL, + Dependency Review, OSV, and the broader Security Scan are organization-level + required workflows owned by `ContextualWisdomLab/.github`; ScopeWeave does not + carry repository-local copies of those central lanes. - `tests/e2e/scopeweave.spec.js`: Playwright coverage for the user-facing app flows. - `tests/config/`: repository governance and workflow ownership checks. @@ -44,4 +44,4 @@ deployment ownership or blocking on absent IaC that this repo does not contain. - Kubernetes/IaC security coverage remains a follow-up design lane for - any future `infra/` or container packaging surface. + any future `infra/` or container packaging surface. \ No newline at end of file From 03e954f953a233b82d32ed4b03790157d3730886 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 01:33:07 +0900 Subject: [PATCH 6/7] docs(ci): align agent guide with central SCA lanes --- CLAUDE.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 81c1a819..dddc19fd 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -105,11 +105,12 @@ deploy guide is `docs/deploy.md`. - **Default branch is `develop`.** SaaS work lands as a stacked PR train — see "Merge order" in `README.md` before retargeting or merging PRs. -- Repo-local PR gates: `server-tests.yml` (unit + API + eval-safe check + cloud e2e), - `fuzz.yml`, `codeql.yml`, `dependency-review.yml`. -- OpenCode Review, Strix Security Scan, and PR Review Merge Scheduler are - organization-level required workflows from `ContextualWisdomLab/.github` — never - copy them into this repository (`tests/config` pytest enforces this). +- Repo-local PR gates are `server-tests.yml` (unit + API + eval-safe check + cloud e2e) + and `fuzz.yml`; Pages remains the repository-owned deployment workflow. +- OpenCode Review, Strix Security Scan, PR Review Merge Scheduler, CodeQL, + Dependency Review, OSV, and the broader Security Scan are organization-level + required workflows owned by `ContextualWisdomLab/.github` — never copy them into + this repository (`tests/config` pytest enforces this ownership boundary). - A failing `trivy-fs` is a real finding, not a flake — follow the remediation protocol in `AGENTS.md`. @@ -125,4 +126,4 @@ deploy guide is `docs/deploy.md`. security (`sentinel.md`: `Object.create(null)` for untrusted-key maps, `crypto.randomUUID()`, CSP). Follow them when touching related code. - `.agents/skills/github-robot-review-gate/SKILL.md` covers diagnosing PR merge-gate - blockers (CodeRabbit robot-review policy, required checks, rulesets). + blockers (CodeRabbit robot-review policy, required checks, rulesets). \ No newline at end of file From 1e35d347ea69d7dcc298e5c35a5d64764b8b5674 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 01:33:39 +0900 Subject: [PATCH 7/7] docs(ci): remove stale local SCA ownership claims --- README.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 6340c1f4..1611dae9 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ two modes: project duplicate (templates), rate limiting (opt-in), metrics (JSON + Prometheus), structured logs - **Docs**: complete API reference at [`docs/api.md`](docs/api.md) (served at - `/docs/api.md`); deploy guide at [`docs/deploy.md`](docs/deploy.md) + `/docs/api.md`); deploy guide is [`docs/deploy.md`](docs/deploy.md) ## Architecture @@ -168,9 +168,10 @@ the previous; merging in order auto-retargets the next): - Runtime dependencies are minimized (`hono`, `@hono/node-server` only, added by the SaaS stack); CI/dev-only automation under `.github/`, `scripts/`, `tests/`, and `docs/` is allowed. -- OpenCode Review, Strix Security Scan, and PR Review Merge Scheduler are - inherited from the organization-level required workflows in - `ContextualWisdomLab/.github`, not copied into this repository. +- OpenCode Review, Strix Security Scan, PR Review Merge Scheduler, CodeQL, + Dependency Review, OSV, and the broader Security Scan are inherited from the + organization-level required workflows in `ContextualWisdomLab/.github`, not + copied into this repository. ## Persistence model @@ -187,12 +188,12 @@ the previous; merging in order auto-retargets the next): ## Security workflow -- Organization required workflows provide OpenCode Review, Strix Security - Scan, PR Review Merge Scheduler, failed-check explanation, and coverage +- Organization-required workflows from `ContextualWisdomLab/.github` own OpenCode + Review, Strix Security Scan, PR Review Merge Scheduler, CodeQL, Dependency + Review, OSV, the broader Security Scan, failed-check explanation, and coverage evidence. -- Repository-local workflows remain for ScopeWeave-specific static delivery - and companion SCA lanes, including dependency review, OSV, Trivy, - Scorecard, and Pages. +- Repository-local workflows remain for ScopeWeave-specific server/runtime tests, + fuzzing, and Pages delivery; they do not duplicate the central SCA lanes. - Server hardening: pinned-HS256 JWT (no header-alg trust), scrypt passwords, hash-only PAT/webhook-secret storage (secrets shown once), server-side RBAC, secrets never logged.