Skip to content

fix(proof): attach miner harbor agent on evaluate - #266

Merged
echobt merged 1 commit into
mainfrom
cursor/harbor-evaluate-artefact-d8ea
Sep 10, 2026
Merged

echobt merged 1 commit into
mainfrom
cursor/harbor-evaluate-artefact-d8ea

Conversation

@echobt

@echobt echobt commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Live tbench Harbor evaluate on prod metal ignored the miner artefact and the miner BYOK file:

  1. harbor run … -a terminus-2 always used the operator pack agent. $PROOF_ARTIFACT_DIR was never read.
  2. Inference always loaded the owner key from PROOF_SECRETS_DIR/$PROOF_PARAM_INFERENCE_KEY_FILE, violating miner_byok_openrouter.

Inspect already walked the artefact. Evaluate did not. This PR ships a versioned reference adaptor operators can bake/deploy so miner code actually affects scoring.

Harbor -a / --agent (verified against Harbor CLI + AgentFactory) accepts a built-in name or a Python import path module.path:ClassNamenot a filesystem path. Evaluate therefore:

  • prefers $PROOF_ARTIFACT_DIR/agent, else $PROOF_ARTIFACT_DIR/recipe/agent
  • puts the parent on PYTHONPATH and passes -a module:Class (AST resolve; optional one-line import_path file)
  • fails closed on recipe/run.sh without an agent dir (classic marker is not a Harbor -a target)
  • never falls back to topic PROOF_PARAM_HARBOR_AGENT (terminus-2) on evaluate when an artefact was staged
  • topic agent is only for baseline with PROOF_ARTIFACT_DIR unset

BYOK: evaluate exports $PROOF_MINER_ENV_DIR/$PROOF_PARAM_MINER_BYOK and refuses the owner key. Owner key remains for baseline when miner_byok is unset / no miner file is staged.

report.json is the mean of Harbor trial verifier_result.rewards.reward only. A trial with no such field is not a measurement.

Greptile P1s (follow-up on this branch)

Fail-closed scoring / integrity fixes for the T-Rex-verified P1s (commit fix(proof): fail closed on incomplete harbor evaluate):

  1. Partial failures are scored — nonzero Harbor exit does not write report.json; summarize.py also refuses harbor_exit != 0.
  2. Trial cap changes scores — every measured trial is scored; only serialized evidence is capped at 256.
  3. Incomplete scans pass — file/byte-limit truncation marks the scan incomplete and fails off-limits rules.
  4. Import path escapes artifactmodule:Class is resolved in the evaluate import env (artefact parent only) and rejected when the origin is outside the staged artefact.
  5. Unknown rules pass — unsupported rule IDs fail closed even when an artefact directory exists.

Owner semantics unchanged: Harbor -a is an import path; evaluate FAIL CLOSED without an agent at $PROOF_ARTIFACT_DIR/agent or …/recipe/agent; miner BYOK required (no owner-key fallback); terminus-2 only for baseline with no miner artefact.

How operators bake / deploy

Preferred (guest image):

deploy/guest/bake-rootfs.sh \
  --guest-agent target/x86_64-unknown-linux-musl/release/proof-vm-guest-agent \
  --runner rlm_fc_in_guest_harbor=deploy/guest/runners/rlm_fc_in_guest_harbor \
  --overlay /path/outside/git/harbor-venv-overlay \
  --chroot-hook /path/outside/git/install-harbor.sh \
  --resolver <allowlisted resolver> \
  --out-dir ./out

--runner copies this tree to /opt/proof/runners/rlm_fc_in_guest_harbor/. run execs the in-tree harness/run-harbor. Do not keep the old overlay /opt/proof/harness/run-harbor as the evaluate path — that is the bug.

Metal copy (then re-bake/remount so the guest actually contains it):

install -d -m 0755 /var/lib/proof/runners/rlm_fc_in_guest_harbor
cp -a deploy/guest/runners/rlm_fc_in_guest_harbor/. \
  /var/lib/proof/runners/rlm_fc_in_guest_harbor/
