Skip to content

Redesign VeRO as a generic program optimization harness#41

Open
varunursekar wants to merge 21 commits into
mainfrom
v0.5
Open

Redesign VeRO as a generic program optimization harness#41
varunursekar wants to merge 21 commits into
mainfrom
v0.5

Conversation

@varunursekar

@varunursekar varunursekar commented Jul 15, 2026

Copy link
Copy Markdown

Summary

  • replace the paper-era Policy and experiment model with backend-neutral candidate, evaluation, optimization, runtime, workspace, and coding-agent interfaces
  • support language-neutral command evaluators, optimizer-independent Python tasks, and Harbor as a canonical evaluation backend
  • add a declarative vero.toml workflow, baseline-only vero evaluate, repeatable vero run, and a complete CLI for objectives, constraints, case selection, refs, environments, limits, and concurrency
  • add a checked-in C matrix-multiplication quickstart that compiles, checks correctness, benchmarks, optimizes, selects the faster feasible commit, preserves the target checkout, and cleans up worktrees
  • support sequential and parallel candidate production, durable budgets and reports, external producers, built-in Vero and Claude coding agents, and cancellation-safe concurrent batches
  • make session resume restore candidate lineage, completed rounds, compatible evaluation history, and supported coding-agent state
  • add recursive session discovery, aggregate evaluation inspection, and optional W&B reporting over canonical runtime events
  • add Harbor sidecar, verifier, transport, HTTP/CLI, and task compiler support with trusted policy and finalization boundaries
  • retain both Python and non-Python matrix-multiplication examples while keeping exact paper reproduction on paper/v1 and the paper-v1 tag

Harbor and Modal

  • support Harbor at the outer level by compiling a VeRO optimization into a canonical Harbor task
  • support Harbor at the inner level by evaluating candidate programs through nested harbor run jobs
  • propagate required task-environment secrets to remote Harbor environments without embedding their values in the compiled task
  • support pinned Harbor environment extras such as harbor[modal]==0.18.0 and select an explicit inner Python version
  • preserve both local Harbor selectors and canonical result task names
  • import candidates safely across the outer agent/sidecar UID boundary using exact trusted Git directories

Hardening

  • terminate complete host process groups on timeout/cancellation and terminate the in-container process group for Docker executions
  • reconcile database.json from canonical completed evaluation directories on resume, closing the write-order crash window
  • persist cancelled evaluations as terminal records and make durable budget reservation disk/memory atomic under cancellation; budgets explicitly meter attempted runs
  • use detached candidate worktrees, roll back interrupted copies, and retain evaluated commits under durable hidden refs/vero/... refs without leaking normal branches
  • make the generic evaluation engine fail closed unless authorization is configured; the trusted local factory opts into an explicit allow-all resolver
  • validate optimizer configuration as a discriminated command/agent union so irrelevant fields cannot be silently ignored
  • map backend request rejection to HTTP 400, separate producer and evaluation timeouts in the CLI, lock database readers, and move remaining durable writes off async event loops
  • document aggregate-differencing and shared-container admin-token trust assumptions

Validation

  • complete suite: 379 passed, 6 skipped
  • Ruff checks pass for all changed Python files
  • source distribution and wheel build successfully
  • checked-in C optimizer and advertised Python evaluation example pass end to end
  • live credentialed VeroAgent C matrix-multiplication optimization completed with five agent checkpoints plus baseline and selected an improved candidate (about 5.5x faster in that run)
  • both tracked uv lockfiles pass uv lock --check
  • isolated wheel imports pass for base, Claude, optimize, and Harbor dependency sets
  • deterministic outer-Harbor-on-Modal smoke completed with reward 1.0 and no exceptions
  • real outer Codex (gpt-5) run completed the full nested workflow on Modal: status, candidate validation through inner Harbor, submission, trusted hidden final evaluation through inner Harbor, and outer reward 1.0 with no exceptions

The final live topology is:

Harbor (Modal, Codex) -> VeRO sidecar -> Harbor validation (Modal) -> submit -> VeRO verifier -> Harbor hidden final (Modal)

Greptile Summary

