Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 19 additions & 0 deletions codex-cli/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion harness/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ build-backend = "hatchling.build"
helios-harness = "harness.scripts.run_harness:main"

[tool.hatch.build.targets.wheel]
packages = ["harness.src.harness"]
packages = ["src/harness"]

# M1/Apple Silicon build settings
[tool.hatch.envs.default]
Expand Down
8 changes: 6 additions & 2 deletions harness/scripts/run-harness.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
from datetime import UTC, datetime
from pathlib import Path

from jsonschema import validate

ROOT = Path(__file__).resolve().parents[1] / "src"
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
Expand Down Expand Up @@ -174,6 +172,8 @@ def run_runner(repo: str, profile: str, out: str, args) -> None:

if args.dry_run:
result["result_code"] = "WARN" if not commands else "PASS"
from harness.benchmark_envelope import add_envelope
result = add_envelope(result, repo=repo, profile=profile, plan_hash=command_hash)
Comment on lines +175 to +176

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: Wrapping the dry-run payload by replacing result with add_envelope(...) drops legacy top-level fields like result_code and plan_hash that existing consumers and tests still read. Keep those fields in the emitted JSON (for compatibility) or include them in the envelope output before writing the file. [api mismatch]

Severity Level: Critical 🚨
- ❌ Dry-run CLI output breaks test_harness_dry_run expectations.
- ❌ Consumers reading result_code from dry-run output fail.
- ⚠️ Replay logic using dry-run artifacts becomes incompatible.
Steps of Reproduction ✅
1. Execute the dry-run CLI path as in `harness/tests/test_run_harness.py:46-61`, which
runs `python3 harness/scripts/run-harness.py run --repo <repo> --out <out_run> --dry-run
...` via `_run()`.

2. The `run_runner()` function in `harness/scripts/run-harness.py:101-165` builds `result`
with keys including `plan_hash`, `plan`, `command_count`, and `reproducibility`.

3. In the dry-run branch at `harness/scripts/run-harness.py:173-176`,
`result["result_code"]` is set and then `result = add_envelope(result, repo=repo,
profile=profile, plan_hash=command_hash)` replaces the original dict with the envelope
returned by `harness/src/harness/benchmark_envelope.py:15-45`, which does not expose
top-level `result_code` or `plan_hash`.

4. `Path(out).write_text(json.dumps(result, indent=2))` at
`harness/scripts/run-harness.py:177` writes this envelope; when the test at
`harness/tests/test_run_harness.py:63-66` reads `output["result_code"]` and
`output["plan_hash"]`, those keys are missing, causing assertion failure and breaking any
consumer expecting the legacy dry-run contract.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** harness/scripts/run-harness.py
**Line:** 175:176
**Comment:**
	*Api Mismatch: Wrapping the dry-run payload by replacing `result` with `add_envelope(...)` drops legacy top-level fields like `result_code` and `plan_hash` that existing consumers and tests still read. Keep those fields in the emitted JSON (for compatibility) or include them in the envelope output before writing the file.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Path(out).write_text(json.dumps(result, indent=2))
return

Expand All @@ -195,6 +195,8 @@ def run_runner(repo: str, profile: str, out: str, args) -> None:
payload["reproducibility"] = _reproducibility_metadata(profile, args)
payload["created_at"] = datetime.now(tz=UTC).isoformat()
payload["command_count"] = len(commands)
from harness.benchmark_envelope import add_envelope
payload = add_envelope(payload, repo=repo, profile=profile, plan_hash=command_hash)
Comment on lines +198 to +199

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: Replacing the normal run payload with envelope-only JSON removes plan/plan_hash, so a later --replay run cannot recover the prior command plan and will compute same_plan/diffs from empty data. Preserve replay-critical fields in persisted output (or embed them in the envelope) so replay comparisons remain correct. [logic error]

Severity Level: Critical 🚨
- ❌ Replay CLI cannot compare plans from prior run envelope.
- ❌ second.json replay.same_plan check in tests fails.
- ⚠️ Plan_diff computed against empty prior_commands is misleading.
Steps of Reproduction ✅
1. Run the first non-dry harness run as in `harness/tests/test_run_harness.py:75-88`,
which executes `python3 harness/scripts/run-harness.py run --repo <repo> --out <out_first>
--timeout 2` and triggers `run_runner()` normal path.

