Skip to content

Add cold-shape cross-run ablation v2#125

Open
Darkroom4364 wants to merge 1 commit into
mainfrom
issue-112-cold-shape-ablation-v2
Open

Add cold-shape cross-run ablation v2#125
Darkroom4364 wants to merge 1 commit into
mainfrom
issue-112-cold-shape-ablation-v2

Conversation

@Darkroom4364

@Darkroom4364 Darkroom4364 commented May 26, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Add a deterministic offline replay ablation for [Paper] Run cold-shape cross-run learning ablation v2 #112 using measured .noeris/cost-model-training.json rows.
  • Hold out cold shape buckets, remove curated starter configs, compare stateless_random, database_seeded, and cost_model_ranking across 3 seeds and 6 iterations.
  • Check in JSON/MD artifacts with raw per-iteration histories and update paper docs to reframe the cross-run claim honestly.

Result

  • cost_model_ranking: 0.9971 mean final normalized throughput, 0.29% mean final regret, 100% 90%-best success.
  • database_seeded: 0.9604 mean final normalized throughput, 3.96% mean final regret, 75% 90%-best success.
  • The v2 replay does not validate standalone database seeding as the dominant selector; it supports the persistent database as replayable training data and selector substrate.

Verification

  • python3 scripts/cold_shape_cross_run_ablation_v2.py
  • python3 -m unittest tests.test_cold_shape_cross_run_ablation_v2 tests.test_public_claim_artifacts
  • python3 -m compileall scripts/cold_shape_cross_run_ablation_v2.py tests/test_cold_shape_cross_run_ablation_v2.py
  • python3 scripts/check_public_claim_artifacts.py
  • git diff --check

Note: ruff is not installed in this environment, so ruff check ... could not run.

Closes #112

Summary by CodeRabbit

  • Documentation

    • Updated research paper and evaluation documents with second-generation ablation analysis results.
    • Added results documentation for cold-shape cross-run learning ablation v2.
  • New Features

    • Added automated ablation evaluation script for cold-shape cross-run learning analysis.
  • Tests

    • Added comprehensive test suite for ablation evaluation pipeline.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 26, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR implements a second-generation offline cold-shape cross-run learning ablation (v2) to fairly test whether a persistent database compounds learnings across runs. It introduces a new replay pipeline that partitions data into held-out buckets, trains ranking models, evaluates three selector conditions across multiple seeds and iterations, and reports findings showing database seeding does not independently improve over stateless baselines, while cost-model ranking achieves near-optimal performance.

Changes

Cold-Shape Cross-Run Learning Ablation v2

Layer / File(s) Summary
Ranking model types and feature encoding
scripts/cold_shape_cross_run_ablation_v2.py
FeatureKnnModel encodes and standardizes shape/config features, computes distance-weighted k-nearest neighbor predictions. RankingModel routes predictions to cost-model regression when available or falls back to kNN.
Data processing utilities and bucket construction
scripts/cold_shape_cross_run_ablation_v2.py
Utility helpers for deterministic seeding, feature encoding, and metric aggregation. _collect_bucket_records filters and aggregates database records by operator/hardware/bucket. _select_heldout_buckets partitions largest buckets per operator for held-out evaluation.
Model training and database seeding logic
scripts/cold_shape_cross_run_ablation_v2.py
_build_training_db excludes held-out buckets; _train_cost_model and _build_knn_model train ranking models. _database_seed_scores computes per-config normalized performance ratios. _ordered_config_ids generates deterministic orderings for stateless random, database-seeded, and cost-model ranking conditions.
Replay simulation and metric aggregation
scripts/cold_shape_cross_run_ablation_v2.py
_replay_bucket evaluates ordered candidates over iterations, tracks best-so-far, regret, 90%-of-oracle threshold crossings, and records full per-iteration histories. _summarize_runs aggregates multi-seed results into mean/median final metrics, regret statistics, and success rates.
Report building and CLI interface
scripts/cold_shape_cross_run_ablation_v2.py
build_report orchestrates the full pipeline: loads database, collects and selects buckets, builds training data, trains ranking models, replays all conditions/seeds, and aggregates summaries. main wires CLI arguments for database path, hardware, operators, held-out sizing, iterations, seeds, filtering, and curated config handling.
Test suite
tests/test_cold_shape_cross_run_ablation_v2.py
Validates report structure (protocol fields, bucket counts, training data presence, ranking model availability), per-iteration history format and length, markdown title and interpretation sections, and checked-in JSON artifact correctness.
Results documentation and paper updates
docs/results/README.md, docs/results/cold-shape-cross-run-ablation-v2.md, docs/paper/evaluation.md, docs/paper/noeris-submission.tex, docs/paper/noeris.md
Adds v2 protocol documentation, results tables, and interpretation. Updates paper sections to report v2 findings (cost-model ranking achieves 0.9971 normalized throughput with 100% success; database seeding matches stateless random). Reframes database as replayable training/ranking substrate rather than standalone compounding evidence. Updates "Cold novel shapes" bullet and limitations to reflect v2 scope and constraints.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