This PR replaces the paper-era VeRO implementation with a fully generic program optimization harness: backend-neutral candidate/evaluation/optimization/runtime interfaces, a declarative vero.toml workflow, Harbor/Modal integration as both outer task and inner evaluation backend, and hardened worktree, budget, and session lifecycle management.

  • Evaluation engine: new EvaluationEngine with authorization resolver, discriminated-union optimizer config, asyncio.to_thread for all durable writes (engine, budget, sidecar, session), and asyncio.TaskGroup-based parallel candidate production replacing the previous asyncio.gather approach.
  • Harbor integration: GitCandidateTransport fetches via unique temporary refs to avoid FETCH_HEAD races, retains commits under hidden refs/vero/… refs, and validates all paths and symlinks before extraction in the build compiler.
  • Unshielded cleanup: in Optimizer._produce_candidate, the finally: await candidate_workspace.destroy() is not wrapped with asyncio.shield, so when TaskGroup cancels sibling tasks the git worktree removal can be interrupted mid-execution, leaving worktrees registered and on disk — unlike temp_copy, which already uses asyncio.shield for the same cleanup.

Confidence Score: 4/5

Safe to merge with the worktree cleanup fix; all other hardening, atomicity, and security changes look correct.

The entire new evaluation/optimization/harbor stack is well-structured and the previously-flagged blocking-write issues are resolved with asyncio.to_thread throughout. One gap remains: Optimizer._produce_candidate calls await candidate_workspace.destroy() in a bare finally block that is not shielded, so a TaskGroup cancellation during parallel production can abort the git worktree teardown mid-way, leaving worktrees registered on disk. All other cleanup paths (temp_copy, budget reservation, session manifest) are already shielded consistently.

vero/src/vero/optimization/optimizer.py — the _produce_candidate finally block needs asyncio.shield on destroy().

Important Files Changed

Filename Overview
vero/src/vero/optimization/optimizer.py New batch-oriented optimizer with parallel candidate production; unshielded destroy() in finally block can leave git worktrees allocated when a parallel task is cancelled by TaskGroup.
vero/src/vero/harbor/transport.py New GitCandidateTransport: resolves agent ref to an object ID before fetching, uses a unique temporary ref to avoid FETCH_HEAD races, retains commits under refs/vero/candidates/, and validates all paths as absolute.
vero/src/vero/evaluation/engine.py New EvaluationEngine with authorization resolver, budget metering, and atomic asyncio.to_thread persistence. Correctly wraps the synchronous write in to_thread (previously-flagged issue is addressed).
vero/src/vero/harbor/verifier.py New CanonicalVerifier for final candidate scoring; the blocking _atomic_write_json inside the asyncio.Lock in finalize was flagged in a previous thread and remains unaddressed.
vero/src/vero/workspace/git.py Refactored worktree management to use --detach, roll back interrupted copies, propagate project_path correctly into copies; temp_copy correctly shields cleanup with asyncio.shield.
vero/src/vero/harbor/sidecar.py Agent-facing sidecar with access policies, aggregate floor enforcement, and correct asyncio.to_thread offloading; previously-flagged sync-write issue is resolved.
vero/src/vero/evaluation/security.py New sanitize_evaluation_report helper that redacts secrets from all free-form report fields while preserving structural identifiers.
vero/src/vero/harbor/build/compiler.py New Harbor task compiler; _safe_extract_tar validates all member paths and symlink targets before extraction.
vero/src/vero/config.py New declarative vero.toml config system with discriminated-union OptimizerConfig validation and path resolution beside the config file.
vero/src/vero/runtime/session.py New durable OptimizationSession with manifest reconciliation on resume and asyncio.to_thread for all manifest writes.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant CLI as vero CLI
    participant Session as OptimizationSession
    participant Optimizer as Optimizer
    participant TG as asyncio.TaskGroup
    participant Producer as CandidateProducer
    participant Workspace as GitWorkspace copy
    participant Engine as EvaluationEngine
    participant Backend as EvaluationBackend

    CLI->>Session: run()
    Session->>Optimizer: run(baseline)
    Optimizer->>Engine: evaluate_candidate(baseline)
    Engine->>Backend: evaluate(request)
    Backend-->>Engine: EvaluationReport
    Engine-->>Optimizer: EvaluationRecord baseline

    loop max_rounds
        Optimizer->>Optimizer: strategy.propose(context)
        Optimizer->>TG: create tasks parallel proposals
        TG->>Workspace: copy from_version parent.version
        TG->>Producer: produce workspace evaluation_gateway
        Producer->>Engine: evaluate_current optional checkpoints
        Engine-->>Producer: EvaluationRecord
        Producer-->>TG: CandidateChange
        Note over TG,Workspace: finally await destroy not shielded
        TG->>Engine: evaluate_candidate new_candidate
        Engine->>Backend: evaluate request
        Backend-->>Engine: EvaluationReport
        Engine-->>Optimizer: EvaluationRecord
    end

    Optimizer-->>Session: OptimizationResult
    Session-->>CLI: best candidate
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant CLI as vero CLI
    participant Session as OptimizationSession
    participant Optimizer as Optimizer
    participant TG as asyncio.TaskGroup
    participant Producer as CandidateProducer
    participant Workspace as GitWorkspace copy
    participant Engine as EvaluationEngine
    participant Backend as EvaluationBackend

    CLI->>Session: run()
    Session->>Optimizer: run(baseline)
    Optimizer->>Engine: evaluate_candidate(baseline)
    Engine->>Backend: evaluate(request)
    Backend-->>Engine: EvaluationReport
    Engine-->>Optimizer: EvaluationRecord baseline

    loop max_rounds
        Optimizer->>Optimizer: strategy.propose(context)
        Optimizer->>TG: create tasks parallel proposals
        TG->>Workspace: copy from_version parent.version
        TG->>Producer: produce workspace evaluation_gateway
        Producer->>Engine: evaluate_current optional checkpoints
        Engine-->>Producer: EvaluationRecord
        Producer-->>TG: CandidateChange
        Note over TG,Workspace: finally await destroy not shielded
        TG->>Engine: evaluate_candidate new_candidate
        Engine->>Backend: evaluate request
        Backend-->>Engine: EvaluationReport
        Engine-->>Optimizer: EvaluationRecord
    end

    Optimizer-->>Session: OptimizationResult
    Session-->>CLI: best candidate
