Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions docs/FULL_WORK_SITE_REPORT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Full-work reports in the canonical static site

`scriptorium-static-site-v2` extends the existing publication-manifest-v1 renderer with
one reviewed, source-free historical diagnostic. It also adds a reader-first homepage
with a real report action, explicit page types, shared keyboard focus/skip links and a
responsive card grid. Existing four routes and their scientific labels are retained.

```bash
python -m scriptorium.site_renderer --repo-root . --output build/site
```

The generated homepage links to `works/anna-karenina-full-work-diagnostic/`. That page
reuses `frozen_diagnostic_report` from SCRIP-SITE-007: 28 historical fields, 23 numeric
actuals, five missing actuals, expected/actual/raw deltas, correct mean-length denominators
and replay identities. A backlink returns to the work list. No metric is recalculated.

## Publication boundary

The manifest must explicitly include the frozen report. Directory discovery is not
supported. `scriptorium/site_frozen_diagnostic.py` registers the exact existing JSON path,
entry ID, slug, publication/compatibility/source-text flags and SHA-256 of the reviewed
snapshot. The standard schema validator runs even after the byte digest matches; the
parsed object must agree with the verified bytes. This narrow registration intentionally
rejects unreviewed new snapshots, changed observations, altered labels and path aliases.
A new snapshot requires scientific/security review and an explicit registration change.

The registration does not grant corpus admission or identify FantLab's input. The entry
remains diagnostic-only, inferred, with `corpus_admissibility=not_admissible`; the original
source-free JSON is not rewritten. M2 remains 0/5. The four existing artifacts keep their
own previously reviewed corpus and compatibility flags.

All entries are validated and rendered before the existing disposable output is replaced.
A broken input, unapproved digest or report-integration mismatch leaves the previous
valid build intact. `build.json` records the exact consumed input hashes and five routes.
The existing workflow performs the full suite and a byte-identical canonical rebuild.

## Acceptance and delivery

Tests exercise the canonical five-entry manifest, all internal links/fragments, historical
row counts, source-free output, digest/flag tampering, missing/aliased files, output
preservation, title escaping and deterministic builds. Shared navigation/card/action links
have minimum 44px targets; tables are named, focusable scrolling regions with scoped
headers. The full report retains its own standalone stylesheet and historical labels.

A successful build is not a live deployment. The existing Pages deployment variable,
repository configuration and later fresh PR acceptance gates are unchanged. No workflow
permissions or external services are added. Visual screenshots require an environment
where browser navigation is allowed; structural tests are not visual verification.
17 changes: 17 additions & 0 deletions project/CHANGELOG.d/2026-10-07-scrip-site-008.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# SCRIP-SITE-008 — canonical full-work report route

Refs #271; stacked on #268 at 50fbb9b9c0da59a5eb78c6826381b8acd3dd8aae.

Static-site-v2 adds one digest-approved historical Anna Karenina full-work report to the
existing publication allow-list, with a real homepage action and backlink. Reuses the
standalone validator/renderer; 28 rows, 23 actuals and five missing actuals remain historical
source-unmatched evidence. The original four routes and source JSON bytes are preserved.

Add 15 integration regressions, extend the canonical manifest safety test for the fifth
entry, and record source hashes in the existing build manifest. Keyboard skip/focus/table
contracts and responsive cards accompany the real reader flow. The compact existing queue
now points to #268, #270 and #271 rather than stale recovery or duplicate local handoffs.

Local actual five-route build and byte-identical rebuild passed. Full hosted CI and later
fresh acceptance remain required. Browser navigation returned ERR_BLOCKED_BY_ADMINISTRATOR;
VISUAL_NOT_VERIFIED. No corpus, analyzer, M2, deployment activation or access-policy changes.
45 changes: 26 additions & 19 deletions project/STATE_AND_QUEUE.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
# STATE_AND_QUEUE — Scriptorium