2. Inside `run_runner()` at `harness/scripts/run-harness.py:191-197`, `payload =
evidence_payload(discovery, runs, normalization)` builds the harness evidence (with
`commands`, `runs`, `result_code`, etc.), and `payload["plan_hash"] = command_hash` adds
the current plan hash.

3. At `harness/scripts/run-harness.py:198-199`, `payload = add_envelope(payload,
repo=repo, profile=profile, plan_hash=command_hash)` wraps this evidence into the envelope
defined in `harness/src/harness/benchmark_envelope.py:15-45`, discarding top-level `plan`,
`commands`, and `plan_hash` from the persisted JSON written at `run-harness.py:245`.

4. The second run with replay at `harness/tests/test_run_harness.py:90-104` passes
`--replay <out_first>`, so `run_runner()` reads the envelope via `prior =
json.loads(replay_path.read_text())` at `harness/scripts/run-harness.py:204`, then
attempts `prior_commands = prior.get("plan")` and `prior_commands = prior.get("commands",
[])` plus `prior_hash = prior.get("plan_hash")` at lines 205-208; because the envelope
lacks these keys, `prior_commands` becomes an empty list and `prior_hash` is recomputed
from an empty plan, making `same_plan = prior_hash == command_hash` at line 235 false and
`plan_diff` at line 236 a diff against empty commands, causing
`second_payload["replay"]["same_plan"]` checked in
`harness/tests/test_run_harness.py:108-109` to be incorrect and assertions to fail.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** harness/scripts/run-harness.py
**Line:** 198:199
**Comment:**
	*Logic Error: Replacing the normal run payload with envelope-only JSON removes `plan`/`plan_hash`, so a later `--replay` run cannot recover the prior command plan and will compute `same_plan`/diffs from empty data. Preserve replay-critical fields in persisted output (or embed them in the envelope) so replay comparisons remain correct.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎


if args.replay:
replay_path = Path(args.replay)
Expand Down Expand Up @@ -277,6 +279,8 @@ def normalize_run(input_file: str, out: str) -> None:


def validate_artifacts(schema: str, file: str) -> None:
from jsonschema import validate

payload = json.loads(Path(file).read_text())
schema_json = json.loads(Path(schema).read_text())
validate(instance=payload, schema=schema_json)
Expand Down
45 changes: 45 additions & 0 deletions harness/src/harness/benchmark_envelope.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"""Deterministic umbrella evidence envelope for harness runs."""

from __future__ import annotations

import hashlib
import json
from datetime import UTC, datetime


def _digest(value: object) -> str:
encoded = json.dumps(value, sort_keys=True, separators=(",", ":")).encode()
return hashlib.sha256(encoded).hexdigest()


def add_envelope(payload: dict, *, repo: str, profile: str, plan_hash: str) -> dict:

Check warning on line 15 in harness/src/harness/benchmark_envelope.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the unused function parameter "profile".

See more on https://sonarcloud.io/project/issues?id=KooshaPari_helios-cli&issues=AZ-JjNaAdJ1LoJ_JLvpl&open=AZ-JjNaAdJ1LoJ_JLvpl&pullRequest=612
identity = {"repo": repo, "commit": "0000000", "harness": "helios-harness", "model": "unknown", "task_id": f"plan:{plan_hash}", "hardware": "unknown"}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Use the actual commit in deterministic identity

For benchmark runs on the same repo path with the same discovered plan but different Git revisions, this hard-coded commit keeps the deterministic_identity hash, run_id, session_id, and attempt_id identical. Because the payload already has manifest commit metadata before wrapping, the envelope should use that value instead of 0000000/unknown; otherwise benchmark provenance cannot distinguish results from different revisions.

Useful? React with 👍 / 👎.

