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
8 changes: 8 additions & 0 deletions .github/workflows/reader-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
- "scriptorium/**"
- "tests/**"
- "tools/reader_package_smoke.py"
- "tools/private_compare_smoke.py"
- ".github/workflows/reader-package.yml"
push:
branches: [master]
Expand All @@ -15,6 +16,7 @@ on:
- "scriptorium/**"
- "tests/**"
- "tools/reader_package_smoke.py"
- "tools/private_compare_smoke.py"
- ".github/workflows/reader-package.yml"
workflow_dispatch:

Expand Down Expand Up @@ -51,6 +53,12 @@ jobs:
cd "$RUNNER_TEMP"
"$RUNNER_TEMP/reader-venv/bin/python" -I "$GITHUB_WORKSPACE/tools/reader_package_smoke.py" "$GITHUB_WORKSPACE"
"$RUNNER_TEMP/reader-venv/bin/scriptorium" --help
- name: Exercise private comparison with the installed analyzer
shell: bash
run: |
set -euo pipefail
cd "$RUNNER_TEMP"
"$RUNNER_TEMP/reader-venv/bin/python" -I "$GITHUB_WORKSPACE/tools/private_compare_smoke.py" "$GITHUB_WORKSPACE"
- name: Verify installed source-free gallery and deterministic output
shell: bash
run: |
Expand Down
82 changes: 53 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

**Understand the language of a text without uploading the manuscript.**
Scriptorium measures vocabulary, sentence length, dialogue and punctuation, then produces
readable offline reports and reproducible data. This integrated **0.2.0a1 preview** brings
the reader site and the local analyzer into the canonical repository.
readable offline reports and reproducible data. This **0.4.0a1 preview** adds private
comparison of two analyses to the canonical Reader and its real-work gallery.

## Try your own text

Expand All @@ -26,24 +26,41 @@ No runtime dependencies, account, server or telemetry are required. Installation
fetch build tools; see [offline wheel installation](docs/READER_PREVIEW.md).
`python -m scriptorium` exposes the same commands from a checkout.

## Compare your own analyses

```bash
scriptorium analyze second-manuscript.txt --output second-analysis.json
scriptorium compare analysis.json second-analysis.json --output comparison.html
scriptorium compare analysis.json second-analysis.json --format json --output comparison.json
scriptorium compare analysis.json second-analysis.json --format csv --output comparison.csv
```

Open `comparison.html` for the same 29 measurements, explicit units, source identities
and **right minus left** differences. Percentage differences use percentage points.
Unknown measurements do not become zero; different methods or dictionaries are labelled
incomparable where applicable. JSON decimal observations and their differences retain
precision. Contradictory counts, means, punctuation rates and same-text results are rejected.
Imported JSON and hashes are declarations, not authenticated proof: rerun the analyzer
on the original bytes to verify them. [Comparison contract and examples](docs/PRIVATE_COMPARISON.md).

## Open a real literary result

The repository already contains a source-free, historical full-work diagnostic for
**Anna Karenina**. It has **28 expected/actual/delta rows: 23 numeric results and five
unavailable values**. No novel download is needed:
The repository contains a source-free, historical full-work diagnostic for
**Anna Karenina**: **28 expected/actual/delta rows**, with 23 numeric results and five
unavailable values. No novel download is needed:

```bash
scriptorium diagnostic benchmarks/fantlab/work270306-wikisource-diagnostic.json \
--title "Anna Karenina — full-work diagnostic" --output anna-report.html
scriptorium site --repo-root . --output build/site
```

Open `anna-report.html` or `build/site/index.html`. The canonical site retains its four
earlier evidence pages and adds the full-work report with a working homepage action.
**A successful local build is not a live GitHub Pages deployment.** The existing Pages
activation interlock is unchanged; this preview does not enable publishing by itself.
Atomic site replacement currently requires Linux `renameat2`; unsupported platforms
fail without deleting the previous build. Private text analysis is a separate capability.
Open `anna-report.html` or `build/site/index.html`. The canonical site retains the five
earlier evidence/report routes and the Reader 0.3 two-book comparison route.
**A successful local build is not a live GitHub Pages deployment.** The Pages activation
interlock is unchanged; this preview does not enable publishing by itself. Atomic site
replacement currently requires Linux `renameat2`; unsupported platforms fail without
deleting the previous build. Private text analysis and comparison are separate capabilities.

## Compare two already-analyzed books