chmod 0755 /var/lib/proof/runners/rlm_fc_in_guest_harbor/run \
  /var/lib/proof/runners/rlm_fc_in_guest_harbor/inspect \
  /var/lib/proof/runners/rlm_fc_in_guest_harbor/harness/run-harbor

Harbor CLI/venv and the task pack stay operator overlays. Topic baseline_runner must be rlm_fc_in_guest_harbor.

Miner attach layout: docs/external-miner/proof-tbench.md and deploy/guest/runners/rlm_fc_in_guest_harbor/README.md.

Test plan

  • deploy/guest/runners/rlm_fc_in_guest_harbor/tests/run.sh (no Harbor, no podman): agent selection, evaluate refuses terminus-2 / recipe/run.sh fallback, BYOK evaluate vs owner key, summarize mean / fail-closed / redact, inspect off-limits markers
  • P1 regressions: nonzero Harbor exit, 260-trial mean vs evidence cap, truncated off-limits scan, unknown rule id, escaped import_path
  • cargo run -p xtask -- external-docs-check
  • cargo fmt --all -- --check (CI)
  • Clippy / deny / remaining xtask gates on CI

Greptile

  • P1s addressed on this branch; @greptileai posted after the push
  • Greptile has re-reviewed this PR; remaining findings are fixed or answered

Risk

Operators must re-bake or replace the live overlay/adaptor for this to affect scoring. Shipping the tree in git does not change prod until the guest image (or /opt/proof/runners/rlm_fc_in_guest_harbor) is updated. No BASE_* env, deployed path, or crypto domain tag changes.

Naming

I did not rename BASE_* environment variables, deployed host paths
(/opt/base, /run/base, …), GHCR baseintelligence/base package names, or
base-*-v1 cryptographic domain tags.

Open in Web Open in Cursor 

Live Harbor evaluate ignored PROOF_ARTIFACT_DIR and the miner BYOK
file, always running terminus-2 on the operator pack with the owner
key. Ship a versioned rlm_fc_in_guest_harbor adaptor that resolves a
Harbor module:Class from the artefact (Harbor -a is not a path),
refuses topic-agent fallback on evaluate, and never falls back to the
owner key when miner_byok is set.

Co-authored-by: Mathis <echobt@users.noreply.github.com>
@cursor

cursor Bot commented Sep 10, 2026

Copy link
Copy Markdown

@greptileai review

@greptile-apps

greptile-apps Bot commented Sep 10, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds a versioned in-guest Harbor adaptor for Proof evaluation, including miner-provided agent selection, BYOK credential handling, result summarization, artifact inspection, deployment documentation, and adaptor tests. No code has changed since the previous review, and the previously identified blocking evaluation-integrity issues remain unresolved.

Confidence Score: 0/5

Not merge-safe: unresolved evaluation-integrity and artifact-isolation issues can affect paid Proof results.

Five outstanding previous findings remain unresolved. A nonzero Harbor exit is still suppressed before a report is written, allowing partial results to be treated as a successful evaluation. Result collection still stops after 256 measured trials, so the reported score can omit completed results. Artifact scanning still stops at its file limit and treats the scanned subset as clean, which can produce false-green prohibited-content evidence. Miner-controlled import paths are still accepted without confirming that the imported module originates within the staged artifact. Unsupported rule IDs still pass when an artifact directory exists rather than being evaluated. The bounded scan and external import-path issues are unresolved security findings.

Reviews (2): Last reviewed commit: "fix(proof): attach miner harbor agent on..." | Re-trigger Greptile

Comment on lines +60 to +65
set +e
"${harbor_cmd[@]}" >"$log" 2>&1
harbor_exit=$?
set -e

python3 "$HERE/summarize.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.

P1 Partial failures are scored

When Harbor writes some trial results and then exits unsuccessfully, this runner suppresses that failure and still writes a successful report. A run that wrote one result before exiting with status 23 produced primary_value: 0.6 and claim_holds: true; the guest runner accepts that finite report and forwards its claim status. This can publish and pay a score derived from an incomplete evaluation. Reject nonzero Harbor exits, or require verified completion of the expected trial set before producing a passing report.

Knowledge Base Used: Proof challenge network and evaluation

Artifacts

Partial Harbor validation script

  • This authored executable creates an empty-result control and a fake Harbor that writes one reward before exiting 23, then runs the real harness and asserts the resulting report, showing the tested failure condition.

No-results control output

  • The control invocation of the real summarizer exited 2 and refused to create report.json when no measured results existed, establishing the baseline rejection behavior.

Partial-results failure output

  • The real harness returned exit code 0 after fake Harbor exited 23, and its emitted report contains primary_value 0.6 and claim_holds true, confirming partial output is accepted.

Downstream report contract output

  • The focused proof-vm-guest contract test passed, corroborating that a finite report and claim_holds field are accepted and forwarded downstream.

View artifacts

T-Rex Ran code and verified through T-Rex

Comment on lines +66 to +68
for result_path in sorted(jobs_dir.rglob("result.json")):
if len(trials) >= MAX_EVIDENCE_TRIALS:
break

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 Trial cap changes scores

The summarizer stops after the first 256 lexically sorted result files, then calculates both primary_value and n_measured from that subset while still setting claim_holds to true. With 260 valid results, the four lexically later rewards of 100 were omitted: the report scored 0.0, while all 260 results average 1.5384615384615385. This makes the authoritative score depend on file ordering rather than all completed trials. Score every measured result and bound only serialized evidence, or fail closed when collection is incomplete.

Knowledge Base Used: Proof challenge network and evaluation

Artifacts

Result-cap reproduction script

  • Authored Python harness creates exact-cap and 260-file Harbor-shaped job trees and invokes the real summarizer, demonstrating whether all measured files affect the report; it proves the test scope.

256-result baseline output

  • Executed baseline command in `/home/user/repo` with 256 measured results, showing all 256 are reported and score to zero; it establishes the cap boundary.

260-result overflow output

  • Executed overflow command in `/home/user/repo` with 260 measured results, showing only the first 256 are reported, the score remains zero, and `claim_holds` remains true; it confirms silent lexicographic truncation.

View artifacts

T-Rex Ran code and verified through T-Rex

Comment on lines +88 to +91
names.append(rel)
n_files += 1
if n_files > MAX_FILES or total > MAX_TOTAL_BYTES:
break

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 security Incomplete scans pass

The scanner stops reading after its file limit but treats the absence of a marker from the truncated text as proof that the off-limits rule passes. An artifact containing 256 lexically earlier benign files and a later z-forbidden.txt containing no_tb4_hardcoding completed successfully with that rule marked passing. This can create false-green integrity evidence at the paid evaluation boundary and allow prohibited hardcoding to be evaluated or promoted. Mark bounded scans as incomplete and fail the relevant rule rather than treating them as clean.

How this was verified: A 257-file artifact with the forbidden marker after the file limit emitted a passing off-limits checklist entry.

Knowledge Base Used: Proof challenge network and evaluation

Artifacts

Scan-limit reproduction script

  • Authored and executed Python reproduction that builds the same-size baseline and lexically later forbidden-marker cases, invokes the real scanner, and prints its emitted checklist state; it confirms the tested path.

Clean scan baseline output

  • Captured output of `python3 trex-artifacts/inspect-scan-limit-repro.py baseline` from `/home/user/repo`, including command, working directory, exit code, and emitted passing checklist for the clean baseline; it establishes expected clean behavior.

Marker after scan limit output

  • Captured output of `python3 trex-artifacts/inspect-scan-limit-repro.py marker` from `/home/user/repo`, including command, working directory, exit code, and emitted passing checklist despite `z-forbidden.txt` containing `no_tb4_hardcoding`; it confirms the bypass.

View artifacts

T-Rex Ran code and verified through T-Rex

Comment on lines +44 to +51
if ":" not in line or line.startswith("acp:"):
_fail(
f"{path} must name a Python import path module.path:ClassName; "
f"got {line!r} (a built-in Harbor name is not miner code)"
)
if ".." in line or "/" in line or "\\" in line:
_fail(f"{path} is not a Python import path: {line!r}")
return line

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 security Import path escapes artifact

If the Harbor environment exposes a matching external Python module, a miner-controlled import_path can select it instead of code staged in the artifact. The resolver accepts module:Class based only on syntax and passes it to Harbor without resolving or checking the module origin. In the evaluation flow, outside_agent:ExternalAgent was accepted and Harbor imported /tmp/.../external/outside_agent.py, outside the staged artifact. This permits scoring code that was not supplied by the miner artifact while it is treated as the selected agent. Resolve the module in the evaluation import environment and reject any origin outside the resolved artifact directory.

How this was verified: An artifact-controlled import path selected a module whose loaded Python file was outside the staged artifact.

Knowledge Base Used: Proof challenge network and evaluation

Artifacts

External import-path validation script

  • This authored script creates a staged artifact whose import_path names a module supplied only outside the artifact, runs resolver-only and Harbor-flow modes, and asserts the imported origin is external; it is the reproducible proof harness.

Resolver external-path output

  • This executed resolver capture shows the artifact import_path `outside_agent:ExternalAgent` was returned with exit code 0 before any Harbor invocation; the resolver does not enforce module-origin containment.

External module execution output

  • This executed fake-Harbor capture shows the adapter passed `outside_agent:ExternalAgent` to Harbor and Harbor imported `/tmp/.../external/outside_agent.py` outside the staged artifact; containment was not enforced before invocation.

Harbor adaptor regression output

  • This executed repository adapter suite completed successfully after the focused validation artifacts were added; the existing tests pass but do not cover external module-origin containment.

View artifacts

T-Rex Ran code and verified through T-Rex

Comment on lines +195 to +202
return {
"id": rid,
"pass": True,
"evidence": _clip(
f"rule {rid}: artefact present ({n_files} files); no paid inference; "
"no off-limits short-circuit/tb4 markers beyond the dedicated probes"
),
}

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 Unknown rules pass

Any substantive rule not explicitly handled by the scanner passes whenever an artifact directory exists, without evaluating the rule ID, its text, or supporting evidence. The unknown requirement must_provide_reproducible_benchmark changed from failing with no artifact directory to passing after adding one unrelated non-proving file. A newly introduced artifact requirement can therefore generate green checklist evidence without being checked, allowing evaluation to proceed without satisfying that requirement. Fail closed for unsupported rule IDs until a rule-specific evaluator is implemented.

Knowledge Base Used: Proof challenge network and evaluation

Artifacts

Unsupported-rule reproduction script

  • Runs inspect_scan.py with the same unknown benchmark rule before and after staging an artifact directory, capturing the checklist output; it reproduces the unsupported-rule fallback.

No-artifact unknown-rule output

  • Executed `trex-artifacts/unsupported-artifact-rule-repro.sh before` in `/home/user/repo` with exit code 0; the unknown rule is marked `pass: false` because no artifact tree was staged.

Artifact-present unknown-rule output

  • Executed `trex-artifacts/unsupported-artifact-rule-repro.sh after` in `/home/user/repo` with exit code 0; the same unknown substantive rule is marked `pass: true` merely because one artifact file exists.

View artifacts

T-Rex Ran code and verified through T-Rex

@echobt
echobt merged commit 41b51ac into main Sep 10, 2026
5 checks passed
@cursor

cursor Bot commented Sep 10, 2026

Copy link
Copy Markdown

@greptileai

cursor Bot pushed a commit that referenced this pull request Sep 10, 2026
images.yml GH013 on main after #266. previous is the complete a8b9018 set.

Co-authored-by: Mathis <echobt@users.noreply.github.com>
@cursor

cursor Bot commented Sep 10, 2026

Copy link
Copy Markdown

@greptileai

#266 was squash-merged at 41b51ac before the P1 fail-closed commit. Fixes are on follow-up #267 (cursor/harbor-evaluate-p1-fail-closed-750d).

@greptile-apps

greptile-apps Bot commented Sep 10, 2026

Copy link
Copy Markdown

Understood. PR #266 was squash-merged at 41b51ac before the fail-closed fixes landed. I’ll treat PR #267 (cursor/harbor-evaluate-p1-fail-closed-750d) as the follow-up containing those fixes.

echobt added a commit that referenced this pull request Sep 11, 2026
images.yml GH013 on main after #266. previous is the complete a8b9018 set.

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Mathis <echobt@users.noreply.github.com>
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.

2 participants