Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
7536d97
fix(autofix): resolve live NVIDIA NIM models instead of a retired pin
devin-ai-integration[bot] Aug 20, 2026
fddd6ee
docs(tests): complete live model resolver coverage
seonghobae Aug 20, 2026
656d506
fix(nim): use validated HTTPS connection for catalog lookup
seonghobae Aug 20, 2026
6315f50
fix(security): enforce TLS verification for NIM catalog
seonghobae Aug 20, 2026
6cdd24a
fix(autofix): close NIM catalog connection explicitly
seonghobae Aug 20, 2026
acac253
Merge branch 'main' into devin/1787237546-autofix-live-model-resolution
opencode-agent[bot] Aug 20, 2026
1a887a7
fix(nim): document reviewed TLS scan exception
seonghobae Aug 20, 2026
ee33f66
Merge branch 'main' into devin/1787237546-autofix-live-model-resolution
seonghobae Aug 21, 2026
6d28e6a
docs(autofix): align live model contract
seonghobae Aug 21, 2026
1df5004
docs(autofix): clarify historical model contract
seonghobae Aug 21, 2026
924da99
fix(autofix): keep live fallback models reasoning-capable
seonghobae Aug 21, 2026
b7dcb63
docs(autofix): document all NVIDIA credential steps
seonghobae Aug 21, 2026
fad116f
Merge branch 'main' into devin/1787237546-autofix-live-model-resolution
opencode-agent[bot] Aug 21, 2026
5d0869b
Merge branch 'main' into devin/1787237546-autofix-live-model-resolution
opencode-agent[bot] Aug 21, 2026
15531dd
fix(autofix): consume resolved model from runner environment
seonghobae Aug 21, 2026
c67bb0f
Merge branch 'main' into devin/1787237546-autofix-live-model-resolution
seonghobae Aug 21, 2026
df68dbf
test: align Strix scheduler contract with current queue policy
seonghobae Aug 21, 2026
edab578
Merge remote-tracking branch 'origin/main' into work/pr1172
seonghobae Aug 21, 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
65 changes: 54 additions & 11 deletions .github/workflows/pr-review-autofix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,39 @@ jobs:
python3 "$GITHUB_WORKSPACE/trusted-autofix-source/scripts/ci/pr_review_autofix_context.py" \
"${context_args[@]}"

- name: Resolve live NVIDIA NIM autofix models
env:
NVIDIA_API_KEY: ${{ secrets.NVIDIA_NIM_API_KEY }}
# Ordered preference pools. NVIDIA retires hosted models on published
# end-of-life dates and then answers HTTP 410 Gone, so the worker
# resolves the first pool entry the provider still serves instead of
# hard-coding one id that a lifecycle event can retire.
AUTOFIX_MODEL_CANDIDATES: >-
${{ vars.NVIDIA_NIM_AUTOFIX_MODEL_CANDIDATES ||
'nvidia/llama-3.3-nemotron-super-49b-v1.5 nvidia/nemotron-3-super-120b-a12b
nvidia/llama-3.1-nemotron-ultra-253b-v1' }}
AUTOFIX_SMALL_MODEL_CANDIDATES: >-
${{ vars.NVIDIA_NIM_AUTOFIX_SMALL_MODEL_CANDIDATES || 'nvidia/nemotron-3-nano-30b-a3b nvidia/llama-3.1-nemotron-nano-8b-v1' }}
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
resolver="$GITHUB_WORKSPACE/trusted-autofix-source/scripts/ci/select_nvidia_nim_model.py"
autofix_model_id="$(
python3 "$resolver" --role primary --candidates "$AUTOFIX_MODEL_CANDIDATES"
)"
autofix_small_model_id="$(
python3 "$resolver" --role small --candidates "$AUTOFIX_SMALL_MODEL_CANDIDATES"
)"
echo "Resolved autofix model: ${autofix_model_id}"
echo "Resolved autofix small model: ${autofix_small_model_id}"
{
printf 'AUTOFIX_MODEL_ID=%s\n' "$autofix_model_id"
printf 'AUTOFIX_SMALL_MODEL_ID=%s\n' "$autofix_small_model_id"
} >>"$GITHUB_ENV"
Comment thread
seonghobae marked this conversation as resolved.
Comment on lines +270 to +281

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

📝 Info: Resolved model ids propagate correctly via GITHUB_ENV

