nasde-toolkit 0.3.2__py3-none-any.whl
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.
- nasde_toolkit/__init__.py +5 -0
- nasde_toolkit/_bundled_skills/nasde-benchmark-creator/SKILL.md +321 -0
- nasde_toolkit/_bundled_skills/nasde-benchmark-from-history/SKILL.md +298 -0
- nasde_toolkit/_bundled_skills/nasde-benchmark-from-public-repos/SKILL.md +303 -0
- nasde_toolkit/_bundled_skills/nasde-benchmark-runner/SKILL.md +388 -0
- nasde_toolkit/_version.py +24 -0
- nasde_toolkit/agents/__init__.py +1 -0
- nasde_toolkit/agents/configurable_claude.py +121 -0
- nasde_toolkit/agents/configurable_codex.py +101 -0
- nasde_toolkit/agents/configurable_gemini.py +194 -0
- nasde_toolkit/banner.py +82 -0
- nasde_toolkit/cli.py +513 -0
- nasde_toolkit/config.py +206 -0
- nasde_toolkit/docker.py +221 -0
- nasde_toolkit/evaluator.py +663 -0
- nasde_toolkit/evaluator_backends/__init__.py +21 -0
- nasde_toolkit/evaluator_backends/claude_subprocess.py +172 -0
- nasde_toolkit/evaluator_backends/codex_subprocess.py +152 -0
- nasde_toolkit/evaluator_backends/protocol.py +30 -0
- nasde_toolkit/runner.py +739 -0
- nasde_toolkit/scaffold/__init__.py +161 -0
- nasde_toolkit/skills_installer.py +83 -0
- nasde_toolkit/update_check.py +166 -0
- nasde_toolkit-0.3.2.dist-info/METADATA +701 -0
- nasde_toolkit-0.3.2.dist-info/RECORD +28 -0
- nasde_toolkit-0.3.2.dist-info/WHEEL +4 -0
- nasde_toolkit-0.3.2.dist-info/entry_points.txt +2 -0
- nasde_toolkit-0.3.2.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nasde-benchmark-from-public-repos
|
|
3
|
+
description: |
|
|
4
|
+
Build diverse benchmark task suites from public GitHub repositories for testing universal skills. Use this skill when the user wants to:
|
|
5
|
+
- Create a benchmark that spans multiple public repositories and languages
|
|
6
|
+
- Test a universal skill (refactoring, test writing, code review, etc.) across diverse codebases
|
|
7
|
+
- Curate a representative set of repos and tasks for cross-codebase validation
|
|
8
|
+
- Build an evaluation suite for a skill that should work in any repository
|
|
9
|
+
Even if the user doesn't say "benchmark" — if they're building a skill meant to work everywhere and want to validate it across many different projects, this skill applies.
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# NASDE Benchmark from Public Repos
|
|
13
|
+
|
|
14
|
+
Build a diverse NASDE benchmark by curating tasks from multiple public GitHub repositories. Designed for validating universal skills — skills that should work across different languages, frameworks, project sizes, and architectural styles.
|
|
15
|
+
|
|
16
|
+
## Prerequisites
|
|
17
|
+
|
|
18
|
+
- An existing NASDE benchmark project (run `nasde init` first, or use the `nasde-benchmark-creator` skill)
|
|
19
|
+
- A clear description of the skill being evaluated (what it does, what kinds of tasks it helps with)
|
|
20
|
+
- Internet access (to browse and clone public repositories)
|
|
21
|
+
|
|
22
|
+
## Step 1: Understand the skill under test
|
|
23
|
+
|
|
24
|
+
Ask the user:
|
|
25
|
+
|
|
26
|
+
- **What does the skill do?** (e.g., "helps agents refactor code", "guides test writing", "enforces DDD patterns")
|
|
27
|
+
- **What languages/frameworks should it support?** (e.g., "Python, TypeScript, and Go" or "any language")
|
|
28
|
+
- **What task types exercise the skill?** (e.g., "extract method, rename module, split class" for a refactoring skill)
|
|
29
|
+
- **Are there known weak spots?** (e.g., "seems to struggle with large files" or "not sure about Rust")
|
|
30
|
+
|
|
31
|
+
## Step 2: Design the diversity matrix
|
|
32
|
+
|
|
33
|
+
Based on the skill description, define axes of variation that the benchmark should cover. Present these to the user as a table:
|
|
34
|
+
|
|
35
|
+
### Example for a refactoring skill
|
|
36
|
+
|
|
37
|
+
| Axis | Values to cover | Why it matters |
|
|
38
|
+
|------|----------------|---------------|
|
|
39
|
+
| **Language** | Python, TypeScript, Go, Rust, C# | Refactoring idioms differ per language |
|
|
40
|
+
| **Project size** | Small (<5K LOC), Medium (5-50K), Large (>50K) | Large codebases stress navigation and context |
|
|
41
|
+
| **Test coverage** | Extensive tests, Minimal tests, No tests | Refactoring with no safety net is harder |
|
|
42
|
+
| **Architecture** | Monolith, Microservice, Library | Different refactoring patterns apply |
|
|
43
|
+
| **Difficulty** | Extract function, Split module, Restructure package | Increasing complexity |
|
|
44
|
+
|
|
45
|
+
Not every cell in the matrix needs a task. Aim for **8–15 tasks** that provide meaningful coverage across the axes. Ask the user which axes matter most — they may want to emphasize language diversity over project size, or vice versa.
|
|
46
|
+
|
|
47
|
+
## Step 3: Find candidate repositories
|
|
48
|
+
|
|
49
|
+
For each cell in the matrix that needs coverage, search for public repositories that fit.
|
|
50
|
+
|
|
51
|
+
**Good source repositories have:**
|
|
52
|
+
- A clear, active codebase (not abandoned, not a tutorial/toy project)
|
|
53
|
+
- A working build system and some test infrastructure
|
|
54
|
+
- A well-understood structure (README, organized directories)
|
|
55
|
+
- A permissive license (MIT, Apache 2.0, BSD — avoid GPL if the benchmark may be shared)
|
|
56
|
+
- Enough complexity to be a meaningful test (not a single-file script)
|
|
57
|
+
|
|
58
|
+
**Search strategies:**
|
|
59
|
+
1. **GitHub search** — search by language, stars, topic tags
|
|
60
|
+
2. **Known ecosystem repos** — well-known open source projects in each language (e.g., FastAPI for Python, Express for Node, Gin for Go)
|
|
61
|
+
3. **GitHub Trending** — find actively maintained repos with good structure
|
|
62
|
+
4. **User suggestions** — the user may know repos that represent their target audience
|
|
63
|
+
|
|
64
|
+
For each candidate repo, present:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
[1] github.com/user/repo — "Description from GitHub"
|
|
68
|
+
Language: Python | Size: ~15K LOC | Stars: 2.3K | License: MIT
|
|
69
|
+
Tests: pytest suite, good coverage
|
|
70
|
+
Why: Medium Python project, clean architecture, good refactoring target
|
|
71
|
+
Proposed task: "Extract the database access layer into a repository pattern"
|
|
72
|
+
|
|
73
|
+
[2] github.com/user/repo2 — "Description from GitHub"
|
|
74
|
+
Language: TypeScript | Size: ~40K LOC | Stars: 890 | License: Apache 2.0
|
|
75
|
+
Tests: Jest, moderate coverage
|
|
76
|
+
Why: Large TS project, component-heavy, tests UI refactoring
|
|
77
|
+
Proposed task: "Split the UserDashboard component into focused sub-components"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Ask the user to select which repos and tasks to include.
|
|
81
|
+
|
|
82
|
+
## Step 4: Create tasks for each selected repo
|
|
83
|
+
|
|
84
|
+
For each approved repo+task pair, generate the full task directory. Work through each file with the user.
|
|
85
|
+
|
|
86
|
+
### 4a: Determine the "before" state
|
|
87
|
+
|
|
88
|
+
Unlike `nasde-benchmark-from-history` (which uses a specific commit), here you choose a state of the repo that presents the problem to solve:
|
|
89
|
+
|
|
90
|
+
- **Option A: Current main branch** — the repo as-is has the problem (e.g., a God class that should be split). Set `source.ref` to a specific commit hash on main for reproducibility.
|
|
91
|
+
- **Option B: A tagged release** — use a specific version. More stable for long-lived benchmarks.
|
|
92
|
+
- **Option C: Create a setup branch** — if the task requires introducing a specific problem into a clean codebase, create a branch that sets up the scenario. Push it to a fork or document the setup in the Dockerfile.
|
|
93
|
+
|
|
94
|
+
Always pin to a specific commit hash, not a branch name — branches move, hashes don't.
|
|
95
|
+
|
|
96
|
+
### 4b: task.toml (single task config, shared with Harbor)
|
|
97
|
+
|
|
98
|
+
```toml
|
|
99
|
+
version = "1.0"
|
|
100
|
+
|
|
101
|
+
[task]
|
|
102
|
+
name = "<benchmark-name>/<language>-<repo-slug>-<task-slug>" # Harbor requires org/name format
|
|
103
|
+
description = "<What the agent must do>"
|
|
104
|
+
|
|
105
|
+
[metadata]
|
|
106
|
+
difficulty = "<easy|intermediate|hard>"
|
|
107
|
+
language = "<language>"
|
|
108
|
+
framework = "<framework>"
|
|
109
|
+
source_repo = "https://github.com/<owner>/<repo>"
|
|
110
|
+
diversity_axes = ["<axis:value>", "<axis:value>"]
|
|
111
|
+
|
|
112
|
+
[agent]
|
|
113
|
+
timeout_sec = 1800 # Rule of thumb: estimated_time_minutes × 60
|
|
114
|
+
|
|
115
|
+
[environment]
|
|
116
|
+
memory_mb = 4096 # Claude Code needs 4096+, default 2048 is too low.
|
|
117
|
+
|
|
118
|
+
[verifier]
|
|
119
|
+
timeout_sec = 300
|
|
120
|
+
|
|
121
|
+
[nasde.source] # Only needed when task has no environment/Dockerfile (auto-generation).
|
|
122
|
+
git = "https://github.com/<owner>/<repo>.git"
|
|
123
|
+
ref = "<pinned-commit-hash>"
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
The `[metadata] diversity_axes` helps track coverage across the matrix. Always pin `[nasde.source] ref` to a specific commit hash, not a branch name.
|
|
127
|
+
|
|
128
|
+
### 4c: instruction.md
|
|
129
|
+
|
|
130
|
+
Write a task instruction that:
|
|
131
|
+
- Describes the codebase context (what the project does, relevant directory structure)
|
|
132
|
+
- States the problem clearly (what needs to change and why)
|
|
133
|
+
- Defines success criteria the agent can verify
|
|
134
|
+
- Does NOT prescribe the implementation approach
|
|
135
|
+
|
|
136
|
+
```markdown
|
|
137
|
+
# Task: <Descriptive name>
|
|
138
|
+
|
|
139
|
+
## Context
|
|
140
|
+
You are working in `/app`, a <language> <framework> project that <brief description>.
|
|
141
|
+
The project structure relevant to this task:
|
|
142
|
+
<tree of relevant directories/files>
|
|
143
|
+
|
|
144
|
+
## Requirement
|
|
145
|
+
<What needs to change. Describe the problem, not the solution.
|
|
146
|
+
Example: "The UserService class handles authentication, authorization, profile management,
|
|
147
|
+
and notification dispatch. It's 800 lines and growing. Separate these concerns into
|
|
148
|
+
focused services.">
|
|
149
|
+
|
|
150
|
+
## Scope
|
|
151
|
+
- Focus on: <specific files/directories>
|
|
152
|
+
- Do NOT modify: <test files, configuration, unrelated modules>
|
|
153
|
+
- Preserve: <all existing public APIs, test behavior>
|
|
154
|
+
|
|
155
|
+
## Quality Expectations
|
|
156
|
+
- Follow <language> idioms and the project's existing style
|
|
157
|
+
- Maintain or improve test coverage
|
|
158
|
+
- Keep changes minimal — change what needs changing, nothing more
|
|
159
|
+
|
|
160
|
+
## Success Criteria
|
|
161
|
+
1. <Specific, testable criterion>
|
|
162
|
+
2. <Specific, testable criterion>
|
|
163
|
+
3. All existing tests continue to pass
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
**Important for universal skill benchmarks:** Write the instruction as if the agent has no special skill. The skill configuration is injected via the variant's `CLAUDE.md` — the instruction describes the raw problem.
|
|
167
|
+
|
|
168
|
+
### 4d: environment/Dockerfile
|
|
169
|
+
|
|
170
|
+
Each repo needs its own Dockerfile. Detect the stack and generate:
|
|
171
|
+
|
|
172
|
+
```dockerfile
|
|
173
|
+
FROM <base-image>
|
|
174
|
+
|
|
175
|
+
RUN apt-get update && apt-get install -y git curl wget ca-certificates && rm -rf /var/lib/apt/lists/*
|
|
176
|
+
|
|
177
|
+
WORKDIR /app
|
|
178
|
+
RUN git clone https://github.com/<owner>/<repo>.git . && git checkout <pinned-hash>
|
|
179
|
+
|
|
180
|
+
# Install dependencies
|
|
181
|
+
RUN <dependency-install-command>
|
|
182
|
+
|
|
183
|
+
# Verify build works at the "before" state
|
|
184
|
+
RUN <build-or-compile-command>
|
|
185
|
+
|
|
186
|
+
CMD ["/bin/bash"]
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Test the Dockerfile** before moving on:
|
|
190
|
+
```bash
|
|
191
|
+
docker build -t benchmark-test-<task-name> -f tasks/<task-name>/environment/Dockerfile .
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### 4e: tests/test.sh
|
|
195
|
+
|
|
196
|
+
For public repos, the verifier typically:
|
|
197
|
+
1. Verifies the project still builds
|
|
198
|
+
2. Runs the existing test suite (all tests must still pass)
|
|
199
|
+
3. Checks for task-specific outcomes (new files exist, specific patterns in code, etc.)
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
#!/bin/bash
|
|
203
|
+
cd /app
|
|
204
|
+
|
|
205
|
+
echo "Step 1: Verifying build..."
|
|
206
|
+
if <build-command>; then
|
|
207
|
+
echo "✓ Build succeeded"
|
|
208
|
+
else
|
|
209
|
+
echo "✗ Build failed"
|
|
210
|
+
echo 0 > /logs/verifier/reward.txt
|
|
211
|
+
exit 1
|
|
212
|
+
fi
|
|
213
|
+
|
|
214
|
+
echo "Step 2: Running existing tests..."
|
|
215
|
+
if <test-command>; then
|
|
216
|
+
echo "✓ Existing tests pass"
|
|
217
|
+
else
|
|
218
|
+
echo "✗ Existing tests failed — regression detected"
|
|
219
|
+
echo 0 > /logs/verifier/reward.txt
|
|
220
|
+
exit 1
|
|
221
|
+
fi
|
|
222
|
+
|
|
223
|
+
echo "Step 3: Checking task-specific criteria..."
|
|
224
|
+
# Example: verify a specific file was created or a class was split
|
|
225
|
+
if <task-specific-check>; then
|
|
226
|
+
echo "✓ Task criteria met"
|
|
227
|
+
else
|
|
228
|
+
echo "✗ Task criteria not met"
|
|
229
|
+
echo 0 > /logs/verifier/reward.txt
|
|
230
|
+
exit 1
|
|
231
|
+
fi
|
|
232
|
+
|
|
233
|
+
echo "EVALUATION PASSED ✓"
|
|
234
|
+
echo 1 > /logs/verifier/reward.txt
|
|
235
|
+
exit 0
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Task-specific checks depend on the task type:
|
|
239
|
+
- **Refactoring:** check that target files exist, original God class is smaller or removed
|
|
240
|
+
- **Test writing:** check that new test files exist and pass
|
|
241
|
+
- **Bug fix:** check that a specific test case now passes
|
|
242
|
+
|
|
243
|
+
### 4f: assessment_criteria.md
|
|
244
|
+
|
|
245
|
+
Use the benchmark project's `assessment_dimensions.json` and adapt each dimension to this specific task and language:
|
|
246
|
+
|
|
247
|
+
```markdown
|
|
248
|
+
# Assessment Criteria: <Task Name>
|
|
249
|
+
|
|
250
|
+
Evaluate the agent's solution across the following dimensions.
|
|
251
|
+
This task is in <language> using <framework> — apply language-specific standards.
|
|
252
|
+
|
|
253
|
+
## 1. <Dimension> (0–<max_score>)
|
|
254
|
+
|
|
255
|
+
| Score | Criteria |
|
|
256
|
+
|-------|----------|
|
|
257
|
+
| 0 | <worst — specific to this language and task> |
|
|
258
|
+
| ... | ... |
|
|
259
|
+
| <max> | <best — specific to this language and task> |
|
|
260
|
+
|
|
261
|
+
**Key checks:**
|
|
262
|
+
- <Language-specific things to look for>
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
**Important:** Assessment criteria should reflect language idioms. "Good refactoring" looks different in Rust (ownership, lifetimes) vs Python (duck typing, protocols) vs Go (interfaces, embedding).
|
|
266
|
+
|
|
267
|
+
## Step 5: Review coverage
|
|
268
|
+
|
|
269
|
+
After all tasks are created, present the filled diversity matrix to the user:
|
|
270
|
+
|
|
271
|
+
```
|
|
272
|
+
Coverage matrix for "refactoring" skill benchmark:
|
|
273
|
+
|
|
274
|
+
| Language | Small | Medium | Large |
|
|
275
|
+
|------------|-------|--------|-------|
|
|
276
|
+
| Python | | ✓ fastapi-extract | |
|
|
277
|
+
| TypeScript | | | ✓ dashboard-split |
|
|
278
|
+
| Go | ✓ cli-service-layer | | |
|
|
279
|
+
| Rust | ✓ error-handling | | |
|
|
280
|
+
| C# | | ✓ ddd-aggregate | |
|
|
281
|
+
|
|
282
|
+
Gaps: No large Python project, no small TypeScript project.
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Ask the user if they want to fill gaps or if current coverage is sufficient.
|
|
286
|
+
|
|
287
|
+
## Step 6: Verify the benchmark
|
|
288
|
+
|
|
289
|
+
1. **Build all Docker images** — every task must build successfully
|
|
290
|
+
2. **Run existing test suites** in each container — they must pass at the "before" state
|
|
291
|
+
3. **Dry run** on one or two tasks:
|
|
292
|
+
```bash
|
|
293
|
+
nasde run --variant <skill-variant> --tasks <task-name> --without-eval -C <benchmark-dir>
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
## Tips
|
|
297
|
+
|
|
298
|
+
- **Pin commit hashes, not branches.** Branches move. A benchmark task that worked yesterday might break tomorrow if main advanced. Always use the full 40-char hash.
|
|
299
|
+
- **Diverse doesn't mean random.** Each task should test a different aspect of the skill. If three tasks all test "extract method in Python," replace two with different languages or problem types.
|
|
300
|
+
- **Test the Dockerfiles early.** The most common failure is a Dockerfile that doesn't build because a dependency changed or a repo restructured. Build images as you create tasks, not all at the end.
|
|
301
|
+
- **Keep instructions skill-agnostic.** The task instruction describes the problem. The skill is injected via the variant's `CLAUDE.md`. This separation lets you test the same tasks with and without the skill.
|
|
302
|
+
- **Start with 5–8 tasks.** You can always add more. A smaller, well-curated benchmark is better than a large, noisy one.
|
|
303
|
+
- **Combine with nasde-benchmark-creator.** This skill generates tasks from public repos; `nasde-benchmark-creator` handles project scaffold, dimensions, and variants. Use them together.
|
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nasde-benchmark-runner
|
|
3
|
+
description: |
|
|
4
|
+
Run coding agent benchmarks and verify results with nasde. Use this skill when the user wants to:
|
|
5
|
+
- Run a benchmark (all tasks, single task, specific variant)
|
|
6
|
+
- Re-run assessment evaluation on existing trial results
|
|
7
|
+
- Check or verify results in Opik (traces, feedback scores, experiments)
|
|
8
|
+
- Troubleshoot a failed benchmark run
|
|
9
|
+
- View or compare trial results
|
|
10
|
+
Even if the user doesn't say "benchmark" — if they're talking about running evaluations, checking scores, or analyzing agent performance, this skill applies.
|
|
11
|
+
After every run that uses --with-opik, ALWAYS verify results via Opik REST API — don't wait for the user to ask.
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# NASDE Benchmark Runner
|
|
15
|
+
|
|
16
|
+
Run coding agent benchmarks with `nasde` and verify results. The two-stage pipeline: Harbor runs agents in Docker containers (functional test → reward 0/1), then an LLM-as-a-Judge scores architecture quality across multiple dimensions.
|
|
17
|
+
|
|
18
|
+
## Authentication setup
|
|
19
|
+
|
|
20
|
+
Before running any benchmark, set up authentication tokens. Both are needed for cross-agent benchmarks.
|
|
21
|
+
|
|
22
|
+
### Claude Code (OAuth token from subscription)
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
source scripts/export_oauth_token.sh
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
This extracts `CLAUDE_CODE_OAUTH_TOKEN` from macOS Keychain (written by `claude` CLI login). Required for both Claude agent runs AND assessment evaluation (which spawns the `claude` CLI as a subprocess when `[evaluation] backend = "claude"`).
|
|
29
|
+
|
|
30
|
+
Alternatively, set `ANTHROPIC_API_KEY` for API billing.
|
|
31
|
+
|
|
32
|
+
### Codex (ChatGPT subscription or API key)
|
|
33
|
+
|
|
34
|
+
**Option 1: ChatGPT subscription (OAuth)** — uses ChatGPT Plus/Pro/Business plan credits, no per-token API cost:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
codex login # one-time: authenticate via ChatGPT
|
|
38
|
+
source scripts/export_codex_oauth_token.sh # validate tokens are present
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
NASDE auto-detects `~/.codex/auth.json` with `auth_mode: "chatgpt"` and injects OAuth tokens into the sandbox. No env vars needed.
|
|
42
|
+
|
|
43
|
+
**Option 2: API key** — billed per-token through OpenAI Platform:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
export $(grep CODEX_API_KEY .env)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Or set directly: `export CODEX_API_KEY=sk-proj-...`
|
|
50
|
+
|
|
51
|
+
API key always takes priority over OAuth when both are present.
|
|
52
|
+
|
|
53
|
+
### Gemini CLI (Google account or API key)
|
|
54
|
+
|
|
55
|
+
**Option 1: Google account OAuth** — uses Google account credits, no per-token API cost:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
gemini login # one-time: authenticate via Google account
|
|
59
|
+
source scripts/export_gemini_oauth_token.sh # validate tokens are present
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
NASDE auto-detects `~/.gemini/oauth_creds.json` and injects OAuth credentials into the sandbox. No env vars needed.
|
|
63
|
+
|
|
64
|
+
**Option 2: API key** — billed through Google AI Studio or Vertex AI:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
export GEMINI_API_KEY=your-key
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Or for Vertex AI: `export GOOGLE_API_KEY=your-key` + `export GOOGLE_CLOUD_PROJECT=your-project`
|
|
71
|
+
|
|
72
|
+
API key always takes priority over OAuth when both are present.
|
|
73
|
+
|
|
74
|
+
### Combined setup for cross-agent runs
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
source scripts/export_oauth_token.sh # Claude (subscription)
|
|
78
|
+
# Codex: either codex login (subscription) or:
|
|
79
|
+
export $(grep CODEX_API_KEY .env) # Codex (API key)
|
|
80
|
+
source scripts/export_gemini_oauth_token.sh # Gemini (Google account)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Running benchmarks
|
|
84
|
+
|
|
85
|
+
All commands assume `-C` points to the benchmark project directory.
|
|
86
|
+
|
|
87
|
+
### Basic run (all tasks, default variant)
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
nasde run -C path/to/benchmark
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Assessment evaluation runs by default. This is the standard workflow.
|
|
94
|
+
|
|
95
|
+
### Specific variant and tasks
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# Single task, specific variant
|
|
99
|
+
nasde run --variant guided --tasks my-task -C path/to/benchmark
|
|
100
|
+
|
|
101
|
+
# Multiple tasks
|
|
102
|
+
nasde run --variant baseline --tasks task-a,task-b -C path/to/benchmark
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### With Opik tracing
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
nasde run --variant baseline --tasks my-task -C path/to/benchmark --with-opik
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
After this completes, ALWAYS verify Opik results (see Opik verification below).
|
|
112
|
+
|
|
113
|
+
### Harbor only (skip assessment)
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
nasde run --variant baseline -C path/to/benchmark --without-eval
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Parallel runs (multiple variants)
|
|
120
|
+
|
|
121
|
+
Running multiple variants simultaneously is safe — each job directory includes a unique random suffix to prevent collisions:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
nasde run --variant vanilla --tasks my-task -C path/to/benchmark &
|
|
125
|
+
nasde run --variant guided --tasks my-task -C path/to/benchmark &
|
|
126
|
+
wait
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
For deterministic job names, use `--job-suffix`:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
nasde run --variant vanilla --job-suffix run1 -C path/to/benchmark
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Running Codex variants
|
|
136
|
+
|
|
137
|
+
Codex variants use `AGENTS.md` (instead of `CLAUDE.md`) and require either `codex login` (ChatGPT subscription) or `CODEX_API_KEY`/`OPENAI_API_KEY` (API billing).
|
|
138
|
+
|
|
139
|
+
**CRITICAL: Codex model must be set explicitly.** The `nasde.toml` default model (e.g. `claude-sonnet-4-6`) is designed for Claude and will be passed to Codex if not overridden. Codex CLI will silently accept invalid model names but produce garbage results (0% pass rate). Always set the model via `--model` flag or in `variant.toml`.
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# Option A: ChatGPT subscription (no env vars needed after codex login)
|
|
143
|
+
nasde run --variant codex-vanilla --model gpt-5.3-codex -C path/to/benchmark
|
|
144
|
+
|
|
145
|
+
# Option B: API key
|
|
146
|
+
export $(grep CODEX_API_KEY .env)
|
|
147
|
+
nasde run --variant codex-vanilla --model gpt-5.3-codex -C path/to/benchmark
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**Codex models** (recommended first, as of 2026-03):
|
|
151
|
+
- `gpt-5.4` — flagship frontier model, best overall for professional work
|
|
152
|
+
- `gpt-5.4-mini` — fast, efficient mini model for responsive coding and subagents
|
|
153
|
+
- `gpt-5.3-codex` — industry-leading coding model for complex software engineering
|
|
154
|
+
- `gpt-5.3-codex-spark` — near-instant real-time coding iteration (ChatGPT Pro only)
|
|
155
|
+
|
|
156
|
+
Older alternatives: `gpt-5.2-codex`, `gpt-5.1-codex`, `gpt-5-codex`, `gpt-5-codex-mini`
|
|
157
|
+
|
|
158
|
+
Codex supports any model compatible with the Responses API. Chat Completions API support is deprecated.
|
|
159
|
+
|
|
160
|
+
**Setting model in variant.toml** (preferred over --model flag):
|
|
161
|
+
```toml
|
|
162
|
+
agent = "codex"
|
|
163
|
+
model = "gpt-5.4"
|
|
164
|
+
```
|
|
165
|
+
This avoids accidentally inheriting the Claude model from `nasde.toml`.
|
|
166
|
+
|
|
167
|
+
### Running Gemini CLI variants
|
|
168
|
+
|
|
169
|
+
Gemini variants use `GEMINI.md` (instead of `CLAUDE.md`) and require either `gemini login` (Google account) or `GEMINI_API_KEY`/`GOOGLE_API_KEY` (API billing).
|
|
170
|
+
|
|
171
|
+
**CRITICAL: Gemini model must use `google/` prefix.** Harbor requires model names in `provider/model_name` format. Always set via `--model` flag or in `variant.toml`.
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
# Option A: Google account OAuth (no env vars needed after gemini login)
|
|
175
|
+
nasde run --variant gemini-vanilla --model google/gemini-3-flash-preview -C path/to/benchmark
|
|
176
|
+
|
|
177
|
+
# Option B: API key
|
|
178
|
+
export GEMINI_API_KEY=your-key
|
|
179
|
+
nasde run --variant gemini-vanilla --model google/gemini-3-flash-preview -C path/to/benchmark
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**Gemini models** (recommended first, as of 2026-03):
|
|
183
|
+
- `google/gemini-3.1-pro-preview` — advanced thinking model, deep reasoning
|
|
184
|
+
- `google/gemini-3-flash-preview` — best quality/speed ratio, daily coding
|
|
185
|
+
- `google/gemini-3.1-flash-lite-preview` — fastest, simple tasks
|
|
186
|
+
|
|
187
|
+
**Setting model in variant.toml** (preferred over --model flag):
|
|
188
|
+
```toml
|
|
189
|
+
agent = "gemini"
|
|
190
|
+
model = "google/gemini-3-flash-preview"
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Cross-agent comparison (Claude vs Codex vs Gemini)
|
|
194
|
+
|
|
195
|
+
Set up all auth tokens first (see Authentication setup above), then run:
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
source scripts/export_oauth_token.sh && export $(grep CODEX_API_KEY .env) && source scripts/export_gemini_oauth_token.sh
|
|
199
|
+
|
|
200
|
+
# Run Claude, Codex, and Gemini variants — non-Claude MUST have --model override
|
|
201
|
+
nasde run --variant claude-vanilla -C path/to/benchmark --with-opik &
|
|
202
|
+
nasde run --variant codex-vanilla --model gpt-5.3-codex -C path/to/benchmark --with-opik &
|
|
203
|
+
nasde run --variant gemini-vanilla --model google/gemini-3-flash-preview -C path/to/benchmark --with-opik &
|
|
204
|
+
wait
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
**WARNING**: Running Claude variants in parallel can cause OOM (exit code 137) in Docker. Claude Code containers are memory-heavy (~2-4 GB each). Run Claude variants sequentially, or increase Docker Desktop memory to 16+ GB.
|
|
208
|
+
|
|
209
|
+
### Custom model and timeout
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
nasde run --variant baseline --model claude-opus-4-7 --timeout 1200 -C path/to/benchmark
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**Timeout priority**: `--timeout` flag overrides everything. Without it, Harbor uses `task.toml [agent] timeout_sec` per task. Timeouts are per-task only — there is no project-wide default in nasde.toml.
|
|
216
|
+
|
|
217
|
+
### Re-evaluate existing results
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
nasde eval path/to/benchmark/jobs/2026-03-16__14-05-58 --with-opik -C path/to/benchmark
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Token cost heuristic
|
|
224
|
+
|
|
225
|
+
**Claude Code variants:**
|
|
226
|
+
When using `CLAUDE_CODE_OAUTH_TOKEN` (Claude subscription — no per-token cost):
|
|
227
|
+
- **Run freely**: total estimated time under 30 minutes (sum of tasks × variants)
|
|
228
|
+
- **Ask first**: over 30 minutes, OR when using `ANTHROPIC_API_KEY` (API billing)
|
|
229
|
+
|
|
230
|
+
**Codex variants:**
|
|
231
|
+
- **ChatGPT OAuth** (`codex login`): uses subscription credits, no per-token cost. Same heuristic as Claude subscription — run freely under 30 minutes.
|
|
232
|
+
- **API key** (`CODEX_API_KEY`): billed per-token. Always ask before running. Codex uses significantly more input tokens than Claude Code (~1M vs ~250K per task).
|
|
233
|
+
|
|
234
|
+
**Gemini CLI variants:**
|
|
235
|
+
- **Google account OAuth** (`gemini login`): free tier via Gemini Code Assist license (1M token context). Run freely.
|
|
236
|
+
- **API key** (`GEMINI_API_KEY`): billed per-token through Google AI Studio. Ask before running.
|
|
237
|
+
- **Vertex AI** (`GOOGLE_API_KEY`): billed through Google Cloud. Ask before running.
|
|
238
|
+
|
|
239
|
+
Task estimated times are derived from `task.toml [agent] timeout_sec` (timeout_sec / 60 is a rough upper bound; agents typically finish faster). When `--tasks` filters are used, count only selected tasks.
|
|
240
|
+
|
|
241
|
+
## Viewing results
|
|
242
|
+
|
|
243
|
+
After a run, results are in `jobs/<timestamp>/`:
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
# Job summary
|
|
247
|
+
cat jobs/<timestamp>/result.json | python3 -m json.tool
|
|
248
|
+
|
|
249
|
+
# Per-trial results
|
|
250
|
+
cat jobs/<timestamp>/<trial-id>/result.json | python3 -m json.tool
|
|
251
|
+
|
|
252
|
+
# Verifier output (what test.sh printed)
|
|
253
|
+
cat jobs/<timestamp>/<trial-id>/verifier/test-stdout.txt
|
|
254
|
+
|
|
255
|
+
# Assessment scores
|
|
256
|
+
cat jobs/<timestamp>/<trial-id>/assessment_eval.json | python3 -m json.tool
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Using Harbor CLI for viewing
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
nasde harbor view path/to/benchmark/jobs/<timestamp>
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## Opik verification
|
|
266
|
+
|
|
267
|
+
After every run with `--with-opik`, verify results via REST API. This is mandatory — Opik has known issues with long-running trials where data may not arrive completely.
|
|
268
|
+
|
|
269
|
+
### Verification script
|
|
270
|
+
|
|
271
|
+
Use Python `urllib.request` (never curl — it drops the `Comet-Workspace` header):
|
|
272
|
+
|
|
273
|
+
```python
|
|
274
|
+
python3 -c "
|
|
275
|
+
import urllib.request, json
|
|
276
|
+
|
|
277
|
+
req = urllib.request.Request(
|
|
278
|
+
'https://www.comet.com/opik/api/v1/private/traces?project_name=<PROJECT_NAME>&limit=1',
|
|
279
|
+
headers={
|
|
280
|
+
'authorization': '<OPIK_API_KEY>',
|
|
281
|
+
'Comet-Workspace': '<OPIK_WORKSPACE>',
|
|
282
|
+
},
|
|
283
|
+
)
|
|
284
|
+
resp = json.loads(urllib.request.urlopen(req).read())
|
|
285
|
+
trace = resp['content'][0]
|
|
286
|
+
print(f'Trace: {trace[\"name\"]}')
|
|
287
|
+
print(f'ID: {trace[\"id\"]}')
|
|
288
|
+
print()
|
|
289
|
+
for s in sorted(trace.get('feedback_scores', []), key=lambda x: x['name']):
|
|
290
|
+
print(f' {s[\"name\"]}: {s[\"value\"]}')
|
|
291
|
+
"
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
Credentials are in the benchmark's `.env` file (or parent directory).
|
|
295
|
+
|
|
296
|
+
### What to check
|
|
297
|
+
|
|
298
|
+
For each trace, verify:
|
|
299
|
+
|
|
300
|
+
1. **Feedback scores present** — should include:
|
|
301
|
+
- `reward` (from Harbor verifier: 0.0 or 1.0)
|
|
302
|
+
- `duration_sec` (trial execution time)
|
|
303
|
+
- `arch_<dimension>` for each assessment dimension (normalized 0.0-1.0)
|
|
304
|
+
- `arch_total` (overall normalized score)
|
|
305
|
+
2. **Trace name format**: `<agent-name>/<trial-name>` (e.g. `baseline/ddd-threshold-discount__4tTaKwg`)
|
|
306
|
+
3. **Tags**: should include `harbor` and the variant name
|
|
307
|
+
|
|
308
|
+
### Finding trace IDs
|
|
309
|
+
|
|
310
|
+
The trace ID is printed during the run:
|
|
311
|
+
```
|
|
312
|
+
OPIK: Started logging traces to ... ?trace_id=<TRACE_ID>&...
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
Or search by project:
|
|
316
|
+
```python
|
|
317
|
+
import opik
|
|
318
|
+
client = opik.Opik()
|
|
319
|
+
traces = client.search_traces(
|
|
320
|
+
project_name='<benchmark-name>',
|
|
321
|
+
filter_string='name = "<agent-name>/<trial-name>"',
|
|
322
|
+
max_results=1,
|
|
323
|
+
wait_for_at_least=1,
|
|
324
|
+
wait_for_timeout=10,
|
|
325
|
+
)
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## Troubleshooting
|
|
329
|
+
|
|
330
|
+
### "No module named 'evals'" or import errors
|
|
331
|
+
|
|
332
|
+
Harbor resolves `import_path` from `harbor_config.json` via `importlib`. If using the built-in agent (`nasde_toolkit.agents.configurable_claude:ConfigurableClaude`), this works when nasde-toolkit is installed. For custom agents, ensure the module is on `sys.path`.
|
|
333
|
+
|
|
334
|
+
### Docker build fails
|
|
335
|
+
|
|
336
|
+
Test the Dockerfile independently:
|
|
337
|
+
```bash
|
|
338
|
+
docker build -t test-env -f tasks/<task>/environment/Dockerfile .
|
|
339
|
+
docker run --rm -it test-env bash
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### Assessment eval fails with "No artifacts/workspace/"
|
|
343
|
+
|
|
344
|
+
Harbor didn't copy artifacts. Check:
|
|
345
|
+
- The `artifacts` config in the merged Harbor config (source path must match container layout)
|
|
346
|
+
- The trial log: `jobs/<ts>/<trial>/trial.log`
|
|
347
|
+
|
|
348
|
+
### Opik scores missing after --with-opik
|
|
349
|
+
|
|
350
|
+
1. Check trace exists: use the REST API verification script above
|
|
351
|
+
2. If trace exists but no `arch_*` scores: assessment eval didn't run or failed. Check the CLI output for errors.
|
|
352
|
+
3. If no trace at all: Opik tracking wasn't enabled. Verify `.env` has `OPIK_API_KEY` and `OPIK_WORKSPACE`.
|
|
353
|
+
|
|
354
|
+
### Codex trial fails immediately (reward 0, 0/100)
|
|
355
|
+
|
|
356
|
+
Check the agent log for errors:
|
|
357
|
+
```bash
|
|
358
|
+
head -20 jobs/<ts>/<trial>/agent/codex.txt
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
Common causes:
|
|
362
|
+
- **`Incorrect API key provided: ''`** — no auth configured. Either run `codex login` (ChatGPT subscription) or set `CODEX_API_KEY`: `export $(grep CODEX_API_KEY .env)`
|
|
363
|
+
- **`model 'X' does not exist`** — wrong model name. Use `gpt-5.4`, `gpt-5.4-mini`, `gpt-5.3-codex`, or `gpt-5.3-codex-spark`
|
|
364
|
+
- **0% pass rate, low scores, but trials completed** — likely inherited Claude model name (e.g. `claude-sonnet-4-6`) instead of OpenAI model. Check `config.json` in the job dir for `model_name`. Fix by adding `model = "gpt-5.3-codex"` to `variant.toml` or using `--model gpt-5.3-codex`
|
|
365
|
+
- **`Tool 'web_search_preview' is not supported`** — model doesn't support Codex tools
|
|
366
|
+
- **`Model metadata for 'X' not found`** — warning only, usually followed by the real error
|
|
367
|
+
|
|
368
|
+
### Gemini trial fails immediately (reward 0, 0/100)
|
|
369
|
+
|
|
370
|
+
Check the agent log for errors:
|
|
371
|
+
```bash
|
|
372
|
+
head -20 jobs/<ts>/<trial>/agent/gemini-cli.txt
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
Common causes:
|
|
376
|
+
- **`GEMINI_API_KEY is not set`** — no auth configured. Either run `gemini login` or set `GEMINI_API_KEY`
|
|
377
|
+
- **`Model name must be in the format provider/model_name`** — model must include `google/` prefix (e.g. `google/gemini-3-flash-preview`)
|
|
378
|
+
- **Node.js errors** — Gemini CLI requires Node.js 22+. Check the Docker image includes nvm setup
|
|
379
|
+
- **DNS resolution failures** — cloud sandboxes may not resolve `generativelanguage.googleapis.com`. ConfigurableGemini auto-fixes this, but custom configs may not
|
|
380
|
+
|
|
381
|
+
### Trial reward is 0 but code looks correct
|
|
382
|
+
|
|
383
|
+
Read the verifier output:
|
|
384
|
+
```bash
|
|
385
|
+
cat jobs/<ts>/<trial>/verifier/test-stdout.txt
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
This shows exactly which step in `test.sh` failed.
|