Skip to content

fix(crown): anchor grid head on scoring watermark + 1h window#106

Merged
entrius merged 1 commit into
testfrom
fix/crown-grid-anchor-on-scoring-watermark
May 28, 2026
Merged

fix(crown): anchor grid head on scoring watermark + 1h window#106
entrius merged 1 commit into
testfrom
fix/crown-grid-anchor-on-scoring-watermark

Conversation

@anderdc
Copy link
Copy Markdown
Collaborator

@anderdc anderdc commented May 28, 2026

Problem

On the Crown History grid, the striped pending cell would sometimes strand on an interior block — sitting next to already-finalized blue cells — and stay stale across refreshes.

Root cause

The grid is drawn entirely from crown_holders, which the validator now writes directly up through crown_holders_max_block (#390 in allways). But the grid anchored its head — window snap, the "AS OF #…" label, and the pending-cell marker — on halt.asOfBlock, i.e. MAX(block_number) FROM contract_events (the event-indexer head).

Those two heads advance on independent pipelines. contract_events only ticks on commitments/swaps, while the validator keeps scoring every block. On a quiet network the crown watermark runs ahead of asOfBlock, so isCurrent = b === asOfBlock lands the stripe on a block that's already finalized (blue cells exist past it), and it doesn't move until a new on-chain event bumps asOfBlock.

Fix

Anchor the head on the crown data's own watermark via useScoringState().lastScoredBlock (= crown_holders_max_block), +1 for the live tip. The pending cell now always sits exactly one block past the last finalized data — it can never strand among finalized cells.

Also: 1h scoring cadence (300 blocks)

The validator's SCORING_WINDOW_BLOCKS is now 300 (~1h), not 600. Mirrored here:

  • SCORING_WINDOW_BLOCKS 600 → 300; RANGE_BLOCKS rebased on it (chips stay honest: 1h=300, 2h=600, 4h=1200)
  • the "scoring window" snap/label/window-pan behavior moved from the 2h chip to the 1h chip (one round = 300 blocks)
  • default crown range 2h1h (both pages); detail-page crownPan default 600 → 300
  • ScoreFactorsStrip copy "2-hour" → "1-hour"

Docs counterpart: entrius/allways-docs-ui#51.

Notes / to confirm

  • Custom-range cap mirrors SCORING_WINDOW_BLOCKS, so the max custom window is now 300 blocks (was 600). Faithful to the prior "caps at one scoring window" intent — flag if it should be decoupled.
  • The "AS OF #" counter + pending cell now advance in ~1h steps (one per scoring round) rather than ticking on every contract event — correct, since the marker and the grid data now share one clock. The live /crown widget still updates every forward step.

tsc -b and eslint pass.

The crown grid is drawn entirely from crown_holders, which the validator
writes directly up through crown_holders_max_block (PR #390). It was anchoring
the head — window snap, "as of" label, and the striped pending-cell marker —
on halt.asOfBlock (the contract_events head) instead. The two advance on
independent pipelines: on a quiet network the validator keeps scoring per block
while the event head stalls, so the pending stripe stranded on an
already-finalized interior block and went stale until the next event landed.

Anchor head on useScoringState().lastScoredBlock (+1 = live tip) so the pending
cell always sits one block past the last finalized data, never stranded.

Also mirror the validator's SCORING_WINDOW_BLOCKS 600 -> 300 (~1h): rebase
RANGE_BLOCKS, move the scoring-window snap/label/window-pan from the 2h chip to
the 1h chip, default crown range 2h -> 1h, and update the 2h -> 1h copy.
@entrius entrius merged commit b021c6d into test May 28, 2026
2 checks passed
@entrius entrius deleted the fix/crown-grid-anchor-on-scoring-watermark branch May 28, 2026 23:01
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.

2 participants