A rabbit builds a replay so neat,
With buckets held out, cold and sweet,
Three conditions race—the database dreams,
But stateless shines in empirical streams.
Yet ranking models show real might,
Bringing cold shapes toward the light. ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.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 specifically summarizes the main change: adding a second-generation cold-shape cross-run learning ablation experiment (v2).
Linked Issues check ✅ Passed All core coding objectives from #112 are met: v2 script with held-out buckets, three selector baselines, multiple seeds, reproducible artifacts with raw per-iteration histories, and paper updates reframing the cross-run learning claim.
Out of Scope Changes check ✅ Passed All changes directly support the #112 objectives: new ablation script, test suite, result artifacts, and paper documentation updates are all within the stated scope.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-112-cold-shape-ablation-v2

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.

@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: 1

🤖 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 `@scripts/cold_shape_cross_run_ablation_v2.py`:
- Around line 187-191: _split_record_key currently rejects 2-part legacy keys
and returns None; update it to accept keys split into 2 parts by ":" and return
operator="matmul" with bucket and hardware (i.e., for len(parts)==2 return
("matmul", parts[0], parts[1])) while keeping the existing len==3 behavior and
returning None otherwise so legacy `bucket:hardware` rows are included in
heldout selection, training DB construction, kNN/seed scoring, and replay.
🪄 Autofix (Beta)

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0e3fcd01-b9de-4dae-9702-f0f2e7cadafe

📥 Commits

Reviewing files that changed from the base of the PR and between d4222c2 and 9dbe3ee.

📒 Files selected for processing (8)
  • docs/paper/evaluation.md
  • docs/paper/noeris-submission.tex
  • docs/paper/noeris.md
  • docs/results/README.md
  • docs/results/cold-shape-cross-run-ablation-v2.json
  • docs/results/cold-shape-cross-run-ablation-v2.md
  • scripts/cold_shape_cross_run_ablation_v2.py
  • tests/test_cold_shape_cross_run_ablation_v2.py

Comment on lines +187 to +191
def _split_record_key(key: str) -> tuple[str, str, str] | None:
parts = key.split(":", 2)
if len(parts) != 3:
return None
return parts[0], parts[1], parts[2]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
python - <<'PY'
import json
from pathlib import Path

path = Path(".noeris/cost-model-training.json")
data = json.loads(path.read_text(encoding="utf-8"))
legacy = [key for key in data.get("records", {}) if len(key.split(":", 2)) == 2]

print(f"legacy_two_part_keys={len(legacy)}")
for key in legacy[:20]:
    print(key)
PY

Repository: 0sec-labs/noeris

Length of output: 83


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show key parsing function + usages
rg -n "def _split_record_key|_split_record_key\(" scripts/cold_shape_cross_run_ablation_v2.py

# Show bucket record collection + training db construction around the lines mentioned
python - <<'PY'
from pathlib import Path
p = Path("scripts/cold_shape_cross_run_ablation_v2.py")
lines = p.read_text(encoding="utf-8").splitlines()
for start,end in [(160,210),(210,260),(300,360),(360,430)]:
    print("\n# ---",start,"-",end,"---")
    for i in range(start-1,min(end,len(lines))):
        print(f"{i+1:4d}: {lines[i]}")
PY

# Inspect cost_model parsing contract
python - <<'PY'
from pathlib import Path
p = Path("src/research_engine/cost_model.py")
lines = p.read_text(encoding="utf-8").splitlines()
# Print around 240-320 and search for legacy handling
for start,end in [(230,290),(290,360),(360,440)]:
    print("\n# ---",start,"-",end,"---")
    for i in range(start-1,min(end,len(lines))):
        print(f"{i+1:4d}: {lines[i]}")
PY

# Find any code that constructs legacy two-part keys
rg -n "\"matmul\"|operator.*matmul|bucket:hardware|split\\(\\\":\\\",\\s*2\\)" -S src/research_engine/cost_model.py scripts/cold_shape_cross_run_ablation_v2.py

Repository: 0sec-labs/noeris

Length of output: 18166


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show key parsing function + usages
rg -n "def _split_record_key|_split_record_key\(" scripts/cold_shape_cross_run_ablation_v2.py

# Show bucket record collection + training db construction around the lines mentioned
python - <<'PY'
from pathlib import Path
p = Path("scripts/cold_shape_cross_run_ablation_v2.py")
lines = p.read_text(encoding="utf-8").splitlines()
for start,end in [(160,210),(210,260),(300,360),(360,430)]:
    print("\n# ---",start,"-",end,"---")
    for i in range(start-1,min(end,len(lines))):
        print(f"{i+1:4d}: {lines[i]}")
PY

# Inspect cost_model parsing contract
python - <<'PY'
from pathlib import Path
p = Path("src/research_engine/cost_model.py")
lines = p.read_text(encoding="utf-8").splitlines()
# Print around 240-440 and search for legacy handling
for start,end in [(240,320),(320,390),(390,470)]:
    print("\n# ---",start,"-",end,"---")
    for i in range(start-1,min(end,len(lines))):
        print(f"{i+1:4d}: {lines[i]}")
PY

# Find any code that constructs legacy two-part keys
rg -n "operator.*matmul|CostModel\\.train_from_databases|split\\(\\\":\\\",\\s*2\\)|bucket:hardware" -S src/research_engine/cost_model.py scripts/cold_shape_cross_run_ablation_v2.py

Repository: 0sec-labs/noeris

Length of output: 18037


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n "def _split_record_key|_split_record_key\(" scripts/cold_shape_cross_run_ablation_v2.py

python - <<'PY'
from pathlib import Path
p = Path("scripts/cold_shape_cross_run_ablation_v2.py")
lines = p.read_text(encoding="utf-8").splitlines()
for start,end in [(170,205),(205,250),(290,335),(335,390)]:
    print("\n# ---",start,"-",end,"---")
    for i in range(start-1,min(end,len(lines))):
        print(f"{i+1:4d}: {lines[i]}")
PY

python - <<'PY'
from pathlib import Path
p = Path("src/research_engine/cost_model.py")
lines = p.read_text(encoding="utf-8").splitlines()
for start,end in [(240,330),(330,420),(420,510)]:
    print("\n# ---",start,"-",end,"---")
    for i in range(start-1,min(end,len(lines))):
        print(f"{i+1:4d}: {lines[i]}")
PY

rg -n "operator.*matmul|train_from_databases|split\\(\\\":\\\",\\s*2\\)" -S src/research_engine/cost_model.py scripts/cold_shape_cross_run_ablation_v2.py

Repository: 0sec-labs/noeris

Length of output: 15796


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n "def _split_record_key|_split_record_key\(" scripts/cold_shape_cross_run_ablation_v2.py

python - <<'PY'
from pathlib import Path
p = Path("scripts/cold_shape_cross_run_ablation_v2.py")
lines = p.read_text(encoding="utf-8").splitlines()
for start,end in [(170,205),(205,250),(290,335),(335,390)]:
    print("\n# ---",start,"-",end,"---")
    for i in range(start-1,min(end,len(lines))):
        print(f"{i+1:4d}: {lines[i]}")
PY

python - <<'PY'
from pathlib import Path
p = Path("src/research_engine/cost_model.py")
lines = p.read_text(encoding="utf-8").splitlines()
for start,end in [(240,330),(330,420),(420,510)]:
    print("\n# ---",start,"-",end,"---")
    for i in range(start-1,min(end,len(lines))):
        print(f"{i+1:4d}: {lines[i]}")
PY

rg -n "operator.*matmul|train_from_databases|split\\(\\\":\\\",\\s*2\\)" -S src/research_engine/cost_model.py scripts/cold_shape_cross_run_ablation_v2.py

Repository: 0sec-labs/noeris

Length of output: 15796


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n "raw_records|records\s*=|\.noeris|json\.load|json\.loads|heldout_keys|bucket:hardware" scripts/cold_shape_cross_run_ablation_v2.py

python - <<'PY'
from pathlib import Path
p = Path("scripts/cold_shape_cross_run_ablation_v2.py")
lines = p.read_text(encoding="utf-8").splitlines()
for start,end in [(1,140),(140,240),(240,340),(340,440),(440,560),(560,760)]:
    print(f"\n# --- {start}-{end} ---")
    for i in range(start-1, min(end, len(lines))):
        print(f"{i+1:4d}: {lines[i]}")
PY

Repository: 0sec-labs/noeris

Length of output: 31633


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n "cost-model-training\.json" -S . || true
rg -n "cold_shape_cross_run_ablation_v2|build_report\\(" -S scripts src || true

