feat(daemon): standalone checkpoint loop + dashboard rework (#505)#511
Merged
Conversation
Daemon — new CheckpointLoop (issue #505) OLAS-style staking requires someone to call checkpoint() on the proxy to advance tsCheckpoint. The existing reward-claim loop only calls checkpointAndClaim when calculateStakingReward > 0; if liveness is already failing because the activity window is too wide, that gate never opens and the cycle stays stuck until eviction. The new CheckpointLoop fires bare checkpoint() on each unique staked proxy at livenessPeriod cadence (default 300_000 ms, env JINN_CHECKPOINT_INTERVAL_MS), independent of pending reward. Master EOA signs; checkpoint() is permissionless so no Safe execTransaction. Store — SQLite NOT NULL fix on artifacts.desired_state_id Legacy DBs predating Task-native IDs defined desired_state_id as NOT NULL. Newer insertArtifact only writes task_id, which made post-success delivery writes revert with "NOT NULL constraint failed: artifacts.desired_state_id" — and mis-flagged completed deliveries as FAILED in the dashboard while the on-chain side was fine. SQLite can't ALTER COLUMN to drop the constraint, so Store now detects the legacy column at startup and mirrors task_id into it on insert. Dashboard — Activity table - Swap Run / Task column order (Run first). - Rename state badge "pending" → "active". - Remove the 50-row + 360px scroll clip so all rows are visible. - Filter "never engaged" FAILED rows: runStartedAt=null OR failureReason matches "not ready" / "not enabled". Catches expired evaluator opportunities and harness-not-enabled rows; keeps real failures (interrupted runs, real impl errors) visible. - Single-SolverNet operators see all rows regardless of manifestCid — previously the delivery manifest CID didn't match the SolverNet manifest CID, silently dropping COMPLETE rows. Dashboard — Wallet card - Wire the existing claimedStakingRewardsWei field from /v1/status into the CLAIMED widget; was reading a non-existent field name and defaulting to '0'. - Add a Service field (e.g. #50) under Identity alongside Agent / Master / Safe, so operators can quote their on-chain service id without digging through `jinn status`. Tests - 6-test CheckpointLoop suite (per-proxy dedup, skip-not-staked, per-call error isolation, intervalMs=0 no-op). - ActivityCard tests cover the new filter (both "never engaged" signatures + a real-failure keep case) and the active-badge label. - WalletCard service-identity fixture updated. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…uriakova-5faeb0 # Conflicts: # client/src/dashboard/spa/src/pages/Overview.tsx
This was referenced May 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Run-mode
FEATURE
Context
Closes #505 — operator nodes on realistic cadence (≥1 novel solution per
livenessPeriod) were silently failing every L2 staking checkpoint because the activity window stayed open indefinitely. The existingRewardClaimLooponly firescheckpointAndClaimwhencalculateStakingReward > 0, butcalculateStakingRewardreturns 0 when liveness is already failing — chicken-and-egg until manual intervention or eviction.Same session surfaced a SQLite NOT NULL constraint that was mis-flagging successful deliveries as FAILED in the dashboard (on-chain deliveries succeeded, local store insert reverted), plus a chain of dashboard cleanups around the Activity table and Wallet card that operators asked for live during the test session.
Summary of changes
Daemon — new
CheckpointLoop(client/src/daemon/checkpoint-loop.ts)checkpoint()on each unique staked proxy atlivenessPeriodcadence.checkpointIntervalMs(default300_000), envJINN_CHECKPOINT_INTERVAL_MS.stakingMode === 'standard'. Master EOA signs (permissionless call, no Safe execTransaction).Store —
artifacts.desired_state_idNOT NULL fix (client/src/store/store.ts)desired_state_idas NOT NULL. Newer code only writestask_id, which made post-success delivery writes revert withNOT NULL constraint failed: artifacts.desired_state_id, mis-flagging the dashboard row as FAILED.Storenow detects the legacy column at startup (hasLegacyDesiredStateId) and mirrorstask_idinto it on insert.Dashboard — Activity table (
ActivityCard.tsx)pending→active.runStartedAt === nullORfailureReasonmatches "not ready" / "not enabled". Catches expired evaluator opportunities and harness-not-enabled rows; keeps real failures visible.manifestCid— previously the delivery manifest CID didn't match the SolverNet manifest CID, silently dropping every COMPLETE row.Dashboard — Wallet card (
WalletCard.tsx,Overview.tsx)rewards.claimedStakingRewardsWeifield through to the CLAIMED widget (was reading a non-existentclaimedJinnLifetimeand defaulting to0).#50) under Identity alongside Agent / Master / Safe, so operators can quote their on-chain service id without digging throughjinn status.Tests
CheckpointLoopsuite (6 tests): per-proxy dedup, skip non-staked services, per-call error isolation,intervalMs=0no-op.ActivityCard.test.tsxupdated foractivelabel + new filter behavior (both "never engaged" signatures + a real-failure keep case).WalletCard.test.tsxfixture updated for the newserviceIdfield onServiceIdentity.Acceptance
CheckpointLoopticks everylivenessPeriodand is gated by config.intervalMs = 0.activefor in-flight state.claimedStakingRewardsWeitotal; Identity panel shows on-chain Service#id.vitest runclean forcheckpoint-loop,ActivityCard,WalletCardsuites.Out of scope
CLAIMABLE/CLAIMEDwidgets still surface L2 reward queue values rather than real L1 distributor balance. Honest fix needs a JinnDistributor read or an L1-balance widget rename.jinn harnesses enable swe-rebench-v2-evaluator" UX gap remains.RewardClaimLoopandCheckpointLoopon the master EOA — the failure is non-fatal (loop logs and retries on next tick) but warrants a follow-up to coordinate transactions or move the checkpoint call onto the Safe.Reference
contracts/src/staking/TaskActivityCheckerV3.sol(isRatioPass,recordSolutionDelivery)0x1e4d75598701fbbe6066b8275eb77f1854d8369f28268b1990d45436306e3a0ddistributor.claimcalls after the checkpoint reset (see operator daemon logs).🤖 Generated with Claude Code