STATE_REVISION: 290
STATE_REVISION: 291
PHASE: M1 — Deterministic FantLab surface
LAST_COMMITTED_RUN_AT: 2026-10-02T09:12:28Z
LAST_RESULT: SCRIP-CORPUS-087 / Issue #263 / PR #264 completed. Independent exact-head review re-read the six-file recovery patch at `950404bb86c191b7eacdf21eb34c231f1d906fc4`, confirmed 24/24 pull-request-triggered workflow runs completed successfully with no submitted reviews or unresolved review threads, and found no semantic merge blocker. PR #264 was squash-merged with expected-head protection as `a9df79ec04664011f6dddf3593031424b15c1073`; Issue #263 closed completed. Embedded text-layer status remains unverified; literary body, >=300k admission, FantLab-input identity, diagnostics, M2 and parity remain closed.
LAST_COMMITTED_RUN_AT: 2026-10-07T12:21:02Z
LAST_RESULT: Owner-requested delivery batch: repaired four mean-length unit labels in PR #268 at `50fbb9b9c0da59a5eb78c6826381b8acd3dd8aae` (654 hosted tests and canonical Pages double-build passed); implemented local analysis for #269 in PR #270 at `752f3c491af2f1c563a0c5ae31e9452f93a1c0a3` (22 focused real-engine tests, applicable hosted workflows passed); implemented the SCRIP-SITE-008 route for #271 in this stacked feature. These are branch/PR effects, not merges or live publication. Later fresh acceptance remains required.
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-SITE-007
ISSUE: #267
UNIT_ID: SCRIP-SITE-008
ISSUE: #271
STATUS: REVIEW_PENDING
PR: Resolve the linked product PR from Issue #267; GitHub owns current head/check/merge facts.
BASE: abe7bb889ef98437ba9faef5a79b023499556991
NEXT_ACTION: Later exact-head acceptance of the readable frozen diagnostic report.
Inspect code/tests and applicable full-suite/Pages CI; do not merge in the authoring run.
Keep the existing historical diagnostic and all source-match/parity gates unchanged.
PR: Resolve the linked route-integration PR from #271; GitHub owns current head/check/merge facts.
BASE: 50fbb9b9c0da59a5eb78c6826381b8acd3dd8aae (PR #268)
NEXT_ACTION: Review/accept #268 separately, then accept this stacked route on a fresh exact head.
PR #270 is independent and can receive its own later acceptance without waiting for this stack.
Re-read applicable full-suite/Pages CI, source-free bytes and publication interlocks.
```

PR #266 is merged as `abe7bb889ef98437ba9faef5a79b023499556991`; it is not a pending
recovery blocker. The older LAST_RESULT above describes the completed corpus unit.
The report PR adopts useful local work with 23 focused tests; hosted acceptance and
actual merge/publication are separate native GitHub effects, not implied here.
PR #266 is already merged as `abe7bb889ef98437ba9faef5a79b023499556991` and is not a
recovery blocker. GitHub writes succeeded in the 2026-10-07 interactive delivery pass;
this does not establish scheduled-context capability. Do not repeat old denied mutations
without a material capability change. This feature includes the real homepage report
action and shared keyboard/mobile structure; do not reimplement them from old preview ZIPs.

## Current milestone gate

Expand All @@ -44,11 +45,17 @@ milestone does not declare M1/M2 complete.

| Priority | Unit | Mode | Deliverable | Gate / dependency |
| --- | --- | --- | --- | --- |
| P1 | SCRIP-SITE-007 / #267 | acceptance / delivery | Accept the offline frozen diagnostic HTML/CLI on its fresh PR head | Full applicable tests/checks; later-run acceptance; no source-match promotion |
| P2 | SCRIP-SITE-008 | public experience | Integrate the reviewed report into the existing Pages allow-list and work route | Reuse report primitives; correct the old local patcher's indentation error; test actual renderer, full build and byte-identical rebuild; deployment rights block live publication only |
| P3 | SCRIP-METRIC-003 | analyzer / CLI | Local UTF-8 text to readable report and JSON using current deterministic metrics | Adopt/revalidate pending local work against actual core modules; private text stays local; dictionary-dependent unknowns stay explicit |
| P4 | SCRIP-SITE-009 | public experience | Reader-first homepage and README with real actions and evidence labels | Revalidate pending local work against accepted Pages items; no invented analyses or capabilities |
| P5 | SCRIP-CORPUS continuation | corpus / provenance | Strengthen a legally usable >=300k diversity candidate with a new executable extraction/provenance result | Preserve translation/edition identity; candidate-specific body/FantLab gates; unchanged scans do not block P1-P4 |
| P1 | SCRIP-SITE-007 / #267 / PR #268 | acceptance | Fresh acceptance of the fixed offline report | Exact head, applicable checks and later-run gate; unit-label fix is already on the PR branch |
| P2 | SCRIP-METRIC-003 / #269 / PR #270 | acceptance | Ship local UTF-8 text to private JSON/offline HTML | Independent of #268; review actual core integration, create-only writer and exact-head CI |
| P3 | SCRIP-SITE-008 / #271 | public experience | Ship five canonical routes including the 28-metric full-work report | Stack depends on #268; digest/source flags, full suite and deterministic build; deployment rights block live publication only |
| P4 | SCRIP-COMPARE-002 pending handoff | analyzer / comparison | Adopt one tested two-diagnostic comparison CLI into the repository | Deduplicate current code/PRs, preserve missing values and schema/profile boundaries; test real canonical Anna/Grin bytes |
| P5 | SCRIP-CORPUS continuation | corpus / provenance | Advance one independent legally usable >=300k diversity candidate | New executable evidence only; preserve translation/edition and FantLab-input gates |

SCRIP-SITE-009's homepage action and keyboard structure are partly covered by #271;
README local-analysis instructions are in #270. Remaining visual acceptance is scoped:
the interactive Chromium attempt to the actual local build returned
`net::ERR_BLOCKED_BY_ADMINISTRATOR`. Structural/link tests and canonical double builds
passed, but screenshots remain VISUAL_NOT_VERIFIED. No browser restriction was bypassed.

## Retained corpus / provenance orientation

Expand Down
73 changes: 73 additions & 0 deletions scriptorium/site_frozen_diagnostic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"""Publish only the explicitly reviewed frozen full-work diagnostic snapshot.

Digest approval is a publication boundary, not an assertion of FantLab source identity.
The historical artifact stays immutable; new snapshots require a reviewed registration.
"""

from __future__ import annotations

from collections.abc import Mapping
from hashlib import sha256
import json
from typing import Any

from . import frozen_diagnostic_report as report


FROZEN_PROFILE = report.SCHEMA_VERSION
ARTIFACT_PATH = "benchmarks/fantlab/work270306-wikisource-diagnostic.json"
ARTIFACT_SHA256 = "2a25c3d2df91c2f26b283ec40055ca20248f865cffadc932026cf9c98b5d0e8b"
ENTRY_ID = "tolstoy-anna-karenina-full-work-diagnostic-v1"
SLUG = "anna-karenina-full-work-diagnostic"
_DECLARATION = {
"entry_id": ENTRY_ID,
"kind": "work_showcase",
"slug": SLUG,
"artifact_path": ARTIFACT_PATH,
"artifact_schema": FROZEN_PROFILE,
"publication_status": "diagnostic",
"benchmark_admissibility": "diagnostic_only",
"corpus_admissibility": "not_admissible",
"compatibility_claim": "inferred",
"source_text_included": False,
}


def prepare(
entry: Mapping[str, Any], artifact: Mapping[str, Any], raw: bytes | None
) -> dict[str, Any]:
"""Validate the publication registration and reuse the standalone report renderer."""
if set(entry) != {*_DECLARATION, "title"}:
raise ValueError("frozen diagnostic declaration keys drift")
for key, expected in _DECLARATION.items():
actual = entry.get(key)
if type(actual) is not type(expected) or actual != expected:
raise ValueError(f"frozen diagnostic declaration mismatch: {key}")
if not isinstance(raw, bytes) or sha256(raw).hexdigest() != ARTIFACT_SHA256:
raise ValueError("frozen diagnostic bytes do not match the reviewed SHA-256")
if json.loads(raw) != artifact:
raise ValueError("frozen diagnostic object differs from its verified bytes")
value = report.validate_artifact(artifact)
if value["candidate_id"] != "tolstoy-anna-karenina-ru":
raise ValueError("frozen diagnostic candidate identity drift")
title = entry["title"]
rendered = report.render_html(value, title=title)
# The reused renderer owns all metric tables, values, units and historical labels.
# Add only navigation to the site's work list and a focusable skip-link destination.
if rendered.count("<main>") != 1 or rendered.count('<div id="metrics">') != 1:
raise ValueError("frozen diagnostic navigation integration marker drift")
rendered = rendered.replace(
"<main>",
'<main id="main-content" tabindex="-1"><nav aria-label="Work navigation">'
'<a href="../../">← All published analyses</a></nav>',
1,
).replace('<div id="metrics">', '<div id="metrics" tabindex="-1">', 1)
return {
**_DECLARATION,
"render_mode": "frozen_diagnostic",
"title": title,
"author": "Leo Tolstoy",
"work_title": "Anna Karenina",
"metric_count": report.summarize(value)["metric_count"],
"report_html": rendered,
}
Loading
Loading