digest = _digest(identity)
run_id = f"run_{digest}"
session_id = f"ses_{_digest({'run_id': run_id, 'session': 'default'})}"
attempt_id = f"att_{_digest({'run_id': run_id, 'attempt': 0})}"
causality = {"tenant_id": "phenotype", "session_id": session_id, "run_id": run_id, "attempt_id": attempt_id}
now = datetime.now(UTC).isoformat()
checkpoint_id = f"cp_{_digest({'run_id': run_id, 'checkpoint': 0})[:16]}"
events = []
for seq, event_type in enumerate(("run_started", "checkpoint", "compaction", "run_finished")):
event = {"event_id": f"evt_{_digest({'run_id': run_id, 'seq': seq, 'type': event_type})}", "seq": seq, "ts": now, "type": event_type, "payload_sha256": _digest({"type": event_type, "seq": seq}), "causality": causality}
if event_type in ("checkpoint", "compaction"):
event["checkpoint_id"] = checkpoint_id
if event_type == "compaction":
event["details"] = {"tokens_before": 0, "tokens_after": 0, "retained_event_ids": [], "dropped_event_ids": []}
events.append(event)
passed = payload.get("result_code") == "PASS"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: This maps every non-PASS result to failed, so WARN runs are incorrectly classified as failures. Add an explicit mapping for warning states so non-failing runs are not reported with failure semantics. [logic error]

Severity Level: Major ⚠️
- ❌ Dry-run benchmark envelopes misreport WARN states as failures.
- ⚠️ Downstream analytics treat advisory runs as failed executions.
Steps of Reproduction ✅
1. Run the harness CLI in dry-run mode via the `helios-harness` script defined in
`/workspace/helios-cli/harness/pyproject.toml:3-4`, which ultimately executes
`run_runner()` in `/workspace/helios-cli/harness/scripts/run-harness.py:24-29` with
`args.dry_run` set to `True` (as in the test `test_run_runner_emits_benchmark_envelope` at
`/workspace/helios-cli/harness/tests/test_benchmark_envelope_direct.py:8-16`).

2. In the dry-run branch at `/workspace/helios-cli/harness/scripts/run-harness.py:24-26`,
the code sets `result["result_code"] = "WARN" if not commands else "PASS"` for empty
command plans, then imports `add_envelope` and calls `result = add_envelope(result,
repo=repo, profile=profile, plan_hash=command_hash)`.

3. Inside `add_envelope()` at
`/workspace/helios-cli/harness/src/harness/benchmark_envelope.py:32`, `passed` is computed
as `payload.get("result_code") == "PASS"`, so any non-`PASS` value, including the
intentional advisory `"WARN"` case from `_result_code()` in
`/workspace/helios-cli/harness/src/harness/schema.py:15-19`, is treated as not passed.

4. The envelope’s `result` block is built at
`/workspace/helios-cli/harness/src/harness/benchmark_envelope.py:42`, setting `"status":
"passed" if passed else "failed"` and `"failure_class": "none" if passed else "unknown"`.
For the dry-run WARN case described above, the outgoing envelope reports `"status":
"failed"` and `"failure_class": "unknown"` even though `_result_code()` and its tests in
`/workspace/helios-cli/harness/tests/test_schema.py:4-9` treat `"WARN"` as a non-failing,
advisory result, misclassifying warning-only benchmark runs as failures.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** harness/src/harness/benchmark_envelope.py
**Line:** 32:32
**Comment:**
	*Logic Error: This maps every non-`PASS` result to `failed`, so `WARN` runs are incorrectly classified as failures. Add an explicit mapping for warning states so non-failing runs are not reported with failure semantics.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

