Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 7 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,10 @@ This section applies to any agent (Claude, Codex, Cursor, opencode, ...) working
- Do not justify risky debug defaults as temporary shortcuts.
- Do not defer dependency review, SBOM generation, or supply-chain checks to a later phase.
- Do not defer Windows or macOS build enforcement to a later phase.

## Local OpenCode contract
- Root `opencode.jsonc` is NVIDIA NIM only: `enabled_providers` is `["nvidia-nim"]`.
- The provider binds `{env:NVIDIA_API_KEY}` to `https://integrate.api.nvidia.com/v1`. That env name is the NVIDIA/OpenCode client contract.
- The organization GitHub secret is `NVIDIA_NIM_API_KEY`. CI maps that secret onto process env `NVIDIA_API_KEY`. Do not rename the local OpenCode binding to `{env:NVIDIA_NIM_API_KEY}`.
- Never introduce `COPILOT_GITHUB_TOKEN`, `github-models`, or `STRIX_GITHUB_MODELS_TOKEN` in `opencode.jsonc`.
- Do not change existing review-agent credential names or routing. Central OpenCode Review and the PR review/merge scheduler stay in `ContextualWisdomLab/.github`.
13 changes: 10 additions & 3 deletions docs/workflow/pr-review-merge-scheduler.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ workflow `GITHUB_TOKEN`, depending on which credential can perform the guarded r
The local repository may keep product CI, security, release, and build workflows. It must not restore
repo-local copies of `opencode-review.yml`, `pr-review-merge-scheduler.yml`, or their `scripts/ci` helper implementations.

Local developer OpenCode (`opencode.jsonc`) is a separate trust boundary from those central
review workflows. It uses NVIDIA NIM only, binds `{env:NVIDIA_API_KEY}` at
`https://integrate.api.nvidia.com/v1`, and must not restore GitHub Models, Copilot tokens, or
review-agent secrets. The organization secret name remains `NVIDIA_NIM_API_KEY`; CI maps that
secret onto `NVIDIA_API_KEY` for the OpenCode client.

## Behavior

- Inspect non-draft PRs targeting the repository default branch, currently `develop`.
Expand Down Expand Up @@ -44,8 +50,8 @@ repo-local copies of `opencode-review.yml`, `pr-review-merge-scheduler.yml`, or

## Security Notes

