Skip to content

fix(design): cold-start emit current epoch - #119

Merged
echobt merged 1 commit into
mainfrom
fix/design-emit-cold-start
Aug 10, 2026
Merged

fix(design): cold-start emit current epoch#119
echobt merged 1 commit into
mainfrom
fix/design-emit-cold-start

Conversation

@echobt

@echobtechobt commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Summary

  • After design-challenge restart, emitted_epoch resets to 0 and catch-up tried epoch 1 with a pruned pin_block, failing every tick (SubnetOwnerHotkey not found).
  • Cold start (last_emitted == 0) now emits the current epoch immediately; catch-up is capped to 16 epochs (Finney prune window).

Why

Blocks D24 seal for current epochs (Prism 24424 submitter WTA ready; design missing → incomplete_participant_set). Restores permanent emit path after digests land.

Test plan

  • cargo test -p design-challenge-task -p design-challenge --lib -- emit_plan
  • Deploy design-challenge digest to prod; confirm design leaf set submitted for live epoch
  • Seal → /v1/weights/latest advances with Prism weight on best-BPB submitter (not uid0 burn)

Summary by CodeRabbit

  • Bug Fixes
    • Improved restart behavior by emitting the current epoch immediately.
    • Limited catch-up processing to a recent 16-epoch window, preventing attempts to access unavailable older blocks.
    • Preserved the current pin block during cold starts.

After deploy the in-process emitted_epoch cursor resets to 0; catch-up
from epoch 1 pins a pruned block and fails forever. Emit the live
epoch immediately on cold start and cap catch-up to the prune window.
@coderabbitai

coderabbitaiBot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

design_emit_plan now emits the current epoch on cold start and limits skipped-epoch recovery to a 16-epoch window. Tests verify the current epoch and pin block for both cold starts and large catch-up gaps.

Changes

Epoch emission recovery

Layer / File(s)Summary
Cold-start and bounded catch-up emission
crates/design-challenge-task/src/emit.rs, crates/design-challenge/src/lib.rs
design_emit_plan emits the current epoch when last_emitted is zero. Skipped-epoch recovery is capped at 16 epochs. Tests verify the emitted epoch and pin block.

Estimated code review effort: 2 (Simple) | ~15 minutes

Possibly related PRs

  • BaseIntelligence/base#71: Both PRs modify epoch emission behavior, but this PR adds cold-start and bounded catch-up handling.
  • BaseIntelligence/base#116: This PR extends the related design_emit_plan catch-up logic with cold-start handling and a 16-epoch cap.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title clearly and concisely describes the primary cold-start emission change.
Docstring Coverage✅ PassedDocstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
✨ 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 fix/design-emit-cold-start

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.

@coderabbitaicoderabbitaiBot 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: 2

🤖 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 `@crates/design-challenge-task/src/emit.rs`:
- Around line 54-62: Update the catch-up calculation in the emission logic
around MAX_CATCHUP_EPOCHS so epochs_back is also bounded by the supported
pin-block retention divided by tempo. When tempo exceeds the retention age,
avoid selecting a historical epoch; otherwise ensure
current_last_epoch_block.saturating_sub(epochs_back.saturating_mul(tempo)) stays
within the retention limit, and revise the cap test to assert this block-age
invariant.
- Around line 103-120: The emit-plan tests in
crates/design-challenge-task/src/emit.rs:103-120 and the related challenge test
coverage in crates/design-challenge/src/lib.rs:87-97 need end-to-end submission
tests. Add integration coverage for both cold-start and bounded-recovery plans,
exercising intake, failure probes, challenge validation, exact-E leaf emission,
POST /v1/weights/raw, sealing, and GET /v1/weights/latest, asserting the latest
response has sealed: true; retain the existing plan-field assertions.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9c6fec53-1c8f-4e4b-a753-29a5b8eff245

📥 Commits

Reviewing files that changed from the base of the PR and between 1237891 and 967bb08.

