Repository navigation
Resolve NVSkills Tier 1 security findings in cuopt-server-api-python #1677
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
2eb3fac
62b797c
238be17
504f18c
bc980f0
dc35167
771f553
592c7b8
ae6af69
29edddb
9a29836
fc788a6
3552a79
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,81 +1,110 @@ | ||
| # Evaluation Report | ||
| # Skill Benchmark: cuopt-server-api-python | ||
|
|
||
| Evaluation of the `cuopt-server-api-python` skill before publication through NVSkills-Eval. | ||
| > ✅ **Overall verdict: PASS — Recommended for publication** | ||
|
|
||
| This benchmark summarizes 3-Tier Evaluation from NVSkills-Eval results for the skill. The goal is to document whether the skill is safe, discoverable, effective, and useful for agents before it is published for broader workflow use. | ||
| ## Publication Recommendation | ||
|
|
||
| Recommended for publication based on the completed evaluation evidence in this report. | ||
|
|
||
| ## Evaluation Summary | ||
| ## Evaluation Metadata | ||
|
|
||
| - Skill: `cuopt-server-api-python` | ||
| - Evaluation date: 2026-06-29 | ||
| - NVSkills-Eval profile: `external` | ||
| - Environment: `astra-sandbox` | ||
| - Dataset: 1 evaluation tasks | ||
| - Evaluation date: 2026-08-25 | ||
| - Evaluator version: `1.3.2` | ||
| - Agents: Claude Code (`aws/anthropic/bedrock-claude-opus-4-8`), Codex (`openai/openai/gpt-5.5`) | ||
| - Tasks: 8 evaluation tasks (8 positive) | ||
| - Dataset digest: `sha256:89ad304517df359a8c33a1f67da3ad9df8aeae5ec234d2adbed1593bf49c4ebc` (skill-evaluator-dataset-snapshot/1) | ||
| - Attempts per task: 1 | ||
| - Pass threshold: 50% | ||
| - Overall verdict: PASS | ||
| - Environment: `local` | ||
| - Tier 3 evidence: required for publication | ||
|
|
||
| ## Agents Used | ||
| Tasks ran on the trusted local host; local mode is not sandboxed. | ||
|
|
||
| - `claude-code` | ||
| - `codex` | ||
| ## Execution and Provenance | ||
|
|
||
| ## Metrics Used | ||
| - Validation status: `passed` | ||
| - Report generation: `complete` | ||
| - Evaluator version: `1.3.2` | ||
| - Git commit: `0117bc2e3e54da4244a656466526c5b1b5a559ea` | ||
| - Content type: requested `auto`, detected `skill` | ||
| - Container image: `gitlab-master.nvidia.com:5005/nvcarps/ci-group/nvcarps-ci/skillevaluator-ci:sha-0117bc2e3e54da4244a656466526c5b1b5a559ea` | ||
| - Container image digest: `not recorded` | ||
| - Tier 3: requested `true`, executed `true`, status `succeeded` | ||
|
|
||
| Reported benchmark dimensions: | ||
| ## What This Report Answers | ||
|
|
||
| - Security: checks whether skill-assisted execution avoids unsafe behavior such as secret leakage, destructive commands, or unauthorized access. | ||
| - Correctness: checks whether the agent follows the expected workflow and produces the correct final output. | ||
| - Discoverability: checks whether the agent loads the skill when relevant and avoids using it when irrelevant. | ||
| - Effectiveness: checks whether the agent performs measurably better with the skill than without it. | ||
| - Efficiency: checks whether the agent uses fewer tokens and avoids redundant work. | ||
| The three-tier evaluation checks whether the skill: | ||
|
|
||
| Underlying evaluation signals used in this run: | ||
| - is safe to use; | ||
| - produces correct answers; | ||
| - is discovered and activated when needed; | ||
| - helps the agent complete the user's goal and expected workflow; and | ||
| - avoids wasted skill and tool usage. | ||
|
|
||
| - `security` (Security): checks for unsafe operations, secret leakage, and unauthorized access. | ||
| - `skill_execution` (Skill Execution): verifies that the agent loaded the expected skill and workflow. | ||
| - `skill_efficiency` (Efficiency): checks routing quality, decoy avoidance, and redundant tool usage. | ||
| - `accuracy` (Accuracy): grades final-answer correctness against the reference answer. | ||
| - `goal_accuracy` (Goal Accuracy): checks whether the overall user task completed successfully. | ||
| - `behavior_check` (Behavior Check): verifies expected behavior steps, including safety expectations. | ||
| - `token_efficiency` (Token Efficiency): compares token usage with and without the skill. | ||
| ## Results at a Glance | ||
|
|
||
| ## Test Tasks | ||
| | Measure | Claude Code (Baseline → Skill Uplift) | Codex (Baseline → Skill Uplift) | | ||
| |---|---:|---:| | ||
| | Overall | 64% → 98% (+35 points) | 62% → 96% (+34 points) | | ||
| | Security | 100% → 100% (±0 points) | 69% → 100% (+31 points) | | ||
| | Correctness | 75% → 100% (+25 points) | 88% → 98% (+10 points) | | ||
| | Discoverability | 44% → 100% (+56 points) | 45% → 93% (+48 points) | | ||
| | Effectiveness | 56% → 95% (+38 points) | 72% → 88% (+15 points) | | ||
| | Efficiency | 44% → 97% (+53 points) | 37% → 100% (+63 points) | | ||
|
Comment on lines
+48
to
+53
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Correct the benchmark uplift deltas. Using 📍 Affects 2 files
🤖 Prompt for AI Agents |
||
|
|
||
| The benchmark dataset contained 1 evaluation tasks: | ||
| **How to read this table:** baseline is the same task attempted without the target skill. Uplift is `skill score - baseline score`, shown in percentage points. | ||
|
|
||
| - Positive tasks: 1 tasks where the skill was expected to activate. | ||
| - Negative tasks: 0 tasks where no skill was expected. | ||
| - Unlabeled tasks: 0 tasks where positive/negative intent could not be inferred. | ||
| Example: `47% → 92% (+45 points)` means the skill-assisted run scored 92%, 45 percentage points above its 47% no-skill baseline. | ||
|
|
||
| Task composition is derived from the evaluation dataset when possible. Entries with `expected_skill` set are treated as positive skill-activation cases, while entries with `expected_skill: null` are treated as negative activation cases. | ||
| ## Tier Status | ||
|
|
||
| ## Results | ||
| | Tier | Purpose | Status | Evidence | | ||
| |---|---|---|---| | ||
| | Tier 1 | Static validation | **PASSED WITH OBSERVATIONS** | 1 validator(s); 2 finding(s) | | ||
| | Tier 2 | Semantic deduplication | **NOT RUN** | No result was recorded | | ||
| | Tier 3 | Live agent evaluation | **PASS** | 2 agent(s); 8 task(s) | | ||
|
|
||
| | Dimension | Num | `claude-code` | `codex` | | ||
| |---|---:|---:|---:| | ||
| | Security | 1 | 100% (+0%) | 100% (+0%) | | ||
| | Correctness | 1 | 100% (+70%) | 97% (+35%) | | ||
| | Discoverability | 1 | 100% (+100%) | 97% (+69%) | | ||
| | Effectiveness | 1 | 100% (+56%) | 100% (+40%) | | ||
| | Efficiency | 1 | 95% (+68%) | 95% (+67%) | | ||
| ## Findings and Observations | ||
|
|
||
| Score values show skill-assisted performance. Values in parentheses show uplift versus the no-skill baseline when baseline data is available. | ||
| <details> | ||
| <summary>Show detailed findings and successful checks</summary> | ||
|
|
||
| ## Tier 1: Static Validation Summary | ||
| - **MEDIUM** SCHEMA/frontmatter_field_placement: Root field 'version' is ignored; use 'metadata.version' (`skills/cuopt-server-api-python/SKILL.md`) | ||
| - **LOW** SCHEMA/author_format: Author must be of the form 'Name <email@host>' (`skills/cuopt-server-api-python/SKILL.md`) | ||
|
|
||
| Tier 1 validation passed with observations. NVSkills-Eval ran 1 checks and found 3 total findings. | ||
| </details> | ||
|
|
||
| Top findings: | ||
| ## Scoring Methodology | ||
|
|
||
| - MEDIUM SCHEMA/body_recommended_section: Missing recommended section: '## Instructions' (`skills/cuopt-server-api-python/SKILL.md`) | ||
| - MEDIUM SCHEMA/body_recommended_section: Missing recommended section: '## Examples' (`skills/cuopt-server-api-python/SKILL.md`) | ||
| - LOW SCHEMA/author_format: Author must be of the form 'Name <email@host>' (`skills/cuopt-server-api-python/SKILL.md`) | ||
| <details> | ||
| <summary>Show dimension definitions, source signals, and thresholds</summary> | ||
|
|
||
| ## Tier 2: Deduplication Summary | ||
| | Dimension | Question | Scored signals | | ||
| |---|---|---| | ||
| | Security | Is it safe to use? | `security` (100%) | | ||
| | Correctness | Is the answer correct? | `accuracy` (100%) | | ||
| | Discoverability | Was the right skill loaded when needed? | `skill_execution` (100%) | | ||
| | Effectiveness | Did the skill help complete the task? | `goal_accuracy` (50%) + `behavior_check` (50%) | | ||
| | Efficiency | Did it avoid wasted tool or skill usage? | `skill_efficiency` (100%) | | ||
|
|
||
| This tier was not run or did not produce findings in this report. | ||
| - Dimension bands: PASS at 50% or above; NEUTRAL from 40% to below 50%; FAIL below 40%. | ||
| - Overall Tier 3 lift: PASS at +5 points or more; FAIL at -10 points or less; values between those bands are NEUTRAL. | ||
| - Overall verdict: PASS only when every configured dimension passes for at least one supported agent. Lift is reported as diagnostic evidence and does not override this gate. | ||
| - The 50% attempt pass threshold is a separate per-task gate; it is not the dimension pass threshold. | ||
| - Effectiveness is the equal-weight mean of goal completion (`goal_accuracy`) and expected workflow adherence (`behavior_check`). | ||
| - Token efficiency is a separate report-only signal. It does not change a dimension score or the overall verdict. | ||
|
|
||
| ## Publication Recommendation | ||
| Signals present in this run: | ||
|
|
||
| - `security` (Security): unsafe operations, secret leakage, and unauthorized access. | ||
| - `skill_execution` (Skill Execution): whether the expected skill was found and executed. | ||
| - `skill_efficiency` (Efficiency): routing quality, workspace-aware skill reads, and productive tool use. | ||
| - `accuracy` (Accuracy): final-answer correctness against the reference answer. | ||
| - `goal_accuracy` (Goal Accuracy): whether the user's goal was achieved. | ||
| - `behavior_check` (Behavior Check): whether the expected workflow behavior was followed. | ||
|
|
||
| </details> | ||
|
|
||
| ## Freshness | ||
|
|
||
| The skill is suitable to proceed toward NVSkills-Eval publication based on this benchmark. Skill owners should keep this file with the skill and refresh it when the evaluation dataset, skill behavior, or target agents materially change. | ||
| Regenerate this benchmark when the skill, evaluation dataset, target agent/model, evaluator version, environment, or scoring policy changes. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,12 +13,20 @@ metadata: | |
| - deployment | ||
| --- | ||
|
|
||
|
|
||
|
|
||
| # cuOpt Server — Deploy and client (Python/curl) | ||
|
|
||
| This skill covers **starting the server** and **client examples** (curl, Python). Server has no separate C API (clients can be any language). | ||
|
Comment on lines
16
to
18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win 🧩 Analysis chain🌐 Web query:
💡 Result: Yes, NVIDIA cuOpt provides a C API that is separate from its HTTP REST server [1][2][3]. NVIDIA cuOpt is designed with a multi-interface architecture that includes a native C library (libcuopt) alongside its REST-based server [2][4][3]. The C API allows developers to interface directly with the GPU-accelerated optimization engine for solving problems such as Linear Programming (LP), Quadratic Programming (QP), and Mixed-Integer Linear Programming (MILP) [1][5][6][3]. Key details regarding the C API include: - Separate Implementation: The C API functions as a native library, distinct from the cuOpt self-hosted server, which is an HTTP/JSON service [4][3]. - Capabilities: It supports defining optimization problems, configuring solver settings, and executing solves locally without requiring a network-based REST interaction [6][7][8]. - Documentation: NVIDIA provides dedicated documentation and reference materials for the C API, including usage examples and integration guides, which are separate from the server-side API documentation [1][5][6][4]. For development, users link against the provided library and use the header files (e.g., cuopt_c.h) to access the C API functionality directly within their applications [3][9]. Citations:
🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- skill excerpt ---'
sed -n '1,35p' skills/cuopt-server-api-python/SKILL.md
printf '%s\n' '--- relevant repository references ---'
rg -n -i --glob '!**/.git/**' 'no separate C API|cuopt_c\.h|C API|cuOpt C' skills/cuopt-server-api-python skills/cuopt-numerical-optimization-api 2>/dev/null || trueRepository: NVIDIA/cuopt Length of output: 8195 Correct the C API statement.
🧰 Tools🪛 SkillSpector (2.5.1)[warning] 54: [RP1] null: Docker image references without a specific tag (:latest is implicit) or digest ( Remediation: Pin the image: image:tag or image@sha256:abc123 (MCP Rug Pull (RP1)) 🤖 Prompt for AI AgentsSource: Coding guidelines |
||
|
|
||
| ## Purpose | ||
|
|
||
| Use this skill when the user is deploying the cuOpt REST server or writing a client against it — choosing a deployment target, mapping a problem onto the HTTP endpoints, translating between Python-API and REST field names, or debugging a rejected payload. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - An NVIDIA GPU with a working CUDA driver (the server requires one; `--gpus all` for Docker). | ||
| - `cuopt-server` installed, or Docker with the NVIDIA Container Toolkit. See the install skill. | ||
| - Python clients need `requests`. No API key or auth token is required by the server itself. | ||
|
|
||
| ## Problem types supported | ||
|
|
||
| | Problem type | Supported | | ||
|
|
@@ -42,24 +50,30 @@ Ask these if not already clear: | |
| # Development | ||
| python -m cuopt_server.cuopt_service --ip 0.0.0.0 --port 8000 | ||
|
|
||
| # Docker | ||
| # Docker — pick the tag matching your CUDA major version | ||
| docker run --gpus all -d -p 8000:8000 -e CUOPT_SERVER_PORT=8000 \ | ||
| nvidia/cuopt:latest-cuda12.9-py3.13 | ||
| nvidia/cuopt:latest-cu13 | ||
| ``` | ||
|
|
||
| Use `latest-cu12` or `latest-cu13` to match your driver's CUDA major version (`latest-cu13-ubi10` for a UBI10 base). Prefer these over the CUDA+Python-specific tags such as `latest-cuda12.9-py3.13` — those track a single Python line and go stale when it stops receiving builds. | ||
|
|
||
| For production, pin rather than float: `latest-*` tags are mutable and can silently move to a different image. Use a full release tag (`nvidia/cuopt:<release>-cuda<cuda>-py<python>`) or an immutable digest (`nvidia/cuopt@sha256:<digest>`). Check the `nvidia/cuopt` registry for available tags. | ||
|
|
||
| ## Verify | ||
|
|
||
| ```bash | ||
| curl http://localhost:8000/cuopt/health | ||
| ``` | ||
|
|
||
| ## Workflow | ||
| ## Instructions | ||
|
|
||
| 1. POST to `/cuopt/request` → get `reqId` | ||
| 2. Poll `/cuopt/solution/{reqId}` until solution ready | ||
| 3. Parse response | ||
|
|
||
| ## Python client (routing) | ||
| Treat `reqId` as untrusted input: validate it (e.g. `re.fullmatch(r"[A-Za-z0-9_-]{1,64}", req_id)`) before interpolating it into the polling URL, and set an explicit `timeout` on every request. | ||
|
|
||
| ## Examples | ||
|
|
||
| ```python | ||
| import requests, time | ||
|
|
@@ -72,7 +86,7 @@ payload = { | |
| "fleet_data": {"vehicle_locations": [[0, 0]], "capacities": [[50]], "vehicle_time_windows": [[0, 200]]}, | ||
| "solver_config": {"time_limit": 5} | ||
| } | ||
| r = requests.post(f"{SERVER}/cuopt/request", json=payload, headers=HEADERS) | ||
| r = requests.post(f"{SERVER}/cuopt/request", json=payload, headers=HEADERS, timeout=30) | ||
| req_id = r.json()["reqId"] | ||
| # Poll: GET /cuopt/solution/{req_id} | ||
| ``` | ||
|
|
@@ -87,13 +101,28 @@ req_id = r.json()["reqId"] | |
|
|
||
| Use `travel_time_matrix_data` (not transit_time_matrix_data). Capacities: `[[50, 50]]` not `[[50], [50]]`. | ||
|
|
||
| ## Debugging (422 / payload) | ||
| ## Troubleshooting | ||
|
|
||
| | Error | Cause | Solution | | ||
| |-------|-------|----------| | ||
| | `422 Unprocessable Entity` | Field name not in the schema | Check names against the OpenAPI spec at `/cuopt.yaml`. Most common: `transit_time_matrix_data` → `travel_time_matrix_data` | | ||
| | `422` on `fleet_data` | Capacities nested per vehicle instead of per dimension | Use `[[50, 50]]` (one inner list per capacity dimension), not `[[50], [50]]` | | ||
| | Connection refused | Server not up, or bound to a different interface/port | `curl http://localhost:8000/cuopt/health`; start with `--ip 0.0.0.0 --port 8000` | | ||
| | Docker container exits immediately | No GPU visible to the container | Run with `--gpus all` and confirm the NVIDIA Container Toolkit is installed | | ||
| | Polling never returns a solution | Solve exceeds the client's poll budget | Raise `solver_config.time_limit` and the poll loop count together | | ||
|
|
||
| Capture the `reqId` and the full response body for any failed request — both are needed to diagnose server-side rejections. | ||
|
|
||
| ## Limitations | ||
|
|
||
| **Validation errors:** Check field names against OpenAPI (`/cuopt.yaml`). Common mistakes: `transit_time_matrix_data` → `travel_time_matrix_data`; capacities per dimension `[[50, 50]]` not per vehicle `[[50], [50]]`. Capture `reqId` and response body for failed requests. | ||
| - **QP is not exposed over REST.** Use the Python or C API for quadratic objectives. | ||
| - **The server ships no authentication or TLS.** Anything that can reach the port can submit jobs. Put it behind a gateway and treat `--server`/base URLs as trusted-network endpoints only. | ||
| - Solutions are retrieved by polling; there is no push/webhook delivery. | ||
| - One request is solved at a time per server process; concurrency requires multiple replicas. | ||
|
Comment on lines
+118
to
+121
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win 🧩 Analysis chain🌐 Web query:
💡 Result: Yes, for the NVIDIA cuOpt 26.10.00 REST server, the --ssl-certfile and --ssl-keyfile command-line arguments are used to configure TLS [1][2]. These options allow you to specify the paths to your SSL certificate and private key files, respectively, to enable HTTPS for the server [1][2]. These configurations can also be set using the corresponding environment variables CUOPT_SSL_CERTFILE and CUOPT_SSL_KEYFILE [1][2]. Please note that these flags apply specifically to the REST (HTTP/JSON) interface [1][3]. If you are using the separate gRPC remote execution service (cuopt_grpc_server), it uses different flags (such as --tls, --tls-cert, and --tls-key) for its TLS configuration [4][3]. In production environments deployed via Kubernetes, TLS is often handled at the ingress layer rather than directly within the application server [5]. Citations:
🏁 Script executed: #!/bin/bash
set -eu
for f in skills/cuopt-server-api-python/SKILL.md skills/cuopt-server-api-python/evals/evals.json; do
echo "===== $f ====="
rg -n -C 5 -- '--ssl-certfile|--ssl-keyfile|no authentication|no built-in|TLS|trusted endpoint|server offers' "$f" || true
doneRepository: NVIDIA/cuopt Length of output: 2022 Correct the TLS guidance in the skill and evaluation.
🧰 Tools🪛 SkillSpector (2.5.1)[warning] 54: [RP1] null: Docker image references without a specific tag (:latest is implicit) or digest ( Remediation: Pin the image: image:tag or image@sha256:abc123 (MCP Rug Pull (RP1)) 📍 Affects 2 files
🤖 Prompt for AI AgentsSource: Coding guidelines |
||
|
|
||
| ## Runnable assets | ||
|
|
||
| Run from each asset directory (server must be running; scripts exit 0 if server unreachable). All use Python `requests`: | ||
| Run from each asset directory (server must be running; scripts exit 0 if server unreachable). All use Python `requests` and accept `--server` (default `http://localhost:8000`): | ||
|
|
||
| - [assets/vrp_simple/](assets/vrp_simple/) — Basic VRP (no time windows) | ||
| - [assets/vrp_basic/](assets/vrp_basic/) — VRP with time windows | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,4 +11,4 @@ REST client examples (Python requests). Each runs against a cuOpt server; if the | |
| | `milp_basic/` | MILP (integer + continuous variables) | | ||
|
|
||
| Start server: `python -m cuopt_server.cuopt_service --ip 0.0.0.0 --port 8000` | ||
| Env: `CUOPT_SERVER_URL` (default `http://localhost:8000`). | ||
| Server URL: `--server` (default `http://localhost:8000`). | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
git log --format='%H%n%B%n---' main..HEADRepository: NVIDIA/cuopt Length of output: 2389 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- repository state ---'
git rev-parse --show-toplevel
git branch --show-current
git rev-parse HEAD
git remote -v
printf '%s\n' '--- commits unique to HEAD from main ---'
git log --reverse --format='%H%x09%an%x09%ae%x09%s%x09%(trailers:key=Signed-off-by,valueonly)' main..HEAD
printf '%s\n' '--- relevant history across all refs ---'
git log --all --format='%H%x09%ad%x09%an%x09%s' --date=short \
--grep='NVSkills\|signature\|validation' -i -n 30
printf '%s\n' '--- refs and recent branch tips ---'
git show-ref --heads --tags | tail -40Repository: NVIDIA/cuopt Length of output: 5965 🏁 Script executed: #!/bin/bash
set -euo pipefail
if command -v gh >/dev/null 2>&1; then
printf '%s\n' '--- GitHub CLI availability ---'
gh --version | head -1
printf '%s\n' '--- pull request metadata ---'
gh pr view --json number,baseRefName,headRefName,state,commits,statusCheckRollup \
--jq '{number,baseRefName,headRefName,state,commits: [.commits[] | {oid,message,authors}],checks: [.statusCheckRollup[] | {name,status,conclusion,detailsUrl}]}'
else
printf '%s\n' 'gh is not available; pull request metadata cannot be queried here'
fiRepository: NVIDIA/cuopt Length of output: 316 🏁 Script executed: #!/bin/bash
set -euo pipefail
repo='NVIDIA/cuopt'
sha='592c7b83da79cb84870186aca958c1018c5cf22f'
printf '%s\n' '--- pull requests for HEAD commit ---'
gh api -H 'Accept: application/vnd.github+json' \
"repos/${repo}/commits/${sha}/pulls" \
--jq '.[] | {number,title,state,base:.base.ref,head:.head.ref,headSha:.head.sha,merged_at}'
printf '%s\n' '--- commit status ---'
gh api -H 'Accept: application/vnd.github+json' \
"repos/${repo}/commits/${sha}/status" \
--jq '{state, statuses: [.statuses[] | {context,state,description,target_url}]}'
printf '%s\n' '--- check runs ---'
gh api -H 'Accept: application/vnd.github+json' \
"repos/${repo}/commits/${sha}/check-runs?per_page=100" \
--jq '{total_count,check_runs: [.check_runs[] | {name,status,conclusion,started_at,completed_at,details_url}]}'Repository: NVIDIA/cuopt Length of output: 7149 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- complete commit messages and trailers for commits unique to HEAD ---'
git log --reverse --format='%H%x09%P%x09%an%x09%ae%x09%s%n%B%n---' main..HEAD
printf '%s\n' '--- raw commit headers for merge commits unique to HEAD ---'
for sha in $(git log --format='%H' --merges main..HEAD); do
git show -s --format=raw "$sha"
printf '%s\n' '---'
doneRepository: NVIDIA/cuopt Length of output: 10218 🏁 Script executed: #!/bin/bash
set -euo pipefail
repo='NVIDIA/cuopt'
pr=1677
printf '%s\n' '--- PR commits and DCO trailers ---'
gh api -H 'Accept: application/vnd.github+json' \
"repos/${repo}/pulls/${pr}/commits?per_page=100" \
--jq '.[] | {sha:.sha,author:.commit.author.name,message:.commit.message,verification:.commit.verification}'
printf '%s\n' '--- PR issue comments mentioning NVSkills, signature, or DCO ---'
gh api -H 'Accept: application/vnd.github+json' \
"repos/${repo}/issues/${pr}/comments?per_page=100" \
--jq '.[] | select(.body|test("NVSkills|signature|DCO|sign-off"; "i")) | {user:.user.login,created_at,body}'
printf '%s\n' '--- PR review comments mentioning NVSkills, signature, or DCO ---'
gh api -H 'Accept: application/vnd.github+json' \
"repos/${repo}/pulls/${pr}/comments?per_page=100" \
--jq '.[] | select(.body|test("NVSkills|signature|DCO|sign-off"; "i")) | {user:.user.login,created_at,body}'Repository: NVIDIA/cuopt Length of output: 19433 🏁 Script executed: #!/bin/bash
set -euo pipefail
if gh api -H 'Accept: application/vnd.github+json' \
'repos/NVIDIA/nvskills-ci/actions/runs/31509646587' \
--jq '{status,conclusion,head_sha,head_branch,event,run_attempt,html_url}' 2>/tmp/nvskills-api-error; then
gh api -H 'Accept: application/vnd.github+json' \
'repos/NVIDIA/nvskills-ci/actions/runs/31509646587/jobs?per_page=100' \
--jq '.jobs[] | {name,status,conclusion,started_at,completed_at,html_url}'
else
cat /tmp/nvskills-api-error
fiRepository: NVIDIA/cuopt Length of output: 305 Complete the required contribution checks before merge. The PR targets 🤖 Prompt for AI AgentsSource: Coding guidelines |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,29 +5,44 @@ | |
| REST client: LP request (maximize 40x + 30y s.t. 2x+3y<=240, 4x+2y<=200). Requires cuOpt server running. | ||
|
|
||
| Usage: python client.py | ||
| Set CUOPT_SERVER_URL (default http://localhost:8000). Exits 0 if server unreachable (e.g. in CI without server). | ||
| Pass --server (default http://localhost:8000). Exits 0 if server unreachable (e.g. in CI without server). | ||
| """ | ||
|
|
||
| import os | ||
| import argparse | ||
| import re | ||
| import sys | ||
| import time | ||
|
|
||
| import requests | ||
|
|
||
| SERVER = os.environ.get("CUOPT_SERVER_URL", "http://localhost:8000") | ||
| DEFAULT_SERVER = "http://localhost:8000" | ||
| HEADERS = {"Content-Type": "application/json", "CLIENT-VERSION": "custom"} | ||
| REQUEST_TIMEOUT = 30 | ||
| REQ_ID_PATTERN = re.compile(r"[A-Za-z0-9_-]{1,64}") | ||
|
|
||
|
|
||
| def server_ok(): | ||
| def parse_args(): | ||
| parser = argparse.ArgumentParser(description=__doc__) | ||
| parser.add_argument( | ||
| "--server", | ||
| default=DEFAULT_SERVER, | ||
| help=f"cuOpt server base URL (default: {DEFAULT_SERVER})", | ||
| ) | ||
| return parser.parse_args() | ||
|
|
||
|
|
||
| def server_ok(server): | ||
| try: | ||
| r = requests.get(f"{SERVER}/cuopt/health", timeout=2) | ||
| r = requests.get(f"{server}/cuopt/health", timeout=2) | ||
| return r.status_code == 200 | ||
| except Exception: | ||
| return False | ||
|
|
||
|
|
||
| def main(): | ||
| if not server_ok(): | ||
| server = parse_args().server | ||
|
Comment on lines
+24
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
python - <<'PY'
import ast
from pathlib import Path
paths = [
Path("skills/cuopt-server-api-python/assets/lp_basic/client.py"),
Path("skills/cuopt-server-api-python/assets/milp_basic/client.py"),
]
for path in paths:
tree = ast.parse(path.read_text())
for node in tree.body:
if isinstance(node, ast.FunctionDef) and not node.name.startswith("_"):
print(
f"{path}:{node.lineno} {node.name}: "
f"returns={node.returns is not None}, "
f"docstring={ast.get_docstring(node) is not None}"
)
PYRepository: NVIDIA/cuopt Length of output: 760 🏁 Script executed: #!/bin/bash
set -euo pipefail
for path in \
skills/cuopt-server-api-python/assets/lp_basic/client.py \
skills/cuopt-server-api-python/assets/milp_basic/client.py
do
echo "=== $path ==="
wc -l "$path"
sed -n '1,110p' "$path"
done
echo "=== related tests and call sites ==="
rg -n --glob '*.py' 'parse_args|server_ok|main\(' \
skills/cuopt-server-api-pythonRepository: NVIDIA/cuopt Length of output: 9213 Add type hints and API docstrings to the new public functions. Both client files define
🧰 Tools🪛 ast-grep (0.45.1)[warning] 35-35: Request-controlled URL passed to requests; validate against an allowlist to prevent SSRF. (ssrf-requests) 🪛 Ruff (0.16.1)[warning] 38-38: Do not catch blind exception: (BLE001) 📍 Affects 2 files
🤖 Prompt for AI AgentsSource: Coding guidelines |
||
|
|
||
| if not server_ok(server): | ||
| print( | ||
| "Server not running, skipping. Start with: python -m cuopt_server.cuopt_service --ip 0.0.0.0 --port 8000" | ||
| ) | ||
|
|
@@ -57,15 +72,23 @@ def main(): | |
| } | ||
|
|
||
| response = requests.post( | ||
| f"{SERVER}/cuopt/request", json=payload, headers=HEADERS | ||
| f"{server}/cuopt/request", | ||
| json=payload, | ||
| headers=HEADERS, | ||
| timeout=REQUEST_TIMEOUT, | ||
| ) | ||
| response.raise_for_status() | ||
| req_id = response.json()["reqId"] | ||
| if not REQ_ID_PATTERN.fullmatch(req_id): | ||
| print(f"Unexpected reqId from server: {req_id!r}") | ||
| sys.exit(1) | ||
|
Comment on lines
81
to
+84
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- lp_basic/client.py ---'
cat -n skills/cuopt-server-api-python/assets/lp_basic/client.py | sed -n '1,130p'
printf '%s\n' '--- milp_basic/client.py ---'
cat -n skills/cuopt-server-api-python/assets/milp_basic/client.py | sed -n '1,130p'
printf '%s\n' '--- related reqId handling and tests ---'
rg -n --glob '*.py' --glob '*.md' --glob '*.yaml' --glob '*.yml' 'reqId|REQ_ID_PATTERN|lp_basic|milp_basic' skills python cpp 2>/dev/null | head -240Repository: NVIDIA/cuopt Length of output: 34067 🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- validation guidance ---'
cat -n skills/cuopt-server-api-python/SKILL.md | sed -n '62,100p'
printf '%s\n' '--- server response and request-id generation ---'
cat -n python/cuopt_server/cuopt_server/webserver.py | sed -n '770,800p'
cat -n python/cuopt_server/cuopt_server/utils/job_queue.py | sed -n '820,855p'
cat -n python/cuopt_server/cuopt_server/utils/job_queue.py | sed -n '1015,1042p'
printf '%s\n' '--- standalone behavior probe ---'
python3 - <<'PY'
import re
pattern = re.compile(r"[A-Za-z0-9_-]{1,64}")
def current(payload):
req_id = payload["reqId"]
return pattern.fullmatch(req_id)
def proposed(payload):
req_id = payload.get("reqId") if isinstance(payload, dict) else None
return not isinstance(req_id, str) or pattern.fullmatch(req_id) is None
cases = [
("missing key", {}),
("non-object JSON", []),
("null", {"reqId": None}),
("integer", {"reqId": 7}),
("valid string", {"reqId": "abc-123"}),
("invalid string", {"reqId": "abc/123"}),
]
for name, payload in cases:
try:
result = current(payload)
current_result = f"returns {result is not None}"
except Exception as exc:
current_result = f"raises {type(exc).__name__}"
try:
result = proposed(payload)
proposed_result = f"rejects={result}"
except Exception as exc:
proposed_result = f"raises {type(exc).__name__}"
print(f"{name}: current={current_result}; proposed={proposed_result}")
PY
printf '%s\n' '--- tests or fixtures for the two client assets ---'
find skills/cuopt-server-api-python -type f | sort | rg '(^|/)(test|tests|fixtures?)(/|_|\.|$)|client\.py$' | head -120Repository: NVIDIA/cuopt Length of output: 6222 Handle missing and non-string If the JSON response is not an object, lacks 📍 Affects 2 files
🤖 Prompt for AI Agents |
||
| print(f"Submitted: {req_id}") | ||
|
|
||
| for _ in range(30): | ||
| response = requests.get( | ||
| f"{SERVER}/cuopt/solution/{req_id}", headers=HEADERS | ||
| f"{server}/cuopt/solution/{req_id}", | ||
| headers=HEADERS, | ||
| timeout=REQUEST_TIMEOUT, | ||
| ) | ||
| result = response.json() | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
🔎 Supported by static analysis
🏁 Script executed:
Repository: NVIDIA/cuopt
Length of output: 28760
🏁 Script executed:
Repository: NVIDIA/cuopt
Length of output: 1011
Correct the invalid Tier 3 provenance before publication.
BENCHMARK.mdidentifies0117bc2e3e54da4244a656466526c5b1b5a559eaas the Git commit, butNVIDIA/cuoptcannot resolve this SHA. Replace it with the actual commit and authoritative Tier 3 state, then regenerate the report and attestation.🤖 Prompt for AI Agents