Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 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
4 changes: 2 additions & 2 deletions .github/workflows/trunk-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ jobs:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Trunk Check
uses: trunk-io/trunk-action@d90b9166660d5e5afae248a58172a3a0e99d56d5 # v1.0.4
uses: trunk-io/trunk-action@04ba50e7658c81db7356da96657e6e77f220bfa3 # v1.3.1

- name: Trunk Upgrade (on schedule only)
if: github.event_name == 'schedule'
uses: trunk-io/trunk-action@d90b9166660d5e5afae248a58172a3a0e99d56d5 # v1.0.4
uses: trunk-io/trunk-action@04ba50e7658c81db7356da96657e6e77f220bfa3 # v1.3.1
with:
trunk-args: --upgrade
15 changes: 4 additions & 11 deletions crates/harness_runner/src/dual_harness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@ async fn run_one_helios_task(task: &FixtureTask) -> Result<TaskOutcome, FixtureE
config.timeout_secs = Some(secs);
}
if let Some(env_key) = &adapter.working_dir_env {
let dir = std::env::var(env_key).map_err(|_| FixtureError::WorkdirUnset(task.task_id.clone()))?;
let dir =
std::env::var(env_key).map_err(|_| FixtureError::WorkdirUnset(task.task_id.clone()))?;
config.working_dir = Some(dir);
}

Expand All @@ -129,11 +130,7 @@ async fn run_one_helios_task(task: &FixtureTask) -> Result<TaskOutcome, FixtureE

let passed = match (&task.acceptance, result) {
(
Acceptance {
must_error: Some(true),
error_class: Some(class),
..
},
Acceptance { must_error: Some(true), error_class: Some(class), .. },
Err(RunError::Timeout(_)),
) if class == "timeout" => true,
(acceptance, Ok(run)) => {
Expand Down Expand Up @@ -172,11 +169,7 @@ async fn run_one_helios_task(task: &FixtureTask) -> Result<TaskOutcome, FixtureE
Ok(TaskOutcome {
task_id: task.task_id.clone(),
passed,
detail: if passed {
"ok".into()
} else {
"acceptance failed".into()
},
detail: if passed { "ok".into() } else { "acceptance failed".into() },
})
}

Expand Down
9 changes: 9 additions & 0 deletions harness/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
# Helios Harness Benchmarks

from pathlib import Path


# Keep the legacy benchmark package importable from the repository root while
# exposing the installable ``src/harness`` package to in-repo entrypoint users.
_SOURCE_PACKAGE = Path(__file__).resolve().parent / "src" / "harness"
if _SOURCE_PACKAGE.is_dir() and str(_SOURCE_PACKAGE) not in __path__:
__path__.append(str(_SOURCE_PACKAGE))
5 changes: 4 additions & 1 deletion harness/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ name = "helios-harness"
version = "0.1.0"
description = "Reusable CLI/API/SDK quality harness for phase-2 evidence generation"
requires-python = ">=3.12"
dependencies = []
dependencies = [
"fastjsonschema>=2.21,<3",
"jsonschema>=4.23,<5",
]

[build-system]
requires = ["hatchling"]
Expand Down
204 changes: 77 additions & 127 deletions harness/scripts/run-harness.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,33 @@
}


def _subject_ref(discovery) -> str:
"""Return a stable ref for a Git checkout, including detached HEADs."""
if discovery.manifest.branch:
return discovery.manifest.branch
if discovery.manifest.commit:
return f"detached:{discovery.manifest.commit}"
return ""


def _write_unresolved_provenance(payload: dict, out: str, repo: str, subject_ref: str) -> None:
"""Emit an explicit warning instead of fabricating an envelope for non-Git input."""
payload["result_code"] = "WARN"
payload["provenance"] = {
"status": "unresolved",
"reason": "non_git_repository",
"collector": "helios-harness",
"source_ref": subject_ref or None,
"source_sha": None,
"repo": repo,
}
payload["result"] = {
"status": "warning",
"failure_class": "provenance_unresolved",
}
Path(out).write_text(json.dumps(payload, indent=2))

Check failure on line 115 in harness/scripts/run-harness.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

LLMs running this code with faulty CLI arguments can escape file system restrictions. Refactor this code to validate the constructed path before accessing the file system.

See more on https://sonarcloud.io/project/issues?id=KooshaPari_helios-cli&issues=AZ-7ZIcB-CkDYWncq5K6&open=AZ-7ZIcB-CkDYWncq5K6&pullRequest=616


def run_discovery(root: str, out: str, max_scan_depth: int) -> None:
from harness.discoverer import Discoverer
from harness.interfaces import DiscoverInput
Expand Down Expand Up @@ -162,8 +189,20 @@
"plan": commands,
"command_count": len(commands),
"reproducibility": _reproducibility_metadata(profile, args),
"fixture": {

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 Split run-harness back under the file limit

This added fixture/envelope assembly pushes harness/scripts/run-harness.py from exactly 500 lines to 528 lines, exceeding the repository's hard 500-line source-file limit; moving this assembly into a helper/module would keep the runner reviewable and within the documented constraint.

AGENTS.md reference: AGENTS.md:L66-L72

Useful? React with 👍 / 👎.

"kind": "discovered-repository",
"repo": repo,
"ref": _subject_ref(discovery) or None,
"commit": discovery.manifest.commit,
"plan_sha256": command_hash,
},
}