Expand All @@ -57,18 +74,21 @@ python -m scriptorium.full_work_gallery --repo-root . --format csv > build/full-
```

Open `build/full-work-gallery.html` for ten exact measurements and seven row-wise charts.
These are Scriptorium-side results, not FantLab parity or author-style scores. The comparison now also has a pinned canonical site route:
`build/site/works/two-full-work-differences/index.html`, with downloadable
`measurements.json` and `measurements.csv`. The offline command remains available.
Building this route does not prove GitHub Pages is deployed.
Shell redirection replaces its destination; use new filenames to keep older exports. [Method and limits](docs/FULL_WORK_GALLERY.md).
These are Scriptorium-side results, not FantLab parity or author-style scores. The pinned
canonical site route is `build/site/works/two-full-work-differences/index.html`, with
`measurements.json` and `measurements.csv` downloads. Navigation and export links have
44-pixel minimum touch targets; visible focus and reduced-motion styles are retained.
Newly approved replacement evidence must declare compatible source units before display;
legacy Grin diagnostics are not assigned invented source-unit fields.
Building this route does not prove GitHub Pages is deployed. Shell redirection replaces
its destination; use new filenames to keep older exports. [Method and limits](docs/FULL_WORK_GALLERY.md).

## What the results mean

FantLab-shaped metrics are **inferred compatibility candidates**, not demonstrated
parity. Scriptorium-only features are **extensions**. The historical Anna diagnostic
has no established identity match to FantLab's input text. **M2 remains 0/5**; none of
M1–M5 is declared complete by this release. The AOT-lineage morphology target and
M1–M5 is declared complete by this preview. The AOT-lineage morphology target and
field-by-field parity criteria remain unchanged.

Texts shorter than 300,000 characters including spaces are valid inputs with explicit
Expand All @@ -79,20 +99,22 @@ Hashes can identify known works; share derived reports deliberately.

## Safety and reproducibility

The reader CLI bounds manuscripts to 32 MiB and dictionaries to 8 MiB, rejects special
files and symlinks, and uses a create-only atomic writer. Operational errors do not echo
private paths or source text. CSV neutralizes formula-like **text** while preserving
numeric cells; spreadsheet import/save behavior is not universally guaranteed.
The CLI bounds manuscripts to 32 MiB and dictionaries and comparison reports to 8 MiB
per file, rejects special files and symlinks, and uses a create-only atomic writer.
Operational errors do not echo private paths or source text. CSV neutralizes formula-like
**text** while preserving numeric cells; spreadsheet import/save behavior is not universally guaranteed.

```bash
python -m unittest discover -s tests -v
python -m pip wheel --no-deps . --wheel-dir dist
```

The Reader package workflow tests the installed wheel outside the checkout, including
the source-free gallery; the Pages workflow runs the complete canonical suite and a
byte-identical site rebuild. The full Python public API, morphology modules, benchmark
data and corpus records remain in place. No external package-registry release is performed by CI.
The Reader workflow runs the complete canonical suite, builds a full wheel and tests it
outside the checkout: actual manuscript analysis/comparison, HTML/JSON/CSV, historical
report, safe failures and deterministic source-free gallery/site. No analyzer stubs are
used in the private-comparison acceptance. Package, project and CLI versions must agree.
The full Python public API, morphology modules, benchmark data and corpus records remain
in place. No external package-registry release is performed by CI.

Site locks are persistent regular files whose kernel locks are released on process death.
Do not delete a lock file while a publisher could be using it. Legacy directory locks
Expand All @@ -102,11 +124,13 @@ from an interrupted older preview fail closed and are not automatically deleted.

[Reader installation and commands](docs/READER_PREVIEW.md) ·
[Local analysis and dictionaries](docs/LOCAL_ANALYSIS.md) ·
[Private comparison](docs/PRIVATE_COMPARISON.md) ·
[Frozen diagnostic methodology](docs/FROZEN_DIAGNOSTIC_REPORT.md) ·
[Canonical site and publication boundary](docs/FULL_WORK_SITE_REPORT.md) ·
[Roadmap and repository assessment](project/ROADMAP.md)

The previous detailed README is preserved as [Research and evidence index](RESEARCH_INDEX.md).
It retains the project history, corpus investigations and original reference links.
The remaining unpublished EPUB/batch Workbench and Comparison Desk prototypes are
**not** advertised as released features; they need focused adoption and repository tests.
The detailed [Research and evidence index](RESEARCH_INDEX.md) retains project history,
corpus investigations and original reference links. Unpublished EPUB/batch Workbench
and browser Comparison Desk prototypes are **not** advertised as released features;
they require focused adoption and real repository tests. Code/data licensing and Pages
activation retain their separately tracked gates (#284/#285).
62 changes: 62 additions & 0 deletions docs/PRIVATE_COMPARISON.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Private comparison of two Reader analyses

The `0.4.0a1` preview adds a complete local `analyze -> compare` path without
uploading manuscripts or report files. It uses the canonical 29-metric registry,
not a second analyzer or a synthetic fixture runtime.

```bash
scriptorium analyze first.txt --output first.json
scriptorium analyze second.txt --output second.json
scriptorium compare first.json second.json --output comparison.html
scriptorium compare first.json second.json --format json --output comparison.json
scriptorium compare first.json second.json --format csv --output comparison.csv
```

Open the HTML locally. All formats preserve metric IDs, source digests, declared
algorithm/dependency identities and measurement units. HTML includes a keyboard
skip link, focusable scroll region, source details and a table alternative. Existing
outputs are never overwritten. Shell redirection is not create-only; prefer `--output`.

## Interpretation

Differences are **right minus left**. A percentage difference is in percentage
points, never relative percentage change. Unknown measurements remain unavailable;
different algorithm profiles make all rows incomparable. A different dictionary
makes only the five dictionary-dependent vocabulary metrics incomparable. Dictionary
identity is content-based, not JSON key-order-based. Revision labels are provenance,
not a replacement for algorithm versioning.

Input JSON decimals are retained as exact decimal observations; subtraction chooses
sufficient precision instead of rounding at the default Decimal context. The analyzer's
existing floating-point measurements are not retrospectively upgraded to exact science.

Reports and hashes are unauthenticated declarations. Validation catches contradictions,
not every possible forgery. Rerun analysis on the original bytes to verify a report.
Shared normalized digests and method identities cannot assert contradictory measurements;
dictionary changes do not excuse dialogue or punctuation drift.

## Rejection and privacy boundaries

Each UTF-8 report is limited to 8 MiB. Duplicate keys, nonfinite/oversized numbers,
unknown/missing fields, malformed digests, incorrect units/evidence statuses, missing
mandatory counts, impossible means, broken vocabulary partitions and inconsistent
punctuation rates are rejected. Symlinks and non-regular input files fail closed.
Create-only output uses the same atomic writer as the analyzer. Operational errors do
not print manuscript text or private paths. CSV protects text cells from formula-like
prefixes while retaining signed numeric differences. Hashes can identify known works;
share reports deliberately. No telemetry or external requests are made.

Short texts are valid inputs with the existing representativeness limitation. No corpus
entry, source edition identity, FantLab parity or M1-M5 completion is established by
this comparison. **M2 remains 0/5**, and AOT-lineage compatibility remains the target.

## Reproducible acceptance

`tests/test_compare.py` and `tests/test_imported_mean_integrity.py` construct their
reports with the real `build_local_analysis()`, not analyzer stubs. The Reader workflow
also builds the full repository wheel, installs it outside the checkout and runs
`tools/private_compare_smoke.py`: real texts, 29 rows, HTML/JSON/CSV, exact deltas,
deterministic output, create-only behavior and negative input rejection.

The separate browser Comparison Desk prototype is tracked in #280 and is not advertised
as an integrated feature of this CLI. GitHub Pages activation remains separately gated.
10 changes: 10 additions & 0 deletions project/CHANGELOG.d/2026-10-22-reader-private-comparison.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# 2026-10-22 — Reader 0.4 delivery batch

- Accepted and merged earlier Reader 0.3 PR #278 as `5c03ee428df6cc36ebdeff2443d35ac9f7e72dca`; #277 closed by native GitHub. Exact-head baseline: 775 tests and installed-wheel checks passed. Pages deployment is still interlocked.
- Opened #288 on the reused `scrip-compare-003-local-cli` branch. Adopted #279: 29 canonical metrics, strict input/cross-report consistency, exact decimal deltas, offline HTML/JSON/CSV and private create-only output.
- Replaced legacy fixture-runtime mean tests with real `build_local_analysis()` reports. First full CI: 809 tests passed; an old hardcoded 0.2.0a1 smoke expectation then failed. Fixed it by requiring pyproject, installed metadata and exact CLI version agreement, retaining all installed tests and adding `-I` isolation. All six workflows passed at `dab93b3143ee8f494b2f2761bb21d25bf8153ad7`.
- Adopted #286's repin-aware source-unit guard without a second metric registry. Eight negative/positive tests plus one actual frozen-record check passed locally (43 local tests with the comparator). Full canonical CI must revalidate this successor before acceptance.
- Improved two-work navigation/export touch targets to a minimum of 44 pixels, retaining focus and reduced-motion styles. This is partial #283, not a claim of full browser/accessibility acceptance.
- Updated product-first README and existing compact queue; version is `0.4.0a1`. No external registry publication, new branch or access/administration change.
- Recovered distinct unpublished POS benchmark-join debt as #287 after deduplicating open and closed records. Existing #279-#286 remain their canonical scopes.
- New implementation remains pending later fresh acceptance. Browser HTTP navigation was blocked by the runtime: VISUAL_NOT_VERIFIED, no live-publication claim. Source data, scientific thresholds and M2 0/5 are unchanged.
Loading
Loading