Skip to content

Add a harness-neutral agent contract and adopt it for Copilot CLI - #1008

Merged
Sun Haoran (haoranpb) merged 7 commits into
core/harness-01-shared-typesfrom
core/harness-02-contract
Nov 3, 2026
Merged

Sun Haoran (haoranpb) merged 7 commits into
core/harness-01-shared-typesfrom
core/harness-02-contract

Conversation

@haoranpb

@haoranpb Sun Haoran (haoranpb) commented Nov 3, 2026 •

Copy link
Copy Markdown
Collaborator

Stacked on #1007.

Adds a harness-neutral agent contract in bcbench_core.agent.harness, designed against all known harnesses (Copilot, Claude, PR Review, BCal, LSA), and adopts it for GitHub Copilot CLI so the contract can be reviewed with a real implementation.

Contract (core)

  • AgentIdentity[N]: harness name (typed by the application, e.g. BC-Bench's AgentHarness), version (CLI semver, engine SHA, hosted agent version) and optional configured model. Resolved before running.
  • AgentRequest[T]: typed task, work dir, output dir, optional timeout (None = harness default). Environment is a harness setting, not per-run input.
  • AgentResult: response, metrics, experiment configuration. A frozen dataclass so metrics subclasses such as PRReviewMetrics pass through unchanged.
  • Harness[T] protocol: identity() and run(request). Generic over the task type, so specialised harnesses (PR Review on CodeReviewEntry, BCal on NL2ALEntry) take their own typed tasks; ty rejects a mismatched harness, so no runtime isinstance checks.

Deliberately out of scope: retries, scoring, dataset loading, workspace setup, config parsing. Transcript, provenance pins and observed model are deferred until a harness needs them.

Uptake (BC-Bench)

  • All harness functions (Copilot, Claude, PR Review, BCal) and the 8 pipelines exchange AgentResult instead of a (metrics, experiment) tuple. Copilot and Claude now return their final message as response (previously discarded).
  • CopilotHarness replaces run_copilot_agent: model, category, agent config, plugin root and runtime are construction-time settings; entry, workspace, output dir, env and timeout arrive per run. identity() replaces the CLI's direct get_copilot_version call.
  • EvaluationContext carries the resolved AgentIdentity (context.agent) instead of separate agent_name, model and agent_version.
  • harness_runner(harness) is a temporary bridge from Harness to the pipelines' AgentRunner. Once Claude, PR Review and BCal become Harness classes, pipelines take a Harness directly and both go away.

Supersedes #1009.

Sun Haoran (haoranpb) and others added 2 commits November 3, 2026 11:13
Harness[T] reports an AgentIdentity (harness, version, configured model,
provenance) before running and turns an AgentRequest[T] into an
AgentResult (response, transcript, metrics, experiment configuration,
observed model). It is generic over the task type so specialised
harnesses (PR Review, BCal, hosted agents) take their own typed tasks,
and AgentResult is a dataclass so harness-specific metrics subclasses
pass through unchanged. The transcript uses the user/assistant turn
shape LMChecklist already scores.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The Copilot, Claude, PR Review and BCal harness functions now return the
core AgentResult instead of a (metrics, experiment) tuple, and pipelines
read it through AgentRunner. Copilot and Claude also return their final
message as the response, which was previously discarded.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The new result type lacks regression coverage confirming that AgentResult preserves a supplied AgentMetrics subclass instance and its extra fields.

1 open issue
What changed in this PR

Adds a shared, harness-neutral agent contract to bcbench-core, allowing evaluation pipelines to work with different agent implementations through one typed interface.

Changes:

  • Defines agent identity, typed requests, results, transcript turns, and the generic Harness[T] protocol.
  • Makes environment input explicit and preserves metrics subclasses in a frozen result dataclass.
  • Documents how applications construct and use harnesses.
File Description
packages/​bcbench-core/​src/​bcbench_core/​agent/​harness.py Introduces the shared agent models and harness protocol.
packages/​bcbench-core/​README.md Documents the contract and its role in evaluation pipelines.

Review effort: Balanced

@github-code-quality

github-code-quality Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Code coverage overview

Languages: Python

Python / code-coverage/pytest

core/harness-01-shar... c89d9aa core/harness-02-cont... 44cd5ec +/-
88% 88% 0%
View coverage of the 10 most impacted files.
File core/harness-01-shar... c89d9aa core/harness-02-cont... 44cd5ec +/-
src/bcbench/exceptions.py 70% 65% -5%
src/bcbench/eva...uest_advisor.py 94% 91% -3%
src/bcbench/eva...e/codereview.py 90% 88% -2%
src/bcbench/eva...quest_triage.py 62% 60% -2%
src/bcbench/eva...st_implement.py 69% 68% -1%
src/bcbench/eva...te/dataquery.py 69% 68% -1%
src/bcbench/eva...stgeneration.py 56% 55% -1%
src/bcbench/types.py 94% 94% 0%
packages/bcbenc...gent/harness.py 0% 100% +100%
packages/bcbenc...t/experiment.py 0% 100% +100%

ℹ️ Calculations represent line coverage. Results may change as calculations are updated.


Updated November 03, 2026 14:01 UTC

…anscript type

CopilotHarness replaces run_copilot_agent: model, category, agent config,
plugin root and runtime are construction-time settings, while the entry,
workspace, output directory, environment and timeout arrive per run as an
AgentRequest. identity() resolves the Copilot CLI version, replacing the
CLI's direct get_copilot_version call. harness_runner adapts any Harness
to the pipeline's AgentRunner, so other harnesses can follow the same path.

The harness now scrubs BC credentials from the request's environment
instead of reading the process environment. The transcript type is
deferred until a harness produces one.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@haoranpb Sun Haoran (haoranpb) changed the title Add a harness-neutral agent contract to bcbench-core Add a harness-neutral agent contract and adopt it for Copilot CLI Nov 3, 2026
Comment thread src/bcbench/evaluate/base.py Resolved
Comment thread src/bcbench/commands/evaluate.py Resolved
Sun Haoran (haoranpb) and others added 2 commits November 3, 2026 12:02
…contract

EvaluationContext now holds the resolved AgentIdentity instead of separate
agent_name, model and agent_version fields; results read harness, model
and version from it. The environment is a harness concern, not per-run
input, so AgentRequest no longer carries it and the Copilot harness reads
it as before.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…its timeout a field

AgentIdentity and Harness take an optional harness-name type, so BC-Bench
uses AgentIdentity[AgentHarness] and reads the enum (and its metrics
contract) without converting from str. CopilotHarness explicitly inherits
Harness so ty checks it at the class definition, and its default timeout
is a dataclass field instead of a module constant.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Drop AgentIdentity.provenance and AgentResult.observed_model until a
harness needs them, simplify the module docstring, and remove the README
section.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

An explicit timeout of 0 is incorrectly replaced with the default timeout; the fallback must apply only to None so numeric overrides are preserved.

1 open issue
1 resolved since last review

Review effort: Balanced

Comment thread src/bcbench/agent/copilot/agent.py Resolved
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@haoranpb
Sun Haoran (haoranpb) merged commit 425f6b5 into main Nov 3, 2026
17 checks passed
@haoranpb
Sun Haoran (haoranpb) deleted the core/harness-02-contract branch November 3, 2026 14:29
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.

3 participants