The resolve step exports AUTOFIX_MODEL_ID/AUTOFIX_SMALL_MODEL_ID through $GITHUB_ENV, so later steps read them as shell env vars. The command substitutions use set -e, so a resolver exit 1 aborts the job before the ids are written. Fail-closed flow is sound.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.


- name: Prepare isolated OpenCode autofix workspace
env:
OPENCODE_AUTOFIX_WORKDIR: ${{ runner.temp }}/opencode-autofix-project
Expand Down Expand Up @@ -277,10 +310,13 @@ jobs:
Do not execute shell commands. Do not invent broad features or claim external approval/check latency is fixed.
Queued reviews or checks remain merge blockers, but their latency is not a reason to invent a code change or stop the broader scheduler from processing other eligible work.
EOF
jq -n --arg workspace "$TARGET_WORKSPACE" '{
jq -n \
--arg workspace "$TARGET_WORKSPACE" \
--arg model_id "$AUTOFIX_MODEL_ID" \
--arg small_model_id "$AUTOFIX_SMALL_MODEL_ID" '{
Comment thread
seonghobae marked this conversation as resolved.
"$schema": "https://opencode.ai/config.json",
"model": "nvidia-nim/mistralai/mistral-small-4-119b-2603",
"small_model": "nvidia-nim/nvidia/nemotron-3-nano-30b-a3b",
"model": "nvidia-nim/\($model_id)",
"small_model": "nvidia-nim/\($small_model_id)",
"enabled_providers": ["nvidia-nim"],
"permission": {
"edit": {
Expand All @@ -306,8 +342,7 @@ jobs:
"ci-autofix": {
"description": "Conservative CI pull request review autofix agent",
"mode": "primary",
"model": "nvidia-nim/mistralai/mistral-small-4-119b-2603",
"reasoningEffort": "high",
"model": "nvidia-nim/\($model_id)",
Comment thread
seonghobae marked this conversation as resolved.
"prompt": "{file:./autofix-prompt.md}",
"steps": 12,
"permission": {
Expand Down Expand Up @@ -341,8 +376,8 @@ jobs:
"apiKey": "{env:NVIDIA_API_KEY}"
},
"models": {
"mistralai/mistral-small-4-119b-2603": {
"name": "Mistral Small 4 119B 2603",
($model_id): {
"name": $model_id,
Comment thread
seonghobae marked this conversation as resolved.
"tool_call": true,
"reasoning": true,
"options": {
Expand All @@ -353,8 +388,8 @@ jobs:
"output": 4096
}
},
"nvidia/nemotron-3-nano-30b-a3b": {
"name": "Nemotron 3 Nano 30B A3B",
($small_model_id): {
"name": $small_model_id,
"tool_call": true,
"reasoning": true,
"limit": {
Comment thread
seonghobae marked this conversation as resolved.
Comment thread
seonghobae marked this conversation as resolved.
Comment thread
seonghobae marked this conversation as resolved.
Expand All @@ -371,7 +406,6 @@ jobs:
if: env.RESOLVE_CONFLICT != 'true'
env:
NVIDIA_API_KEY: ${{ secrets.NVIDIA_NIM_API_KEY }}
MODEL: nvidia-nim/mistralai/mistral-small-4-119b-2603
SHARE: "false"
NPM_CONFIG_IGNORE_SCRIPTS: "true"
NO_COLOR: "1"
Expand All @@ -382,6 +416,11 @@ jobs:
echo "::error::NVIDIA_NIM_API_KEY is required for scheduled OpenCode autofix."
exit 1
fi
if [ -z "${AUTOFIX_MODEL_ID:-}" ]; then
echo "::error::Resolved NVIDIA NIM autofix model is missing."
exit 1
fi
MODEL="nvidia-nim/${AUTOFIX_MODEL_ID}"
prompt_file="${RUNNER_TEMP}/opencode-autofix-prompt.md"
allowed_paths_zlist="${RUNNER_TEMP}/pr-review-autofix-allowed-paths.zlist"
allowed_paths_context="$(
Expand Down Expand Up @@ -546,7 +585,6 @@ jobs:
GITHUB_TOKEN: ${{ secrets.PR_REVIEW_MERGE_TOKEN || secrets.OPENCODE_APPROVE_TOKEN || steps.target_app_token.outputs.token }}
GH_TOKEN: ${{ secrets.PR_REVIEW_MERGE_TOKEN || secrets.OPENCODE_APPROVE_TOKEN || steps.target_app_token.outputs.token }}
MUTATION_CREDENTIAL_AVAILABLE: ${{ secrets.PR_REVIEW_MERGE_TOKEN != '' || secrets.OPENCODE_APPROVE_TOKEN != '' || steps.target_app_token.outputs.available == 'true' }}
MODEL: nvidia-nim/mistralai/mistral-small-4-119b-2603
SHARE: "false"
NPM_CONFIG_IGNORE_SCRIPTS: "true"
NO_COLOR: "1"
Expand All @@ -561,6 +599,11 @@ jobs:
echo "::error::NVIDIA_NIM_API_KEY is required for scheduled OpenCode autofix."
exit 1
fi
if [ -z "${AUTOFIX_MODEL_ID:-}" ]; then
echo "::error::Resolved NVIDIA NIM autofix model is missing."
exit 1
fi
MODEL="nvidia-nim/${AUTOFIX_MODEL_ID}"
cd "$TARGET_WORKSPACE"

# Merge the base branch into the detached head. A clean merge stays
Expand Down
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Semantic Versioning where the repository publishes a release.
- Run the bounded Clearfolio PR review-feedback repair caller at minute 23 of every hour while keeping the shared scheduler free of product-specific timers and repository names for modular reuse by naruon, contextual-orchestrator, Inkspan, and other CWL services.
- Run the bounded DiskSage repair heartbeat at minute 37 of every hour, dispatch no more than one exact-head repair, and wait two hours before redispatching an unchanged head so legitimate OpenCode or NVIDIA NIM latency does not create duplicate writers.
- Run the bounded fast-mlsirm repair heartbeat at minute 49 of every hour with one-dispatch scope and a two-hour same-head floor, without weakening true-parameter recovery, CPU/GPU parity, skipped-test, or Rust-ownership gates.
- Use NVIDIA NIM `mistralai/mistral-small-4-119b-2603` with explicit high reasoning for scheduled repair and `nvidia/nemotron-3-nano-30b-a3b` for bounded helper work instead of GitHub Models in the write-capable autofix worker.
- Resolve the write-capable autofix worker's NVIDIA NIM models at run time from ordered, operator-controlled reasoning-capable candidate pools instead of hard-coding one model id: the retired `mistralai/mistral-small-4-119b-2603` answered every repair request with HTTP 410 after its end-of-life date, so the whole hourly repair loop failed on a routine provider lifecycle event. Resolution queries the live provider catalog, keeps explicit high reasoning without sending it to instruct fallbacks, and fails closed with an actionable annotation when the catalog is unreachable or every candidate is retired.
- Apply one NUL-delimited exact-path and complete pre/post-worktree verification contract to both ordinary review repair and merge-conflict repair rather than relying on a visible post-model diff for the ordinary path.

### Changed
Expand Down
5 changes: 3 additions & 2 deletions docs/automation/hourly-review-repair.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ not overlap its successor. At most one repair dispatch is created per run.

The caller passes only the established `PR_REVIEW_MERGE_TOKEN` and
`OPENCODE_APPROVE_TOKEN` scheduler credentials. It does not receive or forward
`NVIDIA_NIM_API_KEY`; the model credential is scoped exclusively to the two
OpenCode execution steps in the separately reviewed autofix worker.
`NVIDIA_NIM_API_KEY`; the model credential is scoped exclusively to the live
model-resolution step and the two OpenCode execution steps in the separately
reviewed autofix worker.

## Orgmetra execution contract

Expand Down
5 changes: 3 additions & 2 deletions docs/doctoring/clearfolio-hourly-review-caller.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,9 @@ The caller passes exactly two established optional scheduler credentials:

It does not use `secrets: inherit`. It does not receive
`NVIDIA_NIM_API_KEY`, because queue inspection and dispatch are not model
execution. The NVIDIA credential is bound only inside the separately reviewed
`PR Review Autofix` workflow's two OpenCode execution steps.
execution. The NVIDIA credential is bound only inside three provider-bound
steps in the separately reviewed `PR Review Autofix` workflow: live model
resolution and its two OpenCode execution steps.

Both the caller and reusable scheduler keep the workflow-generated
`GITHUB_TOKEN` read-only with only `contents: read`; neither declares job-level
Expand Down
97 changes: 75 additions & 22 deletions docs/doctoring/hourly-nvidia-nim-autofix.md
Comment thread
seonghobae marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -67,21 +67,61 @@ OpenAI-compatible adapter and NVIDIA hosted endpoint:
https://integrate.api.nvidia.com/v1
```

The primary repair model is `mistralai/mistral-small-4-119b-2603`. The
`ci-autofix` agent and its model configuration both request high reasoning
through OpenCode's provider-option contract (`reasoningEffort: "high"`). NVIDIA's
Mistral Small 4 NIM API documents the corresponding request behavior as
The primary repair model is resolved at run time, not hard-coded. NVIDIA retires
hosted models on published end-of-life dates and then answers every request with
HTTP 410 `Gone`, which turns a normal provider lifecycle event into a total
outage of the repair loop. The `Resolve live NVIDIA NIM autofix models` step
therefore runs `scripts/ci/select_nvidia_nim_model.py`, which reads the provider
catalog (`GET /v1/models`) and selects the first entry of an ordered preference
pool that the provider still serves:

| Role | Pool variable | Default order |
| --- | --- | --- |
| primary | `NVIDIA_NIM_AUTOFIX_MODEL_CANDIDATES` | `nvidia/llama-3.3-nemotron-super-49b-v1.5`, `nvidia/nemotron-3-super-120b-a12b`, `nvidia/llama-3.1-nemotron-ultra-253b-v1` |
| small | `NVIDIA_NIM_AUTOFIX_SMALL_MODEL_CANDIDATES` | `nvidia/nemotron-3-nano-30b-a3b`, `nvidia/llama-3.1-nemotron-nano-8b-v1` |

Both default pools contain only reasoning-capable NVIDIA NIM models, because
the generated provider entries deliberately request high reasoning. Operator
overrides must preserve that contract; a non-reasoning instruct model must not
be added to either pool. To change the preference order, set the matching
Actions variable on this repository; no workflow edit is required. Resolution
is fail-closed: an unreachable or unparsable catalog, and a pool whose every
entry is retired, both stop the run with an actionable annotation instead of
silently substituting an arbitrary model. The resolved ids are exported once
as `AUTOFIX_MODEL_ID` and `AUTOFIX_SMALL_MODEL_ID` and are the only model
identifiers the generated OpenCode configuration and both `opencode run`
invocations use, so the writer agent and its provider entry cannot drift apart.

Each resolved model entry requests high reasoning through OpenCode's
provider-option contract (`reasoningEffort: "high"`). NVIDIA's
NIM LLM API documents the corresponding request behavior as
`reasoning_effort: "high"`, which enables the model's reasoning mode. The small
model used for bounded helper work remains `nvidia/nemotron-3-nano-30b-a3b` and
is not a fallback provider. GitHub Models configuration, identifiers, base URLs,
and model-auth fallbacks are absent from the scheduled autofix execution path.
model is used for bounded helper work only and is not a fallback provider.
GitHub Models configuration, identifiers, base URLs, and model-auth fallbacks are
absent from the scheduled autofix execution path. Model resolution shares the
same `NVIDIA_NIM_API_KEY` credential as the two OpenCode runs, and no other step
receives it.

The high-reasoning setting is deliberate for write-capable review repair. This
workflow optimizes correctness, evidence quality, and controllability rather than
latency. It does not imply that deeper reasoning is universally superior; the
setting is an explicit operational choice for this bounded, security-sensitive
writer role and remains subject to exact-head regression evidence.

### Reviewed static-analysis exception

The catalog resolver keeps Python's `http.client.HTTPSConnection` because the
destination host is allowlisted, the request path is derived only from that
validated endpoint, and the call supplies `ssl.create_default_context()`.
Python documents that an explicit `SSLContext` controls the HTTPS options and
that certificate and hostname checks are enabled by default. Semgrep's generic
HTTPSConnection rule is therefore a reviewed false positive at this one sink.
The source uses one rule-specific `# nosemgrep` comment, and the resolver test
asserts that the exception occurs exactly once and that the default TLS context
remains present. This is a scoped exception, not a repository-wide suppression;
the central SARIF gate removes only explicitly suppressed results and continues
to fail on every other finding.

## Credential boundary

The organization secret is bound as:
Expand All @@ -90,10 +130,10 @@ The organization secret is bound as:
NVIDIA_API_KEY: ${{ secrets.NVIDIA_NIM_API_KEY }}
```

It is present only on the two steps that execute OpenCode: ordinary
review-feedback repair and merge-conflict repair. Metadata collection,
checkout, context preparation, validation, commit, and push do not receive the
NVIDIA credential. A missing key is a fatal configuration error rather than a
It is present only on the three steps that need a provider credential: live
model resolution, ordinary review-feedback repair, and merge-conflict repair.
Comment thread
seonghobae marked this conversation as resolved.
Metadata collection, checkout, context preparation, validation, commit, and push
do not receive the NVIDIA credential. A missing key is a fatal configuration error rather than a
signal to choose another provider.

The ordinary model execution step does not bind a GitHub write token. Its later
Expand Down Expand Up @@ -264,20 +304,22 @@ That exact-head evidence is historical after any later documentation commit and
must be re-established on the new current head.

The later writer-model and mutation-authority hardening was likewise captured by
permanent RED contracts before the implementation changed. Those contracts pin
the exact NVIDIA Mistral Small 4 writer, high reasoning, absence of the obsolete
Mistral Nemotron identifier, explicit mutation credentials, and guards that run
before any Git write. Predecessor-head successes are historical TDD evidence,
not merge evidence. The final integrated head must establish every required
quality, security, review, and protection gate again.
permanent RED contracts before the implementation changed. Those predecessor
contracts asserted a fixed writer-model identity, high reasoning, absence of the
obsolete Mistral Nemotron identifier, explicit mutation credentials, and guards
that run before any Git write. The current implementation resolves the writer at
run time, so those predecessor assertions are historical TDD evidence rather
than a live model pin or merge evidence. The final integrated head must establish
every required quality, security, review, and protection gate again.

## Verification contract

Automated tests prove:

1. the caller retains its approved one-hour cadence;
2. OpenCode enables only NVIDIA NIM, uses the exact Mistral Small 4 writer with
high reasoning, and receives the model key only in its two execution steps;
2. OpenCode enables only NVIDIA NIM, resolves the primary and small model ids
from the live ordered candidate pools, requests high reasoning, and receives
those ids only in its two execution steps;
3. missing model credentials fail closed and model children receive no GitHub or
OIDC write credential;
4. mutation-capable ordinary and conflict paths accept only established explicit
Expand Down Expand Up @@ -345,9 +387,20 @@ GitHub, Inc. (n.d.-b). *Secrets reference*. GitHub Docs. Retrieved August 7,
NVIDIA Corporation. (n.d.-a). *LLM APIs*. NVIDIA API Catalog. Retrieved August
7, 2026, from https://docs.api.nvidia.com/nim/reference/llm-apis

NVIDIA Corporation. (2026). *Query the Mistral-Small-4-119B-2603 API*. NVIDIA
NIM for Vision Language Models. Retrieved August 8, 2026, from
https://docs.nvidia.com/nim/vision-language-models/1.7.0/examples/mistral-small-4-119b-2603/api.html
NVIDIA Corporation. (n.d.-d). *NVIDIA NIM for large language models:
OpenAI-compatible API reference*. Retrieved August 20, 2026, from
https://docs.nvidia.com/nim/large-language-models/latest/api-reference.html

Python Software Foundation. (2026). *http.client — HTTP protocol client*.
Python 3.14 documentation. Retrieved August 21, 2026, from
https://docs.python.org/3.14/library/http.client.html

Semgrep, Inc. (2026). *Rule structure syntax examples: Rule ideas*.
Retrieved August 21, 2026, from
https://semgrep.dev/docs/writing-rules/rule-ideas

OpenAI. (2025). *API reference: List models*. Retrieved August 20, 2026, from
https://platform.openai.com/docs/api-reference/models/list

NVIDIA Corporation. (n.d.-c). *NVIDIA / nemotron-3-nano-30b-a3b*. NVIDIA API
Catalog. Retrieved August 7, 2026, from
Expand Down
1 change: 1 addition & 0 deletions organization_commercial_readiness_fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ def __init__(
repositories: list[dict[str, Any]],
snapshots: dict[str, list[RepositorySnapshot | Exception]],
) -> None:
"""Record the repositories and per-repository snapshot scripts to replay."""
self.repositories = repositories
self.snapshots = snapshots
self.dispatched_repairs: list[tuple[str, str]] = []
Expand Down
1 change: 1 addition & 0 deletions scripts/ci/organization_commercial_readiness_loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ class GitHubClient:
"""Use the GitHub CLI as an authenticated, bounded REST transport."""

def __init__(self, token: str, *, timeout_seconds: int = 60) -> None:
"""Bind a required organization-scoped token and a per-call timeout."""
if not token:
raise GitHubError("GH_TOKEN is required for organization coordination")
self._token = token
Expand Down
Loading
Loading