chore: final touches - #1770
Conversation
- harness configs no longer pin `id`; the caller supplies it (--harness.id / toml / a taskset's bundled harness), mirroring tasksets. Update the base HarnessConfig docstring and the `init` scaffold to match. - refine the v1 user guide (GUIDE.md, README.md) - register the reverse-text v0 env as an editable dep for the `eval --id reverse-text` legacy-bridge example Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
trace.num_turns is recorded by the framework; show a custom signal instead. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Keep the config code block focused on the config class. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Build typed task instances from the rows instead of stopping at the dataset load. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A reward can now report a family of named contributions, like @Metric already can; each entry is recorded under its own key and scaled by the function's weight before being summed into trace.reward. This aligns the reward/metric return contracts — the only remaining (and intended) differences are that rewards are summed and carry a weight. Documented in the v1 guide. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Use an enthusiasm metric and a brevity (length-penalty) group reward instead of stubs, and reword "Notes that bite if missed" to "Good to know". Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Group the trace members by area and fix the table: drop the nonexistent trace.messages (use trace.branches[-1].messages), add usage / has_response / id, and note trace.nodes. Reframe in-runtime scoring around when to use the runtime object (host-unsafe/heavy computation, or runtime-only information). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… process" The trace-reading table now lists only what a reward reads; reward/rewards/ metrics are called out as outputs you shouldn't read mid-scoring. Rename that group to "Carried state" (info/state). Use "host" instead of "eval process". Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
validate isn't part of the setup -> harness -> finalize -> scoring rollout loop (it's run only by `uv run validate`, documented in the CLI reference). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Lift the trace.info paragraph into a "Persisted info" section beside "Per-rollout state", with a table contrasting the two per-rollout stores (persisted vs transient). Cross-link both ways. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vf.tool methods are served as MCP tools the harness connects to. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Each tool/user server is its own self-launching module under servers/. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…t row Both are the same placement (a per-rollout runtime); subprocess on the host by default, a docker/prime sandbox when runtime.type is set. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
general-agent-v1 (per-task dynamic tools), tau2-bench-v1 (tools + user sim + bundled harness), and swebench-verified-v1 (SWE-bench on prebuilt images) were the only *_v1 envs absent from the example table. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Frame authoring a harness as "when you need rollout logic the built-ins can't express" rather than "you rarely need this", and add the mini-swe-agent and kimi-code built-ins to the table. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mention it in the taskset authoring intro alongside the generic params. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…RTS_MCP Rename the flag on the base Harness and every harness that sets it (built-ins + tau2/compact env harnesses), the Environment check, and align the user-facing error message and the README/GUIDE docs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pass endpoint/secret/model as CLI args (as the built-in default harness does) instead of OPENAI_* env vars, which have footguns; note why. Drop the max_steps knob (turn limits are framework-enforced, not a harness concern) and the id pin (harness configs don't pin id), leaving a placeholder config. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Break the wall of bold-lead paragraphs into ### subsections (contract, launch, resolve_prompt, program styles, harness metrics), matching the taskset docs' ##/### structure. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
tau2's taskset defines no vf.User/vf.Toolset; it bundles its own harness that runs the whole tau2 simulation in a subprocess and stores the result in trace.info. It's the bundled-harness example, not a tools+user-sim one. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bring back publish-tasksets.yml / publish-harnesses.yml (dropped on the v1 branch). v1 versions packages statically in pyproject.toml rather than via __init__.py __version__, so the version-detection reads [project].version from pyproject. Bump both packages 0.1.0 -> 0.2.0: the v1 branch had reset them to 0.1.0, below what's already on PyPI (tasksets 0.1.5, harnesses 0.1.2), so a progression is required to publish. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The renderer client is no longer marked experimental; keep the substantive caveat (per-model renderers cover a subset of models). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- drop the v0 reverse-text entry from the examples group - drop stale comments in [dependency-groups]/[tool.uv.sources] - drop the redundant [tool.ruff] line-length = 88 (88 is ruff's default) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
publish-envs.yml matrixes over environments/*; skip the *_v1 packages and the compact harness example — the v1 envs aren't ready for the Environments Hub yet. Classic v0 envs still publish. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The version is read from [project].version in pyproject.toml; the mismatch error still pointed at the old __init__.py source. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
| - main | ||
| tags: | ||
| - "harnesses-v*" |
There was a problem hiding this comment.
🟢 Low workflows/publish-harnesses.yml:12
The push event includes a tags filter for harnesses-v* (lines 13-14), so when auto-tag-on-main pushes a new tag (line 65), the tag push triggers a second workflow run. That second run executes build-tag → publish-tag and attempts to upload the same version to PyPI again, which fails with a 409 Conflict because PyPI rejects duplicate uploads. Consider removing the tags filter from the push event so tag pushes do not start a redundant run.
- main
- tags:
- - "harnesses-v*"🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @.github/workflows/publish-harnesses.yml around lines 12-14:
The `push` event includes a `tags` filter for `harnesses-v*` (lines 13-14), so when `auto-tag-on-main` pushes a new tag (line 65), the tag push triggers a second workflow run. That second run executes `build-tag` → `publish-tag` and attempts to upload the same version to PyPI again, which fails with a 409 Conflict because PyPI rejects duplicate uploads. Consider removing the `tags` filter from the `push` event so tag pushes do not start a redundant run.
The merged #1770 bumped tasksets/harnesses to 0.2.0 and dropped reverse-text from the examples group but didn't update uv.lock; sync it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 2f977db. Configure here.
| path: dist/ | ||
|
|
||
| - name: Publish to PyPI | ||
| uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 |
There was a problem hiding this comment.
Duplicate PyPI publish on release
Medium Severity
When auto-tag-on-main creates and pushes a release tag, the same workflow run publishes to PyPI via publish-from-auto-tag, and the tag push starts a second run whose publish-tag job uploads the same version again. PyPI typically rejects the duplicate, so the tag-triggered workflow fails after a successful release.
Additional Locations (2)
Triggered by project rule: BugBot Instructions
Reviewed by Cursor Bugbot for commit 2f977db. Configure here.
ApprovabilityVerdict: Needs human review This PR introduces new PyPI publishing workflows with unresolved review comments identifying a bug that will cause duplicate publish failures. New deployment infrastructure combined with an unfixed issue in that infrastructure warrants human attention. You can customize Macroscope's approvability policy. Learn more. |
* chore: final touches - harness configs no longer pin `id`; the caller supplies it (--harness.id / toml / a taskset's bundled harness), mirroring tasksets. Update the base HarnessConfig docstring and the `init` scaffold to match. - refine the v1 user guide (GUIDE.md, README.md) - register the reverse-text v0 env as an editable dep for the `eval --id reverse-text` legacy-bridge example Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: don't use auto-tracked num_turns as the @vf.metric example trace.num_turns is recorded by the framework; show a custom signal instead. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: move the load_tasks example into the Loading tasks section Keep the config code block focused on the config class. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: show full GSM8KTask construction in the load_tasks example Build typed task instances from the rows instead of stopping at the dataset load. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat: allow @reward to return dict[str, float] A reward can now report a family of named contributions, like @Metric already can; each entry is recorded under its own key and scaled by the function's weight before being summed into trace.reward. This aligns the reward/metric return contracts — the only remaining (and intended) differences are that rewards are summed and carry a weight. Documented in the v1 guide. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: drop the score/score_group override note Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: livelier scoring examples + reframe the notes heading Use an enthusiasm metric and a brevity (length-penalty) group reward instead of stubs, and reword "Notes that bite if missed" to "Good to know". Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: restructure the trace-reading table and reframe in-runtime scoring Group the trace members by area and fix the table: drop the nonexistent trace.messages (use trace.branches[-1].messages), add usage / has_response / id, and note trace.nodes. Reframe in-runtime scoring around when to use the runtime object (host-unsafe/heavy computation, or runtime-only information). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: separate scoring outputs from read inputs; say "host" not "eval process" The trace-reading table now lists only what a reward reads; reward/rewards/ metrics are called out as outputs you shouldn't read mid-scoring. Rename that group to "Carried state" (info/state). Use "host" instead of "eval process". Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: drop validate from the lifecycle-hooks table validate isn't part of the setup -> harness -> finalize -> scoring rollout loop (it's run only by `uv run validate`, documented in the CLI reference). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: give info its own section, contrasted with state Lift the trace.info paragraph into a "Persisted info" section beside "Per-rollout state", with a table contrasting the two per-rollout stores (persisted vs transient). Cross-link both ways. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: note that a Toolset wraps an MCP server @vf.tool methods are served as MCP tools the harness connects to. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: show the self-launching __main__ line in the tool/user examples Each tool/user server is its own self-launching module under servers/. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: merge own-host/own-sandbox into a single "own runtime" placement row Both are the same placement (a per-rollout runtime); subprocess on the host by default, a docker/prime sandbox when runtime.type is set. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: add the missing reference examples general-agent-v1 (per-task dynamic tools), tau2-bench-v1 (tools + user sim + bundled harness), and swebench-verified-v1 (SWE-bench on prebuilt images) were the only *_v1 envs absent from the example table. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: reframe the custom-harness intro and list mini-swe-agent/kimi-code Frame authoring a harness as "when you need rollout logic the built-ins can't express" rather than "you rarely need this", and add the mini-swe-agent and kimi-code built-ins to the table. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: surface the NEEDS_CONTAINER taskset capability flag Mention it in the taskset authoring intro alongside the generic params. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor: rename harness capability flag SUPPORTS_TASK_TOOLS -> SUPPORTS_MCP Rename the flag on the base Harness and every harness that sets it (built-ins + tau2/compact env harnesses), the Environment check, and align the user-facing error message and the README/GUIDE docs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: harness example configures via CLI args, drops max_steps Pass endpoint/secret/model as CLI args (as the built-in default harness does) instead of OPENAI_* env vars, which have footguns; note why. Drop the max_steps knob (turn limits are framework-enforced, not a harness concern) and the id pin (harness configs don't pin id), leaving a placeholder config. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: split the harness "Writing one" section into subsections Break the wall of bold-lead paragraphs into ### subsections (contract, launch, resolve_prompt, program styles, harness metrics), matching the taskset docs' ##/### structure. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: correct the tau2-bench-v1 example description tau2's taskset defines no vf.User/vf.Toolset; it bundles its own harness that runs the whole tau2 simulation in a subprocess and stores the result in trace.info. It's the bundled-harness example, not a tools+user-sim one. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: drop internal bench/ scripts and COMPARE.md from v1 These are work-in-progress benchmarking scripts and a transient PrimeIntellect-ai#1559-vs-PrimeIntellect-ai#1576 comparison doc — not part of the public v1 surface. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * ci: restore taskset/harness PyPI publish workflows; bump to 0.2.0 Bring back publish-tasksets.yml / publish-harnesses.yml (dropped on the v1 branch). v1 versions packages statically in pyproject.toml rather than via __init__.py __version__, so the version-detection reads [project].version from pyproject. Bump both packages 0.1.0 -> 0.2.0: the v1 branch had reset them to 0.1.0, below what's already on PyPI (tasksets 0.1.5, harnesses 0.1.2), so a progression is required to publish. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: drop the experimental flag from the renderer client The renderer client is no longer marked experimental; keep the substantive caveat (per-model renderers cover a subset of models). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: drop stale v1-runtime dependency comment Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: tidy verifiers pyproject - drop the v0 reverse-text entry from the examples group - drop stale comments in [dependency-groups]/[tool.uv.sources] - drop the redundant [tool.ruff] line-length = 88 (88 is ruff's default) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * ci: exclude v1 envs from the auto env-publish for now publish-envs.yml matrixes over environments/*; skip the *_v1 packages and the compact harness example — the v1 envs aren't ready for the Environments Hub yet. Classic v0 envs still publish. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * ci: fix version-mismatch message to reference pyproject, not __init__.py The version is read from [project].version in pyproject.toml; the mismatch error still pointed at the old __init__.py source. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The merged PrimeIntellect-ai#1770 bumped tasksets/harnesses to 0.2.0 and dropped reverse-text from the examples group but didn't update uv.lock; sync it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>


Summary
Final-touches pass over the v1 docs, plus a small scoring feature, CI changes, and cleanup.
Docs (
verifiers/v1/GUIDE.md,README.md)Trace(dropped the nonexistenttrace.messages, addedusage/has_response/id); a dedicated Persisted info section contrasted with Per-rollout state; split the harness "Writing one" section into subsections; reframed in-runtime scoring around when to use theruntimeobject; "host" instead of "eval process".general-agent-v1,swebench-verified-v1,tau2-bench-v1; fixed the tau2 description; merged the own-host/own-sandbox placement rows).NEEDS_CONTAINERtaskset capability flag; noted aToolsetwraps an MCP server; documented the self-launching__main__server pattern; listed themini-swe-agent/kimi-codebuilt-in harnesses; harness example configures via CLI args (notOPENAI_*env vars) and dropsmax_steps.Scoring feature
@vf.rewardmay now returnfloat | dict[str, float](a family of named contributions, each scaled byweight), mirroring@vf.metric. Existing float rewards are unaffected.Harness configs
id(the caller supplies it), mirroring tasksets; updated the baseHarnessConfigdocstring and theinitscaffold.CI
publish-tasksets.yml/publish-harnesses.yml(dropped on the v1 branch). v1 versions packages statically inpyproject.toml, so the version-detection reads[project].versionfrom pyproject. Bumped both packages0.1.0 → 0.2.0(the branch had reset them below what's on PyPI — tasksets 0.1.5, harnesses 0.1.2).publish-envs.yml: excluded the v1 envs (the*_v1packages + thecompactharness) from the auto env-publish for now; classic v0 envs still publish.docs/training.md,docs/faqs.md): dropped the (experimental) flag.Cleanup
bench/scripts and the transientCOMPARE.md.[tool.ruff] line-length = 88(88 is ruff's default) and stale dependency comments.[tool.uv.sources]entry for thereverse-textv0 env (for theeval --id reverse-textlegacy-bridge example).Breaking
SUPPORTS_TASK_TOOLS→SUPPORTS_MCP. Renamed on the baseHarnessand every built-in/bundled harness, theEnvironmentcheck, and the error message. Any external harness settingSUPPORTS_TASK_TOOLSmust rename it toSUPPORTS_MCP.Note
Medium Risk
The
SUPPORTS_TASK_TOOLS→SUPPORTS_MCPrename breaks external harness subclasses; PyPI publish workflows onmaincan release packages when versions change.Overview
This pass tightens v1 docs and release plumbing, extends scoring, and makes a breaking harness rename.
@vf.rewarddict returns — Rewards can returndict[str, float]like@vf.metric; each entry is weighted and merged intotrace.rewardviaTaskset.score.Harness API —
SUPPORTS_TASK_TOOLSis renamed toSUPPORTS_MCPeverywhere (baseHarness, built-ins,Environmentload check). Harness config subclasses no longer pinid(caller supplies--harness.id); theinitscaffold matches.CI / publishing — New
publish-harnesses.ymlandpublish-tasksets.ymlauto-tag frompyproject.tomlversion onmain, build withuv, and publish to PyPI (harnesses/tasksetsbumped to 0.2.0).publish-envs.ymlnow skips*_v1dirs andcompactso only classic v0 envs hub-publish.Docs — Large
verifiers/v1/GUIDE.mdrefresh (trace tables, persistedinfovsstate, harness authoring, examples).rendererclient is no longer labeled experimental indocs/training.md/docs/faqs.md. Minor README legacy-bridge flag tweak.Cleanup — Removes internal
bench/scripts andCOMPARE.md. Addsreverse-textto[tool.uv.sources]for the v0 bridge example; drops redundant ruff line-length and stale pyproject comments.Reviewed by Cursor Bugbot for commit 2f977db. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Add PyPI publish workflows for harnesses and tasksets packages and rename
SUPPORTS_TASK_TOOLStoSUPPORTS_MCPharnessesandtasksetspackages that auto-tag on pushes tomain, build withuv, and publish to PyPI viapypa/gh-action-pypi-publish. Both packages are bumped to0.2.0.SUPPORTS_TASK_TOOLStoSUPPORTS_MCPacross the base class, all harness implementations, environment code, and documentation.publish-envsworkflow matrix to exclude*_v1andcompactenvironments, limiting it to classic v0 environments.bench/directory andCOMPARE.md, removes the(experimental)qualifier fromrendererclient type in docs, and addsreverse-textas an editable uv source.Macroscope summarized 2f977db.