Loading

Fix All in Cursor Fix All in Claude Code Fix All in Codex

Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
vero/src/vero/optimization/optimizer.py:281-282
**Unshielded worktree cleanup under `TaskGroup` cancellation**

`await candidate_workspace.destroy()` in the `finally` block is not wrapped with `asyncio.shield`. When `max_concurrency > 1` and one `produce(proposal)` task raises, `asyncio.TaskGroup` cancels all remaining tasks by calling `task.cancel()`. Python raises `CancelledError` at the first `await` the cancelled task encounters — which is the `await candidate_workspace.destroy()` call here. The `destroy()` coroutine is then aborted at its own internal `await` (e.g., the `self._sandbox.run` call inside `_remove_worktree`), leaving the git worktree registered and on disk. The `temp_copy` context manager already uses `asyncio.shield` for the same reason, so the fix is consistent with existing practice.

Reviews (6): Last reviewed commit: "Document nested Modal Harbor workflow" | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

@socket-security

socket-security Bot commented Jul 15, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedpypi/​wandb@​0.25.1 ⏵ 0.28.074100100100100
Addedpypi/​pydantic@​2.13.4100100100100100
Addedpypi/​fastapi@​0.139.0100100100100100

View full report

@socket-security

socket-security Bot commented Jul 15, 2026

Copy link
Copy Markdown

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn Medium
Potential vulnerability: pypi ipython with risk level "medium"

Location: Package overview

From: ?pypi/jupyter@1.1.1pypi/ipython@9.15.0

ℹ Read more on: This package | This alert | Navigating potential vulnerabilities

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: It is advisable to proceed with caution. Engage in a review of the package's security aspects and consider reaching out to the package maintainer for the latest information or patches.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/ipython@9.15.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Medium
Potential vulnerability: pypi ipython with risk level "medium"

Location: Package overview

