Skip to content

(MOT-4299) fix(ci): run daily Harness benchmarks against Registry - #735

Merged
ytallo merged 1 commit into
mainfrom
feat/daily-registry-benchmark
Aug 7, 2026
Merged

(MOT-4299) fix(ci): run daily Harness benchmarks against Registry#735
ytallo merged 1 commit into
mainfrom
feat/daily-registry-benchmark

Conversation

@ytallo

@ytallo ytallo commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

The daily Harness benchmark now measures the currently published Registry stack instead of rebuilding every worker from source. Main keeps the source build and LLVM coverage for checkout regressions, while daily records the exact live stack identity and preserves Registry failures as infrastructure failures.\n\n## Technical details\n\n- Resolve harness@latest and the live support/provider stack through Registry, then validate every iii.lock worker has an exact published version.\n- Build and package only the harness-e2e runner for the daily Registry lane.\n- Record stack_versions, the resolved lock SHA-256 digest, the lock snapshot, worker list, and deployment status in benchmark artifacts and compact metrics.\n- Classify Registry resolution and lock-verification failures as infra_failed; there is no source fallback.\n- Move LLVM coverage to the source-based main lane and remove the daily source/integration build.\n\n## Validation\n\n- bash -n harness/tests/e2e/run-deployed-ci.sh\n- Python compilation and workflow YAML parsing passed.\n- Dependency-free metadata smoke test passed.\n- The focused pytest suite could not run locally because pytest is not installed.\n\nRefs MOT-4299

Summary by CodeRabbit

  • New Features

    • Added registry-based stack resolution for end-to-end benchmark runs.
    • Reports now include resolved worker versions, stack mode, deployment details, and lock-file identity.
    • Added validation for stack definitions and deterministic version tracking.
  • Bug Fixes

    • Infrastructure and deployment failures are now reflected consistently in scenario results, suite status, reports, snapshots, and reliability metrics.
    • Missing reports after failed deployments are explicitly handled as infrastructure failures.
  • Documentation

    • Documented daily registry-based benchmark behavior and the source-based main workflow.

@vercel

vercel Bot commented Aug 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
workers Ready Ready Preview Aug 7, 2026 1:54am
workers-tech-spec Ready Ready Preview Aug 7, 2026 1:54am

Request Review

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds registry stack identity generation, dynamic and static stack resolution, deployment metadata propagation, and infrastructure-failure reporting across Harness E2E workflows, benchmark collection, snapshots, metrics, and execution reports.

Changes

Registry-backed Harness E2E execution

Layer / File(s) Summary
Stack identity contract
.github/scripts/registry_stack_identity.py, .github/scripts/collect_harness_e2e_benchmarks.py
The lock file is validated and converted into deterministic worker versions and a SHA-256 digest. Collection configuration accepts stack mode, versions, and digest values.
Registry deployment resolution
harness/tests/e2e/run-deployed-ci.sh, .github/workflows/_harness-e2e.yml
Dynamic and static registry modes validate stack inputs, install resolved workers, verify the lock digest, and record deployment metadata.
Infrastructure failure and metadata reporting
.github/scripts/collect_harness_e2e_benchmarks.py, .github/scripts/tests/test_collect_harness_e2e_benchmarks.py
Deployment metadata supplies release and stack observations. Infrastructure failures affect scenario and suite statuses, counters, snapshots, reliability metrics, and execution reports.
Workflow lane integration
.github/workflows/harness-e2e-daily.yml, .github/workflows/harness-e2e-main.yml, .github/workflows/_harness-e2e.yml, harness/tests/e2e/README.md, .github/scripts/tests/test_registry_stack_identity.py
The daily lane uses registry resolution without coverage. The main lane enables coverage. Workflow artifacts include deployment and stack data. Tests cover identity generation and registry-mode collection.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant HarnessWorkflow
  participant run_deployed_ci
  participant registry_stack_identity
  participant BenchmarkCollector
  HarnessWorkflow->>run_deployed_ci: Pass stack resolution inputs
  run_deployed_ci->>registry_stack_identity: Resolve worker versions and lock digest
  registry_stack_identity-->>run_deployed_ci: Return stack identity
  run_deployed_ci-->>HarnessWorkflow: Write deployment result
  HarnessWorkflow->>BenchmarkCollector: Pass deployment and stack metadata
  BenchmarkCollector-->>HarnessWorkflow: Produce failure metrics and reports
Loading

Possibly related PRs

Poem

A rabbit checks the lock at dawn,
Exact stack versions carry on.
Failures hop into reports,
Digests guard the registry ports.
Benchmarks bloom with metadata bright.
Thump, thump—the lanes now run right.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: running daily Harness benchmarks against the Registry.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/daily-registry-benchmark

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

skill-check — worker

0 verified, 55 skipped (no docs/).

Layer Result
structure
vale
ai
render

Four for four. Nicely done.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (6)
.github/scripts/collect_harness_e2e_benchmarks.py (2)

179-196: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the dead seen set and consider narrowing the upward search.

The function returns on the first existing candidate, and the three candidates are distinct paths. The seen set therefore never suppresses a duplicate. Remove it.

The three-level walk also reaches the artifact root. If a stray deployment.json exists above a scenario directory, a scenario without its own deployment file inherits it and gets classified as infra_failed. The workflow currently writes deployment.json inside each scenario artifact, so two levels are sufficient.

♻️ Proposed refactor
 def load_deployment(context_path: Path | None) -> dict[str, Any] | None:
     if context_path is None:
         return None
     candidates = (
         context_path.parent / "deployment.json",
         context_path.parent.parent / "deployment.json",
-        context_path.parent.parent.parent / "deployment.json",
     )
-    seen: set[Path] = set()
     for candidate in candidates:
-        if candidate in seen or not candidate.is_file():
+        if not candidate.is_file():
             continue
-        seen.add(candidate)
         value = load_json(candidate)
         if not isinstance(value, dict):
             raise CollectionError(f"{candidate} must contain an object")
         return value
     return None
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/scripts/collect_harness_e2e_benchmarks.py around lines 179 - 196,
Update load_deployment to remove the unused seen set and its duplicate-check
logic, and restrict candidates to the scenario directory and its parent (two
deployment.json locations). Preserve validation and first-existing-file
behavior.

704-708: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Duplicated single-observation resolution in collect. Both blocks apply the same rule: start from stack_metadata(config, None), then override when exactly one release observation and one stack observation exist. Extract one helper and call it from both places.

  • .github/scripts/collect_harness_e2e_benchmarks.py#L704-L708: replace the suite block with a call to a shared helper, for example resolve_release_and_stack(config, release_observations, stack_observations).
  • .github/scripts/collect_harness_e2e_benchmarks.py#L850-L854: replace the snapshot block with a call to the same helper.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/scripts/collect_harness_e2e_benchmarks.py around lines 704 - 708,
Extract the duplicated release/stack resolution into a shared helper, such as
resolve_release_and_stack, that starts with stack_metadata(config, None) and
overrides each value only when its corresponding observation list has exactly
one item. In .github/scripts/collect_harness_e2e_benchmarks.py lines 704-708,
replace the suite resolution block with the helper call; make the same
replacement in lines 850-854 for the snapshot resolution block.
.github/scripts/registry_stack_identity.py (1)

22-52: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Read the lock file once to guarantee the digest matches the validated content.

Line 24 reads the file as text, and line 50 reads it again as bytes. The digest therefore covers a second read, not the content that was validated. Line 50 is also outside the try block, so an OSError there escapes as a traceback instead of the invalid_lock: contract. A single read fixes both points.

♻️ Proposed refactor
 def stack_identity(lock_path: Path) -> dict[str, Any]:
     try:
-        document = yaml.safe_load(lock_path.read_text()) or {}
+        raw = lock_path.read_bytes()
+        document = yaml.safe_load(raw) or {}
     except (OSError, yaml.YAMLError) as error:
         raise SystemExit(f"invalid_lock: cannot read {lock_path}: {error}") from error
@@
     return {
         "schema_version": 1,
-        "lock_digest": hashlib.sha256(lock_path.read_bytes()).hexdigest(),
+        "lock_digest": hashlib.sha256(raw).hexdigest(),
         "stack_versions": versions,
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/scripts/registry_stack_identity.py around lines 22 - 52, Update
stack_identity to read lock_path once as bytes inside the existing try block,
derive the YAML text from those bytes for validation, and compute lock_digest
from the same bytes. Ensure any read failure remains wrapped in the existing
invalid_lock SystemExit contract and remove the second lock_path.read_bytes()
call.
.github/scripts/tests/test_collect_harness_e2e_benchmarks.py (1)

61-69: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add one assertion for precedence over the other blocking statuses.

The new case proves infra_failed beats passed. It does not prove that infra_failed beats technical_failed or incomplete, which is the actual ordering guarantee in semantic_result_status.

♻️ Proposed addition
     assert (
         semantic_result_status(
             passed=True,
             hard_gate_failures=0,
             technical_failures=0,
             infra_failures=1,
         )
         == "infra_failed"
     )
+    assert (
+        semantic_result_status(
+            passed=False,
+            hard_gate_failures=1,
+            technical_failures=1,
+            infra_failures=1,
+            complete=False,
+        )
+        == "infra_failed"
+    )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/scripts/tests/test_collect_harness_e2e_benchmarks.py around lines 61
- 69, Add assertions in the semantic_result_status tests to verify that an infra
failure takes precedence over both technical failures and incomplete results,
not only passed results. Keep the existing infra_failed expectation and vary the
relevant blocking-status inputs while preserving the infra_failures=1 condition.
harness/tests/e2e/run-deployed-ci.sh (2)

382-390: 🗄️ Data Integrity & Integration | 🔵 Trivial | 💤 Low value

release_version loses the requested value in dynamic mode.

Line 389 overwrites release_version with the resolved harness version. write_deployment_result then emits the resolved version in both release_version and actual_release_version. The record no longer states that the run requested latest.

Keep the requested value and store the resolved value in a separate variable, so the deployment record distinguishes the request from the result.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@harness/tests/e2e/run-deployed-ci.sh` around lines 382 - 390, In the
resolve_stack block, preserve the requested release_version value (latest) and
assign the resolved .stack_versions.harness value to a separate variable. Update
write_deployment_result and any downstream uses so release_version reports the
request while actual_release_version reports the resolved version, using the
existing resolved-value flow where applicable.

391-393: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Duplicated expected-digest comparison. Both branches compute lock_digest and then run the identical comparison against expected_stack_digest. Move the comparison to a single place after the if/else, so the two branches only compute the digest.

  • harness/tests/e2e/run-deployed-ci.sh#L391-L393: remove the comparison from the dynamic branch and keep only the digest assignment.
  • harness/tests/e2e/run-deployed-ci.sh#L414-L416: remove the comparison from the static branch and place one shared comparison after fi on line 417.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@harness/tests/e2e/run-deployed-ci.sh` around lines 391 - 393, In
harness/tests/e2e/run-deployed-ci.sh, update the dynamic branch at lines 391-393
and static branch at lines 414-416 to only assign lock_digest; remove the
duplicated expected_stack_digest comparisons from both sites, then add one
shared comparison after the closing fi at line 417 using the existing
lock_digest and expected_stack_digest values.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/harness-e2e-daily.yml:
- Around line 82-90: Update the daily workflow so the build job resolves
harness@latest once, captures its digest, and passes that value as stack_digest
to every matrix job. Disable per-job latest resolution by changing the matrix
configuration around resolve_stack, and ensure the collected benchmark metadata
uses the pinned digest instead of relying on empty stack_versions or
stack_observations fallbacks.

In `@harness/tests/e2e/README.md`:
- Around line 234-240: Update the later daily-lane description in the README to
state that it installs and evaluates registry artifacts resolved from latest,
without falling back to source-built repository binaries; keep the quickstart
validator distinction accurate. Also update the “Harness E2E Daily” table row to
include the infra_failed classification.

In `@harness/tests/e2e/run-deployed-ci.sh`:
- Around line 166-169: Update write_deployment_result to create
"$artifact_dir/results" before copying deployment.json, ensuring the directory
exists when cleanup runs after an early registry-phase failure.

---

Nitpick comments:
In @.github/scripts/collect_harness_e2e_benchmarks.py:
- Around line 179-196: Update load_deployment to remove the unused seen set and
its duplicate-check logic, and restrict candidates to the scenario directory and
its parent (two deployment.json locations). Preserve validation and
first-existing-file behavior.
- Around line 704-708: Extract the duplicated release/stack resolution into a
shared helper, such as resolve_release_and_stack, that starts with
stack_metadata(config, None) and overrides each value only when its
corresponding observation list has exactly one item. In
.github/scripts/collect_harness_e2e_benchmarks.py lines 704-708, replace the
suite resolution block with the helper call; make the same replacement in lines
850-854 for the snapshot resolution block.

In @.github/scripts/registry_stack_identity.py:
- Around line 22-52: Update stack_identity to read lock_path once as bytes
inside the existing try block, derive the YAML text from those bytes for
validation, and compute lock_digest from the same bytes. Ensure any read failure
remains wrapped in the existing invalid_lock SystemExit contract and remove the
second lock_path.read_bytes() call.

In @.github/scripts/tests/test_collect_harness_e2e_benchmarks.py:
- Around line 61-69: Add assertions in the semantic_result_status tests to
verify that an infra failure takes precedence over both technical failures and
incomplete results, not only passed results. Keep the existing infra_failed
expectation and vary the relevant blocking-status inputs while preserving the
infra_failures=1 condition.

In `@harness/tests/e2e/run-deployed-ci.sh`:
- Around line 382-390: In the resolve_stack block, preserve the requested
release_version value (latest) and assign the resolved .stack_versions.harness
value to a separate variable. Update write_deployment_result and any downstream
uses so release_version reports the request while actual_release_version reports
the resolved version, using the existing resolved-value flow where applicable.
- Around line 391-393: In harness/tests/e2e/run-deployed-ci.sh, update the
dynamic branch at lines 391-393 and static branch at lines 414-416 to only
assign lock_digest; remove the duplicated expected_stack_digest comparisons from
both sites, then add one shared comparison after the closing fi at line 417
using the existing lock_digest and expected_stack_digest values.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: da3f51d0-243a-44d3-b586-b09e2d763d6e

📥 Commits

Reviewing files that changed from the base of the PR and between aef3806 and 24e4c0d.

📒 Files selected for processing (9)
  • .github/scripts/collect_harness_e2e_benchmarks.py
  • .github/scripts/registry_stack_identity.py
  • .github/scripts/tests/test_collect_harness_e2e_benchmarks.py
  • .github/scripts/tests/test_registry_stack_identity.py
  • .github/workflows/_harness-e2e.yml
  • .github/workflows/harness-e2e-daily.yml
  • .github/workflows/harness-e2e-main.yml
  • harness/tests/e2e/README.md
  • harness/tests/e2e/run-deployed-ci.sh

Comment on lines +82 to +90
stack_mode: registry
resolve_stack: true
benchmark_lane: daily
release_tag: daily/${{ needs.context.outputs.benchmark_day }}
release_worker: main
release_version: ${{ needs.context.outputs.benchmark_day }}
release_worker: harness
release_version: latest
release_url: ${{ needs.context.outputs.source_url }}
registry_tag: daily
coverage: true
registry_tag: latest
coverage: false

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Each matrix job resolves latest independently, so the daily data point can mix stack versions.

resolve_stack: true makes every subject/scenario job run its own harness@latest resolution. If a release publishes while the matrix runs, jobs resolve different versions.

collect_harness_e2e_benchmarks.py then records more than one entry in stack_observations, and lines 704-708 and 850-854 fall back to the configured stack. Because the daily lane passes no stack_versions and no stack_digest, that fallback is empty. The suite and snapshot metadata for that day would then carry no resolved stack version.

The reusable workflow already accepts stack_digest. Resolving latest once in the build job and passing the resolved digest to the matrix would pin the whole day to one stack.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/harness-e2e-daily.yml around lines 82 - 90, Update the
daily workflow so the build job resolves harness@latest once, captures its
digest, and passes that value as stack_digest to every matrix job. Disable
per-job latest resolution by changing the matrix configuration around
resolve_stack, and ensure the collected benchmark metadata uses the pinned
digest instead of relying on empty stack_versions or stack_observations
fallbacks.

Comment on lines +234 to +240
The daily lane uses the registry mode to measure the currently published live
stack. It resolves `latest` once per matrix job, records the exact versions and
SHA-256 digest of the resulting `iii.lock`, and treats Registry resolution
failures as `infra_failed`; it does not fall back to a source build. The main
lane keeps the source build and LLVM coverage so operational daily metrics stay
separate from checkout regression coverage.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

A later paragraph now contradicts this one.

Lines 329-331 still state that the daily lane evaluates repository binaries built from the resolved default branch commit, does not install registry artifacts, and leaves registry installation to the quickstart validator. The new paragraph and harness-e2e-daily.yml make the daily lane registry-based. Update lines 329-331.

The table row for Harness E2E Daily at line 222 also omits the new infra_failed classification.

📝 Proposed replacement for lines 329-331
-The daily lane evaluates repository binaries built from the resolved default
-branch commit. It does not install registry artifacts; registry installation
-remains the responsibility of the quickstart validator.
+The daily lane installs the published registry stack and evaluates it against
+the resolved default branch commit. The main lane evaluates repository
+binaries built from the checkout. The quickstart validator remains the
+coverage for the `iii worker add` CLI path.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@harness/tests/e2e/README.md` around lines 234 - 240, Update the later
daily-lane description in the README to state that it installs and evaluates
registry artifacts resolved from latest, without falling back to source-built
repository binaries; keep the quickstart validator distinction accurate. Also
update the “Harness E2E Daily” table row to include the infra_failed
classification.

Comment on lines +166 to +169
stack_lock_digest: $lock_digest,
elapsed_ms: $elapsed_ms
}' >"$artifact_dir/deployment.json"
cp "$artifact_dir/deployment.json" "$artifact_dir/results/deployment.json"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Create the results directory before copying deployment.json into it.

write_deployment_result runs from cleanup. If the run fails during the registry phase, the workflow step that runs mkdir -p target/harness-e2e/results has not executed yet, so $artifact_dir/results may not exist. The cp then fails. cleanup uses set +e, so the failure is silent, but the results artifact loses deployment.json.

🐛 Proposed fix
     }' >"$artifact_dir/deployment.json"
+  mkdir -p "$artifact_dir/results"
   cp "$artifact_dir/deployment.json" "$artifact_dir/results/deployment.json"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
stack_lock_digest: $lock_digest,
elapsed_ms: $elapsed_ms
}' >"$artifact_dir/deployment.json"
cp "$artifact_dir/deployment.json" "$artifact_dir/results/deployment.json"
stack_lock_digest: $lock_digest,
elapsed_ms: $elapsed_ms
}' >"$artifact_dir/deployment.json"
mkdir -p "$artifact_dir/results"
cp "$artifact_dir/deployment.json" "$artifact_dir/results/deployment.json"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@harness/tests/e2e/run-deployed-ci.sh` around lines 166 - 169, Update
write_deployment_result to create "$artifact_dir/results" before copying
deployment.json, ensuring the directory exists when cleanup runs after an early
registry-phase failure.

@ytallo
ytallo merged commit b90ed93 into main Aug 7, 2026
18 checks passed
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