Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
95b258e
feat(experimentalist): add a fast, diagnostic smoke agent fixture
schuellc-nvidia Aug 10, 2026
4d00ba0
docs(experimentalist): document the model pair and platform URL the r…
schuellc-nvidia Aug 10, 2026
3047691
fix(experimentalist): make g1 solvable by inference, not guesswork
schuellc-nvidia Aug 10, 2026
8d7e05c
fix(experimentalist): refuse a symlinked answer before scoring it
schuellc-nvidia Aug 10, 2026
a9cbbd2
refactor(experimentalist): run the smoke gates for two rounds, not one
schuellc-nvidia Aug 10, 2026
bddc03b
fix(experimentalist): make the task template a first-class fixture asset
schuellc-nvidia Aug 10, 2026
386f4d9
test(experimentalist): refuse to score a broken Insight suite
schuellc-nvidia Aug 10, 2026
bfb1fd8
test(experimentalist): fail an Insight metric that cannot see the repair
schuellc-nvidia Aug 11, 2026
3ef5232
test(experimentalist): clarify smoke agent guards
Aug 11, 2026
13572da
test(experimentalist): simplify smoke test docstrings
Aug 11, 2026
ac3cf0d
chore : fix reasoning effort
Aug 11, 2026
ccfec80
test(experimentalist): add mode 1 smoke loop coverage
Aug 11, 2026
7f9849c
chore: test mode 2
Aug 11, 2026
41fe459
test(experimentalist): add mode 2 smoke loop coverage
Aug 11, 2026
a710af4
test(experimentalist): consolidate mode 1 smoke checks
Aug 11, 2026
7ad86d4
test(experimentalist): expand mode 1 insight evidence
Aug 11, 2026
ed186c9
test(experimentalist): extend mode 2 smoke timeout
Aug 11, 2026
e589739
test(experimentalist): use terra and luna for smoke loops
Aug 11, 2026
904ed70
chore: allow empty datasets
Aug 12, 2026
4b35cae
chore: remove duplicate cache
Aug 12, 2026
c193453
chore: up eval author tasks to 5
Aug 12, 2026
6d47005
chore: allow empty datasets
Aug 12, 2026
4ad20b1
test(experimentalist): require a sandbox for the smoke E2E loops
schuellc-nvidia Aug 12, 2026
0ca530f
test(experimentalist): run smoke loops in sandbox
Aug 12, 2026
0e96918
chore: revert unneeded request timeout
Aug 12, 2026
9c0d88e
chore: revert unrelated change
Aug 12, 2026
7eb6fd6
chore: revert unrelated change
Aug 12, 2026
c729767
chore: revert unwanted change
Aug 12, 2026
635334b
test(experimentalist): isolate smoke E2E runs
Aug 12, 2026
9f22d68
chore: remove unused model client import
Aug 12, 2026
b9b3525
chore(experimentalist): remove unused smoke test tools
Aug 12, 2026
74a92ef
test(experimentalist): share smoke runs across assertions
Aug 12, 2026
1e5cc91
chore: assume existing sandbox
Aug 13, 2026
c25e501
chore(tests): increase e2e test timeouts
Aug 13, 2026
1356c79
docs: update example aent to smoke agent
Aug 13, 2026
8106afb
fix(experimentalist): finalize when no improvements remain
Aug 13, 2026
74c9f25
docs(experimentalist): explain smoke scenario
Aug 13, 2026
5144fcc
refactor(experimentalist): render smoke tasks from manifest
Aug 13, 2026
f46146a
fix(experimentalist): target full smoke objectives
Aug 13, 2026
8bedf2a
docs(experimentalist): correct the smoke-agent weakness reference
schuellc-nvidia Aug 13, 2026
d6f2f2d
fix(experimentalist): address smoke agent review feedback
Aug 13, 2026
ce54161
test(experimentalist): report both digests when the task tree changes
schuellc-nvidia Aug 13, 2026
5b5bc5f
docs(experimentalist): reunite the smoke-agent headings with their co…
schuellc-nvidia Aug 13, 2026
d3e3660
chore: remove internal details
Aug 13, 2026
0b212ad
docs(experimentalist): clarify smoke agent setup
Aug 13, 2026
7aab5ac
refactor(experimentalist): consolidate smoke fixture docs
Aug 13, 2026
1e56719
docs: simplify getting started guide
Aug 13, 2026
95ffeee
docs(experimentalist): keep the fuller smoke-fixture README
schuellc-nvidia Aug 13, 2026
f2292ad
docs: revert the walkthorugh
Aug 13, 2026
6aa685f
fix(experimentalist): repair full-suite test collection
Aug 13, 2026
b3e18cd
Merge branch 'main' into experimentalist-smoke-agent-proposal/cschueller
gaiadilorenzo Aug 13, 2026
38e225b
Merge branch 'main' into experimentalist-smoke-agent-proposal/cschueller
gaiadilorenzo Aug 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .copyrightignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ web/vendor/
release/
.agents/skills/
e2e/
plugins/nemo-experimentalist/examples/smoke-agent/dataset/_shared/records.json
plugins/nemo-experimentalist/examples/smoke-agent/dataset/task-template/instruction.md
plugins/nemo-experimentalist/examples/smoke-agent/dataset/task-template/records.json
plugins/nemo-experimentalist/examples/smoke-agent/dataset/task-template/tests/expected.txt
packages/garak_api/garakapi/_config.py
packages/garak_api/garakapi/_plugins.py
packages/garak_api/garakapi/exception.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
Task,
TrialResult,
)
from nemo_experimentalist_plugin.experimentalist.components import cache
from nemo_experimentalist_plugin.experimentalist.components.tools import GuardedShellTools
from nemo_experimentalist_plugin.experimentalist.components.trace_analyzer import (
Diagnostic,
Expand Down Expand Up @@ -486,7 +485,6 @@ async def _run(
reporter.note(f"trace analysis failed for {ref}: {result}")
analysis_statuses[task.id] = ("failed", str(result))
continue
cache.store(self.experiment_dir, cache.task_hash(f"eval_author:{ref}"), result)
diagnostics.append((ref, result))
analysis_statuses[task.id] = ("completed", None)
insight_suite.record_analysis(analysis_statuses)
Expand Down
1 change: 0 additions & 1 deletion plugins/nemo-eval-author/tests/test_eval_author_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,6 @@ def validate_metric_contracts(
monkeypatch.setattr(eval_author_module, "TraceAnalyzer", FakeTraceAnalyzer)
monkeypatch.setattr(eval_author_module, "validate_metric_contracts", validate_metric_contracts)

monkeypatch.setattr(eval_author_module.cache, "store", lambda *args: None)
monkeypatch.setattr(eval_author_module, "doc", lambda *_args, **_kwargs: "dataset docs")
return calls

Expand Down
2 changes: 0 additions & 2 deletions plugins/nemo-eval-author/tests/test_plugin_boundary.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
# adding one needs a deliberate argument for why duplicating the helper is worse.
#
# client -> make_client, the platform client factory
# ...components -> the cache module, for run artifacts
# ...dataset_staging -> stage_eval_author_inputs
# ...evaluator.base -> EvaluatorType
# ...evaluator.factory -> DatasetFactory
Expand All @@ -41,7 +40,6 @@
# ...reporting -> RunReporter (ASE-749: reuse Experimentalist narrator; do not duplicate)
_BORROWED_BEHAVIOUR = {
"nemo_experimentalist_plugin.client",
"nemo_experimentalist_plugin.experimentalist.components",
"nemo_experimentalist_plugin.experimentalist.components.dataset_staging",
"nemo_experimentalist_plugin.experimentalist.components.evaluator.base",
"nemo_experimentalist_plugin.experimentalist.components.evaluator.factory",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Generated by scripts/build_all_group.py, not authored.
#
# The loop takes a single --train-dataset path, so running several groups at once
# needs one combined directory. Its contents are byte-identical copies of the
# other groups, so committing it would double the dataset in the repo and put
# every group change in two places. Build it before running the full scenario.
dataset/groups/_all/
75 changes: 75 additions & 0 deletions plugins/nemo-experimentalist/examples/smoke-agent/AGENT-SPEC.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<!-- SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -->
<!-- SPDX-License-Identifier: Apache-2.0 -->

# smoke-agent

## Prerequisites

The task container ships Python, the standard library, and NOOA. It has no
network access and no API key, so anything that needs either fails outright.

## Job
Comment thread
coderabbitai[bot] marked this conversation as resolved.

Answer one question about the records file at `/app/data/records.json` and write
the single answer line to `/app/artifacts/output.txt`.

## Interface

- Invoked as `python main.py --prompt "<instruction text>"` with `/app` as the
working directory.
- Writes exactly one line, plus a trailing newline, to
`/app/artifacts/output.txt`.
- Writes an OTLP JSONL trace under `/app/traces/`.

## Design

`ReportAgent.solve` dispatches the instruction across an ordered list of
handlers and returns the first non-`None` answer, falling back to a fixed
string. Each handler matches the question with a regular expression, looks the
answer up in the records, and formats one line as `<field>=<value>`.

The records are a list of objects with `name`, `dept`, `role`, and `hours`.
`FIELD_ALIASES` maps the word a question uses to the key the records store it
under, so the answer line is always keyed by the canonical field name.

## Missing and empty values

A question may name a person the records do not contain, or ask for a field
whose stored value is an empty string. Both are answered the same way: the value
is the word `unknown`, so the line reads `dept=unknown`. This is part of the
output contract and is compared byte-for-byte like any other answer — the
sentinel is `unknown` exactly, not `n/a`, `none`, or the empty string.

## Answer keys

The key on the left of the `=` names what the answer *is*, not the field it came
from. The vocabulary is fixed:

- a value read from one record uses that field's own name — `dept=`, `role=`,
`hours=`
- a sum over records is reported as **`total=`**, whatever field was summed and
however the records were selected
- a number of records is reported as `count=`

Keys are compared byte-for-byte like the rest of the line, so `hours=99` is wrong
where `total=99` is expected, even though the number is right.

## Constraints — these are hard requirements

- **The agent is deterministic and offline.** The same instruction must always
produce the same answer. Reward differences between candidates must come from
code changes, never from sampling.
- **No LLM.** Do not add a `@strategy` method, an LLM-backed handler, a subagent
with its own model, or a model swap. The task container has no network and no
API key, so such a change fails outright — but more importantly, being
reproducible is this agent's entire contract.
- Standard library plus NOOA only. No new dependencies.
- Do not edit `/app/data/records.json`. It is task-supplied input, not agent
code, and it is not part of this directory.
- The output line is compared byte-for-byte against the task's expected value,
so trailing whitespace, extra lines, and changes to the `<field>=<value>` form
all count as wrong answers.

## Next steps

Any implementation change must still satisfy every constraint above.
Loading
Loading