Record per-site probe provenance in completed fixtures (#168)

Spec review flagged the live-verification acceptance criterion as
unproven in the diff: the brief's adapter rule wants the probe
recorded, not just the date. Each fixture comment now names how the
live body was fetched on 2026-08-22 — curl probe for asura,
demonic and lightnovelworld; cleared Chrome tab (CDP sidecar) for
comix, kagane and novelfull, including the challenge/403 fallback
story for novelfull. Also renamed lnwCompletedRe to lnwStatusRe for
symmetry with the other site-marker vars.
This commit is contained in:
2026-08-22 18:26:34 +07:00
parent f6782e212a
commit b38dfe54e8
2 changed files with 24 additions and 22 deletions
+2 -2
View File
@@ -437,10 +437,10 @@ func novelfullCompleted(_, body string) bool {
// whole body is scanned and the comment marker is not required, unlike // whole body is scanned and the comment marker is not required, unlike
// lnwLatestChapter: the status block sits ahead of the visitor-writable // lnwLatestChapter: the status block sits ahead of the visitor-writable
// thread, and hiatus maps to a distinct PotentialActionStatus value. // thread, and hiatus maps to a distinct PotentialActionStatus value.
var lnwCompletedRe = regexp.MustCompile(`"creativeWorkStatus"\s*:\s*"https://schema\.org/CompletedActionStatus"`) var lnwStatusRe = regexp.MustCompile(`"creativeWorkStatus"\s*:\s*"https://schema\.org/CompletedActionStatus"`)
func lnwCompleted(_, body string) bool { func lnwCompleted(_, body string) bool {
return lnwCompletedRe.MatchString(body) return lnwStatusRe.MatchString(body)
} }
// siteCompletedFrom reports whether the Site calls this work completed, via // siteCompletedFrom reports whether the Site calls this work completed, via
+22 -20
View File
@@ -193,21 +193,22 @@ const lnwSeriesFixture = `
// from the consts and must answer false. // from the consts and must answer false.
// Trimmed from https://asurascans.com/comics/solo-leveling (301 to // Trimmed from https://asurascans.com/comics/solo-leveling (301 to
// /comics/solo-leveling-b60d532c) fetched 2026-08-22. The astro-island props // /comics/solo-leveling-b60d532c) fetched 2026-08-22 by a curl probe from
// are HTML-escaped in the served document, so the quotes arrive as ". // this machine. The astro-island props are HTML-escaped in the served
// document, so the quotes arrive as ".
const asuraCompletedFixture = ` const asuraCompletedFixture = `
"bookmarkCount":[0,39128],"status":[0,"completed"],"type":[0,"manhwa"] "bookmarkCount":[0,39128],"status":[0,"completed"],"type":[0,"manhwa"]
` `
// Trimmed from https://asurascans.com/comics/chronicles-of-the-demon-faction-f886a8af // Trimmed from https://asurascans.com/comics/chronicles-of-the-demon-faction-f886a8af
// fetched 2026-08-22. // fetched 2026-08-22 by a curl probe.
const asuraOngoingFixture = ` const asuraOngoingFixture = `
"bookmarkCount":[0,54027],"status":[0,"ongoing"],"type":[0,"manhwa"] "bookmarkCount":[0,54027],"status":[0,"ongoing"],"type":[0,"manhwa"]
` `
// Trimmed from https://demonicscans.org/manga/Solo-Leveling fetched // Trimmed from https://demonicscans.org/manga/Solo-Leveling fetched
// 2026-08-22. The info block is sloppy: bare <li>s inside a <div>, label and // 2026-08-22 by a curl probe. The info block is sloppy: bare <li>s inside a
// value as a sibling pair. // <div>, label and value as a sibling pair.
const demonicCompletedFixture = ` const demonicCompletedFixture = `
<div class="flex flex-row"> <div class="flex flex-row">
<li style="width:150px;color:#b2b2b2;">Status</li> <li style="width:150px;color:#b2b2b2;">Status</li>
@@ -216,7 +217,7 @@ const demonicCompletedFixture = `
` `
// Trimmed from https://demonicscans.org/manga/Catastrophic-Necromancer // Trimmed from https://demonicscans.org/manga/Catastrophic-Necromancer
// fetched 2026-08-22. Same block, ongoing value. // fetched 2026-08-22 by a curl probe. Same block, ongoing value.
const demonicOngoingFixture = ` const demonicOngoingFixture = `
<div class="flex flex-row"> <div class="flex flex-row">
<li style="width:150px;color:#b2b2b2;">Status</li> <li style="width:150px;color:#b2b2b2;">Status</li>
@@ -224,12 +225,12 @@ const demonicOngoingFixture = `
</div> </div>
` `
// Trimmed from https://comix.to/title/q77m-countach fetched 2026-08-22 over a // Trimmed from https://comix.to/title/q77m-countach fetched 2026-08-22 by a
// cleared Chrome tab (the in-tab fetch of the Series URL, the same // cleared Chrome tab (the CDP sidecar: the Series URL is fetched in-tab, the
// server-rendered payload the poll reads). The served page escapes the query // same server-rendered payload the poll reads). The served page escapes the
// map keys as \u0022; the fixture carries the decoded form, which parses to // query map keys as \u0022; the fixture carries the decoded form, which
// the same key. The recommended strip on this very page carries a finished // parses to the same key. The recommended strip on this very page carries a
// entry; only the ["manga","detail","q77m"] entry counts. // finished entry; only the ["manga","detail","q77m"] entry counts.
const comixCompletedFixture = `<script type="application/json" id="initial-data">{"queries":{"[\"manga\",\"recommended\",\"q77m\",1]":{"items":[{"hid":"pz65","title":"Wangan Midnight: C1 Runner","status":"finished"}]},"[\"manga\",\"detail\",\"q77m\"]":{"id":13211,"hid":"q77m","title":"Countach","status":"finished","originalLanguage":"ja"}}}</script>` const comixCompletedFixture = `<script type="application/json" id="initial-data">{"queries":{"[\"manga\",\"recommended\",\"q77m\",1]":{"items":[{"hid":"pz65","title":"Wangan Midnight: C1 Runner","status":"finished"}]},"[\"manga\",\"detail\",\"q77m\"]":{"id":13211,"hid":"q77m","title":"Countach","status":"finished","originalLanguage":"ja"}}}</script>`
// Trimmed from https://comix.to/title/n8we-dungeons-and-crayons fetched // Trimmed from https://comix.to/title/n8we-dungeons-and-crayons fetched
@@ -238,14 +239,15 @@ const comixCompletedFixture = `<script type="application/json" id="initial-data"
// releasing, and only the detail read counts. // releasing, and only the detail read counts.
const comixOngoingFixture = `<script type="application/json" id="initial-data">{"queries":{"[\"manga\",\"recommended\",\"n8we\",1]":{"items":[{"hid":"g2rk","title":"On the Way to Meet Mom","status":"finished"}]},"[\"manga\",\"detail\",\"n8we\"]":{"id":1429,"hid":"n8we","title":"Dungeons and Crayons","status":"releasing","originalLanguage":"ko"}}}</script>` const comixOngoingFixture = `<script type="application/json" id="initial-data">{"queries":{"[\"manga\",\"recommended\",\"n8we\",1]":{"items":[{"hid":"g2rk","title":"On the Way to Meet Mom","status":"finished"}]},"[\"manga\",\"detail\",\"n8we\"]":{"id":1429,"hid":"n8we","title":"Dungeons and Crayons","status":"releasing","originalLanguage":"ko"}}}</script>`
// Trimmed from GET https://kagane.to/api/v2/series/019c29c3-5abd-70e6-9efc-1f1f22d839f6
// on 2026-08-22.
const kaganeCompletedFixture = `{"series_id":"019c29c3-5abd-70e6-9efc-1f1f22d839f6","title":"Real Account 1-17","publication_status":"Completed","upload_status":"Completed"}`
// Trimmed from GET https://kagane.to/api/v2/series/019f84bc-9ba0-7ed9-86f5-8b905ec7c28b // Trimmed from GET https://kagane.to/api/v2/series/019f84bc-9ba0-7ed9-86f5-8b905ec7c28b
// on 2026-08-22. // fetched 2026-08-22 in a cleared Chrome tab (plain TLS serves the Cloudflare
// challenge).
const kaganeOngoingFixture = `{"series_id":"019f84bc-9ba0-7ed9-86f5-8b905ec7c28b","title":"Infinite Decryption: The Strongest Level 0","publication_status":"Ongoing","upload_status":"Ongoing"}` const kaganeOngoingFixture = `{"series_id":"019f84bc-9ba0-7ed9-86f5-8b905ec7c28b","title":"Infinite Decryption: The Strongest Level 0","publication_status":"Ongoing","upload_status":"Ongoing"}`
// Trimmed from GET https://kagane.to/api/v2/series/019c29c3-5abd-70e6-9efc-1f1f22d839f6
// fetched 2026-08-22 the same way.
const kaganeCompletedFixture = `{"series_id":"019c29c3-5abd-70e6-9efc-1f1f22d839f6","title":"Real Account 1-17","publication_status":"Completed","upload_status":"Completed"}`
// Composed, not a single live trim: upload Completed alongside a // Composed, not a single live trim: upload Completed alongside a
// non-Completed publication status is the research note's inferred inverse // non-Completed publication status is the research note's inferred inverse
// case and did not turn up in the ~1900-series live scan of 2026-08-22 (both // case and did not turn up in the ~1900-series live scan of 2026-08-22 (both
@@ -255,12 +257,12 @@ const kaganeOngoingFixture = `{"series_id":"019f84bc-9ba0-7ed9-86f5-8b905ec7c28b
const kaganeDivergentFixture = `{"series_id":"019f84bc-9ba0-7ed9-86f5-8b905ec7c28b","title":"Infinite Decryption: The Strongest Level 0","publication_status":"Ongoing","upload_status":"Completed"}` const kaganeDivergentFixture = `{"series_id":"019f84bc-9ba0-7ed9-86f5-8b905ec7c28b","title":"Infinite Decryption: The Strongest Level 0","publication_status":"Ongoing","upload_status":"Completed"}`
// Trimmed from https://novelfull.com/reverend-insanity.html fetched // Trimmed from https://novelfull.com/reverend-insanity.html fetched
// 2026-08-22 (the challenge served to plain TLS cleared in a real Chrome the // 2026-08-22 in a cleared Chrome tab after the plain-TLS probe was served the
// same day). // challenge (time-varying; plain curl answered 403 the same day).
const novelfullCompletedFixture = `<div><h3>Status:</h3><a href="/status/Completed">Completed</a></div>` const novelfullCompletedFixture = `<div><h3>Status:</h3><a href="/status/Completed">Completed</a></div>`
// Trimmed from https://novelfull.com/a-cunning-pervert-in-the-cultivation-world.html // Trimmed from https://novelfull.com/a-cunning-pervert-in-the-cultivation-world.html
// fetched 2026-08-22. // fetched 2026-08-22 the same way.
const novelfullOngoingFixture = `<div><h3>Status:</h3><a href="/status/Ongoing">Ongoing</a></div>` const novelfullOngoingFixture = `<div><h3>Status:</h3><a href="/status/Ongoing">Ongoing</a></div>`
// Trimmed from the JSON-LD block in the head of // Trimmed from the JSON-LD block in the head of