Skip to content

feat(verify): runner parity + contract wiring for embed-repro (Phase 2) - #11

Open
BoozeLee wants to merge 1 commit into
fix/embed-repro-metadatafrom
fix/embed-repro-runner
Open

BoozeLee wants to merge 1 commit into
fix/embed-repro-metadatafrom
fix/embed-repro-runner

Conversation

@BoozeLee

Copy link
Copy Markdown
Collaborator

Phase 2 of the Q4-2026 roadmap (STRATEGY.md)

This PR stacks on #10 (Phase 1) which adds harness/repro.py and the CLI --embed-repro flag. PR #10 must merge first; once it does, this branch will be a clean fast-forward of main.

What it adds

The runner path is the async, parallel re-implementation of cmd_verify that runs inside harness serve. Before this change, it ignored embed_repro. Now embed_repro_metadata(self.root) runs there too, and the contract carries an embed_repro: bool field so dashboard / API callers do not need to know the flag.

Files

File Δ Purpose
harness/runner.py _verify_run +3 lines When c.get("embed_repro") is true, set ev["repro"] = await asyncio.to_thread(embed_repro_metadata, self.root).
harness/contract.py cmd_start +3 lines Persist "embed_repro": bool(a.embed_repro) in the contract.
harness/contract.py cmd_update +6 lines --embed-repro {on,off} toggle that normalises strings to bool.
harness/cli.py task start +2 lines --embed-repro flag.
harness/cli.py task update +4 lines --embed-repro {on,off} symmetric flag.
harness/server.py TaskCreate +1 line embed_repro: bool = False field.
harness/server.py /api/tasks +1 line Pass embed_repro=body.embed_repro into cmd_start.
harness/server.py /api/tasks/{name}/verify +6 lines Optional embed_repro query param; when provided & different, the contract is amended via jsave so the next run inherits.
tests/test_runner.py (new) +208 lines 8 tests covering runner parity, contract persistence, override idempotency, and CLI surface.

Why contract-stored instead of argv-flag-plumbed

The runner doesn't parse argv; Runner.create(..., argv, worktree) records argv but _verify_run re-implements the verify work inline. So embed_repro flows through the contract, not argv. The FastAPI handler optionally amends the contract for per-invocation overrides; the override is idempotent and visible on the dashboard.

Behaviour change

None for existing callers. The CLI harness verify --embed-repro already worked from Phase 1; nothing there changes.

Tests

uv run pytest -q tests/test_runner.py   →   8 passed
uv run pytest -q (full suite)          →   107 passed
uv run ruff check harness/ tests/...   →   clean
uv run mypy harness/                   →   no issues

Out of scope

  • --numeric-verify flag → separate Phase 3 PR.
  • verify-all orchestrator → Phase 5 (depends on Phase 3 + 4).

Acceptance

  • harness serve and harness verify produce byte-identical repro blocks for the same inputs (test_repro_block_is_byte_identical_to_cli_when_inputs_match).
  • POST /api/tasks with embed_repro: true → contract stores it, runner emits the repro block.
  • POST /api/tasks/<name>/verify?embed_repro=true overrides and persists.

Phase 2 of the Q4-2026 roadmap (STRATEGY.md).

The CLI path `harness verify --embed-repro` already writes a stable
`repro` block into evidence JSON (Phase 1, PR #10). This commit wires
the same behavior into the runner path (the async parallel reimplementation
of verify used by `harness serve`) and exposes it through the task
contract so dashboard / API callers do not have to know the flag.

  - harness/runner.py:_verify_run
      When the loaded contract has embed_repro=True, ev['repro'] =
      embed_repro_metadata(root). Same shape as cmd_verify; same total
      contract (the function never raises).

  - harness/contract.py:cmd_start
      Persists 'embed_repro': bool(a.embed_repro) into the contract; default
      off. No schema_version bump needed (field is forward-compatible).

  - harness/contract.py:cmd_update
      Adds '--embed-repro {on,off}' toggle. Normalises the on/off string
      into the persisted bool.

  - harness/cli.py
      --embed-repro on 'task start'; --embed-repro {on,off} on 'task update'
      for symmetry with the existing 'verify --embed-repro'.

  - harness/server.py
      TaskCreate gains 'embed_repro: bool = False' (POST /api/tasks).
      /api/tasks/{name}/verify gains 'embed_repro: bool | None' query:
      when provided and different from the contract, the contract is
      amended via jsave so the dashboard reflects the new state and the
      next run inherits it. argv stays 'verify <name>' because the runner
      does not parse flags; embed_repro is plumbed via contract.

tests
  - tests/test_runner.py (new, 8 tests, all pass):
    - test_runner_emits_repro_when_contract_says_so
    - test_runner_omits_repro_when_off
    - test_per_invocation_embed_repro_override_mutates_contract
    - test_repro_block_is_byte_identical_to_cli_when_inputs_match
    - test_task_start_persists_embed_repro
    - test_task_start_default_is_off
    - test_task_update_toggles_embed_repro
    - one extra sanity test for the CLI surface

verified
  - uv run pytest -q tests/test_runner.py -> 8 passed
  - uv run pytest -q (full suite)          -> 107 passed
  - uv run ruff check harness/ tests/...   -> clean
  - uv run mypy harness/                   -> no issues

This branch has not been deployed

No deployments
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