- Add tools/validate.py: validates packages, and with --correction runs proposed corrections through the gate against a package without writing anything (spec/11 §11.4). The gate now refuses a proposal that fails the correction schema, rule correction.schema. - tools/load.py validates every package before loading, and with --bundle --built-from builds a scienting-bundle/1 with the FTS5 search index and bundle_meta (spec/13 §13.5). Search rows are defined per unit (sentence, cell, equation outside a sentence, figure-text) with the parent kind as context. - Roster keys carry a role, and a key with the role owner may revoke any receipt (spec/08 §8.7, spec/20); roster schema, store table and the fixture roster updated. The checker signs a trial revocation to prove the rule both ways. - A qa: receipt raises the nodes it sampled except those in its errors (spec/08 §8.2); the example paper's fidelity counts become 27 F3, 13 F2, 4 F1 and 1 F0. - The destination chooses the keyed scheme, not the text policy: hmac-team between the team's machines, hkdf-pages outside the team (spec/05 §5.8, spec/12 §12.5). - A TextQuoteSelector must repeat the anchor's plain quote and is absent for hashed or keyed anchors (spec/18 §18.3). - Add fixtures/records/suspect.json, a scienting-suspect/1 record. - Oracle: hashes are kept incrementally and checked after every correction against a full recomputation; load and write refuse unsafe manifest paths; Ed25519, HKDF and schema validation come from the cryptography and jsonschema packages; canonical JSON uses the built-in encoder with an exact RFC 8785 fallback. - The tools need Python 3.14 with cryptography and jsonschema; the py310 CI environment is dropped and the workflow runs the default only. - Resolve every [CHECK] note in the docs, READMEs and context; add CONTRIBUTING.md; every tool answers --help and refuses unknown options. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
133 lines
9.0 KiB
Markdown
133 lines
9.0 KiB
Markdown
# manuspec
|
|
|
|
**The data formats for storing a team's scientific papers once, correcting them once, addressing them down to the sentence, and keeping them.**
|
|
|
|
This page is for three readers.
|
|
A newcomer should read straight through; each term is explained where it first appears.
|
|
The tables below point an implementer, who will write a reader, writer, converter or checker, to the chapters, test vectors and fixtures that define exact behavior.
|
|
The sections on status and on differences give an expert in the neighboring standards the version, the maturity of each format and the comparison.
|
|
The repository is at <https://git.scient.ing/infra/manuspec>.
|
|
|
|
A research team usually cares about a few dozen papers it understands completely, not the world's literature.
|
|
Those papers deserve better than a folder of PDFs.
|
|
Every sentence, table cell and equation should have a permanent address, and every correction should be recorded with its evidence.
|
|
Notes, claims and extracted numbers should point at exactly what they came from.
|
|
Anyone should be able to see how far each piece was checked, and by whom.
|
|
|
|
This repository defines the files that make that possible.
|
|
It holds no application.
|
|
Every format is documented here and readable without any program's code, so a reader, writer, converter, checker or store can each be a separate program.
|
|
Every file is JSON (a plain-text format for structured data) or JSON Lines (one JSON record per line).
|
|
A package is the unit these formats store a paper in: a folder or a zip file of such files holding the text as nodes (sections, sentences, cells, equations), page geometry, references, corrections, review receipts and the list of suspects ([spec/12](spec/12-package.md)).
|
|
|
|
```text
|
|
cornell1995second#k3m9q2a@4f1a0c[12:57]
|
|
└──── document ──┘└ node ┘└ pin ┘└span┘
|
|
```
|
|
|
|
A hash is a short fingerprint computed from text: the same text always gives the same fingerprint, and changing one character changes the hash.
|
|
The string above names code points 12 to 57 of one sentence, as it read when its hash began `4f1a0c`.
|
|
The node ID `k3m9q2a` encodes no page, position or kind.
|
|
It is minted once from the document key, the node's kind, its text hash and its occurrence, and then frozen.
|
|
|
|
Fixing a typo elsewhere in the paper leaves the ID alone, and converting the same input again mints the same IDs.
|
|
A teammate's download of the same PDF, stamped differently by the publisher, has the same page fingerprints.
|
|
If a different converter reads the paper, each sentence it reads identically keeps its ID. Every difference becomes a suspect, a place flagged for review.
|
|
Nothing changes until a correction with its evidence is accepted ([spec/04](spec/04-identity.md), [spec/05 §5.6](spec/05-hashes.md#56-alignment)).
|
|
The address grammar is in [spec/06 §6.1](spec/06-anchors.md#61-addresses), and [vectors/addresses.jsonl](vectors/addresses.jsonl) holds valid and invalid examples.
|
|
|
|
## Start here
|
|
|
|
| If you want to | Read |
|
|
| --- | --- |
|
|
| Understand what the project is and how the parts fit | [docs/overview.md](docs/overview.md) |
|
|
| Learn the ideas one at a time, each with an example | [docs/concepts.md](docs/concepts.md) |
|
|
| Follow one paper from its first reading to a signed document | [docs/walkthrough.md](docs/walkthrough.md) |
|
|
| Run something in the next five minutes | [docs/examples.md](docs/examples.md) |
|
|
| Implement a reader or writer | [spec/](spec/README.md), then [vectors/](vectors/README.md) |
|
|
| Know why a rule is the way it is | [docs/rationale.md](docs/rationale.md) |
|
|
| Look up a term | [docs/glossary.md](docs/glossary.md) |
|
|
| Compare with neighboring standards | [docs/comparison.md](docs/comparison.md) |
|
|
|
|
## What is in the repository
|
|
|
|
| Folder | Holds |
|
|
| --- | --- |
|
|
| [spec/](spec/README.md) | The specification, in 23 chapters. Normative. |
|
|
| [schemas/](schemas/README.md) | JSON Schemas, which state what a valid file or record looks like, for every file and record. |
|
|
| [sql/](sql/README.md) | Tables for SQLite (a database kept in one file), Dolt and PostgreSQL, and the SQLite bundle with full-text search. |
|
|
| [context/](context/README.md) | The JSON-LD context (a file that gives JSON terms shared meanings) that makes annotation layers W3C Web Annotations. |
|
|
| [registry/](registry/README.md) | The list of formats, the rule IDs validators report, download-stamp rules, and the default rights each processing stage requires. |
|
|
| [vectors/](vectors/README.md) | Test vectors: inputs and the exact outputs every implementation must compute. |
|
|
| [fixtures/](fixtures/README.md) | Example packages and records, deliberately broken packages, and the test keys that signed them. |
|
|
| [tools/](tools/README.md) | The programs that build and check everything above. |
|
|
| [docs/](docs/README.md) | Guides for people getting to know the project. |
|
|
|
|
## Try it
|
|
|
|
With [pixi](https://pixi.sh), one command sets up a pinned environment and checks everything:
|
|
|
|
```sh
|
|
pixi run check
|
|
```
|
|
|
|
The checker validates every schema, record and package.
|
|
It confirms that every broken package is refused for the stated reason.
|
|
It recomputes every test vector, and it rebuilds everything and compares it byte for byte.
|
|
Last, it loads every package into SQLite and back, and checks the prose and the links.
|
|
Pixi lints the Markdown first.
|
|
The run ends with `All checks pass.`
|
|
`pixi task list` shows the other tasks: `quick`, `build`, `lint` and `load`.
|
|
|
|
The tools need Python 3.14 and two packages, `jsonschema` and `cryptography`, which pixi installs along with markdownlint for the Markdown.
|
|
Without pixi, install those two with pip and run `python3 tools/check.py`.
|
|
|
|
To explore a worked package, load the example paper (a synthetic chemistry paper with 12 corrections) into SQLite and query it; [docs/examples.md](docs/examples.md) has queries to start from.
|
|
|
|
```sh
|
|
pixi run load --sqlite lab.db fixtures/packages/hale2026harmonic
|
|
```
|
|
|
|
## Format names
|
|
|
|
Every format is named `scienting-<name>/<major>`, such as `scienting-doc/1` or `scienting-anchor/1`.
|
|
The `scienting-` prefix is the formats' namespace, a separate matter from the repository's name.
|
|
A format is named after what it holds, never after a product or a repository, and products can be renamed without touching data.
|
|
Schemas use the identifier base `https://scient.ing/ns/schemas/`.
|
|
[registry/formats.json](registry/formats.json) lists every format with its media type, schema, status and chapter.
|
|
|
|
## Status and limits
|
|
|
|
This is version 0.1.0.
|
|
Of the 27 formats, 20 are `candidate` and seven are `provisional`.
|
|
The `provisional` formats are project, bundle, dataset, digitization, view, snapshot and draft-ids; where those are described, they are marked as such.
|
|
The repository includes a reference checker, test vectors and fixtures.
|
|
|
|
The formats are built for a team-scale corpus of hundreds of documents, not hundreds of millions of papers.
|
|
They do not replace publisher interchange formats.
|
|
They do not fix what a converter reads wrongly; they record it and make it checkable.
|
|
Not every addressable thing is a node with five hashes (the content values `text_hash`, `match_hash`, `align_key`, `own_hash` and `node_hash`, explained in [docs/concepts.md](docs/concepts.md)).
|
|
Table columns and figure-text items have IDs and are not nodes ([spec/04 §4.2](spec/04-identity.md), [spec/09](spec/09-figures-tables-equations.md)).
|
|
|
|
## How it differs from neighboring standards
|
|
|
|
- JATS is the XML format in which publishers and archives exchange journal content ([NISO Z39.96-2024](https://www.niso.org/publications/z3996-2024-jats)).
|
|
Keep using it for exchange.
|
|
Here, a JATS file is one kind of reading a package can be established from (`jats` is a witness kind, [spec/02 §2.3](spec/02-model.md)).
|
|
- TEI has a sentence element, `<s>` ([TEI P5](https://tei-c.org/release/doc/tei-p5-doc/en/html/ref-s.html)), and recommends author-assigned `xml:id` values for durable pointers ([TEI P5 pointers](https://tei-c.org/release/doc/tei-p5-doc/en/html/SA.html)).
|
|
Here, node IDs are minted by a rule and, when a node is merged or deleted, retired with a recorded successor ([spec/04 §4.3](spec/04-identity.md)).
|
|
- W3C Web Annotation is a general model for annotating any resource, with text quote, text position and other selectors ([W3C Recommendation](https://www.w3.org/TR/annotation-model/)).
|
|
Use it for annotation in general.
|
|
Here, annotation layers are Web Annotations whose target selector is a custom `AnchorSelector`, optionally followed by a standard `TextQuoteSelector` for tools that do not know ours ([spec/18](spec/18-layers.md)).
|
|
- Docling is an open-source document conversion toolkit ([arXiv:2501.17887](https://arxiv.org/abs/2501.17887)).
|
|
Use a converter like it to read PDFs.
|
|
It identifies items by position in a list, such as `#/texts/12` ([schema](https://raw.githubusercontent.com/docling-project/docling-core/main/docs/DoclingDocument.json)).
|
|
Here, IDs do not depend on position, and a second converter's reading is aligned with the first and compared.
|
|
|
|
## Licenses
|
|
|
|
The specification and other prose are CC BY 4.0, so anyone may implement the formats.
|
|
Schemas, SQL, the JSON-LD context, the registries, the vectors and the fixtures are CC0 1.0.
|
|
The tools are Apache-2.0.
|
|
See [LICENSE.md](LICENSE.md).
|