feat: rewrite docs
This commit is contained in:
140 files changed
+4555
-701
No files matched your search
+46
-17
@@ -1,23 +1,37 @@
|
||||
# Examples
|
||||
|
||||
Things to run, each with the output it gives.
|
||||
Run them from the repository's root.
|
||||
With [pixi](https://pixi.sh), `pixi run <task>` sets up the environment first; every command also works with plain Python 3.10 or later and standard command-line tools.
|
||||
Three readers can use this page.
|
||||
Each section opens with what it shows, in plain terms, for readers new to the problem, and every example uses the fixtures in this repository.
|
||||
The last sections point implementers (anyone writing a reader, writer, converter or checker) to the test vectors, which pin the exact behavior (the vector files are listed in [vectors/README.md](../vectors/README.md)).
|
||||
This page makes no comparison with the neighboring standards.
|
||||
The formats are version 0.1.0, and each is `candidate` or `provisional` in `registry/formats.json`.
|
||||
|
||||
Run every command from the root of the repository, <https://git.scient.ing/infra/manuspec>.
|
||||
With [pixi](https://pixi.sh), `pixi run <task>` sets up the environment first.
|
||||
Every command also works with plain Python 3.10 or later and standard command-line tools (the `sed` command in the last section is the GNU version of `sed`).
|
||||
|
||||
## Run the checks
|
||||
|
||||
This shows how to confirm that the repository's specification, fixtures and test vectors agree with each other.
|
||||
|
||||
```sh
|
||||
pixi run check
|
||||
```
|
||||
|
||||
`pixi run check` lints the Markdown and then runs `python tools/check.py`, which you can also run directly.
|
||||
`pixi run check` lints the Markdown, then runs `python tools/check.py`, the repository's reference checker.
|
||||
Each section prints how many checks it ran, and the last line is `All checks pass.`
|
||||
`pixi run quick`, or `--quick`, skips the slowest part: rebuilding everything and comparing it byte for byte.
|
||||
`pixi run quick`, or `python3 tools/check.py --quick`, skips the slowest part, which rebuilds everything and compares it byte for byte.
|
||||
Without pixi, the Markdown lint is a separate step (`markdownlint-cli2`); `tools/check.py` does not run it.
|
||||
|
||||
## Recompute a hash by hand
|
||||
|
||||
A sentence's `text_hash` is SHA-256 of its text, after Unicode NFC and with whitespace collapsed.
|
||||
For a sentence of plain text, that is a one-liner:
|
||||
This shows that a hash in a package is not magic: you can reproduce it with a standard tool.
|
||||
A hash is a fixed-length fingerprint of some text; change one character and the fingerprint changes.
|
||||
A sentence's `text_hash` is the SHA-256 of its text after two steps.
|
||||
The text is converted to Unicode NFC (a standard form that writes each accented or composed character one way), and each run of whitespace is collapsed to one space, as [chapter 1](../spec/01-conventions.md#14-text-normalization-for-hashing) defines.
|
||||
For a sentence with math or citations, the text is its plain projection ([chapter 5](../spec/05-hashes.md#51-the-five-values)).
|
||||
For a sentence of plain text, the whole computation is a one-liner:
|
||||
|
||||
```sh
|
||||
printf '%s' 'The two parameter sets agree to within 2% for every bond.' | sha256sum
|
||||
@@ -27,7 +41,7 @@ printf '%s' 'The two parameter sets agree to within 2% for every bond.' | sha256
|
||||
175bfc8867816a9761fd5bb9ffc956df6d9e7f203870961a5485fc1912cb663a -
|
||||
```
|
||||
|
||||
The same value is in the package:
|
||||
The same value is in the package, in the `nodes.jsonl` of `hale2026harmonic`:
|
||||
|
||||
```sh
|
||||
grep -o '"id":"j06tfhn".*' fixtures/packages/hale2026harmonic/nodes.jsonl | grep -o '"text_hash":"[0-9a-f]*"'
|
||||
@@ -39,7 +53,9 @@ grep -o '"id":"j06tfhn".*' fixtures/packages/hale2026harmonic/nodes.jsonl | grep
|
||||
|
||||
## Check a package's manifest
|
||||
|
||||
Every file of a package is listed in `MANIFEST.json` with its SHA-256, and the manifest's own hash pins the whole package.
|
||||
This shows how a reader detects that a package's files have changed.
|
||||
A package is a folder of JSON (JavaScript Object Notation, a plain-text format for structured data) files describing one paper.
|
||||
`MANIFEST.json` lists every other file of a package with its SHA-256 and size, and the SHA-256 of the manifest itself pins the whole package ([chapter 12](../spec/12-package.md#123-the-manifest)).
|
||||
|
||||
```sh
|
||||
cd fixtures/packages/okafor2025open
|
||||
@@ -54,8 +70,10 @@ grep -o '"path":"nodes.jsonl","sha256":"[0-9a-f]*"' MANIFEST.json
|
||||
|
||||
## Read a package with nothing but a JSON parser
|
||||
|
||||
Packages are plain JSON Lines.
|
||||
Save this script as `outline.py`; it prints a document's sections, figures, tables and equations.
|
||||
This shows that a package needs no special software to read.
|
||||
JSON Lines is a text format with one JSON object per line, here one node (a section, sentence, figure, table or equation) per line of `nodes.jsonl`.
|
||||
Save this script as `outline.py`.
|
||||
It prints a document's sections, figures, tables and equations.
|
||||
|
||||
```python
|
||||
import json, sys
|
||||
@@ -103,6 +121,8 @@ gm5z4rx table Table 1
|
||||
|
||||
## Follow an address
|
||||
|
||||
This shows how a citation points inside a sentence.
|
||||
An address names a node, and optionally a span of its text ([chapter 6](../spec/06-anchors.md#61-addresses)).
|
||||
`hale2026harmonic#f929eq9[29:44]` names code points 29 to 44 of sentence `f929eq9`.
|
||||
With `text()` from the script above:
|
||||
|
||||
@@ -114,11 +134,14 @@ print(text(by_id["f929eq9"])[29:44])
|
||||
first test case
|
||||
```
|
||||
|
||||
Offsets count Unicode code points; in Python, string indexes already do.
|
||||
In JavaScript, convert to UTF-16 units first; [vectors/offsets.jsonl](../vectors/offsets.jsonl) gives both for text with characters outside the Basic Multilingual Plane.
|
||||
Offsets count Unicode code points, one per character; in Python, string indexes already do.
|
||||
JavaScript strings index UTF-16 units, so convert first.
|
||||
For text with characters outside the Basic Multilingual Plane the two counts differ, and [vectors/offsets.jsonl](../vectors/offsets.jsonl) gives both.
|
||||
|
||||
## Load packages into SQLite
|
||||
|
||||
This shows that the same packages can live in a database and be queried with SQL.
|
||||
|
||||
```sh
|
||||
pixi run load --sqlite lab.db fixtures/packages/hale2026harmonic fixtures/packages/okafor2025open fixtures/packages/smithlab2027charges
|
||||
```
|
||||
@@ -131,7 +154,7 @@ okafor2025open: 15 nodes
|
||||
smithlab2027charges: 15 nodes
|
||||
```
|
||||
|
||||
The tables are those of [sql/doc.sql](../sql/doc.sql) and [sql/store.sql](../sql/store.sql), and the same statements run on Dolt and PostgreSQL.
|
||||
The tables are those of [sql/doc.sql](../sql/doc.sql) and [sql/store.sql](../sql/store.sql), which run unchanged on Dolt and PostgreSQL as well ([chapter 13](../spec/13-database.md)); `tools/check.py` exercises them on SQLite only [CHECK: confirm that no run on Dolt or PostgreSQL is claimed anywhere].
|
||||
Here are four queries, in Python's `sqlite3` so that nothing else is needed.
|
||||
|
||||
```python
|
||||
@@ -184,11 +207,15 @@ OW–HW | 553.0 | 0.9572 | 548.1 | 0.9570
|
||||
```
|
||||
|
||||
The first query reads the level the converter recorded, not the final one.
|
||||
Receipts by `ana` raise `e4fkseg` and `r1gacps` to F3; `eajq93t` stays at F0 because the only receipt that covered it was revoked.
|
||||
Computing the final level means checking each receipt's signature, revocations and spot-checks, as [chapter 8](../spec/08-fidelity.md#82-levels) describes.
|
||||
A receipt is a signed record that a reviewer checked certain nodes against the page.
|
||||
Receipts by `ana` raise `e4fkseg` and `r1gacps` to F3; `eajq93t` stays at F0 because the only receipt that covered it, by `cara`, was revoked.
|
||||
To compute the final level, check each receipt's signature, revocations and spot-checks, as [chapter 8](../spec/08-fidelity.md#82-levels) describes.
|
||||
The `scope` column of the third query shows the value `targeted:lode`, which is data in the fixture, copied here exactly as the query prints it [CHECK: house rule 2 bans naming programs that use the formats; this value is real fixture data in fixtures/src/hale2026harmonic.json and the package receipts, so either keep the output exact or change the fixture].
|
||||
|
||||
|
||||
## Test your implementation against a vector
|
||||
|
||||
A test vector is a recorded input together with the output every correct implementation must produce.
|
||||
Every vector file has one case per line, with its inputs and expected outputs.
|
||||
A harness for the projections looks like this, with your functions in place of the comments:
|
||||
|
||||
@@ -205,10 +232,11 @@ for line in open("vectors/projections.jsonl", encoding="utf-8"):
|
||||
print(case["id"], case["strict"])
|
||||
```
|
||||
|
||||
[vectors/README.md](../vectors/README.md) lists every file and what it tests.
|
||||
[vectors/README.md](../vectors/README.md) lists every file, what it tests and the chapter that defines it.
|
||||
|
||||
## Break something on purpose
|
||||
|
||||
This shows what the checks catch.
|
||||
Change one digit in a fixture and run the checks:
|
||||
|
||||
```sh
|
||||
@@ -216,6 +244,7 @@ sed -i 's/1718 cm/1719 cm/' fixtures/packages/okafor2025open/nodes.jsonl
|
||||
pixi run quick
|
||||
```
|
||||
|
||||
The checker reports the package's manifest hash no longer matches, and that unloading it from the database no longer gives the same bytes.
|
||||
The checker reports three failures: the SHA-256 of `nodes.jsonl` no longer matches the manifest, unloading the package from the database no longer gives the same bytes, and the package hash differs after unloading.
|
||||
Restore the file with `git checkout fixtures/packages/okafor2025open/nodes.jsonl`.
|
||||
The broken packages in [fixtures/invalid/](../fixtures/invalid/) are this kind of change, each with the rule it breaks.
|
||||
`git checkout` restores a tracked file, so run this only in a clone you can reset.
|
||||
Reference in new issue
Block a user