# find any scripts that generate ".noeris/cost-model-training.json"
fd -e py -e sh -e js -e ts .noeris -S . || true
fd -e py .noeris -S . || true

# Find where ".noeris" directory is populated
rg -n "\\.noeris" -S scripts src README.md .github || true

Repository: 0sec-labs/noeris

Length of output: 8682


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n "cost-model-training\.json" -S . || true
rg -n "cost[-_ ]model[-_ ]training" -S . || true
rg -n "\\.noeris" -S scripts src README.md .github || true | head -n 200

Repository: 0sec-labs/noeris

Length of output: 12458


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect collect_cost_model_data.py around how record keys are written
rg -n "bucket:hardware|operator:bucket:hardware|split\\(\":\",\\s*2\\)|\"matmul\"|records\\[" scripts/collect_cost_model_data.py scripts/train_cost_model_v2.py scripts/train_cost_model_v2.py tests/test_cold_shape_cross_run_ablation_v2.py src/research_engine/cost_model.py || true

python - <<'PY'
from pathlib import Path
paths = [
  Path("scripts/collect_cost_model_data.py"),
  Path("scripts/train_cost_model_v2.py"),
  Path("tests/test_cold_shape_cross_run_ablation_v2.py"),
]
for p in paths:
  if not p.exists(): 
    continue
  print("\n====", p, "====")
  txt = p.read_text(encoding="utf-8").splitlines()
  # print relevant regions around "records" or "key"
  for i,line in enumerate(txt, start=1):
    if "records" in line and ("output" in line or "json" in line or "=" in line):
      pass
  # just print first 180 lines for those small files
  max_lines = 220
  for i in range(1, min(max_lines, len(txt))+1):
    print(f"{i:4d}: {txt[i-1]}")
PY

Repository: 0sec-labs/noeris

Length of output: 19684


🏁 Script executed:

#!/bin/bash
set -euo pipefail

targets=(
  "scripts/collect_cost_model_data.py"
  "scripts/train_cost_model_v2.py"
  "tests/test_cold_shape_cross_run_ablation_v2.py"
)
for f in "${targets[@]}"; do
  echo "== $f =="
  rg -n "bucket:hardware|operator:bucket:hardware|records|split\\(\"\":\"\",\\s*2\\)|matmul|cost-model-training\\.json|_split_record_key" "$f" || true
done

python - <<'PY'
from pathlib import Path
import re
def show_section(path, pattern, context=5, max_lines=120):
    p=Path(path)
    lines=p.read_text(encoding="utf-8").splitlines()
    for i,line in enumerate(lines, start=1):
        if re.search(pattern,line):
            start=max(1,i-context)
            end=min(len(lines), i+context)
            print(f"\n--- {path}:{start}-{end} (match at {i}) ---")
            for j in range(start,end+1):
                print(f"{j:4d}: {lines[j-1]}")
            if end-start>max_lines: 
                break

show_section("scripts/collect_cost_model_data.py", r"records", context=8)
show_section("scripts/collect_cost_model_data.py", r"matmul", context=12)
show_section("scripts/train_cost_model_v2.py", r"records", context=8)
show_section("tests/test_cold_shape_cross_run_ablation_v2.py", r"cold_shape_cross_run_ablation_v2|split|legacy|bucket", context=15)
PY

Repository: 0sec-labs/noeris

Length of output: 17234


🏁 Script executed:

#!/bin/bash
set -euo pipefail

targets=(
  "scripts/collect_cost_model_data.py"
  "scripts/train_cost_model_v2.py"
  "tests/test_cold_shape_cross_run_ablation_v2.py"
)
for f in "${targets[@]}"; do
  echo "== $f =="
  rg -n "bucket:hardware|operator:bucket:hardware|records|split\\(\\\":\\\",\\s*2\\)|matmul|cost-model-training\\.json|_split_record_key" "$f" || true
done

python - <<'PY'
from pathlib import Path
import re

def show_section(path, pattern, context=6, max_groups=6):
    p=Path(path)
    lines=p.read_text(encoding="utf-8").splitlines()
    count=0
    for i,line in enumerate(lines, start=1):
        if re.search(pattern,line):
            start=max(1,i-context)
            end=min(len(lines), i+context)
            print(f"\n--- {path}:{start}-{end} (match at {i}) ---")
            for j in range(start,end+1):
                print(f"{j:4d}: {lines[j-1]}")
            count+=1
            if count>=max_groups:
                return

show_section("scripts/collect_cost_model_data.py", r"records", context=8)
show_section("scripts/collect_cost_model_data.py", r"matmul", context=12)
show_section("scripts/train_cost_model_v2.py", r"records", context=10)
show_section("tests/test_cold_shape_cross_run_ablation_v2.py", r"legacy|bucket|split|_split_record_key|cost-model-training\\.json", context=15)
PY