legacy_digest = _digest(payload)
return {

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 Badge Preserve legacy harness fields in the envelope

When run_runner writes the return value from add_envelope(), this replacement object drops the existing top-level result_code, plan_hash, plan/commands, runs, and quality fields. Existing consumers still read those fields, so run --dry-run now raises KeyError in test_harness_dry_run_and_plan_hash, replay from a newly generated artifact compares against an empty prior plan, and commands/execute-phase-2-harness.sh summarizes successful runs as WARN with zero commands. Merge the envelope with the legacy payload or keep the legacy fields at top level.

Useful? React with 👍 / 👎.

"schema_version": "1.0.0",
"tenant_id": "phenotype", "session_id": session_id, "run_id": run_id, "attempt_id": attempt_id,
"deterministic_identity": {"algorithm": "sha256(canonical-json(inputs))", "canonical_json_sha256": digest, "inputs": identity},
"subject": {"repo": repo, "commit": "unknown", "harness": "helios-harness", "runtime": "python", "model": "unknown", "hardware": "unknown"},
"lease": {"lease_id": f"lease_{attempt_id[4:20]}", "owner": "helios-harness", "ttl_seconds": 120, "heartbeat_interval_seconds": 20},
"task_manifest": {"task_id": f"plan:{plan_hash}", "input_sha256": plan_hash, "timeout_seconds": 1, "assertions": [{"id": "plan_discovered", "kind": "command_plan", "expected": True}], "judge": {"name": "helios-harness", "version": "0.1.0"}},
"events": events,
"result": {"status": "passed" if passed else "failed", "outcome_sha256": legacy_digest, "replay_hash": _digest(events), "failure_class": "none" if passed else "unknown", "artifacts": [{"kind": "report", "uri": f"urn:helios:legacy-evidence:{legacy_digest}", "sha256": legacy_digest}]},
"provenance": {"collector": "helios-harness", "collected_at": now, "source_hashes": {"plan": plan_hash}},
"signature": {"algorithm": "placeholder", "key_id": "unconfigured", "signature_b64": ""},
}
Comment on lines +34 to +45

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: This returns a brand-new envelope and drops the original payload fields, which breaks existing consumers that still read top-level legacy keys like result_code and plan_hash. Preserve the original payload (for example under a nested field or by merging required legacy keys) so downstream contracts do not regress. [api mismatch]

Severity Level: Major ⚠️
- ❌ Replay logic misreads prior runs lacking top-level plan.
- ⚠️ External tools expecting result_code/plan_hash break on envelope.
Steps of Reproduction ✅
1. Run the legacy harness runner via the CLI entrypoint defined in
`/workspace/helios-cli/harness/pyproject.toml:3-4` (`helios-harness =
"harness.scripts.run_harness:main"`), which calls `main()` in
`harness/src/harness/scripts/run_harness.py:20-22` and then `run_runner()` in
`harness/scripts/run-harness.py:150-52` for a normal run.

2. In `run_runner()` (see `/workspace/helios-cli/harness/scripts/run-harness.py:31-49`),
the code builds a legacy payload containing top-level keys such as `repo`, `profile`,
`plan_hash`, `plan`, `command_count`, and `reproducibility`, then at
`/workspace/helios-cli/harness/scripts/run-harness.py:49` imports `add_envelope` and calls
`payload = add_envelope(payload, repo=repo, profile=profile, plan_hash=command_hash)`.

3. Inspect `add_envelope()` in
`/workspace/helios-cli/harness/src/harness/benchmark_envelope.py:15-45`: at lines 34-45 it
returns a brand-new dictionary with only envelope fields (`schema_version`, `tenant_id`,
`subject`, `task_manifest`, `events`, `result`, `provenance`, `signature`) and does not
preserve the original top-level keys (`plan_hash`, `plan`, `result_code`,
`reproducibility`, etc.) from the incoming `payload`.

4. Later, when the same harness script is run with `--replay` pointing at a previously
produced run file, code at `/workspace/helios-cli/harness/scripts/run-harness.py:205-208`
expects legacy top-level keys: it reads `prior = json.loads(replay_path.read_text())`,
then accesses `prior.get("plan")`, `prior.get("commands", [])`, and
`prior.get("plan_hash")`. Because the new envelope structure returned from
`add_envelope()` at `benchmark_envelope.py:34-45` no longer exposes these keys at the top
level, `prior_plan` and `prior_hash` become empty/None, breaking replay/plan-diff behavior
and any other consumers that rely on legacy top-level fields.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** harness/src/harness/benchmark_envelope.py
**Line:** 34:45
**Comment:**
	*Api Mismatch: This returns a brand-new envelope and drops the original payload fields, which breaks existing consumers that still read top-level legacy keys like `result_code` and `plan_hash`. Preserve the original payload (for example under a nested field or by merging required legacy keys) so downstream contracts do not regress.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

18 changes: 12 additions & 6 deletions harness/src/harness/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,23 @@ class RepoManifest:

@classmethod
def from_repo(cls, repo_root: Path, repo_id: str) -> RepoManifest:
from subprocess import CalledProcessError, check_output
from subprocess import CalledProcessError, TimeoutExpired, check_output

def git_output(*args: str) -> str:
try:
return check_output(["git", "-C", root, *args], text=True, timeout=2).strip()
except (CalledProcessError, TimeoutExpired, FileNotFoundError):
return ""

root = str(repo_root.resolve())
try:
remote = check_output(["git", "-C", root, "remote", "get-url", "origin"], text=True).strip()
except CalledProcessError:
remote = git_output("remote", "get-url", "origin")
except (CalledProcessError, TimeoutExpired):
remote = "(no-remote)"
try:
branch = check_output(["git", "-C", root, "branch", "--show-current"], text=True).strip()
commit = check_output(["git", "-C", root, "rev-parse", "--short", "HEAD"], text=True).strip()
except CalledProcessError:
branch = git_output("branch", "--show-current")
commit = git_output("rev-parse", "--short", "HEAD")
Comment on lines +58 to +71

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: The helper swallows git exceptions and returns an empty string, so the surrounding fallback logic never triggers and sentinel values like (no-remote) / (no-git) are effectively dead code. Either let the helper raise, or move fallback assignment into the helper so failure states are represented consistently. [incorrect condition logic]

Severity Level: Major ⚠️
- ⚠️ Repo discovery records empty remote instead of no-remote sentinel.
- ⚠️ Git failure states encoded inconsistently in RepoManifest metadata.
Steps of Reproduction ✅
1. Invoke repository discovery using the harness API, e.g.
`Discoverer().discover(DiscoverInput(repo_root=<path>))`, where `Discoverer` is lazily
exported by `harness/src/harness/__init__.py:9-12` and its `discover()` method in
`/workspace/helios-cli/harness/src/harness/discoverer.py:9-12` calls
`RepoManifest.from_repo(root, root.name)`.

2. In `RepoManifest.from_repo()` at
`/workspace/helios-cli/harness/src/harness/interfaces.py:16-23`, `git_output()` is defined
to run `check_output(["git", "-C", root, *args], text=True, timeout=2)` and on any
`CalledProcessError`, `TimeoutExpired`, or `FileNotFoundError` it **swallows** the
exception and returns an empty string `""` instead.

3. The surrounding fallback logic at
`/workspace/helios-cli/harness/src/harness/interfaces.py:25-35` expects those git errors
to bubble up: it wraps `remote = git_output("remote", "get-url", "origin")` in a
`try:`/`except (CalledProcessError, TimeoutExpired)` to fall back to `remote =
"(no-remote)"`, and similarly wraps `branch = git_output("branch", "--show-current");
commit = git_output("rev-parse", "--short", "HEAD")` to fall back to sentinel values
`(no-git)` and empty commit on failure.

4. For a realistic non-git repository (or when `git` is missing), `check_output()` will
raise `CalledProcessError` or `FileNotFoundError`, but because `git_output()` at
interfaces.py:19-23 catches these and returns `""`, the outer `try` blocks never see an
exception, so `remote_url` is set to `""` and `branch`/`commit` become `""` instead of the
intended sentinel strings `(no-remote)` / `(no-git)`. This makes the fallback branches at
lines 28-35 effectively dead code and yields inconsistent failure metadata in the
`RepoManifest` returned to `Discoverer.discover()` at
`/workspace/helios-cli/harness/src/harness/discoverer.py:10-21`.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** harness/src/harness/interfaces.py
**Line:** 58:71
**Comment:**
	*Incorrect Condition Logic: The helper swallows git exceptions and returns an empty string, so the surrounding fallback logic never triggers and sentinel values like `(no-remote)` / `(no-git)` are effectively dead code. Either let the helper raise, or move fallback assignment into the helper so failure states are represented consistently.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

