Latest Chapter provenance: what records that the number moved #131

Closed
opened 2026-08-20 21:19:11 +07:00 by sulthan · 1 comment
Owner

Part of #114

Question

Does anything record how a Series' Latest Chapter came to hold its present value, and if so
in what shape?

Graduated out of the map's fog by #127. The dependency that kept it unsharp is now answered:
#127 stores no failure streak and no history. poll_failures holds one row per currently
failing Series and the row is deleted on the next correct read, so it evidences nothing
about the machine side of the past — only about a failure that is still happening.

The hole, assembled from the closed tickets:

  • SetLatestChapter (store.go:1063) lowers the number unconditionally, and nothing records
    that it moved. #118 rejected a "went backwards" filter for exactly this reason: nothing
    stores the previous value, and a downward write is usually the correction
    (poller_test.go:481-497 asserts 400 -> 296).
  • #121's latest_corrected_at is deliberately transient: it means "the current value is a
    human's" and is erased by the next machine write. It records nothing about what happened.
  • #117's poll_passes is per Site, not per Series, and expires after 14 days — it would
    silently discard the one thing worth looking back on. #117 explicitly ruled the audit trail
    not subsumed, on grounds of different provenance (machine observation vs human action)
    and different retention instinct.
  • #120 makes a replaced Cover visible in the address itself (SHA-256 of the bytes), so the
    Cover half of this question may already be answered by construction.
  • A Forced Poll (#119) is self-evidencing while unserved: force_poll_at > latest_checked_at
    ages visibly. It stops evidencing anything the moment it is served.

To decide:

  • Whether the owner needs to look backwards at all, or whether "the current value and who owns
    it" is the whole requirement — in which case this closes as out of scope and the map keeps
    only #121's transient stamp.
  • If yes: what an entry records (previous value, new value, actor, cause), and whether a
    Reader's PUT (reportLatestChapter sends the site-read number up or down on every series
    page visit, store.go:864-867) is an actor worth recording or noise that would dominate the
    table.
  • Retention, and whether it may differ from #117's 14 days.
  • Whether this is admin-only reading, or a fact the Series detail page shows inline.
Part of #114 ## Question Does anything record *how* a Series' Latest Chapter came to hold its present value, and if so in what shape? Graduated out of the map's fog by #127. The dependency that kept it unsharp is now answered: #127 stores **no failure streak and no history**. `poll_failures` holds one row per currently failing Series and the row is **deleted** on the next correct read, so it evidences nothing about the machine side of the past — only about a failure that is still happening. The hole, assembled from the closed tickets: - `SetLatestChapter` (store.go:1063) lowers the number unconditionally, and nothing records that it moved. #118 rejected a "went backwards" filter for exactly this reason: nothing stores the previous value, and a downward write is usually the *correction* (poller_test.go:481-497 asserts 400 -> 296). - #121's `latest_corrected_at` is deliberately **transient**: it means "the current value is a human's" and is erased by the next machine write. It records nothing about what happened. - #117's `poll_passes` is per Site, not per Series, and expires after 14 days — it would silently discard the one thing worth looking back on. #117 explicitly ruled the audit trail **not** subsumed, on grounds of different provenance (machine observation vs human action) and different retention instinct. - #120 makes a replaced Cover visible in the address itself (SHA-256 of the bytes), so the Cover half of this question may already be answered by construction. - A Forced Poll (#119) is self-evidencing while unserved: `force_poll_at > latest_checked_at` ages visibly. It stops evidencing anything the moment it is served. To decide: - Whether the owner needs to look backwards at all, or whether "the current value and who owns it" is the whole requirement — in which case this closes as out of scope and the map keeps only #121's transient stamp. - If yes: what an entry records (previous value, new value, actor, cause), and whether a Reader's PUT (`reportLatestChapter` sends the site-read number up *or* down on every series page visit, store.go:864-867) is an actor worth recording or noise that would dominate the table. - Retention, and whether it may differ from #117's 14 days. - Whether this is admin-only reading, or a fact the Series detail page shows inline.
sulthan added the wayfinder:grilling label 2026-08-20 21:19:11 +07:00
sulthan self-assigned this 2026-08-21 13:33:30 +07:00
Author
Owner

Nothing records it, and nothing will. No history table, no attribution column, no migration 0018. The current number plus the actor class behind it is the whole requirement, and both are already derivable from state this map has decided.