Repository: 0sec-labs/noeris

Length of output: 15037


🏁 Script executed:

#!/bin/bash
set -euo pipefail

targets=(
  "scripts/collect_cost_model_data.py"
  "scripts/train_cost_model_v2.py"
  "tests/test_cold_shape_cross_run_ablation_v2.py"
)
for f in "${targets[@]}"; do
  echo "== $f =="
  rg -n "bucket:hardware|operator:bucket:hardware|records|split\\(\\\":\\\",\\s*2\\)|matmul|cost-model-training\\.json|_split_record_key" "$f" || true
done

python - <<'PY'
from pathlib import Path
import re

def show_section(path, pattern, context=6, max_groups=6):
    p=Path(path)
    lines=p.read_text(encoding="utf-8").splitlines()
    count=0
    for i,line in enumerate(lines, start=1):
        if re.search(pattern,line):
            start=max(1,i-context)
            end=min(len(lines), i+context)
            print(f"\n--- {path}:{start}-{end} (match at {i}) ---")
            for j in range(start,end+1):
                print(f"{j:4d}: {lines[j-1]}")
            count+=1
            if count>=max_groups:
                return

show_section("scripts/collect_cost_model_data.py", r"records", context=8)
show_section("scripts/collect_cost_model_data.py", r"matmul", context=12)
show_section("scripts/train_cost_model_v2.py", r"records", context=10)
show_section("tests/test_cold_shape_cross_run_ablation_v2.py", r"legacy|bucket|split|_split_record_key|cost-model-training\\.json", context=15)
PY

Repository: 0sec-labs/noeris

Length of output: 15037


🏁 Script executed:

python - <<'PY'
import json
from pathlib import Path
p = Path(".noeris/cost-model-training.json")
data = json.loads(p.read_text(encoding="utf-8"))
keys = list(data.get("records", {}).keys())
legacy = [k for k in keys if len(k.split(":", 2)) == 2]
print("legacy_two_part_keys=", len(legacy))
PY

Repository: 0sec-labs/noeris

Length of output: 84


🏁 Script executed:

python - <<'PY'
import json
from pathlib import Path
data = json.loads(Path(".noeris/cost-model-training.json").read_text(encoding="utf-8"))
legacy = [k for k in data.get("records", {}).keys() if len(k.split(":", 2)) == 2]
print("legacy_two_part_keys=", len(legacy))
PY

Repository: 0sec-labs/noeris

Length of output: 84


🏁 Script executed:

python - <<'PY'
import json
from pathlib import Path
data = json.loads(Path(".noeris/cost-model-training.json").read_text(encoding="utf-8"))
legacy = [k for k in data.get("records", {}).keys() if len(k.split(":", 2)) == 2]
print("legacy_two_part_keys=", len(legacy))
PY

Repository: 0sec-labs/noeris

Length of output: 84


Add backward-compatible parsing for legacy bucket:hardware record keys in _split_record_key

src/research_engine/cost_model.py::CostModel.train_from_databases() supports legacy 2-part record keys (bucket:hardware, treated as operator="matmul"), but scripts/cold_shape_cross_run_ablation_v2.py::_split_record_key() only accepts operator:bucket:hardware and returns None for 2-part keys—so those rows would be skipped during heldout selection, training DB construction, kNN/seed scoring, and replay for older databases. The checked-in .noeris/cost-model-training.json currently has legacy_two_part_keys=0, so the default artifact/tests aren’t affected.

Suggested fix
 def _split_record_key(key: str) -> tuple[str, str, str] | None:
     parts = key.split(":", 2)
-    if len(parts) != 3:
-        return None
-    return parts[0], parts[1], parts[2]
+    if len(parts) == 3:
+        return parts[0], parts[1], parts[2]
+    if len(parts) == 2:
+        bucket, hardware = parts
+        return "matmul", bucket, hardware
+    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 `@scripts/cold_shape_cross_run_ablation_v2.py` around lines 187 - 191,
_split_record_key currently rejects 2-part legacy keys and returns None; update
it to accept keys split into 2 parts by ":" and return operator="matmul" with
bucket and hardware (i.e., for len(parts)==2 return ("matmul", parts[0],
parts[1])) while keeping the existing len==3 behavior and returning None
otherwise so legacy `bucket:hardware` rows are included in heldout selection,
training DB construction, kNN/seed scoring, and replay.

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.

[Paper] Run cold-shape cross-run learning ablation v2

1 participant