except (CalledProcessError, TimeoutExpired):
branch = "(no-git)"
commit = ""
default_branch = branch or "main"
Expand Down
1 change: 1 addition & 0 deletions harness/src/harness/scripts/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Importable harness command entrypoints."""
27 changes: 27 additions & 0 deletions harness/src/harness/scripts/run_harness.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""Importable wrapper for the repository's legacy hyphenated runner script."""

from __future__ import annotations

import importlib.util
from pathlib import Path
from types import ModuleType


def _legacy_module() -> ModuleType:
script = Path(__file__).resolve().parents[3] / "scripts" / "run-harness.py"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Package the runner code with the console entrypoint

In a non-editable wheel install, harness/pyproject.toml packages only src/harness, but this wrapper resolves scripts/run-harness.py outside that package. The helios-harness console script can import harness.scripts.run_harness, then fails with FileNotFoundError when main() or run_runner() tries to load the uninstalled legacy script; moving the runner implementation into the package or including the legacy script in the wheel avoids shipping a broken entrypoint.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: This wrapper hard-codes a filesystem jump to a top-level script that is not included in the wheel build (packages = ["src/harness"]), so the installed CLI entrypoint can fail at runtime with a missing file. Load the runner from package code (or include the legacy script in the package data) instead of traversing outside the installed package tree. [api mismatch]

Severity Level: Critical 🚨
- ❌ Installed helios-harness CLI fails with ImportError on start.
- ⚠️ Packaging excludes legacy runner required by entrypoint wrapper.
Steps of Reproduction ✅
1. Build and install the harness wheel using the configuration in
`/workspace/helios-cli/harness/pyproject.toml:1-8`, which declares the script entrypoint
`helios-harness = "harness.scripts.run_harness:main"` and limits wheel contents to
`packages = ["src/harness"]`, excluding the top-level `harness/scripts` directory.

2. After installation, execute the CLI entrypoint `helios-harness`, which calls `main()`
in `/workspace/helios-cli/harness/src/harness/scripts/run_harness.py:20-22`. `main()`
immediately calls `_legacy_module()` defined at lines 10-17 in the same file.

3. `_legacy_module()` computes `script = Path(__file__).resolve().parents[3] / "scripts" /
"run-harness.py"` at
`/workspace/helios-cli/harness/src/harness/scripts/run_harness.py:11`, expecting to find
`harness/scripts/run-harness.py` three levels above the installed module path.

4. In the installed wheel, only `src/harness` is packaged, so the sibling
`scripts/run-harness.py` file does not exist at runtime.
`importlib.util.spec_from_file_location` at run_harness.py:12 either returns a spec with
`loader is None` or fails due to the missing file; `_legacy_module()` then raises
`ImportError(f"Unable to load harness runner: {script}")` at line 13-14, causing the
`helios-harness` CLI entrypoint to fail on startup in installed environments.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** harness/src/harness/scripts/run_harness.py
**Line:** 11:11
**Comment:**
	*Api Mismatch: This wrapper hard-codes a filesystem jump to a top-level script that is not included in the wheel build (`packages = ["src/harness"]`), so the installed CLI entrypoint can fail at runtime with a missing file. Load the runner from package code (or include the legacy script in the package data) instead of traversing outside the installed package tree.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

spec = importlib.util.spec_from_file_location("helios_harness_legacy_runner", script)
if spec is None or spec.loader is None:
raise ImportError(f"Unable to load harness runner: {script}")
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module


def main() -> None:
"""Run the canonical harness CLI."""
_legacy_module().main()


def run_runner(repo: str, profile: str, out: str, args) -> None:
"""Expose the runner seam for integration tests and adapters."""
_legacy_module().run_runner(repo, profile, out, args)
39 changes: 39 additions & 0 deletions harness/tests/test_benchmark_envelope_direct.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import json
import tempfile
from types import SimpleNamespace

from harness.scripts.run_harness import run_runner