The actor behind the present value, derived — three classes, not four:

  • Correction — latest_corrected_at <> 0 (#121, migration 0015). Means "the number on this row is a human's".
  • Sighting — latest_raised_by IS NOT NULL. A Reader's Sighting raised the number and no Poll has judged it yet; surfaced anonymously as #116's SightingRaised and #127's unverified.
  • Machine read — neither of the above, with latest_checked_at > 0.

Acquisition does not survive as a distinct actor. acquire.go:125 stamps latest_checked_at exactly as poller.go:428 does, so an acquired value and a polled value are indistinguishable the moment the Acquisition finishes. Accepted deliberately: the only case where the difference is actionable — acquired once and never read again — is already #116's unchecked filter. Telling the two apart would need a column, which is the thing this ticket declines to add.

Consequence for #121: latest_corrected_at is promoted from convenience to load-bearing. It is now the only evidence a Correction ever happened, so it must not be dropped, and its zeroing rules are what keep the derivation honest — SetLatestChapter clears it, and Upsert clears it only when the number actually changes. #121's line "deliberately not an audit trail" stops being a caveat and becomes the entire design.

Presentation: one line on the Series detail page, naming the actor class beside the number. Owner-only by route. No list-row field (#122 gives a row two lines), no new filter name (the vocabulary closes at twelve, per #130), and no landing figure — an actor class is context for a Series you are already looking at, never a population to sweep.

The Cover half is closed by construction, and a replaced Cover is deliberately unrecoverable. #120 addresses new bytes by their SHA-256, so a replacement is visible in cover_address itself; #125 reclaims the unreferenced covers row. The superseded address is gone, and that is a decision rather than an oversight — the Site is the only true source of what the art should be.

#118's rejected "Latest Chapter went backwards" filter stays rejected, and its first ground stays true: nothing stores the previous number. A flap detector (fell, then rose) was reachable only under the history option and dies with it.

What was rejected, and why — the history table was designed before it was dropped. Shape considered: one row per actual change (a no-change PUT and a confirming Poll writing nothing, roughly 52 rows per Series per year), actor class only, newest-20-per-Series pruned on insert in the lazy style of sessions.go, migration 0018. Three costs killed it:

  1. A per-Series timestamped table is one column away from the log the map forbids. Add a Reader id — the obvious next request, since a Sighting comes from someone — and it becomes a record of which Series each Reader reads and when. That is the map's own Out of scope line "Inspecting an individual Reader's library or reading progress".
  2. It would duplicate a fact with a second writer. "The current value is a human's" would live in both latest_corrected_at and the newest row's actor class, and the two would eventually disagree. #127 rejected a stored column for exactly this reason.
  3. No owner question on this map needs the past. The Poll is the oracle, so the next successful read re-establishes the number without reference to history; distrust of a Reader is already readers.sighting_disagreements, durable, judged by Polls, and self-healing over SightingAgreementsToClear = 20. A trail's unique payload was "who to distrust", and that mechanism already exists and is better.

Retention: not applicable. Filed as a decision rather than out of scope — "the dashboard shows no history, and here is why" is guidance the implementer needs, not a boundary past the destination.

Glossary: Correction added to CONTEXT.md this session (an owner-set Latest Chapter on a Series no Poll can read; no authority, overwritten by the next Poll and by any Sighting; never a pin or a floor). Movement, a word proposed for a history row, is deliberately not added — there are no rows to name.

**Nothing records it, and nothing will.** No history table, no attribution column, no migration 0018. The current number plus the actor class behind it is the whole requirement, and both are already derivable from state this map has decided. **The actor behind the present value, derived — three classes, not four:** - **Correction** — `latest_corrected_at <> 0` (#121, migration 0015). Means "the number on this row is a human's". - **Sighting** — `latest_raised_by IS NOT NULL`. A Reader's Sighting raised the number and no Poll has judged it yet; surfaced anonymously as #116's `SightingRaised` and #127's `unverified`. - **Machine read** — neither of the above, with `latest_checked_at > 0`. **Acquisition does not survive as a distinct actor.** `acquire.go:125` stamps `latest_checked_at` exactly as `poller.go:428` does, so an acquired value and a polled value are indistinguishable the moment the Acquisition finishes. Accepted deliberately: the only case where the difference is actionable — acquired once and never read again — is already #116's `unchecked` filter. Telling the two apart would need a column, which is the thing this ticket declines to add. **Consequence for #121: `latest_corrected_at` is promoted from convenience to load-bearing.** It is now the *only* evidence a Correction ever happened, so it must not be dropped, and its zeroing rules are what keep the derivation honest — `SetLatestChapter` clears it, and `Upsert` clears it *only when the number actually changes*. #121's line "deliberately **not** an audit trail" stops being a caveat and becomes the entire design. **Presentation: one line on the Series detail page**, naming the actor class beside the number. Owner-only by route. **No list-row field** (#122 gives a row two lines), **no new filter name** (the vocabulary closes at twelve, per #130), and **no landing figure** — an actor class is context for a Series you are already looking at, never a population to sweep. **The Cover half is closed by construction, and a replaced Cover is deliberately unrecoverable.** #120 addresses new bytes by their SHA-256, so a replacement is visible in `cover_address` itself; #125 reclaims the unreferenced `covers` row. The superseded address is gone, and that is a decision rather than an oversight — the Site is the only true source of what the art should be. **#118's rejected "Latest Chapter went backwards" filter stays rejected**, and its first ground stays true: nothing stores the previous number. A flap detector (fell, then rose) was reachable only under the history option and dies with it. **What was rejected, and why — the history table was designed before it was dropped.** Shape considered: one row per *actual change* (a no-change PUT and a confirming Poll writing nothing, roughly 52 rows per Series per year), actor class only, newest-20-per-Series pruned on insert in the lazy style of `sessions.go`, migration 0018. Three costs killed it: 1. **A per-Series timestamped table is one column away from the log the map forbids.** Add a Reader id — the obvious next request, since a Sighting comes from someone — and it becomes a record of which Series each Reader reads and when. That is the map's own **Out of scope** line "Inspecting an individual Reader's library or reading progress". 2. **It would duplicate a fact with a second writer.** "The current value is a human's" would live in both `latest_corrected_at` and the newest row's actor class, and the two would eventually disagree. #127 rejected a stored column for exactly this reason. 3. **No owner question on this map needs the past.** The Poll is the oracle, so the next successful read re-establishes the number without reference to history; distrust of a Reader is already `readers.sighting_disagreements`, durable, judged by Polls, and self-healing over `SightingAgreementsToClear = 20`. A trail's unique payload was "who to distrust", and that mechanism already exists and is better. Retention: not applicable. Filed as a decision rather than out of scope — "the dashboard shows no history, and here is why" is guidance the implementer needs, not a boundary past the destination. **Glossary:** **Correction** added to `CONTEXT.md` this session (an owner-set Latest Chapter on a Series no Poll can read; no authority, overwritten by the next Poll and by any Sighting; never a pin or a floor). **Movement**, a word proposed for a history row, is deliberately not added — there are no rows to name.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sulthan/mangaBookmark#131