From: ?pypi/jupyter@1.1.1pypi/ipython@9.15.0

ℹ Read more on: This package | This alert | Navigating potential vulnerabilities

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: It is advisable to proceed with caution. Engage in a review of the package's security aspects and consider reaching out to the package maintainer for the latest information or patches.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/ipython@9.15.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

Comment thread vero/src/vero/evaluation/engine.py
Comment thread vero/src/vero/evaluation/budget.py Outdated
Comment thread vero/src/vero/optimization/optimizer.py Outdated
Comment thread vero/src/vero/evaluation/persistence.py
Comment on lines +394 to +400
result = await self._finalize()
_atomic_write_json(
self.result_path,
result.model_dump(mode="json"),
)
self._result = result
return result

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Blocking _atomic_write_json inside an asyncio.Lock in finalize

_atomic_write_json (mkstemp → write → fsync → rename) is called synchronously while holding self._lock, blocking the event loop for the full duration of the disk write. Every coroutine waiting on self._lock — or any other coroutine in the same event loop — is stalled until fsync returns. The same pattern was addressed in engine.py and budget.py with asyncio.to_thread; the same fix applies here.

Suggested change
result = await self._finalize()
_atomic_write_json(
self.result_path,
result.model_dump(mode="json"),
)
self._result = result
return result
result = await self._finalize()
await asyncio.to_thread(
_atomic_write_json,
self.result_path,
result.model_dump(mode="json"),
)
self._result = result
return result
Prompt To Fix With AI
This is a comment left during a code review.
Path: vero/src/vero/harbor/verifier.py
Line: 394-400

Comment:
Blocking `_atomic_write_json` inside an `asyncio.Lock` in `finalize`

`_atomic_write_json` (mkstemp → write → fsync → rename) is called synchronously while holding `self._lock`, blocking the event loop for the full duration of the disk write. Every coroutine waiting on `self._lock` — or any other coroutine in the same event loop — is stalled until fsync returns. The same pattern was addressed in `engine.py` and `budget.py` with `asyncio.to_thread`; the same fix applies here.

```suggestion
            result = await self._finalize()
            await asyncio.to_thread(
                _atomic_write_json,
                self.result_path,
                result.model_dump(mode="json"),
            )
            self._result = result
            return result
```

How can I resolve this? If you propose a fix, please make it concise.

Fix in Cursor Fix in Claude Code Fix in Codex

Comment thread vero/src/vero/harbor/sidecar.py
Comment on lines +281 to +282
finally:
await candidate_workspace.destroy()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Unshielded worktree cleanup under TaskGroup cancellation

await candidate_workspace.destroy() in the finally block is not wrapped with asyncio.shield. When max_concurrency > 1 and one produce(proposal) task raises, asyncio.TaskGroup cancels all remaining tasks by calling task.cancel(). Python raises CancelledError at the first await the cancelled task encounters — which is the await candidate_workspace.destroy() call here. The destroy() coroutine is then aborted at its own internal await (e.g., the self._sandbox.run call inside _remove_worktree), leaving the git worktree registered and on disk. The temp_copy context manager already uses asyncio.shield for the same reason, so the fix is consistent with existing practice.

Prompt To Fix With AI
This is a comment left during a code review.
Path: vero/src/vero/optimization/optimizer.py
Line: 281-282

Comment:
**Unshielded worktree cleanup under `TaskGroup` cancellation**

`await candidate_workspace.destroy()` in the `finally` block is not wrapped with `asyncio.shield`. When `max_concurrency > 1` and one `produce(proposal)` task raises, `asyncio.TaskGroup` cancels all remaining tasks by calling `task.cancel()`. Python raises `CancelledError` at the first `await` the cancelled task encounters — which is the `await candidate_workspace.destroy()` call here. The `destroy()` coroutine is then aborted at its own internal `await` (e.g., the `self._sandbox.run` call inside `_remove_worktree`), leaving the git worktree registered and on disk. The `temp_copy` context manager already uses `asyncio.shield` for the same reason, so the fix is consistent with existing practice.

How can I resolve this? If you propose a fix, please make it concise.

Fix in Cursor Fix in Claude Code Fix in Codex

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant