Skip to content

feat(eval): aelf eval subcommand + lift calibration harness to module (#365 R4) - #509

Merged
robotrocketscience merged 4 commits into
mainfrom
feat/issue-365-r4-aelf-eval
May 9, 2026
Merged

feat(eval): aelf eval subcommand + lift calibration harness to module (#365 R4)#509
robotrocketscience merged 4 commits into
mainfrom
feat/issue-365-r4-aelf-eval

Conversation

@robotrocketscience

@robotrocketscience robotrocketscience commented May 9, 2026

Copy link
Copy Markdown
Owner

Phase B of the close-the-loop relevance-calibration loop ratified at
#317 — exposes the R1 harness as an operator-facing aelf eval
subcommand.

Shape

Three atomic commits + one slash-file follow-up:

  1. feat(eval): aelfrice.eval_harness module — lift the calibration
    harness (load_calibration_fixtures / build_calibration_store /
    run_calibration_on_fixtures / format_calibration_report) out of
    scripts/audit_rebuild_log.py into a wheel-installable leaf module.
    12 unit tests.
  2. refactor(eval): audit_rebuild_log delegates calibration to aelfrice.eval_harness — the script keeps its CLI surface (flags,
    exit codes, stderr wording) and now imports the harness instead of
    inlining it. Output is bytes-identical before and after; existing
    16 audit_rebuild_log tests stay green.
  3. feat(cli): aelf eval subcommand for relevance-calibration harness
    — adds the eval subparser with --corpus / --k / --seed / --json
    flags. 10 new CLI tests.
  4. feat(slash): ship /aelf:eval slash file for the new subcommand
    ships slash_commands/eval.md and registers eval in the slash
    parity test, so the visible CLI surface matches EXPECTED_COMMANDS.

Determinism contract

Same (corpus, --k, --seed) → bytes-identical output across reruns,
in both text and JSON modes. JSON keys are sorted so the line stays
diff-stable across Python releases — relevant for the future R5 CI
status-check surface.

Verification

  • Full suite: 3014 passed, 48 skipped.
  • Discretion grep: clean.
  • uv run aelf eval and uv run python scripts/audit_rebuild_log.py --calibrate-corpus produce identical metric lines on the bundled
    synthetic corpus (P@10=0.1000, ROC-AUC=0.8444, ρ=0.5241; n=7
    queries, n_obs=35; seed=0).

Out of scope

R2 (hybrid labeling pipeline) and R3 (hand-label calibration) remain
lab-side per the issue spec. R5 (CI workflow on push to main) is
the next public-repo round and can now consume aelf eval --json
directly.

Refs #365.

Summary by Sourcery

Introduce a reusable relevance-calibration harness module and expose it via both the existing audit script and a new aelf eval CLI subcommand.

New Features:

  • Add the aelfrice.eval_harness module providing a reusable relevance-calibration harness API and defaults.
  • Add an aelf eval CLI subcommand to run the calibration harness against a synthetic corpus with configurable corpus, k, seed, and JSON output.
  • Ship an /aelf:eval slash command description for the new eval subcommand.

Enhancements:

  • Refactor scripts/audit_rebuild_log.py to delegate calibration mode to the shared aelfrice.eval_harness module while preserving its CLI surface and output.

Tests:

  • Add unit tests for the aelfrice.eval_harness module covering fixture loading, determinism, store construction, and report formatting.
  • Add CLI tests for aelf eval covering default behavior, JSON output, determinism, flag handling, and error cases.
  • Extend slash command parity tests to cover the new eval command.

@coderabbitai

coderabbitai Bot commented May 9, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@robotrocketscience has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 31 minutes and 39 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 35053b71-c9de-4071-8a0d-5e34f1aeb232

📥 Commits

Reviewing files that changed from the base of the PR and between ccda41a and af4121a.

📒 Files selected for processing (7)
  • scripts/audit_rebuild_log.py
  • src/aelfrice/cli.py
  • src/aelfrice/eval_harness.py
  • src/aelfrice/slash_commands/eval.md
  • tests/test_cli_eval.py
  • tests/test_eval_harness.py
  • tests/test_slash_commands.py
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/issue-365-r4-aelf-eval

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 and usage tips.

@sourcery-ai

sourcery-ai Bot commented May 9, 2026

Copy link
Copy Markdown

Reviewer's Guide

Lifts the relevance-calibration harness into a reusable aelfrice.eval_harness module, updates audit_rebuild_log.py to delegate to it while preserving its CLI behavior, introduces an operator-facing aelf eval CLI subcommand (with text and JSON outputs) wired to the harness, and documents the new subcommand via a slash command file and tests.

Sequence diagram for the new aelf eval subcommand flow

sequenceDiagram
    actor Operator
    participant AelfCLI as aelf_cli_main
    participant EvalCmd as _cmd_eval
    participant EvalHarness as eval_harness
    participant Store as MemoryStore
    participant Retrieval as retrieve
    participant Metrics as calibration_metrics

    Operator->>AelfCLI: run aelf eval [--corpus --k --seed --json]
    AelfCLI->>EvalCmd: dispatch func with parsed args

    EvalCmd->>EvalCmd: validate args.eval_k > 0
    alt invalid k
        EvalCmd-->>Operator: exit code 2 (usage error)
    else valid k
        EvalCmd->>EvalHarness: DEFAULT_CALIBRATION_CORPUS
        EvalCmd->>EvalCmd: resolve corpus_path
        EvalCmd->>EvalHarness: load_calibration_fixtures(corpus_path)
        EvalHarness-->>EvalCmd: fixtures
        EvalCmd->>EvalHarness: run_calibration_on_fixtures(fixtures, k, seed)
        EvalHarness->>Store: build_calibration_store(fixture, seed)
        Store-->>EvalHarness: MemoryStore instance
        EvalHarness->>Retrieval: retrieve(store, query, l1_limit, flags)
        Retrieval-->>EvalHarness: ranked beliefs
        EvalHarness->>Metrics: precision_at_k / roc_auc / spearman_rho
        Metrics-->>EvalHarness: metric values
        EvalHarness->>Store: close()
        EvalHarness-->>EvalCmd: CalibrationReport

        alt args.eval_json is set
            EvalCmd->>EvalCmd: build JSON payload dict
            EvalCmd-->>Operator: JSON line (sorted keys), exit 0
        else human-readable text
            EvalCmd->>EvalHarness: format_calibration_report(report, corpus_path, seed)
            EvalHarness-->>EvalCmd: text block
            EvalCmd-->>Operator: text block, exit 0
        end
    end
Loading

Class diagram for the new eval_harness module and related types

classDiagram
    class EvalHarnessModule {
        <<module>>
        Path DEFAULT_CALIBRATION_CORPUS
        int DEFAULT_K
        int DEFAULT_SEED
        +list~dict~ load_calibration_fixtures(path: Path)
        +MemoryStore build_calibration_store(fixture: dict, seed: int)
        +CalibrationReport run_calibration_on_fixtures(fixtures: Sequence~dict~, k: int, seed: int)
        +str format_calibration_report(report: CalibrationReport, corpus_path: Path, seed: int)
    }

    class CalibrationReport {
        +float p_at_k
        +int k
        +int n_queries
        +int n_truncated_queries
        +float roc_auc
        +float spearman_rho
        +int n_observations
    }

    class MemoryStore {
        +MemoryStore(path: str)
        +insert_belief(belief: Belief) void
        +close() void
    }

    class Belief {
        +str id
        +str content
        +str content_hash
        +float alpha
        +float beta
        +str type
        +str lock_level
        +str locked_at
        +int demotion_pressure
        +str created_at
        +str last_retrieved_at
    }

    class CalibrationMetricsModule {
        <<module>>
        +float precision_at_k(labels: list~bool~, k: int)
        +float roc_auc(scores: list~float~, labels: list~bool~)
        +float spearman_rho(scores: list~float~, labels: list~float~)
    }

    EvalHarnessModule --> CalibrationReport : returns
    EvalHarnessModule --> MemoryStore : builds
    EvalHarnessModule --> CalibrationMetricsModule : uses
    MemoryStore --> Belief : stores
Loading

File-Level Changes

Change Details Files
Extract calibration harness logic into a reusable module with deterministic reporting APIs.
  • Introduce src/aelfrice/eval_harness.py encapsulating calibration corpus defaults, fixture loading, in-memory store construction, calibration execution, and human-readable report formatting.
  • Ensure determinism via seed-controlled shuffling, pure functions over fixtures, and stable text formatting (including handling of undefined metrics).
  • Expose a small, documented public API (DEFAULT_* constants plus load/build/run/format helpers) and add targeted unit tests to validate behavior, determinism, and edge cases.
src/aelfrice/eval_harness.py
tests/test_eval_harness.py
Refactor audit_rebuild_log calibration mode to call the shared harness while preserving its existing CLI surface and output shape.
  • Remove inline calibration corpus defaults, fixture loading, store-building, and metric aggregation logic from the script.
  • Add a lazy import helper to load aelfrice.eval_harness only when calibration is requested so audit-mode usage remains decoupled from the wheel.
  • Delegate fixture loading, calibration execution, and report formatting to eval_harness and wire argparse defaults to the harness-provided defaults, keeping flags, exit codes, and stderr wording unchanged.
scripts/audit_rebuild_log.py
Add an aelf eval CLI subcommand that runs the calibration harness over a corpus and supports both human-readable and JSON output modes with strict determinism.
  • Implement _cmd_eval in the CLI, validating arguments (notably positive k) and interpreting --corpus/--k/--seed/--json flags into harness calls.
  • Use eval_harness to load fixtures and compute a CalibrationReport, then either render text identical in shape to audit_rebuild_log calibration mode or emit a single-line JSON object with sorted keys for diff-stable CI consumption.
  • Extend the main parser to register the eval subcommand and its arguments with sensible defaults aligned with the harness constants, and add CLI tests to cover success paths, error codes, determinism, and JSON key ordering.
src/aelfrice/cli.py
tests/test_cli_eval.py
Register and document the new eval capability in the slash-command surface.
  • Add the eval command to the EXPECTED_COMMANDS list used by the slash parity test so the slash surface matches the CLI.
  • Create a slash command definition for aelf:eval explaining its purpose, arguments, determinism contract, and usage pattern via uv run.
  • Ensure tests validate presence of the new slash command entry.
tests/test_slash_commands.py
src/aelfrice/slash_commands/eval.md

Possibly linked issues

  • #unknown: The issue specifies the close-the-loop calibration loop including R4 aelf eval; this PR implements that eval subcommand and harness.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@robotrocketscience robotrocketscience added author-Gylf PR coordination mutex attn:review Needs review (PR open, awaiting reviewer) labels May 9, 2026

@sourcery-ai sourcery-ai 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.

Hey - I've found 2 issues, and left some high level feedback:

  • In cli._cmd_eval, the parser defaults and help text for --k and --seed are hard-coded (10 and 0); consider wiring these to eval_harness.DEFAULT_K / DEFAULT_SEED so the CLI stays in sync with the harness defaults.
  • In scripts/audit_rebuild_log.py, _load_calibration_fixtures is now just a thin alias around eval_harness.load_calibration_fixtures and appears unused within the module; consider removing it to avoid dead code and keep the delegation path clear.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `cli._cmd_eval`, the parser defaults and help text for `--k` and `--seed` are hard-coded (10 and 0); consider wiring these to `eval_harness.DEFAULT_K` / `DEFAULT_SEED` so the CLI stays in sync with the harness defaults.
- In `scripts/audit_rebuild_log.py`, `_load_calibration_fixtures` is now just a thin alias around `eval_harness.load_calibration_fixtures` and appears unused within the module; consider removing it to avoid dead code and keep the delegation path clear.

## Individual Comments

### Comment 1
<location path="scripts/audit_rebuild_log.py" line_range="218-223" />
<code_context>
-    )
-    from aelfrice.retrieval import retrieve  # noqa: PLC0415

+def _run_calibration(corpus_path: Path, k: int, seed: int) -> int:
+    """Run the #365 R1 calibration harness; print report or error."""
+    eh = _load_aelfrice_eval_harness()
</code_context>
<issue_to_address>
**issue:** Guard against non-positive k before calling run_calibration_on_fixtures to avoid uncaught ValueError.

`eval_harness.run_calibration_on_fixtures` now raises `ValueError` for `k <= 0`, and this script passes `k` straight from the CLI without validation. That means `--k 0` (or negative) will produce a traceback instead of a controlled, non-zero exit. Adding a simple `if k <= 0: ...` check before calling into the harness (similar to `aelf eval`) would avoid exposing this internal exception and keep CLI behavior consistent.
</issue_to_address>

### Comment 2
<location path="src/aelfrice/eval_harness.py" line_range="51-56" />
<code_context>
             print(f"  rank {rank:>2}: {summary['packed_ranks'][rank]}")


-DEFAULT_CALIBRATION_CORPUS = (
-    Path(__file__).resolve().parent.parent
-    / "benchmarks"
-    / "posterior_ranking"
-    / "fixtures"
-    / "default.jsonl"
-)
-DEFAULT_CALIBRATION_K = 10
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Resolve the default corpus path via package resources instead of repo-relative filesystem paths.

The current path computation (`Path(__file__).resolve().parent.parent.parent / "benchmarks" / ...`) assumes a specific source layout and may break once this is installed as a wheel, where that directory may not exist or be packaged. This can cause `DEFAULT_CALIBRATION_CORPUS.is_file()` to fail at runtime. To make this robust in installed environments, use `importlib.resources.files(...)` (or `open_text`/`open_binary`) to load the bundled JSONL from package data instead of walking up the filesystem tree.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +218 to 223
def _run_calibration(corpus_path: Path, k: int, seed: int) -> int:
"""Run the #365 R1 calibration harness; print report or error."""
eh = _load_aelfrice_eval_harness()
if not corpus_path.is_file():
print(
f"audit_rebuild_log: calibration corpus not found: "

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue: Guard against non-positive k before calling run_calibration_on_fixtures to avoid uncaught ValueError.

eval_harness.run_calibration_on_fixtures now raises ValueError for k <= 0, and this script passes k straight from the CLI without validation. That means --k 0 (or negative) will produce a traceback instead of a controlled, non-zero exit. Adding a simple if k <= 0: ... check before calling into the harness (similar to aelf eval) would avoid exposing this internal exception and keep CLI behavior consistent.

Comment on lines +51 to +56
DEFAULT_CALIBRATION_CORPUS = (
Path(__file__).resolve().parent.parent.parent
/ "benchmarks"
/ "posterior_ranking"
/ "fixtures"
/ "default.jsonl"

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 (bug_risk): Resolve the default corpus path via package resources instead of repo-relative filesystem paths.

The current path computation (Path(__file__).resolve().parent.parent.parent / "benchmarks" / ...) assumes a specific source layout and may break once this is installed as a wheel, where that directory may not exist or be packaged. This can cause DEFAULT_CALIBRATION_CORPUS.is_file() to fail at runtime. To make this robust in installed environments, use importlib.resources.files(...) (or open_text/open_binary) to load the bundled JSONL from package data instead of walking up the filesystem tree.

@robotrocketscience

Copy link
Copy Markdown
Owner Author

[claim:review:kulili:2026-05-09T05:31:19Z]

@robotrocketscience

Copy link
Copy Markdown
Owner Author

Review pass — diff reads clean.

Substantive checks:

  • Module lift is faithful: audit_rebuild_log.py keeps its CLI surface (flags, exit codes, stderr wording); calibration mode now delegates to aelfrice.eval_harness via lazy import. Audit mode unchanged.
  • _cmd_eval exit codes match the docstring (0/1/2) and the empty-corpus branch is exercised.
  • JSON mode is deterministic: sort_keys=True + compact separators + format_calibration_report already terminates with \n so end="" avoids the double-newline. Good.
  • 4 atomic signed commits. CI green across pytest 3.12/3.13, CodeQL, deptry, vulture, secrets-scan, pattern-scan, history-scan.
  • Discretion grep clean.

Blocker — needs rebase before FF merge.

main has moved forward (PR #508 README rewrite landed). The branch is mergeable per GitHub's check (no conflicts — README touches don't overlap), but protocol §6 requires FF, not a merge commit.

$ git merge-base --is-ancestor github/main github/feat/issue-365-r4-aelf-eval
$ echo $?
1   # FF not possible

Please rebase onto github/main and force-push (with-lease). I'll re-claim and FF-merge after.

Releasing my claim:review so the rebased branch can pick up a fresh reviewer.

@robotrocketscience robotrocketscience added attn:unblock Needs answer from another session and removed attn:review Needs review (PR open, awaiting reviewer) labels May 9, 2026
@robotrocketscience

Copy link
Copy Markdown
Owner Author

[release:review:kulili:2026-05-09T05:32:44Z]

@github-actions github-actions Bot added the attn:merge-conflict PR branch needs rebase label May 9, 2026
@github-actions

github-actions Bot commented May 9, 2026

Copy link
Copy Markdown

This PR is now behind main. Rebase locally so your commit signatures stay intact:

git fetch origin && git checkout 'feat/issue-365-r4-aelf-eval' && git rebase origin/main
# resolve conflicts if any, then
git push --force-with-lease

Auto-rebase was removed because the bot has no signing key; rebasing as the bot strips author signatures and the required_signatures rule on main then blocks the merge. See #341.

@robotrocketscience

Copy link
Copy Markdown
Owner Author

[claim:merge:setr:2026-05-09T05:43:48Z]

@robotrocketscience

Copy link
Copy Markdown
Owner Author

[claim:pr:Toug:2026-05-09T05:44:01Z]

…rom script (#365 R4)

Extract the calibration harness (load_calibration_fixtures /
build_calibration_store / run_calibration_on_fixtures /
format_calibration_report) from scripts/audit_rebuild_log.py into a
wheel-installable module so the upcoming `aelf eval` subcommand and
the existing script can share one implementation. Pure leaf module:
imports only stdlib, aelfrice.calibration_metrics, and lazy-imports
aelfrice.{models,store,retrieval} inside the run path.

API change vs the script's inline shape: the runner is now
run_calibration_on_fixtures(fixtures, k, seed) returning
CalibrationReport, instead of run_calibration(corpus_path, k, seed)
returning int + printing. Existence/empty checks move to call sites,
so each surface emits its own prefix wording.

Determinism contract preserved: same (fixtures, k, seed) -> identical
report and identical formatted text.

12 unit tests cover: fixture loading skips malformed rows, seed
controls noise shuffle, k validation, empty-fixtures guard, format
output for defined and undefined metrics, truncated-line presence/
absence, and report determinism.

Refs #365 (R4 Phase B preparation).
…val_harness (#365 R4)

Replace the script's inline calibration helpers (_load_calibration_fixtures
/ _build_calibration_store / _run_calibration / _print_calibration_report
/ _format_optional_float / DEFAULT_CALIBRATION_*) with delegation to the
new aelfrice.eval_harness module. Same exit codes, same stderr wording,
same flag set.

The script keeps a thin _load_calibration_fixtures alias so the existing
unit test (tests/test_audit_rebuild_log.py:_load_calibration_fixtures
import) continues to work without churn.

Behavior gate: `python scripts/audit_rebuild_log.py --calibrate-corpus`
emits the same byte-for-byte output before and after this change. All 16
audit_rebuild_log tests still pass.
… R4)

Phase B of the close-the-loop calibration loop ratified at #317:
operator-facing alias of the R1 audit_rebuild_log --calibrate-corpus
mode, exposed as a top-level `aelf eval` subcommand.

Flags:
  --corpus PATH   override the bundled synthetic corpus
  --k N           K for P@K (default 10)
  --seed N        deterministic noise-shuffle seed (default 0)
  --json          emit one sorted-keys JSON object instead of text

Determinism contract preserved: same (corpus, seed, k) -> bytes-identical
output across reruns, in both text and JSON modes. Sorted JSON keys give
the future R5 CI status-check surface a diff-stable wire format.

Exit codes match audit_rebuild_log:
  0 report printed
  1 corpus missing or empty
  2 usage error (--k <= 0)

10 new CLI tests cover defaults, custom corpus, JSON shape, determinism
in both modes, --k label propagation, --k validation, missing/empty
corpus, and JSON-key sort stability.

Closes Phase B of the R-rounds plan; R5 (CI synthetic-corpus aggregate)
can now consume `aelf eval --json` directly.

Refs #365.
Add src/aelfrice/slash_commands/eval.md and register `eval` in
EXPECTED_COMMANDS so the slash-command parity test suite stays green
after the previous commit added the `aelf eval` subcommand.

Same template as locked.md / core.md / wonder.md — verbatim passthrough,
allowed-tools restricted to Bash.
@robotrocketscience
robotrocketscience force-pushed the feat/issue-365-r4-aelf-eval branch from 2afe9b4 to af4121a Compare May 9, 2026 05:44
@robotrocketscience robotrocketscience added attn:review Needs review (PR open, awaiting reviewer) and removed attn:unblock Needs answer from another session attn:merge-conflict PR branch needs rebase labels May 9, 2026
@robotrocketscience

Copy link
Copy Markdown
Owner Author

Rebased onto github/main (4 commits, all signed G). uv run pytest tests/test_eval_harness.py tests/test_cli_eval.py tests/test_slash_commands.py → 138 passed. Discretion grep clean. Re-flagged attn:review for FF merge.

@robotrocketscience

Copy link
Copy Markdown
Owner Author

[release:merge:setr:2026-05-09T05:45:19Z]

@robotrocketscience

Copy link
Copy Markdown
Owner Author

[release:pr:Toug:2026-05-09T05:46:09Z]

@robotrocketscience

Copy link
Copy Markdown
Owner Author

[claim:review:Toug:2026-05-09T05:46:17Z]

@robotrocketscience

Copy link
Copy Markdown
Owner Author

[claim:review:setr:2026-05-09T05:46:44Z]

@robotrocketscience

Copy link
Copy Markdown
Owner Author

[release:review:setr:2026-05-09T05:46:49Z]

@robotrocketscience
robotrocketscience merged commit af4121a into main May 9, 2026
22 checks passed
@robotrocketscience
robotrocketscience deleted the feat/issue-365-r4-aelf-eval branch May 9, 2026 05:47
@robotrocketscience

Copy link
Copy Markdown
Owner Author

[release:review:Toug:2026-05-09T05:47:51Z]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

attn:review Needs review (PR open, awaiting reviewer) author-Gylf PR coordination mutex

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant