Latest Chapter provenance: one derived line naming the actor class #152

Closed
opened 2026-08-22 08:38:13 +07:00 by sulthan · 1 comment
Owner

Parent

Spec #135.

What to build

Looking at a Latest Chapter, the owner cannot tell where it came from — their own hand, a Reader's report, or a machine read — and so cannot judge whether to trust it before acting on it. This ticket adds one line beside the number on the Series detail page naming the actor class behind the current value.

Derived, never recorded. No history table, no attribution column, no migration, and none is coming. Three classes, all read from state the system already keeps:

  • Correction — the correction stamp is non-zero: the number is a human's.
  • Sighting — the Series carries a raising Reader: a Reader's report raised the number and no Poll has judged it. Surfaced anonymously, exactly as the list row's Sighting flag already is.
  • Machine read — neither of the above, with a non-zero check stamp.

Acquisition does not survive as a distinct actor. Acquisition stamps the check timestamp exactly as a Poll does, so the two are indistinguishable the moment it finishes. Accepted deliberately: the only case where the difference is actionable — acquired once and never read again — is already the unchecked filter, and telling them apart would need the column this declines to add.

A history table was designed and dropped, and should not be re-proposed: a per-Series timestamped table is one column away from the log this project forbids, it would duplicate "the current value is a human's" with a second writer that eventually disagrees, and no owner question needs the past — the Poll re-establishes the number, and distrust of a Reader is already the durable, self-healing Sighting-disagreement counter.

Placement is deliberate: the detail page only, owner-only by route. No list-row field (a row has two lines), no new filter name, no landing figure — an actor class is context for a Series you are already looking at, never a population to sweep.

Acceptance criteria

  • The detail page renders one line beside the number naming the actor class
  • Each of the three classes is named for the state that produces it
  • A Series whose value came from an Acquisition reads as a machine read
  • No new column, table or migration is added
  • The line appears on the detail page only, and no Reader identity reaches it

Blocked by

  • #149 — the Correction class is derived from the correction stamp that ticket adds.
## Parent Spec #135. ## What to build Looking at a Latest Chapter, the owner cannot tell where it came from — their own hand, a Reader's report, or a machine read — and so cannot judge whether to trust it before acting on it. This ticket adds one line beside the number on the Series detail page naming the actor class behind the current value. **Derived, never recorded. No history table, no attribution column, no migration, and none is coming.** Three classes, all read from state the system already keeps: - **Correction** — the correction stamp is non-zero: the number is a human's. - **Sighting** — the Series carries a raising Reader: a Reader's report raised the number and no Poll has judged it. Surfaced anonymously, exactly as the list row's Sighting flag already is. - **Machine read** — neither of the above, with a non-zero check stamp. **Acquisition does not survive as a distinct actor.** Acquisition stamps the check timestamp exactly as a Poll does, so the two are indistinguishable the moment it finishes. Accepted deliberately: the only case where the difference is actionable — acquired once and never read again — is already the unchecked filter, and telling them apart would need the column this declines to add. A history table was designed and dropped, and should not be re-proposed: a per-Series timestamped table is one column away from the log this project forbids, it would duplicate "the current value is a human's" with a second writer that eventually disagrees, and no owner question needs the past — the Poll re-establishes the number, and distrust of a Reader is already the durable, self-healing Sighting-disagreement counter. **Placement is deliberate**: the detail page only, owner-only by route. No list-row field (a row has two lines), no new filter name, no landing figure — an actor class is context for a Series you are already looking at, never a population to sweep. ## Acceptance criteria - [ ] The detail page renders one line beside the number naming the actor class - [ ] Each of the three classes is named for the state that produces it - [ ] A Series whose value came from an Acquisition reads as a machine read - [ ] No new column, table or migration is added - [ ] The line appears on the detail page only, and no Reader identity reaches it ## Blocked by - #149 — the Correction class is derived from the correction stamp that ticket adds.
sulthan added the ready-for-agent label 2026-08-22 08:38:13 +07:00
sulthan self-assigned this 2026-08-22 09:26:36 +07:00
Author
Owner

Landed on spec-135 as a --no-ff merge of ticket/152-latest-chapter-provenance (a4491ba).

Implemented: one Provenance field on seriesDetailView, derived inside seriesDetailView(store.AdminSeries) where every other judgement on that page already happens - "correction" when the correction stamp stands, else "sighting" when a Reader raised it, else "machine read" when any check stamp exists, else "" and the line is not rendered at all. Rendered inside the series-detail-meta fragment beside the chapter number, so it re-renders with the number it describes and can never be left describing the previous value.

No new column, table or migration, and no store, SQL or projection change: all three inputs were already on store.AdminSeries after #149.

A Series whose value came from an Acquisition reads as a machine read, deliberately - an Acquisition stamps latest_checked_at exactly as a Poll does, so the two are indistinguishable the moment it finishes, the only actionable case (acquired once, never read again) is already the unchecked filter, and telling them apart would need the column this spec declines to add. That is recorded in one comment at the derivation.

Privacy invariant preserved: the Sighting class is surfaced anonymously through the existing RaisedByReader bool. No Reader id was added to the view, and the admin projection still never selects latest_raised_by - ReaderCount remains the only figure crossing the privacy boundary.

Tests: a table test over the derivation covering all four states including correction-outranks-sighting, plus a router test asserting the line reaches the rendered detail page and appears nowhere in the rendered Series list.

The full backend suite is green on the merged base: 585 tests, 10 packages.

No concerns handed back.

Landed on `spec-135` as a `--no-ff` merge of `ticket/152-latest-chapter-provenance` (a4491ba). Implemented: one `Provenance` field on `seriesDetailView`, derived inside `seriesDetailView(store.AdminSeries)` where every other judgement on that page already happens - "correction" when the correction stamp stands, else "sighting" when a Reader raised it, else "machine read" when any check stamp exists, else "" and the line is not rendered at all. Rendered inside the `series-detail-meta` fragment beside the chapter number, so it re-renders with the number it describes and can never be left describing the previous value. No new column, table or migration, and no store, SQL or projection change: all three inputs were already on `store.AdminSeries` after #149. A Series whose value came from an Acquisition reads as a machine read, deliberately - an Acquisition stamps `latest_checked_at` exactly as a Poll does, so the two are indistinguishable the moment it finishes, the only actionable case (acquired once, never read again) is already the unchecked filter, and telling them apart would need the column this spec declines to add. That is recorded in one comment at the derivation. Privacy invariant preserved: the Sighting class is surfaced anonymously through the existing `RaisedByReader bool`. No Reader id was added to the view, and the admin projection still never selects `latest_raised_by` - `ReaderCount` remains the only figure crossing the privacy boundary. Tests: a table test over the derivation covering all four states including correction-outranks-sighting, plus a router test asserting the line reaches the rendered detail page and appears nowhere in the rendered Series list. The full backend suite is green on the merged base: 585 tests, 10 packages. No concerns handed back.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sulthan/mangaBookmark#152