- Attack surface: organization required workflows with write access to PR comments, PR branch updates, and normal merges.
- Trust boundary touched: GitHub repository governance, PR review state, status checks, and CodeRabbit review requests.
- Attack surface: organization required workflows with write access to PR comments, PR branch updates, and normal merges; local `opencode.jsonc` that calls NVIDIA NIM over HTTPS.
- Trust boundary touched: GitHub repository governance, PR review state, status checks, CodeRabbit review requests, and the local OpenCode provider allowlist (`nvidia-nim` + `{env:NVIDIA_API_KEY}`).
- Realistic threats: spammed review comments, merging a PR with unresolved conversations, merging without required checks, or hiding conflicts behind automation.
- Mitigations: central required workflow source pinning, idempotent per-head review comment marker,
explicit unresolved-thread check, retry-bounded GitHub API reads, required-check verification
Expand All @@ -54,4 +60,5 @@ repo-local copies of `opencode-review.yml`, `pr-review-merge-scheduler.yml`, or
- Test points: organization ruleset inheritance, current-head OpenCode approval, unresolved review
thread count, required-check rollup, approved behind PR, approved conflict-free PR, approved dirty PR,
external failed-check classification, provider/runtime failure summary, and Strix evidence lookup
scope diagnostics.
scope diagnostics, and local `opencode.jsonc` NIM-only contract (`small_model`, `{env:NVIDIA_API_KEY}`,
no GitHub Models / Copilot leftovers).
57 changes: 15 additions & 42 deletions opencode.jsonc
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"$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/nvidia/llama-3.3-nemotron-super-49b-v1.5",
"small_model": "nvidia-nim/meta/llama-3.3-70b-instruct",
"enabled_providers": ["nvidia-nim"],
"mcp": {
"codegraph": {
"type": "local",
Expand Down Expand Up @@ -37,56 +37,29 @@
}
},
"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",
"nvidia/llama-3.3-nemotron-super-49b-v1.5": {
"name": "NVIDIA Llama 3.3 Nemotron Super 49B v1.5",
"tool_call": true,
"reasoning": true,
"limit": {
"context": 200000,
"output": 100000
"context": 131072,
"output": 32768
}
},
"deepseek/deepseek-r1-0528": {
"name": "DeepSeek R1 0528",
"meta/llama-3.3-70b-instruct": {
"name": "Meta Llama 3.3 70B Instruct",
"tool_call": true,
"reasoning": true,
"limit": {
"context": 128000,
"output": 4096
}
},
"deepseek/deepseek-v3-0324": {
"name": "DeepSeek V3 0324",
"tool_call": true,
"limit": {
"context": 128000,
"output": 4096
}
},
"openai/o3": {
"name": "OpenAI o3",
"tool_call": true,
"reasoning": true,
"limit": {
"context": 200000,
"output": 100000
}
},
"openai/o4-mini": {
"name": "OpenAI o4-mini",
"tool_call": true,
"reasoning": true,
"limit": {
"context": 200000,
"output": 100000
"context": 131072,
"output": 16384
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""Regression contract for the repository's NVIDIA NIM OpenCode configuration."""

from __future__ import annotations

import json
from pathlib import Path


def test_opencode_uses_the_canonical_nvidia_nim_contract() -> None:
"""Require the reviewed NIM models, process credential alias, and option boundary."""
repo_root = Path(__file__).resolve().parents[3]
opencode_text = (repo_root / "opencode.jsonc").read_text(encoding="utf-8")
config = json.loads(opencode_text)

assert config["model"] == "nvidia-nim/nvidia/llama-3.3-nemotron-super-49b-v1.5"
assert config["small_model"] == "nvidia-nim/meta/llama-3.3-70b-instruct"
assert config["enabled_providers"] == ["nvidia-nim"]
assert set(config["provider"]) == {"nvidia-nim"}

provider = config["provider"]["nvidia-nim"]
assert provider["options"]["baseURL"] == "https://integrate.api.nvidia.com/v1"
# Central workflows source GitHub Secret NVIDIA_NIM_API_KEY and intentionally
# expose it to this OpenCode-compatible client through the NVIDIA_API_KEY
# process alias. The repository config must consume the alias, not rename
# the organization secret contract.
assert provider["options"]["apiKey"] == "{env:NVIDIA_API_KEY}"

primary_model = provider["models"]["nvidia/llama-3.3-nemotron-super-49b-v1.5"]
assert "reasoningEffort" not in primary_model.get("options", {})
assert "meta/llama-3.3-70b-instruct" in provider["models"]

for forbidden_token in (
"github-models",
"STRIX_GITHUB_MODELS_TOKEN",
"COPILOT_GITHUB_TOKEN",
"openai/gpt-5",
"openai/o3",
"openai/o4-mini",
"models.github.ai",
):
assert forbidden_token not in opencode_text
30 changes: 26 additions & 4 deletions services/analysis-engine/tests/test_supply_chain_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -5073,14 +5073,36 @@ def test_opencode_approval_write_failure_updates_overview_only() -> None:
assert "source-backed repository findings" in policy


def test_opencode_uses_nvidia_nim_only() -> None:
"""Ensure local OpenCode is NVIDIA NIM only and does not use GitHub Models."""
repo_root = Path(__file__).resolve().parents[3]
opencode_text = (repo_root / "opencode.jsonc").read_text(encoding="utf-8")
opencode_config = json.loads(opencode_text)

assert opencode_config["model"] == "nvidia-nim/nvidia/llama-3.3-nemotron-super-49b-v1.5"
Comment thread
cursor[bot] marked this conversation as resolved.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This test still omits small_model, the openai/o3 / openai/o4-mini deny-list, reasoningEffort absence, and {env:NVIDIA_NIM_API_KEY} rejection. Those locks live in test_opencode_nim_secret_contract.py on this head. Do not open another NIM successor from here — #885 already closes this split in both tests.

assert opencode_config["enabled_providers"] == ["nvidia-nim"]
assert set(opencode_config["provider"]) == {"nvidia-nim"}

nim_provider = opencode_config["provider"]["nvidia-nim"]
assert nim_provider["options"]["baseURL"] == "https://integrate.api.nvidia.com/v1"
assert nim_provider["options"]["apiKey"] == "{env:NVIDIA_API_KEY}"
assert "nvidia/llama-3.3-nemotron-super-49b-v1.5" in nim_provider["models"]
Comment thread
seonghobae marked this conversation as resolved.

leftover_tokens = (
Comment thread
cursor[bot] marked this conversation as resolved.
"github-models",
"STRIX_GITHUB_MODELS_TOKEN",
"COPILOT_GITHUB_TOKEN",
"openai/gpt-5",
"models.github.ai",
)
for leftover in leftover_tokens:
assert leftover not in opencode_text


def test_pr_review_merge_scheduler_uses_central_mutation_credential() -> None:
"""Ensure mechanical PR queue handling uses the central mutation credential."""
repo_root = Path(__file__).resolve().parents[3]
policy = central_required_workflow_policy_text()

opencode_config = (repo_root / "opencode.jsonc").read_text(encoding="utf-8")
assert '"openai/o3"' in opencode_config
assert '"openai/o4-mini"' in opencode_config
assert_local_review_workflows_removed()
assert "selected workflow mutation" in policy
assert "credential, not by a maintainer's local `gh` session" in policy
Expand Down
Loading