📒 Files selected for processing (2)
  • crates/design-challenge-task/src/emit.rs
  • crates/design-challenge/src/lib.rs

Comment on lines 54 to 62
if last_emitted + 1 < current_epoch {
let target = last_emitted + 1;
let gap = current_epoch.saturating_sub(last_emitted);
let target = if gap > MAX_CATCHUP_EPOCHS {
current_epoch.saturating_sub(MAX_CATCHUP_EPOCHS)
} else {
last_emitted + 1
};
let epochs_back = current_epoch.saturating_sub(target);
let pin_block = current_last_epoch_block.saturating_sub(epochs_back.saturating_mul(tempo));

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 | 🟠 Major | ⚡ Quick win

Calculate the catch-up limit from block retention.

MAX_CATCHUP_EPOCHS does not bound the age of pin_block. With the new test value tempo = 360, current_epoch - 16 produces a pin block 5,760 blocks old. This exceeds the approximately 256-block retention stated at line 19, so the RPC can still reject the planned emission.

Cap epochs_back by the supported pin-block age divided by tempo. If one epoch exceeds that age, do not select a historical epoch. Update the cap test to enforce the block-age invariant.

🤖 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 `@crates/design-challenge-task/src/emit.rs` around lines 54 - 62, Update the
catch-up calculation in the emission logic around MAX_CATCHUP_EPOCHS so
epochs_back is also bounded by the supported pin-block retention divided by
tempo. When tempo exceeds the retention age, avoid selecting a historical epoch;
otherwise ensure
current_last_epoch_block.saturating_sub(epochs_back.saturating_mul(tempo)) stays
within the retention limit, and revise the cap test to assert this block-age
invariant.

Comment on lines +103 to +120
#[test]
fn emit_plan_cold_start_emits_current_immediately() {
let p = design_emit_plan(0, 24424, 10, 360, 8_816_047).unwrap();
assert_eq!(
p,
DesignEmitPlan {
epoch: 24424,
pin_block: 8_816_047
}
);
}

#[test]
fn emit_plan_caps_catchup_to_prune_window() {
let p = design_emit_plan(100, 24424, 10, 360, 8_816_047).unwrap();
assert_eq!(p.epoch, 24424 - 16);
assert_eq!(p.pin_block, 8_816_047 - 16 * 360);
}

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bashset -eu
printf'%s\n''--- file inventory ---'
git ls-files 'crates/design-challenge-task/src/emit.rs''crates/design-challenge/src/lib.rs''crates/design-challenge*'| sed -n '1,160p'printf'%s\n''--- outlines ---'
ast-grep outline crates/design-challenge-task/src/emit.rs --lang rust 2>/dev/null | sed -n '1,220p'
ast-grep outline crates/design-challenge/src/lib.rs --lang rust 2>/dev/null | sed -n '1,220p'printf'%s\n''--- relevant symbols and assertions ---'
rg -n -C 3 \
'design_emit_plan|DesignEmitPlan|emit_plan|sealed|seal|raw weight|raw_weight|leaf|failure probe|challenge-specific|intake|submit' \
crates/design-challenge-task/src/emit.rs \
crates/design-challenge/src/lib.rs \
crates/design-challenge-task \
crates/design-challenge \
2>/dev/null | sed -n '1,320p'

Repository: BaseIntelligence/base

Length of output: 24732


🏁 Script executed:

#!/bin/bashset -eu
forfin \
crates/design-challenge/tests/e2e_sim.rs \
crates/design-challenge/src/orchestrator.rs \
crates/design-challenge/src/host_sim.rs \
crates/design-challenge/src/lib.rs
doif [ -f"$f" ];thenprintf'\n--- %s (%s lines) ---\n'"$f""$(wc -l <"$f")"
ast-grep outline "$f" --lang rust 2>/dev/null | sed -n '1,260p'fidoneprintf'\n--- test names and flow terms ---\n'
rg -n -C 4 \
'#\[test\]|#\[tokio::test\]|failure|probe|intake|validate|leaf|weight|seal|sealed|emit_signed_leaf_set|submit_signed_leaf_set|GatewayClient' \
crates/design-challenge/tests crates/design-challenge/src crates/challenge-common \
2>/dev/null | sed -n '1,520p'printf'\n--- shared helper locations ---\n'
rg -n -C 3 \
'pub (async )?fn (emit_signed_leaf_set|submit_signed_leaf_set)|struct GatewayClient|fn seal|sealed' \
crates 2>/dev/null | sed -n '1,360p'

Repository: BaseIntelligence/base

Length of output: 50377


🏁 Script executed:

#!/bin/bashset -eu
printf'%s\n''--- e2e_sim.rs ---'
cat -n crates/design-challenge/tests/e2e_sim.rs
printf'%s\n''--- orchestrator emitter and execution ranges ---'
sed -n '500,760p' crates/design-challenge/src/orchestrator.rs | nl -ba
sed -n '760,960p' crates/design-challenge/src/orchestrator.rs | nl -ba
sed -n '960,1110p' crates/design-challenge/src/orchestrator.rs | nl -ba
printf'%s\n''--- shared submit implementation and tests ---'
cat -n crates/challenge-common/src/submit.rs | sed -n '1,360p'printf'%s\n''--- leaf emit implementation and tests ---'
cat -n crates/challenge-common/src/leaf_emit.rs | sed -n '1,260p'printf'%s\n''--- gateway sealer routes and tests ---'
rg -n -C 8 \
'Router|route|seal|sealed|raw|weight|test|#\[tokio::test\]|#\[test\]' \
crates/gateway/src/sealer.rs crates/gateway/src/api.rs crates/gateway/tests \
2>/dev/null | sed -n '1,520p'printf'%s\n''--- challenge flow markers in tests ---'
python3 - <<'PY'from pathlib import Pathfiles = list(Path("crates/design-challenge").rglob("*.rs"))terms = ("failure", "probe", "intake", "validate", "emit_signed_leaf_set", "submit_signed_leaf_set", "raw", "seal", "sealed")for p in files: text = p.read_text() hits = [t for t in terms if t in text.lower()] if hits: print(f"{p}: {', '.join(hits)}")PY

Repository: BaseIntelligence/base

Length of output: 4807


🏁 Script executed:

#!/bin/bashset -eu
printf'%s\n''--- orchestrator emitter methods ---'
sed -n '700,930p' crates/design-challenge/src/orchestrator.rs
sed -n '930,1110p' crates/design-challenge/src/orchestrator.rs
printf'%s\n''--- submit API ---'
sed -n '1,340p' crates/challenge-common/src/submit.rs
printf'%s\n''--- leaf emit API ---'
sed -n '1,180p' crates/challenge-common/src/leaf_emit.rs
printf'%s\n''--- sealer relevant symbols ---'
rg -n -C 6 \
'pub fn|pub async fn|Router|route|seal|sealed|raw|weight|#\[test\]|#\[tokio::test\]' \
crates/gateway/src/sealer.rs crates/gateway/src/api.rs crates/gateway/tests 2>/dev/null | sed -n '1,500p'printf'%s\n''--- all test source flow markers ---'
rg -n -C 2 \
'emit_signed_leaf_set|submit_signed_leaf_set|sealed\s*[:=]|sealed.*true|seal_epoch|seal|raw_weights|raw weight|failure probe|failure_probe|challenge.*valid|validate.*challenge' \
crates/*/tests crates/*/src 2>/dev/null | sed -n '1,500p'printf'%s\n''--- source-level verifier ---'
python3 - <<'PY'from pathlib import Pathroots = [Path("crates/design-challenge"), Path("crates/challenge-common"), Path("crates/gateway")]files = [p for root in roots for p in root.rglob("*.rs")]required = { "intake": ("insert_harness", "insert_run", "GatewayClient"), "failure probes": ("failure", "reject", "invalid"), "challenge validation": ("validate_bundle", "challenge_id", "verify"), "leaf emission": ("emit_signed_leaf_set", "make_signed_leaf"), "raw weight submission": ("submit_signed_leaf_set", "RawWeight"), "sealing": ("seal", "sealed"), "sealed true assertion": ("sealed: true", "sealed == true", "assert!(sealed"),}for p in files: text = p.read_text() lower = text.lower() hits = [name for name, needles in required.items() if any(n.lower() in lower for n in needles)] if hits: print(f"{p}: {', '.join(hits)}")PY

Repository: BaseIntelligence/base

Length of output: 50377


🏁 Script executed:

#!/bin/bashset -eu
printf'%s\n''--- gateway files ---'
git ls-files 'crates/gateway'| sed -n '1,240p'printf'%s\n''--- seal and raw-weight endpoints across gateway ---'
rg -n -C 5 \
'seal_epoch|admin.*seal|/v1/admin|weights/raw|post_raw|RawWeight|sealed|build_latest|build_burn_fallback' \
crates/gateway --glob '*.rs'| sed -n '1,620p'printf'%s\n''--- exact flow assertions in tests ---'
rg -n -C 5 \
'#\[test\]|#\[tokio::test\]|assert[^;]*(202|409|sealed|true|raw|seal)|failure|probe|invalid|reject|challenge_id|emit_signed_leaf_set|submit_signed_leaf_set' \
crates/gateway crates/challenge-common crates/design-challenge \
--glob '*test*.rs' --glob 'tests/*.rs' --glob '*.rs'| sed -n '1,700p'printf'%s\n''--- focused source-level test verifier ---'
python3 - <<'PY'from pathlib import Pathroots = [Path("crates/gateway"), Path("crates/challenge-common"), Path("crates/design-challenge")]for p in sorted({p for root in roots for p in root.rglob("*.rs")}): text = p.read_text() if "#[test]" not in text and "#[tokio::test]" not in text: continue low = text.lower() groups = { "intake": ["insert_harness", "insert_run", "post(\"/v1", "router"], "failure probes": ["failure", "probe", "invalid", "reject"], "challenge validation": ["validate_bundle", "challenge_id", "verify"], "leaf emission": ["emit_signed_leaf_set", "make_signed_leaf"], "raw submission": ["submit_signed_leaf_set", "/v1/weights/raw"], "sealing": ["seal_epoch", "admin/seal", "build_sealed_bundle"], "sealed assertion": ["sealed: true", '"sealed": true', "sealed == true"], } present = [name for name, needles in groups.items() if any(n.lower() in low for n in needles)] if present: print(f"{p}: {'; '.join(present)}")PY

Repository: BaseIntelligence/base

Length of output: 50377


Add an end-to-end challenge submission test.

These tests assert only DesignEmitPlan fields. Add integration coverage for both cold-start and bounded-recovery plans through intake, failure probes, challenge validation, exact-E leaf emission, POST /v1/weights/raw, sealing, and GET /v1/weights/latest with sealed: true. Existing tests stop at sandbox execution, sanitization, and scoring.

📍 Affects 2 files
  • crates/design-challenge-task/src/emit.rs#L103-L120 (this comment)
  • crates/design-challenge/src/lib.rs#L87-L97
🤖 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 `@crates/design-challenge-task/src/emit.rs` around lines 103 - 120, The
emit-plan tests in crates/design-challenge-task/src/emit.rs:103-120 and the
related challenge test coverage in crates/design-challenge/src/lib.rs:87-97 need
end-to-end submission tests. Add integration coverage for both cold-start and
bounded-recovery plans, exercising intake, failure probes, challenge validation,
exact-E leaf emission, POST /v1/weights/raw, sealing, and GET
/v1/weights/latest, asserting the latest response has sealed: true; retain the
existing plan-field assertions.

Source: Coding guidelines

@echobt
echobt merged commit ba69d98 into mainAug 10, 2026
3 checks passed
Sign up for freeto 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

@echobt