cue-ai 0.9.0 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +40 -0
- package/README.md +82 -33
- package/bin/cue-review-progress +107 -0
- package/bin/cue-review-watch +98 -0
- package/dist/cue.js +7352 -3744
- package/package.json +16 -5
- package/profiles/_types.ts +9 -0
- package/profiles/backend/profile.yaml +2 -0
- package/profiles/blog-writer/profile.yaml +10 -0
- package/profiles/browser/profile.yaml +9 -2
- package/profiles/builder/profile.yaml +3 -6
- package/profiles/career/profile.yaml +13 -2
- package/profiles/claude-api/profile.yaml +1 -1
- package/profiles/commerce/profile.yaml +27 -3
- package/profiles/core/logo.png +0 -0
- package/profiles/core/profile.yaml +62 -2
- package/profiles/dash-merge-test/profile.yaml +109 -0
- package/profiles/designer/profile.yaml +2 -0
- package/profiles/designer-medusa-next/profile.yaml +4 -1
- package/profiles/designer-medusa-vite/profile.yaml +4 -1
- package/profiles/docs-writer/profile.yaml +3 -1
- package/profiles/eu-tender-research/README.md +48 -0
- package/profiles/eu-tender-research/logo.png +0 -0
- package/profiles/eu-tender-research/profile.yaml +108 -0
- package/profiles/finance/logo.png +0 -0
- package/profiles/finance/profile.yaml +46 -0
- package/profiles/frontend/profile.yaml +5 -9
- package/profiles/growth/profile.yaml +2 -3
- package/profiles/gstack/profile.yaml +15 -0
- package/profiles/higgsfield/profile.yaml +3 -0
- package/profiles/hyperframes/logo.png +0 -0
- package/profiles/hyperframes/profile.yaml +59 -0
- package/profiles/improver/profile.yaml +88 -0
- package/profiles/marketing/profile.yaml +0 -3
- package/profiles/medusa-dev/profile.yaml +2 -0
- package/profiles/medusa-next/profile.yaml +2 -3
- package/profiles/medusa-vite/profile.yaml +2 -3
- package/profiles/n8n/logo.png +0 -0
- package/profiles/n8n/profile.yaml +50 -0
- package/profiles/nextjs/profile.yaml +2 -3
- package/profiles/ops/profile.yaml +2 -0
- package/profiles/postizz/profile.yaml +13 -3
- package/profiles/python/profile.yaml +3 -0
- package/profiles/research/profile.yaml +3 -1
- package/profiles/schema.json +10 -0
- package/profiles/secops/profile.yaml +2 -0
- package/profiles/seo/profile.yaml +56 -0
- package/profiles/skill-writer/profile.yaml +8 -0
- package/profiles/ssh/profile.yaml +32 -0
- package/profiles/strapi/logo.png +0 -0
- package/profiles/strapi/profile.yaml +45 -0
- package/profiles/stripe/logo.png +0 -0
- package/profiles/stripe/profile.yaml +1 -0
- package/profiles/supabase/logo.png +0 -0
- package/profiles/supabase/profile.yaml +85 -0
- package/profiles/vercel/logo.png +0 -0
- package/profiles/vercel/profile.yaml +25 -1
- package/profiles/vite/profile.yaml +4 -3
- package/profiles/web-frontend-base/profile.yaml +5 -4
- package/profiles/webshop/profile.yaml +23 -5
- package/profiles/x-growth-bot/profile.yaml +44 -0
- package/resources/icons/generate-icons.py +128 -2
- package/resources/mcps/configs/claude.sanitized.json +42 -0
- package/resources/mcps/configs/codex.sanitized.json +7 -0
- package/resources/skills/skills/career/resume-version-manager/SKILL.md +351 -0
- package/resources/skills/skills/career/salary-negotiation-prep/SKILL.md +378 -0
- package/resources/skills/skills/content/pdf/SKILL.md +2 -0
- package/resources/skills/skills/content/postiz-cards/SKILL.md +48 -0
- package/resources/skills/skills/content/postiz-cards/scripts/analytics.sh +38 -0
- package/resources/skills/skills/content/postiz-cards/scripts/card.sh +42 -0
- package/resources/skills/skills/content/postiz-cards/scripts/lint.py +38 -0
- package/resources/skills/skills/design/headless-gif-demo/SKILL.md +1 -1
- package/resources/skills/skills/design/readme-svg-design/SKILL.md +1 -1
- package/resources/skills/skills/eu-funding/grant-outreach/SKILL.md +70 -0
- package/resources/skills/skills/eu-funding/hu-grant-finder/SKILL.md +114 -0
- package/resources/skills/skills/eu-funding/hu-grant-finder/evals.md +26 -0
- package/resources/skills/skills/eu-funding/ted-tender-search/SKILL.md +80 -0
- package/resources/skills/skills/eu-funding/ted-tender-search/evals.md +26 -0
- package/resources/skills/skills/eu-funding/ted-tender-search/scripts/ted-search.sh +46 -0
- package/resources/skills/skills/event-design/wedding-invitations/SKILL.md +1 -1
- package/resources/skills/skills/github/gx-agents/SKILL.md +96 -0
- package/resources/skills/skills/gstack/design-shotgun/SKILL.md +1 -1
- package/resources/skills/skills/marketing/ab-test-analyzer/SKILL.md +1 -1
- package/resources/skills/skills/marketing/ab-test-setup-and-analysis/SKILL.md +1 -1
- package/resources/skills/skills/marketing/account-structure-review/SKILL.md +1 -1
- package/resources/skills/skills/marketing/ad-copy-variant-generator/SKILL.md +1 -1
- package/resources/skills/skills/marketing/ad-extension-audit/SKILL.md +1 -1
- package/resources/skills/skills/marketing/ad-spend-allocator/SKILL.md +1 -1
- package/resources/skills/skills/marketing/anomaly-detection/SKILL.md +1 -1
- package/resources/skills/skills/marketing/attribution-model-comparison/SKILL.md +1 -1
- package/resources/skills/skills/marketing/audience-overlap-analysis/SKILL.md +7 -1
- package/resources/skills/skills/marketing/bid-strategy-recommendations/SKILL.md +7 -1
- package/resources/skills/skills/marketing/budget-scenario-planner/SKILL.md +6 -1
- package/resources/skills/skills/marketing/campaign-naming-convention-builder/SKILL.md +7 -1
- package/resources/skills/skills/marketing/channel-mix-optimizer/SKILL.md +7 -1
- package/resources/skills/skills/marketing/client-report-narratives/SKILL.md +6 -1
- package/resources/skills/skills/marketing/competitor-creative-analysis/SKILL.md +1 -1
- package/resources/skills/skills/marketing/competitor-teardown/SKILL.md +1 -1
- package/resources/skills/skills/marketing/content-repurposer/SKILL.md +1 -1
- package/resources/skills/skills/marketing/conversion-path-analysis/SKILL.md +1 -1
- package/resources/skills/skills/marketing/cpa-diagnostics/SKILL.md +1 -1
- package/resources/skills/skills/marketing/creative-fatigue-detection/SKILL.md +1 -1
- package/resources/skills/skills/marketing/day-hour-performance-breakdown/SKILL.md +1 -1
- package/resources/skills/skills/marketing/device-performance-split/SKILL.md +1 -1
- package/resources/skills/skills/marketing/e2e-seo-assistant/SKILL.md +1 -1
- package/resources/skills/skills/marketing/email-sequence-writer/SKILL.md +1 -1
- package/resources/skills/skills/marketing/frequency-cap-recommendations/SKILL.md +1 -1
- package/resources/skills/skills/marketing/geo-performance-analysis/SKILL.md +1 -1
- package/resources/skills/skills/marketing/google-ads-audit/SKILL.md +1 -1
- package/resources/skills/skills/marketing/icp-research-assistant/SKILL.md +1 -1
- package/resources/skills/skills/marketing/keyword-cannibalization-check/SKILL.md +1 -1
- package/resources/skills/skills/marketing/landing-page-audit/SKILL.md +1 -1
- package/resources/skills/skills/marketing/landing-page-audit-quick/SKILL.md +1 -1
- package/resources/skills/skills/marketing/linkedin-ads-audit/SKILL.md +1 -1
- package/resources/skills/skills/marketing/meta-ads-audit/SKILL.md +1 -1
- package/resources/skills/skills/marketing/pacing-monitor/SKILL.md +1 -1
- package/resources/skills/skills/marketing/performance-benchmarking/SKILL.md +1 -1
- package/resources/skills/skills/marketing/programmatic-seo-builder/SKILL.md +1 -1
- package/resources/skills/skills/marketing/quality-score-breakdown/SKILL.md +1 -1
- package/resources/skills/skills/marketing/reddit-ads-audit/SKILL.md +1 -1
- package/resources/skills/skills/marketing/retargeting-window-analysis/SKILL.md +1 -1
- package/resources/skills/skills/marketing/roas-forecasting/SKILL.md +1 -1
- package/resources/skills/skills/marketing/search-term-mining/SKILL.md +1 -1
- package/resources/skills/skills/marketing/utm-tracking-generator/SKILL.md +1 -1
- package/resources/skills/skills/marketing/wasted-spend-finder/SKILL.md +1 -1
- package/resources/skills/skills/marketing/weekly-account-summary/SKILL.md +1 -1
- package/resources/skills/skills/meta/awesome-list-submit/SKILL.md +4 -4
- package/resources/skills/skills/meta/cue-dashboard/SKILL.md +109 -0
- package/resources/skills/skills/meta/cue-developer/SKILL.md +161 -0
- package/resources/skills/skills/meta/cue-developer/evals/evals.json +57 -0
- package/resources/skills/skills/meta/cue-developer/references/architecture.md +65 -0
- package/resources/skills/skills/meta/cue-developer/references/build_and_test.md +72 -0
- package/resources/skills/skills/meta/cue-developer/references/contributing.md +75 -0
- package/resources/skills/skills/meta/cue-developer/references/conventions.md +57 -0
- package/resources/skills/skills/meta/cue-developer/references/first_time_setup.md +51 -0
- package/resources/skills/skills/meta/cue-developer/references/skill_and_mcp_authoring.md +84 -0
- package/resources/skills/skills/meta/cue-developer/references/troubleshooting.md +42 -0
- package/resources/skills/skills/meta/delegation-check/SKILL.md +148 -0
- package/resources/skills/skills/meta/delegation-check/specs/scan-algorithm.md +125 -0
- package/resources/skills/skills/meta/delegation-check/specs/separation-rules.md +190 -0
- package/resources/skills/skills/meta/focus/SKILL.md +62 -0
- package/resources/skills/skills/meta/help/SKILL.md +1 -1
- package/resources/skills/skills/meta/integrity-tags/SKILL.md +2 -0
- package/resources/skills/skills/meta/next-steps/SKILL.md +124 -0
- package/resources/skills/skills/meta/next-steps/evals/eval-set.json +92 -0
- package/resources/skills/skills/meta/profile-from-docs/SKILL.md +141 -0
- package/resources/skills/skills/meta/ralph-loop/SKILL.md +83 -0
- package/resources/skills/skills/meta/ralph-loop/scripts/loop.sh +73 -0
- package/resources/skills/skills/meta/skill-simplify/SKILL.md +136 -0
- package/resources/skills/skills/meta/skill-simplify/phases/01-analysis.md +173 -0
- package/resources/skills/skills/meta/skill-simplify/phases/02-optimize.md +104 -0
- package/resources/skills/skills/meta/skill-simplify/phases/03-check.md +145 -0
- package/resources/skills/skills/meta/smart-loader/scripts/smart-lookup.sh +13 -4
- package/resources/skills/skills/meta/verify-council/SKILL.md +182 -0
- package/resources/skills/skills/meta/verify-council/references/lane-prompts.md +103 -0
- package/resources/skills/skills/meta/verify-council/references/workflow.js +217 -0
- package/resources/skills/skills/nvidia/aiq-research/SKILL.md +1 -1
- package/resources/skills/skills/nvidia/cuopt-developer/SKILL.md +16 -1
- package/resources/skills/skills/nvidia/cuopt-developer/resources/contributing.md +2 -2
- package/resources/skills/skills/nvidia/cuopt-developer/resources/numerical_debugging.md +128 -0
- package/resources/skills/skills/nvidia/cuopt-developer/resources/python_bindings.md +2 -9
- package/resources/skills/skills/nvidia/cuopt-developer/resources/vrp_skills.md +166 -0
- package/resources/skills/skills/nvidia/cuopt-install/SKILL.md +2 -10
- package/resources/skills/skills/nvidia/cuopt-numerical-optimization-api-c/SKILL.md +3 -23
- package/resources/skills/skills/nvidia/cuopt-numerical-optimization-api-c/resources/examples.md +40 -20
- package/resources/skills/skills/nvidia/cuopt-numerical-optimization-api-python/SKILL.md +5 -1
- package/resources/skills/skills/nvidia/skill-evolution/SKILL.md +4 -5
- package/resources/skills/skills/research/trendradar/SKILL.md +1 -1
- package/resources/skills/skills/ssh/ssh-config/SKILL.md +94 -0
- package/resources/skills/skills/ssh/ssh-copy/SKILL.md +92 -0
- package/resources/skills/skills/ssh/ssh-harden/SKILL.md +108 -0
- package/resources/skills/skills/ssh/ssh-keys/SKILL.md +82 -0
- package/resources/skills/skills/ssh/ssh-paste-image/LICENSE +28 -0
- package/resources/skills/skills/ssh/ssh-paste-image/SKILL.md +149 -0
- package/resources/skills/skills/ssh/ssh-paste-image/scripts/build.sh +29 -0
- package/resources/skills/skills/ssh/ssh-paste-image/scripts/client/go.mod +3 -0
- package/resources/skills/skills/ssh/ssh-paste-image/scripts/client/main.go +79 -0
- package/resources/skills/skills/ssh/ssh-paste-image/scripts/daemon/ccimgd.service +12 -0
- package/resources/skills/skills/ssh/ssh-paste-image/scripts/daemon/com.ccimgd.plist +20 -0
- package/resources/skills/skills/ssh/ssh-paste-image/scripts/daemon/go.mod +3 -0
- package/resources/skills/skills/ssh/ssh-paste-image/scripts/daemon/main.go +98 -0
- package/resources/skills/skills/ssh/ssh-tunnel/SKILL.md +96 -0
- package/resources/skills/skills/strapi/building-with-strapi/SKILL.md +112 -0
- package/resources/skills/skills/strapi/strapi-cli/SKILL.md +93 -0
- package/resources/skills/skills/strapi/strapi-content-api/SKILL.md +115 -0
- package/resources/skills/skills/strapi/strapi-deploy/SKILL.md +89 -0
- package/resources/skills/skills/strapi/strapi-mcp-setup/SKILL.md +101 -0
- package/resources/skills/skills/strapi/strapi-plugins/SKILL.md +97 -0
- package/resources/skills/skills/tools/context7/SKILL.md +101 -0
- package/resources/skills/skills/tools/opensrc/SKILL.md +1 -1
- package/resources/skills/skills/tools/portless/SKILL.md +186 -0
- package/resources/skills/skills/xbot/operate/SKILL.md +229 -0
- package/src/commands/_index.ts +8 -0
- package/src/commands/ai-score.e2e.test.ts +11 -4
- package/src/commands/ai.ts +3 -4
- package/src/commands/auto-detect.ts +1 -1
- package/src/commands/cli.test.ts +1 -2
- package/src/commands/cli.ts +1 -1
- package/src/commands/cloud.ts +1 -1
- package/src/commands/current.ts +1 -4
- package/src/commands/dash.test.ts +110 -0
- package/src/commands/dash.ts +194 -0
- package/src/commands/dashboard.ts +26 -0
- package/src/commands/diff.ts +1 -1
- package/src/commands/discover.test.ts +1 -1
- package/src/commands/discover.ts +90 -40
- package/src/commands/doctor.test.ts +58 -0
- package/src/commands/doctor.ts +79 -3
- package/src/commands/eval-behavior.ts +1 -1
- package/src/commands/eval.ts +2 -2
- package/src/commands/evolve.ts +4 -3
- package/src/commands/failures.test.ts +1 -1
- package/src/commands/features-batch1.test.ts +6 -1
- package/src/commands/icon.ts +1 -5
- package/src/commands/import-profile.ts +1 -1
- package/src/commands/init.ts +50 -7
- package/src/commands/install-sh.e2e.test.ts +65 -0
- package/src/commands/launch-handoff.e2e.test.ts +88 -0
- package/src/commands/launch.e2e.test.ts +8 -1
- package/src/commands/launch.test.ts +29 -0
- package/src/commands/launch.ts +185 -131
- package/src/commands/lock.ts +0 -1
- package/src/commands/marketplace.ts +0 -4
- package/src/commands/materialize.ts +1 -1
- package/src/commands/mem.ts +341 -0
- package/src/commands/optimizer.ts +0 -3
- package/src/commands/playground.ts +1 -2
- package/src/commands/profile-draft-skill.ts +1 -1
- package/src/commands/replay-whatif.ts +1 -6
- package/src/commands/score.ts +2 -2
- package/src/commands/security.test.ts +88 -0
- package/src/commands/security.ts +74 -28
- package/src/commands/shell.test.ts +65 -4
- package/src/commands/shell.ts +67 -7
- package/src/commands/skills-test.ts +0 -1
- package/src/commands/skills.ts +28 -2
- package/src/commands/sources.ts +1 -2
- package/src/commands/status.ts +2 -6
- package/src/commands/submit-profile.ts +1 -1
- package/src/commands/suggest.ts +35 -10
- package/src/commands/trigger-gaps.test.ts +50 -0
- package/src/commands/trigger-gaps.ts +63 -29
- package/src/commands/update.ts +1 -1
- package/src/commands/validate.ts +16 -4
- package/src/commands/watch-live.ts +1 -1
- package/src/commands/workspace.ts +1 -1
- package/src/index.ts +26 -10
- package/src/lib/active-sessions.ts +1 -1
- package/src/lib/agent-adapters.test.ts +100 -0
- package/src/lib/agent-adapters.ts +2 -2
- package/src/lib/analytics.test.ts +88 -0
- package/src/lib/analytics.ts +82 -1
- package/src/lib/auto-detect.test.ts +10 -4
- package/src/lib/auto-detect.ts +19 -23
- package/src/lib/brand-icons.ts +0 -1
- package/src/lib/cache.ts +2 -3
- package/src/lib/claude-mem-env.test.ts +148 -0
- package/src/lib/claude-mem-env.ts +172 -0
- package/src/lib/combo-history.test.ts +53 -0
- package/src/lib/combo-history.ts +83 -0
- package/src/lib/companion-detect.test.ts +108 -0
- package/src/lib/companion-detect.ts +140 -0
- package/src/lib/companion-fetch.ts +4 -6
- package/src/lib/conditional-skills.test.ts +1 -1
- package/src/lib/config-paths.test.ts +53 -0
- package/src/lib/config-paths.ts +33 -0
- package/src/lib/dashboard-server.test.ts +351 -0
- package/src/lib/dashboard-server.ts +1476 -27
- package/src/lib/debug-log.test.ts +66 -0
- package/src/lib/debug-log.ts +45 -0
- package/src/lib/mcp-catalog.test.ts +102 -0
- package/src/lib/mcp-catalog.ts +193 -0
- package/src/lib/pair-suggestions.test.ts +111 -0
- package/src/lib/pair-suggestions.ts +98 -5
- package/src/lib/permissions.test.ts +76 -0
- package/src/lib/permissions.ts +125 -0
- package/src/lib/picker.test.ts +1106 -1
- package/src/lib/picker.ts +1230 -142
- package/src/lib/plugin-discovery.ts +126 -0
- package/src/lib/pr-poster.ts +1 -1
- package/src/lib/pr-throttle.ts +2 -6
- package/src/lib/profile-linter.test.ts +67 -1
- package/src/lib/profile-linter.ts +59 -14
- package/src/lib/profile-loader.test.ts +21 -0
- package/src/lib/profile-loader.ts +22 -3
- package/src/lib/profile-metrics.ts +2 -6
- package/src/lib/profile-names.test.ts +58 -0
- package/src/lib/repos.test.ts +57 -0
- package/src/lib/repos.ts +167 -0
- package/src/lib/resolver-npx.ts +10 -1
- package/src/lib/runtime-materializer.test.ts +200 -3
- package/src/lib/runtime-materializer.ts +129 -20
- package/src/lib/shared-profiles.ts +2 -3
- package/src/lib/skill-clis.test.ts +113 -0
- package/src/lib/skill-clis.ts +232 -0
- package/src/lib/skill-dependencies.ts +9 -1
- package/src/lib/skill-deps.ts +1 -1
- package/src/lib/skill-linter.ts +1 -1
- package/src/lib/skill-quality.ts +0 -1
- package/src/lib/skill-sandbox.test.ts +1 -1
- package/src/lib/skills-lock.test.ts +1 -1
- package/src/lib/telemetry-consent.ts +3 -5
- package/src/lib/telemetry-report.test.ts +2 -2
- package/src/lib/token-budget.ts +111 -0
- package/src/lib/trigger-gaps.test.ts +70 -0
- package/src/lib/trigger-gaps.ts +48 -6
- package/src/lib/tui/data.ts +1 -5
- package/src/lib/workflow-store.ts +150 -0
- package/src/lib/workspace-secrets.ts +0 -4
- package/src/lib/workspaces.ts +1 -1
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
export const meta = {
|
|
2
|
+
name: 'verify-council',
|
|
3
|
+
description: 'Token-scaled council of independent verifier lanes plus a real-screen visual lane; returns raw verdicts for the author to adjudicate.',
|
|
4
|
+
phases: [
|
|
5
|
+
{ title: 'Council', detail: 'parallel verifier lanes over the diff + claims' },
|
|
6
|
+
],
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// args (all passed by the orchestrating agent — scripts have no FS access):
|
|
11
|
+
// diff string capped unified diff of the change (inline)
|
|
12
|
+
// diffCmd string OR a scoped command the lane runs to get the diff,
|
|
13
|
+
// e.g. "git diff -- src/lib/picker.ts". Use this
|
|
14
|
+
// instead of `diff` for large diffs — same token cost,
|
|
15
|
+
// no giant string through args. One of diff/diffCmd.
|
|
16
|
+
// claims array [{ id, text, kind: 'logic'|'visual', file }]
|
|
17
|
+
// surface string 'code' | 'tui' | 'web' (default 'code')
|
|
18
|
+
// hardToReverse boolean add the skeptic lane when true
|
|
19
|
+
// appCmd string how the visual lane launches a TUI surface (optional)
|
|
20
|
+
// url string dev-server URL for a web surface (optional)
|
|
21
|
+
//
|
|
22
|
+
// The MECHANICAL gate (tests / typecheck / lint) runs in the orchestrator
|
|
23
|
+
// BEFORE this script — a failing gate means no council is spawned at all. This
|
|
24
|
+
// engine is only the agent fan-out; adjudication happens back in the orchestrator
|
|
25
|
+
// on the strong model, so the strong model never enters the parallel barrier.
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
|
|
28
|
+
// The harness may hand `args` to the script as a JSON STRING rather than a parsed
|
|
29
|
+
// object (verified: typeof args === 'string'). Parse it so a.claims / a.diff /
|
|
30
|
+
// a.hardToReverse resolve — otherwise every field reads undefined and the lanes
|
|
31
|
+
// run with no diff and no claims, which makes them roam the whole repo.
|
|
32
|
+
let a = args ?? {}
|
|
33
|
+
if (typeof a === 'string') {
|
|
34
|
+
try { a = JSON.parse(a) } catch { a = {} }
|
|
35
|
+
}
|
|
36
|
+
const diff = String(a.diff ?? '').slice(0, 60000)
|
|
37
|
+
const diffCmd = a.diffCmd ? String(a.diffCmd) : ''
|
|
38
|
+
const claims = Array.isArray(a.claims) ? a.claims : []
|
|
39
|
+
const surface = a.surface ?? 'code'
|
|
40
|
+
const isVisual = surface === 'tui' || surface === 'web'
|
|
41
|
+
|
|
42
|
+
// Each lane either gets the diff inline, or is told to run one scoped command to
|
|
43
|
+
// obtain it (kept scoped so the lane never roams the repo — the token discipline
|
|
44
|
+
// is the same either way).
|
|
45
|
+
const diffSection = diff
|
|
46
|
+
? `The change under review is EXACTLY the diff below. Do not read or report on any
|
|
47
|
+
file outside it; discard any issue you cannot tie to a line shown here.
|
|
48
|
+
--- DIFF ---\n${diff}\n--- END DIFF ---`
|
|
49
|
+
: diffCmd
|
|
50
|
+
? `The change under review is EXACTLY the output of this one command. Run it
|
|
51
|
+
verbatim and treat its output as the complete and only changeset:
|
|
52
|
+
${diffCmd}
|
|
53
|
+
Hard scope: do NOT run \`git diff\` without these exact paths, do NOT open, read,
|
|
54
|
+
or report on any file outside this output, and discard any finding you cannot
|
|
55
|
+
tie to a line inside it. Reviewing the wider repo is a scope violation that wastes
|
|
56
|
+
the token budget.`
|
|
57
|
+
: '(no diff provided — audit the claims against the named files only)'
|
|
58
|
+
|
|
59
|
+
// When the caller lists claims, the lane must answer THOSE claims, not invent its
|
|
60
|
+
// own. Without this the lane drifts into a free-form repo review (more tokens, and
|
|
61
|
+
// the caller's actual claims go unverified).
|
|
62
|
+
const claimsDirective = claims.length
|
|
63
|
+
? `Return exactly one verdict per claim id below, using these ids verbatim. Do not
|
|
64
|
+
add, rename, merge, or invent claim ids. If a claim cannot be judged from the
|
|
65
|
+
changeset, mark it NA with that reason.`
|
|
66
|
+
: `No claims were listed: derive the key correctness claims from the changeset itself.`
|
|
67
|
+
|
|
68
|
+
const claimsBlock = claims.length
|
|
69
|
+
? claims.map((c, i) => `${c.id ?? i + 1}. [${c.kind ?? 'logic'}] ${c.text}${c.file ? ` (${c.file})` : ''}`).join('\n')
|
|
70
|
+
: '(no explicit claims listed — audit the diff for correctness)'
|
|
71
|
+
|
|
72
|
+
// Structured verdict every lane returns, so the orchestrator never parses prose.
|
|
73
|
+
const VERDICT = {
|
|
74
|
+
type: 'object',
|
|
75
|
+
additionalProperties: false,
|
|
76
|
+
required: ['lane', 'summary', 'claims', 'findings'],
|
|
77
|
+
properties: {
|
|
78
|
+
lane: { type: 'string' },
|
|
79
|
+
summary: { type: 'string', description: 'one line' },
|
|
80
|
+
claims: {
|
|
81
|
+
type: 'array',
|
|
82
|
+
items: {
|
|
83
|
+
type: 'object',
|
|
84
|
+
additionalProperties: false,
|
|
85
|
+
required: ['id', 'verdict', 'evidence'],
|
|
86
|
+
properties: {
|
|
87
|
+
id: { type: 'string' },
|
|
88
|
+
verdict: { type: 'string', enum: ['PASS', 'FAIL', 'PARTIAL', 'NA'] },
|
|
89
|
+
evidence: { type: 'string', description: 'quoted line or measured value — never a paraphrase' },
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
findings: {
|
|
94
|
+
type: 'array',
|
|
95
|
+
items: {
|
|
96
|
+
type: 'object',
|
|
97
|
+
additionalProperties: false,
|
|
98
|
+
required: ['severity', 'text'],
|
|
99
|
+
properties: {
|
|
100
|
+
severity: { type: 'string', enum: ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW'] },
|
|
101
|
+
text: { type: 'string' },
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const NEUTRAL = `You are an INDEPENDENT verifier with no shared context. Do not edit anything.
|
|
109
|
+
Several assertions below may be false — do not assume they are correct.
|
|
110
|
+
For each claim return verdict PASS/FAIL/PARTIAL/NA with evidence that QUOTES the
|
|
111
|
+
exact line or MEASURES the value. A remembered or paraphrased line is not evidence.`
|
|
112
|
+
|
|
113
|
+
function correctnessPrompt() {
|
|
114
|
+
return `${NEUTRAL}
|
|
115
|
+
|
|
116
|
+
Lane: correctness. Re-derive each claim strictly from the change.
|
|
117
|
+
${claimsDirective}
|
|
118
|
+
|
|
119
|
+
CLAIMS:
|
|
120
|
+
${claimsBlock}
|
|
121
|
+
|
|
122
|
+
${diffSection}`
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function redteamPrompt() {
|
|
126
|
+
return `${NEUTRAL}
|
|
127
|
+
|
|
128
|
+
Lane: red-team. Review ONLY the change for blocking defects.
|
|
129
|
+
CRITICAL: security holes, data loss, crashes, injection, broken auth.
|
|
130
|
+
HIGH: real bugs, broken contracts, race conditions, wrong logic.
|
|
131
|
+
List each as a finding with its severity. Do not list LOW/style nits as blocking.
|
|
132
|
+
If there are no CRITICAL or HIGH defects, return an empty findings array and
|
|
133
|
+
summary "REVIEW_CLEAN". Map each claim's verdict to NA unless the change disproves it.
|
|
134
|
+
|
|
135
|
+
${diffSection}`
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function visualPrompt() {
|
|
139
|
+
const visualClaims = claims.filter((c) => c.kind === 'visual')
|
|
140
|
+
const vBlock = visualClaims.length
|
|
141
|
+
? visualClaims.map((c, i) => `${c.id ?? i + 1}. ${c.text}`).join('\n')
|
|
142
|
+
: '(measure whatever the diff claims about the rendered surface)'
|
|
143
|
+
const driver = surface === 'web'
|
|
144
|
+
? `Surface: WEB. Use the lightpanda MCP tools (search for them with ToolSearch:
|
|
145
|
+
goto ${a.url ?? '<dev-server-url>'} , then eval getComputedStyle() /
|
|
146
|
+
getBoundingClientRect() on the relevant selectors and return the MEASURED
|
|
147
|
+
pixel values.`
|
|
148
|
+
: `Surface: TUI. Use the cue-tty-watch MCP tools (search for them with ToolSearch):
|
|
149
|
+
launch the app in a tmux pane${a.appCmd ? ` with \`${a.appCmd}\`` : ''}, send_keys_tmux to
|
|
150
|
+
reach the target screen, screenshot it, then find_text / ask_about_image to
|
|
151
|
+
assert each claim against what is ACTUALLY on screen.`
|
|
152
|
+
|
|
153
|
+
return `${NEUTRAL}
|
|
154
|
+
|
|
155
|
+
Lane: visual proof. Drive the REAL rendered surface and report what you observe.
|
|
156
|
+
A code read is NOT acceptable evidence for a visual claim — only a measured or
|
|
157
|
+
screenshotted value counts.
|
|
158
|
+
|
|
159
|
+
${driver}
|
|
160
|
+
|
|
161
|
+
VISUAL CLAIMS:
|
|
162
|
+
${vBlock}`
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function skepticPrompt() {
|
|
166
|
+
return `${NEUTRAL}
|
|
167
|
+
|
|
168
|
+
Lane: skeptic. Your job is to REFUTE the riskiest claim, not confirm it. Default
|
|
169
|
+
each claim to FAIL ("refuted") unless the change makes it undeniable. Be adversarial.
|
|
170
|
+
${claimsDirective}
|
|
171
|
+
|
|
172
|
+
CLAIMS:
|
|
173
|
+
${claimsBlock}
|
|
174
|
+
|
|
175
|
+
${diffSection}`
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Adaptive lane set: 2 default, +visual when visual, +skeptic when hard to reverse.
|
|
179
|
+
const lanes = [
|
|
180
|
+
{ key: 'correctness', prompt: correctnessPrompt() },
|
|
181
|
+
{ key: 'redteam', prompt: redteamPrompt() },
|
|
182
|
+
]
|
|
183
|
+
if (isVisual) lanes.push({ key: 'visual', prompt: visualPrompt() })
|
|
184
|
+
if (a.hardToReverse) lanes.push({ key: 'skeptic', prompt: skepticPrompt() })
|
|
185
|
+
|
|
186
|
+
// Surface the parsed inputs so a misdelivery (e.g. empty claims, no diff) is
|
|
187
|
+
// obvious in the run log instead of silently degrading into a repo-wide roam.
|
|
188
|
+
log(
|
|
189
|
+
`council: ${lanes.map((l) => l.key).join(' + ')} ` +
|
|
190
|
+
`(surface=${surface}, claims=${claims.length}, diff=${diff ? 'inline' : diffCmd ? 'cmd' : 'NONE'})`,
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
phase('Council')
|
|
194
|
+
const verdicts = await parallel(
|
|
195
|
+
lanes.map((l) => () =>
|
|
196
|
+
agent(l.prompt, { label: `lane:${l.key}`, phase: 'Council', schema: VERDICT, model: 'sonnet' })
|
|
197
|
+
.then((v) => ({ ...v, lane: l.key }))
|
|
198
|
+
),
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
const ok = verdicts.filter(Boolean)
|
|
202
|
+
const blocking = ok.flatMap((v) =>
|
|
203
|
+
(v.findings ?? []).filter((f) => f.severity === 'CRITICAL' || f.severity === 'HIGH').map((f) => ({ lane: v.lane, ...f })),
|
|
204
|
+
)
|
|
205
|
+
const failed = ok.flatMap((v) =>
|
|
206
|
+
(v.claims ?? []).filter((c) => c.verdict === 'FAIL' || c.verdict === 'PARTIAL').map((c) => ({ lane: v.lane, ...c })),
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
// Raw material for the orchestrator's Phase-2 adjudication. No strong-model
|
|
210
|
+
// spend happened inside this script.
|
|
211
|
+
return {
|
|
212
|
+
lanes: lanes.map((l) => l.key),
|
|
213
|
+
verdicts: ok,
|
|
214
|
+
blocking,
|
|
215
|
+
disputedClaims: failed,
|
|
216
|
+
clean: blocking.length === 0 && failed.length === 0,
|
|
217
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "
|
|
2
|
+
description: "Use when user says \"deep research this\", \"research the regulatory landscape\", \"synthesize findings from our docs\", \"produce a cited memo\", \"multi-source research\". Routes deep research, multi-source synthesis, regulatory analysis, or enterprise document research through the NVIDIA AI-Q server for structured reports with citations."
|
|
3
3
|
tags: [research, nvidia, aiq, deep-research, enterprise]
|
|
4
4
|
category: nvidia
|
|
5
5
|
version: 2.0.0
|
|
@@ -3,7 +3,6 @@ name: cuopt-developer
|
|
|
3
3
|
version: "26.08.00"
|
|
4
4
|
description: Modify, build, test, debug, and contribute to NVIDIA cuOpt (C++/CUDA, Python, server, CI). Use for solver internals, PRs, DCO, and code conventions.
|
|
5
5
|
---
|
|
6
|
-
|
|
7
6
|
# cuOpt Developer Skill
|
|
8
7
|
|
|
9
8
|
Contribute to the NVIDIA cuOpt codebase. This skill is for modifying cuOpt itself, not for using it.
|
|
@@ -232,3 +231,19 @@ For build/test pitfalls (Cython rebuild, OOM, CUDA driver mismatch, missing `nvc
|
|
|
232
231
|
- **Python binding architecture**: [resources/python_bindings.md](resources/python_bindings.md)
|
|
233
232
|
|
|
234
233
|
_Shell-execution, install, sudo, and outside-workspace policies are covered by [Refusal Rules — Read First](#refusal-rules--read-first) at the top of this skill._
|
|
234
|
+
|
|
235
|
+
## VRP dimension internals (routing engine)
|
|
236
|
+
|
|
237
|
+
When implementing or debugging **VRP dimensions** (constraints, objectives, forward/backward propagation, `combine`, local-search deltas), read:
|
|
238
|
+
|
|
239
|
+
- **`resources/vrp_skills.md`** — architecture contracts, required interfaces, and implementation checklist.
|
|
240
|
+
|
|
241
|
+
Read it **before** adding a new dimension or changing combine semantics.
|
|
242
|
+
|
|
243
|
+
## Numerical issues in non-routing solver internals
|
|
244
|
+
|
|
245
|
+
When a bug surfaces as **wrong-but-plausible** solver output (invalid lower bound, unexpectedly large duals, 10× iteration blow-up after a small change) rather than a crash, read:
|
|
246
|
+
|
|
247
|
+
- **`resources/numerical_debugging.md`** — methodology for locating catastrophic-cancellation sites, the cancellation patterns endemic to cMIR / flow-cover / MIR-style cut construction, and threshold guidance for numerical guards.
|
|
248
|
+
|
|
249
|
+
Apply the *instrument-first, guard-at-the-exact-site* workflow it describes before patching — speculative fixes on these symptoms usually miss.
|
|
@@ -32,11 +32,11 @@ Never push branches directly to the main cuOpt repository. Use the fork workflow
|
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
34
|
# 1. Clone the main repo
|
|
35
|
-
git clone
|
|
35
|
+
git clone https://github.com/NVIDIA/cuopt.git
|
|
36
36
|
cd cuopt
|
|
37
37
|
|
|
38
38
|
# 2. Add your fork as a remote
|
|
39
|
-
git remote add fork
|
|
39
|
+
git remote add fork https://github.com/<your-username>/cuopt.git
|
|
40
40
|
|
|
41
41
|
# 3. Create a branch from the appropriate base
|
|
42
42
|
git checkout -b my-feature-branch
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Debugging Numerical Issues in Numerical Optimization Solver Internals
|
|
2
|
+
|
|
3
|
+
Read this when a solver bug surfaces as **wrong-but-plausible output** rather
|
|
4
|
+
than a crash or assertion.
|
|
5
|
+
|
|
6
|
+
## Symptoms
|
|
7
|
+
|
|
8
|
+
- A lower bound that contradicts a known incumbent (LP claims a value the MIP
|
|
9
|
+
cannot reach).
|
|
10
|
+
- Dual values of order `1e10+` on a problem whose data is `O(1)`–`O(1e5)`.
|
|
11
|
+
- A 10× blow-up in simplex iterations after an algorithmic change that should
|
|
12
|
+
have been cheap.
|
|
13
|
+
- Bit-for-bit reproducibility of the wrong answer across runs — the bug is
|
|
14
|
+
deterministic, not a memory or race issue.
|
|
15
|
+
|
|
16
|
+
The root cause is often **catastrophic cancellation** in a
|
|
17
|
+
floating-point accumulator: `final = Σ(signed contributions)` collapses to a
|
|
18
|
+
value many orders of magnitude smaller than its constituents, leaving the
|
|
19
|
+
result dominated by floating-point noise.
|
|
20
|
+
|
|
21
|
+
## Methodology — Instrument Before Patching
|
|
22
|
+
|
|
23
|
+
The classical mistake is to guess the cancellation site and apply a fix. There
|
|
24
|
+
are usually several candidates and you will guess wrong. Do this instead:
|
|
25
|
+
|
|
26
|
+
### Locate the suspicious region
|
|
27
|
+
|
|
28
|
+
Usually a recent commit or a code path tied to the symptom. Read it end-to-end before adding any instrumentation.
|
|
29
|
+
|
|
30
|
+
### Audit candidate cancellation sites by hand
|
|
31
|
+
|
|
32
|
+
Any floating-point accumulator whose result can be much smaller than its inputs is a candidate.
|
|
33
|
+
Write the list down before you instrument anything.
|
|
34
|
+
|
|
35
|
+
### Instrument each site with a `cancel_ratio = |final| / max(1, Σ|delta|)`
|
|
36
|
+
|
|
37
|
+
Logged per event. A ratio of `1.0` means no cancellation; `1e-9` means ~7 decimal digits of precision lost; `1e-15` means the result is numerical noise.
|
|
38
|
+
|
|
39
|
+
### Reproduce, log, read
|
|
40
|
+
|
|
41
|
+
Sort the log by `cancel_ratio` ascending; the worst offenders are at the top.
|
|
42
|
+
|
|
43
|
+
### Guard at the exact site that's cancelling — not earlier, not later
|
|
44
|
+
|
|
45
|
+
A guard on an upstream accumulator does nothing if cancellation happens downstream; cut-generation paths typically have multiple sites in series.
|
|
46
|
+
|
|
47
|
+
### Re-run and confirm
|
|
48
|
+
|
|
49
|
+
If the symptom persists, your instrumentation missed a site — return to step 2. The cancellation hypothesis is wrong only if every measured ratio is `≥ ~1e-6` and the symptom is still there.
|
|
50
|
+
|
|
51
|
+
## Threshold Guidance
|
|
52
|
+
|
|
53
|
+
A cancellation ratio of `1e-9` leaves ~7 decimal digits of precision in a
|
|
54
|
+
double. Use this as the *machine-safety* floor — a guard at this level only
|
|
55
|
+
rejects results that are essentially noise.
|
|
56
|
+
|
|
57
|
+
A ratio of `1e-4` leaves ~12 digits, which is still numerically clean but
|
|
58
|
+
tight enough that downstream LP solves remain conditioned. Use this for guards
|
|
59
|
+
on quantities that feed back into a basis whose conditioning matters (cut
|
|
60
|
+
RHS, constraint accumulators, anything that becomes a row of `A` after
|
|
61
|
+
addition).
|
|
62
|
+
|
|
63
|
+
When in doubt, log the ratio *without* filtering first, observe the
|
|
64
|
+
distribution across a representative benchmark, and place the threshold at
|
|
65
|
+
least one order of magnitude below the cleanest "bad" case and at least one
|
|
66
|
+
order of magnitude above the cleanest "good" case. Single-instance threshold
|
|
67
|
+
choices tend to over-fit.
|
|
68
|
+
|
|
69
|
+
## Cancellation Sites in Cut Generation
|
|
70
|
+
|
|
71
|
+
Cut-generation routines (Gomory, MIR, complemented-MIR, flow-cover) are
|
|
72
|
+
repeat offenders. They build a cut by combining row data with variable-bound
|
|
73
|
+
substitutions, each of which can introduce a large
|
|
74
|
+
`coefficient × bound_bias` shift. The shifts often sum to a small residual.
|
|
75
|
+
|
|
76
|
+
In a cMIR-style routine, expect **three accumulators in series**, each
|
|
77
|
+
capable of independent cancellation:
|
|
78
|
+
|
|
79
|
+
| # | Accumulator | Cancellation form |
|
|
80
|
+
|---|---|---|
|
|
81
|
+
| 1 | Substituted row RHS | `b − Σ (coef × variable_bound_bias)` |
|
|
82
|
+
| 2 | Cut-LHS constant | `Σ (multiplier × per_arc_constant)` across all arcs |
|
|
83
|
+
| 3 | Final cut RHS subtraction | `cut.rhs = lhs_constant − substituted_b` |
|
|
84
|
+
|
|
85
|
+
Two of the three can have well-behaved ratios individually while the third
|
|
86
|
+
still cancels — site (3) is especially insidious because both inputs can be
|
|
87
|
+
clean on their own and only their *difference* loses precision. A guard at
|
|
88
|
+
only one site is insufficient; instrument all three before deciding where to
|
|
89
|
+
clamp.
|
|
90
|
+
|
|
91
|
+
## Scale-Mismatch Hazard
|
|
92
|
+
|
|
93
|
+
A cut that is mathematically valid by construction can still poison the LP
|
|
94
|
+
basis after addition. If `cut.rhs` is several orders of magnitude below the
|
|
95
|
+
original constraint matrix's typical row scale, the dual simplex needs to
|
|
96
|
+
produce dual values at the inverse scale to express dual feasibility, and
|
|
97
|
+
those duals propagate into the bound.
|
|
98
|
+
|
|
99
|
+
The diagnostic for this is **iteration count**, not the cut shape.
|
|
100
|
+
Re-optimization after cut addition should take `O(few ×)` the original root
|
|
101
|
+
iterations. If it suddenly takes `O(10×)`, the cuts are valid but
|
|
102
|
+
ill-conditioned for the LP.
|
|
103
|
+
|
|
104
|
+
Filters that help, in order of increasing aggressiveness:
|
|
105
|
+
|
|
106
|
+
- Reject cuts with high coefficient dynamism (`max|coef| / min|coef|`).
|
|
107
|
+
- Reject cuts with `|cut.rhs|` much smaller than the original row scale on
|
|
108
|
+
the source row.
|
|
109
|
+
- Suppress variable-bound substitutions whose bias term is itself huge —
|
|
110
|
+
root-cause filter, but rejects more cuts than necessary.
|
|
111
|
+
|
|
112
|
+
Pick the lowest-risk filter that removes the symptom on the failing instance.
|
|
113
|
+
Re-validate on the broader benchmark before declaring the fix done — a guard
|
|
114
|
+
that fixes one instance can quietly suppress healthy cuts on others.
|
|
115
|
+
|
|
116
|
+
## Common Mistakes
|
|
117
|
+
|
|
118
|
+
- **Speculative fix before measurement.** "It's probably the MIR floor at
|
|
119
|
+
large ratios" is a guess. Instrument first; the data usually points
|
|
120
|
+
elsewhere.
|
|
121
|
+
- **Single global guard.** A guard at the first cancellation site won't catch
|
|
122
|
+
the rest. Cut paths typically have 2–3 distinct sites in series.
|
|
123
|
+
- **Confusing "small final value" with "cancellation."** A small `final`
|
|
124
|
+
derived from a small sum of small `delta_i` is healthy. The ratio
|
|
125
|
+
`|final| / Σ|delta_i|` is what distinguishes the two.
|
|
126
|
+
- **Picking the most aggressive (root-cause) filter when a narrow site-guard
|
|
127
|
+
would do.** Be surgical; the narrowest filter that recovers correctness is
|
|
128
|
+
the right one.
|
|
@@ -106,6 +106,8 @@ def Solve(py_data_model_obj, settings, mip=False):
|
|
|
106
106
|
return create_solution(move(sol_ret_ptr), data_model_obj)
|
|
107
107
|
```
|
|
108
108
|
|
|
109
|
+
Always release the GIL around C++ calls that do GPU work — this allows other Python threads to run during solve.
|
|
110
|
+
|
|
109
111
|
### Step 6: C++ implementation receives the call
|
|
110
112
|
|
|
111
113
|
`cpp/src/math_optimization/solver_settings.cu`:
|
|
@@ -145,15 +147,6 @@ settings.reset(new solver_settings_t[int, double]())
|
|
|
145
147
|
# Auto-destroyed when scope exits
|
|
146
148
|
```
|
|
147
149
|
|
|
148
|
-
### Releasing the GIL for GPU work
|
|
149
|
-
|
|
150
|
-
```cython
|
|
151
|
-
with nogil:
|
|
152
|
-
result = move(call_solve(problem_ptr, settings_ptr))
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
Always release the GIL around C++ calls that do GPU work. This allows other Python threads to run during solve.
|
|
156
|
-
|
|
157
150
|
### Bridging C++ enums to Python IntEnum
|
|
158
151
|
|
|
159
152
|
```python
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# cuOpt VRP Dimension Developer Skills
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## `cuopt-dimension-architecture`
|
|
6
|
+
|
|
7
|
+
**When to use**: Before implementing any new constraint or objective in cuOpt.
|
|
8
|
+
|
|
9
|
+
### The forward/backward propagation model
|
|
10
|
+
Each node stores accumulated state (`fwd_X`, `bwd_X`) so that combining any two adjacent fragments is O(1). This is the core design contract that makes cuOpt fast:
|
|
11
|
+
- `fwd_X[k]` = contribution of the prefix `[0..k]`
|
|
12
|
+
- `bwd_X[k]` = contribution of the suffix `[k..n]`
|
|
13
|
+
- No recomputation is needed when a move splits a route at any point
|
|
14
|
+
|
|
15
|
+
### The combine invariant
|
|
16
|
+
`combine(node[k], node[k+1])` must return the **same value for every split point `k`** in a route (within floating-point tolerance — small differences from order of operations are acceptable; large gaps indicate a bug). This is the fundamental correctness contract. Violating it breaks local search delta evaluation (the solver computes `cost_after - cost_before` using combine; if combine is materially inconsistent, deltas are wrong).
|
|
17
|
+
|
|
18
|
+
### Why boundaries double-count
|
|
19
|
+
`fwd_excess[k]` accumulates violations from `[0..k]`. `bwd_excess[k+1]` accumulates violations from `[k+1..n]`. At the join point `k → k+1`, both sides have already "seen" the in-transit state at that boundary — so their sum overcounts the boundary contribution once. The correction term `excess(fwd_state[k])` subtracts the double-counted boundary:
|
|
20
|
+
```
|
|
21
|
+
combine(k, k+1) = fwd_excess[k] + bwd_excess[k+1] - excess(fwd_state[k])
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Required interface for every dimension
|
|
25
|
+
| Method | Description |
|
|
26
|
+
|--------|-------------|
|
|
27
|
+
| `calculate_forward(next)` | Propagate fwd state from `this` to `next`; update `next.fwd_excess` |
|
|
28
|
+
| `calculate_backward(prev)` | Propagate bwd state from `this` to `prev`; update `prev.bwd_excess` |
|
|
29
|
+
| `combine(prev, next)` | O(1) total cost for joining two fragments; must satisfy the invariant |
|
|
30
|
+
| `get_cost(prev, this)` | Same formula as `combine`, called from `next`'s perspective |
|
|
31
|
+
| `compute_cost(n_nodes)` | Full-route cost; must equal `combine(last_node, return_depot)` |
|
|
32
|
+
| `forward_excess` | Returns `fwd_excess` as double |
|
|
33
|
+
| `backward_excess` | Returns `bwd_excess` as double |
|
|
34
|
+
| `forward_feasible` | True if `fwd_excess <= excess_limit` |
|
|
35
|
+
| `backward_feasible` | True if `bwd_excess <= excess_limit` |
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## `cuopt-implement-dimension`
|
|
40
|
+
|
|
41
|
+
**When to use**: When given a constraint/objective description to implement as a new cuOpt dimension.
|
|
42
|
+
|
|
43
|
+
### Step-by-step recipe
|
|
44
|
+
|
|
45
|
+
**Step 1 — Define per-node state**
|
|
46
|
+
Identify the minimal set of scalars needed for O(1) propagation:
|
|
47
|
+
- What is "in transit" at each route position? (e.g. load, type counts, time)
|
|
48
|
+
- What accumulated violation measure can be updated incrementally? (e.g. excess load, incompatibility excess)
|
|
49
|
+
- Separate: *fixed data* (set once from problem input), *forward data*, *backward data*
|
|
50
|
+
|
|
51
|
+
**Step 2 — Write `calculate_forward(next)`**
|
|
52
|
+
```
|
|
53
|
+
propagate accumulated fwd_state from this → next
|
|
54
|
+
apply next node's demand to fwd_state
|
|
55
|
+
compute positional_excess = f(fwd_state_at_next)
|
|
56
|
+
next.fwd_excess = this.fwd_excess + positional_excess // depot nodes: no positional contribution
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Step 3 — Write `calculate_backward(prev)`**
|
|
60
|
+
Mirror of forward, applied in reverse direction. Backward demand direction is opposite to forward (e.g. a pickup that adds +1 forward subtracts -1 backward).
|
|
61
|
+
|
|
62
|
+
**Step 4 — Derive `combine(prev, next)`**
|
|
63
|
+
|
|
64
|
+
`combine` is the **core cost computation for every local search move**: operators evaluate candidate edits by differencing combined fragment costs (`cost_after - cost_before`). It is called extremely often, so **keep it as fast as possible**.
|
|
65
|
+
|
|
66
|
+
- **Typical dimensions** (capacity, distance, simple time windows, etc.): `combine` is **O(1)** — only prefix/suffix scalars and a boundary correction. This is what all current VRP operators assume.
|
|
67
|
+
- **Richer dimensions** can be **much more expensive** — e.g. **O(log n)** in route size `n` when the join cost needs a non-trivial lookup (time-dependent travel times, multiple time windows, profile queries). Prefer precomputed tables or cached state so `combine` stays hot-path friendly; if it must be superlinear, document it and expect fewer applicable operators or higher move-evaluation cost.
|
|
68
|
+
|
|
69
|
+
Write out the invariant formula and verify it equals the total route cost for a complete route:
|
|
70
|
+
```
|
|
71
|
+
total = prev.fwd_excess + next.bwd_excess - boundary_correction(prev.fwd_state)
|
|
72
|
+
```
|
|
73
|
+
where `boundary_correction` removes the double-counted overlap at the join point.
|
|
74
|
+
|
|
75
|
+
**Step 5 — Derive `get_cost(prev, this)` from combine**
|
|
76
|
+
|
|
77
|
+
`get_cost` is on the **same hot path as `combine`**: local search operators call it constantly when scoring edges and fragments. It must stay **as fast as `combine`** — same **O(1)** target for typical dimensions, same risk of **O(log n)** or worse for time-dependent travel, multiple time windows, etc. **Do not** put a separate heavy computation here.
|
|
78
|
+
|
|
79
|
+
`get_cost` is called on the `next` node with `prev` passed in. It must be identical to `combine` — substitute `this` for `next`:
|
|
80
|
+
```
|
|
81
|
+
get_cost(prev, this) == combine(prev, this)
|
|
82
|
+
```
|
|
83
|
+
Implement by **delegating to `combine`** (or inlining the same formula). Do **not** derive an independent formula; any deviation breaks coherence assertions and can hide a slower code path.
|
|
84
|
+
|
|
85
|
+
**Step 6 — Write `compute_cost(n_nodes)`**
|
|
86
|
+
Must equal `combine(last_service_node, fresh_return_depot)` within the same floating-point tolerance:
|
|
87
|
+
```
|
|
88
|
+
compute_cost = fwd_excess[n_nodes] - boundary_correction(fwd_state[n_nodes])
|
|
89
|
+
```
|
|
90
|
+
(For a balanced route, `bwd_excess` at the return depot is 0 and `bwd_state` is 0, so the depot term drops out.)
|
|
91
|
+
|
|
92
|
+
**Step 7 — Create the node class**
|
|
93
|
+
File: `cpp/src/routing/node/your_node.cuh`
|
|
94
|
+
- Fixed data fields (problem input)
|
|
95
|
+
- `fwd_state[]`, `fwd_excess`, `bwd_state[]`, `bwd_excess`
|
|
96
|
+
- All 9 interface methods listed in `cuopt-dimension-architecture`
|
|
97
|
+
|
|
98
|
+
**Step 8 — Create the route class**
|
|
99
|
+
File: `cpp/src/routing/route/your_route.cuh`
|
|
100
|
+
- Host-side: `rmm::device_uvector` for each array (fixed, fwd, bwd)
|
|
101
|
+
- Device-side `view_t`: `raft::device_span` members, `get_node`, `set_node`, `set_forward_data`, `set_backward_data`, `copy_forward_data`, `copy_backward_data`, `copy_fixed_route_data`, `compute_cost`, `create_shared_route`, `get_shared_size`
|
|
102
|
+
- Stride layout: all arrays use `stride = n_nodes_route + 1`; multi-type arrays are row-major `[n_types * stride]`
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## `cuopt-dimension-wiring-checklist`
|
|
107
|
+
|
|
108
|
+
**When to use**: After writing node/route logic, to ensure the dimension is fully integrated into the framework.
|
|
109
|
+
|
|
110
|
+
### Files to create
|
|
111
|
+
- [ ] `cpp/src/routing/node/your_node.cuh`
|
|
112
|
+
- [ ] `cpp/src/routing/route/your_route.cuh`
|
|
113
|
+
|
|
114
|
+
### Files to modify
|
|
115
|
+
|
|
116
|
+
**`cpp/src/routing/routing_helpers.cuh`** (or `dimensions_info`)
|
|
117
|
+
- [ ] Add new `dim_t` enum value
|
|
118
|
+
- [ ] `enabled_dimensions_t::has_dimension` covers it
|
|
119
|
+
- [ ] `enabled_dimensions_t::get_dimension<dim>` covers it
|
|
120
|
+
- [ ] `loop_over_dimensions` range covers it (check `Start`/`End` bounds)
|
|
121
|
+
|
|
122
|
+
**`cpp/src/routing/route/dimensions_route.cuh`**
|
|
123
|
+
- [ ] Add to `route_from_dim<I>` type alias chain
|
|
124
|
+
- [ ] Add member `your_route_t<i_t, f_t> your_dim` to `dimensions_route_t`
|
|
125
|
+
- [ ] Initialize in constructor: `your_dim(sol_handle_, dimensions_info_.get_dimension<dim_t::YOUR_DIM>())`
|
|
126
|
+
- [ ] Copy constructor copies `your_dim`
|
|
127
|
+
- [ ] `view_t` has `typename your_route_t<i_t, f_t>::view_t your_dim` member
|
|
128
|
+
- [ ] `view()` calls `get_dimension_of<I>(v) = get_dimension_of<I>(*this).view()` via loop — automatic if wired into enum
|
|
129
|
+
|
|
130
|
+
**`cpp/src/routing/node/node.cuh`**
|
|
131
|
+
- [ ] `get_dimension<dim_t::YOUR_DIM>()` returns `your_dim` member — add to the accessor chain
|
|
132
|
+
|
|
133
|
+
**`cpp/src/routing/problem/problem.cuh`**
|
|
134
|
+
- [ ] Add storage for input data (e.g. `std::vector<int> order_incompatible_types`)
|
|
135
|
+
- [ ] Add setter method
|
|
136
|
+
|
|
137
|
+
**`cpp/src/routing/problem/problem.cu`**
|
|
138
|
+
- [ ] `populate_dimensions_info()`: enable dimension when input data is non-empty
|
|
139
|
+
|
|
140
|
+
**`cpp/src/routing/util_kernels/set_nodes_data.cuh`**
|
|
141
|
+
- [ ] Depot boundary initialization in `set_route_data`: set `fwd_state[0] = 0`, `fwd_excess[0] = 0`, `bwd_state[n_nodes] = 0`, `bwd_excess[n_nodes] = 0`
|
|
142
|
+
|
|
143
|
+
**`cpp/src/routing/fleet_info.hpp`** (if dimension has vehicle-level parameters)
|
|
144
|
+
- [ ] Add vehicle-level constraint data
|
|
145
|
+
|
|
146
|
+
**Python/C API**
|
|
147
|
+
- [ ] Expose setter in C API header
|
|
148
|
+
- [ ] Python binding in the routing data class
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## `cuopt-dimension-testing`
|
|
153
|
+
|
|
154
|
+
**When to use**: After implementing a new dimension, to write tests that validate correctness end-to-end.
|
|
155
|
+
|
|
156
|
+
### C++ unit tests (`cpp/tests/routing/`)
|
|
157
|
+
- Add a simple unit test with less than 10 nodes/orders
|
|
158
|
+
|
|
159
|
+
### Python integration tests (`python/cuopt/cuopt/tests/routing/`)
|
|
160
|
+
- Add a similar test in python to test the Python APIs and end-to-end testing
|
|
161
|
+
|
|
162
|
+
### What every test should verify
|
|
163
|
+
- `is_feasible()` for the final solution when feasibility is expected
|
|
164
|
+
- Infeasibility cost for the new dimension is 0 in a feasible solution
|
|
165
|
+
- Optimal objective value is obtained for curated tests
|
|
166
|
+
- Edge cases: empty route, single-node route, all nodes same type/value
|
|
@@ -3,7 +3,6 @@ name: cuopt-install
|
|
|
3
3
|
version: "26.08.00"
|
|
4
4
|
description: Install cuOpt for Python, C, or as a server (pip, conda, Docker) — system requirements, install commands, and verification. Use when the user wants to install or verify cuOpt for any user-facing interface. For building cuOpt from source or contributing to cuOpt, see cuopt-developer.
|
|
5
5
|
---
|
|
6
|
-
|
|
7
6
|
# cuOpt Install (user)
|
|
8
7
|
|
|
9
8
|
Install cuOpt to *use* it from Python, C, or as a REST server. For building cuOpt from source to contribute or modify it, see `cuopt-developer`.
|
|
@@ -77,15 +76,8 @@ conda install -c rapidsai -c conda-forge -c nvidia libcuopt
|
|
|
77
76
|
|
|
78
77
|
### Verify
|
|
79
78
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
find $CONDA_PREFIX -name "cuopt_c.h"
|
|
83
|
-
find $CONDA_PREFIX -name "libcuopt.so"
|
|
84
|
-
|
|
85
|
-
# pip (venv):
|
|
86
|
-
find "$(python -c 'import sys; print(sys.prefix)')" -name "cuopt_c.h"
|
|
87
|
-
find "$(python -c 'import sys; print(sys.prefix)')" -name "libcuopt.so"
|
|
88
|
-
```
|
|
79
|
+
See [`resources/verification_examples.md`](resources/verification_examples.md)
|
|
80
|
+
for the canonical C-API header/library `find` commands (conda and pip/venv variants).
|
|
89
81
|
|
|
90
82
|
## Server (REST)
|
|
91
83
|
|
|
@@ -4,7 +4,6 @@ version: "26.08.00"
|
|
|
4
4
|
description: LP, MILP, and QP (beta) with cuOpt — C API only. Use when the user is embedding LP, MILP, or QP in C/C++.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
|
|
8
7
|
# cuOpt Numerical Optimization — C API
|
|
9
8
|
|
|
10
9
|
Solve LP, MILP, and QP problems via the cuOpt C API. The same library, headers, build pattern, and core calls (`cuOptCreate*Problem`, `cuOptSolve`, `cuOptGetObjectiveValue`) apply across all three; QP extends the API with quadratic-objective creation calls.
|
|
@@ -13,28 +12,9 @@ Confirm problem type and formulation (variables, objective, constraints, variabl
|
|
|
13
12
|
|
|
14
13
|
This skill is **C only**.
|
|
15
14
|
|
|
16
|
-
##
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
#include <cuopt/linear_programming/cuopt_c.h>
|
|
20
|
-
|
|
21
|
-
// CSR format for constraints
|
|
22
|
-
cuopt_int_t row_offsets[] = {0, 2, 4};
|
|
23
|
-
cuopt_int_t col_indices[] = {0, 1, 0, 1};
|
|
24
|
-
cuopt_float_t values[] = {2.0, 3.0, 4.0, 2.0};
|
|
25
|
-
char var_types[] = {CUOPT_CONTINUOUS, CUOPT_INTEGER};
|
|
26
|
-
|
|
27
|
-
cuOptCreateRangedProblem(
|
|
28
|
-
num_constraints, num_variables, CUOPT_MINIMIZE,
|
|
29
|
-
0.0, objective_coefficients,
|
|
30
|
-
row_offsets, col_indices, values,
|
|
31
|
-
constraint_lower, constraint_upper,
|
|
32
|
-
var_lower, var_upper, var_types,
|
|
33
|
-
&problem
|
|
34
|
-
);
|
|
35
|
-
cuOptSolve(problem, settings, &solution);
|
|
36
|
-
cuOptGetObjectiveValue(solution, &obj_value);
|
|
37
|
-
```
|
|
15
|
+
## API Call Sequence
|
|
16
|
+
|
|
17
|
+
For LP/MILP, the ordered C entry points are: `cuOptCreateRangedProblem` (sense `CUOPT_MINIMIZE` / `CUOPT_MAXIMIZE`, CSR constraint matrix as `row_offsets` / `col_indices` / `values`, `var_types` char array using `CUOPT_CONTINUOUS` / `CUOPT_INTEGER` macros) → `cuOptSolve(problem, settings, &solution)` → `cuOptGetObjectiveValue(solution, &obj_value)` → matching `cuOptDestroy*` calls. Include `<cuopt/linear_programming/cuopt_c.h>`. Full ordered code with build instructions in [resources/examples.md](resources/examples.md).
|
|
38
18
|
|
|
39
19
|
## QP via C API (beta)
|
|
40
20
|
|