Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
77910ff
fix(security): update Strix Python dependency locks
seonghobae Aug 4, 2026
60b6dd9
fix(ci): restore central security baseline
seonghobae Aug 4, 2026
c73ee47
fix(ci): let dependency upgrades self-heal coverage
seonghobae Aug 4, 2026
880486b
fix(deps): constrain patched aiohttp floor in Strix lock
seonghobae Aug 4, 2026
bb5e436
test(ci): reject mixed fatal pip preflight evidence
seonghobae Aug 4, 2026
b326f65
fix(ci): keep mixed pip integrity failures fatal
seonghobae Aug 4, 2026
5b4929a
fix(ci): restore coverage contract wording
seonghobae Aug 4, 2026
0b6a188
fix(ci): snapshot dependencies on default-branch pushes so dependency…
seonghobae Aug 4, 2026
69fc4d2
ci: run securely pinned review repair every hour (#745)
seonghobae Aug 4, 2026
6b705b3
test(ci): fail closed on mixed unknown pip errors
seonghobae Aug 4, 2026
83b9d50
fix(ci): reject mixed unknown pip failures
seonghobae Aug 4, 2026
ced08de
test(ci): preserve pip stale-pin context lines
seonghobae Aug 4, 2026
98dc0b5
docs(doctoring): record central security baseline evidence
seonghobae Aug 4, 2026
5c5c032
fix(ci): preserve verified pip stale-pin context
seonghobae Aug 4, 2026
a0a84f7
fix(ci): recognize pip incompatible-version context
seonghobae Aug 4, 2026
4aefeb1
docs(doctoring): correct APA 7 standards provenance
seonghobae Aug 4, 2026
cfa6893
docs(automation): correct APA 7 dates for living GitHub documentation
seonghobae Aug 4, 2026
03a95a4
test(ci): prove exact-pair stale-pin classification
seonghobae Aug 4, 2026
3e92ae9
chore(ci): remove branch-pushing one-shot workflow
seonghobae Aug 4, 2026
0160d65
build(ci): add bounded stale-pin patch helper
seonghobae Aug 4, 2026
a900f51
test(ci): require exact-pair stale-pin evidence
seonghobae Aug 4, 2026
0d22ee8
fix(ci): simplify one-shot stale-pin verification
seonghobae Aug 4, 2026
98ef79e
fix(security): remove branch-controlled write workflow
seonghobae Aug 4, 2026
044030b
fix(ci): require paired exact-requirement stale-pin diagnostics
seonghobae Aug 4, 2026
b61878f
chore(ci): remove completed one-shot patch helper
seonghobae Aug 4, 2026
f2c5333
docs(doctoring): record paired stale-pin evidence contract
seonghobae Aug 4, 2026
13e8d72
ci(security): advance CodeQL baseline to v4.37.5
seonghobae Aug 4, 2026
2ad1fc0
ci(security): use latest immutable CodeQL v4.37.5
seonghobae Aug 4, 2026
c61bdd7
test(ci): reject non-version index evidence
seonghobae Aug 4, 2026
d20072a
fix(ci): require concrete version evidence before deferral
seonghobae Aug 4, 2026
13c12cc
docs(doctoring): define concrete stale-pin version evidence
seonghobae Aug 4, 2026
3dff404
test(ci): reject duplicate malformed resolver evidence
seonghobae Aug 4, 2026
c3b16d0
fix(ci): validate every paired resolver line independently
seonghobae Aug 4, 2026
60f6009
docs(doctoring): require concrete evidence on every resolver line
seonghobae Aug 4, 2026
4e0fc8b
test(ci): require fail-closed scheduler source resolution
seonghobae Aug 4, 2026
95bb78a
fix(ci): fail closed on unresolved scheduler source identity
seonghobae Aug 4, 2026
e672f23
docs(doctoring): cite called-workflow identity contract
seonghobae Aug 4, 2026
32ac926
fix(ci): run hourly review autofix through NVIDIA NIM (#752)
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@d1ba80a13dd99fba24a470575428917156a28b43 # v4.37.5
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@d1ba80a13dd99fba24a470575428917156a28b43 # v4.37.5
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@d1ba80a13dd99fba24a470575428917156a28b43 # v4.37.5
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@d1ba80a13dd99fba24a470575428917156a28b43 # v4.37.5
with:
category: "/language:${{ matrix.language }}-merge"
upload: false
Expand Down
74 changes: 40 additions & 34 deletions .github/workflows/pr-review-autofix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ jobs:
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
repository: ContextualWisdomLab/.github
ref: ${{ github.sha }}
fetch-depth: 1
persist-credentials: false
path: trusted-autofix-source
Expand Down Expand Up @@ -231,9 +232,9 @@ jobs:
EOF
jq -n --arg workspace "$TARGET_WORKSPACE" '{
"$schema": "https://opencode.ai/config.json",
"model": "github-models/openai/gpt-5",
"small_model": "github-models/deepseek/deepseek-v3-0324",
"enabled_providers": ["github-models"],
"model": "nvidia-nim/mistralai/mistral-nemotron",
"small_model": "nvidia-nim/nvidia/nemotron-3-nano-30b-a3b",
"enabled_providers": ["nvidia-nim"],
"permission": {
"edit": "allow",
"bash": "deny",
Expand All @@ -242,10 +243,13 @@ jobs:
"glob": "allow",
"list": "allow",
"task": "deny",
"skill": "deny",
"question": "deny",
"webfetch": "deny",
"websearch": "deny",
"lsp": "deny",
"external_directory": "deny"
"external_directory": "deny",
"doom_loop": "deny"
},
"agent": {
"ci-autofix": {
Expand All @@ -261,45 +265,40 @@ jobs:
"glob": "allow",
"list": "allow",
"task": "deny",
"skill": "deny",
"question": "deny",
"webfetch": "deny",
"websearch": "deny",
"lsp": "deny",
"external_directory": "deny"
"external_directory": "deny",
"doom_loop": "deny"
}
}
},
"provider": {
"github-models": {
"nvidia-nim": {
"npm": "@ai-sdk/openai-compatible",
"name": "GitHub Models",
"name": "NVIDIA NIM",
"options": {
"baseURL": "https://models.github.ai/inference",
"apiKey": "{env:STRIX_GITHUB_MODELS_TOKEN}"
"baseURL": "https://integrate.api.nvidia.com/v1",
"apiKey": "{env:NVIDIA_API_KEY}"
},
"models": {
"openai/gpt-5": {
"name": "OpenAI GPT-5",
"mistralai/mistral-nemotron": {
"name": "Mistral Nemotron",
"tool_call": true,
"reasoning": true,
"options": {
"reasoningEffort": "high"
},
"variants": {
"high": {
"reasoningEffort": "high"
}
},
"limit": {
"context": 200000,
"output": 100000
"context": 128000,
"output": 4096
}
},
"deepseek/deepseek-v3-0324": {
"name": "DeepSeek V3 0324",
"nvidia/nemotron-3-nano-30b-a3b": {
"name": "Nemotron 3 Nano 30B A3B",
"tool_call": true,
"reasoning": true,
"limit": {
"context": 128000,
"output": 4096
"output": 32768
}
}
}
Expand All @@ -310,16 +309,18 @@ jobs:
- name: Run OpenCode review autofix
if: env.RESOLVE_CONFLICT != 'true'
env:
STRIX_GITHUB_MODELS_TOKEN: ${{ secrets.STRIX_GITHUB_MODELS_TOKEN || github.token }}
GITHUB_TOKEN: ${{ secrets.PR_REVIEW_MERGE_TOKEN || secrets.OPENCODE_APPROVE_TOKEN || steps.target_app_token.outputs.token || github.token }}
MODEL: github-models/openai/gpt-5
USE_GITHUB_TOKEN: "true"
NVIDIA_API_KEY: ${{ secrets.NVIDIA_NIM_API_KEY }}
MODEL: nvidia-nim/mistralai/mistral-nemotron
SHARE: "false"
NPM_CONFIG_IGNORE_SCRIPTS: "true"
NO_COLOR: "1"
OPENCODE_AUTOFIX_WORKDIR: ${{ runner.temp }}/opencode-autofix-project
run: |
set -euo pipefail
if [ -z "${NVIDIA_API_KEY:-}" ]; then
echo "::error::NVIDIA_NIM_API_KEY is required for scheduled OpenCode autofix."
exit 1
fi
prompt_file="${RUNNER_TEMP}/opencode-autofix-prompt.md"
allowed_paths_context="$(
awk '
Expand Down Expand Up @@ -374,7 +375,8 @@ jobs:
}
trap restore_workspace_config EXIT
cd "$TARGET_WORKSPACE"
timeout 18000 opencode run "$(cat "$prompt_file")" \
env -u GITHUB_TOKEN -u GH_TOKEN -u ACTIONS_ID_TOKEN_REQUEST_TOKEN -u ACTIONS_ID_TOKEN_REQUEST_URL \
timeout 18000 opencode run "$(cat "$prompt_file")" \
--pure \
--agent ci-autofix \
--model "$MODEL" \
Expand Down Expand Up @@ -446,17 +448,20 @@ jobs:
- name: Merge base branch and resolve conflicts with OpenCode
if: env.RESOLVE_CONFLICT == 'true'
env:
STRIX_GITHUB_MODELS_TOKEN: ${{ secrets.STRIX_GITHUB_MODELS_TOKEN || github.token }}
NVIDIA_API_KEY: ${{ secrets.NVIDIA_NIM_API_KEY }}
GITHUB_TOKEN: ${{ secrets.PR_REVIEW_MERGE_TOKEN || secrets.OPENCODE_APPROVE_TOKEN || steps.target_app_token.outputs.token || github.token }}
GH_TOKEN: ${{ secrets.PR_REVIEW_MERGE_TOKEN || secrets.OPENCODE_APPROVE_TOKEN || steps.target_app_token.outputs.token || github.token }}
MODEL: github-models/openai/gpt-5
USE_GITHUB_TOKEN: "true"
MODEL: nvidia-nim/mistralai/mistral-nemotron
SHARE: "false"
NPM_CONFIG_IGNORE_SCRIPTS: "true"
NO_COLOR: "1"
OPENCODE_AUTOFIX_WORKDIR: ${{ runner.temp }}/opencode-autofix-project
run: |
set -euo pipefail
if [ -z "${NVIDIA_API_KEY:-}" ]; then
echo "::error::NVIDIA_NIM_API_KEY is required for scheduled OpenCode autofix."
exit 1
fi
cd "$TARGET_WORKSPACE"

# Merge the base branch into the detached head. A clean merge stays
Expand Down Expand Up @@ -516,7 +521,8 @@ jobs:
fi
}
trap restore_workspace_config EXIT
timeout 18000 opencode run "$(cat "$prompt_file")" \
env -u GITHUB_TOKEN -u GH_TOKEN -u ACTIONS_ID_TOKEN_REQUEST_TOKEN -u ACTIONS_ID_TOKEN_REQUEST_URL \
timeout 18000 opencode run "$(cat "$prompt_file")" \
--pure \
--agent ci-autofix \
--model "$MODEL" \
Expand Down
90 changes: 80 additions & 10 deletions .github/workflows/pr-review-fix-scheduler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ on:
retry_hours:
description: Minimum hours before redispatching autofix for the same head
required: false
default: "24"
default: "1"
type: string
autofix_workflow:
description: Autofix workflow file to dispatch
Expand All @@ -44,14 +44,16 @@ on:
default: ""
type: string
canonical_ref:
description: Ref of ContextualWisdomLab/.github to use for scheduler code
description: Deprecated compatibility input; accepted and ignored because privileged source is bound to the called workflow SHA
required: false
default: "main"
default: ""
type: string
repository_dispatch:
types: [pr-review-fix-scheduler]
schedule:
- cron: "23 */2 * * *"
# Run away from minute zero, where scheduled GitHub Actions are more likely
# to be delayed, while preserving a bounded one-dispatch-per-run repair loop.
- cron: "23 * * * *"

concurrency:
group: central-pr-review-fix-scheduler-${{ github.event.client_payload.target_repository || inputs.target_repository || vars.PR_REVIEW_FIX_TARGET_REPOSITORY || github.repository }}
Expand Down Expand Up @@ -80,19 +82,87 @@ jobs:
DRY_RUN: ${{ github.event.client_payload.dry_run == true || github.event.client_payload.dry_run == 'true' || inputs.dry_run == true }}
MAX_PRS: ${{ github.event.client_payload.max_prs || inputs.max_prs || '50' }}
MAX_DISPATCHES: ${{ github.event.client_payload.max_dispatches || inputs.max_dispatches || '1' }}
RETRY_HOURS: ${{ github.event.client_payload.retry_hours || inputs.retry_hours || '24' }}
RETRY_HOURS: ${{ github.event.client_payload.retry_hours || inputs.retry_hours || '1' }}
AUTOFIX_WORKFLOW: pr-review-autofix.yml
AUTOFIX_REPOSITORY: ContextualWisdomLab/.github
CANONICAL_REF: main
steps:
- name: Checkout canonical scheduler
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Resolve immutable called-workflow source
id: trusted_source
env:
WORKFLOW_REPOSITORY: ${{ job.workflow_repository }}
WORKFLOW_SHA: ${{ job.workflow_sha }}
WORKFLOW_REF: ${{ job.workflow_ref }}
WORKFLOW_FILE_PATH: ${{ job.workflow_file_path }}
run: |
set -euo pipefail
expected_repository="ContextualWisdomLab/.github"
expected_file=".github/workflows/pr-review-fix-scheduler.yml"

if [ "$WORKFLOW_REPOSITORY" != "$expected_repository" ]; then
printf '::error::Called workflow repository resolved to %s, expected %s.\n' \
"${WORKFLOW_REPOSITORY:-<empty>}" "$expected_repository"
exit 1
fi
if ! [[ "$WORKFLOW_SHA" =~ ^[0-9a-f]{40}$ ]]; then
printf '::error::Called workflow SHA is missing or malformed: %s.\n' \
"${WORKFLOW_SHA:-<empty>}"
exit 1
fi
if [ "$WORKFLOW_FILE_PATH" != "$expected_file" ]; then
printf '::error::Called workflow file resolved to %s, expected %s.\n' \
"${WORKFLOW_FILE_PATH:-<empty>}" "$expected_file"
exit 1
fi
expected_ref_prefix="${WORKFLOW_REPOSITORY}/${WORKFLOW_FILE_PATH}@"
case "$WORKFLOW_REF" in
"$expected_ref_prefix"*) ;;
*)
printf '::error::Called workflow ref is missing or inconsistent: %s.\n' \
"${WORKFLOW_REF:-<empty>}"
exit 1
;;
esac

{
printf 'repository=%s\n' "$WORKFLOW_REPOSITORY"
printf 'sha=%s\n' "$WORKFLOW_SHA"
printf 'workflow_ref=%s\n' "$WORKFLOW_REF"
printf 'workflow_file_path=%s\n' "$WORKFLOW_FILE_PATH"
} >>"$GITHUB_OUTPUT"
printf 'Resolved immutable called-workflow source repository=%s file=%s sha=%s ref=%s.\n' \
"$WORKFLOW_REPOSITORY" "$WORKFLOW_FILE_PATH" "$WORKFLOW_SHA" "$WORKFLOW_REF"

- name: Checkout immutable called-workflow source
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: ContextualWisdomLab/.github
ref: ${{ env.CANONICAL_REF }}
# GitHub documents job.workflow_repository and job.workflow_sha as
# the called workflow identity. The preceding step validates every
# field before checkout so an absent property cannot select defaults.
repository: ${{ steps.trusted_source.outputs.repository }}
ref: ${{ steps.trusted_source.outputs.sha }}
fetch-depth: 1
persist-credentials: false

- name: Verify immutable called-workflow checkout
env:
EXPECTED_SHA: ${{ steps.trusted_source.outputs.sha }}
EXPECTED_FILE: ${{ steps.trusted_source.outputs.workflow_file_path }}
run: |
set -euo pipefail
actual_sha="$(git rev-parse HEAD)"
if [ "$actual_sha" != "$EXPECTED_SHA" ]; then
printf '::error::Checked-out scheduler SHA %s does not match called-workflow SHA %s.\n' \
"$actual_sha" "$EXPECTED_SHA"
exit 1
fi
if [ ! -f "$EXPECTED_FILE" ] || [ -L "$EXPECTED_FILE" ]; then
printf '::error::Called workflow source file is missing or symlinked: %s.\n' \
"$EXPECTED_FILE"
exit 1
fi
printf 'Verified immutable scheduler checkout at %s (%s).\n' \
"$actual_sha" "$EXPECTED_FILE"

- name: Self-test fix scheduler contract
run: python3 scripts/ci/pr_review_fix_scheduler.py --self-test

Expand Down
15 changes: 14 additions & 1 deletion .github/workflows/sbom-generation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,30 @@
# NOTE: contents: write is required for release-asset upload and for the
# dependency submission API. Fork PR heads run without write and simply skip
# those side effects; the artifact is still produced.
#
# NOTE on the push trigger: it exists so the DEFAULT BRANCH has a dependency
# snapshot. dependency-review compares base...head in the dependency graph; with
# PR-only runs the base commit never has one, so every comparison reports "the
# number of snapshots compared for the base SHA (0) and the head SHA (1) do not
# match" and the whole dependency set reads as newly added. That re-flags
# pre-existing vulnerabilities on every PR instead of only the ones the PR adds.
# Snapshotting pushes to the default branch gives the comparison a real base.
name: SBOM Generation

on:
push:
branches: [main, master, develop]
pull_request:
types: [opened, synchronize, reopened, ready_for_review, closed]
branches: [main, master, develop]
release:
types: [published]

concurrency:
group: sbom-generation-${{ github.event.pull_request.base.repo.full_name || github.repository }}-${{ github.event.pull_request.number || github.event.release.tag_name || github.ref }}
# Final fallback is the SHA, not the ref, so two pushes landing close together
# do not cancel each other: a cancelled push run leaves that commit without a
# snapshot, which is exactly the base-side gap this trigger exists to close.
group: sbom-generation-${{ github.event.pull_request.base.repo.full_name || github.repository }}-${{ github.event.pull_request.number || github.event.release.tag_name || github.sha }}
cancel-in-progress: true

permissions:
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/scheduled-security-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,13 @@ jobs:
with:
persist-credentials: false
- name: Initialize CodeQL
uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
uses: github/codeql-action/init@d1ba80a13dd99fba24a470575428917156a28b43 # v4.37.5
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
- name: Perform CodeQL Analysis
continue-on-error: true
uses: github/codeql-action/analyze@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
uses: github/codeql-action/analyze@d1ba80a13dd99fba24a470575428917156a28b43 # v4.37.5
with:
category: "/language:${{ matrix.language }}-scheduled"

Expand Down Expand Up @@ -131,7 +131,7 @@ jobs:
- name: Upload Trivy SARIF to code scanning
if: always() && hashFiles('trivy-results.sarif') != ''
continue-on-error: true
uses: github/codeql-action/upload-sarif@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
uses: github/codeql-action/upload-sarif@d1ba80a13dd99fba24a470575428917156a28b43 # v4.37.5
with:
sarif_file: trivy-results.sarif
category: trivy-fs-scheduled
Loading
Loading