subject_ref = _subject_ref(discovery)
if not discovery.manifest.commit or not subject_ref:
_write_unresolved_provenance(result, out, repo, subject_ref)
return

if replay_payload is not None:
result["replay"] = {
**replay_payload,
Expand All @@ -173,7 +212,14 @@
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)
result = add_envelope(
result,
repo=repo,
profile=profile,
plan_hash=command_hash,
subject_commit=discovery.manifest.commit or "",
subject_ref=subject_ref,
)
Path(out).write_text(json.dumps(result, indent=2))
return

Expand All @@ -195,9 +241,13 @@
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)

payload["fixture"] = {
"kind": "discovered-repository",
"repo": repo,
"ref": subject_ref or None,
"commit": discovery.manifest.commit,
"plan_sha256": command_hash,
}
if args.replay:
replay_path = Path(args.replay)
if replay_payload is None and replay_path.exists():
Expand Down Expand Up @@ -242,6 +292,20 @@
"plan_diff": plan_diff,
}

if not discovery.manifest.commit or not subject_ref:
_write_unresolved_provenance(payload, out, repo, subject_ref)
return

from harness.benchmark_envelope import add_envelope
payload = add_envelope(
payload,
repo=repo,
profile=profile,
plan_hash=command_hash,
subject_commit=discovery.manifest.commit or "",

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 Keep phase-2 harness runs working for non-Git clones

When execute-phase-2-harness.sh iterates clones/*, those directories are not guaranteed to be Git repositories; the existing smoke test creates clones/toyrepo that way. With this new argument, discovery.manifest.commit is empty, add_envelope raises before writing *-run.json, the phase-2 script swallows the non-zero exit, and the run is reported as MISSING instead of PASS; if a resolved Git identity is mandatory, the phase-2 path needs to initialize, skip, or handle non-Git targets before invoking the envelope.

Useful? React with 👍 / 👎.

subject_ref=subject_ref,
)

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


Expand Down Expand Up @@ -287,130 +351,16 @@
print("VALID")


# =============================================================================
# Teammates CLI
# =============================================================================


def cmd_teammates_list(agents_dir: str) -> None:
from harness import TeammateRegistry

registry = TeammateRegistry(agents_dir=Path(agents_dir))
teammates = registry.discover()

if not teammates:
print("No teammates found")
return

print(f"Found {len(teammates)} teammates:\n")
for t in teammates.values():
print(f" {t.id}: {t.name} ({t.role})")
print(f" {t.description[:60]}...")


def cmd_teammates_delegate(teammate_id: str, task: str, timeout: int, profile: str) -> None:
import asyncio

from harness import CodexExecutor, DelegationProtocol, DelegationRequest, Priority, TeammateRegistry

async def run():
registry = TeammateRegistry()
registry.discover()

teammate = registry.get(teammate_id)
if not teammate:
print(f"Teammate not found: {teammate_id}")
return

protocol = DelegationProtocol()
executor = CodexExecutor(profile=profile)

request = DelegationRequest(
teammate_id=teammate_id, task_description=task, priority=Priority.NORMAL, timeout_seconds=timeout
)

result = await protocol.delegate(request, executor)

print(f"Delegation: {result.delegation_id}")
print(f"Status: {result.status}")
print(f"Duration: {result.duration_ms}ms")
if result.result:
print(f"Result: {result.result[:200]}...")
if result.error:
print(f"Error: {result.error}")

asyncio.run(run())


def cmd_teammates_status(delegation_id: str) -> None:
from harness import DelegationProtocol

protocol = DelegationProtocol()
result = protocol.get_status(delegation_id)

if result:
print(f"Delegation: {result.delegation_id}")
print(f"Status: {result.status}")
print(f"Duration: {result.duration_ms}ms")
else:
print(f"Delegation not found: {delegation_id}")


# =============================================================================
# Scaling CLI
# =============================================================================


def cmd_scaling_status() -> None:
from harness import DynamicLimitController, ResourceSampler

sampler = ResourceSampler()
controller = DynamicLimitController()

snapshot = sampler.sample()

print("Resource Status:")
print(f" CPU: {snapshot.cpu_percent:.1f}%")
print(f" Memory: {snapshot.memory_percent:.1f}% ({snapshot.memory_available_mb:.0f}MB available)")
print(f" FDs: {snapshot.fd_count}/{snapshot.fd_limit}")
print(f" Load: {snapshot.load_avg:.2f}")
print(f"\nDynamic Limit: {controller.current_limit}")
print(f"State: {controller._state}")


# =============================================================================
# Cache CLI
# =============================================================================


def cmd_cache_stats() -> None:
from harness import L1Cache

cache = L1Cache()
stats = cache.stats

print("L1 Cache Stats:")
print(f" Hits: {stats.hits}")
print(f" Misses: {stats.misses}")
print(f" Hit Rate: {stats.hit_rate:.1%}")


def cmd_cache_clear() -> None:
from harness import L1Cache, L2Cache

l1 = L1Cache()
l2 = L2Cache()

# Clear L1 (recreate)
l1._cache.clear()
print("L1 cache cleared")

# Clear L2
l2.clear()
print("L2 cache cleared")


def main() -> None:
from harness.commands import (
cmd_cache_clear,
cmd_cache_stats,
cmd_scaling_status,
cmd_teammates_delegate,
cmd_teammates_list,
cmd_teammates_status,
)

p = argparse.ArgumentParser()
sp = p.add_subparsers(dest="cmd", required=True)

Expand Down
Loading
Loading