The cutover: finished becomes a Series fact, and the Lane's poll gate is rewritten with it #157
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Part of #136.
Blocked by: none — can start immediately.
What to build
One landing that moves the poll gate from the per-Reader finished bucket to a Series-owned flag, and deletes the bucket's write paths in the same moment. After it lands, the Lane polls exactly the set it polled yesterday (the migration seeds from the buckets before flipping them), the API refuses
finishedlike any other invalid status, no surface can create the bucket anymore, and the decision is recorded as an ADR because the migration is one-way.Acceptance criteria
status: finishedwith the same plain 400 as any invalid value — no special message, no special case.Landed on
spec-136as ffb7d69.All 12 acceptance criteria met.
ALTER TABLE series ADD finished_at, seed from the pre-flip finished buckets (mirrors the old due gate exactly: not finished while any bookmark is outside the bucket), then flip every finished bookmark to archived — column, seed, flip, load-bearing order commented in the file.TestMigration0016SeedsFinishedAtBeforeFlippingBucket: seeds a 0015-era schema (finished buckets, no column), runs 0016, asserts done/shared stamped now-ish and archived; mixed (one reader finished, one archived) not stamped; live and orphan untouched. Would fail with the two data statements reordered.series.finished_at;force_poll_atoverrides the flag;finished_atjoins the grouping; the finished-only HAVING arm is gone from both Lane queries, and the eligible count is now a single WHERE over the Series rows.EligibleSeriesCount(issue #157).nothing-eligiblepass row sleeping a full rest, not a stall (existingSkipNothingEligiblepath, test in latest/poller_test.go).finished_atoutside the migration;TestForcedSeriesSelfClearsOnFailedAttempt+TestDueForLatestCheckForcedOverridesFinishedFlagguard the force side.TestDueForLatestCheckSkipsFinishedKeepsArchived).StatusFinishedconstant and the three-state doc comment are gone; validation admitsreading | archived.PUT /bookmarks/{key}answersfinishedwith the plain invalid-status 400 (TestPutStatusValidation).buildListView,uiStatus; dead.finishCSS, the--mosstoken and filter.js branches removed; web tests rewritten to the two buckets.archived > reading; finished filters/comments removed; 66/66 logic tests pass.go vet ./...clean;go test ./...green (store/latest/root re-run with -count=1).No file/Discord/SSH code touched.
Review round (cr-spec + cr-standards on ffb7d69) — findings fixed and amended into 43ca043.
Fixed:
.actions .play { color: var(--paper); }— collateral of the finish-rule sweep; the Continue-reading icon had dropped to idle grey..confirm-row.calmbackground/span rules — the archive confirm was silently rendered with the remove's danger wash.--clay: #7c5533— same sweep had removed it along with--moss, dropping the pencil hover below the 3:1 icon threshold.#i-checksprite (only consumers were the removed finish badge/button).Store.SetFinishedAtreference (no such writer exists; the migration is the only writer) and the duplicated API paragraph.TestEligibleSeriesCountnow forces a Series and asserts the count stays unchanged — the eligible count's deliberate non-admission of forced rows is no longer comment-only.Verification:
go vet ./...clean;go test -count=1 ./...green.