def test_run_runner_emits_benchmark_envelope(tmp_path):
repo = tmp_path / "repo"
repo.mkdir()
(repo / "Makefile").write_text("check:\n\t@echo check\n")
out = tmp_path / "run.json"
run_runner(str(repo), "strict-full", str(out), SimpleNamespace(
replay=None, dry_run=True, max_parallel=2, timeout=2, retries=0,
retry_delay=1.0, budget=None, continue_on_fail=False,
))
payload = json.loads(out.read_text())
try:
import jsonschema
from pathlib import Path
schema_path = Path(__file__).parents[3] / "docs/sessions/20260722-agent-harness-portfolio/artifacts/benchmark_run.schema.json"
jsonschema.Draft202012Validator(json.loads(schema_path.read_text())).validate(payload)
except ModuleNotFoundError:
Comment on lines +21 to +23

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: This test only ignores missing jsonschema, but not a missing schema file; when jsonschema is installed and that docs path does not exist, the test fails with FileNotFoundError. Guard the schema read with an existence check (or also catch file-not-found) to avoid environment-dependent failures. [possible bug]

Severity Level: Major ⚠️
- ⚠️ Test suite may error when schema file is absent.
- ⚠️ CI reliability depends on non-packaged docs presence.
Steps of Reproduction ✅
1. Run the harness test suite (e.g. `pytest`) so that
`test_run_runner_emits_benchmark_envelope` in
`/workspace/helios-cli/harness/tests/test_benchmark_envelope_direct.py:8-32` is executed;
this test drives `run_runner()` via the wrapper in
`harness/src/harness/scripts/run_harness.py:25-27` to produce a benchmark envelope
payload.

2. After reading the output JSON into `payload` at
`/workspace/helios-cli/harness/tests/test_benchmark_envelope_direct.py:17`, the test
enters a `try` block at lines 19-23 that imports `jsonschema` and constructs `schema_path
= Path(__file__).parents[3] /
"docs/sessions/20260722-agent-harness-portfolio/artifacts/benchmark_run.schema.json"`.

3. In an environment where the `jsonschema` package is installed but the
`docs/sessions/20260722-agent-harness-portfolio/artifacts/benchmark_run.schema.json` file
is not present (for example, when running tests against an installed wheel that only
packages `src/harness` as per `/workspace/helios-cli/harness/pyproject.toml:6-7`),
`schema_path.read_text()` at test_benchmark_envelope_direct.py:21-22 raises
`FileNotFoundError`.

4. The `except` block at
`/workspace/helios-cli/harness/tests/test_benchmark_envelope_direct.py:23-24` only catches
`ModuleNotFoundError`, so `FileNotFoundError` propagates, causing the test to error out
instead of being skipped when the external schema file is missing, leading to
environment-dependent test failures.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** harness/tests/test_benchmark_envelope_direct.py
**Line:** 21:23
**Comment:**
	*Possible Bug: This test only ignores missing `jsonschema`, but not a missing schema file; when `jsonschema` is installed and that docs path does not exist, the test fails with `FileNotFoundError`. Guard the schema read with an existence check (or also catch file-not-found) to avoid environment-dependent failures.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

pass
assert payload["tenant_id"] == "phenotype"
assert payload["session_id"].startswith("ses_")
assert payload["run_id"].startswith("run_")
assert payload["attempt_id"].startswith("att_")
assert payload["subject"]["harness"] == "helios-harness"
assert payload["provenance"]["collector"] == "helios-harness"
assert payload["signature"]["algorithm"] == "placeholder"
assert {event["type"] for event in payload["events"]} >= {"checkpoint", "compaction"}


if __name__ == "__main__":
with tempfile.TemporaryDirectory() as directory:
from pathlib import Path
test_run_runner_emits_benchmark_envelope(Path(directory))
print("direct_envelope_test_pass")
7 changes: 7 additions & 0 deletions harness/tests/test_entrypoint_import.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from importlib import import_module


def test_harness_entrypoint_is_importable():
module = import_module("harness.scripts.run_harness")
assert callable(module.main)
assert callable(module.run_runner)
Loading