diff --git a/corpus/candidates/bely-petersburg-1916-ru.md b/corpus/candidates/bely-petersburg-1916-ru.md index fc9ccfe1..90cc187e 100644 --- a/corpus/candidates/bely-petersburg-1916-ru.md +++ b/corpus/candidates/bely-petersburg-1916-ru.md @@ -28,6 +28,16 @@ The contract freezes only future composition semantics: ascending PDF-page order The retained Commons file description identifies the facsimile as the first 1916 book publication and marks the work public domain. That source/legal evidence is retained in the structured trace. The candidate is not collapsed with a generic source-less transcription or the revised 1922 Berlin edition. +## Extraction-strategy preflight + +**SCRIP-CORPUS-087** adds a source-free preflight before choosing direct PDF text extraction versus raster OCR. On 24 September 2026 the official Commons surface still exposed the frozen candidate as a 632-page PDF facsimile of the first 1916 book edition, with the current file history rooted at the 20 March 2016 upload, explicit public-domain notice, PDF format 1.6, and a current-file no-overwrite notice. + +Two provider PDF screenshots were inspected directly: the title-page surface at carrier page 1 and a prose surface at carrier page 21, where printed folio 19 is visible. Those previews visibly look like facsimile page imagery, but that fact **does not prove that the PDF lacks a hidden text layer**. Conversely, the provider metadata does not prove that a usable embedded text layer exists. + +Therefore the embedded text layer remains **unverified**. Scriptorium does not yet choose either direct PDF text extraction or raster OCR. The next bounded evidence is an exact-carrier, version-recorded text-layer probe that retains only aggregate counts, an output digest and page-segment coverage; any extracted text remains transient. Even a non-empty text layer will still require separate correctness and literary-page-selection evidence before body promotion. + +Canonical source-free evidence: [`source-edition-traces/bely-petersburg-1916-ru.extraction-preflight.json`](source-edition-traces/bely-petersburg-1916-ru.extraction-preflight.json), physical SHA-256 **`093f251cb8d03846a5158a1ac29d4b66e1796a7cc2bc65a77ade3d9e3cebcff1`**. + ## What is still open Defining the promotion contract does **not** freeze the literary text. Scriptorium still needs an independently evidenced bound contract version with exact literary-page selection and reproducible rasterizer/OCR identities/settings, then a frozen extracted body with character count and raw/normalized digests and proof that that frozen body itself clears the **300,000-character** corpus threshold. diff --git a/corpus/candidates/source-edition-traces/bely-petersburg-1916-ru.extraction-preflight.json b/corpus/candidates/source-edition-traces/bely-petersburg-1916-ru.extraction-preflight.json new file mode 100644 index 00000000..5fc0b6e1 --- /dev/null +++ b/corpus/candidates/source-edition-traces/bely-petersburg-1916-ru.extraction-preflight.json @@ -0,0 +1,58 @@ +{ + "candidate_id": "bely-petersburg-1916-ru", + "carrier": { + "byte_count": 3621459, + "current_file_history_upload_timestamp": "2016-03-20T18:31:00Z", + "encrypted": false, + "page_count": 632, + "pdf_format_version": "1.6", + "provider": "Wikimedia Commons", + "sha1": "682476934dd6ed49c6bbcdb0720127c1812ff477", + "sha256": "b08820ad1339894c6d20fbaa2367c11385492bf376d199f8de23c859ef6ddef5" + }, + "decision": { + "direct_pdf_text_extraction_admissible": false, + "embedded_text_layer_status": "unverified", + "next_required_evidence": "Run a source-free exact-carrier text-layer probe with a version-recorded extractor; retain only aggregate counts, output digest and page-segment coverage. If a text layer exists, correctness still requires separate evidence before body promotion.", + "provider_metadata_proves_embedded_text_layer": false, + "raster_ocr_required": false, + "visual_facsimile_preview_proves_absence_of_text_layer": false + }, + "evidence_version": "scriptorium-petersburg-1916-extraction-preflight-v1", + "existing_promotion_contract": { + "body_outputs_frozen": false, + "canonical_sha256": "d338d8dc4d800b0fe28a848e383265ba9a0e720e75962f7f9e5733ad727a20d2", + "contract_version": "scriptorium-petersburg-1916-ocr-body-contract-v1", + "ocr_toolchain_bound": false, + "page_selection_bound": false, + "rasterization_toolchain_bound": false + }, + "gates": { + "admitted_for_calibration": false, + "diagnostic_ready": false, + "extraction_profile_frozen": false, + "fantlab_source_edition_match": "unknown", + "literary_body_frozen": false, + "literary_page_selection_bound": false, + "m2_parity_admissible": false, + "minimum_300k_proved_from_frozen_body": false + }, + "observed_on": "2026-09-24", + "provider_surface": { + "current_file_cannot_be_overwritten": true, + "first_book_edition_facsimile": true, + "metadata_short_title": "Андрей Белый. Петербург. 1916. EBook 2008", + "public_domain_notice": true, + "visual_samples": [ + {"carrier_page": 1, "observation": "facsimile title-page image visible in the provider PDF preview"}, + {"carrier_page": 21, "observation": "facsimile prose page visible in the provider PDF preview; printed folio 19 is visible"} + ] + }, + "publication": { + "extracted_text_committed": false, + "literary_source_text_committed": false, + "page_images_committed": false, + "pdf_bytes_committed": false, + "source_free": true + } +} diff --git a/project/CHANGELOG.d/2026-09-24-scrip-corpus-087.md b/project/CHANGELOG.d/2026-09-24-scrip-corpus-087.md new file mode 100644 index 00000000..fb3a9c38 --- /dev/null +++ b/project/CHANGELOG.d/2026-09-24-scrip-corpus-087.md @@ -0,0 +1,9 @@ +## 2026-09-24 — Petersburg 1916 extraction-strategy preflight + +- Recovery assigns this Petersburg work to **SCRIP-CORPUS-087**; White Guard remains SCRIP-CORPUS-086. +- Issue #263 and Draft PR #264 recover the staged Petersburg preflight onto fresh current-master branch `scrip-corpus-087-petersburg-preflight-current`. +- Exact stale source handoff `a24bbaeff4054762640694b8025500815853d4a5` was used only to transfer five Petersburg-specific files; stale project state was not merged. +- Source-free evidence remains `scriptorium-petersburg-1916-extraction-preflight-v1`, physical SHA-256 `093f251cb8d03846a5158a1ac29d4b66e1796a7cc2bc65a77ade3d9e3cebcff1`. +- Embedded-text-layer status remains `unverified`; neither direct PDF extraction nor raster OCR is selected. +- Literary-page selection, body identity, >=300k admission, FantLab analyzer-input identity, diagnostics, M2 admission and parity remain closed; M2 remains 0/5. +- PR #264 remains Draft for a later independent exact-head review after fresh hosted checks. diff --git a/project/STATE_AND_QUEUE.md b/project/STATE_AND_QUEUE.md index ef158fea..8569bd1e 100644 --- a/project/STATE_AND_QUEUE.md +++ b/project/STATE_AND_QUEUE.md @@ -1,23 +1,23 @@ # STATE_AND_QUEUE — Scriptorium -STATE_REVISION: 287 +STATE_REVISION: 288 PHASE: M1 — Deterministic FantLab surface -LAST_COMMITTED_RUN_AT: 2026-09-29T13:08:28Z -LAST_RESULT: SCRIP-CORPUS-086 / Issue #261 / PR #262 completed. Independent exact-head review `5353031421` re-read all 7 changed files at `64d405809c400a7f7294b1308b5d394fa61ee2aa`, found no merge blockers, and confirmed 26/26 pull-request-triggered workflows completed successfully with no unresolved review threads. PR #262 was marked Ready and squash-merged with expected-head protection as `fa9ead6e5a2489c9eea604ddbdbe73b0093c9eb1`; Issue #261 closed completed. No live 20-row provider manifest, literary-body identity, FantLab analyzer-input identity, benchmark or M2 movement is claimed. +LAST_COMMITTED_RUN_AT: 2026-09-29T22:39:45Z +LAST_RESULT: SCRIP-CORPUS-087 / Issue #263 / Draft PR #264 recovered the Petersburg 1916 extraction-strategy preflight from exact stale handoff `a24bbaeff4054762640694b8025500815853d4a5` onto current master without merging stale state. The five Petersburg-specific files were transferred onto fresh branch `scrip-corpus-087-petersburg-preflight-current`; source-free preflight SHA-256 remains `093f251cb8d03846a5158a1ac29d4b66e1796a7cc2bc65a77ade3d9e3cebcff1`. Embedded text-layer status remains unverified; literary body, >=300k admission, FantLab-input identity, diagnostics, M2 and parity remain closed. PR #264 is intentionally Draft for later independent exact-head judgement. LAST_VERIFIED_PROGRESS: M1 deterministic metric families remain executable inferred candidates. Public corpus/showcase evidence includes exact frozen/admitted works and source-free derived outputs, while no retained work has an independently established FantLab analyzer-input identity. Perelman now has independently reviewed exact PDF/DjVu identities, pagination, current Wikisource/FantLab surface boundaries, zero-PDF-PageLabels evidence, front-matter anchors, transition/tail anchors, restored-page interior observations, and canonical broad mid-body exact-PDF anchors that expose an unlabelled carrier page while keeping global mapping closed. Darwin/Rachinsky retains canonical reviewed dependency/replay/provider evidence through SCRIP-CORPUS-084. M2 stays 0/5. ## Current unit ```text -UNIT_ID: SCRIP-CORPUS-086 -ISSUE: #261 (closed completed) -STATUS: COMPLETE -PR: #262 (squash-merged as fa9ead6e5a2489c9eea604ddbdbe73b0093c9eb1) -NEXT_ACTION: Resume normal-flow corpus/provenance selection. - A separate bounded White Guard unit may perform authoritative 20-page identity-only capture/replay - of page ID, revision ID, UTC timestamp and MediaWiki SHA-1. - Keep literary-body, composite/single-edition identity, FantLab-input, benchmark, M2 and parity gates closed - until separately evidenced. +UNIT_ID: SCRIP-CORPUS-087 +ISSUE: #263 (open) +STATUS: REVIEW_PENDING +PR: #264 (Draft) +AUTHORED_HEAD: e6e93a4639f5986a85f87b5341f684ba6808dda7 +NEXT_ACTION: Independently review PR #264 on its final exact head after this bookkeeping reconciliation. + Require fresh exact-head checks, no blocking reviews and no unresolved review threads before Ready/merge. + Keep embedded text-layer status unverified and do not select direct PDF extraction or raster OCR. + Literary-page selection, body identity, >=300k admission, FantLab-input identity, diagnostics, M2 and parity remain closed. ``` ## Current milestone gate diff --git a/project/run-receipts/SCRIP-CORPUS-087.md b/project/run-receipts/SCRIP-CORPUS-087.md new file mode 100644 index 00000000..a4c12a68 --- /dev/null +++ b/project/run-receipts/SCRIP-CORPUS-087.md @@ -0,0 +1,29 @@ +# Run receipt — SCRIP-CORPUS-087 + +Status: REVIEW_PENDING + +## Recovery state + +- Canonical recovery base: `master@27f54858d20000244bb8e80342038d80ea510b45`. +- Issue: #263. +- Draft PR: #264. +- Fresh recovery branch: `scrip-corpus-087-petersburg-preflight-current`. +- Exact stale Petersburg handoff used only as a five-file source: `a24bbaeff4054762640694b8025500815853d4a5`. +- Recovery semantic head before bookkeeping: `e6e93a4639f5986a85f87b5341f684ba6808dda7`. +- The stale branch itself was not merged and its old `STATE_AND_QUEUE.md` was not copied. + +## Recovered evidence + +- Source-free preflight physical SHA-256: `093f251cb8d03846a5158a1ac29d4b66e1796a7cc2bc65a77ade3d9e3cebcff1`. +- Exact frozen carrier: 632 pages / 3,621,459 bytes / SHA-1 `682476934dd6ed49c6bbcdb0720127c1812ff477` / SHA-256 `b08820ad1339894c6d20fbaa2367c11385492bf376d199f8de23c859ef6ddef5`. +- Existing OCR/body promotion contract SHA-256 remains `d338d8dc4d800b0fe28a848e383265ba9a0e720e75962f7f9e5733ad727a20d2`. +- Embedded text-layer status remains `unverified`; neither direct PDF text extraction nor raster OCR is selected. +- No PDF bytes, page images, extracted text or literary source text are committed. + +## Gate boundary + +Literary-page selection, extraction profile, body identity, >=300k admission, FantLab analyzer-input identity, diagnostics, M2 admission and parity remain closed. M2 remains 0/5. + +## Handoff + +PR #264 remains intentionally Draft. A later independent wake must re-read the final exact head, inspect fresh hosted checks/reviews/threads and only then decide Ready/merge. diff --git a/tests/test_petersburg_extraction_preflight.py b/tests/test_petersburg_extraction_preflight.py new file mode 100644 index 00000000..b4c56dd0 --- /dev/null +++ b/tests/test_petersburg_extraction_preflight.py @@ -0,0 +1,77 @@ +from __future__ import annotations + +import hashlib +import json +from pathlib import Path +import unittest + + +ROOT = Path(__file__).resolve().parents[1] +EVIDENCE = ROOT / "corpus/candidates/source-edition-traces/bely-petersburg-1916-ru.extraction-preflight.json" +CANDIDATE_PAGE = ROOT / "corpus/candidates/bely-petersburg-1916-ru.md" +EXPECTED_PHYSICAL_SHA256 = "093f251cb8d03846a5158a1ac29d4b66e1796a7cc2bc65a77ade3d9e3cebcff1" +EXPECTED_SCAN_SHA256 = "b08820ad1339894c6d20fbaa2367c11385492bf376d199f8de23c859ef6ddef5" + + +class PetersburgExtractionPreflightTests(unittest.TestCase): + @classmethod + def setUpClass(cls) -> None: + cls.raw = EVIDENCE.read_bytes() + cls.data = json.loads(cls.raw) + + def test_source_free_artifact_is_frozen(self) -> None: + self.assertEqual(hashlib.sha256(self.raw).hexdigest(), EXPECTED_PHYSICAL_SHA256) + self.assertTrue(self.data["publication"]["source_free"]) + self.assertFalse(self.data["publication"]["pdf_bytes_committed"]) + self.assertFalse(self.data["publication"]["page_images_committed"]) + self.assertFalse(self.data["publication"]["extracted_text_committed"]) + self.assertFalse(self.data["publication"]["literary_source_text_committed"]) + + def test_exact_carrier_identity_is_preserved(self) -> None: + carrier = self.data["carrier"] + self.assertEqual(carrier["page_count"], 632) + self.assertEqual(carrier["byte_count"], 3621459) + self.assertEqual(carrier["sha1"], "682476934dd6ed49c6bbcdb0720127c1812ff477") + self.assertEqual(carrier["sha256"], EXPECTED_SCAN_SHA256) + + def test_preflight_does_not_guess_text_layer_or_ocr_strategy(self) -> None: + decision = self.data["decision"] + self.assertEqual(decision["embedded_text_layer_status"], "unverified") + self.assertFalse(decision["provider_metadata_proves_embedded_text_layer"]) + self.assertFalse(decision["visual_facsimile_preview_proves_absence_of_text_layer"]) + self.assertFalse(decision["direct_pdf_text_extraction_admissible"]) + self.assertFalse(decision["raster_ocr_required"]) + self.assertIn("text-layer probe", decision["next_required_evidence"]) + + def test_existing_promotion_contract_remains_unbound(self) -> None: + contract = self.data["existing_promotion_contract"] + self.assertEqual( + contract["canonical_sha256"], + "d338d8dc4d800b0fe28a848e383265ba9a0e720e75962f7f9e5733ad727a20d2", + ) + self.assertFalse(contract["page_selection_bound"]) + self.assertFalse(contract["rasterization_toolchain_bound"]) + self.assertFalse(contract["ocr_toolchain_bound"]) + self.assertFalse(contract["body_outputs_frozen"]) + + def test_downstream_gates_remain_closed(self) -> None: + gates = self.data["gates"] + self.assertFalse(gates["literary_page_selection_bound"]) + self.assertFalse(gates["extraction_profile_frozen"]) + self.assertFalse(gates["literary_body_frozen"]) + self.assertFalse(gates["minimum_300k_proved_from_frozen_body"]) + self.assertEqual(gates["fantlab_source_edition_match"], "unknown") + self.assertFalse(gates["diagnostic_ready"]) + self.assertFalse(gates["m2_parity_admissible"]) + self.assertFalse(gates["admitted_for_calibration"]) + + def test_public_candidate_exposes_preflight_without_promotion(self) -> None: + page = CANDIDATE_PAGE.read_text(encoding="utf-8") + self.assertIn("Extraction-strategy preflight", page) + self.assertIn(EXPECTED_PHYSICAL_SHA256, page) + self.assertIn("embedded text layer remains **unverified**", page) + self.assertIn("does not prove that the PDF lacks a hidden text layer", page) + + +if __name__ == "__main__": + unittest.main()