---
title: Freeze derived final_block_at once the block has convened
type: task
status: planned
description: >-
  The derived final_block_at recedes two minutes per signing and drives the live/election sawtooth;
  ruled 2026-10-09 to freeze it at convene in a new nullable seasons column, read after the
  commissioner pin. Planned, to ship before the 2027 FA period.
base_uri: user:task/league/freeze-derived-final-block-at-once-convened.md
created_at: '2026-09-07T22:09:20.384Z'
entity_id: a767a7e2-bdaa-4f9b-8744-14a4206d23c0
observations:
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
owner_identity_uri: █████████████████████████
priority: Low
public_read: true
relations:
  - relates [[user:task/league/fix-auction-nomination-mode-flip-interleaving.md]]
  - relates [[█████████████████████-███████-█████-█████-████████████]]
tags:
  - user:tag/league-xo-football.md
updated_at: '2026-10-09T18:21:32.191Z'
visibility_analyzed_at: '2026-11-05T23:49:31.007Z'
---

## Problem

`final_block_at` (the derived path) is recomputed on demand and never stored, and it RECEDES two minutes per signing (`period_end - spots_remaining * 2min - 3h`), which is what makes the live/election sawtooth oscillate all through the final block. A pinned override sidesteps this for one league but does not fix the mechanism.

The investigator's proposal: once the block has convened, `final_block_at` should stop moving — freeze the value that took the block live, even if it is derived, instead of letting each signing chase it later. That would end the oscillation for every league at once, and with it the per-final-block mode churn this entire queue of findings rides on (nomination-timer interleaving, pending-election latches, spot-count-driven election stints).

## Evidence

- `repository/active/league/docs/guides/auction.md` — the derived formula and the reason it recedes.
- League 119 on 2026-09-07: derived path spent about 3.5 minutes per signing in election mode with its nomination clock cleared, because each signing pushed `final_block_at` past `now`.

## Plan

Ruled 2026-10-09: persist the frozen value in a new nullable `seasons` column; no in-process memo, no reuse of `auction_final_block_at`, no backfill. Ship before the 2027 free-agency period. All items land in one commit in `repository/active/league`.

Defaults for the two open sub-questions, taken unless the implementer finds a reason against:

- Freeze the derived value at the moment it first reaches `now`, not the instant of the poll that observed it.
- A commissioner pin set after convene overrides the frozen value.

- [ ] Add the nullable column `seasons.auction_final_block_convened_at` (DDL plus schema export). Verify: the column exists, null for every existing row.
- [ ] In `get_auction_final_block` (`libs-server/auction-final-block.mjs`), write the derived time once — `UPDATE ... WHERE auction_final_block_convened_at IS NULL` — the first time it is `<= now` within the period. Verify: a second call does not rewrite it, and concurrent calls leave one value.
- [ ] Read order inside the wrapper: commissioner pin (`auction_final_block_at`), then frozen, then derived. Verify: a signing after convene no longer moves the value, a spot freed early cannot pull it earlier, and a post-convene pin wins.
- [ ] Route `scripts/generate-tag-board.mjs` through the wrapper instead of its own derivation. Verify: grep finds no derivation of final-block time outside `auction-final-block.mjs`.
- [ ] Rewrite the docs in the same commit: `docs/guides/auction.md` around line 419 and lines ~427-429, `docs/guides/ship.md:173`, and the `auction-final-block.mjs:150-156` docstring. Verify: none still describes the derived value as receding after convene.
- [ ] Confirm on a derived-path league that the live/election mode poll stops oscillating through a final block.

## Related

- `user:task/league/fix-auction-nomination-mode-flip-interleaving.md` — the oscillation is the surface its race rides on.
